Hoo虎符主办EOSing线上专访第四十二期:BOS核心代码贡献者
03/15

由Hoo虎符钱包主办的EOSing线上专访第42期,本期嘉宾deadlock,是BOS的一名技术开发人员, 同时也是 eosio.sg 的CTO。

 

本期内容要点:

1. DPOS Batch PBFT 原理介绍

2. BOS主网共识升级提案

 

第一部分原理介绍


DPOS Batch PBFT 有三部分特性,分别是:

1. DPOS: 继承了DPOS特性, 通过链上投票选择BP, 同时保证了恒定时间间隔出块

2. PBFT: 成熟的理论和实践基础, Practical Byzantine Fault Tolerance (pBFT)

3. Batch: 动态批量共识

 

三个特性以及设计的思路和难点我们会一一讲出来,首先介绍DPOS,DPOS的两个特性 1. 链上投票选出BP 2. 稳定时间间隔出块,这两个特性融合的时候是有难点的, 分别分析完这两个特性后我们再具体讨论。

 

链上投票的概念很容易理解, 他是一个每时每刻都在投票的系统, 得票最多的人就获取了代表席位, 替大家做出决策,也就是21个BP拥有最高权限, 而用户决定了谁会成为这21个BP。

 

而稳定时间间隔出块原理是这样的, 依据现在的BP Schedule 和当前时间 t, 算出接下来 0.5秒的 time slot该那个BP出块, 然后按照这个规则来出块。

 

这两个特性融合的时候有一个难点,就是在持续出块的过程中,如何变动BP Schedule。从BP Schedule A (A1-A21)变为 BP Schedule B (B1-B21)。A里BP正在出块,HEAD 和 LIB 有一定的高度差,此时投票变动,B里的BP该在什么时候开始出块,又如何保证这个投票的信息是安全的被全网共识的。

 

pipeline BFT的解决方案是使用事件驱动的思路去做,pipeline BFT 就是目前EOS mainnet所用的共识方案。

主网启动前有一次讨论在这里  相关链接


pipeline BFT的解决方案是使用事件驱动的思路去做,BP有两大触发器,一个是0.5秒间隔的时间触发器,用来检查是否该自己出块,第二个是收到block的触发,收到block后会加入fork_db中,然后改变自己的链的状态。而出块意味着需要选择一个块作为自己的链上一个块,出的这个块就包含了两部分信息,第一部分是块里的交易内容,第二部分是一个间接的隐藏信息,申明我是支持上一个块代表的链的,这个申明就是pipeline BFT的共识基础。


他通过这种间接的方式把所有信息附加在了自己出的块上,正因为每个BP要等到自己出块的时候才可以对外发声, 而完整的共识确认需要两轮确认, 所以pipeline BFT需要的共识时间才会长达3分钟。

 

DPOS Batch PBFT的解决方案也是类似,区别在于BP的声明信息是不跟着块走的,也就是说共识信息是单独的信息进行传递。设计思路是这样的,这个方案的左手收集同步区块,右手收集同步共识信息,然后把两个手上的信息结合起来,不停的计算是否满足共识条件,一旦满足之后, 就把LIB提升上来。

 

接下来是 PBFT 的特性,这是一个理论非常成熟的算法,已经被业界大量应用。

 

这个是PBFT的原理图

 

通过prepare和commit进行两次确认来达成共识,本身PBFT是针对 c/s 结构,也就是 客户端 / 服务器 的结构,出块的bp相当于是 客户端,提交了一个 pre-prepare,然后由剩下的 20个 BP进行共识,也就是说当块发出的时候,已经完成了 pre prepare的这一步,PBFT的一个特点就是每次仅针对一个块进行共识,而且当共识在进行的时候,整个网络是不出块的,也就是说,PBFT是出一个块,停下来等共识,共识完成后再出下一个块,PBFT设计的最精妙的部分是在view change,这部分可以说是整篇论文的精华。

 

这一块的理论非常的精妙, 我摘抄了一下原文:

The three phases are pre-prepare, prepare, and commit. The pre-prepare and prepare phases are used to totally order requests sent in the same view even when the primary, which proposes the ordering of requests, is faulty. The prepare and commit phases are used to ensure that requests that commit are totally ordered across views.

 

这里重点提到了 :

  1. 同一个view里的total order 

  2. 不同view的total order

 


这是 BOS的技术白皮书里面的示意图,当网络出现波动的时候, 或者大家网络连接被断开了, 就会切换到右边的状态。大家都贡献出自己的信息来帮助整个网络恢复正常的时候,这就是 view change的流程。


可以这么理解view,  大家都在同一个楼层上看楼房外面的东西,这时候大家看到的都是在同一个view里的,  大家靠的也近, 互相之间讨论也没问题。然后网络出现问题了,  大家按照之前的约定, 又向上爬了一层,  view + 1,然后大家又开始正常通信了。那么上一个view里, 大家达成的协议, 也必须要带到 view + 1 里面来。


