在区块链上实现PBFT实用拜占庭容错共识

FileStorm和MOAC共同打造的基于PBFT共识算法的联盟链经过一个多月的测试,马上就要开始为区块链应用服务了。这里我写一篇博客来详细介绍PBFT。PBFT,practical Byzantine Fault Tolerance,即实用拜占庭容错算法,是由Miguel Castro和Barbara Liskov在1999年提出来的,可以在作恶节点少于总节点的三分之一的情况下,保证所有节点能达成共识。与原始的BFT算法相比,算法复杂度从指数级降低到了多项式级,从而使得BFT算法的实际应用成为可能。原论文可以在这里看到。http://pmg.csail.mit.edu/papers/osdi99.pdf。

PBFT可以用在很多场景下,这里我主要介绍PBFT在区块链上的应用。

三阶段协议

首先我们来看一下PBFT的三阶段协议,这是PBFT的核心,参见下图:

image.png

从发起请求到收到最终结果,中间的共识过程一共需要经过3个阶段,怎样从区块链的角度来理解呢?

首先,0,1,2,3都是区块链上的验证节点。C在原论文里是定义为客户端,共识的需求由C来提出。区块链没有客户端,但是它有共识的需求。所以,C在这里就可以理解成区块链本身。

所以,先由C发出请求(request),请求发给0。我们可以理解成区块链选定0做为出块节点。然后进入三阶段协议。

pre-prepare阶段:0 被选为出块节点后,就生成新区块并对全网广播,通知1,2,3节点接收新区块。节点3打了一个叉,可以理解成节点3掉线了。
prepare:1,2,3节点收到这个区块后,需要告知所有其他节点它已经收到区块了。所以,这里会有 n^2 条信息发出。3因为掉线了,所以它没有发消息。
commit:只要收到全网超过2/3的节点告知已收到同一个区块,就可以认为这是大家需要共同验证的下一个区块。于是所有节点在这个阶段对区块进行验证,验证成功就把确认结果发给所有其他节点。

三阶段结束后,所有人再将最终结果提交给客户(reply),也就是区块链。只要有超过2/3的人同意将新区块加到链上,区块就会被加上去。

这就是对这张图的解释。这里可能会有几个问题:

问:为什么需要经历 prepare 和 commit 两个阶段的节点广播呢?
答:在一个公共区块链网络中,每一个节点都有可能做恶,在pre-prepare阶段,可能会有做恶节点也发一个新区块,或者还会因为网络延迟同时产生多个新区块,所以要先确定大家都是收到的同一个区块,然后在下一个阶段对这个区块进行验证。

问:PBFT共识怎么决定哪个节点出块?
答:其实PBFT共识并没有决定由谁来出块。在三阶段图中,0节点被选定做为本轮出块节点,但是在所有节点提交的结果(reply)中,必须通过某种规则同时决定下一个出块节点,这个节点还可以是0,也可以是1,或者2。

问:决定出块节点的规则有哪些?
答:很多采用PBFT的公链会采用随机的方式决定下一个出块节点,但是一个绝对完美的真实随机数的产生函数VRF(verifiable random function)暂时还很难实现。如果是采用了POS,或者DPOS的共识,因为节点有质押,可以把质押数量也加入到节点选择的规则中去,而且节点如果做恶会受到惩罚。在一个可信环境,如联盟链上,我们则可以选择 round-robin 轮流出块的方式来决定出块节点。如果有节点下线,如图中节点3,我们可以选择轮空。

PBFT的优缺点

PBFT的优势是确认时间相对固定,共识效率高,这对多种商业行为很友好。

PBFT区块链的运转可以脱离币的存在,不需要为出块节点设计激励机制。支持共识算法的各节点由业务的参与方或者监管方组成,安全性与稳定性由业务相关方保证。

但是PBFT机制要求是一个封闭的集群,出块节点两两需要进行通信,通信量是O(n^2)。如果节点数超过100,信息量会变得非常大,所以不适合大型全球性的公有链,因为公链既不符合封闭性的原则,也无法支撑这种巨大的通信量。

另外,PBFT共识要求做恶节点和失效节点数量不超过(n-1)/3。对做恶节点也没有任何惩罚机制。

