您的位置:首页 > 理论基础 > 计算机网络

区块链基础知识系列第5课 Hyperledger fabric1.0网络中transaction产生以及流转过程

2018-03-12 11:14 751 查看


一、发起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)就会被添加到读集中,例如s=(k1,1,v1),
(k2,1,v2), (k3,1,v3),
(k4,1,v4), (k5,1,v5),anchor中包含的key值为k1,
k2,则readset={k1: v1, k2: v2},只有在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。重要的是要注意,无效的交易虽然会被放入区块中,但不会改变本地的帐本状态。

通过一个例子来解释节点如何通过读写集来判断transaction的有效性的:

  假设当前本地状态为s=(k1,1,v1), (k2,1,v2), (k3,1,v3), (k4,1,v4), (k5,1,v5),节点接收到一个包含5个transaction的区块,分别为T1, T2, T3, T4和T5

  T1 -> Write(k1, v1'), Write(k2, v2'),T2 -> Read(k1), Write(k3, v3'),T3 -> Write(k2, v2''),T4 -> Write(k2, v2'''), read(k2),T5 -> Write(k6, v6'), read(k5),
由于T1没有执行任何的读操作,所以被判定为有效,且k1和k1对应的值分别被写为v1'和v2',
T2因为读了已经
cbe9
被修改过的K1的值而被判定为无效,因此k3的值并不发生改变,
T3也没有执行任何读操作,所以有效,k2的值被修改为v2'',
T4也因为尝试读已经被修改过的k2的值而判定为无效,
T5读的k5并没有发生任何修改而被判定为有效,并将k6的值写为v6'。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: