endorsor端流程也一致,入口都是core/endorser/endorser.go#ProcessProposal
,具体不再重复展开,可以参看instantiate(3)。主要的区别在于core/endorser/endorser.go#callChaincode
里,(“lscc”, “deploy”)的if
条件不再满足,不需要进入(回顾一下,这里主要是launch用户application chaincode的容器,执行application chaincode的Init方法等,在install阶段当然不需要)。真正的区别在于lscc.go#Invoke
的select-case
里,进入的是INSTALL
分支(部署chaincode时进入的是DEPLOY
分支)。INSTALL首先执行lscc.policyChecker.CheckPolicyNoChannel(mgmt.Admins, sp)
检查策略,这部分以后详述。从名字也印证出install是不指定channel的。然后执行lscc的executeInstall
方法.
1 | // executeInstall implements the "install" Invoke transaction |
ccpack, err := ccprovider.GetCCPackage(ccbytes)
这里讲传入的ChaincodeDeploymentSpec
字节反序列化,抽取信息构建CDSPackage
或者SignedCDSPackage
,根据是否执行peer chaincode package
并签名。ccprovider.ExtractStatedbArtifactsFromCCPackage(ccpack)
和cceventmgmt.GetMgr().HandleChaincodeInstall(chaincodeDefinition, statedbArtifactsTar, lscc.sccprovider)
涉及couchdb相关,笔者尚未深入分析,以后专题详述。lscc.support.PutChaincodeToLocalStorage(ccpack)
将代码package放到本地路径,在instantiate里launch时候取出。这里确定的放置package路径为path := fmt.Sprintf("%s/%s.%s", chaincodeInstallPath, ChaincodeId.Name, ChaincodeId.Version)
,这里的path为chaincodeInstallPath(config.GetPath("peer.fileSystemPath") + string(filepath.Separator) + "chaincodes")
, 配置项peer.fileSystemPath
是peer启动时从配置文件core.yaml里读取的。
至此完成了install工作,在endorser节点的chaincodeInstallPath路径下,存在名为ChaincodeName.ChaincodeVersion的源码包,供instantiate(3)中在安装时从该路径取出。