【共识系列.01】PBFT为什么需要三阶段

【共识系列.01】PBFT为什么需要三阶段


本文面向对PBFT算法有一定了解的同学,因此PBFT算法的背景介绍以及具体的流程算法本文不做介绍。

1.两阶段为什么不能达成共识

- 现在假设算法为两阶段,并且假设主节点为诚实节点

算法的流程为:
a. 客户端将自己的请求转发给主节点(或者通过其他的从节点转发给主节点);
b. 之后主节点构造pre-prepare消息,并将其转发给其他的从节点(由于主节点是诚实节点,因此主节点发送给其他从节点的消息都是一致的);
c. 从节点验证pre-prepare的签名,视图,水位线以及是否冲突(主节点给客户端发送的每条消息都会赋予一个编号,同一编号消息是相同的,冲突就是同一编号但却是不同的消息),验证通过则发送prepare消息到其他节点;
d. 当一个节点收到2f+1个(包括自己的,当然也包括主节点的,实际上主节点发送pre-prepare消息之后就不会发prepare消息了)相同的prepare消息,则此消息在该节点prepared,之后执行消息。

如果是两阶段的话,请求被当前节点prepared之后就应该去执行。那如果prepared之后直接去执行有没有问题?

比如A节点已经prepared,但这个时候只能确定A节点prepared,其他诚实节点可能由于网络延时或其他原因还没有收齐2f+1个prepare消息,因此其他诚实节点没有prepared,也就是说其他诚实节点不会去执行。若A节点自己去执行,会破坏安全性吗?答案是否定的,PBFT中有个重要的假设:网络是弱同步的(网络终究会进入同步的状态)。随着GST的到来(不知道会什么时候到来,但终究会到来),网络会进入同步的状态,其他的节点会收到其他好的节点发送的prepare消息,所以也会进入prepared状态,当然了也就会去执行,从而保证了整个系统的安全性。

现在考虑主节点宕机换主,换的主也是诚实节点(因为假设就是主节点都是诚实节点),换好主之后主节点可以去收集其他从节点还未prepared的pre-prepare的消息,由于前后的主节点都是诚实的,新的主节点可以很容易的验证收集到的pre-prepare消息的合法性,之后新的主节点将收集到的合法的pre-prepare消息修改视图编号之后重新发起,从而保证了跨视图的安全性。

所以在主节点诚实的情况下,两阶段可以达成共识。

- 现在假设算法为两阶段,并且假设主节点可能是恶意的情况

算法的流程为:
a. 客户端将自己的请求转发给主节点(或者通过其他的从节点转发给主节点);
b. 之后主节点构造pre-prepare消息,并将其转发给其他的从节点(由于主节点可能是恶意节点,因此主节点发送给其他从节点的消息可能是不一致的);
c. 从节点验证pre-prepare的签名,视图,水位线以及是否冲突,验证通过则发送prepare消息到其他节点(因为这一步从节点与从节点之间不会交互,因此主节点发送给从节点不一样的消息这一步仍会验证通过);
d. 当一个节点收到2f+1个(包括自己的,当然也包括主节点的,实际上主节点发送pre-prepare消息之后就不会发prepare消息了)相同的prepare消息,则此消息在该节点prepared,之后执行消息。

考虑一种情况,主节点在编号为n的操作给其中的f+1个诚实的从节点(这些节点的集合我们称为M)发送了m,给其他f个诚实的从节点(这些节点的集合我们称为M’)发送了消息m’(或其他和m不一致的消息),之后进入prepare阶段,M中的节点(f+1个)会给m投票。假设另外f个作恶节点(包括主节点)只向M中的部分节点(M1)发给m投票的消息,向M中的其他节点(M2)给与m冲突的消息投票,最终M1中的节点会提交m,而由于M2中的节点始终无法2f+1个投票,则不会去提交。而这个时候如果M’或M1收到了彼此的投票消息,发现当前的主节点是恶意节点,会发起换主请求。新的主会去重新对n发起新的消息,如果新的主是一个诚实节点,则新的主会收集2f+1个已经执行的消息,但假如收集的消息中不包含已经提交的消息(因为只有少于f+1个节点提交了m),这个时候新的主节点不会去重新发起m,这时就会引起冲突,系统的安全性被破坏;如果新的主也是恶意节点,安全性更没办法保证,比如这时新的主就会故意的不去发起m,当然也可以很容易构造自己不发起m的证据,现在除了M1中的节点(超过2f+1个)都没有提交,因此会同意新主的请求(因为他们也不知道有人已经提交了),这个时候主发起的请求会收到2f+1个投票,从节点会执行主发起的请求,就和之前执行m的节点发生了冲突,这个时候就出现了不一致。系统的安全性由此被破坏。

