fabric源码解读【peer chaincode】:安装链码

文章目录

  • 源码目录
  • 安装流程
  • 源码分析
    • 命令定义
    • 创建消息
    • 发送背书节点处理
    • LSCC处理
    • 执行安装

源码目录

peer/chaincode/chaincode.go

peer/chaincode/install.go

peer/chaincode/common.go

安装流程

fabric源码解读【peer chaincode】:安装链码_第1张图片

源码分析

命令定义

chaincode.go

func Cmd(cf *ChaincodeCmdFactory) *cobra.Command {
   addFlags(chaincodeCmd)

   chaincodeCmd.AddCommand(installCmd(cf))         // 添加install
   chaincodeCmd.AddCommand(instantiateCmd(cf))     // 添加instantiate
   chaincodeCmd.AddCommand(invokeCmd(cf))          // 添加invoke
   chaincodeCmd.AddCommand(packageCmd(cf, nil))		// 添加package
   chaincodeCmd.AddCommand(queryCmd(cf))           // 添加query
   chaincodeCmd.AddCommand(signpackageCmd(cf))      // 添加signpackage
   chaincodeCmd.AddCommand(upgradeCmd(cf))    // 添加更新
   chaincodeCmd.AddCommand(listCmd(cf))			// 添加list

   return chaincodeCmd
}

var chaincodeCmd = &cobra.Command{
	Use:              chainFuncName,
	Short:            fmt.Sprint(shortDes),
	Long:             fmt.Sprint(longDes),
    //prerun设置order环境
	PersistentPreRun: common.SetOrdererEnv,
}

install.go

// 安装链码命令
func installCmd(cf *ChaincodeCmdFactory) *cobra.Command {
   chaincodeInstallCmd = &cobra.Command{
      Use:       "install",
      Short:     fmt.Sprint(installDesc),
      Long:      fmt.Sprint(installDesc),
      ValidArgs: []string{"1"},
      RunE: func(cmd *cobra.Command, args []string) error {
         var ccpackfile string
         if len(args) > 0 {
            ccpackfile = args[0]
         }
         //安装
         return chaincodeInstall(cmd, ccpackfile, cf)
      },
   }
   flagList := []string{
      "lang",
      "ctor",
      "path",
      "name",
      "version",
   }
   attachFlags(chaincodeInstallCmd, flagList)

   return chaincodeInstallCmd
}
//安装到peer,通过背书客户端的ProcessProposal,背书服务调用LSCC的invoke
func install(msg proto.Message, cf *ChaincodeCmdFactory) error {
	creator, err := cf.Signer.Serialize()
	if err != nil {
		return fmt.Errorf("Error serializing identity for %s: %s", cf.Signer.GetIdentifier(), err)
	}
	//创建提案消息
	prop, _, err := utils.CreateInstallProposalFromCDS(msg, creator)
	if err != nil {
		return fmt.Errorf("Error creating proposal  %s: %s", chainFuncName, err)
	}
	//签名消息
	var signedProp *pb.SignedProposal
	signedProp, err = utils.GetSignedProposal(prop, cf.Signer)
	if err != nil {
		return fmt.Errorf("Error creating signed proposal  %s: %s", chainFuncName, err)
	}

	//背书节点处理消息
	proposalResponse, err := cf.EndorserClient.ProcessProposal(context.Background(), signedProp)
	//处理结果
	if err != nil {
		return fmt.Errorf("Error endorsing %s: %s", chainFuncName, err)
	}

	if proposalResponse != nil {
		logger.Debugf("Installed remotely %v", proposalResponse)
	}

	return nil
}

创建消息

fabric/protos/utils/proputils.go

