区块链原理、架构与应用
上QQ阅读APP看书,第一时间看更新

2.3 区块链共识机制

前面说过,可以将区块链看作网络中每个节点都拥有的一个巨大账本。在缺乏第三方监管机构的情况下,当网络中的大部分人都拥有书写账本的权利时,区块链该如何保持账本内容的一致性和内容不被恶意篡改呢?共识机制就是区块链中节点就区块信息达成全网一致共识的机制,保证最新的区块信息被准确添加至区块链、节点存储的区块链信息一致并能够抵御恶意攻击。共识机制是区块链这个分布式账本能够实现的灵魂所在。

随着区块链技术的不断发展,不同的共识机制不断涌现,现有的一部分共识机制和代表应用介绍如表2-2所示。需要特殊说明的是,IOTA采用的共识机制有向无环图(drected acyclic graph)改变了区块的链式存储结构,实现了无区块的概念。

表2-2 部分共识机制和应用举例

2.3.1 实用拜占庭容错算法

对于分布式系统首先需要解决的问题就是一致性的达成。一致性问题的定义是对于系统中的多个服务器节点,在给定一系列操作的情况下,在一致性协议的保障下,服务器节点对它们的处理结果相同,当然这里并不强制处理结果的正确性,所有节点都达成失败状态也是一种一致性的表现。

而在实际的计算机系统中达成一致性需要面临的挑战有很多,包括节点之间的网络通信并不是永久可靠的,可能有任意时延和内容故障;节点的处理结果错误,甚至节点自身都有可能随时宕机;以及同步调用使得系统不具备可扩展性。拜占庭问题与算法讨论的场景是:有少数节点作恶场景下系统的一致性达成问题。

1. 拜占庭将军问题

拜占庭将军问题(Byzantine failures problem)是由莱斯利·兰伯特(Leslie.Lamport)和其他两人针对点对点通信在1982年提出的一个基本问题。

问题描述为:在古代东罗马的首都,由于地域宽广,守卫边境的多个将军(系统中的多个节点)需要通过信使来传递消息,达成某些一致的决定。但由于将军中可能存在叛徒(系统中节点出错),这些叛徒将努力向不同的将军发送不同的消息,试图干扰一致性的达成。拜占庭问题即为在此情况下,如何让忠诚的将军们能达成行动的一致。

例如,10个将军共同去攻打一座城堡,只有一半以上也就是至少要6个将军一起进攻,才可能攻破。但是,这中间有可能存在未知叛徒,有可能造成真正进攻的军队数量少于或等于5,致使进攻失败而遭受灭亡。那么如何相互通信,才能确保有6个将军的进攻命令,从而使军队一致进攻而成功,或者确保少于6个将军的进攻命令,从而使军队一致不进攻避免被灭掉?也就是说,要么一半以上同意一起进攻而决定进攻,要么不到一半同意一起进攻而决定不进攻,但要避免说进攻但命令却是不进攻,使那些进攻军队数少于或等于一半,造成进攻者的被灭。这种情况并不考虑进攻的命令是否准确有效,单纯就各位将军的命令在何种情况下能够确保一致。

拜占庭将军问题可以简化为,所有忠诚的将军能够相互间知晓对方的真实意图,并最终做出一致行动。而形式化的要求就是一致性和正确性。兰伯特对拜占庭将军问题的研究结论是,如果叛徒的数量大于或等于1/3,拜占庭问题不可解;如果叛徒个数小于将军总数的1/3,在通信信道可靠的情况下,通过口头协议,可以构造满足一致性和正确性的解决方法,将军们能够做出正确决定。

口头协议指的是将军们通过口头消息传递达到一致。隐藏条件是:每则消息都能够被正确传递;信息接收方确定信息的发送方;缺少的信息部分已知。

如果一个节点的信息同时传递给其他两个节点,这两个节点接收到消息后也分别传达给其他节点,这样每个节点都是信息的接收方和传递方,直到每个节点最后都有所有节点发送的信息。在此过程中若出现叛徒或虚假消息导致信息不匹配,所有节点按照少数服从多数的原则,行动便能够达成一致。缺点是如果出现信息不一致的情况,因为对于信息的传送方未知,所以无法判断叛徒。

为了解决无法追溯根源的问题,方案二是采用签名信息。将军们利用不可伪造的签名技术表达自己的意见,其他人可以验证签名的有效性,如果签名被除本人外的第三方篡改很容易被发现。但是这种方案需要解决如何实现真正可靠的签名体系的问题。如果依赖第三方存储签名数据,那么这个网络本身就不再是前提中所假设的节点间互不信任的分布式结构,其次是签名造假的问题也无法避免,同时存在异步协商带来的漫长的传输时间并不适合实际使用。

2. 拜占庭容错(BFT)

拜占庭将军问题是对现实中可能遇到问题的模型化,在分布式计算机领域中,由于硬件错误、网络堵塞或中断以及遭遇恶意攻击等原因,网络可能出现各种不可预测的异常行为。不同出错类型对于系统造成的危害程度也不同。影响最小的出错类型是“出错-停止(failstop)”。此种类型的节点在出错之后,就会立即停止工作,这样,系统中的其他节点也会知道该节点出错了。但是拜占庭错误节点在出错后会继续工作,做出任意行为,就像拜占庭将军问题中的叛徒一样,做出不响应、发出错误消息、复制多份信息、向不同节点发出不同的决策信息、与其他拜占庭节点合谋等扰乱行为,而系统中的节点无法自发识别拜占庭错误节点。被攻击者控制、向系统发出攻击的节点就是典型的拜占庭错误节点。如果一个系统中存在少量的拜占庭错误节点,仍能达成共识,那么系统就是拜占庭容错的。

