首页 > 代码库 > Hyperledger fabric网络中transaction产生以及流转过程
Hyperledger fabric网络中transaction产生以及流转过程
一、发起transaction
当client想要发起一个transaction时,它会首先发送一个PROPOSE消息到它选择的一组endorser节点,消息模式有以下两种,节点可以自由选择(可能有更多种):
- client首先将<PROPOSE, tx>消息发送给某个单个的endorser,该endorser会产生相应的版本依赖(anchor),以供client稍后作为PROPOSE消息的参数发送给其它endorser节点;
- client直接将<PROPOSE, tx>消息发送给它选择的这一组endorser节点。
PROPOSE消息的格式为<PROPOSE, tx, [anchor]>,其中anchor参数为可选,表示读版本依赖,通常是指key-version对,必选的tx参数代表transaction的内容,包括发起该transaction的client唯一标识符clientID,指向transaction所涉及chaincode的chaincodeID,包含所发起的transaction本身的txPayload,一个由client维护的单调递增的整数timestamp以及client的签名clientSig。其中txPayload根据transaction的不同而分成两种不同的类型:
- 唤醒事务(invoke transaction):txPayload=<operation, metadata>,其中operation表示chaincode操作以及传递给chaincode的参数,metadata表示与调用相关的属性;
- 部署事务(deploy transaction):txPayload=<source, metadata, policies>,其中source表示chaincode的源码,metadata表示与chaincode和应用相关的属性,policies表示与chaincode相关的策略,包括备书策略等。
二、模拟transaction
- 当endorser接收到一个PROPOSE消息后,它会首先验证其中的clientSig,通过验证后会对该transaction进行模拟。如果PROPOSE消息中包含anchor字段,endorser会根据anchor中的key获取当前本地状态中对应该key值的version值,从而生成readset(读集),如当前endorser本地保存的状态为s,对任意一个transaction中的key k,(k, s(k).version)就会被添加到读集中,只有在anchor与readset匹配即完全相等时,endorser才会模拟该transaction。模拟transaction基于endorser本地保存的状态副本,调用对应的chaincode来试探性地执行该transaction,从而生成一个被称为writeset(写集)的状态更新,如任意一个transaction中的key k对应的值被修改成为v,则(k, v)就会被加入到写集中去。
- endorser内部转发tran-proposal到它备书transaction的逻辑部分——备书逻辑,默认情况下,备书逻辑会接受该tran-proposal并给它加上签名,当然,也可以通过任意函数来达成是否备书的决定。
- 如果endorser决定给一个transaction备书,它会给提交的client发送一个<TRANSACTION-ENDORSED, tid, tran-proposal,epSig>消息,其中tid是对PROPOSE消息中的tx进行哈希运算生成的,用来指向某个transaction,epSig是备书节点的签名,tran-proposal = (epID,tid,chaincodeID,txContentBlob,readset,writeset),其中epID是备书节点的节点ID,txContentBlob是chaincode/transaction的具体信息,作为tx的某种形式进行使用,如txContentBlob = tx.txPayload。
- 如果endorser拒绝给一个transaction备书,它只需要直接给发起该transaction的client发送(TRANSACTION-INVALID, tid, REJECTED)消息。
- 整个过程中,endorser并不会修改它本地状态,只是对transaction进行模拟。
三、接收备书消息
发起transaction的client发出PROPOSE消息后会一直等待接收备书消息,是否备书成功取决于当前的备书策略,如当前client选择的备书节点集合为{Alice, Bob, Charlie, Dave, Eve, Frank, George},当前的备书策略为有5个备书节点通过即通过,则client在收集到5个TRANSACTION-ENDORSED消息后即认为当前transaction备书成功,接收到的TRANSACTION-ENDORSED消息集被称为endorsement。
之后,client会发送broadcast(blob)(此时blob即为endorsement)消息到Orderer system channel中,通过orderer来将该transaction同步到整个channel内的节点中。orderer会将一段时间内的所有transaction进行排序并打包成block然后通过deliver(seqno, prevhash, blob)消息将block发送给所有节点,其中seqno表示一个非负的序号,prevhash表示最近一次block的哈希值,blob表示一个block区块。
四、同步transaction
当节点收到一个deliver消息时,它会根据chaincode的策略来检查blob.endorsement是否有效,再检查readset是否与当前节点的本地状态一致。
如果所有的验证都通过后,transaction被视为有效的。此时,节点将PeerLedger的位掩码中将该transaction标记为1,通过blob.endorsement.tran-proposal.writeset 修改本地的帐本状态。
如果blob.endorsement的备书策略验证失败,则该transaction被认为是无效的,节点在PeerLedger的位掩码中将该transaction标记为0。重要的是要注意,无效的交易虽然会被放入区块中,但不会改变本地的帐本状态。
<style>p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Andale Mono"; color: #e74c3c; background-color: #ffffff } span.s1 { }</style>
<style>p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Andale Mono"; color: #e74c3c; background-color: #ffffff } span.s1 { }</style> <style>p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Andale Mono"; color: #e74c3c; background-color: #ffffff } span.s1 { }</style> <style>p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Andale Mono"; color: #e74c3c; background-color: #ffffff } span.s1 { }</style> <style>p.p1 { margin: 0.0px 0.0px 0.0px 24.0px; text-indent: -24.0px; font: 12.0px "Andale Mono"; color: #e74c3c; background-color: #ffffff } span.s1 { }</style> <style>p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Andale Mono"; color: #e74c3c; background-color: #ffffff } span.s1 { }</style> <style>p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Andale Mono"; color: #e74c3c; background-color: #ffffff } span.s1 { }</style>
Hyperledger fabric网络中transaction产生以及流转过程