一、前言
本文是一篇针对的是区块链的共识机制的序言,也可以说是“杂烩”。之后,还会详细地针对共识机制描述的博文。
提及共识机制,我们不得不说到中本聪的在《Bitcoin: A peer-to-peer electronic cash system》文章中涉及的工作量证明(POW)。这种共识机制在去中心化的思想下解决了节点间相互信任的问题,使得区块链能在众多的节点上达到一种较为平衡的状态。区块链解决了在不可信信道上传输可信信息、价值转移的问题,而共识机制解决了区块链如何在分布式场景下达成一致性的问题,奠定了比特币系统的安全性。说到分布式一致性问题,其实由来已久。因为传统分布式系统的一致性算法是一个从上世纪70年代就开始研究的经典问题。Fischer, Lynch 和 Patterson在1985年发表《Impossibilityof Distributed Consensuswith One Faulty Process》,论文中提出了可以说是最重要的分布式系统定理:FLP不可能性;2000年,EricBrewer教授在PODC的研讨会上提出了一个猜想:一致性、可用性和分区容错性三者无法在分布式系统中被同时满足,并且最多只能满足其中两个;2002年,Lynch与其他人证明了Brewer猜想,从而把CAP上升为一个定理。这期间和之后,都涌现了一些很有名的分布式一致性算法,如LeslieLamport在1989年提出的Paxos;1999年Castro和Liskov提出的PBFT,这是第一个得到广泛应用的BFT算法,IBM的Hyperledge fabric就是基于PBFT共识机制的。
所以现在的不少共识机制的都是修改自那些分布式领域的大拿的成果。
二、FLP不可能性
FLPImpossibility(FLP不可能性)是分布式领域中一个非常著名的结果,该结果在专业领域被称为“定理”,其地位之高可见一斑。FLP给出了一个令人吃惊的结论:在异步通信场景,即使只有一个进程失败,也没有任何算法能保证非失败进程达到一致性!
因为同步通信中的一致性被证明是可以达到的,因此在之前一直有人尝试各种算法解决以异步环境的一致性问题,有个FLP的结果,这样的尝试终于有了答案。
三、CAP理论
在理论计算机科学中,CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer's theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下三点:
1. 一致性(Consistency):同一个数据在集群中的所有节点,同一时刻是否都是同样的值。
2. 可用性(Availability):集群中一部分节点故障后,集群整体是否还能处理客户端的更新请求。
3. 分区容忍性(Partition tolerance):是否允许数据的分区,分区的意思是指是否允许集群中的节点之间无法通信。
四、拜占庭将军问题
4.1什么是拜占庭将军问题
拜占庭将军问题是一个共识问题: 首先由Leslie Lamport与另外两人在1982年提出,被称为The Byzantine Generals Problem或者Byzantine Failure。核心描述是军中可能有叛徒,却要保证进攻一致,由此引申到计算领域,发展成了一种容错理论。
关于拜占庭将军问题,一个简易的非正式描述如下:
拜占庭帝国想要进攻一个强大的敌人,为此派出了10支军队去包围这个敌人。这个敌人虽不比拜占庭帝国,但也足以抵御5支常规拜占庭军队的同时袭击。基于一些原因,这10支军队不能集合在一起单点突破,必须在分开的包围状态下同时攻击。他们任一支军队单独进攻都毫无胜算,除非有至少6支军队同时袭击才能攻下敌国。他们分散在敌国的四周,依靠通信兵相互通信来协商进攻意向及进攻时间。困扰这些将军的问题是,他们不确定他们中是否有叛徒,叛徒可能擅自变更进攻意向或者进攻时间。在这种状态下,拜占庭将军们能否找到一种分布式的协议来让他们能够远程协商,从而赢取战斗?这就是著名的拜占庭将军问题。
应该明确的是,拜占庭将军问题中并不去考虑通信兵是否会被截获或无法传达信息等问题,即消息传递的信道绝无问。Lamport已经证明了在消息可能丢失的不可靠信道上试图通过消息传递的方式达到一致性是不可能的。所以,在研究拜占庭将军问题的时候,我们已经假定了信道是没有问题的,并在这个前提下,去做一致性和容错性相关研究。
4.2拜占庭问题的实质
根据上面非正式的描述,一群将军想要实现某一个目标(一致进攻或者一致撤退),但是单独行动行不通,必须合作,达成共识;由于叛徒的存在,将军们不知道应该如何达到一致。而这里“一致性”才是拜占庭将军问题探讨的内容。
但是,光靠“一致”就可以解决问题吗?考虑一下,如果万事俱备,客观上每个忠诚的将军只要进攻了就一定能够胜利,但是却因为叛徒的存在他们都“一致的”没有进攻;反之,条件不利,将军们不应该进攻,但是却因为叛徒的存在所有人都“一致的”进攻了。
可以发现,只有“一致性”是不足以解决拜占庭将军问题的,我们还需要提出一个“正确性”要求。这个要求是值得斟酌的,因为如果客观来看或许会有“绝对正确的”判断,但是针对每一个将军,大家的判断或许都不相同,我们如何定义“正确”呢?我们或许可以简单地说,正确就是每个忠诚的将军都正确的表达了自己的意思,不会因为叛徒让别的将军认为忠诚的将军是叛徒而不采用他传达的消息。
至此,我们将拜占庭将军问题简化成了,所有忠诚的将军都能够让别的将军接收到自己的真实意图,并最终一致行动;而形式化的要求就是,“一致性”与“正确性”。
如果将问题推广开来,可以发现针对一致性和正确性的算法并不要求命令必须是“进攻/撤退”或是“1/0”,而可以是“发送消息1/发送消息2/待机”或“x/y/z/w”,这意味着拜占庭将军问题算法可以为多种分布式系统提供启发,比如电力系统或网络系统。
由此可见,这个问题说到底是一个关于一致性和正确性的算法问题,这个算法是针对的是忠诚的将军,因为叛徒可以做出任何超出约定的判断。我们就是要在有叛徒的干扰下,找到一个抗干扰的算法。要解决这个算法问题,我们需要将形式化要求具体化。
在经典的情形下,口头协议和书面协议这两种方法可以解决此问题。
四、传统分布式一致性算法
4.1 Paxos算法
1998年Lamport提出Paxos算法,后续又增添多个改进版本的Paxos形成Paxos协议家族,且Paxos都有共同点是不容易工程实现。Paxos被用于分布式系统中典型的例子就是Zookeeper,他是第一个被证明的共识算法,其原理基于两阶段提交并扩展。
Paxos算法中将节点分为三种类型:proposer:提出一个提案,等待大家批准为结案。往往是客户端担任该角色acceptor:负责对提案进行投票。往往是服务端担任该角色learner:被告知结案结果,并与之统一,不参与投票过程。可能为客户端或服务端基本过程包括 proposer 提出提案,先争取大多数 acceptor 的支持,超过一半支持时,则发送结案结果给所有人进行确认。一个潜在的问题是 proposer 在此过程中出现故障,可以通过超时机制来解决。极为凑巧的情况下,每次新的一轮提案的 proposer 都恰好故障,系统则永远无法达成一致(概率很小)。Paxos 能保证在超过50%的正常节点存在时,系统能达成共识。
4.2PBFT算法
1999年Castro和Liskov提出的PBFT算法,它是第一个得到广泛应用的BFT算法。这是一种基于消息传递的一致性算法,算法经过三个阶段达成一致性,这些阶段可能因为失败而重复进行。
假设节点总数为3f+1,f为拜占庭错误节点:
1. 当节点发现leader作恶时,通过算法选举其他的replica为leader。
2. leader通过pre-prepare (第一个协议阶段)消息把它选择的 value广播给其他replica节点,其他的replica节点如果接受则发送 prepare(第二个协议阶段),如果失败则不发送。
3. 一旦2f个节点接受prepare消息,则节点发送commit(第三个协议阶段)消息。
4. 当2f+1个节点接受commit消息后,代表该value值被确定 如下图表示了4个节点,0为leader,同时节点3为fault节点,该节点不响应和发出任何消息。最终节点状态达到commited时,表示该轮共识成功达成。 注:预准备阶段(pre-prepare):主节点分配一个序列号n给收到的请求,然后向所有备份节点群发预准备消息,预准备消息的格式为<<PRE-PREPARE,v,n,d>,m>,这里v是视图编号,m是客户端发送的请求消息,d是请求消息m的摘要。准备阶段(prepare): 如果备份节点i接受了预准备消息<<PRE-PREPARE,v,n,d>,m>,则进入准备阶段。在准备阶段的同时,该节点向所有副本节点发送准备消息<PREPARE,v,n,d,i>,并且将预准备消息和准备消息写入自己的消息日志。如果看预准备消息不顺眼,就什么都不做。确认阶段(commit): 当(m,v,n,i)条件为真的时候,副本i将<COMMIT,v,n,D(m),i>向其他副本节点广播,于是就进入了确认阶段。
五、常见区块链共识模型
5.1POW
依赖机器进行数学运算来获取记账权,资源消耗相比其他共识机制高、可监管性弱,同时每次达成共识需要全网共同参与运算,性能效率比较低,容错性方面允许全网50%节点出错。
5.2POS
Proofof Stake由Quantum Mechanic 2011年在bitcointalk首先提出。
存在一个持币人的集合,他们把手中的代币放入POS机制中,这样他们就变成验证者。假设在区块链最前面一个区块(区块链中最新的块),这时POS算法在这些验证者中随机选取一个(选择验证者的权重依据他们投入的代币多少,比如一个投入押金为10000代币的验证者被选择的概率是一个投入1000代币验证者的10倍),给他们权利产生下一个区块。如果在一定时间内,这个验证者没有产生一个区块,则选出第二个验证者来代替来产生新区块。与POW一样,以最长的链为准。
5.3DPOS
与PoS的主要区别在于节点选举若干代理人,由代理人验证和记账。其合规监管、性能、资源消耗和容错性与PoS相似。类似于董事会投票,持币者投出一定数量的节点,代理他们进行验证和记账。
DPoS的工作原理为:去中心化表示每个股东按其持股比例拥有影响力,51%股东投票的结果将是不可逆且有约束力的。其挑战是通过及时而高效的方法达到51%批准。为达到这个目标,每个股东可以将其投票权授予一名代表。获票数最多的前100位代表按既定时间表轮流产生区块。每名代表分配到一个时间段来生产区块。所有的代表将收到等同于一个平均水平的区块所含交易费的10%作为报酬。如果一个平均水平的区块含有100股作为交易费,一名代表将获得1股作为报酬。
5.4Casper(投注共识)
这是一种以太坊下一代的共识机制,属于PoS。Casper的共识是按块达成的而不是像PoS那样按链达成的。
为了防止验证人在不同的世界中提供不同的投注,还有一个简单严格的条款:如果你有两次投注序号一样,或者说你提交了一个无法让Casper合约处理的投注,你将失去所有保证金。从这一点我们可以看出,Casper与传统的PoS不同的是Casper有惩罚机制,这样非法节点通过恶意攻击网络不仅得不到交易费,而且还面临着保证金被没收的风险。
Casper协议下的验证人需要完成出块和投注两个活动。具体如下:
1. 出块是一个独立于其它所有事件而发生的过程:验证人收集交易,当轮到他们的出块时间时,他们就制造一个区块,签名,然后发送到网络上。投注的过程更为复杂一些。目前Casper默认的验证人策略被设计为模仿传统的拜占庭容错共识:观察其他的验证人如何投注,取33%处的值,向0或者1进一步移动。
2. 而客户端的确认当前状态的过程如下所示:
一开始先下载所有的区块和投注,然后用上面的算法来形成自己的意见,但是不公布意见。它只要简单的按顺序在每个高度进行观察,如果一个块的概率高于0.5就处理它,否则就跳过它。在处理所有的区块之后得到的状态就可以显示为区块链的“当前状态”。客户端还可以给出对于“最终确定”的主观看法:当高度k之前的每个块,意见要么高于99.999%或者低于0.001%,那么客户端就可以认为前k个块已经最终确定。
六、总结
POW不足:目前bitcoin已经吸引全球大部分的算力,其它再用Pow共识机制的区块链应用很难获得相同的算力来保障自身的安全;挖矿造成大量的资源浪费;共识达成的周期较长。
POS不足:还是需要挖矿,本质上没有解决商业应用的痛点;所有的确认都只是一个概率上的表达,而不是一个确定性的事情,理论上有可能存在其他攻击影响。
DPOS不足:整个共识机制还是依赖于代币,很多商业应用是不需要代币存在的。