从事区块链相关研发几年了,共识这一块接触过pbft\kafka\raft,当然还有最经典的比特币的工作量证明,这个在上一篇比特币原理一文有讲述。对pbft一开始从fabric0.6开始,论文也看了几遍,后来共识换成了kafka\raft。pbft就没有继续研究下去,最近接触一个区块链底层平台,采用pbft。因此这里又把论文读了一遍,总结一下心得体会,对一些比较难理解的地方进行梳理。
关于分布式系统里能够容拜占庭错误的节点数n>3f+1,这个结论早在1982年图灵奖得主lamport《The Byzantine Generals Problem》已经证明过:当将军总数大于3f时,叛徒数小于等于f时,忠诚将军能够达成一致,其算法复杂度为指数O(n^(f+1))。
图灵奖得主Barbara Liskov和其学生Miguel Castro在1999年发表的论文《Practical Byzantine Fault Tolerance》中首次提出pbft算法,该算法容错数量也满足3f+1<=n,算法复杂度为O(n^2)让容拜占庭错误的共识算法可用于工程实践。
下面是自己的一些理解及简单证明,至于详细的证明论述可以参考Lamport论文。例如A、B、C三位将军,忠诚将军应该执行进攻命令;A是叛徒,向B发送撤退指令,向C发送进攻指令。这时对于B将军来讲,他分不清A是叛徒还是C是叛徒。
设总结点数为N,作恶的拜占庭节点数为 f,法定人数为Q。
要满足liveness必须:
Q <= N - f
因为如果共识算法需要的Q大于N-f,则当f个拜占庭故障节点都主动破坏时,算法必然不能执行下去。
要满足safety必须:
2Q - N > f
因为任何两个quorum的交集(2Q - N)中必须有非拜占庭故障节点大于f个。如果2Q - N <= f,此时f个节点同时加入到两个Quorum中说不同的话,系统内会同时通过两个不同的意见,此时系统一致性无法满足。
因此
N + f < 2Q <= 2(N - f)
N > 3f
Q_min=2f+1
1、client向Primary发送请求:
2、primary会对req分配一个序号seq n,生成pre-prepare:<
3、rep节点收到pre-prepare,如果满足一下条件则接受:
4、如果副本节点i接受pre-prepare,则进入prepare阶段,广播
5、如果节点满足以下条件则认为prepared:
6、当处于prepared,则进入Commit阶段,广播
7、如果收到2f+1个commit,则执行,并把结果返回client.
8、当Client收到f+1个相同结果,则认为执行成功,因为最多有f个错误,收到f+1个相同结果说明都是对的。
主要因为在共识过程中要保存message到log,为减少存储的消息,会有一个稳定状态的检查,如果达到稳定状态则删除之前的消息。
每隔一段时间会产生一个checkpoint,
当primary节点挂掉后,viewchange协议保证了liveness。
副本节点rep收到request时如果timer还没启动则启动timer直到该交易执行完成;
1、如果timer time out了,则会view change,这时只接收checkpoint,view-change,new-view消息,其他不接收
2、广播
3、当view v+1的primary节点收到来自其他2f个节点的view v+1的view-change后,广播
4、接下来,Primary会把O中消息记录到自己log中,如果min-s latest stable checkpoint的seq num,也把seq-num为min-s的checkpoint 记录到log中。并除去stable checkpoint以前的消息。
5、副本节点接受view v+1的new-view message,如果满足:
协议使得重新执行min-s到max-s的消息,但避免重新执行client的request,利用存储在自己log中的消息。
有些节点可能丢失 request message或者stable checkpoint s,因为在new-view message中没有传递,这些内容可以通过向其他节点同步来获得。