区块链pow算法仿真实现
1. 区块链怎么校验
POA(ProofofActivity)区块链共识算法POA(ProofofActivity)算法是一个区块链的共识算法,基本原理是结合POW(Proofofwork)和POS(Proofofstake)算法的特点进行工作,POW算法和POS算法的具体内容可以参考:
POW算法:
POS算法:
POA算法相比于其他算法可以改进网络拓扑,维持在线节点比例,需求更少的交易费同时减少共识算法过程中的能量损耗。
POA算法需求的网络中同样包含两类节点,矿工和普通参与者,其中普通参与者不一定一直保持在线。POA算法首先由矿工构造区块头,由块头选出N个币,这N个币的所有者参与后续的校验和生成块的过程。
从这里可以看到POA算法不仅与算力有关,后续的N个参与者的选举则完全由参与者在网络中所拥有的币的总数量决定。拥有越多币的参与者越有机会被选为N个后续的参与者。而后续N个参与者参与的必要条件是这N个参与者必须在线,这也是POA命名的由来,POA算法的维护取决于网络中的活跃节点(Active)。
POA算法的一个理想的基本流程是,类似于POW协议,矿工构造出一个符合难度要求的块头,通过矿工得到的块头计算衍生出N个币的编号,从区块链中追溯可以得到这几个币目前所述的参与者。矿工将这个块头发送给这N个参与者,其中前N-1个参与者对这个块进行校验和签名,最后第N个参与者校验并将交易加入到该块中,将这个区块发布出去,即完成一个区块的出块。
一个理想过程如下图所示:
在实际运行中,无法保证网络上所有参与者都在线,而不在线的参与者则无法进行校验和签名,这个无法被校验和签名的块头则会被废弃。
即在实际运行中,应该是一个矿工构造出块头后广播给各个参与者签名,同时继续重新构造新的块头,以免上一个块头衍生的N个参与者存在有某一个没有在线,而导致块头被废弃。
因此,在这种情况下,一个块是否被确认不仅与矿工的计算能力有关同时也与网络上的在线比例有关。
与纯POW相比,在与比特币(POW)同样10分钟出一个块的情况下,POA由于会有参与者不在线而产生的损耗,因此,10分钟内矿工可以构造的块的数量会更多,即块头的难度限制会降低,那么矿工在挖矿过程中会造成的能量损耗也会降低。
与纯POS相比,可以看到POA的出块流程并不会将构造区块过程中的相关信息上链,可以明显减少区块链上用于维护协议产生的冗余信息的量。
本节对上诉协议中一些参数设置进行分析
在矿工构造出块头后对块头进行校验和区块构造的N个参与者的数量选定比较类似于比特币中每一个块的出块时间的选取。比特币中选择了10分钟作为每一个块的期望出块时间并通过动态调节难度来适应。
这里N的取值同样可以选择选定值或者动态调节。动态调节需要更加复杂的协议内容,同时可能会带来区块链的数据膨胀,而复杂的协议也增加了攻击者攻击的可能性。另外暂时没有办法证明动态调节可以带来什么好处。静态调节在后续的分析(4安全分析)中可以得到N=3的取值是比较合适的。
从上面的描述可以看到,构造新的区块的除了矿工还有从块头中衍生出来的N个币所有者。在构造出一个新的区块后,这些参与者同样应该收到一定的激励,以维持参与者保持在线状态。
矿工与参与者之间的非配比例与参与者的在线状态相关。给予参与者的激励与参与者保持在线状态的热情密切相关,越多参与者保持在线状态,能更好地维持网络的稳定。因此,可以在网络上在线参与者不够多的时候,提高参与者得到的激励分成比例,从而激发更多的参与者上线。
如何确定当前参与者的在线情况呢?可以最后第N个参与者构造区块时,将构造出来但是被废弃的块头加入到区块中,如果被丢弃的块头数量过多,说明在线人数过低,应当调节分成比例。
同时最后第N个参与者与其他参与者的分成同样需要考虑,第N个参与者需要将交易加入区块中,即需要维护UTXO池,同时第N个参与者还需要将被丢弃的块头加入新构建的区块中。
为了激励其将废弃区块头加入新构建的区块中,可以按照加入的区块头,适当增加一点小的激励。虽然加入更多的区块头,可以在下一轮的时候增加分成的比例,应当足够激励参与者往区块中加入未使用的块头了(这里参与者不可能为了增加分成而更多地加入区块头,每一个区块头都意味着一位矿工的工作量)。
一个参与者如果没有维护UTXO池则无法构造区块,但是可以参与前N-1个的签名,因此为了激励参与者维护UTXO池,作为最后一个构造区块的参与者,必须给予更多的激励,比如是其他参与者的两倍。
从3.2的描述中可以知道一个用户必须在线且维护UTXO池才可能尽可能地获得利益。这种机制势必会导致一些用户将自己的账户托管给一个中心化的机构。这个机构一直保持在线,并为用户维护其账户,在被选为构造区块的参与者时参与区块的构建并获取利益。最后该机构将收益按照某种形式进行分成。
上面说到参与者必须用自己的密钥进行签名,而托管给某个机构后,这个机构在可以用这个密钥签名构造区块的同时,也有可能使用这个密钥消费用户的财产。这里可以采用一种有限花销的密钥,这个密钥有两个功能,一个是将账户中的部分财产消费出去,另一个是将所有财产转移到一个指定账户。在托管的时候可以使用这个密钥,在被通知部分财产被花费后可以立即将所有财产转移到自己的另一个账户下,以保证财产的安全。
从上面的分析可以看到,POA的安全性与攻击者所拥有的算力和攻击者所拥有的股权有关。假设攻击者拥有的在线股权占比为,则攻击者的算力需要达到其他所有算力的倍才能达成分叉。假设攻击者股权总占比为,网络中诚实用户的在线比例为,则攻击者的算力需要达到其他所有算力的倍才能达成攻击。
攻击的分析表格如下:
从上文的分析可以看到,POA算法相比于其他算法可以改进网络拓扑,维持在线节点比例,需求更少的交易费同时减少共识算法过程中的能量损耗。同时,PoA协议的攻击成本要高于比特币的纯PoW协议。
参考文献:ProofofActivity:ExtendingBitcoin’sProofofWorkviaProofofStake
利用区块链技术实现不记密码加密存储验证,解决离线安全存储问题本文介绍一种利用区块链技术配合个人存储设备进行网络安全验证的方法
以微嘟为代表的不记密码快捷加密存储设备,已经完美做到了快捷安全存储,但美中不足的是无法通过网络查询设备何时被使用,以及无法预知极端情况下设备被离线破解等。
利用区块链技术可以解决此问题,具体工作原理:
在设备连接PC端,并检测到射频ID验证通过后,接入设备内的特定硬件,此时自动通过安装在PC端的程序向特定的区块链网络上广播设备打开时间的等信息。在得到区块链网络确认后,才授权设备后级存储用户重要数据的存储颗粒接入。因为每次设备打开都需要网络授权及相关的信息都存储在区块链网络上了,所以有效的避免了不明目的的人在用户不知情的情况下偷偷地打开设备。
多了一层区块链的网络验证是不是发现设备的安全性提高了好多?
下面以微嘟链安全验证为示意:
区块链---共识算法
PoW算法是一种防止分布式服务资源被滥用、拒绝服务攻击的机制。它要求节点进行适量消耗时间和资源的复杂运算,并且其运算结果能被其他节点快速验算,以耗用时间、能源做担保,以确保服务与资源被真正的需求所使用。
PoW算法中最基本的技术原理是使用哈希算法。假设求哈希值Hash(r),若原始数据为r(raw),则运算结果为R(Result)。
R=Hash(r)
哈希函数Hash()的特性是,对于任意输入值r,得出结果R,并且无法从R反推回r。当输入的原始数据r变动1比特时,其结果R值完全改变。在比特币的PoW算法中,引入算法难度d和随机值n,得到以下公式:
Rd=Hash(r+n)
该公式要求在填入随机值n的情况下,计算结果Rd的前d字节必须为0。由于哈希函数结果的未知性,每个矿工都要做大量运算之后,才能得出正确结果,而算出结果广播给全网之后,其他节点只需要进行一次哈希运算即可校验。PoW算法就是采用这种方式让计算消耗资源,而校验仅需一次。
?
PoS算法要求节点验证者必须质押一定的资金才有挖矿打包资格,并且区域链系统在选定打包节点时使用随机的方式,当节点质押的资金越多时,其被选定打包区块的概率越大。
POS模式下,每个币每天产生1币龄,比如你持有100个币,总共持有了30天,那么,此时你的币龄就为3000。这个时候,如果你验证了一个POS区块,你的币龄就会被清空为0,同时从区块中获得相对应的数字货币利息。
节点通过PoS算法出块的过程如下:普通的节点要成为出块节点,首先要进行资产的质押,当轮到自己出块时,打包区块,然后向全网广播,其他验证节点将会校验区块的合法性。
?
DPoS算法和PoS算法相似,也采用股份和权益质押。
但不同的是,DPoS算法采用委托质押的方式,类似于用全民选举代表的方式选出N个超级节点记账出块。
选民把自己的选票投给某个节点,如果某个节点当选记账节点,那么该记账节点往往在获取出块奖励后,可以采用任意方式来回报自己的选民。
这N个记账节点将轮流出块,并且节点之间相互监督,如果其作恶,那么会被扣除质押金。
通过信任少量的诚信节点,可以去除区块签名过程中不必要的步骤,提高了交易的速度。
?
拜占庭问题:
拜占庭是古代东罗马帝国的首都,为了防御在每块封地都驻扎一支由单个将军带领的军队,将军之间只能靠信差传递消息。在战争时,所有将军必须达成共识,决定是否共同开战。
但是,在军队内可能有叛徒,这些人将影响将军们达成共识。拜占庭将军问题是指在已知有将军是叛徒的情况下,剩余的将军如何达成一致决策的问题。
BFT:
BFT即拜占庭容错,拜占庭容错技术是一类分布式计算领域的容错技术。拜占庭假设是对现实世界的模型化,由于硬件错误、网络拥塞或中断以及遭到恶意攻击等原因,计算机和网络可能出现不可预料的行为。拜占庭容错技术被设计用来处理这些异常行为,并满足所要解决的问题的规范要求。
拜占庭容错系统:
发生故障的节点被称为拜占庭节点,而正常的节点即为非拜占庭节点。
假设分布式系统拥有n台节点,并假设整个系统拜占庭节点不超过m台(n≥3m+1),拜占庭容错系统需要满足如下两个条件:
另外,拜占庭容错系统需要达成如下两个指标:
PBFT即实用拜占庭容错算法,解决了原始拜占庭容错算法效率不高的问题,算法的时间复杂度是O(n^2),使得在实际系统应用中可以解决拜占庭容错问题
?
PBFT是一种状态机副本复制算法,所有的副本在一个视图(view)轮换的过程中操作,主节点通过视图编号以及节点数集合来确定,即:主节点p=vmod|R|。v:视图编号,|R|节点个数,p:主节点编号。
PBFT算法的共识过程如下:客户端(Client)发起消息请求(request),并广播转发至每一个副本节点(Replica),由其中一个主节点(Leader)发起提案消息pre-prepare,并广播。其他节点获取原始消息,在校验完成后发送prepare消息。每个节点收到2f+1个prepare消息,即认为已经准备完毕,并发送commit消息。当节点收到2f+1个commit消息,客户端收到f+1个相同的reply消息时,说明客户端发起的请求已经达成全网共识。
具体流程如下:
客户端c向主节点p发送REQUEST,o,t,c请求。o:请求的具体操作,t:请求时客户端追加的时间戳,c:客户端标识。REQUEST:包含消息内容m,以及消息摘要d(m)。客户端对请求进行签名。
主节点收到客户端的请求,需要进行以下交验:
a.客户端请求消息签名是否正确。
非法请求丢弃。正确请求,分配一个编号n,编号n主要用于对客户端的请求进行排序。然后广播一条PRE-PREPARE,v,n,d,m消息给其他副本节点。v:视图编号,d客户端消息摘要,m消息内容。PRE-PREPARE,v,n,d进行主节点签名。n是要在某一个范围区间内的[h,H],具体原因参见垃圾回收章节。
副本节点i收到主节点的PRE-PREPARE消息,需要进行以下交验:
a.主节点PRE-PREPARE消息签名是否正确。
b.当前副本节点是否已经收到了一条在同一v下并且编号也是n,但是签名不同的PRE-PREPARE信息。
c.d与m的摘要是否一致。
d.n是否在区间[h,H]内。
非法请求丢弃。正确请求,副本节点i向其他节点包括主节点发送一条PREPARE,v,n,d,i消息,v,n,d,m与上述PRE-PREPARE消息内容相同,i是当前副本节点编号。PREPARE,v,n,d,i进行副本节点i的签名。记录PRE-PREPARE和PREPARE消息到log中,用于ViewChange过程中恢复未完成的请求操作。
主节点和副本节点收到PREPARE消息,需要进行以下交验:
a.副本节点PREPARE消息签名是否正确。
b.当前副本节点是否已经收到了同一视图v下的n。
c.n是否在区间[h,H]内。
d.d是否和当前已收到PRE-PPREPARE中的d相同
非法请求丢弃。如果副本节点i收到了2f+1个验证通过的PREPARE消息,则向其他节点包括主节点发送一条COMMIT,v,n,d,i消息,v,n,d,i与上述PREPARE消息内容相同。COMMIT,v,n,d,i进行副本节点i的签名。记录COMMIT消息到日志中,用于ViewChange过程中恢复未完成的请求操作。记录其他副本节点发送的PREPARE消息到log中。
主节点和副本节点收到COMMIT消息,需要进行以下交验:
a.副本节点COMMIT消息签名是否正确。
b.当前副本节点是否已经收到了同一视图v下的n。
c.d与m的摘要是否一致。
d.n是否在区间[h,H]内。
非法请求丢弃。如果副本节点i收到了2f+1个验证通过的COMMIT消息,说明当前网络中的大部分节点已经达成共识,运行客户端的请求操作o,并返回REPLY,v,t,c,i,r给客户端,r:是请求操作结果,客户端如果收到f+1个相同的REPLY消息,说明客户端发起的请求已经达成全网共识,否则客户端需要判断是否重新发送请求给主节点。记录其他副本节点发送的COMMIT消息到log中。
?
如果主节点作恶,它可能会给不同的请求编上相同的序号,或者不去分配序号,或者让相邻的序号不连续。备份节点应当有职责来主动检查这些序号的合法性。
如果主节点掉线或者作恶不广播客户端的请求,客户端设置超时机制,超时的话,向所有副本节点广播请求消息。副本节点检测出主节点作恶或者下线,发起ViewChange协议。
ViewChange协议:
副本节点向其他节点广播VIEW-CHANGE,v+1,n,C,P,i消息。n是最新的stablecheckpoint的编号,C是2f+1验证过的CheckPoint消息集合,P是当前副本节点未完成的请求的PRE-PREPARE和PREPARE消息集合。
当主节点p=v+1mod|R|收到2f个有效的VIEW-CHANGE消息后,向其他节点广播NEW-VIEW,v+1,V,O消息。V是有效的VIEW-CHANGE消息集合。O是主节点重新发起的未经完成的PRE-PREPARE消息集合。PRE-PREPARE消息集合的选取规则:
副本节点收到主节点的NEW-VIEW消息,验证有效性,有效的话,进入v+1状态,并且开始O中的PRE-PREPARE消息处理流程。
?
在上述算法流程中,为了确保在ViewChange的过程中,能够恢复先前的请求,每一个副本节点都记录一些消息到本地的log中,当执行请求后副本节点需要把之前该请求的记录消息清除掉。
最简单的做法是在Reply消息后,再执行一次当前状态的共识同步,这样做的成本比较高,因此可以在执行完多条请求K(例如:100条)后执行一次状态同步。这个状态同步消息就是CheckPoint消息。
副本节点i发送CheckPoint,n,d,i给其他节点,n是当前节点所保留的最后一个视图请求编号,d是对当前状态的一个摘要,该CheckPoint消息记录到log中。如果副本节点i收到了2f+1个验证过的CheckPoint消息,则清除先前日志中的消息,并以n作为当前一个stablecheckpoint。
这是理想情况,实际上当副本节点i向其他节点发出CheckPoint消息后,其他节点还没有完成K条请求,所以不会立即对i的请求作出响应,它还会按照自己的节奏,向前行进,但此时发出的CheckPoint并未形成stable。
为了防止i的处理请求过快,设置一个上文提到的高低水位区间[h,H]来解决这个问题。低水位h等于上一个stablecheckpoint的编号,高水位H=h+L,其中L是我们指定的数值,等于checkpoint周期处理请求数K的整数倍,可以设置为L=2K。当副本节点i处理请求超过高水位H时,此时就会停止脚步,等待stablecheckpoint发生变化,再继续前进。
?
在区块链场景中,一般适合于对强一致性有要求的私有链和联盟链场景。例如,在IBM主导的区块链超级账本项目中,PBFT是一个可选的共识协议。在Hyperledger的Fabric项目中,共识模块被设计成可插拔的模块,支持像PBFT、Raft等共识算法。
?
?
Raft基于领导者驱动的共识模型,其中将选举一位杰出的领导者(Leader),而该Leader将完全负责管理集群,Leader负责管理Raft集群的所有节点之间的复制日志。
?
下图中,将在启动过程中选择集群的Leader(S1),并为来自客户端的所有命令/请求提供服务。Raft集群中的所有节点都维护一个分布式日志(复制日志)以存储和提交由客户端发出的命令(日志条目)。Leader接受来自客户端的日志条目,并在Raft集群中的所有关注者(S2,S3,S4,S5)之间复制它们。
在Raft集群中,需要满足最少数量的节点才能提供预期的级别共识保证,这也称为法定人数。在Raft集群中执行操作所需的最少投票数为(N/2+1),其中N是组中成员总数,即投票至少超过一半,这也就是为什么集群节点通常为奇数的原因。因此,在上面的示例中,我们至少需要3个节点才能具有共识保证。
如果法定仲裁节点由于任何原因不可用,也就是投票没有超过半数,则此次协商没有达成一致,并且无法提交新日志。
?
数据存储:Tidb/TiKV
日志:阿里巴巴的DLedger
服务发现:Consuletcd
集群调度:HashiCorpNomad
?
只能容纳故障节点(CFT),不容纳作恶节点
顺序投票,只能串行apply,因此高并发场景下性能差
?
Raft通过解决围绕Leader选举的三个主要子问题,管理分布式日志和算法的安全性功能来解决分布式共识问题。
当我们启动一个新的Raft集群或某个领导者不可用时,将通过集群中所有成员节点之间协商来选举一个新的领导者。因此,在给定的实例中,Raft集群的节点可以处于以下任何状态:追随者(Follower),候选人(Candidate)或领导者(Leader)。
系统刚开始启动的时候,所有节点都是follower,在一段时间内如果它们没有收到Leader的心跳信号,follower就会转化为Candidate;
如果某个Candidate节点收到大多数节点的票,则这个Candidate就可以转化为Leader,其余的Candidate节点都会回到Follower状态;
一旦一个Leader发现系统中存在一个Leader节点比自己拥有更高的任期(Term),它就会转换为Follower。
Raft使用基于心跳的RPC机制来检测何时开始新的选举。在正常期间,Leader会定期向所有可用的Follower发送心跳消息(实际中可能把日志和心跳一起发过去)。因此,其他节点以Follower状态启动,只要它从当前Leader那里收到周期性的心跳,就一直保持在Follower状态。
当Follower达到其超时时间时,它将通过以下方式启动选举程序:
根据Candidate从集群中其他节点收到的响应,可以得出选举的三个结果。
共识算法的实现一般是基于复制状态机(Replicatedstatemachines),何为复制状态机:
简单来说:相同的初识状态+相同的输入=相同的结束状态。不同节点要以相同且确定性的函数来处理输入,而不要引入一下不确定的值,比如本地时间等。使用replicatedlog是一个很不错的注意,log具有持久化、保序的特点,是大多数分布式系统的基石。
有了Leader之后,客户端所有并发的请求可以在Leader这边形成一个有序的日志(状态)序列,以此来表示这些请求的先后处理顺序。Leader然后将自己的日志序列发送Follower,保持整个系统的全局一致性。注意并不是强一致性,而是最终一致性。
日志由有序编号(logindex)的日志条目组成。每个日志条目包含它被创建时的任期号(term),和日志中包含的数据组成,日志包含的数据可以为任何类型,从简单类型到区块链的区块。每个日志条目可以用[term,index,data]序列对表示,其中term表示任期,index表示索引号,data表示日志数据。
Leader尝试在集群中的大多数节点上执行复制命令。如果复制成功,则将命令提交给集群,并将响应发送回客户端。类似两阶段提交(2PC),不过与2PC的区别在于,leader只需要超过一半节点同意(处于工作状态)即可。
leader、follower都可能crash,那么follower维护的日志与leader相比可能出现以下情况
当出现了leader与follower不一致的情况,leader强制follower复制自己的log,Leader会从后往前试,每次AppendEntries失败后尝试前一个日志条目(递减nextIndex值),直到成功找到每个Follower的日志一致位置点(基于上述的两条保证),然后向后逐条覆盖Followers在该位置之后的条目。所以丢失的或者多出来的条目可能会持续多个任期。
?
要求候选人的日志至少与其他节点一样最新。如果不是,则跟随者节点将不投票给候选者。
意味着每个提交的条目都必须存在于这些服务器中的至
2. 最易于小白读透的POW和POS概念详解(内含波卡)
POW(工作量证明)与POS(权益证明)是两种不同的区块链共识机制,它们各有优劣。POW机制通过计算强度来验证交易,如比特币的挖矿,谁的计算能力更强,获得新区块的可能性越大,但这也导致了能源消耗和算力集中。而POS机制,如EOS的DPoS和波卡的NPOS,持有代币者通过质押来参与验证,持有越多,获得奖励的机会越多,较为节能,但安全性主要依赖于代币分散度。在EOS中,21个节点通过质押竞争网络奖励,而在波卡中,通过随机性分散节点来提高公平性。
在性能方面,POS通常具有更高的吞吐量和较低的创建区块成本,因为不依赖于现实能耗。然而,POS的共识需要大多数验证者达成一致,可能导致网络状态确认困难。波卡采用分片技术,降低对每个节点的要求,提高了网络的灵活性和安全性。
POW与POS在资源利用上也有所不同。POW挖矿消耗大量电力和硬件资源,而POS几乎不消耗除网络带宽以外的资源。POW形成了一套产业链,但其挖矿过程的实际效用有限,而POS则相对环保。
在去中心化方面,POW有天然的抗集中风险,但可能导致算力集中,而传统POS易出现大户控制。波卡的NPOS通过随机性降低了集中化的风险,但提高安全性需要结合其他算法。
总的来说,POW和POS各有优缺点,选择哪种机制取决于具体应用场景和安全需求。POW以公平性和可靠性见长,而POS强调效率和资源节约,但安全性需要额外的措施来保障。两者的发展都体现了区块链技术的不断优化和进步。
3. 区块链中PoW是指什么
是指工作量证明机制,是区块链的一种共识机制。指在区块链系统中,根据每个节点在运算的过程中所做出的贡献来确定权限的一种算法。工作量证明机制是现在区块链应用最为广泛的一种共识机制。共识机制是区块链系统中很重要的一部分,如果出现问题,那么整个系统都会出问题,在区块链开发中是必须要注意的。这是之前我一个在煊凌科技上班的人告诉我的,他虽然只是里面的销售,但是对区块链的了解也比大部分人要全面。
4. 区块链pow解决了什么(区块链pocc合法吗)
两种共识机制对比(PoWvsPoS)区块链中最核心的架构就是共识机制,可以说是区块链的驱动引擎,发展这么多年,目前主流比较明确经得住考验的就只剩下PoW(ProofofWork)与PoS(ProofofStake)两种机制。简单概述下,PoW系统的特点是通过消耗大量算力来计算特定算法的解(典型如哈希),第一个算出结果的有权生成区块,同时也会得到coin作为奖励(这也是coin的生产与分发过程,形象地称为Mining),采用PoW的典型区块链有Bitcoin和Ethereum,目前PoW也是运行时间最长,被公认为是最可靠安全的共识机制;其本质是通过消耗大量算力来实现系统内的逆熵过程,保证系统的长期安全与稳定。但PoW被广为诟病的也是其消耗太多的能源资源,这方面PoS就被认为是更为绿色的解决方案,顾名思义PoS是通过质押系统中的资产即coin来成为一个质押者(staker),这样就有权产出区块,质押份额越多,获得产出区块权的概率就越高,也代表着奖励越多。
在分布式系统中有一个CAP定理,是指一个分布式系统中存在着三元悖论,即不可能同时满足这三个特性:一致性(Consistency)、可用性(Availability)和分区容错性(Partitiontolerance),而只能满足其中两个。区块链作为一种分布式网络,这个定理也逐渐演变成了区块链的三元悖论,即安全性(Security)、去中心化(Decentralization)和可扩展性(Scalability),也是同时只能满足两个特性。
整体上看PoW系统更注重的是安全性(Security)与去中心化(Decentralization),放弃可扩展性(Scalability),这也是Bitcoin网络的吞吐量非常慢的原因。而PoS系统更关注的是可扩展性(Scalability)与去中心化(Decentralization),但就PoS能否真的实现去中心化(Decentralization),我是比较持怀疑态度的。从保守主义与系统的更长期稳定的角度出发,我个人是坚定地站在PoW这边的,可能跟自身保守的性格有关,并不是特别看好PoS作为基础层能比较稳定。特别是像这次5月份的Luna事件,事件大概的过程是Luna链上的算法稳定币UST缺乏价值支撑最终脱锚,其核心问题在于UST的锚定设计试图用一个PoS股权系统去支撑其锚定美元,而且还超发了太多UST,再加上UST与Luna的兑换设计缺陷最终导致Luna自身的死亡螺旋。但这个事件更大的意义应该是敲响了一个警钟,PoS机制在面对空头资本砸盘时真的还能维持稳定、维持所谓的去中心化吗?可能到时节点数量萎缩的速度会很快,逐渐趋于中心化。
所有系统设计都需要根据自身定位来折中,以下从价值锚定的角度,简单分析下为什么长期来看PoW会更有优势。
在PoW系统中三股主要的参与者分别是研发人员,投资者(或者叫用户)与Miner,这三者的相互制衡,使得这个系统达到一个稳定平衡的状态。而PoS系统中,将Miner这个重要的制衡力量移除了,投资者和Miner变成了同一群体质押者(stakers),因此该群体滥用权力的行为会变得相对不受限制,并且该链随后的发展方向也可能会更加不平衡,更容易倾向有利于质押者(stakers)群体的方向。
PoW系统很好的阐述了什么是被普遍认可的价值,抽象上来看就是高代价的稀缺性,高代价与稀缺性两者缺一不可。PoS最多只能实现其中一个稀缺性。
Miner为了在链上生产区块赚取coin,不仅需要持续支付高额电力成本,还必须不断投入研发、升级硬件、优化基础设施和运营规模来保持其竞争力。最终结果是,能够长期持续盈利的Miner并不会是一个一层不变的群体,而是总在竞争中淘汰掉效率太低的Miner,使高效率的Miner能存活下来。这也更有利于去中心化(Decentralization),因为不断变化的Miner群体意味着没有一个Miner可以在相当长的时间内保持网络的大部分算力,除非他们通过严酷的竞争考验,不断优化自身来提供更多的算力。
而PoS系统中的质押者实际上并多少真正的风险投入,也没有优胜劣汰的严酷竞争机制,他们只需要简单地运行一个staker节点就可以躺着赚利息,本质上只是将自己在银行系统里的钱简单的转化为链上资本,就可以坐地收割后进入这个系统的新人。这种行为并没有太多难度,只是简单地赚取“无风险”利息,他们并没有将资本转化为任何形式的需要面临风险考验的投资。
而且当发生硬分叉时,PoW的Miner选择支持哪条链时会更为谨慎,因为他们需要投入高昂的电力成本来为他们的选择背书,一旦选错了将损失所有投入成本。PoS系统如果发生硬分叉,质押的coin作为系统内部状态的一部分,硬分叉后质押者将在两条不同链上都拥有相同数量的资产,由于没有什么沉默成本,导致质押者更愿意两边都支持,从而使硬分叉更容易且更频繁地出现,这被称为nothingatstake问题。
PoW是真正能做到无准入限制的(Permissionless),就是说已经在这个系统中的老人无法限制新人加入,只要你有能力提供算力,就能直接接入网络中产出coin。而PoS系统中,新人要进入,都不得不先从老人手中买coin。
而且PoW中Miner为了支付各种高昂成本(电力,设备,基础设施等),产出coin后也不得不卖出一些以弥补成本,这同时也是一种把coin分发给更多人的过程;特别是在熊市,Miner为了维持开销也不得不低价贱卖coin,这样新人才有机会以相对低的成本获得筹码入场,这才是一个健康的生态扩张过程。而PoS中由于质押者并没有什么运行成本,也不需要面对太多竞争,质押者出块得到coin后不需要急着卖出,更容易哄抬价格,其实会变相激励场内老人剥削新入场者,不给后来人更多机会;整个系统会趋向于更封闭,逐渐演变成一个有限游戏,长期运行下去只会越来越中心化;系统中财富越来越集中,富者更富,穷者更穷,从而更不可能实现去中心化(Decentralization)。
由于PoW系统中是以提供工作量的方式产出区块的,随着时间的推移这些工作量都会被累积起来并使链不断向前延伸,这也是为什么叫区块链;这些累积的工作量也给攻击者造成了巨大障碍,如果想要反转整条链,不仅需要非常高的算力,还需要相当长的时间,这也为应对攻击提供了足够长的时间缓冲。
而PoS系统其实只是维护一个分布式账本,并没有工作量累积的概念,一旦攻击成功,要反转整条链就是相当容易的,几分钟就可以搞定。
严格来说由PoW算力支撑的BTC不应归为高科技类,由于它整个系统架构更保守更稳定,提供的更多的是一种物化价值(objectivecostliness),更能作为价值之锚,所以数字黄金这个称号很贴切。而像ETH(目前还是PoW,2.0升级后为PoS)这些更接近科技类创新平台,PoS本质上更像是一种股权系统,其实PoS系统反而是需要中心化,偏向更依靠整个社区的生命力,需要依靠核心团队的创新与开拓能力往前走;而PoW则需要去中心化,更偏向稳定与提供物化价值(objectivecostliness)。
区块链作为一个价值分配系统,算力是它的价值之锚,如果没有算力,就会退化为一个股权系统。算力在哪,资金就会跟去哪。目前的发展趋势也是逐渐往多层网络的方向发展,类似TCP/IP的多层协议栈。从作为基础层(BaseLayer)的角度看,更需要的是长期稳定与提供价值支撑,因此PoW系统更合适;而PoS可能更多的是可以作为Layer2以实现可扩展性(Scalability),弥补PoW基础层的吞吐量不足,并通过锚定在PoW基础层上来获取算力安全性与价值支撑。
最后顺带说下最近市场行情,5,6月份以来的瀑布令很多人很恐慌,恐慌指数一度长时间停留在个位数;其实我觉得也没必要那么恐慌,要在这个圈子长期活下去,面对这种大波动的心理预期还是要有的。想起之前红杉资本的沈南鹏经常提到一个词Grit,沙砾,它是砾石在千万次打磨后留下来的细小颗粒;Grit代表了勇气和持之以恒的一种坚持,有种经常被按地上摩擦但依然勇往直前的感觉。这个和塔勒布讲的反脆弱性有异曲同工之妙,承载价值的东西就应该具有这种品质,PoW系统肯定是有反脆弱性的。
回望2017年入圈后经历过的各种事件,其实像这样的大波动近乎每年都有(除了2019年一年比较顺利外);像2017年国内的94事件,2018年一整年的大熊市,2020的312事件,2021的519事件,再到2022今年的5,6月份市场转熊,每次经历大波动后,市场都会淘汰掉该淘汰的,出清掉该出清的风险,对整个行业发展也是好事。眼光还是应该放远一点,至少看5到10年后的变化,科技发展过程中所带来的波动和风险是不可避免的,日光之下无新鲜事,每次科技革命过程中总会夹杂着众多的反对、质疑,还有众多的投机、骗局;这个过程也总是通过各种暴雷、回归,清除泡沫后价值重估,夯实了基础后积蓄能量再次进入跃升到新的发展阶段。价值互联网的到来是一件无法回避的事情,当理解和看清了这种趋势后,规避掉各种坑和市场噪音,远离合约杠杆和各种山寨的诱惑,握住核心资产,时间本身就会带来回报。
在公链项目早期,为什么PoW是一个更好选择?在传统的互联网公司或金融机构中,如果一家公司,在一年之内,被委托的交易结算的总量为万亿美元的话,这家公司要么拥有可靠的技术和雄厚的资本,要么就是其它大公司及政府为其信用来做背书。而比特币却在没有政府或公司背书的情况下,在过去一年内支持了相当于一万亿美元的交易。这是因为比特币的工作量证明(PoW)机制确保了全世界的比特币矿工以点对点的方式去分布式地维护账本,且保证了其正确性和不可篡改性。
实际上,PoW?协议并不完美,它在运行过程中需要消耗大量的能量来计算哈希函数的结果,以保护区块链系统不被攻击。很多人认为这是一种“无用的能源消耗”。为了避免这种消耗,股权证明协议(PoS)便作为替代方案被提出。包括以太坊在内的几个著名的项目也开始探索股权证明协议(PoS),?甚至有人认为,PoS协议在未来将完全取代PoW协议。
但是,在对PoS?协议进行了深入的技术剖析之后,我们会发现:在一个公链项目的早期阶段,PoS?协议会带来很多问题,而这些问题在PoW协议下是可以避免。首先,使用PoS协议启动主网的公链项目,会不可避免地存在共识中心化的问题,因为主网上线的时候股权分布往往是相对集中的。此外,纯?PoS?协议还面临着远程攻击(LongRangeattack)的威胁。最严重的远程攻击会导致新加入的节点必须信任一些中心化的网站给出的信息,而这会导致?PoS?公链成为一个本质上中心化的网络。去使用PoW协议启动主网的区块链则可以实现分散的共识,从而避免这些问题。当PoW公链经过一段时间的发展,股权分布相对分散以后,还可以选择PoW/PoS复合机制。
除此之外,还有一点值得注意的是,很多人误以为比特币的扩容问题是PoW机制的局限性造成的。我们经常在媒体网站或白皮书中看到这样的句子,“比特币因为使用了PoW机制,所以只能处理每秒3-7笔交易”。而事实上,经过适当的设计,例如,GHOST,Conflux?这样的PoW算法可以显著提高出块效率,达到每秒处理数千笔交易,且每笔交易都能得到全网节点的验证。
PoWv.s.PoS:如何确定投票权
关于PoW和PoS之间的主要区别,就是在于如何确定区块链共识中的投票权。?在PoW中,系统中的投票权与节点的计算能力成正比。每秒可以计算哈希函数次数越多,节点就越有可能赢得区块链中下一个区块的出块权。而在PoS中,系统的投票权与持有的股权比例成正比。节点拥有资金越多,能为确定的下一个区块投的票数就越多。
在公链早期阶段,股权中心化将导致共识中心化
对于一个公有链来说,其上线初期往往是股权最集中的时候。在主网上线伊始,创始块中分配的币绝大多数属于项目方和私募投资人,而这些人的数量往往非常有限。对于PoW共识机制,初始股权的集中不会带来安全性问题,因为它的出块和安全性不依赖于股权持有的分散,而是依赖于算力的分散。对于使用反?ASIC?矿机的挖矿算法的公有链来说,任何人只要拥有显卡和网络就可以成为矿工,这有助于促进更多人参与挖矿,实现早期算力的分散。只要超过50%的算力来自于诚实的矿工,区块链中的交易就是安全不可逆转的。
然而,在PoS共识机制下,股权集中会导致共识协议的参与者集中。区块链的出块权只能由少数在创世块中拥有股权的玩家决定。如果这些人合谋对区块链进行攻击,则完全可以成功的实现双花攻击(Doublespendingattack).?尽管开发者和投资人出于利益考虑不会进行这样的攻击来摧毁他们自己的公链,但PoS公链也无可避免的在主网上线后就被这些人垄断和支配。更糟的是,如果出块可以获得大量奖励和交易费用,这些垄断者就会将大量股权牢牢控制在自己的手里,使得PoS公链成为一个本质上由巨头控制的网络。
我们不要忘了,区块链的核心价值是什么?是去中心化的共识协议,保证了区块链系统中每笔交易的正确性、不可篡改性。如果共识协议无法保证参与者的分散,区块链就无法做到无需信任的安全性,那么区块链和传统的分布式系统相比就没有任何优势了,甚至传统的分布式系统能做得更经济更高效。因此,公链项目在早期使用PoW,?是避免共识中心化,保护区块链核心价值的明智选择。
“长程攻击”与“主观依赖”问题
在一个公有链中,一个攻击者如果拥有当下足够多的算力或股权,无疑是可以打破公有链安全性完成攻击的。但是在PoS?公链中,如果攻击者获得了一些账户的私钥,这些私钥在历史上某一时刻控制了超过51%的股权,也可以完成攻击,这种攻击的方式被称为长程攻击(LongRangeAttack)。
在长程攻击中,攻击者首先获得一些私钥,只要这些私钥在历史上曾经获得了足够多的股权,便可以从这一时刻开始分叉进行51%?攻击,制造一条分叉链出来。而?PoS?的出块不需要进行工作量证明,攻击者可以短时间内让重写历史的分叉链追赶上原本的主链,从而造成PoS链的分叉和防篡改性被打破。
攻击者能够取得这些私钥不是天方夜谭。如果PoS公链的早期投资人在二级市场将持有的代币卖掉后,将账户私钥卖给攻击者,攻击者就可以从创世块进行长链攻击,从而可以打破一个链的安全性。如果一些投资者追求短期收益而非价值投资,攻击者从他们手里获得私钥就成为了一个可能的事情。
而为了应对长程攻击,则有各种各样的解决方案被提出:例如使用密钥演化算法更新密钥,以避免密钥被盗。但是如果早期投资者一开始就决定通过出售私钥获利,那么他完全可以保留密钥种子以绕开这一限制。还有一些解决方案基于这样一个事实:如果攻击者挖了一条完全不同的链,长期在系统中运行的节点或许有能力探测出这种异常。但是,这些方案依然存在如下问题:
PoS?长程攻击造成的分叉与?PoW?的分叉有所不同。PoW?的分叉链难以获得比特币全网算力,比特币矿工很容易从总算力中辨别谁是真正的比特币。鉴于PoS共识协议在实际运行时,绝大多数股权持有者只是区块链的使用者,并不会一直运行一台服务器。攻击者只要在一个历史节点拥有了相当与PoS实际参与者的股权比例,就可以制造出一条难以辨别的分叉链出来。配合女巫攻击(SybilAttack),攻击者可以从区块历史和节点数量上都获得和被攻击主链接近的水平,令新加入的节点无法区分,只能通过人工指定的方式选择。这样新参与者必须咨询受信任节点来安全地加入系统,这一问题被称为“主观依赖”(WeakSubjectivity)
无利害攻击
无利害攻击(NothingatStake)是另一种PoS攻击方式。当一个?PoS?链因为网络延迟、长程攻击或其他原因出现分叉时,PoS?矿工可以选择在两个分叉的链上同时出块,以获取最大收益。而这违反了共识协议。
在PoW?链中,如果一个矿工想同时在多个分叉上挖矿,就必须将自己的算力分散在多个分叉上,所有分叉上分配的算力总和不会超过矿工拥有的总算力。对于多数矿工而言,将自己的全部算力投入到协议指定的链上是最优的选择。
然而,在PoS?多个分叉上同时出块所带来的额外成本可以忽略不计,而选择同时出块可以保证无论哪一条分叉链最终胜出都可获得收益。如果矿工遵守共识协议,只在协议指定的链上挖矿。一旦这个链被丢弃,矿工将会失去挖矿奖励。只追求挖矿收益最大化的矿工会在两边同时参与,不惜因此打破协议——这会导致链长时间维持分叉的状态。
与长程攻击不同,精巧的激励机制设计可以避免这一攻击。但无利害攻击依然表明让PoS链正确地运行是一件很困难的事情。
总结
虽然PoS?具有节省能源等优势,从而很多项目表示将采用PoS。但我们在分析区块链安全性假设后发现,避免了计算“无用的哈希”之后会引入很多攻击情形,而且目前没有很完美的解决方案。诚然PoS有能源效率的优势,但也带来了很多安全性威胁。在PoS很好地解决这些威胁之前,PoW消耗的能源,就像和平时期国家军队用掉的军费一样,阻挡了很多潜在的威胁。最重要的是,其中许多威胁在区块链项目早期显得尤其致命。这也是我们为什么相信新的公链项目应该从PoW开始。
POW&POS,傻傻分不清楚的共识机制什么是共识机制?
我在开更的第一篇文章,就简单讲解了数字货币世界的16个最高频名词,其中一个就是共识机制,还记得吗?
为什么要有共识机制呢?
这就必须要解释一下在分布式系统中不得不了解的“拜占庭将军问题”了。
拜占庭将军问题(TheByzantineGeneralsProblem)可以总结为一句话:
在古代,11位忠诚的、不同位置的将军,如何排除叛徒的影响,对进攻或撤退达成一致。
当然,拜占庭将军问题并不是如今才提出的,我们大中华在春秋战国时期就发明了“虎符”这个神奇的方式来保障命令的正确执行。
在分布系数系统中,各个节点就是“拜占庭将军”,算法执行中的任意一个错误就是“叛徒”。
为了尽可能地排除错误、快速达成一致,来让系统有效地、正确地运行,便应运而生了各种“共识机制”。
————————————————
下面,我们就来一起学习数字货币世界中常见的几种共识机制:
PoW,工作量证明ProofofWork
PoW是比特币所采用的共识机制,最早是由AdamBack为了解决垃圾邮件的问题而开发的一个“哈希现金Hashcash”程序。
比特币采用的是SHA256的单向函数,其具体的工作原理实在太专业,我们只需要理解到“SHA256的结果很容易验证,但是要将其计算出来,需要不断尝试运算,直到匹配到某个随机数;技术上而言,任何新增区块都需要经过232394亿运算才能得到”的程度,感兴趣的小伙伴可以搜索SHA256去深入学习。
因此,只要矿工出示运算结果,那通过PoW,全网节点就认可了他所付出的成本,承认新的区块奖励属于他。
如此大量的运算相当浪费资源,实际上并没有任何科学或实际用途,只是为了实践工作量证明机制、阻止攻击者伪装成节点来控制网络。
虽然在2009年时为了构建这种去中心化的、允许所有人可以免费参与的全球货币网络,没有更好的选择;但是发展到如今,已经有了其他不需要大量浪费算力的证明机制,比如我们下面就要提到的,PoS权益证明。
————————————————
PoS,权益证明ProofofStake
主要思想是:节点记账权的获得难度与节点持有的权益成反比,也就是说,一个节点拥有的币越多、时间越久,越容易获取记账权,也就越容易获取区块奖励。
实际上,最初的PoS是PoW的一种升级,根据每个节点的币龄,来等比例地降低挖矿难度,从而加快找到随机数的速度。
什么是币龄呢?
币龄=数量*拥有天数。
由于区块链中的每笔交易记录都会被标记时间戳,这个时间戳就可以作为币龄的证明,因此币龄也不可能被轻易伪造。
比如A从B那里收到10个币,并且持有了90天,那么,A就拥有了900的币龄;如果A卖了这10个币,这900币龄就被消耗了;
后来,为了彻底摆脱PoW这种依靠算力的共识机制,PoS引入了“利息”的概念;年利率是在PoS机制最初确认时就设定的,一般不会变化。
利息=(币龄*年利率)/365,如果利率是1%,在上个例子中,A就可以得到0.02466个币的利息。
如此一来,PoS区块链的作用过程就可以这样描述:
在初期,通过PoW机制,产生创世币;
在创世币达到一定规模时,PoS机制开始作用,交易时消耗币龄、获得产生区块的优先权,并获取利息,同时PoW机制由于消耗太多资源、浪费算力而逐渐淡出;
最终系统中仅剩PoS来维持正常运作。
目前大家所熟悉的以太坊,主要还是采用PoW的机制,不过正在转向PoS。
————————————————
大家了解了PoW和PoS,在遇到其他共识机制的时候,相信也会比较快得就能理解。
比如:股份授权证明DPOS,类似于董事会投票;燃烧证明POB;沉淀证明POD;能力证明POC;消逝时间证明PODT,等等。
就不在这里为大家一一展开了,感兴趣的同学可以网络或知乎一下~
区块链共识机制之一:POW工作量证明机制区块链可以理解为一个不可篡改的公共账本,所有参与者都能验证交易并进行记账,即为分布式账本。那到底由谁来记账?又如何保证账本的一致性、准确性呢?也就是区块链的共识机制是如何的?
区块链的共识机制就是解决由谁来记账(构造区块),以及如何维护区块链的一致性问题。目前区块链项目采用的共识机制有多种,如:POW工作量证明机制,POS权益证明机制,DPOS股份授权证明机制等等。本文说明POW工作量证明机制。
区块链的第一个成功应用比特币系统采用的POW工作量证明机制。即以比特币系统为例说明POW机制,首先比特币系统有一套激励机制让所有参与者竞争记账的权利,即谁拥有记账权谁将获取构造新区块的比特币奖励(目前奖励为12.5比特币),同时获取新区块内所有交易的手续费作为奖励。
参与者如何竞争记账权利呢?参与者通过自己的算力计算一道数学难题,谁先计算的结果,谁就拥有了记账的权利,也就可获得构造新区块的奖励。这道数学难题就是寻找一个随机数Nonce,使得对区块头的哈希计算的结果小于目标值,Nonce本身是区块头中的一个字段,所以通过不断的尝试Nonce的值,以满足区块头的哈希计算结果小于目标值。通过动态调整目标值,即可调整计算的Nonce值的难度。
关于哈希计算Nonce的过程通常类比为掷筛子游戏,基于参与游戏的筛子的个数通过调整掷得筛子的点数可调整游戏的难度。例如:100个人参与掷筛子,总共有100个筛子,要求掷得点数为100为赢,则100个人谁先掷得点数100即为胜利者,即拥有了记账权。如果发现大家掷出100点的时间太快,则可增加难度,要求掷得点数为80为赢。如果又有100个人参与游戏,则游戏中增加了筛子数,如:筛子数增加为200个,同样通过设置掷得点数来调整游戏的难度。
筛子类似于比特币网络的算力,掷得点数类似于比特币网络可动态调整的目标值。
区块链以最长的链条视为正确的链条,如果存在同时出现两个区块,会暂时并行记录两个区块,后续再生成的区块基于其中的某一个
5. 区块链 --- 共识算法
PoW算法是一种防止分布式服务资源被滥用、拒绝服务攻击的机制。它要求节点进行适量消耗时间和资源的复杂运算,并且其运算结果能被其他节点快速验算,以耗用时间、能源做担保,以确保服务与资源被真正的需求所使用。
PoW算法中最基本的技术原理是使用哈希算法。假设求哈希值Hash(r),若原始数据为r(raw),则运算结果为R(Result)。
R = Hash(r)
哈希函数Hash()的特性是,对于任意输入值r,得出结果R,并且无法从R反推回r。当输入的原始数据r变动1比特时,其结果R值完全改变。在比特币的PoW算法中,引入算法难度d和随机值n,得到以下公式:
Rd = Hash(r+n)
该公式要求在填入随机值n的情况下,计算结果Rd的前d字节必须为0。由于哈希函数结果的未知性,每个矿工都要做大量运算之后,才能得出正确结果,而算出结果广播给全网之后,其他节点只需要进行一次哈希运算即可校验。PoW算法就是采用这种方式让计算消耗资源,而校验仅需一次。
PoS算法要求节点验证者必须质押一定的资金才有挖矿打包资格,并且区域链系统在选定打包节点时使用随机的方式,当节点质押的资金越多时,其被选定打包区块的概率越大。
POS模式下,每个币每天产生1币龄,比如你持有100个币,总共持有了30天,那么,此时你的币龄就为3000。这个时候,如果你验证了一个POS区块,你的币龄就会被清空为0,同时从区块中获得相对应的数字货币利息。
节点通过PoS算法出块的过程如下:普通的节点要成为出块节点,首先要进行资产的质押,当轮到自己出块时,打包区块,然后向全网广播,其他验证节点将会校验区块的合法性。
DPoS算法和PoS算法相似,也采用股份和权益质押。
但不同的是,DPoS算法采用委托质押的方式,类似于用全民选举代表的方式选出N个超级节点记账出块。
选民把自己的选票投给某个节点,如果某个节点当选记账节点,那么该记账节点往往在获取出块奖励后,可以采用任意方式来回报自己的选民。
这N个记账节点将轮流出块,并且节点之间相互监督,如果其作恶,那么会被扣除质押金。
通过信任少量的诚信节点,可以去除区块签名过程中不必要的步骤,提高了交易的速度。
拜占庭问题:
拜占庭是古代东罗马帝国的首都,为了防御在每块封地都驻扎一支由单个将军带领的军队,将军之间只能靠信差传递消息。在战争时,所有将军必须达成共识,决定是否共同开战。
但是,在军队内可能有叛徒,这些人将影响将军们达成共识。拜占庭将军问题是指在已知有将军是叛徒的情况下,剩余的将军如何达成一致决策的问题。
BFT:
BFT即拜占庭容错,拜占庭容错技术是一类分布式计算领域的容错技术。拜占庭假设是对现实世界的模型化,由于硬件错误、网络拥塞或中断以及遭到恶意攻击等原因,计算机和网络可能出现不可预料的行为。拜占庭容错技术被设计用来处理这些异常行为,并满足所要解决的问题的规范要求。
拜占庭容错系统 :
发生故障的节点被称为 拜占庭节点 ,而正常的节点即为 非拜占庭节点 。
假设分布式系统拥有n台节点,并假设整个系统拜占庭节点不超过m台(n ≥ 3m + 1),拜占庭容错系统需要满足如下两个条件:
另外,拜占庭容错系统需要达成如下两个指标:
PBFT即实用拜占庭容错算法,解决了原始拜占庭容错算法效率不高的问题,算法的时间复杂度是O(n^2),使得在实际系统应用中可以解决拜占庭容错问题
PBFT是一种状态机副本复制算法,所有的副本在一个视图(view)轮换的过程中操作,主节点通过视图编号以及节点数集合来确定,即:主节点 p = v mod |R|。v:视图编号,|R|节点个数,p:主节点编号。
PBFT算法的共识过程如下:客户端(Client)发起消息请求(request),并广播转发至每一个副本节点(Replica),由其中一个主节点(Leader)发起提案消息pre-prepare,并广播。其他节点获取原始消息,在校验完成后发送prepare消息。每个节点收到2f+1个prepare消息,即认为已经准备完毕,并发送commit消息。当节点收到2f+1个commit消息,客户端收到f+1个相同的reply消息时,说明客户端发起的请求已经达成全网共识。
具体流程如下 :
客户端c向主节点p发送<REQUEST, o, t, c>请求。o: 请求的具体操作,t: 请求时客户端追加的时间戳,c:客户端标识。REQUEST: 包含消息内容m,以及消息摘要d(m)。客户端对请求进行签名。
主节点收到客户端的请求,需要进行以下交验:
a. 客户端请求消息签名是否正确。
非法请求丢弃。正确请求,分配一个编号n,编号n主要用于对客户端的请求进行排序。然后广播一条<<PRE-PREPARE, v, n, d>, m>消息给其他副本节点。v:视图编号,d客户端消息摘要,m消息内容。<PRE-PREPARE, v, n, d>进行主节点签名。n是要在某一个范围区间内的[h, H],具体原因参见 垃圾回收 章节。
副本节点i收到主节点的PRE-PREPARE消息,需要进行以下交验:
a. 主节点PRE-PREPARE消息签名是否正确。
b. 当前副本节点是否已经收到了一条在同一v下并且编号也是n,但是签名不同的PRE-PREPARE信息。
c. d与m的摘要是否一致。
d. n是否在区间[h, H]内。
非法请求丢弃。正确请求,副本节点i向其他节点包括主节点发送一条<PREPARE, v, n, d, i>消息, v, n, d, m与上述PRE-PREPARE消息内容相同,i是当前副本节点编号。<PREPARE, v, n, d, i>进行副本节点i的签名。记录PRE-PREPARE和PREPARE消息到log中,用于View Change过程中恢复未完成的请求操作。
主节点和副本节点收到PREPARE消息,需要进行以下交验:
a. 副本节点PREPARE消息签名是否正确。
b. 当前副本节点是否已经收到了同一视图v下的n。
c. n是否在区间[h, H]内。
d. d是否和当前已收到PRE-PPREPARE中的d相同
非法请求丢弃。如果副本节点i收到了2f+1个验证通过的PREPARE消息,则向其他节点包括主节点发送一条<COMMIT, v, n, d, i>消息,v, n, d, i与上述PREPARE消息内容相同。<COMMIT, v, n, d, i>进行副本节点i的签名。记录COMMIT消息到日志中,用于View Change过程中恢复未完成的请求操作。记录其他副本节点发送的PREPARE消息到log中。
主节点和副本节点收到COMMIT消息,需要进行以下交验:
a. 副本节点COMMIT消息签名是否正确。
b. 当前副本节点是否已经收到了同一视图v下的n。
c. d与m的摘要是否一致。
d. n是否在区间[h, H]内。
非法请求丢弃。如果副本节点i收到了2f+1个验证通过的COMMIT消息,说明当前网络中的大部分节点已经达成共识,运行客户端的请求操作o,并返回<REPLY, v, t, c, i, r>给客户端,r:是请求操作结果,客户端如果收到f+1个相同的REPLY消息,说明客户端发起的请求已经达成全网共识,否则客户端需要判断是否重新发送请求给主节点。记录其他副本节点发送的COMMIT消息到log中。
如果主节点作恶,它可能会给不同的请求编上相同的序号,或者不去分配序号,或者让相邻的序号不连续。备份节点应当有职责来主动检查这些序号的合法性。
如果主节点掉线或者作恶不广播客户端的请求,客户端设置超时机制,超时的话,向所有副本节点广播请求消息。副本节点检测出主节点作恶或者下线,发起View Change协议。
View Change协议 :
副本节点向其他节点广播<VIEW-CHANGE, v+1, n, C , P , i>消息。n是最新的stable checkpoint的编号, C 是 2f+1验证过的CheckPoint消息集合, P 是当前副本节点未完成的请求的PRE-PREPARE和PREPARE消息集合。
当主节点p = v + 1 mod |R|收到 2f 个有效的VIEW-CHANGE消息后,向其他节点广播<NEW-VIEW, v+1, V , O >消息。 V 是有效的VIEW-CHANGE消息集合。 O 是主节点重新发起的未经完成的PRE-PREPARE消息集合。PRE-PREPARE消息集合的选取规则:
副本节点收到主节点的NEW-VIEW消息,验证有效性,有效的话,进入v+1状态,并且开始 O 中的PRE-PREPARE消息处理流程。
在上述算法流程中,为了确保在View Change的过程中,能够恢复先前的请求,每一个副本节点都记录一些消息到本地的log中,当执行请求后副本节点需要把之前该请求的记录消息清除掉。
最简单的做法是在Reply消息后,再执行一次当前状态的共识同步,这样做的成本比较高,因此可以在执行完多条请求K(例如:100条)后执行一次状态同步。这个状态同步消息就是CheckPoint消息。
副本节点i发送<CheckPoint, n, d, i>给其他节点,n是当前节点所保留的最后一个视图请求编号,d是对当前状态的一个摘要,该CheckPoint消息记录到log中。如果副本节点i收到了2f+1个验证过的CheckPoint消息,则清除先前日志中的消息,并以n作为当前一个stable checkpoint。
这是理想情况,实际上当副本节点i向其他节点发出CheckPoint消息后,其他节点还没有完成K条请求,所以不会立即对i的请求作出响应,它还会按照自己的节奏,向前行进,但此时发出的CheckPoint并未形成stable。
为了防止i的处理请求过快,设置一个上文提到的 高低水位区间[h, H] 来解决这个问题。低水位h等于上一个stable checkpoint的编号,高水位H = h + L,其中L是我们指定的数值,等于checkpoint周期处理请求数K的整数倍,可以设置为L = 2K。当副本节点i处理请求超过高水位H时,此时就会停止脚步,等待stable checkpoint发生变化,再继续前进。
在区块链场景中,一般适合于对强一致性有要求的私有链和联盟链场景。例如,在IBM主导的区块链超级账本项目中,PBFT是一个可选的共识协议。在Hyperledger的Fabric项目中,共识模块被设计成可插拔的模块,支持像PBFT、Raft等共识算法。
Raft基于领导者驱动的共识模型,其中将选举一位杰出的领导者(Leader),而该Leader将完全负责管理集群,Leader负责管理Raft集群的所有节点之间的复制日志。
下图中,将在启动过程中选择集群的Leader(S1),并为来自客户端的所有命令/请求提供服务。 Raft集群中的所有节点都维护一个分布式日志(复制日志)以存储和提交由客户端发出的命令(日志条目)。 Leader接受来自客户端的日志条目,并在Raft集群中的所有关注者(S2,S3,S4,S5)之间复制它们。
在Raft集群中,需要满足最少数量的节点才能提供预期的级别共识保证, 这也称为法定人数。 在Raft集群中执行操作所需的最少投票数为 (N / 2 +1) ,其中N是组中成员总数,即 投票至少超过一半 ,这也就是为什么集群节点通常为奇数的原因。 因此,在上面的示例中,我们至少需要3个节点才能具有共识保证。
如果法定仲裁节点由于任何原因不可用,也就是投票没有超过半数,则此次协商没有达成一致,并且无法提交新日志。
数据存储:Tidb/TiKV
日志:阿里巴巴的 DLedger
服务发现:Consul& etcd
集群调度:HashiCorp Nomad
只能容纳故障节点(CFT),不容纳作恶节点
顺序投票,只能串行apply,因此高并发场景下性能差
Raft通过解决围绕Leader选举的三个主要子问题,管理分布式日志和算法的安全性功能来解决分布式共识问题。
当我们启动一个新的Raft集群或某个领导者不可用时,将通过集群中所有成员节点之间协商来选举一个新的领导者。 因此,在给定的实例中,Raft集群的节点可以处于以下任何状态: 追随者(Follower),候选人(Candidate)或领导者(Leader)。
系统刚开始启动的时候,所有节点都是follower,在一段时间内如果它们没有收到Leader的心跳信号,follower就会转化为Candidate;
如果某个Candidate节点收到大多数节点的票,则这个Candidate就可以转化为Leader,其余的Candidate节点都会回到Follower状态;
一旦一个Leader发现系统中存在一个Leader节点比自己拥有更高的任期(Term),它就会转换为Follower。
Raft使用基于心跳的RPC机制来检测何时开始新的选举。 在正常期间, Leader 会定期向所有可用的 Follower 发送心跳消息(实际中可能把日志和心跳一起发过去)。 因此,其他节点以 Follower 状态启动,只要它从当前 Leader 那里收到周期性的心跳,就一直保持在 Follower 状态。
当 Follower 达到其超时时间时,它将通过以下方式启动选举程序:
根据 Candidate 从集群中其他节点收到的响应,可以得出选举的三个结果。
共识算法的实现一般是基于复制状态机(Replicated state machines),何为 复制状态机 :
简单来说: 相同的初识状态 + 相同的输入 = 相同的结束状态 。不同节点要以相同且确定性的函数来处理输入,而不要引入一下不确定的值,比如本地时间等。使用replicated log是一个很不错的注意,log具有持久化、保序的特点,是大多数分布式系统的基石。
有了Leader之后,客户端所有并发的请求可以在Leader这边形成一个有序的日志(状态)序列,以此来表示这些请求的先后处理顺序。Leader然后将自己的日志序列发送Follower,保持整个系统的全局一致性。注意并不是强一致性,而是 最终一致性 。
日志由有序编号(log index)的日志条目组成。每个日志条目包含它被创建时的任期号(term),和日志中包含的数据组成,日志包含的数据可以为任何类型,从简单类型到区块链的区块。每个日志条目可以用[ term, index, data]序列对表示,其中term表示任期, index表示索引号,data表示日志数据。
Leader 尝试在集群中的大多数节点上执行复制命令。 如果复制成功,则将命令提交给集群,并将响应发送回客户端。类似两阶段提交(2PC),不过与2PC的区别在于,leader只需要超过一半节点同意(处于工作状态)即可。
leader 、 follower 都可能crash,那么 follower 维护的日志与 leader 相比可能出现以下情况
当出现了leader与follower不一致的情况,leader强制follower复制自己的log, Leader会从后往前试 ,每次AppendEntries失败后尝试前一个日志条目(递减nextIndex值), 直到成功找到每个Follower的日志一致位置点(基于上述的两条保证),然后向后逐条覆盖Followers在该位置之后的条目 。所以丢失的或者多出来的条目可能会持续多个任期。
要求候选人的日志至少与其他节点一样最新。如果不是,则跟随者节点将不投票给候选者。
意味着每个提交的条目都必须存在于这些服务器中的至少一个中。如果候选人的日志至少与该多数日志中的其他日志一样最新,则它将保存所有已提交的条目,避免了日志回滚事件的发生。
即任一任期内最多一个leader被选出。这一点非常重要,在一个复制集中任何时刻只能有一个leader。系统中同时有多余一个leader,被称之为脑裂(brain split),这是非常严重的问题,会导致数据的覆盖丢失。在raft中,两点保证了这个属性:
因此, 某一任期内一定只有一个leader 。
当集群中节点的状态发生变化(集群配置发生变化)时,系统容易受到系统故障。 因此,为防止这种情况,Raft使用了一种称为两阶段的方法来更改集群成员身份。 因此,在这种方法中,集群在实现新的成员身份配置之前首先更改为中间状态(称为联合共识)。 联合共识使系统即使在配置之间进行转换时也可用于响应客户端请求,它的主要目的是提升分布式系统的可用性。