与我们交流区块链相关技术请关注长安链公众号:长安链ChainMaker,点击加入社区进群交流。
作者为长安链核心开发工程师史金乾。
编者语:
长安链ChainMaker(以下简称“ChainMaker”)目前实现了很多种共识算法,比如SOLO、RAFT、TBFT、HOTSTUFF等,TBFT共识算法是ChainMaker实际应用中常见的共识算法。TBFT共识算法是一种拜占庭容错算法,可以在拜占庭节点数小于总数1/3的情况下,保证系统的安全运行,本文主要对ChainMaker TBFT共识源代码进行解析。
TBFT基于Tendermint算法,与PBFT的最大区别在于:PBFT有一个固定的leader节点打包交易,当leader节点故障的时候会使用view-change子协议更换leader;而在TBFT中,leader是轮换的,每提交n个块(可以配置)leader会轮换成下一个节点。因此,TBFT比PBFT有更好的公平性。
一、ChainMaker TBFT共识流程
1.1 TBFT 节点之间的共识流程
- NewRound: 共识投票的准备阶段,会初始化共识相关状态;
- Proposal: 提案阶段,leader节点会打包区块,并广播给follwer节点;
- Prevote: 预投票阶段,follower节点在收到proposal并验证proposal合法后,广播自己的prevote投票到其他节点;
- Precommit: 预提交阶段,节点收到 >2/3 针对proposal的prevote投票后,广播自己的precommit投票到其他节点;
- Commit: 提交阶段,节点收到 >2/3 针对proposal的precommit投票后,提交proposal中的区块到账本。
1.2 TBFT 节点自己的共识阶段
TBFT共识网络启动后,共识节点本地的各个共识阶段如下:
二、TBFT共识代码解析
2.1 TBFT源代码目录
- TBFT共识模块的源代码目录为:module/consensus/tbft;
- TBFT的核心代码文件:module/consensus/tbft/consensus_tbft_impl.go;
- 本文分析的ChainMaker源代码分支为v1.1.1。
2.2 TBFT共识流程代码解析
开始阶段
Start方法对应TBFT共识流程中的开始阶段,它是TBFT共识的启动函数,主要实现了:
- 注册Msgbus与TBFT共识相关的topic,为TBFT共识后续通过Msgbus传输消息做准备。Msgbus类似消息中间件mq,实现了消息发送方和消息接收方之间的解耦;
- 如果共识节点重启,就需要从wal日志中恢复TBFT共识宕机时的共识状态;
- timeScheduler用来设置proposal阶段超时重新选主节点的逻辑;
- gossip主要用来在共识节点之间传输网络消息的,同步共识状态、投票消息;
- handle方法用来处理TBFT共识中涉及到Channel的共识消息。
NewHeight阶段
enterNewHeight方法对应TBFT共识流程中的NewHeight阶段,这是进入新区块高度的起始阶段。NewHeight阶段会设置新区块高度,重置Round为0,添加、移除验证者,然后进入NewRound阶段,开启一轮对新区块的验证、投票、提交。
NewRound阶段
enterNewRound方法对应TBFT共识流程中的NewRound阶段 ,进入新一轮Round,需要重新初始化相关的共识状态,将Proposal、VerifingProposal重置为空,设置NewRound阶段的意义:共识节点在投票阶段有可能会超时,超时未对新区块达成一致投票,那么就进入下一轮投票round+1,直到对新区块投票达成一致。
Proposal阶段
enterPropose方法对应TBFT共识流程中的Proposal阶段,Proposal超时后,会重新选举主节点,如果没有超时,主节点会通过msgbus发送消息给核心引擎,核心引擎负责打包区块,然后返给主节点,所有共识节点都会广播共识状态,告诉其他共识节点,自己进入了新的块高。
Prevote阶段
enterPrevote方法对应TBFT共识流程中的Prevote阶段,共识节点在Prevote阶段,首先会生成区块的prevote投票并签名,然后把投票放到internalMsgC通道中,最后广播给其他共识节点。
Precommit阶段
enterPrecommit方法对应TBFT共识流程中的Precommit阶段,共识节点在Precommit阶段,首先会验证prevote投票是否大于2/3,如果满足,会生成对区块的precommit投票并签名,然后将投票放到internalMsgC通道中,最后广播给其他共识节点。
Commit阶段
enterCommit方法对应TBFT共识流程中的Commit阶段,共识节点在Commit阶段,首先会验证precommit投票是否大于2/3,如果满足,共识节点把区块发给核心引擎,核心引擎负责把区块提交到账本中。
三、TBFT共识模块与核心引擎模块的交互
3.1 共识与核心引擎的交互流程
TBFT共识模块和核心引擎模块是通过Msgbus互相传递消息的,核心引擎模块为TBFT共识模块提供区块打包、区块验证、提交区块到账本的功能。
3.1.1 ProposaState,Proposal是主节点专有的共识阶段
- ProposaState: TBFT发送给核心引擎本节点在当前高度是否是leader节点,核心引擎如果是leader节点,需要打包区块;
- Proposal: 核心引擎打包区块并发送给TBFT。
3.1.2 Verify和VerifyResult是从节点专有的共识阶段
- Verify: 当从节点收到主节点发来的区块后,向核心引擎验证区块读写集等信息;
- VerifyResult: 核心引擎返回给TBFT Verify的结果,当区块合法时,本节点将会投票给区块。
3.1.3 主节点和从节点都包含Commit和BlockInfo阶段
- Commit: TBFT完成共识后,向核心引擎发送提交区块的信号,核心引擎提交区块到账本;
- BlockInfo: 核心引擎告知TBFT已提交区块的高度等信息,TBFT进入下一个高度。
3.2 共识与核心引擎交互代码解析
OnMessage方法对应接受核心引擎发给Msgbus的消息,包括Proposal、VerifyResult、BlockInfo,然后Msgbus把消息放到各个相应channel中等待被处理。
handle方法处理OnMessage方法放到各个channel中的消息。
四、共识节点之间的交互
以发送prevote投票为例,共识节点之间传输共识消息的流程图如下:
节点通过Msgbus,调用publishToMsgbus函数,向其他节点发送消息。
4.1 共识节点发送共识消息给其他共识节点
4.1.1 节点主动发送消息给其他节点。
4.1.1.1 进入Propose阶段,需要向其他节点同步自己进入到新的块高了。
4.1.1.2 如果收到自己的投票就直接触发,即节点自己主动把自己的投票信息添加到投票集合发送给其他节点。
4.1.2 节点被动发送共识消息
如果节点收到其他节点发送给自己的共识状态消息,会将消息响应相应的节点,证明自己收到了该消息。
4.1.3 节点发送共识消息的判断
以节点发送Prevote投票为例,如果收到节点的投票集合中不包括自己的投票,那么就发送自己的投票。
4.2 共识节点接受其他共识节点发送的共识消息
共识节点之间传输的共识消息主要有4种类型:propose,provote,precommit,state,然后分别进行处理。
五、总结
本文主要对TBFT共识的整体流程以及涉及到的关键代码进行了整理和解析,代码解析主要包括3个部分,TBFT共识的各个阶段、共识模块与核心引擎模块的交互、共识节点之间的交互,同时通过TBFT相关的共识流程图更加直观的展示了TBFT共识过程。TBFT共识算法涉及多个阶段、多个节点,不同模块之间的交互,相对比较复杂,需要在掌握TBFT的基本概念、实现原理、整体流程的基础后,再深入到TBFT代码层面,进行详细研究。
“长安链ChainMaker”是国内首个自主可控区块链软硬件技术体系,由微芯研究院、清华、北航、腾讯和百度等机构共同研发,具有自主可控、灵活装配、性能领先、开源开放的突出特点。长安链面向大规模节点组网、高交易处理性能、强数据安全隐私等下一代区块链技术需求,融合区块链专用加速芯片硬件和可装配底层软件平台,为构建高性能、高可信、高安全的数字基础设施提供新的解决方案,为长安链生态联盟提供强有力的区块链技术支撑。取名“长安链”,喻意“长治久安、再创辉煌、链接世界”。