fabric源码解读【peer channel】:创建通道 peer channel join

fabric源码解读【peer channel】:加入通道peer channel join

命令

peer channel join -b mychannel.block -o orderer.suisui.com:7050

流程

fabric源码解读【peer channel】:创建通道 peer channel join

源码分析

目录 /fabric/peer/channel/join.go

定义命令

//加入命令
func joinCmd(cf *ChannelCmdFactory) *cobra.Command {
   joinCmd := &cobra.Command{
      Use:   "join",
      Short: commandDescription,
      Long:  commandDescription,
      RunE: func(cmd *cobra.Command, args []string) error {
         //加入通道
         return join(cmd, args, cf)
      },
   }
   // 创世快区块路径 命令行中-b 表示 flags.StringVarP(&genesisBlockPath, "blockpath", "b", common.UndefinedParamValue, "Path to file containing genesis block")
   flagList := []string{
      "blockpath",
   }
   attachFlags(joinCmd, flagList)

   return joinCmd
}

加入通道

//加入通道
func join(cmd *cobra.Command, args []string, cf *ChannelCmdFactory) error {
   if genesisBlockPath == common.UndefinedParamValue {
      return errors.New("Must supply genesis block path")
   }
 //初始化命令工厂,加入通道需要背书节点支持
   var err error
   if cf == nil {
      cf, err = InitCmdFactory(EndorserRequired, OrdererNotRequired)
      if err != nil {
         return err
      }
   }
   //执行加入通道
   return executeJoin(cf)
}

执行加入通道

//执行加入通道
func executeJoin(cf *ChannelCmdFactory) (err error) {
   //创建链码描述
   spec, err := getJoinCCSpec()
   if err != nil {
      return err
   }

   //创建链码调用规范
   invocation := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec}

   creator, err := cf.Signer.Serialize()
   if err != nil {
      return fmt.Errorf("Error serializing identity for %s: %s", cf.Signer.GetIdentifier(), err)
   }
   //创建交易消息
   var prop *pb.Proposal
   prop, _, err = putils.CreateProposalFromCIS(pcommon.HeaderType_CONFIG, "", invocation, creator)
   if err != nil {
      return fmt.Errorf("Error creating proposal for join %s", err)
   }
   //对消息进行签名
   var signedProp *pb.SignedProposal
   signedProp, err = putils.GetSignedProposal(prop, cf.Signer)
   if err != nil {
      return fmt.Errorf("Error creating signed proposal %s", err)
   }

   // 发送消息到背书客户端请求加入通道
   var proposalResp *pb.ProposalResponse
   proposalResp, err = cf.EndorserClient.ProcessProposal(context.Background(), signedProp)
   if err != nil {
      return ProposalFailedErr(err.Error())
   }

   //验证相应结果
   if proposalResp == nil {
      return ProposalFailedErr("nil proposal response")
   }

   if proposalResp.Response.Status != 0 && proposalResp.Response.Status != 200 {
      return ProposalFailedErr(fmt.Sprintf("bad proposal response %d", proposalResp.Response.Status))
   }
   logger.Info("Successfully submitted proposal to join channel")
   return nil
}

背书节点处理

见后续背书节点处理章节,背书节点处理后,调用系统链码CSCC,执行CSCC invoke方法,arg[1]=JoinChain

CSCC链码处理

func (e *PeerConfiger) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
   args := stub.GetArgs()

   switch fname {
	case JoinChain:
		//加入通道
		//校验参数
		if args[1] == nil {
			return shim.Error("Cannot join the channel <nil> configuration block provided")
		}
		//解析区块参数
		block, err := utils.GetBlockFromBlockBytes(args[1])
		if err != nil {
			return shim.Error(fmt.Sprintf("Failed to reconstruct the genesis block, %s", err))
		}
		//获取链id
		cid, err := utils.GetChainIDFromBlock(block)
		if err != nil {
			return shim.Error(fmt.Sprintf("\"JoinChain\" request failed to extract "+
				"channel id from the block due to [%s]", err))
		}
		//校验区块
		if err := validateConfigBlock(block); err != nil {
			return shim.Error(fmt.Sprintf("\"JoinChain\" for chainID = %s failed because of validation "+
				"of configuration block, because of %s", cid, err))
		}

		// 2. check local MSP Admins policy
		// 校验访问策略
		if err = e.policyChecker.CheckPolicyNoChannel(mgmt.Admins, sp); err != nil {
			return shim.Error(fmt.Sprintf("\"JoinChain\" request failed authorization check "+
				"for channel [%s]: [%s]", cid, err))
		}
		//加入通道
		return joinChain(cid, block)
       case GetConfigBlock:
       			...
   }
//cscc加入通道
func joinChain(chainID string, block *common.Block) pb.Response {
   // 创建本地账本对象 kvLedger
   if err := peer.CreateChainFromBlock(block); err != nil {
      return shim.Error(err.Error())
   }
    //初始化链id
   peer.InitChain(chainID)
   //创建区块事件
   bevent, _, _, err := producer.CreateBlockEvents(block)
   if err != nil {
      cnflogger.Errorf("Error processing block events for block number [%d]: %s", block.Header.Number, err)
   } else {
      //发送区块事件
      if err := producer.Send(bevent); err != nil {
         cnflogger.Errorf("Channel [%s] Error sending block event for block number [%d]: %s", chainID, block.Header.Number, err)
      }
   }
   //返回成功结果
   return shim.Success(nil)
}