在兰伯特提出拜占庭将军问题时,就提出了一种在同步环境中解决问题的拜占庭容错算法;1988年,也有学者提出了一种在大多数异步环境中工作的算法,但是对于实际应用的指导意义都不大。直到1999年由Miguel Castro(卡斯特罗)和Barbara Liskov(利斯科夫)提出了PBFT(实用拜占庭容错算法)。解决了原始拜占庭容错算法效率不高的问题,将算法由指数降低到多项式级,使得拜占庭容错算法在实际系统中应用可行,但除了在专业领域以外并没有引起足够的重视。而2009年中本聪创建的比特币,作为第一个开放式去中心化应用程序,对区块链网络的记账问题和拜占庭将军问题是类似的。每次参与记账的节点就好比一位将军,某些节点可能因为某些原因传递错误消息给其他节点,做出“背叛”行为。而对于不需要货币体系的联盟链或者私有链来说,传统共识算法比PoW和PoS更符合要求,传统共识算法能够提供绝对可信任的节点,满足高效的需求。

传统共识算法中较为典型的有Paxos、Raft算法,其中Paxos问题是指分布式系统中存在故障节点场景下的一致性问题,并不存在恶意节点;而Raft算法是Paxos算法的一种简化实现。在一些互联网的数据库产品的防火墙内都使用了该类算法,使得有故障的机器出现时服务正常可用。

而在区块链系统中,存在攻击者,也有潜在可能存在拜占庭容错节点。攻击者可以延迟网络中的通信、协调拜占庭错误节点发起攻击、阻断部分节点与其他节点的联系。所以使用实用拜占庭容错算法的更适合。

PBFT算法中各个节点由业务的参与方或监管方组成,安全性与稳定性由业务相关方保证,共识时延能够达到商用实时处理的需求,共识效率高,能够满足高频交易量的需求,因此被一些区块链应用选作共识算法,在超级账本(Hyperledger)Fabric的0.6版中就使用了经典的PBFT共识算法。

3. 实用拜占庭容错算法(PBFT)

拜占庭将军问题的核心是,如何使得将军们需要收到正确的命令并做出正确的反应。而PBFT的解决思路是,每个节点都对周围节点进行信息正确性的确认,用通信次数换取信用,每条命令的执行都需要两两验证去检验消息。利用状态机副本复制的方法,假设系统中共有3f+1个复制节点,其中最多f个节点为拜占庭错误节点,系统中每个节点都运行一个有限状态机的副本,同时支持若干种操作,该算法在保证活性与安全性(liveness&safety)的前提下提供了(n-1)/3的容错性。

客户端会给各个复制节点(replicas)发送一系列请求来执行相应操作,需要保证所有节点执行相同顺序的操作。因为所有复制节点的初始状态是相同的,对于相同请求的响应也是相同的,根据状态机原理,这些复制节点应该产生相同的结果状态。但是状态机原理的问题在于如何确保正常工作的复制节点能够以相同的序列执行相同的操作,尤其是在面对拜占庭故障的时候。

R是所有复制节点的组合,用[0,|R|-1]的证书表示每一个复制节点。假设|R|=3f+1,f为可能失效复制节点的最大个数。所有复制节点在视图(view)的轮换过程中运作,视图是一个连续编号的整数,不同视图的意义类似于不同的时间段。在每个视图中使用不同的主节点(primary),其余复制节点均为备份节点(backups)。主节点编号由公式p=vmod|R|得到,其中v是视图编号,p是节点的编号。

主节点负责接收客户端的请求,并将请求排好序,按序组播给备份节点(全部复制节点构成的一个组,组播指的就是发送消息给组成员)。但是主节点可能会出错,它可能会给不同的请求编上相同的号码,或不分配编号,或将相邻的序号编上不连续的号码。备份节点需要主动检查号码的合法性,当出现异常情况的时候,启发视图更换(view change)过程重新选择主节点。

一次共识过程包括请求(request)、预准备(pre-prepare)、准备(prepare)、确认(commit)和回复(reply)。其中,请求和回复过程为客户端发起请求并收到最终答复,预准备、准备和确认过程为PBFT算法的主线,预准备和准备阶段用来确保时序性,即同一个视图中的请求的正确序列;而准备和确认过程为确保到达确认阶段的请求即使在视图转换后在新的视图中仍然保持原有顺序不变,也就是不同视图之间的确认请求的严格排序。比如说在视图V0中,三个请求Req0、Req1、Req2依次进入了确认阶段。如果节点不存在问题,那么节点需要依次执行三条请求并返回给客户端,但是如果主节点出现异常,那么视图更换过程启动,视图从V0更替为V1。在新的视图里,原本的Req0、Req1、Req2三个请求的序列被保留,但是处于预准备和准备阶段的请求在新的视图中并不会进行保留。

