共识算法-PBFT

2023-11-16

 

  • 简介

1. PBFT简介

BFT(Byzantine Fault Tolerance)是区块链共识算法中需要解决的一个核心问题。例如,公有链网络中,比特币和以太访中用的是POW,EOS用的是DPOS。PBFT一般用于联盟链场景中,它是共识节点较少的情况下BFT的一种解决方案。

PBFT(Practical Byzantine Fault Tolerance)即:实用拜占庭容错算法。该算法是Miguel Castro(卡斯特罗)和Barbara Liskov(利斯科夫)在1999年提出来的,解决了之前拜占庭容错算法效率不高的问题。PBFT将算法复杂度由指数级降低到多项式级,使得在实际系统应用中可以用此算法解决拜占庭容错问题。

2. 拜占庭协定

关于拜占庭问题,网上也有非常多的解读,这里就不在详述,这里仅给出拜占庭问题算法的结论:

假如节点总数为n,故障节点数为f,当n>3f时才能达成拜占庭协定。即算法在失效节点数量f<n/3时,可以保证集群的安全性(safety)和活性(liveness)。

关于拜占庭协定的更多信息,可以参考:《拜占庭协定》

安全性指的是集群能够达成正确的共识(即:集群的决策值为正确的输入值),并且集群中所有副本数据满足线性一致性(linearizability)。另外,PBFT算法中,集群通过访问控制来限制失效客户端可能造成的破坏,审核客户端并阻止客户端发起无权执行的操作。

活性指的是系统能在有限的时间内能达成共识。

 

3. PBFT算法基础

PBFT算法采用密码学相关的技术(RSA签名算法、消息验证编码和摘要等)确保消息传递过程中无法被篡改和破坏。消息包含了公钥签名(RSA算法)、消息验证编码(MAC)和无碰撞哈希函数生成的消息摘要(message digest)。

 

1) PBFT算法

  • 算法设计的角色

客户端(c):向primary发起请求的客户端节点;会触发view change。

主节点(primary):在收到请求后请求分配序号,排好序后广播。

备份节点(replica,也称副本节点):接收广播消息,验证请求合法性,投票,触发view change协议来推举新的主节点。

视图(view):一个view中存在一个主节点和多个副本节点,它描述了一个多副本系统的当前状态。另外,节点是在同一个view上对数据达成共识,不能跨域view。

每个副本节点的状态都包含了服务的整体状态,副本节点上的消息日志(message log)包含了该副本节点接受(accepted)的消息,并且使用一个整数表示副本节点的当前视图编号(记作i)。

2) 算法流程介绍

  • 算法流程

1. 简化逻辑

客户端向主节点发送请求 

主节点通过广播将请求发送给其他副本 

所有副本都执行请求并将结果发回客户端 

客户端需要等待f+1个不同副本节点发回相同的结果,作为整个操作的最终结果。

2.流程图

 

3.算法限定条件

PBFT算法有两个限定条件:

  • 所有节点必须是确定性的,即:在给定状态和参数相同的情况下,操作执行的结果必须相同
  • 所有节点必须从相同的状态开始执行

在这两个限定条件下,即使失效的副本节点存在,PBFT算法对所有非失效副本节点的请求执行总顺序达成一致,从而保证安全性。

在每一个View中,首先需要选举一个主节点,例如P节点,其它节点为备份节点,例如B1、B2、B3节点;选举主节点的过程被称之为「View Change」。

4. 主节点计算公式

主节点选举其实由以下公式决定:

p = v % |R|

v是视图编号,p是主节点编号,|R|是副本集合的个数。

REQUEST

客户端C向主节点P发送<REQUEST, o, t, c>请求。o指请求的具体操作;t指请求时客户端追加的时间戳;c指客户端标识;REQUEST包含消息内容m,以及消息摘要d。客户端C发出请求的时间戳是顺序排列的,后续发出的请求比早先发出的请求拥有更高的时间戳。

主节点P收到客户端C的<REQUEST, o, t, c>请求,需要进行以下校验:

  • 客户端请求REQUEST中消息签名是否正确。

如果验证不通过,则丢弃,否则接受消息,于是进入PRE-PREPARE阶段。

PRE-PREPARE