但假如不换主(尽管主节点是恶意节点但仍不换主),过一段时间,M1中的所有节点会去执行m,而最终M2和M’中的节点由于始终无法收到2f+1个投票,这个时候系统就会死在这里,那就有人说了,不是M1中的所有节点都已经提交了嘛,那M1中的节点执行完之后直接把自己执行的消息广播出来不久好了,其他的节点只要收到提交的消息之后,再去执行不就可以完成了嘛?!但需要注意,这个时候从这些没有提交的节点的角度来看,他们是不知道是否已经有人提交了的,他们如果一直等待的话,可能就是在等待一个没有结果的结果----因为有可能根本就没人提交,所以等还是不等,That’s a question

所以在主节点是恶意节点的情况下,两阶段不可以达成共识。

2.三阶段为什么能达成共识

三阶段算法相比于两阶段多了一个commit阶段,节点在第二个阶段prepared之后,会发送commit消息,commit阶段每个节点会收集其他节点的commit消息,如果收到2f+1个commit消息,并且自己本身已经prepared,则会去提交然后执行请求。

现在假设诚实节点A已经提交了消息m,如果恶意节点想要破坏系统的安全性,就会想办法让其他的诚实节点提交和m不同的消息。其实当前的这个主节点无论好坏,这个时候他想要做啥都已经无力回天了,因为PBFT算法流程中,恶意主节点和其他恶意节点唯一的不同就是恶意主节点可以发起pre-prepare消息,其他流程中他和普通恶意节点没有什么不同,所以这个时候如果有一个诚实节点已经commit,主节点实际上做不了什么特殊的事情,目前算法的设计就已经能够保证最终所有的诚实节点都会commit。

所以这个时候如果主节点是恶意节点的话,唯一能做的就是自己把自己挂掉(比如不响应其他节点,引起超时,从而引起其他的从节点认为自己已经挂掉),然后寄希望于下一个主节点是恶意的,然后发起和当前已经提交的诚实节点提交的消息(m)不一样的消息(m’)。

换主过程中,新的主节点会收集2f+1个换主(view-change)请求,换主请求中会包含当前节点已经prepared但还没有commit的消息。收到2f+1个view-change请求之后,新的主节点发起new-view消息,new-view消息中包含2f+1个换主(view-change)请求,每个view-change请求中会包含当前节点已经prepared的消息以及相对应的需要新提起的pre-prepare消息(方便其他节点可以检查当前这个主节点是不是会提出一些冲突的请求)。

2f+1个view-change请求里面必定包含当前已经提交的m的prepared信息。

因为节点提交m时需要2f+1个commit消息,也就意味着有2f+1个节点对m已经prepared了,其中至少包含f+1个诚实节点(这f+1个节点的集合我们表示为H)。当换主时,新的主节点收集的2f+1个换主请求中,必定包含H中的其中一个节点的换主消息,因为除掉上面的那f+1个诚实节点,系统中只剩2f个节点了,是凑不够2f+1个的,所以为了换主成功,必定至少包含前面的那f+1个诚实节点(集合H)中的一个,而这一个诚实节点会将已经commit的消息相应的prepared消息放到view-change请求里面,而这也必定会被新的主节点重新提起。通过这种方式就会强迫新的主节点会将当前已经commit的消息带到下一轮,不然的话,会被大家检测出来,又会换主,直到换到一个诚实的主节点。

从本质上来讲,commit阶段就是想要在存在换主的情况下,新的主节点能够把被部分诚实节点已经提交的请求在下一轮重新提起,使得没有提交的诚实节点也会提交,从而保证全局的一致性。

通过commit阶段,保证了最终不会提交和已经commit的消息冲突的消息。所以三阶段就彻底保证了在恶意主节点存在的情况下,既能保证算法的活性,又能保证算法的安全性。

因个人专业能力和理解水平有限,如有理解错误或不到位的地方,敬请批评指正。

转载请注明出处。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值