BFT(Byzantine Fault Tolerance)是区块链共识算法中需要解决的一个核心问题。例如,公有链网络中,比特币和以太访中用的是POW,EOS用的是DPOS。PBFT一般用于联盟链场景中,它是共识节点较少的情况下BFT的一种解决方案。
PBFT(Practical Byzantine Fault Tolerance)即:实用拜占庭容错算法。该算法是Miguel Castro(卡斯特罗)和Barbara Liskov(利斯科夫)在1999年提出来的,解决了之前拜占庭容错算法效率不高的问题。PBFT将算法复杂度由指数级降低到多项式级,使得在实际系统应用中可以用此算法解决拜占庭容错问题。
关于拜占庭问题,网上也有非常多的解读,这里就不在详述,这里仅给出拜占庭问题算法的结论:
假如节点总数为n,故障节点数为f,当n>3f时才能达成拜占庭协定。即算法在失效节点数量f 关于拜占庭协定的更多信息,可以参考:《拜占庭协定》 安全性指的是集群能够达成正确的共识(即:集群的决策值为正确的输入值),并且集群中所有副本数据满足线性一致性(linearizability)。另外,PBFT算法中,集群通过访问控制来限制失效客户端可能造成的破坏,审核客户端并阻止客户端发起无权执行的操作。 活性指的是系统能在有限的时间内能达成共识。 PBFT算法采用密码学相关的技术(RSA签名算法、消息验证编码和摘要等)确保消息传递过程中无法被篡改和破坏。消息包含了公钥签名(RSA算法)、消息验证编码(MAC)和无碰撞哈希函数生成的消息摘要(message digest)。 客户端(c):向primary发起请求的客户端节点;会触发view change。 主节点(primary):在收到请求后请求分配序号,排好序后广播。 备份节点(replica,也称副本节点):接收广播消息,验证请求合法性,投票,触发view change协议来推举新的主节点。 视图(view):一个view中存在一个主节点和多个副本节点,它描述了一个多副本系统的当前状态。另外,节点是在同一个view上对数据达成共识,不能跨域view。 每个副本节点的状态都包含了服务的整体状态,副本节点上的消息日志(message log)包含了该副本节点接受(accepted)的消息,并且使用一个整数表示副本节点的当前视图编号(记作i)。 1. 简化逻辑 客户端向主节点发送请求 主节点通过广播将请求发送给其他副本 所有副本都执行请求并将结果发回客户端 客户端需要等待f+1个不同副本节点发回相同的结果,作为整个操作的最终结果。 2.流程图 3.算法限定条件 PBFT算法有两个限定条件: 在这两个限定条件下,即使失效的副本节点存在,PBFT算法对所有非失效副本节点的请求执行总顺序达成一致,从而保证安全性。 在每一个View中,首先需要选举一个主节点,例如P节点,其它节点为备份节点,例如B1、B2、B3节点;选举主节点的过程被称之为「View Change」。 4. 主节点计算公式 主节点选举其实由以下公式决定: p = v % |R| v是视图编号,p是主节点编号,|R|是副本集合的个数。 REQUEST 客户端C向主节点P发送 主节点P收到客户端C的 如果验证不通过,则丢弃,否则接受消息,于是进入PRE-PREPARE阶段。 PRE-PREPARE 此阶段中,主节点给收到的消息分配一个编号n,接着广播一条< 从 副本节点收到主节点的< 如果验证不通过,则丢弃,否则接受消息,于是进入PREPARE阶段。 PREPARE 此阶段中,当前副本节点广播一条 主节点和副本节点收到 如果验证不通过,则丢弃,否则接受消息。PREPARE准备阶段完成的条件为:当前节点i将(m,v,n,i)写入消息日志,从2f个不同副本节点收到的与预准备消息一致的准备消息。满足这两个条件后进入COMMIT阶段。 COMMIT 此阶段中,当前节点广播一条 主节点和副本节点收到 如果验证不通过,则丢弃,否则接受消息。COMMIT阶段完成的条件是: 完成COMMIT阶段后,进入REPLY阶段。 REPLY 到达此阶段,说明共识已达成,运行客户端的请求操作o,并返回 如果客户端收到f+1不同节点返回的相同REPLY消息,说明客户端发起的请求已经达成共识,否则如果客户端没有在有限时间内收到足够的回复,客户端将判断是否再次向所有副本节点进行广播请求。为什么客户端收到f+1个不同节点返回相同的REPLY消息,就能认为达成共识了呢?因为失效节点不能超过f,f+1个相同的REPLY消息说明其中至少有一个好节点返回正确的结果了,好节点返回正确的结果,那么就可以认为消息已经得到有效的共识。 如果客户端没有在有限时间内收到回复,请求将向所有副本节点进行广播。如果请求已经在副本节点处理过了,副本就向客户端重发一遍执行结果。如果请求没有在副本节点处理过,该副本节点将把请求转发给主节点。如果主节点没有将该请求进行广播,那么就有认为主节点失效,如果有足够多的副本节点认为主节点失效,则会触发一次视图变更。 另外:根据副本发给客户端的响应为 视图改变由以下两个条件之一触发: View Change由副本发起,它们向其他副本发送IHatePrimary消息以启动一个视图改变。注意View Chage不能由拜占庭节点发起。 副本持续接收IHatePrimary消息,直到遇到下面两个条件之一: 当遇到这两个条件之一时,将会将广播一条 当节点收到2f个有效的VIEW-CHANGE消息后,向其他节点广播 副本节点收到主节点的NEW-VIEW消息,验证有效性,有效的话,进入v+1视图,并且开始O中的PRE-PREPARE消息处理流程。 在上面的流程中我们看到,消息的各个环节都会记录日志,这将占用大量空间,所以当请求执行请求后,需要把之前记录的该请求的信息清除掉。具体过程如下: 每执行完一条请求,该节点会再一次发出广播,就是否可以清除信息在全网达成一致。更好的方案是,执行K条请求后再向全网发起广播,告诉大家它已经将这K条执行完毕;如果大家反馈说这K条我们也执行完毕了,那就可以删除这K条的信息了;接下来再执行K条,完成后再发起一次广播,即每隔K条发起一次全网共识,这个概念叫checkpoint,即每隔K条去征求一下大家的意见,要是获得了大多数的认同(a quorum certificate with 2 f + 1 CHECKPOINT messages (including its own)),就形成了一个 stable checkpoint(记录在第K条的编号)。 这是理想的情况,实际上当副本i向全网发出checkpoint共识后,其他节点可能没有执行完这K条请求,所以副本i不会立即得到响应,它还要继续自己的事情,那这个checkpoint在它那里就不是stable的。这里有一个处理策略:对该副本来说,它的低水位h等于它上一个stable checkpoint的编号,高水位H=h+L(一般我们设置L是K的倍数,例如2倍),这样即使该副本处理速度很快,它处理的请求编号达到高水位H后也得停一停自己的脚步,直到它的stable checkpoint发生变化,它才能继续向前。 集群中各节点间通过心跳监听节点状态,如果leader宕机,那么副本节点将无法收到主节点的心跳,超过一定时间后,副本节点将发起发送IHatePrimary消息给其他节点,以触发View Change。 可以,如流程图中的示例。 主节点分别发给副本节点不同的结果,让集群无法达成共识。当发生这种情况时,副本节点因为无法达成共识,认为主节点作恶,此时可以发起「View Change」流程。 假设客户端输入内容是1,主节点将内容改成2后分别发给所有的副本节点,因为副本节点收到的数据都是一致的,可以达成共识(决策值是2),出现这种情况时,集群是否能感知并保持数据可靠? 集群是可以保持可靠的,原理如下:当客户端发送Request给主节点时带有摘要信息(d),这个摘要在整个共识阶段都会用到,并且被所有节点验证,并且最后REPLY给客户端的时候也会返回此信息。如果整个过程中d一致,那么说明数据是可靠的。如果当客户端收到REPLY中此信息和发送时不一致,则认为数据被篡改了,客户端就会向所有副本发送一条IHatePrimary消息来通知整个不正当的行为,这将导致触发「View Change」。 在视图改变时,消息中将包含视图最近一次提交的消息,这将用来恢复之前正确历史,见View Change部分。 在上面的流程图中,我们可以看到,PBFT使用了三阶段协议(预准备、准备、确认)实现拜占庭协定。预准备和准备两个阶段用来确保同一个视图中请求发送的时序性;准备和确认两个阶段用来确保在不同的视图之间的确认请求是严格排序的。 预准备阶段给请求分配了一个序号n,准备阶段如果验证通过,那么这个消息将持久化下来。这可以确保其他节点中持久化下来的消息顺序与主节点一直,即实现同一个视图内的顺序性。 消息经过准备、确认阶段后,说明消息已经达成共识了,并且已经持久化下来了,消息持久化后,顺序也就确定了;即便此时发生了view change,也可以保证消息可靠。 需要注意的是,这里消息的顺序由主节点接受消息分配序号n为准,并不以客户端请求顺序为准,因为客户端有可能后发出的请求,主节点先收到。 《区块链结束指南》 《PBFT算法》 https://www.jianshu.com/p/2383c7841d41 深入浅出PBFT算法原理 https://blog.csdn.net/jfkidear/article/details/81275974 PBFT实用拜占庭容错算法深入详解 https://blog.csdn.net/TurkeyCock/article/details/81672759 深入浅出PBFT算法原理 https://blog.csdn.net/jfkidear/article/details/81275974 区块链核心技术:拜占庭共识算法之PBFT http://8btc.com/article-3756-1.html 3. PBFT算法基础
1) PBFT算法
2) 算法流程介绍
View Change
1.触发条件
2. VIEW-CHANGE的条件
3. NEW-VIEW的条件
垃圾清理
算法论证
主节点宕机,集群是否能正产工作?
如果副本节点宕机,集群是否能够正常工作?
如果主节点伪造请求内容,集群数据是否能继续保持可靠?
View Change后,之前的数据是否会丢失?
所有节点上数据的顺序是否能保持一致?
参考文档