美文网首页
关于链码调用请求发送到交易被打包的过程分析

关于链码调用请求发送到交易被打包的过程分析

作者: 天地一小儒 | 来源:发表于2020-03-23 23:49 被阅读0次

    主题:一个链码调用请求,系统如何处理这些数据,直到被打包成交易?从交易到请求的过程中经历了哪些变化?请求大小和交易大小之间相差多少?

    1. 数据流向

    1.1 生成交易的方式
    整个区块链系统(Hyperledger Fabric)是通过智能合约也就是链码(Chaincode)来驱动各式各样的交易(Tx)并被打包成块(Block)的。整体上讲,链码调用只有两种形式,一种是调用(Invoke),一种是查询(Query)。前者可以被记录并通过交易改动区块链账本(Ledger),后者则不会改动账本,也就是说,即使你调用了链码中的“更新”函数,但你是用的Query,其更新,不会被刷新到区块链中。
    由于链码Query是直接查询本地分类账,不会生成交易,因此,这里我们以链码Inovke过程来分析。

    1.2 如何生成交易
    当peer节点收到一个链码调用请求后,在对请求验证通过后,它会形成一个本地签名的提案(Proposal),此节点可称为提案节点。然后提案节点经gossip协议随机发送给若干个节点(默认是3),其他节点在收到此签名提案也会对它进行验证,通过后会对此提案添加自己的签名,这就是背书,此节点可称为背书节点。背书节点在签完名后发送给最初的那个节点——提案节点在收集到足够的签名后(比如,超过2/3节点的背书签名),将此提案和背书结果打包形成交易,签名后发送给order节点进行共识。
    共识过后,众多提案背书完成的交易会被打包成块,此过程本文不予分析,因为与主题不符。

    2 背书过程

    2.1 生成提案
    提案主要分为两个部分,Header和Payload,Header又主要分为两部分,Channel Header和Signature Header

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

    Payload主要就是链码请求。另外,交易id也是在此阶段生成。

    背书主要使用的是一个签名提案的结构SignedProposal,里面只有两部分,一部分是上面提案的字节数组,另一部分则是
    签名。这个结构体主要作用有四:1. 验证证书有效性 2. 验证证书是否可信(包括有收信人的CA签名以及此交易是否被许可) 3. 验证签名 4.防止重放攻击。

    2.2 提案处理
    节点在收到签名的提案后,会有如下过程:1. 检查并确认提案的有效性。 2. 在本地模拟提案执行,也即执行链码然后得到链码返回结果 3. 背书并生成一个提案响应的结构体。 这里需要提一下的是,它的背书响应结构体同时包含需要对账本进行修改的读写集,以及私有读写集。因此对于一个近乎是“put”(上链) 的链码方法,提案响应甚至会比实际请求要大。

    2.3 发送交易
    提案在收集完成后,会打包成信封发送出去,这里用到的是一个Envelope的结构&common.Envelope{Payload: paylBytes, Signature: sig},这里在把提案和背书结果(提案响应)一起封装成一个payload结构,过程曲折而复杂,我就不贴了,基本上只是增加少量的辅助字段,没有其他的一些重大的数据引入。

    3 大小变化
    我对批量上链做了一个测试。当请求大小是4582532时,请求变成交易的数据变化过程:


    request to transaction

    当请求大小是30601785,区块链报错了:CreateAndSendTransaction failed: SendTransaction failed: calling orderer 'orderer.rabbit.com:7050' failed: Orderer Server Status Code: (400) BAD_REQUEST. Description: message payload is 30601785 bytes and exceeds maximum allowed 10485760 bytes

    可以看到,提案(proposal)Payload跟请求大小相比几乎一致(有点误差是因为,payload采用了压缩,而request计算没有),然后提案响应(response)Payload比请求更大,原因我也说了,主要是响应中包含对分类账以及隐私数据更新的读写集,而后数据结构基本无明显变化。
    因此可以得到一些结论:

    1. 对于需要大量更新区块链的的链码调用来说,交易的大小可能是原请求的两倍甚至更高。
    2. fabric限制了交易的最大大小为10M,如果你想发送更大的交易,请提前根据链码调用方法做好请求切割。

    相关文章

      网友评论

          本文标题:关于链码调用请求发送到交易被打包的过程分析

          本文链接:https://www.haomeiwen.com/subject/eyngyhtx.html