fabric 作为目前世界上最为知名的联盟链开源项目,所涉及的模块和概念很多,本文以交易作为一个切入点,通过分析一笔交易从发送到最终上链所经历的各个环节,将fabric的核心模块串联起来,为接下来更为深入的各个模块的源码分析奠定基础。
1. 发送签名提案消息到Endorser背书节点请求处理
Client节点构造签名提案消息<font color="blue">(SignedProposal类型)</font>,通过调用Endorser背书服务客户端的<font color="blue">ProcessProposal()接口</font>,提交该消息到Endorser背书节点,请求模拟执行交易提案并签名背书。
2. Endorser背书节点模拟执行交易提案并签名背书Endorser背书
节点收到签名提案消息之后,进行如下处理。
- 检查签名提案消息的格式合法性与签名有效性,包括通道头部、签名头部、签名 域、交易ID、消息扩展域的Chaincodeld属性与PayloadVisibility可见性模式等;
- 检查提案消息的创建者是否满足指定通道上的通道访问权限,即/Channel/ Application/Writers 写权限;
- 检查并启动链码容器以模拟执行交易提案,并将模拟执行结果暂时保存在交易模拟器中,等待排序共识与交易验证,而不是直接更新到账本中。其中,<font color="blue">交易模拟执行结果釆用状态数据读写集(读数据的键和版本、写数据的键值)记录交易造成的状态变更结果;</font>
- <font color="blue">调用ESCC系统链码对该提案消息的模拟结果读写集等进行签名背书</font>。
3. Endorser背书节点向客户端返回提案响应消息,并分发隐私数据明文
Endorser背书节点基于背书信息、模拟执行结果等构造提案响应消息(ProposalResponse 类型),并回复给请求客户端。
目前,模拟执行结果读写集包含公有数据(包括公共数据与隐私数据哈希值)与私有数据(或隐私数据)。
其中,公有数据交由0rderer节点进行排序出块,再提交到账本区块 数据文件,并广播到该通道上的所有节点。
如果模拟执行结果中还存在有效的隐私数据明文,则<font color="blue">Endorser背书节点通过Gossip消息协议将隐私数据发送给通道内授权的其他节点(由隐私数据集合配置的签名策略决定),交由transient隐私数据存储对象暂时保存到本地的transient隐私数据库(LevelDB),并在提交账本时存储到隐私数据库(LevelDB),同时清理transient隐私数据库中的过期数据</font>。
4. 处理提案响应消息
Client节点解析Endorser背书节点回复的提案响应消息,获取背书结果并检查提案响应消息状态的合法性,以判断是否收集到了<font color="blue">足够多的符合要求的背书签名信息</font>。
5. 发送交易数据给Orderer服务节点请求排序
当收集到足够多数量的符合要求的Endorser背书签名之后(由背书策略决定),<font color="blue">Client节点基于模拟执行结果、背书签名等构造合法的签名交易消息(Envelope类型),通过Broadcast()服务接口将该消息提交给Orderer节点</font>,请求交易排序处理。其中,配置交易消 息不需要经过Endorser节点处理。
6. Orderer服务节点对交易进行排序并构造新区块
Orderer排序节点<font color="blue">提供Solo类型(用于单节点测试)、Kafka类型(支持CFT容错)等共识组件</font>,对符合通道处理要求的合法交易消息(普通交易消息、配置交易消息等)进行排序并达成一致观点,并对一段时间内接收的一批交易消息按照打包交易的岀块规则(出块周期 时间、区块字节数限制、配置交易单独出块等)构造新区块,创建应用通道或更新通道配置同时提交账本。
7. Leader主节点请求Orderer服务节点发送通道账本区块
<font color="blue">Leader主节点通过Deliver()服务接口代表组织从Orderer节点请求通道账本上所有的区块数据,并通过Gossip消息协议分发到组织内的其他Peer节点</font>。如果请求的区块数据不 存在,则Orderer节点默认阻塞等待,直到指定区块创建完成并提交账本,再将该区块发送 给Leader主节点。
8. Committer记账节点验证交易并提交账本
Committer记账节点对区块与隐私数据(明文)执行如下检查,并提交至本地账本。如果不存在隐私数据明文,则跳过隐私数据的相关检查与提交账本的步骤。
- 检查交易消息格式的正确性、签名合法性、交易内容是否篡改、消息头部的合法性等。
- <font color="blue">调用VSCC系统链码</font>,验证收集的签名背书结果是否符合指定的背书策略。
- 对模拟结果中公有数据(即区块数据,含有公共数据与隐私数据哈希值)的<font color="blue">读写集执行MVCC检查</font>,针对单个键查询、键范围查询、隐私数据哈希值三种情况,检查读数据版本与交易时的账本是否一致,即是否存在读写冲突,并将存在冲突的交易标记为无效交易。
- 验证模拟结果中隐私数据的正确性,遍历区块中有效交易的隐私数据读写集哈希值,取岀对应交易的原始隐私数据读写集明文,重新计算其哈希值并对两者进行比较。如果两者完全相同,则说明该交易的隐私数据是真实有效的。
- 保存所有的区块数据(即公有数据)到<font color="blue">区块数据文件</font>中,保存所有的私有数据(即隐私数据)读写集到<font color="blue">隐私数据库(LevelDB)</font>中,建立区块索引信息到<font color="blue">区块索引数据库</font>,将最新的有效交易数据(包含公共数据读写集、隐私数据读写集、隐私数据读写集哈希值)更新到<font color="blue">状态数据库</font>,最后将区块数据中经过Endorser背书的有效交易数据同步到<font color="blue">历史数据库</font>。同时,清理<font color="blue">transient隐私数据库中</font>的过期数据。
9. Leader主节点分发数据与状态同步
Leader主节点基于<font color="blue">Gossip消息协议</font>将区块数据分发到组织内的其他节点上。同时,<font color="blue">节点之间通过反嫡算法等机制主动拉取缺失的数据</font>(区块数据与隐私数据)、节点身份信息等,以确保组织内所有节点上的账本数据等信息保持同步。
10. Committer记账节点验证交易并提交账本(同步骤8)
至此,Hyperledger Fabric系统上的一次完整交易处理流程即告结束。
预告
从下一篇开始,我们就要正式开启fabric源码分析的专题了,本篇文章其实是一个知识准备。这里多说一句,就是我为什么要开启这个fabric源码分析的专题,其实这件事一直在我心中酝酿,但是由于前一段时间较忙,而且内心总是有一些否定的声音让我陷入自我怀疑,到底要不要做,因为现在网上已经有很多关于fabric源码分析的资料,而且质量也很高,为什么不直接抄“学霸”的作业呢,一定要自己搞一遍,不累吗?其实我是这样想的,“一千个读者就有一千个哈姆雷特”。那么我可不可以这么理解,“一千个开发者就有一千个fabric”。别人关于源码解读的文章都是基于其本人的知识架构下的,而如果我们一定要去灌输到自己的大脑中,可能会有些消化不良。而且我们也不能一味的迷信“权威”,学霸的作业也可能有疏漏的地方,别人的分析都是经过二次加工的产物,带有强烈的主观主义色彩,我们还是应该忠于源码,探索“属于我自己的fabric”。好了,废话有点多,接下来就进入正题吧。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。