view change 是我觉得网络有问题了, 虽然我不知道你们怎么样, 我发一个 view change 信息出来, 大家好知道我觉得不太对劲,当我收到很多不同人的view change的时候,就说明这个网络真的有问题,那大家一起往上走一层吧。

 

换到PBFT的  prepare - commit 流程里面,只要有一个人在之前的 prepare-commit的流程中进入到了committed状态, 这个block就一定会在view change之后被保证依然进入commit状态,从而达到一致性的要求,哪怕这个唯一进入commit的人的网络是被全网断开的。

 

接下来就是Batch PBFT的重点特性batch。这个特性是融合DPOS和PBFT的关键,DPOS需要持续出块,PBFT需要出一个块停下来共识. 这里有着一个矛盾点需要解决,这两方面的特性需要融合的时候, 就需要做出创新的改变.异步网络的特性导致了大家没有办法在同一个时间(对应到DPOS就是同一个块高度), 一起喊口号1,2,3来进行共识操作. 那么如何解决这个问题就是一个难点了。

 

我们的方案是利用区块链merkle tree的特性,不同的BP对链的不同高度进行 prepare, 间接的就可以计算出满足prepared人数的那个块。

 


举例说明: 现在有7个BP, 分别prepare了  100, 102,103 ... 106 的块.小人代表了 BP 支持这个块进共识,右边是统计的数字, 有多少人支持这个块,在BFT里面   N = 3k +1 ,  N是总人数,  k是允许的作恶人数,BP 们都选了一个块进行 prepare,  支持 #106的人就相同于同时支持了 #100 - #106的所有块。我们把 BP prepare的 block number 都取出来, 进行降序排列,然后再 index = N/3 的地方, 拿到的数字,  就是计算得出的prepared的block number.所以这个 batch的个数,  是动态的, 根据网络情况实时计算出来的。

 

batch引出的另一个需要解决的难点就是DPOS的链上BP变更的问题. 如果现有LIB到HEAD中间的一个块有BP变动, 这个点后面的部分就不应该由LIB上的BP进行共识, 而是应该由新的BP进行共识.解决这个问题的方法是使用watermark进行监控, 当有BP变动的时候, watermark会停止在这个变动的块高度, 当这个块进入LIB之后, BP的变动也随之发生, 从而保证了BP变更的安全性。

 

第二部分:升级提案


经过测试网的测试, 目前LIB的代码已经可以达到

CDF block 6 = 90.192 ± 0.2 % (95% CI)

CDF block 10 = 99.022 ± 0.034 % (95% CI)

 

具体数据在 相关链接

 

这个公式可以理解为: 我们有95%的信心保证 90%的块会在3秒内进LIB, 误差不超过0.2%, 99%的块会在5秒内进LIB, 误差不超过 0.034%

 

升级提案的思路是保证用户无感知的情况下, 进行两种共识算法的切换。因为pipeline BFT的特性, HEAD和LIB之间至少会相差325个块的高度, 在切换完成后, 这300+的块就会用DPOS Batch PBFT来进行共识。

 

而这300+的块是在原本共识的影响下使得 GB-2nd 进入LIB. GB-2nd 相当于第二个genesis block, 他跟最初起链时候的genesis block的区别在于, 那时候是eosio或者abp出块, 一个人进行共识, 而GB-2nd是21个BP进行共识, 所以需要保留链上证据。

 

在升级的过程中只需要保证BP Schedule不发生变化即可, 升级后的node代码会保证这段时间的BP变更功能是暂时锁定的。

 

整个系统升级是不影响正常用户使用的,  只需要在 maintenance mode ON的时候 暂时锁定 BP schedule,  持续大约3分钟,需要BP们都升级到最新的版本,  然后BP们需要通过多签的方式设置图中的 GB-2 的块高度,当系统达到这个高度的时候, 新代码会自动完成剩下的所有工作。

 

LIB的相关文档链接:

DPOS Batch PBFT 设计文档中文: 相关链接 基于PBFT提升EOS共识速度的算法.md

DPOS Batch PBFT 设计文档英文: 相关链接

测试网benchmark : 相关链接

升级提案: 相关链接

 

Meetup介绍


2019年4月6日,我们在泰国曼谷举办首次BOS社区见面会,诚邀您的参加!

 

此次见面会将区块链生态系统合作伙伴,开发人员和社区成员聚集在一起,促进最新技术创新的健康交流。 同时为每个人创造了更好的机会,让大家更多地去了解BOS生态规模和平台,EOSIO生态系统,DApps,BOS开发者激励模型以及BOS IBC和Batch-PBFT共识机制等信息。

 


精彩评论

木槿七七
03/15
不错