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)就会被添加到读集中,例如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因为读了已经被修改过的K1的值而被判定为无效,因此k3的值并不发生改变,
  • T3也没有执行任何读操作,所以有效,k2的值被修改为v2'',
  • T4也因为尝试读已经被修改过的k2的值而判定为无效,
  • T5读的k5并没有发生任何修改而被判定为有效,并将k6的值写为v6'。

 

 

 

转载于:https://www.cnblogs.com/qinglizi/p/7087833.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值