复制节点的状态中会保留服务的整体状态,接收的信息会被保存在消息日志中,并且有一个整数表示当前所处的视图编号,而在和客户端的交互中,复制节点向客户端发送的信息便包含当前的视图编号,以便客户端能够跟踪当前的视图编号,从而推算出当前的主节点。

客户端会给它认为的主节点发送请求,内容为<Request,o,t,c>,其中,o为operation,表示期待状态机执行的操作;t为timestamp时间戳,用来保证客户端的请求只会执行一次,因为客户端发出请求的时间戳是全序排列的,后续发出的请求的时间戳会高于之前发出的请求。主节点接收请求后会自动将请求进行组播。

当主节点接收到客户端的请求后,会给请求进行编号,然后主节点组播一条预准备消息给所有备份节点。预准备消息的格式是<<pre-prepare,v,n,d>,m>,其中,v为视图编号,n为主节点给请求的编号,m为客户端发送的请求消息,d是请求消息的摘要。请求本身不在预准备信息中,这样能够使得预准备消息足够小。发送预准备消息的目的是为了确定该请求在视图v中被赋予了编号,使得即使在视图变更过程中序列仍是可追溯的。另外,将请求排序协议和请求传输协议进行解耦,有利于传输速率的优化。

备份节点并不是无条件接收主节点发送的所有预准备消息,需要满足以下条件:请求和预准备消息的签名正确,d和消息m的摘要一致;视图编号与当前视图相符;节点从未接收过同一视图和同一序列编号的不同摘要的预准备信息;消息的序号必须在水线的上下限h和H之前,水线的意义在于防止一个失效节点故意用一个很大的序号消耗序号空间。

如果消息通过验证,那么备份节点接收预准备信息,同时进入准备阶段。在准备阶段,备份节点组播准备信息<prepare,v,n,d,i>,并将预准备消息和准备消息都写入消息日志中。在这个阶段,该备份节点还会分别收到其他备份节点的准备消息,该备份节点会综合所有准备消息做出自己对该消息的最终裁决,以防主节点为拜占庭错误节点。每个节点验证预准备和准备信息的一致性主要检查:视图编号、消息序号和摘要。如果无误,那么就称请求在该节点的状态是prepared,该节点就拥有了一个prepared certificate。

