交易背书的基本流程概括性的简述如下:
1)客户端创建交易后,发送请求到其选择的背书节点,即发送一个PROPOSE消息到交易所选择的背书节点集合。
2)背书节点模拟交易,然后生成背书签名。(在此首先会验证客户端的签名clientSig,然后模拟交易)
3)提交客户端获取交易的背书,通过排序服务进行广播。(之前提交节点会等待,当得到足够的消息及签名,得出交易已被背书的结论后,就会涉及其与背书节点之间的多轮交互;如果没有得到足够的消息及签名,其会放弃此次交易,稍后重试。在此的“足够多的消息及签名”和背书策略有关)
4)排序服务向所有节点投递传播交易的消息。
2)背书节点模拟交易,然后生成背书签名。(在此首先会验证客户端的签名clientSig,然后模拟交易)
当接收到来自客户端的 PROPOSE 消息
,背书节点 epID 首先会验证客户端的签名 clientSig ,然后进行模拟交易。
在进行模拟交易时,会涉及背书节点,其将通过调用所属的链码临时执行一个交易(txPayload),并执行背书节点本地持有的状态副本。
在执行结果,背书节点会计算读版本依赖(readset)和状态更新(writeset)。这在 DB 语言中也称之为 MVCC+postimage。
状态由键值对组成,每个条目都包含排序后的版本信息,当存储在一个键下的值被更新时,这个排序的版本号就会增加。即,所有的键值对条目都是版本化的。
节点解释了通过链代码下所有的键值对访问的交易记录,读或者写。进一步说明就是,在背书节点执行交易之前,比如给定状态 s,对于每个键 k 通过交易读,(k, s(k).version)被增加到读集合(readset)当中。此外,对于每个键 k,通过交易修改 k 的值为 v' ,(k, v')被增加到写集合(writeset)当中。当然,v' 也可以是新值相对于先前的值增量。
需要注意的是若客户端在PROPOSE 消息中指定了 anchor ,那么客户端指定的 anchor 必须等于背书节点模拟交易产生的 readset 。
如果背书逻辑决定要对一个交易进行背书,其会发送 消息到提交客户端。
说明如下
tran-proposal:其等于(epID, tid, chaincodeID, txContentBlob, readset, writeset)
txContentBlob,是链代码/交易特定的信息,其目的是使 txContentBlob 作为交易的表示使用。
epSig,是背书节点针对交易提案的签名。
另外一种情况,若背书逻辑拒绝背书交易,那么背书者可以向提交客户端发送消息(TRANSACTION-INVALID, tid, REJECTED)。
注:这一步背书者不会改变其状态,在背书者上下文中通过交易模拟产生的更新也不会影响到状态。
3)提交客户端获取交易的背书,通过排序服务进行广播。
之前提交节点会等待,当得到足够的(TRANSACTION-ENDORSED, tid, *, *)消息及签名,就可以得出交易已被背书的结论。这里会涉及其与背书节点之间的多轮交互。
注:这里的“足够的”取决于链代码的背书策略。满足了背书策略,交易才算背书成功。需要说明的是,现在这时还没有提交交易。
如果客户端没有得到足够的消息及签名,其会放弃此次交易,稍后重试。
对于持有合法背书的交易,可以开始排序服务。在此提交客户端通过 broadcast (blob)调用排序服务,此时 blob=endorsement。如果客户端没有能力直接调用排序服务,则可以通过其所选择的节点代理执行 broadcast(blob),如此一个节点必须被客户端信任,并且不会从背书中删除任何消息,否则交易会被当作非法的。
注:一个代理节点是不可能伪造出一个合法的背书信息的。
4)排序服务向所有节点投递传播交易的消息。
当发生了一个 deliver 事件(seqno, prevhas,blob),并且节点已经对那些序列号低于 seqno 的 blob 应用了所有的状态更新时,节点会进行以下操作。
一、根据链代码(blob.tran-proposal.chaincodeID)的策略,节点检查 blob.endorsement 是否是合法的。
二、检查有无违反核实依赖(blob.endorsement.tran-proposal.readset)。
在某些复杂的用例中,背书信息的交易提案可能会不同。在这种情况下,背书策略指定了状态如何的演化。根据状态更新选择的一致性内容(consistency property)或隔离保证(isolation guarantee)的不同,依赖验证是有多种实现方式的。
其中串行性(serializability)要求每个 readset 和 writeset 里键对应的版本号必须与状态里键的版本号相同,并抛弃不能满足此要求的交易。
如果所有的检查都能通过,那么可以认为此交易合法,这时可提交交易。在这种情况下,节点在原始总账(peer ledger)的位掩码中为这个交易标记 1 然后应用 blob.tran-proposal.stateUpdates 到区块链状态。
注:只有提交了的交易才可以改变状态。
若出现 blob.endorsement 的背书策略核实失败,则交易为非法。节点会在原始总账的位掩码中用 0 标记交易。
注:非法的交易不会更改状态。
最后还需要注意的是,对于一个给定的序号,所有正常的节点在处理一个 deliver 事件(区块)之后,必须具备相同的状态。即,通过排序服务的处理,保证所有正常的节点都将收到 deliver(seqno, prevhash, blob)事件的相同序号
领取专属 10元无门槛券
私享最新 技术干货