此阶段中,主节点给收到的消息分配一个编号n,接着广播一条<<PRE-PREPARE, v, n, d>,  m>消息给其他副本节点,并将请求记录到本地历史(log)中。说明:n主要用于对所有客户端的请求进行排序;v指视图编号;m指消息内容;d指消息摘要。

从<PRE-PREPARE, v, n, d>可以看出,请求消息本身内容(m)是不包含在预准备的消息里面的,这样就能使预准备消息足够小。预准备消息的目的是作为一种证明,确定该请求是在视图v中被赋予了序号n,从而在视图变更的过程中可以追索。

副本节点收到主节点的<<PRE-PREPARE, v, n, d>,  m>消息,需要进行以下校验:

  • REQUEST和PRE-PREPARE消息中签名是否正确。
  • 当前视图编号是v。
  • 该节点从未在视图v中接受过序号为n但是摘要d不同的消息m。
  • m的消息摘要与消息中d是否一致。
  • 判断n是否在区间[h, H]内

如果验证不通过,则丢弃,否则接受消息,于是进入PREPARE阶段。

PREPARE

此阶段中,当前副本节点广播一条<PREPARE, v, n, d, i>消息,并且将预准备消息和准备消息写入自己的消息日志。i是当前节点编号。

主节点和副本节点收到<PREPARE, v, n, d, i>消息,需要进行以下校验 :

  • 消息签名是否正确。
  • 判断n是否在区间[h, H]内。
  • d是否和当前已收到PRE-PPREPARE中的d相同

如果验证不通过,则丢弃,否则接受消息。PREPARE准备阶段完成的条件为:当前节点i将(m,v,n,i)写入消息日志,从2f个不同副本节点收到的与预准备消息一致的准备消息。满足这两个条件后进入COMMIT阶段。

COMMIT

此阶段中,当前节点广播一条<COMMIT, v, n, d, i>消息。

主节点和副本节点收到<COMMIT, v, n, d, i>消息,需要进行以下校验:

  • COMMIT消息签名是否正确。
  • 当前副本节点是否已经收到了同一视图v下的n。
  • 计算m的摘要,并判断和d是否一致。
  • n是否在区间[h, H]内。

如果验证不通过,则丢弃,否则接受消息。COMMIT阶段完成的条件是:

  • 任意f+1个正常副本节点集合中prepared(m,v,n,i)为真,这一条确保committed(m,v,n)为真。
  • prepared(m,v,n,i)为真,并且节点i已经接受了2f+1个确认(包括自身在内)与预准备一致的消息。这一条确保committed-local(m,v,n,i)为真。确认与预准备消息一致的条件是具有相同的视图编号、消息序号和消息摘要。

完成COMMIT阶段后,进入REPLY阶段。

REPLY

到达此阶段,说明共识已达成,运行客户端的请求操作o,并返回<REPLY, v, t, c, i, r>给客户端。其中v是视图编号,t是时间戳,i是副本的编号,r是请求执行的结果。

如果客户端收到f+1不同节点返回的相同REPLY消息,说明客户端发起的请求已经达成共识,否则如果客户端没有在有限时间内收到足够的回复,客户端将判断是否再次向所有副本节点进行广播请求。为什么客户端收到f+1个不同节点返回相同的REPLY消息,就能认为达成共识了呢?因为失效节点不能超过f,f+1个相同的REPLY消息说明其中至少有一个好节点返回正确的结果了,好节点返回正确的结果,那么就可以认为消息已经得到有效的共识。

如果客户端没有在有限时间内收到回复,请求将向所有副本节点进行广播。如果请求已经在副本节点处理过了,副本就向客户端重发一遍执行结果。如果请求没有在副本节点处理过,该副本节点将把请求转发给主节点。如果主节点没有将该请求进行广播,那么就有认为主节点失效,如果有足够多的副本节点认为主节点失效,则会触发一次视图变更。

另外:根据副本发给客户端的响应为<REPLY,v,t,c,i,r>,客户端通过p = v % |R|可以推到出主节点的编号。以后客户端就能够通过点对点消息向它自己认为的主节点发送请求,然后主节点自动将该请求向所有备份节点进行广播。

 

View Change

1.触发条件

视图改变由以下两个条件之一触发:

  • 副本从一个客户得知,主节点存在不正当行为(例如:伪造数据等)
  • 副本不能收到主节点发出的消息

View Change由副本发起,它们向其他副本发送IHatePrimary消息以启动一个视图改变。注意View Chage不能由拜占庭节点发起。