预准备阶段和准备阶段确保所有正常节点对同一个视图中的请求序号达成一致。接下去是对这个结论的形式化证明:如果prepared(m,v,n,i)为真,则prepared(m',v,n,j)必不成立,这就意味着至少f+1个正常节点在视图v的预准备或者准备阶段发送了序号为n的消息m。因为系统中至多存在f个故障节点,所以此时消息必为真。

当条件为真时,节点i将<commit,v,n,D(m),i>向其他节点广播,广播信息代表节点i已经拥有一个prepared certificate,同时节点i也会收到其他节点发送的commit信息,如果它收到了2f+1条带有相同视图编号、序列编号和摘要的确认信息(包括节点自身所有的一条信息),那么就说该节点拥有了comminted certificate,请求在这个节点达到了committed状态。

每个复制节点i在committed-local(m,v,n,i)为真之后执行m的请求,并且i的状态反映了所有编号小于n的请求依次顺序执行。这就确保了所有正常节点以同样的顺序执行所有请求,这样就保证了算法的正确性。在完成请求的操作之后,每个副本节点都向客户端发送回复。副本节点会把时间戳比已回复时间戳更小的请求丢弃,以保证请求只会被执行一次。

上述过程可简要描述如下,假设C为请求客户端,0、1、2、3为副本节点,其中0是主节点,3是失效节点,如图2-7所示。

(1)请求(request):客户端向主节点发送请求调用服务。

(2)预准备(pre-prepare):主节点0收到客户端的请求后将其组播给其他副本,即0->123。

(3)准备(prepare):复制节点1、2、3收到请求后记录,并再次组播给其他复制节点,即1->023、2->013,复制节点3因为宕机失效无法进行组播。

图2-7 PBFT算法示意图

(4)确认(commit):0、1、2、3节点在prepare阶段,若收到超过一个数量的相同请求,则进入commit阶段,组播commit请求,即0->123、1->023、2->013。

(5)回复(reply):0、1、2、3节点在commit阶段,若收到超过一定数量的相同请求,则对客户端进行反馈。客户端需要等待f+1个不同复制节点发回相同的结果,作为整个操作的最终节点。

根据上述操作流程,当节点数n>3f+1时,系统的一致性能够得到解决。以刚才的系统为例,如表2-3所示,拜占庭容错能够容纳将近1/3的错误节点误差。

表2-3 不同数目错误节点可能情况列举

2.3.2 工作量证明

区块链网络作为一种分布式网络,需要解决拜占庭将军问题,达成工程上的相对一致。在比特币区块链中,通过工作量证明机制解决了这个互不信任的分布式网络如何在各方利益都能得到确保的情况下达成一致共识的难题。

工作量证明(PoW)是一种对应服务与资源滥用或是阻断服务攻击的经济对策。一般是要求用户进行一些耗时适当的复杂运算,并且答案能被服务方快速验算,以此耗用的时间、设备与能源作为担保成本,以确保服务与资源是被真正的需求所使用。此概念最早由Cynthia Dwork和Moni Naor于1993年的学术论文提出,而工作量证明一词则是在1999年由Markus Jakobsson与Ari Juels所发表。现在常说工作量证明机制指的是应用于区块链技术中的一种主流共识机制。

工作量证明常用的技术原理是散列函数。在比特币挖矿过程中使用的是SHA-256哈希函数,无论输入值的大小,SHA-256函数的输出的长度总是256位。算法的规则是,节点通过解决密码学难题(即工作量证明)竞争获得唯一记账权;平均10分钟内(具体时间会和密码学问题的难度相互影响)只能有一个人可以记账成功,其他节点验证通过后复制这一记账结果。

矿工首先根据存储的交易池中的交易构造一个候选区块,计算区块头信息的哈希值,观察是否小于当前的目标值。如果小于目标值,那么在没有其他节点广播信息的时候,矿工成功争夺记账权;如果哈希值不小于目标值,那么矿工就会修改nonce值,然后再试一次。

具体目标值越小,找到小于其的哈希值就会越难。拿掷骰子举例,两个骰子的和小于12的概率远大于两个骰子的和小于5,相同的,哈希值前有多少位规定为0,随着0位数的增加,难度越大。如果考虑的是256位空间。每次要求多一个0,那么哈希查找的空间缩减了一半。

矿工成功挖矿就代表得到了新区块的工作量证明解,就会迅速在网络中进行广播,其他节点在接收并验证后也会继续传播新区块,每个节点都会把它当作新区块添加到自身节点的区块链副本中。当挖矿节点收到并验证了这个新区块后,便会放弃之前对构建这个相同高度区块的计算,并立即开始计算区块链中下一个区块的工作。

在比特币网络中,实现所有节点的去中心化共识机制,不单单需要工作量证明,还有其他三个独立的过程相互作用产生:每个全节点依据综合标准对每个交易进行独立验证;通过完成工作量证明算法的验算,挖矿节点将交易记录独立打包进新区块;每个节点独立地对新区块进行校验并组装进区块链;每个节点对区块链进行独立选择,在工作量证明机制下选择累计工作量最大的区块链。

其中解决区块链的分叉问题遵循了累计工作量最大的链条为网络主链的原则。当有两名矿工几乎在同一时间算得新区块的工作量证明解,在分别对各自区块进行传播的过程中,就会出现两个版本不同的区块链。解决方法就是,总有一方能够抢先发现工作量证明解并传播出去,所有节点会接收更长的链,这样网络就会重新达成共识。

2.3.3 权益证明

工作量证明算法的优势明显,但为了维持其正常运转却需要大量的资源投入,尤其是电力资源和购置矿机的成本消耗。Digiconomist调查显示,仅仅比特币,矿工就要使用54太千瓦时的电力。这些电量足够支持美国500万个家庭用电,甚至整个新西兰或匈牙利的电力,但是实际耗电不仅止于此。权益证明机制试图找到一个更为绿色环保的分布式共识机制。

2011年,QuantumMechanic在Bitcointalk论坛首次提出了权益证明,权益证明(PoS)是一类应用于公共区块链的共识算法,不同于工作量证明中新区块的挖掘完全取决于节点进行哈希碰撞的算力,在权益证明中,新区块的创建是通过随机、财富或币龄的各种组合来进行选择的,取决于节点在网络中的经济效益。它所蕴含的概念是:区块链应该由具有经济利益的人进行保障。系统通过选举随机选择节点验证下一个区块,但要成为验证者,节点需要在网络中事先存入一定数量的货币作为权益,类似于保证金机制。权益证明的运作方式是,当创造一个新区块的时候,节点需要创建一个coinstake交易,交易会按照一定比例将一些币发送给节点本身。根据节点拥有币的比例和时间,按照算法对难度目标进行调整,从而加快了节点找到符合难度目标随机数的速度,极大地降低了系统达成共识所需要的时间。

权益证明并不单纯考虑账户余额,因为如果将账户余额定义为下一个有效区块的挖掘方式,那么单个最富有的节点将具有永久优势,势必会导致网络的集中化。在不同的数字加密货币中,已经设计了几种不同选择方法的权益证明体系,本节将主要讲述点点币(Peercoin)和黑币(Blackcoin)采用的权益证明机制。

1. PoS1.0——点点币(Peercoin)

点点币是从中本聪创造的比特币衍生而来的数字货币,首次实现了PoS,由化名为Sunny King的网友于2012年提出并发布。但点点币的共识机制是并不纯粹的权益证明,而是采用了基于PoW和PoS的混合机制,前期采用工作量证明机制进行挖矿开采和分配货币,后期采用权益证明机制,保证网络安全,因此从长远来看,点点币更节能而且具有成本优势。

点点币中采用的PoS是基于币龄(coinage)的,同样涉及与比特币类似的散列运算,但是不像比特币无范围地盲目搜索,点点币中的搜索空间被加以限制。Sunny King在《点点币:一种点对点的权益证明电子密码货币》(PPCoinPeer-to-Peer Crypto-Currency with Proof-of-Stake)中对其进行了详细的说明。

1)币龄

币龄的概念缘于中本聪的设计,被简单定义为货币的持有时间,例如Alice收到了10个币,并且持有10天,那Alice就有了10×10=100币天(coinday)的币龄,当Alice花费了这10个币,那么认为这10个币上的积累的币龄被消耗。但在比特币中,币龄只用来给交易排序,并没有起到很重要的作用。点点币中加入了交易时间戳的概念,简化了系统对于币天的运算。

