[eos14]协议-共识协议-part1
https://developers.eos.io/welcome/latest/protocol/consensus_protocol
最近几天通读了一遍eos协议章节,包括共识协议、交易协议、网络协议和账号&权限等内容,对整体机制有基本理解。
这部分内容是eosio的核心,值得花时间学习钻研,目前很多细节不清楚,现在开始对其内容重读,并对相关内容展开学习,希望通过不断挖掘,能够提升自己的认知,同时也能提升写作和表达能力。
1 概述
EOSIO是一个以去中心化方式运行的、高效的区块链项目。每个块会连接到前一个块。每个块中包括若干交易。可以参考eospark.com。修改一个块中的交易是很困难的。因此,可以认为区块链中的交易是不能被篡改且安全的。
1.1 块生产者
在EOSIO系统中,有一类特殊的节点,叫块生产者,Block Producer(BP),类似比特币网络中的矿工。顾名思义,BP负责块的生产和校验。BP被EOS Token(通证)持有者选举出来的。是不是类似发达国家的选举制度。目前有21个BP,这样通过削弱去中心化的程度,极大提升了交易效率和吞吐量。每一个BP运行一个nodeos服务的实例。因此,当前正处于生产区块过程中的BP,也被称为”活跃“或者”生产中“节点。
1.2 共识的需求
所谓共识,是指分布式系统的中的节点如何对当前状态达成一致。特别是在区块链的去中心化系统中,各个节点在彼此不信任的情况下,通过某种共识机制达成一致。
2 共识模型
多数共识模型是通过对某种事物的证明达成一致的。PoW(Proof of Work 工作量证明)和PoS(Proof of Stake,权益证明)是两种最流行的共识模型。
2.1 工作量证明
比特币就是工作量证明机制。通过算一道题,这道题没啥捷径,就看谁算的块,从1开始数,谁数的块谁就可以获得奖励。其最大优点就是安全性,因为足够去中心化,想要攻击这样的网络需要耗费大量的资源;但同时,这恰恰也是它的缺点,即整个网络的挖矿行为导致大量计算资源的耗费。
2.2 权益证明
顾名思义,谁的权益(股权)多,谁的决策权就大,谁就能出块,DPos(代理权益证明)是Pos的一个变体,用户可以选择自己的代理人,由代理人帮你投票做决策。
3 EOSIO的共识机制
eosio使用两种共识机制:
Layer1 - aBFT(asynchronous byzantine fault tolerant )
Layer2 - DPos(Delegate Proof of Stake)
其中,DPos通过投票选举出谁有权利作为区块生产者,21个生产者生产一轮区块后,重新按照选举出来的BP循环往复;aBFT关注的是BP产出的区块如何达到不可逆状态。即两种共识机制关注的层次和业务不一样,功能相对独立运行。Layer1需要依赖Layer2,即上层依赖下层。
3.1 aBFT层
这一层决定在BP中被接收到和同步的区块,最终哪些块会变成不可逆状态,从而被永久的记录在区块链中。
aBFT层通过DPoS层获取到每一轮21个生产者生产区块的顺序(其实就是得票最前的21个BP,按照字母顺序排序),然后使用这个顺序决定这个块是不是被正确的生产者生产出来的。
为了达到拜占庭容错,aBFT使用二阶段块确认机制(a two-stage block confirmation process),这个机制中,2/3的生产者对每个块确认两次。
第一个确认阶段提出LIB(last irreversible block)。第二个确认阶段确认LIB是不可逆状态。注意,第一个阶段只是提议哪个是LIB,还未真正确认其final状态。
每个确认阶段都需要2/3的生产者确认。(Each stage of confirmations is performed by a supermajority of producers from the current scheduled set of active producers.)
3.2 DPoS层
这一层引入了通证、抵押、投票、代理投票、投票衰减、生产者排名等等概念。该层也负责产生块生产者。每个生产者在每一轮次有6秒的生产块时间,每0.5秒产出一个块,即每一个BP在一个轮次生产12个块。每个轮次的持续时间是21*6=126秒,大概2分钟。每个轮次生产块的21个BP可能都一样,这依赖于具体的得票排名。
3.2.1 权益持有者和代理
每一轮次的投票对通证持有者都是开放的。所有EOS通证持有者都可以行使自己的投票权。(从这个意义上讲,是不是EOS更加去中心化呢?如果是PoW机制,没有一定的算力就啥也不是,但是不管你有多少EOS,都可以发挥一定的投票权利。)尽管如此,每个轮次的21个生产者并不会经常性发生变化。EOSIO和其他普通DPoS的一个不同之处就是:21个被选中的BP权利是相等的,跟具体票多票少无关。
3.3 共识过程
从全局角度看,EOSIO的共识过程包括两个方面:
step1:BP选举,被DPoS层执行
step2:块生产和校验,被aBFT层(原生共识)执行
这两个过程是相对独立,可以并行执行。当然特殊情况是,创始区块被创建出后,先step1,再step2。
问题:
1、21个BP的生产顺序应该也是记录在区块链中的,这个顺序本身如何达成共识,是不是也是用aBFT机制?
This layer is also used to signal producer schedule changes, if any, at the beginning of every schedule round.
Changes to this schedule can be initiated by privileged smart contracts running on the EOSIO blockchain, but any initiated changes to the schedule do not take effect until after the block that initiated the schedule change has been finalized by two stages of confirmations.
此处有个难点,到底啥是拜占庭容错,啥是2阶段提交。
扩展:
1、(异步)拜占庭容错
论文:http://pmg.csail.mit.edu/papers/osdi99.pdf
参考:https://www.jianshu.com/p/6420eb1661a0
简单地说,PBFT的作用如下:每个“将军”维持一个内部状态(持续的特定信息或状态),当“将军”接收消息时,它们将消息与其内部状态结合使用,以运行计算或操作。这种计算反过来告诉这个“将军”如何思考有关信息。然后,在达成关于新消息的个人决定之后,这个“将军”再与系统中所有其他“将军”共享该决定,最后根据所有将军提交的全部决定,确定共识决定。
算法的研究结果显示,当“叛变将军”少于将军总数的三分之一时,“忠诚将军”将可以做出正确的决定并达成一致。
下面我们看这个例子,一共三个将军,其中一个是发令将军A、两个是普通将军B和C。当A告诉B攻击而告诉C撤退时,B和C互相发送消息,因为他俩都是忠诚的,都将如实转发A的消息。这样B和C都不能弄清楚到底谁是叛徒----因为不确定A是叛徒、或者是否另一个普通将军可能伪造了据称来自A的信息。可以证明,如果n是将军总数,而t是其中的叛徒数量 ,那么只有当n> 3t并且通信是同步的时候,拜占庭将军问题才能得到解决。
PBFT要求所有节点之间的两两通信,因此这种通信机制要求节点数量不能太多,通常是几十个,在这种模式下,节点达成一致的速度更快,延时更低。
PoW网络的容错性是50%,也就是须防范51%攻击;而PBFT容错性只有三分之一,也就是34%的恶意节点即可发起攻击。
参考:https://www.jianshu.com/p/5fea30b25f0a
果10个将军中的几个同时发起消息,势必会造成系统的混乱,造成各说各的攻击时间方案,行动难以一致。
谁都可以发起进攻的信息,但由谁来发出呢?中本聪巧妙地在个系统加入了发送信息的成本,即:一段时间内只有一个节点可以传播信息。
在拜占庭的系统里,加入工作量证明,其实就是简单粗暴地引入了一个条件:大家都别忙着发起消息,都来做个题,看谁最聪明,谁就有资格第一个发起消息。
参考:https://www.jianshu.com/p/56f60fe349e0
首先,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机制要求是一个封闭的集群,出块节点两两需要进行通信,通信量是O(n^2)。如果节点数超过100,信息量会变得非常大,所以不适合大型全球性的公有链,因为公链既不符合封闭性的原则,也无法支撑这种巨大的通信量。
另外,PBFT共识要求做恶节点和失效节点数量不超过(n-1)/3。对做恶节点也没有任何惩罚机制。
因此,PBFT非常适合一个出块节点不超过100的联盟链的环境。(但是同步节点可以支持10万个以上,足够支撑联盟内部基于链的各种业务。)
2、两阶段提交
参考:https://blog.csdn.net/kangkanglou/article/details/79743655