兄弟连区块链技术培训Fabric 1.0源代码分析(33) Peer #peer channel命令及子命令实现

Delete_88c3 · · 1042 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

兄弟连区块链技术培训Fabric 1.0源代码分析(33) Peer #peer channel命令及子命令实现

# Fabric 1.0源代码笔记 之 Peer #peer channel命令及子命令实现


## 1、peer channel create子命令实现(创建通道)


### 1.1、初始化Orderer客户端


```go

const (

    EndorserRequired EndorserRequirement = true

    EndorserNotRequired EndorserRequirement = false

    OrdererRequired OrdererRequirement = true

    OrdererNotRequired OrdererRequirement = false

)


cf, err = InitCmdFactory(EndorserNotRequired, OrdererRequired)

//代码在peer/channel/create.go

```


cf, err = InitCmdFactory(EndorserNotRequired, OrdererRequired)代码如下:


```go

type ChannelCmdFactory struct {

    EndorserClient pb.EndorserClient //EndorserClient

    Signer msp.SigningIdentity //Signer

    BroadcastClient common.BroadcastClient //BroadcastClient

    DeliverClient deliverClientIntf //DeliverClient

    BroadcastFactory BroadcastClientFactory //BroadcastClientFactory,type BroadcastClientFactory func() (common.BroadcastClient, error)

}


func InitCmdFactory(isEndorserRequired EndorserRequirement, isOrdererRequired OrdererRequirement) (*ChannelCmdFactory, error) {

    var err error

    cmdFact := &ChannelCmdFactory{}

    cmdFact.Signer, err = common.GetDefaultSignerFnc() //GetDefaultSignerFnc = GetDefaultSigner


    cmdFact.BroadcastFactory = func() (common.BroadcastClient, error) {

        return common.GetBroadcastClientFnc(orderingEndpoint, tls, caFile) //GetBroadcastClientFnc = GetBroadcastClient

    }


    //peer channel join或list需要endorser,本处暂未使用

    if isEndorserRequired {

        cmdFact.EndorserClient, err = common.GetEndorserClientFnc()

    }


    //peer channel create或fetch需要orderer

    if isOrdererRequired {

        var opts []grpc.DialOption

        if tls {

            if caFile != "" {

                creds, err := credentials.NewClientTLSFromFile(caFile, "")

                opts = append(opts, grpc.WithTransportCredentials(creds))

            }

        } else {

            opts = append(opts, grpc.WithInsecure())

        }

        conn, err := grpc.Dial(orderingEndpoint, opts...)

        client, err := ab.NewAtomicBroadcastClient(conn).Deliver(context.TODO())

        cmdFact.DeliverClient = newDeliverClient(conn, client, chainID) //构造deliverClient

    }

    return cmdFact, nil

}


//代码在peer/channel/channel.go

```


### 1.2、发送创建区块链的交易


```go

err = sendCreateChainTransaction(cf)

//代码在peer/channel/create.go

```


sendCreateChainTransaction(cf)代码如下:


```go

func sendCreateChainTransaction(cf *ChannelCmdFactory) error {

    var err error

    var chCrtEnv *cb.Envelope


    if channelTxFile != "" { //peer channel create -f指定通道交易配置文件

        chCrtEnv, err = createChannelFromConfigTx(channelTxFile) //获取创世区块

    } else {

        chCrtEnv, err = createChannelFromDefaults(cf) //没有指定通道交易配置文件

    }


    chCrtEnv, err = sanityCheckAndSignConfigTx(chCrtEnv) //检查和签名交易配置

    var broadcastClient common.BroadcastClient

    broadcastClient, err = cf.BroadcastFactory()

    defer broadcastClient.Close()

    err = broadcastClient.Send(chCrtEnv)

    return err

}

//代码在peer/channel/create.go

```


### 1.3、获取创世区块并写入文件


```go

var block *cb.Block

block, err = getGenesisBlock(cf) //获取创世区块

b, err := proto.Marshal(block) //块序列化

err = ioutil.WriteFile(file, b, 0644) //写入文件

//代码在peer/channel/create.go

```


## 2、peer channel join子命令实现(加入通道)