2)coinstake

coinstake依据比特币中的coinbase交易命名,是Sunny King为实现PoS专门设计的一种特殊交易类型,如图2-8所示。类似于比特币中coinbase必须是区块中的第一笔交易,点点币中规定,如果一个区块为PoS区块,那么它的第二笔交易必须是coinstake,同时如果一个区块的第二笔交易为coinstake,那么它是PoS区块。coinstake的第一个输入不能为空,即kernel(核心)字段永恒存在,合格区块的判定只与kernel的币龄有关。输出的output0必须置零,output1输出给区块持有人指定的收益地址,包括输入的本金和利息(stakeReward)。利息的计算公式为

可简化为

式中,coin_number代表拥有币的数量。

图2-8 coinstake示意图

这样,点点币便通过coinstake交易定义了除过PoW以外的一种新型的铸币方式。PoS将根据coinstake交易中所消耗的币龄产生利息,0.01代表每一个币一年将产生1分的利息。这就使得点点币有一个与通货紧缩的比特币完全不同的特征,点点币没有固定的数量,点点币也是第一种引入无限量代币供应的数字货币。

3)权益证明

权益证明通过选举的方式,选择节点进行下一个区块的验证,将这样的节点称为验证者(validator),新区块不再是矿工挖掘产生的,而是通过铸造(mint/forge)生成。要成为验证者,节点需要在网络中存入一定数量的货币作为权益,类似于保证金机制。

PPC中加入了币龄的考量。在coinstake交易中,区块持有人可以消耗他的币龄获得利息,同时获得为网络产生一个区块和用PoS铸币的优先权。coinstake的第一个输入kernel需要满足某一哈希的目标协议,这使得区块的产生具有了随机性,具体公式为

proofhash<CoinDayWeight×Target

CoinDayWeight=coin_number×days,days∈[30,90]

proofhash=hash(nStakeModifier+txPrev.block.nTime+txPrev.offset+txPrev.nTime+txPrev.voutn+nTime)

proofhash对应一组数据的哈希值,CoinDayWeight即币龄,用户持有的货币数量乘以持有该笔货币的时间,天数存在取值区间,用户只有将该笔货币储存在钱包中至少30天才能够参与创建新区块,最大值为90天。从公式能明显看出,随着持币天数的增加,能够搜索的目标空间就会增大。Target为目标值,用于衡量PoS机制下铸造新区块的难度,具体计算公式为

block_interval为前两个区块的时间间隔,由公式可见,两个区块的目标时间间隔是10分钟。目标与难度成反比,难度越高,目标值越小,铸造难度越大。如果前两个区块的时间间隔大于10分钟,目标值会提高,当前区块的难度会降低;与此相反,如果前两个区块的时间间隔小于10分钟,目标值会降低,当前难度就会提高。与比特币中难度目标约两周调整一次不同,点点币中目标值持续调整,主要目的是避免铸造新区块的突然波动。

proofhash由一些固定字段通过哈希运算得到。nStakeModifier是专门为PoS设计的调节器,每个区块对应一个nStakeModifier值,但并不是每个区块的值都会进行变化,协议规定每隔一段时间必须重新计算一次,取值与前一个nStakeModifier和最新区块哈希值有关。如果没有nStakeModifier字段,当用户收到一笔币后,能够提前计算得知自己在未来什么时间段构造区块,这并不符合Sunny King的初衷,系统需要用户进行哈希值的盲目探索,以确保区块链网络的安全性。txPrev为kernel对应的与一笔交易;txPrev.block.nTime为上一笔交易所在区块的时间戳;txPrev.offset是上一笔交易在区块中的偏移量;txPrev.nTime为上一笔交易的构造时间,也就是上一笔交易的时间戳;txPrev.voutn为kernel在txPrev的输出下标,也就是kernel是txPrev的第几个输出。

而判断主链的标准转变为对区块累计消耗币龄的判断,每个区块的交易都会将消耗的币龄提交给该区块,获得最高消耗币龄的区块将被选为主链。

2. PoS2.0——黑币(Blackcoin)

点点币采用的基于币龄的PoS机制存在一些潜在的安全问题,例如一些节点会积攒币龄,平时保持离线状态,只有在积累了一定的币龄之后才重新上线获取利息,网络中不够数量的节点保持活跃状态就会影响网络中安全性能。另外,币龄可能会被恶意节点滥用以获得更高的网络权重以实现双花。