2. VIEW-CHANGE的条件

副本持续接收IHatePrimary消息,直到遇到下面两个条件之一:

  • 当接收到超过f+1个IHatePrimary消息
  • 如果收到了其他节点的ViewChange消息。

当遇到这两个条件之一时,将会将广播一条<VIEW-CHANGE, v+1, n, C, P, i>消息,n是最新的stable CheckPoint的编号,C是2f+1验证过的CheckPoint消息集合,P是当前副本节点未完成的请求的PRE-PREPARE和PREPARE消息集合。

3. NEW-VIEW的条件

当节点收到2f个有效的VIEW-CHANGE消息后,向其他节点广播<NEW-VIEW, v+1, V, O>消息。V是有效的VIEW-CHANGE消息集合。O是主节点重新发起的未经完成的PRE-PREPARE消息集合。PRE-PREPARE消息集合的选取规则:

  • 选取V中最小的stable CheckPoint编号min-s,选取V中prepare消息的最大编号max-s。
  • 在min-s和max-s之间,如果存在P消息集合,则创建<<PRE-PREPARE, v+1, n, d>, m>消息。否则创建一个空的PRE-PREPARE消息,即:<<PRE-PREPARE, v+1, n, d(null)>, m(null)>, m(null)空消息,d(null)空消息摘要。

副本节点收到主节点的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后,之前的数据是否会丢失?

在视图改变时,消息中将包含视图最近一次提交的消息,这将用来恢复之前正确历史,见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

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

共识算法-PBFT 的相关文章

  • leetcode 1604. 警告一小时内使用相同员工卡大于等于三次的人

    力扣公司的员工都使用员工卡来开办公室的门 每当一个员工使用一次他的员工卡 安保系统会记录下员工的名字和使用时间 如果一个员工在一小时时间内使用员工卡的次数大于等于三次 这个系统会自动发布一个 警告 给你字符串数组 keyName 和 key
  • C~运算符

    运算符是一种告诉编译器执行特定的数学或逻辑操作的符号 C 语言提供了以下类型的运算符 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 杂项运算符 算术运算符 下表显示了 C 语言支持的所有算术运算符 假设变量 A 的值为 10 变