### 2.1、初始化Endorser客户端


```go

cf, err = InitCmdFactory(EndorserRequired, OrdererNotRequired)

//代码在peer/channel/join.go

```


### 2.2、构造ChaincodeInvocationSpec消息(cscc.JoinChain)


```go

spec, err := getJoinCCSpec()

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

//代码在peer/channel/join.go

```


spec, err := getJoinCCSpec()代码如下:


```go

func getJoinCCSpec() (*pb.ChaincodeSpec, error) {

    gb, err := ioutil.ReadFile(genesisBlockPath)

    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,

    }

    return spec, nil

}

//代码在peer/channel/join.go

```


### 2.3、创建cscc Proposal并签名


```go

creator, err := cf.Signer.Serialize()

//从CIS创建Proposal,CIS即ChaincodeInvocationSpec

//调用CreateChaincodeProposal(typ, chainID, cis, creator)

//而后调用CreateChaincodeProposalWithTransient(typ, chainID, cis, creator, nil)

prop, _, err = putils.CreateProposalFromCIS(pcommon.HeaderType_CONFIG, "", invocation, creator)

var signedProp *pb.SignedProposal

signedProp, err = putils.GetSignedProposal(prop, cf.Signer)

//代码在peer/channel/join.go

```


CreateChaincodeProposalWithTransient(typ, chainID, cis, creator, nil)代码如下:


```go

func CreateChaincodeProposalWithTransient(typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, creator []byte, transientMap map[string][]byte) (*peer.Proposal, str ing, error) {

    //创建随机Nonce

    nonce, err := crypto.GetRandomNonce()

    //计算交易ID

    //digest, err := factory.GetDefault().Hash(append(nonce, creator...),&bccsp.SHA256Opts{})

    txid, err := ComputeProposalTxID(nonce, creator)

    return CreateChaincodeProposalWithTxIDNonceAndTransient(txid, typ, chainID, cis, nonce, creator, transientMap)

}

//代码在protos/utils/proputils.go

```


CreateChaincodeProposalWithTxIDNonceAndTransient(txid, typ, chainID, cis, nonce, creator, transientMap)代码如下:


```go

func CreateChaincodeProposalWithTxIDNonceAndTransient(txid string, typ common.HeaderType, chainID string, cis *peer.ChaincodeInvocationSpec, nonce, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error) {

    ccHdrExt := &peer.ChaincodeHeaderExtension{ChaincodeId: cis.ChaincodeSpec.ChaincodeId}

    ccHdrExtBytes, err := proto.Marshal(ccHdrExt)

    cisBytes, err := proto.Marshal(cis)

    ccPropPayload := &peer.ChaincodeProposalPayload{Input: cisBytes, TransientMap: transientMap}

    ccPropPayloadBytes, err := proto.Marshal(ccPropPayload)

    var epoch uint64 = 0

    timestamp := util.CreateUtcTimestamp()

    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)

    return &peer.Proposal{Header: hdrBytes, Payload: ccPropPayloadBytes}, txid, nil

}

//代码在protos/utils/proputils.go

```


### 2.4、提交并处理Proposal


```go

var proposalResp *pb.ProposalResponse

proposalResp, err = cf.EndorserClient.ProcessProposal(context.Background(), signedProp)

//代码在peer/channel/join.go

```


## 3、peer channel update(更新锚节点配置)


```go

cf, err = InitCmdFactory(EndorserNotRequired, OrdererRequired)

fileData, err := ioutil.ReadFile(channelTxFile)

ctxEnv, err := utils.UnmarshalEnvelope(fileData)

sCtxEnv, err := sanityCheckAndSignConfigTx(ctxEnv)

var broadcastClient common.BroadcastClient

broadcastClient, err = cf.BroadcastFactory()

defer broadcastClient.Close()

return broadcastClient.Send(sCtxEnv)

//代码在peer/channel

 是科技发展太快,还是我们已经掉尾?7月7日起,每天两小时跟清华微软谷歌大牛团队一起实战区块链。

http://www.ydma.cn/open/course/16来来来,清华学霸尹成大哥带你飞起来~~~


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1042 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传