Fabric 1.4源码分析 - chaincode install(2)endorsor的install流程

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#Invokeselect-case里,进入的是INSTALL分支(部署chaincode时进入的是DEPLOY分支)。INSTALL首先执行lscc.policyChecker.CheckPolicyNoChannel(mgmt.Admins, sp)检查策略,这部分以后详述。从名字也印证出install是不指定channel的。然后执行lscc的executeInstall方法.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// executeInstall implements the "install" Invoke transaction
func (lscc *lifeCycleSysCC) executeInstall(stub shim.ChaincodeStubInterface, ccbytes []byte) error {
ccpack, err := ccprovider.GetCCPackage(ccbytes)

// Get any statedb artifacts from the chaincode package, e.g. couchdb index definitions
statedbArtifactsTar, err := ccprovider.ExtractStatedbArtifactsFromCCPackage(ccpack)

if err = isValidStatedbArtifactsTar(statedbArtifactsTar); err != nil {
return InvalidStatedbArtifactsErr(err.Error())
}

chaincodeDefinition := &cceventmgmt.ChaincodeDefinition{
Name: ccpack.GetChaincodeData().Name,
Version: ccpack.GetChaincodeData().Version,
Hash: ccpack.GetId()} // Note - The chaincode 'id' is the hash of chaincode's (CodeHash || MetaDataHash), aka fingerprint

// HandleChaincodeInstall will apply any statedb artifacts (e.g. couchdb indexes) to
// any channel's statedb where the chaincode is already instantiated
// Note - this step is done prior to PutChaincodeToLocalStorage() since this step is idempotent and harmless until endorsements start,
// that is, if there are errors deploying the indexes the chaincode install can safely be re-attempted later.
err = cceventmgmt.GetMgr().HandleChaincodeInstall(chaincodeDefinition, statedbArtifactsTar, lscc.sccprovider)
defer func() {
cceventmgmt.GetMgr().ChaincodeInstallDone(err == nil)
}()

// Finally, if everything is good above, install the chaincode to local peer file system so that endorsements can start
if err = lscc.support.PutChaincodeToLocalStorage(ccpack); err != nil {
return err
}

return nil
}
  1. ccpack, err := ccprovider.GetCCPackage(ccbytes)这里讲传入的ChaincodeDeploymentSpec字节反序列化,抽取信息构建CDSPackage或者SignedCDSPackage,根据是否执行peer chaincode package并签名。
  2. ccprovider.ExtractStatedbArtifactsFromCCPackage(ccpack)cceventmgmt.GetMgr().HandleChaincodeInstall(chaincodeDefinition, statedbArtifactsTar, lscc.sccprovider)涉及couchdb相关,笔者尚未深入分析,以后专题详述。
  3. 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)中在安装时从该路径取出。