这篇文章主要是讲一下RBFT中共识算法流程以及节点的加入的流程。在下一篇博客中,将使用Java实现该算法。html
传统的PBFT算法没法动态的添加和删除结点,高鲁棒拜占庭容错算法RBFT(Robust Byzantine Tolerance)算法实现了该功能。node
在RBFT算法中,有几个变量咱们须要知道:f,N,quorum算法
所以在PBFT算法中,为了可以容忍f个错误,须要的结点数量是$3f+1$缓存
在RBFT算法中,有一个主节点和多个从结点,其中主节点是经过选举产生的,负责对客户端发来的交易进行打包处理,而从节点很简单,进行共识认证以及主结点的选取。微信
下面是来自hyperchain的关于RBFT流程的一些介绍:网络
RBFT常规流程
RBFT的常规流程保证了区块链各共识节点以相同的顺序处理来自客户端的交易。RBFT同PBFT的容错能力相同,须要至少3f+1个节点才能容忍f个拜占庭错误。下图为最少集群节点数下的共识流程,其N=4,f=1。图中的Primary1为共识节点动态选举出来的主节点,负责对客户端发来的交易进行排序打包,Replica2,3,4为从节点。全部节点执行交易的逻辑相同并可以在主节点失效时参与新主节点的选举。并发
常规流程
RBFT共识保留了PBFT原有的三阶段处理流程(PrePrepare、Prepare、Commit)的同时增长了重要的交易验证(validate)环节,在保证对交易执行顺序达成共识的同时也保证了对区块验证结果的共识。异步
![]()
RBFT常规流程在原生的PBFT算法中穿插了交易验证环节,主节点将交易打包成块后先行验证,并将验证结果包含到PrePrepare消息中进行全网广播,这样PrePrepare消息中既包含了排好序的交易信息也包含了区块验证结果。从节点在收到主节点的PrePrepare消息后先检查消息的合法性,检查经过后广播Prepare消息代表本节点赞成主节点的排序结果;在收到(quorum-1)个Prepare消息后从节点才会开始验证区块,并将验证结果与主节点的验证结果进行比对,比对结果一致则广播Commit代表本节点赞成主节点的验证结果,不然直接发起ViewChange代表本节点认为主节点有异常行为。RBFT常规流程具体分为以下几个步骤:svg
- 交易转发阶段: 客户端将交易发送到区块链中的任意节点(包括共识节点与记帐节点),其中记帐节点在收到交易后会主动转发给与其相连的共识节点;而共识节点在收到客户端的交易后将其广播给其余共识节点,这样全部共识节点的交易池中都会维护一份完整的交易列表;
- PrePrepare阶段: 主节点按照以下策略进行打包:用户能够根据需求自定义打包的超时时间(batch timeout)与打包的最大区块大小(batch size),主节点在超时时间内收集到了足够多(超过最大区块大小个数)的交易或者超时时间到达后仍未收集到足够多的交易都会触发主节点的打包事件。主节点将交易按照接收的时间顺序打包成块,并进行验证,计算执行结果,最后将定序好的交易信息连同验证结果等写入PrePrepare消息中广播给全部共识节点,开始三阶段处理流程;
- Prepare阶段: 从节点在收到主节点的PrePrepare消息后,首先进行消息合法性检查,检查当前的视图与区块号等信息,检查经过后向共识节点广播Prepare消息;
- Commit阶段: 从节点在收到(quorum-1)个Prepare消息以及相应的PrePrepare消息后进行验证,并将验证结果与主节点写入PrePrepare消息中的验证结果进行比对,比对结果一致则广播Commit代表本节点赞成主节点的验证结果,不然直接发起ViewChange代表本节点认为主节点存在异常行为,须要切换主节点;
- 写入帐本: 全部共识节点在收到quorum个Commit消息后将执行结果写入本地帐本。
以上的过程仍是很简单的,就是主节点发送交易信息,若是大部分的从结点(也就是quorum个结点)赞成,则这个交易信息会被写入全部结点的区块(少数服从多数)。区块链
在前面咱们能够发现,从节点是能够怀疑主节点的,也就是说从节点能够发起请求进行从新选举,获得一个新的主节点(这个在主节点被攻击或者宕机是很是有效的)。
在PBFT以及RBFT中,都有视图(View),这个值从零开始只增不减。那么咱们如何获得主节点呢?或者说从新选举,选择谁为主节点。
设:结点数为N,当前视图为view,则主结点的id为:
$$primaryId = (view +1) mod N$$
下面的引用仍是来自hyperchain,毕竟有图可以理解的更好。其中:
视图变动流程
![]()
上图中,Primary 1为拜占庭节点,须要进行ViewChange。在RBFT中的ViewChange流程以下:
- 从节点在检测到主节点有异常状况(没有按时收到nullRequest消息)或者接收到来自其余f+1个节点的ViewChange消息以后会向全网广播ViewChange消息,自身view从v更改成v+1;
- 新视图中主节点收到N-f 个ViewChange消息后,根据收到的ViewChange消息计算出新视图中主节点开始执行的checkpoint和接下来要处理的交易包,封装进NewView消息并广播,发起VcReset;
- 从节点接收到NewView消息以后进行消息的验证和对比,若是经过验证,进行VcReset,若是不经过,发送ViewChange消息,进行又一轮ViewChange;
- 全部节点完成VcReset以后向全网广播FinishVcReset;
- 每一个节点在收到N-f个FinishVcReset消息以后,开始处理肯定的checkpoint后的交易,完成整个ViewChange流程。
因为共识模块与执行模块之间是异步通讯的,而ViewChange以后执行模块可能存在一些无用的validate缓存,所以共识模块须要在ViewChange完成以前通知执行模块清除无用的缓存,RBFT经过VcReset事件主动通知执行模块清除缓存,并在清理完成以后才能完成ViewChange。
在前面咱们知道,PBFT算法是没法实现结点动态的增删的,而新的算法RBFT实现了该功能。
结点的增长和删除固然会遵照共识原则,下面仍是来自hyperchain的介绍。毕竟别人介绍的比我好多了,我就很少介绍了。
简单点来讲,就是新加入的结点会向区块链中的已经存在的结点申请加入,若是存在的结点赞成的话,则就加入成功,而后新加入的结点会发送recovery消息(关于recovery能够看hyperchain的介绍),目的是为了让本身与区块链中结点的内容保持一致。而后新加入的结点会要求进行从新选举主节点(由于N已经发生改变),而后完成主节点的更改。
新增节点流程
![]()
上图中,Replica 5为待新增的节点。RBFT节点的动态新增节点流程以下:
- 新增节点Replica 5经过读取配置文件信息,主动向现有节点发起链接,确认全部节点链接成功后更新自身的路由表,并发起recovery;
- 现有节点接收到Replica 5的链接请求后确认赞成该节点加入,而后向全网广播AddNode消息,代表本身赞成该新节点加入整个共识网络;
- 当现有节点收到N条(N为现有区块链共识网络中节点总数)AddNode消息后,更新自身的路由表,随后开始回应新增节点的共识消息请求(在此以前,新增节点的全部共识消息是不予处理的);
- Replica 5完成recovery以后,向全网现有节点广播ReadyForN请求;
- 现有节点在收到ReadyForN请求后,从新计算新增节点加入以后的N,view等信息,随后将其与PQC消息封装到AgreeUpdateN消息中,进行全网广播;
- Replica 5加入后的共识网络会产生一个新的主节点,该主节点在收到N-f个AgreeUpdateN消息后,以新的主节点的身份发送UpdateN消息;
- 全网全部节点在收到UpdateN消息以后确认消息的正确性,进行VCReset;
- 每一个节点完成VCReset后,全网广播FinishUpdate消息;
- 节点在收到N-f个FinishUpdate消息后,处理后续请求,完成新增节点流程。
这篇文章基本上就是从hyperchain上面copy上来的,在这里仅仅是作一个笔记用。若是想了解更多,建议参考官方文档。这一篇主要是为了弄清楚PBFT or RBFT的流程,这几天在看《区块链底层设计 Java实战》一直没弄得太懂,而后代码也写的没头绪。这里不得不感谢牛冬(这本书的做者)大佬,很热心的回答个人问题(真没想到加做者的微信居然加成功了O(∩_∩)O~~)。
哦,还得掉头发,想想怎么实现这些算法……