因此,PBFT非常适合一个出块节点不超过100的联盟链的环境。(但是同步节点可以支持10万个以上,足够支撑联盟内部基于链的各种业务。)

共识的优化

2019年Facebook推出的Libra项目让人眼睛一亮。它偏偏要在全球性的范围内搭建一个高效的联盟链来实现全球支付功能。而它选择的共识,就是基于BFT的LibraBFT。LibraBFT又是基于HotstuffBFT。我会写一篇文章专门解释这两个共识。这两个共识跟PBFT相比最主要的改进,就是把通信量从O(n^2)降低到了O(n),这样,可以支持的节点就可以突破PBFT的局限性。完全可以支持一个全球性的大型公链。

FileStorm现在也在跟MOAC一起开发属于自己的新的共识,叫MBFT,或者MoacBFT。这个共识对PBFT有如下改进:

  1. 使用聚合签名,用类似HotStuff的方式把系统的通信量从O(n^2)降低到了O(n)。
  2. 引入可验证随机函数VRF,随机产生出块的Leader。
  3. 结合POS机制,通过质押让出块节点不做恶,提高链的安全性。

希望MoacBFT未来可以成为被其他公链认可和采用的经典共识。

区块链存储

最后介绍一下FileStorm和MOAC共同打造的PBFT联盟链的现有的一个核心技术,那就是区块链存储。众所周知,区块链的区块空间很小,每笔交易的数据量不能太大。可是很多区块链应用如溯源,存证平台,有很多非文本的大型数据需要存储。这是一个刚需。FileStorm通过区块链激励层链接全球分散的存储资源形成一个规模浩荡的分布式存储池。任何区块链都可以将数据直接存入FileStorm平台。但是对很多基于联盟链的应用,现阶段都有将数据存入内部网络的需求。所以在我们的PBFT联盟链上,可以部署专门的FileStorm节点,搭建联盟存储池,对大型数据进行存储。下图是PBFT联盟链节点的一个基本配置图。

Screen Shot 2020-02-08 at 12.13.19 PM.png

文件存在FileStorm中,哈希数据上链。数据确权,不可篡改,而且源文件可寻址,易于查找和呈现。再加上支持智能合约,可发行包括ERC20和ERC721,支持无币也可有原生代币,未来必将成为区块链应用的首选。

————————————————
最后,给资深码农们更多关于PBFT数据结构的介绍。这里引用CSDN博主「TurkeyCock」的原创文章和图片说明。并对原作者表示感谢。原文链接:https://blog.csdn.net/TurkeyCock/article/details/81672759

数据结构

说完PBFT的共识原理,接下来我们来介绍一下相关的数据结构。主要是状态和消息。通过对数据结构和状态改变的实现,可以将PBFT用在区块链上。

状态(State)

image.png

节点的状态主要包含三部分:

  • 世界状态(即最新区块信息)
  • 消息日志(所有跟其他节点的通信)
  • 当前界面(三阶段的界面)

三阶段协议

image.png

这里列出了三阶段协议中每个阶段发出的消息结构。几个重要参数介绍如下:
view id:界面ID
seq number:消息计数,便于统计收到的消息总数。
block:区块
replica index: 节点ID
signature:签名

状态改变

image.png

状态改变(VIEW-CHANGE)的消息包含的内容比较多:
首先需要基于一个稳定的检查点(CHECKPOINT),因此需要包含2f+1个CHECKPOINT消息以证明该checkpoint是有效的。
然后,在该checkpoint之上的所有sequence number,都需要打包对应的PRE-PREPARE消息以及2f个PREPARE消息。

新状态

image.png

新状态(NEW-VIEW)消息首先需要包含2f+1个状态改变(VIEW-CHANGE)消息,以证明确实有超过2/3的节点同意在更高的view上进行新一轮共识。
然后,根据收到的所有VIEW-CHANGE消息中的checkpoint信息,找出最小值min_s和最大值max_s,打包该区间内的每一个sequence number对应的PRE-PREPARE消息。
特别的,为了减少重复验证,如果在某个sequence number上从未进行过view change(即第一轮就达成了共识),则PRE-PREPARE中包含一个特殊的null请求的摘要信息。

具体逻辑参见下图:

image.png

你可能感兴趣的:(在区块链上实现PBFT实用拜占庭容错共识)