func CreateInstallProposalFromCDS(ccpack proto.Message, creator []byte) (*peer.Proposal, string, error) {
   // prop类型install
   return createProposalFromCDS("", ccpack, creator, "install")
}
//创建提案消息
func createProposalFromCDS(chainID string, msg proto.Message, creator []byte, propType string, args ...[]byte) (*peer.Proposal, string, error) {
。。。
	switch propType {
	case "deploy":
        // 和upgrade是一样的流程
		fallthrough
	case "upgrade":
。。。
	}

	//系统链码描述.
	lsccSpec := &peer.ChaincodeInvocationSpec{
		ChaincodeSpec: &peer.ChaincodeSpec{
			Type:        peer.ChaincodeSpec_GOLANG,
			//调用lscc系统链码
			ChaincodeId: &peer.ChaincodeID{Name: "lscc"},
			Input:       ccinp}}

	//...and get the proposal for it
	//HeaderType_ENDORSER_TRANSACTION消息类型
	return CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, chainID, lsccSpec, creator)
}

发送背书节点处理

fabric/protos/peer/peeer.pb.go

func (c *endorserClient) ProcessProposal(ctx context.Context, in *SignedProposal, opts ...grpc.CallOption) (*ProposalResponse, error) {
   out := new(ProposalResponse)
   err := grpc.Invoke(ctx, "/protos.Endorser/ProcessProposal", in, out, c.cc, opts...)
   if err != nil {
      return nil, err
   }
   return out, nil
}

LSCC处理

fabric/core/scc/lscc.go

调用invoke方法

func (lscc *lifeCycleSysCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
   args := stub.GetArgs()
   if len(args) < 1 {
      return shim.Error(InvalidArgsLenErr(len(args)).Error())
   }

   function := string(args[0])

   // 1.获取签名的消息
   sp, err := stub.GetSignedProposal()
   if err != nil {
      return shim.Error(fmt.Sprintf("Failed retrieving signed proposal on executing %s with error %s", function, err))
   }

   switch function {
   case INSTALL:
      //安装链码
      if len(args) < 2 {
         return shim.Error(InvalidArgsLenErr(len(args)).Error())
      }

      // 2. 检查 local MSP Admins 策略
      if err = lscc.policyChecker.CheckPolicyNoChannel(mgmt.Admins, sp); err != nil {
         return shim.Error(fmt.Sprintf("Authorization for INSTALL has been denied (error-%s)", err))
      }

      depSpec := args[1]
      // 调用安装执行
      err := lscc.executeInstall(stub, depSpec)
      if err != nil {
         return shim.Error(err.Error())
      }
      // 返回结果
      return shim.Success([]byte("OK"))
   }
}

执行安装

包括状态数据库,安装到本地文件系统后,

// 安装链码 peer chaincode install
func (lscc *lifeCycleSysCC) executeInstall(stub shim.ChaincodeStubInterface, ccbytes []byte) error {
   ccpack, err := ccprovider.GetCCPackage(ccbytes)
   if err != nil {
      return err
   }

   cds := ccpack.GetDepSpec()

   if cds == nil {
      return fmt.Errorf("nil deployment spec from from the CC package")
   }
   //检查链码名称
   if err = lscc.isValidChaincodeName(cds.ChaincodeSpec.ChaincodeId.Name); err != nil {
      return err
   }
   //检查版本
   if err = lscc.isValidChaincodeVersion(cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version); err != nil {
      return err
   }

   // Get any statedb artifacts from the chaincode package, e.g. couchdb index definitions
   //解压状态db数据
   statedbArtifactsTar, err := ccprovider.ExtractStatedbArtifactsFromCCPackage(ccpack)
   if err != nil {
      return err
   }

   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.
   //处理安装,含有db数据
   err = cceventmgmt.GetMgr().HandleChaincodeInstall(chaincodeDefinition, statedbArtifactsTar)
   if err != nil {
      return err
   }

   //安装到本地文件系统
   if err = lscc.support.PutChaincodeToLocalStorage(ccpack); err != nil {
      return err
   }

   logger.Infof("Installed Chaincode [%s] Version [%s] to peer", ccpack.GetChaincodeData().Name, ccpack.GetChaincodeData().Version)

   return nil
}

你可能感兴趣的:(区块链)