区块链共识算法:实用拜占庭容错机制PBFT

  共识机制是区块链的核心组成部分,以POW、POS以及DPOS等为代表的共识机制运行需要以代币为基础,即需要发行各自的货币体系来构成各自网络运行的激励机制,而在于节点已经有一定的互信基础且不需要靠代币来支撑整个网络的区块链,传统的一致性算法如PBFT、PAXOS、RAFT则派上了用场,PAXOS则是第一个被证明的共识算法。。

  Paxos算法

  Paxos算法是一种两阶段算法,主要有三类角色,proposer、acceptor、learner,proposer提出议案,acceptor同意或拒绝,learner则是获取达成共识后的最终值。

  准备阶段:

  proposer 选择一个提案编号 n 并将 prepare 请求发送给 acceptors 中的一个多数派;

  acceptor 收到 prepare 消息后,如果提案的编号大于它已经回复的所有 prepare 消息,则 acceptor 将自己上次接受的提案回复给 proposer,并承诺不再回复小于 n 的提案;

  批准阶段:

  当一个 proposor 收到了多数 acceptors 对 prepare 的回复后,就进入批准阶段。它要向回复 prepare 请求的 acceptors 发送 accept 请求,包括编号 n 和value(如果没有已经接受的 value,那么它可以自由决定 value)。

  在不违背自己向其他 proposer 的承诺的前提下,acceptor 收到 accept 请求后即接受这个请求。
  
  Paxos算法适用于简单容错模型,即系统中只可能存在失效或故障节点,不存在恶意节点,如果失效节点数为x,则只需要未失效节点数为x+1就能维持系统的正常工作。

  Raft算法

  Raft算法包含三种角色,分别是:跟随者(follower),候选人(candidate)和领导者(leader)。一个节点在某一时刻只能是这三种状态的其中一种,这三种角色是可以随着时间和条件的变化而互相转换的。

  所有的节点初始状态都为follower,超时未收到心跳包的follower将变身candidate并广播投票请求,获得多数投票的节点将化身leader,这一轮投票的过程是谁先发出谁有利,每个节点只会给出一次投票。leader节点周期性给其他节点发送心跳包,leader节点失效将会引发新一轮的投票过程。

  logo

  上图描述了一个Raft提案的执行过程:

  leader收到客户端发来的请求,写入本地日志,但写入日志的条目在提交状态机之前需要将请求发给所有follower请求验证;

  follower对收到的信息进行验证,验证成功后写入本地日志并返回leader验证成功标识;

  leader收到大部分的follower节点验证信息后,就会将当前的日志提交,更新节点的值,并广播更新所有follower节点的值,从而再一次达成共识;

  Raft算法从节点不会拒绝主节点的请求,并且和Paxos一样只能容错故障或失效节点。

  实用拜占庭容错机制PBFT

  PBFT算法由Miguel Castro和 Barbara Liskov 1999年提出,初衷是为解决分布式系统中达成一致性的问题,与区块链共识机制的目标重合,其主要特点是网络具有高度容错性,在一个有3f + 1个节点的网络中,失效节点数为f,网络依然能够正常运行,容错率接近33%。目前,中国ChinaLedger 联盟和HyperLedger联盟就在研究探讨PBFT的实际应用。

  算法首先需要引入视图(View)和验证节点(replica)的概念,replica包含主节点和备份节点。主节点(primary)依据某个公式选取,选取好之后,其他replica节点就成为备份(backups)节点。主节点有效时是表示处于同一幅视图当中,当主节点失效时,备份节点检测到之后需要通过timeout机制启动视图更换(view change)过程,选举新的主节点。整个算法流程如下:首先,由某个客户端向主节点发起服务请求,主节点将请求分发给所有备份节点,备份节点处理完后再全部回馈给客户端,客户端只要收到f + 1个节点回馈的相同结果即为算法的最终结果。

  具体实现流程分为三阶段协议(three-phase protocol),即预准备(pre-prepare)、准备(prepare)和确认(commit)。

  logo

  预准备(pre-prepare)阶段:主节点收到请求后,给请求编一个序号n,然后向所有备份节点发送信息,信息格式为<,m>,v是视图编号,m是客户端发送的请求信息,d是m的摘要。如果该信息满足该备份节点设立的条件(如检查视图编号,序号n是否处于一个合理区间, m是否之前收到过等),则该节点进入准备阶段。备份节点设立某些条件的原因是主节点有可能是失效节点,它可能会给不同的请求编上相同的序号,或者不去分配序号,或者让相邻的序号不连续:

  准备(prepare)阶段:进入准备阶段的节点向所有replica节点发送准备消息,i是节点编号。经过这两个阶段,每个节点都收到了两条信息,每个replica节点验证预准备和准备消息的一致性,即验证视图编号v、消息序号n和摘要d是否一致,如果一致,进入下一个阶段。

  确认(commit)阶段:进入这一阶段,某个replica节点向其他replica节点发送信息,信息格式。节点收到其他replica节点确认信息后进行验证,仍是验证视图编号v、消息序号n和摘要d是否一致,一致则验证通过。当replica节点收到2f + 1个(包含自身) 验证通过的确认信息后,向客户端反馈执行结果,并将结果写入区块中,即写入区块前,至少有2f + 1个(包含自身)节点达成了共识。

  存在一个确认(commit)阶段的缘由在于,单个replica节点收到2f + 1个(包括自己) PREPARE信息并不能保证自己发出的PREPARE信息已被其他replica节点接收到,即其他节点不一定已经准备好Prepared,需要一个确认(commit)阶段来对此进行验证。

  如果连续执行了K条请求,在第K条请求执行完时,向全网发起广播,告诉其他replica节点它已经将这K条执行完毕,要是都反馈说这K条我们也执行完毕了,那就可以删除这K条的信息了,接下来再执行K条,完成后再发起一次广播,即每隔K条发起一次全网共识,这个概念叫checkpoint,每隔K条去征求一下大家的意见,要是获得了大多数的认同,就形成了一个 stable checkpoint(记录在第K条的编号),这一机制被称为“Garbage Collection”。

  PBFT是一种静态共识, 在得知有限共识节点的情况可以适用。对于私有链和联盟链,如果节点数不大(不大于100),可采用PBFT形成共识,公有链拥有大量且不断动态变化的节点网络,PBFT由于其封闭性(节点数目提前确定并互相联通)和高性能开销(O(N^2)的消息量),以及复杂的view change算法和开销,用PBFT效率太低。

  使用PBFT算法还需要注意的一点是,其不能很好的存贮其交易信息,一些失效的副本可能会导致信息外泄,应有相应应对机制。

我的BTC地址:1K8ni4mnQn7VjFZKjHJHLPWZ55owG9J1jd
我的邮箱:mch200610@163.com,欢迎批评指正!

您的支持将是我最大的动力!