随机推荐

  • Windows10安装Docker(基于WSL2,包含WSL2安装教程)

    WSL2 wsl是windows自带的功能 只需要开启Windows功能即可安装子系统 可以通过以下命令获取发行版名字 wsl list online 通过以下命令安装 wsl install d 发行版名字 如 wsl install d
  • android input 机制源码分析

    具体文字说明请参考 http blog csdn net luoshengyang article details 6882903
  • 2018年AI趋势盘点(02)

    善用智能之道 请您点击上方蓝色字体 欢迎关注 九三智能控 懒人阅读 2017年被定义为AI的史诗年 九三觉得17年确实引爆了AI 同时泡沫也存在不少 18年的AI将更加务实技术更加接近真实场景 可以确认的一点是 认知决策能力的升级将对所有行
  • WiFi探针的工作原理及采集的数据?

    WiFi探针在商业 公共安全领域的大放异彩 更多的人想了解什么是WiFi探针 WiFi探针是怎么工作的 WiFi探针的工作原理 要深入了解WiFi探针技术 首先先认识WiFi使用的网络协议 WiFi采用的是IEEE802 11协议集 此协议
  • element对上传组件二次封装,vue上传下载组件的实现

    前言 对element的上传组件进行二次封装 让他可以实现上传下载功能 实现效果 手动上传 不是自动 选中文件后可上传 也可清空选中文件 单个删除也是可以的 实现步骤 1 封装好的 uploadAndDown vue源码 引入就好
  • Linux 入门常用命令(ZT)

    1 Linux进入与退出系统 进入Linux系统 必须要输入用户的账号 在系统安装过程中可以创建以下两种帐号 1 root 超级用户帐号 系统管理员 使用这个帐号可以在系统中做任何事情 2 普通用户 这个帐号供普通用户使用 可以进行有限的操
  • MATLAB——求冲激响应和阶跃响应

    题目 已知一个RLC串联振荡电路系统函数为 其中L 22mH C 2000pF R 100 求其时域的冲激响应和阶跃响应 代码解释 这段代码定义了三个变量 电感L 电容C和电阻R 然后 定义了两个数组a和b 它们是差分方程的系数 接下来 使
  • 拿不到年薪25W全额退款

    速报 2023年经济下行趋势明显 毕业生出路在哪儿 今年 毕业人数将达到1158万 导致很多公司招聘非常谨慎 要求也变得非常更高 别说offer 现在出门找个实习都难 大学四年我都学了啥 是啊 现在咋找实习丰富简历啊 今年毕业的我该怎么办
  • selenium自动处理验证码

    自动化测试中的验证码处理方法小总结 转自 Selenium中文论坛 gt Selenium RC gt 转 自动化测试中的验证码处理方法小总结 原作者 yanpingsha 目前 不少网站在用户登录 用户提交信息等登录和输入的页面上使用了验
  • kubernetes ——网络存储nfs

    kubernetes 网络存储nfs 一 共享的机器上安装nfs 1 yum y insstall nfs utils 2 mkdir p etc exports 3 vi etc exports ifs kubernetes rw no
  • 恶意代码分析实战——Lab03-01.exe基础动态分析篇

    恶意代码分析实战 Lab03 01 exe基础动态分析篇 1 实验目的 综合运用各种分析工具 分析Lab03 01 exe的基本信息 并推测其功能 2 实验环境 硬件 软件 VMware虚拟机 winxp 硬件 处理器Intel Core
  • 浅谈Class.forName()在JDBC中的作用

    目录 1 Class forName 有什么作用呢 2 为什么不直接new 3 为什么删除Class forName com mysql jdbc Driver 还是可以运行 JDBC是Bridge模式的典型应用 DriverManager
  • 怎么在matlab项目中找到某个变量或函数(必行)

    怎么在matlab项目中找到某个变量或函数 必行 1 首先将当前文件路径设置到项目所在文件夹 2 单击 编辑器 下的 查找文件 功能键 3 在 查找包含以下文本的文件 对话框内输入你要搜索的文本 并在 仅包括以下文件类型 对话框选择相应类型
  • cocos2d-x 卡牌翻牌效果的实现

    cocos2d x 卡牌翻牌效果的实现 2012年07月25日 综合 共 3085字 字号 小 中 大 评论关闭 猴子原创 欢迎转载 转载请注明 转载自Cocos2D开发网 Cocos2Dev com 谢谢 原文地址 http www co
  • Java8 HashMap源码解析(内部存储结构及实现方式详解)

    HashMap是我们日常使用的非常多的java集合框架下的一员 它是基于哈希表的 Map 接口的实现 以key value的形式存在 我们可以通过key快速地存 取value 本文以基于 JDK1 8 为源码 简单梳理了一下hashMap的
  • 西瓜书(周志华):什么是版本空间以及如何求取版本空间

    下面是自己结合百度的资料来理解的一些比较通俗的说法 假设空间 属性所有可能取值组成的可能的样本 版本空间 与已知数据集一致的所有假设的子集集合 绿色加号代表正类样本 红色小圈代表负类样本 GB 是最大泛化正假设边界 maximally Ge
  • 【管理篇 / 登录】❀ 01. 网线连接登录 ❀ FortiGate 防火墙

    简介 当我们拿到新的防火墙的时候 首先要做的就是将电脑快速 简便的连接到防火墙 登录并进行管理 而最方便的连接方式就是用网线了 这里介绍的是最简单的飞塔防火墙物理连接以及浏览器登录访问 桌面式防火墙网线连接 飞塔防火墙产品线里低端的桌面式防
  • 对象转换为JSON数据格式&使用JQuery获取数据

    将对象转换为JSON数据格式 我们需要json lib 2 3 jdk15 jar架包 当然还需要其它架包 来实现对象转JSON数据格式 此架包提供两个类来实现转换 JSONObject fromObject object 将对象转换成js
  • Python爬虫编程实践--re bs及xpath

    Beautiful Soup库入门 Beautiful Soup 是一个HTML XML 的解析器 主要用于解析和提取 HTML XML 数据 它基于HTML DOM 的 会载入整个文档 解析整个DOM树 因此时间和内存开销都会大很多 所以
  • 共识算法-PBFT

    简介 1 PBFT简介 BFT Byzantine Fault Tolerance 是区块链共识算法中需要解决的一个核心问题 例如 公有链网络中 比特币和以太访中用的是POW EOS用的是DPOS PBFT一般用于联盟链场景中 它是共识节点