在DPOS2.0时代,V神提出一个问题,也就是原来大家一直认为BFT是不会有分叉的现象的,但是在V神看来,这个是有可能的,看下面的示例:
上图中可以看到,假设Z为不可逆块,有A,B,C,D四个节点出块,当从A开始到c完成出块,即达到2N/3 + 1(所有出块节点的三分之二再加一),即达到新的不可逆节点。
但是假如D节点断网了,看不到102以后的块,自己出了一块101,然后又连接到网络上了,而ABC三个节点又无法控制必然是跟随哪个节点出块,假设一种情况,它们都从D(101)开始,继续出块,如上图,这也是合法的,在达到B时,发现会有两个101提交,产生冲突,结果就不知道哪条链中的不可逆块是合法的。
BM得知后不服啊,带着兄弟们搞出了如下的名堂,也就是说,不可逆块不是一次到位了,分成两步,先生成一个prelib,然后再经过2/3共识后,生成真正的lib(不可逆块)。
好是好,确实解决了问题,但是,结果是增加了不可逆块的确认时长和块数。
从目前来看,应该是增加了三倍左右的时间。
BM新的方法基本流程如下图:
当出块时间到达E时,产生一个prelib,然后依次递进,当prelib再次达到105时,101正式成为不可逆的lib.
重点来分析一下异常的情况,先看一下下面的图:
在上面的图中,仍然假设在虚线E处生成离线又连线的101,这时候儿有以下几种情况:
- 正式分叉到E,即如上图所示,一直延展下去,最张抛弃A产生的101块。通过第二次的共识,确定E生成的101为不可逆块。
- 在E的基础上生成几块后又回到以A的基础的块生成,这时候儿就要看哪个先达到三分之二加一共识,也就是说最长链。最终抛弃短链。
- 比较麻烦的是来回跳跃,某一个始终达不到最长,结果就是可能需要很长时间才能出块,因为最终肯定会有一个链最长的。
参考的站点:
https://github.com/EOSIO/eos/issues/2718
https://medium.com/eosio/dpos-bft-pipelined-byzantine-fault-tolerance-8a0634a270ba
https://github.com/EOSIO/eos/issues/3088