Analytical Fabric1.4 Source: Peer node joins passage

      And start a new reading, this time to see that the process Peer node joins the channel. In fact, each time to see the source code, there will be a lot of places do not understand, but I believe as long as the stick, record-keeping, there are still a lot of harvest.
      Peer node added to the channel process, from the user point of view also simply execute the command line:

peer channel join -b mychannel.block 

      To complete the process of a node is added channels. Fabric from the internal network is concerned, but it is a lot of work to do, let's look at a specific process:
the whole process starting point and client to create a channel processes the same fabric/peer/main.gofile main()method, by executing the above command to call peer/channel/channel.goin Cmd()method, then the peer/channel/join.gofile joinCmd()method, line 131 join(), and finally went to the line 88 executeJoin()method, then look at the method:

spec, err := getJoinCCSpec()
if err != nil {
    return err
}

      The first is get specific information channels need to be added, in line 67:

func getJoinCCSpec() (*pb.ChaincodeSpec, error) {
    #判断指定路径下是否有创世区块,创世区块的创建流程可以看之前那篇解析客户端创建通道的文章
    if genesisBlockPath == common.UndefinedParamValue {
        return nil, errors.New("Must supply genesis block file")
    }
    #读取创世区块中的内容,就是通道的一些基本信息
    gb, err := ioutil.ReadFile(genesisBlockPath)
    if err != nil {
        return nil, GBFileNotFoundErr(err.Error())
    }
    #构造一个ChaincodeSpec结构体,第一个参数为JoinChain,指定操作为加入通道,第二个参数为创世区块的信息
    input := &pb.ChaincodeInput{Args: [][]byte{[]byte(cscc.JoinChain), gb}}

    spec := &pb.ChaincodeSpec{
        Type:        pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]),
        ChaincodeId: &pb.ChaincodeID{Name: "cscc"},
        Input:       input,
    }
===================ChaincodeSpec=======================
type ChaincodeSpec struct {
    Type                 ChaincodeSpec_Type `protobuf:"varint,1,opt,name=type,proto3,enum=protos.ChaincodeSpec_Type" json:"type,omitempty"`
    ChaincodeId          *ChaincodeID       `protobuf:"bytes,2,opt,name=chaincode_id,json=chaincodeId,proto3" json:"chaincode_id,omitempty"`
    Input                *ChaincodeInput    `protobuf:"bytes,3,opt,name=input,proto3" json:"input,omitempty"`
    Timeout              int32              `protobuf:"varint,4,opt,name=timeout,proto3" json:"timeout,omitempty"`
    XXX_NoUnkeyedLiteral struct{}           `json:"-"`
    XXX_unrecognized     []byte             `json:"-"`
    XXX_sizecache        int32              `json:"-"`
}
===================ChaincodeSpec=======================
    #最后返回该结构体
    return spec, nil
}

executeJoin()The method continues to look down:

invocation := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec}

The structure of a package prior to re-create the structure ChaincodeInvocationSpec:

type ChaincodeInvocationSpec struct {
    ChaincodeSpec        *ChaincodeSpec `protobuf:"bytes,1,opt,name=chaincode_spec,json=chaincodeSpec,proto3" json:"chaincode_spec,omitempty"`
    XXX_NoUnkeyedLiteral struct{}       `json:"-"`
    XXX_unrecognized     []byte         `json:"-"`
    XXX_sizecache        int32          `json:"-"`
}

      And then obtain the identity of a creator, after the proposal for the creation and signature:

creator, err := cf.Signer.Serialize()
if err != nil {
    return fmt.Errorf("Error serializing identity for %s: %s", cf.Signer.GetIdentifier(), err)
}

      The next step is the creation of the Proposal:

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)
}

      It depends on the specific CreateProposalFromCIS()method in core/protos/proputils.gothe first 466 lines of the file, and then call the 237 line CreateChaincodeProposal()method, look at the name should be understood that a information about creating a chain code proposal. Then the 243 line CreateChaincodeProposalWithTransient()method:

func CreateChaincodeProposalWithTransient(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error) {
    #首先就是生成一个随机数
    nonce, err := crypto.GetRandomNonce()
    if err != nil {
        return nil, "", err
    }
    #计算出一个TxID,具体是根据HASH算法生成的
    txid, err := ComputeTxID(nonce, creator)
    if err != nil {
        return nil, "", err
    }
    #然后调用了这个方法,将之前生成的数据传入进去
    return CreateChaincodeProposalWithTxIDNonceAndTransient(txid, typ, chainID, cis, nonce, creator, transientMap)
}

CreateChaincodeProposalWithTxIDNonceAndTransient()Method on line 282:
      first look at the method of the incoming values: txidgenerated by the previous methods, typthe first method of passing in, value HeaderType_CONFIG, chainID empty string, cisare passed to come original method, the value of ChaincodeInvocationSpecthe structure , noncegenerated by the previous method, creatorbut also original method passed in, transientMapit is empty, before the CreateChaincodeProposal()method can be seen. Then we look at the specific flow method:

