背景介绍
曾经一篇标题为"震惊!V神和BM竟如此互怼!"的文章在网上热议起来,这是一篇BM和V神在issue上对于DPOS的机制的讨论,接下来我们具体讨论下他们的讨论内容:
先看一下英文版的:
翻译成中文版的:
这似乎并不安全。考虑一个包含四个验证器的情况,因此我们允许一个拜占庭。
假设在时间T之前,共同商定的头部是Z; 然后,有时(T,T + 1,T + 2,T + 3),
验证器(A,B,C,D)使得从Z延伸链的块.A现在有来自B,C和D的投票等等最终确定。
现在,在时间段T + 3结束之前,D 也(拜占庭)在Z之上形成一个块(称之为D')。
然后,有时(T + 4 ... T + 11),(A,B) ,C,D,A,B,C,D)在D'之上制作块(这是可以的,
因为每个验证器在高于其先前制作的块的高度处制作块)。
该链中的第二个A区块有三票,因此也是最终确定的。因此,两个冲突的块已经完成。
通常,如果没有来自直接或间接引用该块的大多数节点的至少两条消息,则无法在块上实现BFT安全性;
这个算法试图在一轮中完成它并且实际上不可能安全地做到这一点。
如果你想要一个直观而好的方法,我建议你只使用我们的Casper FFG文件中的算法:https://arxiv.org/abs/1710.09437
@V神
我们已经建立了以下可以削减的行为:
1.为同一时间戳生成两个块。
2.不管是直接还是间接地产生两个块确认。
3.为块时间戳的相同块数生成两个bft预提交消息。
单轮共识引起不可逆块冲突
我们先来看一下最初EOS的DPOS2.0+BFT的共识机制:当一个特定的区块被(2/3+1)生产者确认的时候,该块成为不可逆块。
假设现在有A,B和C三个块: A 生产了一个区块 N, B 生产区块 N + 1 并且确认了区块 N, C 生产区块 N + 2 并且确认了区块 N, N + 1 , 此时 N 已经有 3 个确认,达到了 2/3 + 1 个确认,则区块 N 成为不可逆。
提出问题: 上面所述的共识只经过了一次共识,那么会出现什么问题呢?
V神就在issue上提出一个例子,如下图:
可以看出第一条链 A 生产的 2 经过 B、C 已经达到了 3 个确认数已经成为不可逆了, 但此时 D 因网络不好, 没接收到这些块, 从而产生分叉开始生产区块 2 , 之后 A 生产区块 3 , 因为块高度大于之前的 2 ,所以是可生产的,B同理, 经过 A, B 之后 D 生产的 2 同样达到了三个确认数, 这样就会有 2 个块高度为 2 的区块成为了不可逆,造成冲突。
分析解决不可逆块冲突
为什么会造成这个原因呢? 因为区块 2 没有经过所有节点就成为不可逆了, 导致后面的产生的区块 2 可在下一轮被确认成为不可逆块。如果说 A ,B ,C ,D 都确认了区块 2, 那么下一轮谁都没可能生产块高度为 2 的区块。也就不会同时出现 2 个不可逆块了。 但全部节点确认才成为不可逆这就破坏了引入BFT的想法, 而且你没办法保证所有节点都会对他进行确认,毕竟网络延迟一直存在。
那怎么解决不可逆块冲突,但是又不会破坏BFT的想法呢? V神给出的解决方法:经过2轮(2/3+1)的确认,继续使用BFT的思想,破坏掉分叉的区块2成为最终的不可逆区块,因为最终的不可逆块已经是3,小于3的区块都认为是不可逆块了。
这里引进proposed lib的概念, 即可能成为不可逆的区块,简称plib: 一个区块经过2/3 + 1共识后,他不会立马成为lib, 会先成为plib, 然后再plib经过 (2/3+1) 共识后才会成为lib。 两轮共识的正常流程如下图:
再来看一轮共识,不可逆块产生冲突时,两轮共识的结果:
上图中,当D因网络不好,没接收到之前的块,从而产生分叉开始生产区块2,当一轮共识时,区块2成为不可逆区块时会产生冲突,经过两轮共识后,分叉的链,产生的备选不可逆块为2时,正常的链产生的最终的不可逆块已经是3,此时,小于3的区块都是最终的不可逆区块了。
其实这种方式你可以看成对有多条分叉链的处理,节点对这些链进行(2/3+1)共识来选出哪条plib分叉链作为主链(不可逆序号最大的链),丢弃掉其他plib分叉链。
总结
dpos3.0+BFT由最初的一次共识增加到了两次,避免掉出现conflict(冲突)lib, 但是这也让head_block_num和lib的高度拉到((2/3+1) * 21 - 1) * 12 * 2 = 336 个块(不考虑漏块的情况)。 根据一个区块生产的时间为0.5秒计算,产生最终的不可逆块的用时为:336 * 0.5 = 168