上一篇写了分布式一致性协议相关理论与算法,那些算法不可用于区块链系统之中,不可防止做恶状况,只能容忍节点宕机、网络分区等状况。web
这节,咱们一块儿看看区块链中经常使用的共识算法。先来看看为何分布式网络须要共识?算法
如图,白军军队实力强大,且居于要地,蓝军被白军隔开成为了两个军队,只有两个蓝军达成一致(具体几点几分开始进攻白军),方可打败白军。但蓝军一、蓝军2要想达成一致,必须使用信使穿过白军领地进行互相通讯,才能同时进攻取胜。但因为白军可能抓捕信使,致使两方蓝军没法达成共识状况。因此两军问题表达的是,信道不可信(消息丢失,超时等),若是存在可信信道,则两军问题可解。安全
两军通讯,就像TCP的三次握手,须要双方发送而且获得反馈才能确认彼此以收到正确消息达到共识。markdown
拜占庭将军问题是一个共识问题: 首先是由**莱斯利·兰伯特(Leslie Lamport)**及其余两人于1982年提出,被称为Byzantine Failure。核心描述是军中可能有叛徒,却要保证进攻一致。与分布式系统类比,节点中有做恶节点,也可能被黑客攻击。网络
图是丑了一点,你们将就了[捂脸哭]。分布式
拜占庭帝国想要进攻一个强大的城市,为此派出了10支军队去包围这个敌人。这个敌人虽不比拜占庭帝国,但也足以抵御5支常规拜占庭军队的同时袭击。基于一些缘由,这10支军队不能集合在一块儿单点突破,必须在分开的包围状态下同时攻击。他们任一支军队单独进攻都毫无胜算,除非有至少6支军队同时袭击才能攻下敌国。他们分散在敌国的四周,依靠通讯兵相互通讯来协商进攻意向及进攻时间。困扰这些将军的问题是,他们不肯定他们中是否有叛徒,叛徒可能擅自变动进攻意向或者进攻时间。在这种状态下,拜占庭将军们可否找到一种分布式的协议来让他们可以远程协商,从而赢取战斗?这就是著名的拜占庭将军问题。ide
应该明确的是,拜占庭将军问题中并不去考虑通讯兵是否会被截获或没法传达信息等问题,即消息传递的信道是可信安全的。Lamport已经证实了在消息可能丢失的不可靠信道上试图经过消息传递的方式达到一致性是不可能的。如下已假定信道是安全可靠的oop
这个问题说究竟是一个关于一致性和正确性的算法问题,这个算法是针对的是忠诚的将军,由于叛徒能够不传,或者乱传消息捣乱。咱们就是要在有叛徒的干扰下,找到一个容忍干扰的算法——BFT(Byzantine fault tolerance)拜占庭容错。post
能够看出,两军问题是拜占庭将军问题的特例。区块链
什么能够称为拜占庭错误?
做恶节点,或者被黑客攻击的节点。节点宕机、网络分区、超时等都不是拜占庭错误。
拜占庭将军问题中:每个将军都须要与全部将军进行通讯,已得知其余将军的进攻安排,从而达到共识。因此拜占庭将军问题可简化为司令——副官模型。一个司令,多个副官,须要一致性协议保证,司令发出的命令,多个副官能够获得一致的结果。
一个司令把本身的命令传递给n-1个副官,使得:
一致性:全部忠诚的副官遵照一个命令(结果集中的大多数 n/2+1)。
正确性:若司令是忠诚的,每个忠诚的副官遵照他发出的命令。(若将军是做恶的,则只须要遵照第一条)
f为拜占庭错误节点数,也是BFT能够容忍的叛徒数量。
反证法,若是n<3f+1 即当f= 1时,n = 3。
因此得出n<3f+1时没法达到拜占庭容错,须要n>=3f+1。具体推导可看参考里的论文,或者李永乐老师的视频。
BFT假设信道没有问题,也就是不考虑消息不可达、消息丢失、乱序、重复、网络分区等状况。Miguel Castro (卡斯特罗)和 Barbara Liskov (利斯科夫)在1999年发表的论文《 Practical Byzantine Fault Tolerance 》中首次提出 pbft 算法,该算法容错数量也知足 3f+1<=n。
pbft 算法的基本流程主要有如下四步:
客户端发送请求给主节点
主节点广播请求给其它节点,节点执行 pbft 算法的三阶段共识流程。
节点处理完三阶段流程后,返回消息给客户端。
客户端收到来自 f+1 个节点的相同消息后,表明共识已经正确完成。
图片来于源论文截图,此图中主节点是忠诚的,编号3节点是拜占庭节点(叛徒)。
PBFT是三阶段提交协议。
完成后响应客户端。客户端收到f+1个消息后便可肯定操做共识结束。
为何客户端只须要f+1个消息呢?
假设若是没有收到f个消息,但没法判断那f个节点就是拜占庭节点,因此可能最坏的状况下,收到的消息中有f个是拜占庭节点的发出的,那要保持容错性,就须要忠诚的节点数量大于拜占庭节点数量(多数派),即f+1个忠诚节点。因此客户端只须要收到f+1个相同消息,就能够判定已经共识成功了。
这也是PBFT容错只能f个,n>=f+f+(f+1) = 3f + 1。
PBFT还有一个View的概念,使用View进行主节点切换。当副本节点与主节点间的心跳超时, 就会发起视图变动,进行主节点切换。每次视图变动,view=view+1。
主节点 = view % n 。 能够看出,PBFT使用轮询当选主节点。咱们看prepare阶段,若是主节点是做恶节点,这个阶段是没法收到2f个prepare消息的,由于主节点会像集群中发送多个不一样的消息,此时你们收到的不一致,就判断主节点有问题,就会进行视图变动,重选主节点。
POW(proof-of-work) 使用计算一个合法的随机数,来增长做恶节点的成本。由于你想做恶,就须要计算合法nonce,若是想要更改某个区块的信息,就须要从那个区块开始,从新计算全部后置区块的合法nonce,成本巨大且不可能实现。因此比特币依靠POW安全运行快十年之久。想要了解POW的能够看一看我以前的文章:比特币入门
POS:股权证实。大白话就是:持有的币量越多,持有的越久(币龄:好比你持有100个币,持有一天,就是100币龄),能够挖矿的几率越大,得到的币就会越多。好比Dash币,拥有1000Dash,就能够成为master,成为master就有机会去挖矿。POS会让富有的人越富有,但币龄到达某一个值时,会重置为0。这样就能够更换新的人来进行挖矿,避免贫富差距过大。
DPOS:委托权益证实。一般被理解的DPOS在于Delegated(委托),将本身的权益委托给超级节点,选出超级节点代为出块,本身根据委托权益的比例得到利息。有兴趣的能够看看Bitshares、Steem、EOS、Asch等项目。
我从0到1参与过两条公链开发,咱们选用的也是DPOS思想,都是自研的DPOS算法。我理解的DPOS是,经过某种规则选出见证者节点(也能够理解为超级节点),这些节点只负责在矿工打包出区块后对区块进行共识,验证等。而矿工则能够经过其余方式选取,选取方式就能够多种多样,能够采用积分、能够采用信用分(发送的交易数、持有的币量、部署的合约数量、对全网的贡献等),只要可以保证全网使用相同的数据,计算出来的结果是惟一的,可验证追溯的,那就没有问题。
见证者节点之间的共识就颇有意思,基本思想离不开BFT,由于要防止做恶节点。你有什么好的想法,能够互相讨论。
本文从两军问题,到拜占庭将军问题,以及如何解决拜占庭将军问题,引出了BFT,PBFT。最后泛谈了区块链中常见的共识算法,共识算法主要理解思想,我的认为不应被某种算法禁锢,可根据实际状况进行思惟扩展,可能就会创造出更优雅的共识算法。
重要:文中有错误之处,敬请各位大佬指出。也欢迎对区块链有兴趣的小伙伴进行讨论交流。
参考连接:
美团技术团队:共识算法系列之一:raft和pbft算法