func CreateChaincodeProposalWithTxIDNonceAndTransient(txid string, typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, nonce, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error) {
    #首先是构造一个ChaincodeHeaderExtension结构体
    ccHdrExt := &peer.ChaincodeHeaderExtension{ChaincodeId: cis.ChaincodeSpec.ChaincodeId}
=========================ChaincodeHeaderExtension=====================
    type ChaincodeHeaderExtension struct {
        PayloadVisibility []byte `protobuf:"bytes,1,opt,name=payload_visibility,json=payloadVisibility,proto3" json:"payload_visibility,omitempty"`
        // The ID of the chaincode to target.
        ChaincodeId          *ChaincodeID `protobuf:"bytes,2,opt,name=chaincode_id,json=chaincodeId,proto3" json:"chaincode_id,omitempty"`
        XXX_NoUnkeyedLiteral struct{}     `json:"-"`
        XXX_unrecognized     []byte       `json:"-"`
        XXX_sizecache        int32        `json:"-"`
    }
=========================ChaincodeHeaderExtension=====================
    #将该结构体序列化
    ccHdrExtBytes, err := proto.Marshal(ccHdrExt)
    if err != nil {
        return nil, "", errors.Wrap(err, "error marshaling ChaincodeHeaderExtension")
    }
    #将ChaincodeInvocationSpec结构体序列化
    cisBytes, err := proto.Marshal(cis)
    if err != nil {
        return nil, "", errors.Wrap(err, "error marshaling ChaincodeInvocationSpec")
    }
    #又是一个结构体
    ccPropPayload := &peer.ChaincodeProposalPayload{Input: cisBytes, TransientMap: transientMap}
============================ChaincodeProposalPayload=====================
type ChaincodeProposalPayload struct {
    Input []byte `protobuf:"bytes,1,opt,name=input,proto3" json:"input,omitempty"`
    TransientMap         map[string][]byte `protobuf:"bytes,2,rep,name=TransientMap,proto3" json:"TransientMap,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
    XXX_NoUnkeyedLiteral struct{}          `json:"-"`
    XXX_unrecognized     []byte            `json:"-"`
    XXX_sizecache        int32             `json:"-"`
}
============================ChaincodeProposalPayload=====================
    #将该结构体序列化
    ccPropPayloadBytes, err := proto.Marshal(ccPropPayload)
    if err != nil {
        return nil, "", errors.Wrap(err, "error marshaling ChaincodeProposalPayload")
    }
    var epoch uint64
    #创建一个时间戳
    timestamp := util.CreateUtcTimestamp()
    #构造Header结构体,包含两部分ChannelHeader和SignatureHeader
    hdr := &common.Header{
        ChannelHeader: MarshalOrPanic(
            &common.ChannelHeader{
                Type:      int32(typ),
                TxId:      txid,
                Timestamp: timestamp,
                ChannelId: chainID,
                Extension: ccHdrExtBytes,
                Epoch:     epoch,
            },
        ),
        SignatureHeader: MarshalOrPanic(
            &common.SignatureHeader{
                Nonce:   nonce,
                Creator: creator,
            },
        ),
    }
    #序列化
    hdrBytes, err := proto.Marshal(hdr)
    if err != nil {
        return nil, "", err
    }
    #最后构造成一个Proposal
    prop := &peer.Proposal{
        Header:  hdrBytes,
        Payload: ccPropPayloadBytes,
    }
    #返回Proposal,这里一直返回到最外面的方法
    return prop, txid, nil
}

      Let's go back executeJoin()methods, read on:

    #刚刚这行代码返回了创建的Proposal
    prop, _, err = putils.CreateProposalFromCIS(pcommon.HeaderType_CONFIG, "", invocation, creator)
    if err != nil {
        return fmt.Errorf("Error creating proposal for join %s", err)
    }
    #定义一个被签名的Proposal
    var signedProp *pb.SignedProposal
    #这个方法就是对创建的Proposal进行签名了,具体的就不再看了,继续往下
    signedProp, err = putils.GetSignedProposal(prop, cf.Signer)
    if err != nil {
        return fmt.Errorf("Error creating signed proposal %s", err)
    }
    #定义了个提案响应
    var proposalResp *pb.ProposalResponse
    #重要的方法,由Peer节点对刚刚创建的提案进行处理,处理完成后返回提案响应,之前有篇文章对这个方法进行了讲解,在文章最后贴出了地址,这里就不再说明了
    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: %s", proposalResp.Response.Status, proposalResp.Response.Message))
    }
    logger.Info("Successfully submitted proposal to join channel")
    return nil
}

      Peer node is added to this channel operation has ended, we summarize the work done before:

  1. The first is the peer channel join -b mychannel.blocktrigger of this order, and finally after several calls to the executeJoin()method.
  2. First, obtain mychannel.blockinformation in the file, close to ChaincodeSpecthe structure.
  3. It is then encapsulated ChaincodeInvocationSpecstructure.
  4. Gets a proposal for initiating a proposal and signing operations creator.
  5. The TxID and the nonce, and further packaged as ChaincodeHeaderExtension, ChaincodeProposalPayload, Header, Proposalstructure.
  6. Of the resulting Proposalstructure is a signing operation performed by a Peer node processing, the processing is completed after returning a response message.

      Message processing method for Peer node ProcessProposalin this article: Fabric1.4 source code parsing: Peer node endorsement proposal process

      Here is a class diagram Well, there are too many structures before, the relationship a bit more complicated:

The Source: https://github.com/yeasy/hyperledger_code_fabric/blob/master/peer/_images/signed_proposal.png

Finally, reference documentation

Guess you like

Origin www.cnblogs.com/cbkj-xd/p/11131677.html
Recommended