本文内容精选自华章鲜读专栏《Hyperledger-Fabric-源代码分析与深入解读》一书第二章“架构分析”。
《Hyperledger-Fabric-源代码分析与深入解读》纸书预计出版时间:2018年9月
华章鲜读上线:2018年7月(按章更新,纸书出版前更完本书全部内容)
我们概述一个交易的请求流程。如图2-5所示。
图2-5 交易的请求流程
图字翻译:
Peers 同级节点
Orderers 订单方
Endorse(TX) 发起交易TX
Respond(TX) 响应交易TX
Broadcast(EndorsedTX) 广播已发起的交易TX
Blocks 写入区块
调用交易,客户端发送一个PROPOSE消息到它选择的一组背书peer节点。给定chaincodeID的背书peer节点的设置由客户端通过peer节点实现,从背书策略知道背书peer节点的设置。例如,交易能被发送给所有给定chaincodeID背书者,也就是说,一些背书者能够离线,其它人可能反对和选择不为交易背书。提交客户端尝试满足背书者可用的背书策略表达。
接下来,将描述PROPOSE消息格式,讨论在提交客户端和背书者之间可能的互动模式。
一个PROPOSE消息的格式是,其中tx是强制的,anchor可选参数在下面列出。
clientID是提交客户端的身份,chaincodeID引用交易相关的链码,txPayload是提交交易自身的载体,timestamp是由客户端维护的一个单独递增整型值,clientSig是tx的其它域客户端签名.
txPayload的细节会在调用交易和部署交易之间有所不同。
对于调用交易,txPayload会包含两个域
对于部署交易,txPayload会包含三个域
tx加密哈希被所有node节点用作唯一的交易标识tid(即,tid=HASH(tx))。客户端保存tid在内存中,等待背书peer节点的响应。
客户端决定与背书者互动的顺序。例如,客户端通常会发送(即,没有anchor参数)到一个单独的背书者,背书者随后产生版本依赖(anchor),客户端可以在晚些时候使用这个版本依赖(anchor)作为它的PROPOSE消息参数,发送给其它背书者。另外的例子,客户端能直接发送(没有anchor)到它选择的所有背书者。不同的通信模式都有可能,客户端在这方面是自由的。
在从客户端接收消息时,背书peer节点epID首先校验客户端签名clientSig,然后模拟一个交易。如果客户端指定了anchor,那么背书peer节点模拟交易只基于在它本地KVS匹配的由anchor指定的版本号对应的key读版本号(即下面定义的readset)。
模拟一个交易涉及背书节点尝试执行一个交易(txPayload),通过调用链码到交易引用(chaincodeID)和背书peer节点本地持有的状态拷贝。
作为执行的结果,背书peer节点计算读版本依赖(readset)和状态更新(writeset),也在DB语言中称为MVCC+postimage info。
回顾状态包含键/值对。所有键/值对实体都是版本化的,那就是说,每个实体包含排序版本信息,它是在每次键的值更新时增加的。解释交易的peer节点记录了所有的被链码访问的键/值对,不管读或是写,peer节点不会更新它的状态。更具体地说:
如果客户端在PROPOSE消息中指定了anchor,那么客户端指定的anchor在模拟交易时必须等于背书peer节点产生的readset.
然后,peer节点内部提交交易提案到它的逻辑部分来背书交易,称为背书逻辑。缺省时,一个peer节点的背书逻辑接受交易提案并简单签署。无论如何,背书逻辑可以执行任意功能。
如果背书逻辑决定背书一个交易,它发送消息到提交客户端,其中:
否则,如果背书逻辑拒绝背书交易,背书者可以发送消息(TRANSACTION-INVALID,tid,REJECTED)到提交客户端。
注意背书者在这一步不能改变它的状态,在背书没有影响状态的情况下交易模拟产生状态更新。
提交客户端一直等待直到它在(TRANSACTION-ENDORSED,tid,,)上收集到“足够”的消息和签名来推断出交易提案已背书。
“足够”的准确数字取决于链码背书策略。如果背书策略是安全的,交易已经背书;注意它还没提交。经过背书节点签过名的TRANSACTION-ENDORSED消息的集合包含了被背书过的交易。
如果提交客户端没有设法为交易提案收集背书,则放弃这个交易,稍后再试。
对于一个具有有效背书的交易,我们现在开始使用排序服务。提交客户端使用broadcast(blob)调用排序服务,其中blob=endorsement.如果客户端没有能力直接调用排序服务,它可以通过它选择的peer节点代理广播。这样的peer节点必须被客户端信任不会从背书移除任何消息或其它可能被无效的交易。注意一点,无论如何,代理peer节点不可能制造有效背书。
当一个事件(seqno,prevhash,blob)发生并且一个peer节点已为所有序列号低于seqno的blosbs更新状态,peer节点执行如下流程,图2-6所示。
依赖的验证能以不同的方式实现,根据一致性属性或为状态更新选择的“孤立保证”。Serializability是一个缺省的孤立保证,除非链码背书策略指定一个不同的。Serializability能够通过在readset中的每个key关联的版本被提供,相当于key在状态中的版本,并拒绝不满足这个要求的交易。
图2-6 提交交易