PBFT(实用拜占庭容错算法)原理及代码分析(go语言)

PBFT原理及go语言代码实现

PBFT

前提

客户端

正常情况下的操作

预准备阶段

准备阶段

确认阶段

垃圾回收

视图切换

算法的安全性与活性

前提

在pbft算法中,用R表示副本节点集合,每个副本用{0,...,|R|-1}来表示。假设|R|=3f+1,f为出错节点的数量。
副本节点通过一系列称为“视图”(view)的配置来移动。在每一个视图中,包含一个primary(主节点),其他做为backups(备份节点)。算法的步骤如下:
step1:客户端向主节点发送请求以调用服务器操作。
step2:主节点向备份节点广播该请求。
step3:副本节点执行该请求并回复到客户端。
step4:客户端收到来自不同副本节点的f+1个相同的结果。
由于pbft算法是基于状态机复制的算法,因此副本节点必须满足以下两点:
(1)它们必须是确定性的。(在给定状态与给定参数集下,执行操作后产生的结果是相同的)
(2)它们必须以相同的状态开始。

客户端

在客户端执行的操作有两个:
客户端向主节点发送请求信息<REQUEST,o,t,c> 其中,o为请求状态复制机的操作,t为时间戳。
副本节点向客户端返回回复信息<REPLY,v,t,c,i,r> 其中,v为当前的视图编号,t为时间戳,i为副本节点编号,r为执行请求后的操作结果。

正常情况下的操作

“三阶段协议”
当主节点p收到客户端请求m,它将会启动三阶段协议自动广播请求信息给其他副本节点。三阶段协议分别是“pre-prepare预准备阶段”“prepare准备阶段”“commit确认阶段”

pre-prepare预准备阶段

预准备阶段主节点向所有的副本节点发送pre-prepare消息,<<PRE-PREPARE,v,n,d>,m>
但这个消息要满足以下四点,副本节点才会接收:
(1)请求消息m和pre-prepare消息的数字签名都是正确的,且d是消息m的摘要。
(2)它存在于当前的视图v中。
(3)该备份节点从未在当前视图v中接收过包含不同摘要的序号为n的预准备消息。
(4)预准备消息中的序号n位于消息量下限h和上限H之间。

prepare准备阶段

当备份节点i接收了预准备消息,它将进入准备阶段,将准备消息<PREPARE,v,n,d,i>发送给其他副本节点,并将预准备消息和准备消息都写入消息日志中。
同上,prepare消息满足以下三个要求,才会被其他副本节点接收:
(1)准备消息的签名是正确的。
(2)视图编号与副本节点当前的视图编号一致。
(3)准备消息的序列号位于消息量下限h和上限H之间。
准备阶段完成的标志,有以下内容插入到日志中就代表完成:
(1)请求消息m
(2)在视图v中,序列号为n的请求m的预准备消息
(3)2f个与预准备消息匹配的且来自不同备份节点的准备消息。(检查视图编号、序列号、消息摘要,如果都一致则代表匹配)

在PBFT算法中,pre-prepare和prepare阶段保证了非故障副本节点对在同一个视图中的请求排序达成一致。

commit确认阶段

准备阶段完成进入确认阶段,同上,副本节点接收确认信息<COMMIT,v,n,D(m),i>,确认消息也要满足以下条件:
(1)确认消息的签名是正确的。
(2)视图编号与副本节点当前的视图编号一致。
(3)确认消息的序列号位于消息量下限h和上限H之间。
PBFT算法流程图

垃圾回收

为了保证系统的安全性,副本节点在删除自己的消息日志前,需确保至少f+1个正常副本节点执行了消息所对应的请求,并且在视图变更时向其他副本节点证明。另外,如果某些副本节点错过了部分消息,且这些消息已经被非故障副本节点删除了,则需要通过转移全部或部分服务状态来更新,因此在执行每个阶段后,副本节点需要对状态的正确性进行证明。
因此在PBFT中定义了检查点协议checkpoint,如果已经进行证明了,则转换成stable checkout 。当一个副本节点i生成了"checkpoint",它向其他副本节点广播<CHECKPOINT,n,d,i>消息。每个副本节点在日志中收集checkpoint信息,直到收集到2f+1个来自不同副本节点的具有相同序列号n和摘要d的检查点消息,就代表已经进行证明了。
另外,checkpoint协议还可以用来更新水线的高低值h和H,即代表了可以被接收的消息量大小。

视图变更

视图变更机制保证了系统的活性。
当在视图v中,副本节点i计时器超时后,则会触发view-change,视图由v变成v+1,并且停止接收消息(检查点协议、视图变更、新消息视图除外),并向所有副本节点播报<VIEW-CHANGE,v+1,n,c,p,i>,当视图编号为v+1中的主节点从其他副本节点收到2f个有效的view-change消息后,则广播<NEW-VIEW,v+1,v,o>。其中v是有效的VIEW-CHANGE消息集合,o是主节点重新发起的未经完成的pre-prepare消息集合,主节点将o集合中的消息放入日志中。接下来就进入到视图v+1中,并开始o集合中的pre-prepare及后续处理流程。

算法的正确性

在PBFT中,视图变更和垃圾回收机制保证了算法的安全性safety活性liveness

代码实现

首先定义消息类型结构体

//请求消息结构体
type RequestMsg struct{
   
          TimeStamp  int64  'json:"timestamp"'
          ClientID         string  'json:"clientID"'
          Operation     string  'json:"operation"'
          SequenceID int64   'json:"sequenceID"'
}
//回复消息结构体
type ReplyMsg struct{
   
          ViewID            int64  'json:"viewID"'
          TimeStamp  int64  'json:"timestamp"'
          ClientID         string  'json:"clientID"'
          NodeID           string  'json:"nodeID"'
          Result             string  'json:"result"'
}
//预准备消息结构体
type PrePrepareMsg struct{
   
          ViewID            int64  'json:"viewID"'
          SequenceID int64   'json:"sequenceID"'
          Digest             string  'json:"digest"'
         RequestMsg *RequestMsg 'json:"requestMsg"'
}
//投票消息结构体<
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值