黑币(Blackcoin,BLK)诞生于2014年2月24日,作者是Paul Vasin。在黑币的白皮书《黑币POS协议2.0》(BlackCoin's Proof-of-Stake Protocol v2)中,他阐述了现有PoS协议的不足,除了上述的币龄的问题,还包括权益证明的组件是可以充分预测的,节点能够对将来的权益证明进行提前计算。在黑币中提出了PoS2.0机制,对之前权益证明的不足之处进行了修改完善。

黑币中PoS证明的计算公式为

proofhash<coin_number×Target

安全的PoS系统需要保证可能多的节点保持在线状态,越多的节点进行在线的权益累积,系统遭遇攻击的可能性就越低,同时交易得到确认的速度也就越快。因此在新的等式中去掉币龄,使得积攒币龄的方法在新系统中无法使用,进行权益累计就需要节点尽可能保持在线状态。proofhash的具体表达式为

proofhash=hash(nStakeModifier+txPrev.block.nTime+txPrev.nTime+

txPrev.vout.hash+txPrev.voutn+nTime)

为了降低节点进行预算计算的可能性,nStakeModifier权重修正因子在每次修正因子间歇时都会进行改变,以便对将要用来进行下一个权益证明的时间戳的计算结果进行更好的模糊处理。

同时,黑币对区块的时间戳也进行了适当的改变,使得在PoS机制下能进行更有效的工作,理想预计区块的生成时间为64s。每生成一个区块,不包括验证交易产生的交易费,系统给予验证者的奖励为1.5BLK,可大致估算出每年生成的区块奖励为×24×365×1.5=739 125BLK。根据黑币官网介绍,截至目前,739 125是黑币总供应量的0.972%。这0.972%仅分配给参与网络权益证明的用户,奖励率高于1%。

黑币是首创快速挖矿+低股息的发行模式,发行前7天采用Scrypt算法挖矿,第8天开始进入纯粹PoS阶段,是历史上第一个使用PoW创建周期然后过渡到完整的PoS的数字货币。随着时间的推移,黑币的核心协议已经进入了PoS3.0阶段,PoS3.0主要对交易中多重签名的部分进行了补充。

3. PoS机制存在的问题

区块链应用的最核心问题是如何在去中心化的环境中达成共识,比特币最核心的突破是在没有中心组织的情况下,让全网对交易的有效性达成了一致。比特币通过引入外部算力资源来确保共识的安全性,也就是工作量证明,另外通过每个新区块产生一定量的比特币激励网络参与者,这也几乎是所有采用工作量证明的系统采用的方法。但是这种激励必须保证足够的吸引力,才能吸引足够的参与者持续参与新区块的挖掘,以维持网络的运行,一旦激励的吸引力下降,网络的安全性就会很容易被破坏。同时引入外部资源也使得网络暗含着被外部资源攻击的危险,只要有足够的资金那么就能够买到足以破坏现有共识的设备和算力。

正是因为比特币存在的这些问题,出现了权益证明。权益证明放弃通过外部资源而选择通过网络用户币种的权益维持网络的稳定,此时用户的权益就类似工作量证明中的算力。但因为没有引入外部资源,采用权益证明的系统不需要消耗大量能源,也不用担心外部的算力攻击。

但是PoS系统出现了新的问题——内部的Nothing-at-Stake(无利害关系,N@S)攻击。在早期的基于区块链的权益证明算法中,只为创造区块提供激励,没有惩罚措施,这就造成了当网络出现分叉,多条链相互竞争的情况下,对于币种的持有者,最佳策略就是在每条链上都创造区块,以确保自己能获得最终奖励,如图2-9所示。

这样,无论哪条链最终胜出,币种持有者的利益都不会有任何损失。这就导致一旦出现分叉,只要系统中有一定量“贪心”的验证者,即使没有外部攻击,全网也不会达成共识。工作量证明机制中则不需要考虑这种攻击存在,因为矿工获得激励的可能性会随着算力分配的区块数目增加而降低,有损于矿工自身利益,如图2-10所示。

第二个问题是重写历史攻击。从理论上来说,攻击者可以通过购买原始持有币种的账户从头发起攻击,重新分叉一个区块链。因为持有原始币种的账户可以将货币转移到任意账户而不受惩罚,因此存在重写历史攻击的可能性。

图2-9 N@S攻击示意图

图2-10 工作量证明机制下攻击情况示意图

前面说过,想要维持一个区块链网络的稳定性,必须要有足够的激励机制吸引参与者尽可能多地参与新区块的挖掘或者铸造。但是一般的PoS系统是没有新币产生的,矿工只能赚交易费,如果交易费不高,那么对于矿工的激励就十分有限。因此有些PoS系统中,通过持续产生新币,也就是coinstake交易产生的利息,来激励验证者,但这就会导致通货膨胀。假设利息为1%,那么就是每年1%的通货膨胀率,通货膨胀率会使得小户、散户的货币贬值,只有大户才能对货币进行保值,最终会导致中心化的现象出现。

为了解决上述问题,改进的PoS机制加入了十分严苛的惩罚制度来保障系统的安全。验证者将权益通过保证金的形式存入,一旦对系统有恶意攻击,得到的惩罚比奖励要大得多,攻击得不偿失,但是对于如何判定恶意攻击依然是一个备受争议的问题。所以在这种情况下,很多应用选择了PoW+PoS的模式,依据PoS机制通过降低PoW出块的难度从而缩短了共识达成的时间,就连ETH也将采用这种模式,根据2018年1月2日Ethereum Team发布的第四季度总结,基于PoS的项目Casper测试网络也已经发布了。

2.3.4 委任权益证明

委任权益证明(DPoS)由区块链工程师丹尼尔·拉尔默(Daniel Larmer)提出,首先在比特股(Bitshares)上实现,之后的斯蒂姆币(Steem)、柚子(EOS)等数字货币或应用上都使用了DPoS机制。

简单来说,持币者投票选出一定数量的节点,代替他们进行区块验证的记账。用户通过一个特别的加密货币社区,投票选择网络的代表。投票的影响是根据持有的货币数量来决定的,货币持有量越大,那么投票的影响力也就越大。这些代表需要负责区块的产生,同时系统会给予他们一定收益。一旦被选择出来的代表没有履行应尽的职责,社区可以进行投票将其资格取消。有固定收益的激励机制存在,有大量用户愿意成为票选出的代表。类似于一个公司,公司中的员工都持有该公司数额不等的股份。每隔一段时间,员工可以把自己手中的票投向自己最认可的N个人来领导公司进行决策,每个员工的投票权和他手里持有的股份数等比例,投票结束后,得票最多的N个人成为公司的领导。如果领导做了不利于公司发展的事情,那么员工可以取消领导的资格,从而退出管理层。DPoS通过一定程度的中心化,实现了秒级的共识验证速度,同时规避了纯粹PoS机制可能导致的攻击问题。

DPoS中投票选择出来的代表根据任务不同,可分为两类:证人(witnesses)和受托人(delegates),在比特股的白皮书中进行了仔细的解释。

委托人的权利是提议更改网络参数,包括交易费用、区块大小、证人的奖励金额大小、区块间隔时间等所有内容,这些参数通过创世账户进行记录更新,一旦大多数代表批准了拟定的变更后,货币持有人即利益相关者拥有两周的审核期,在此期间他们可以将提案的代表罢免并使变更提案无效。此设计是为了确保委托人在技术上没有直接权力,所有对网络参数的更改最终都是得到利益相关方批准的。根据DPoS,真正实现了权力掌握在利益相关方手中。值得注意的是,委托人并不是有偿职位。

证人的作用类似于现实社会中的公证人,公证人有时需要证明合同是在特定的时间由特定的人签署的,证人需要验证区块中的交易及签名的有效性。证人每产出一个区块,系统会给予他们固定数目的奖励,奖励数额的大小由委托人决定。如果证人没有按照规定产生新的区块,他们不会获得报酬,同时还会被票决出代表集体。证人的名单并不是固定的,系统会按照设定好的时间间隔进行名单的更新。同时,所有利益相关者都可以观察证人的参与率来监督网络的健康状况,在任何时间一旦证人的参与率低于某个基准,用户可以为交易的确认预留出更长的时间,同时对网络的安全性保持警惕。此属性使得比特股能够在不到1min内提醒用户潜在问题。

图2-11 区块产生示意图

假设每个区块的生成时间为3s,那么正常情况下,块生产者需要每3s轮流生成区块,一旦错过自己的轮次,这个时间段不再有区块产生,由规定的名单序列中的下一个证人生产新区块。块生产者在被调度轮次之外的任何时间段产出的块都是无效的,如图2-11所示。

在《DPoS Consensus Algorithm-The Missing White Paper(DPoS——缺失的白皮书)》中,将可能对共识产生威胁的情况做以列举说明。

如果不超过1/3的节点故障或者恶意分叉,如图2-12所示,依照每3s进行一次区块产生者轮换,在这种情况下,少数节点只能每9s产生一个区块,而多数节点可以产生两个区块。这样,诚实的多数节点将永远比少数节点产生的链条更长,网络不会产生分叉。如果少数节点试图在离线状态下进行无限量的分叉实验,也不会对网络的共识产生影响。因为少数人在出块速度上注定比多数节点的慢,他们产生的分叉也永远比多数人的链条短。

图2-12 少数节点分叉情况

如果多数节点出现故障或进行恶意分叉,在他们所属的生产区块的时间段可以产生无限数量的分叉,如图2-13所示。每个分叉都有2/3以上的算力在创建区块以延长分叉,最后在不可逆区块时按照最长链法则进行主链的选择,最长链就是为大多数节点批准承认的链条,这种情况下由少部分诚实节点决定。同时绝大多数节点进行恶意分叉或者故障的情况并不会维持很长时间,因为利益相关方很快会将这些代表节点票决替换。

图2-13 多数节点恶意分叉情况

网络有可能出现碎片化的情况,导致没有任何一条分叉拥有占据网络多数区块生产者,如图2-14所示。假设可能存在三条分叉,其中两条的长度相同,因为投票选择的证人总数永远为奇数,但第三个生产者产生较小的分叉加入网络中后,平局会被打破。网络最长链会倒向最大的那个少数群体。当网络的连通性恢复时,较小的少数群体会切换到最长链,网络共识重新恢复。

图2-14 网络碎片化情况

实际在网络中并不会出现这种情况,因为即使区块生产者的数目相同,分叉也不会以相同的步长增加,因为每轮生产过后,都会经历生产者的洗牌,重新安排出块顺序。这种随机性确保顺序相近的生产者不会总是相互忽略,在拥有相同生产者进行分叉的情况下,平局也总是会被打破的。

图2-15 最后不可逆区块

在网络出现碎片化的情况下,多个分叉有可能会增长一段相当长的时间,虽然最终最长链会获得胜利,但是观察者需要一种更确切的手段判断一个区块是否属于增长最快的那条链。这可以通过观察来自2/3+1多数块生产者进行判定。如图2-15所示,区块A已经被B和C确认,这代表了网络中2/3+1的多数确认,在全部节点诚实的情况下,可以判定没有其他链会比该链更长,将区块B称为不可逆区块。

设想一种比较极端的情况,网络中的大多数生产者不履行职责,只有少数代表坚持继续出块。在DPoS机制下,利益相关方可以在这些被少数区块坚持生产的区块中发起更改投票的交易,这些投票可以选择一批新的生产者,将参与出块的比率恢复到100%。这样,该条链最终会超过其他以低于100%参与率运行的分叉链。很明显的是,一条参与率低于67%的链最终的网络状态是不确定的,共识最终会在一个不同的分叉上建立起来。选择在此条件下交易的用户冒的风险与在比特币网络中选择接受不到6个区块确认的人是相似的。

在能够设想的自然网络分叉的情况下,DPoS都是强健的,甚至于在面对大量生产者作弊的场景也是安全的。同时不像其他共识机制,在大多数生产者不合格的情况中,DPoS机制也是可以继续运行的。DPoS机制在高强度和多变化的失败条件下仍然保持极高的强健性,在共识算法中后来居上,吸引了越来越多开发者的注意。

2.3.5 其他共识算法

随着区块链技术的不断发展以及各种数字货币的涌现,新的共识机制也不断地被创造出来。下面介绍两种比较热点的共识机制。

1. 瑞波共识机制(RPCA)

瑞波共识机制(Ripple protocol consensus algorithm,RPCA)使得节点通过基于特殊信任节点达成共识。在Ripple网络中,交易由客户端发起,经过追踪节点(tracking node)或验证节点(validating node)对交易进行广播,追踪节点能够分发交易信息并响应客户端需求,验证节点除了包括追踪节点的功能外,还要对需确认的交易达成共识,也就是说,Ripple网络的共识只发生在验证节点中。

每个验证节点都会维护一份可信任节点列表,称为UNL(unique node list),系统默认信任列表中的节点不会联合作弊。在共识过程中,交易需要接收UNL中节点的投票,投票超过一定阈值后便达成共识。具体共识过程大致如下。

(1)验证节点接收待验证的交易,结合本地账本数据内容,对交易内容进行验证,不合格交易会被直接丢弃,合法交易将汇总为交易候选集,候选集中还包括之前无法被确认而遗留的交易。

(2)活跃的验证节点将自己的交易候选集作为提案发送给其他验证节点,需要注意的是,参与共识机制的节点必须处于活跃状态,验证节点和活跃节点之间存在报活机制。

(3)验证节点检查收到的提案是否来自UNL中的可信任节点。如果不是,该提案可以被忽略。如果是可信任节点,对提案内容进行本地存储。

(4)验证节点对比可信任节点的提案内容和本地候选集,寻找交集,如果有相同的交易,那么该交易获得一票。如果UNL中可信任节点数目为M,本轮交易认可的阈值为N(百分比,如50%),则每一个超过M×N个信任节点认可的交易将被该验证节点认可;验证节点需要在系统设置的本轮交易验证计数时间之内,将所有被认可的交易生成可交易列表。

(5)验证节点持续接收来自可信任节点的提案内容,并更新可交易列表,如果账本中每笔交易都获得满足条件阈值的信任节点列表的认可,则共识达成,交易验证结束。

共识遵循可信任节点的认可,就类似俱乐部会员中的核心会员,外部人员对于共识没有影响力,对比其他共识机制,RPCA更中心化。Stellar恒星币的共识机制(Stellar consensus protocol,SCP)便是在RPCA的基础上演化形成的。

2. 授权拜占庭容错算法(dBFT)

授权拜占庭容错算法(delegated Byzantine fault tolerance,dBFT)是根据权益选出记账人,然后记账人之间通过拜占庭容错算法来达成共识。该算法由小蚁(NEO)团队提出,对比PBFT,白皮书中进行的改进包括:

(1)将C/S架构的请求响应模式改进为适合P2P网络的对等节点模式。

(2)将静态的共识参与节点改进为可动态进入、退出的动态共识参与节点。

(3)为共识参与节点的产生设计了一套基于持有权益比例的投票机制,通过投票决定共识参与节点(记账节点)。

(4)在区块链中引入数字证书,解决了投票中对记账节点真实身份的认证问题。

机制将网络的参与者分为两类:专业记账的记账节点和普通用户。普通用户基于持有权益的比例进行投票选择记账节点,当需要通过一项共识时,在记账节点中选定一个发言人进行方案的拟定,其他记账节点根据拜占庭容错算法进行表态,如果超过指定比例的节点同意该方案,则方案达成,否则重新选择发言人进行方案的拟定。

这种方法的优点是有专业化的记账人;能够容忍任何类型的错误;记账由多人协同完成;每个区块都有最终性,不会分叉;算法的可靠性有严格的数学证明。但在白皮书中也坦言了现有算法的缺陷:当有1/3或以上记账人停止工作后,系统将无法提供服务;当有1/3或以上记账人联合作恶,且其他所有的记账人被恰好分割为两个网络孤岛时,恶意记账人可以使系统出现分叉,但是会留下密码学证据。综上来说,dBFT机制最核心的一点,就是最大限度地确保系统的最终性,使区块链能够适用于真正的金融应用场景。

这符合NEO团队的定位,用户可以将实体世界的资产和权益进行数字化,通过点对点网络进行登记发行、转让交易、清算交割等金融业务的去中心化网络协议。目标市场不仅是数字货币圈,还包括主流互联网金融。小蚁可以被用于股权众筹、P2P网贷、数字资产管理、智能合约等。