PBFT协议的理解
Posted 落霞与孤鹜亓飞
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PBFT协议的理解相关的知识,希望对你有一定的参考价值。
PBFT协议的理解
PBFT 是一种分布式节点间的状态复制协议,在总节点数为n的情况下,它能容错不超过 ⌊ n − 1 3 ⌋ \\lfloor \\frac n-13 \\rfloor ⌊3n−1⌋ 的拜占庭节点,使得大多数的状态复制机(replica)保持一致的状态。保持分布式节点之间的系统状态的一致性,只需要做到如下两点即可:
- 系统中节点就 client 的 request 分配一个唯一的编号,并且对于系统中任意两个非故障节点,同一个 request 对应相同并且唯一的编号.
- 系统中的节点有序的执行 request ,保证任意两个非故障节点的系统状态一致.
PBFT 协议通过完成上述两个要求从而实现了系统的一致性.在介绍PBFT协议的具体内容前,应该首先明确该协议的系统模型.
一、 系统模型
- 网络是异步的分布式网络,网络中节点之间会出现信息发送失败, 延迟,重复发送,甚至无序的情况.
- 系统中可能有一个强力的恶意节点联合其他节点,故意导致发送信息出现延迟或者故意延迟正确的节点发送的信息,但是恶意节点不能无限延迟.
- 恶意节点无法伪造诚实节点的签名,而恶意节点之间可能串通,可以相互伪造签名.
- 恶意节点无法通过一条消息的摘要计算出消息体.
- 恶意节点无法针对一个消息m,找到另外一个对应的消息m’使得它们的摘要相同.(摘要是对消息求hash).
- 系统中总结点数为n的时候, PBFT协议最多容忍 ⌊ n − 1 3 ⌋ \\lfloor \\fracn-13\\rfloor ⌊3n−1⌋ 的拜占庭节点.
二、 系统角色
- Replica, 状态复制机,所有的 replica 都会执行 PBFT 协议并保持系统状态一致性.
- Primary, 在 PBFT 协议中,每个 primary 都有一个任期,称之为 view, 在一个 view 中,只有一个 replica 会被称为 primary,可以理解为leader.
- Backup,除了primary 以外的 replica 都称之为backup.
- client, 向 primary 发送 request 请求服务的客户端.
三、PBFT协议简述
PBFT 协议以状态机复制的形式展示,将服务建立为在分布式环境下跨机器之间进行数据复制的状态机模型. 每一个状态复制机都会维护一个当前的服务状态,PBFT 协议可以保证所有非拜占庭节点的系统状态全部相同, 而这些状态复制机执行客户的请求后转入下一个状态,并将执行结果反馈给 client.
在PBFT协议中,主要有三个身份,client,primary 和 backup。replica 中有一个主节点,称之为primary, 其他 replica 称之为backup. client向 primary 发出操作请求, primary 把 client 的请求发送给所有 backup , primary和其他backup通过按照PBFT协议对操作进行响应,然后将执行结果返回给client.
PBFT论文中默认client在收到前一个 request 的执行结果之前不会发送下一个 request .每一个primary在其任期内对应一个view, 下一任primary上任时,view自动加1. 一个view中只有一个primary.
整个协议的整体流程如下:
- client向 primary发送一个 request .
- primary向其他备份节点广播 request .
- 所有节点执行 request 并且向client返回执行结果
- client 从f+1个不同的节点处得到相同的执行结果,则认为执行结果可靠并且接受这个结果.
PBFT 细节
再次强调的是,在该协议中,假定拜占庭节点的数目最多为 f f f 个, 而全体节点的数目为 n = 3 f + 1 n = 3f+1 n=3f+1.
1. client 发出 request
client 向 primary 发出一个 request , request 的具体形式如下:
< R E Q U E S T , o , t , c > σ i <REQUEST, o,t,c>_\\sigma i <REQUEST,o,t,c>σi
o o o 表示 operation,即具体执行的操作, t 表示 timestamp, 之所以需要加上时间戳, 是在一个client在发出多次相同operation的时候, primary 用 timestamp 区分这些命令, c 表示 client 编号, σ i \\sigma i σi 表示 client i i i 将这些信息进行签名,以证实自身合法的身份.
注意: 如果 client 将 request 发送给了 backup 节点,那么该节点会将 client 的 request 转发给 primary.
2. pre-prepare 阶段
为了确保所有的非拜占庭节点保持一致的状态, primary 需要对 request 分配一个序号(sequence number),如果全体 replica 能够对每一个 request 的序号达成一致,那么就能达成整个系统服务状态的一致性.
2.1 Primary 收到 Request
收到一个 request 时,primary会检查 request 的合法性,首先检查客户端的签名是否正确, 如果不正确,则拒绝执行后续步骤;
如果正确,则给 request分配一个唯一的序列号n,然后向其他 backup 广播一条 p r e − p r e p a r e pre-prepare pre−prepare (预准备)消息,形式如下:
< < P R E − P R E P A R E , v , n , d > σ p , m > \\left < \\left < PRE-PREPARE, v, n, d \\right > _\\sigma p, m \\right > ⟨⟨PRE−PREPARE,v,n,d⟩σp,m⟩
v v v是当前view序号, n n n是 primary 为 request 分配的序列号, d是 request 的摘要, m 代表 client的 request 信息, σ p \\sigma_p σp 是 primary 的签名.
2.2 Backup 收到 pre-prepare消息
backup收到pre-prepare消息时,会验证如下消息:
- request 的签名是否正确, 确保client的签名不是伪造的.
- view的序列号与当前backup当前的view序列号相等.
- backup确定当前 view下,序号n没有分配给另外一个不同的 request .
- n应该在某个范围[h, H].
如果上述条件全部符合,则backup接受这个 p r e − p r e p a r e pre-prepare pre−prepare 消息, 并且进入 prepare 阶段.
3. prepare阶段
3.1 广播 Prepare 消息
对于 Prepare 阶段做一下解释,节点收到 pre-prepare 消息之后,相当于收到了一个来自 primary 的提议,但是节点不清楚其他节点是否收到了同样的 pre-prepare 信息,因为 primary 节点可能是恶意节点,它可能向其 backup 发送不同的 pre-prepare 信息。因此,每个节点向网络中其他节点广播 prepare 信息进行同步,其含义是告诉其他节点:本节点收到了来自 primary 的一条 pre-prepare 信息。
backup 在 prepare 阶段,向本地的log中插入 p r e − p r e p a r e pre-prepare pre−prepare 消息以及自身的 p r e p a r e prepare prepare 消息 ,并向其他 backup(包括primary)广播一条prepare消息,prepare消息形式如下:
< P R E P A R E , v , n , d , i > σ i \\left < PREPARE, v, n, d,i\\right >_\\sigma i ⟨PREPARE,v,n,d,i⟩σi
其中 i i i 是 backup 的编号, σ i \\sigma_i σi 表示节点 i i i 的签名, backup(包括primary)收到来自其他节点的prepare消息时,会验证如下信息:
- view 序号和节点自身的 view序号相同.
- n在 [h,H] 范围内.
- d 和 pre-prepare阶段消息的摘要相同。
如果上述验证通过,则将这条信息插入本地log.
如果一个节点收到 2 f + 1 2f+1 2f+1 (包括自身的)相同的 p r e p a r e prepare prepare 消息,并且这些消息与之前收到的 p r e − p r e p a r e pre-prepare pre−prepare 消息的 m , v , n m, v, n m,v,n相同, 则认为 prepared(m, v, n, i) 为真,并将 prepared(m, v, n, i) 插入log, 然后进入commit 阶段.
3.2 pre-prepare 和 prepare 阶段的作用
p r e p a r e d ( m , v , n , i ) prepared(m, v, n, i) prepared(m,v,n,i) 的主要作用就是,确保在一个 view 中,一个 request 唯一的对应一个序列号 n。因为 p r e p a r e d ( m , v , n , i ) prepared(m, v, n, i) prepared(m,v,n,i)为真的条件是,有 2 f + 1 2f+1 2f+1个节点广播信息验证了 m , v , n m, v, n m,v,n的一一对应关系.证明如下:
- 2 f + 1 2f+1 2f+1 个一致的 p r e p a r e d ( m , v , n , i ) prepared(m, v, n, i) prepared(m,v,n,i)消息中,最多有 f f f 个拜占庭节点的 prepared 消息, 至少有 f + 1 f+1 f+1 个诚实节点的 p r e p a r e d ( m , v , n , i ) prepared(m, v, n, i) prepared(m,v,n,i) 消息。
- 剩余的 f f f 个诚实节点由于收到了错误的prepare 消息,它们互相广播 p r e p a r e d ( m ′ , v , n , i ) prepared(m', v, n, i) prepared(m′,v,n,i) 。由于存在 f f f 个拜占庭节点,这些节点可能广播了 f f f 个 p r e p a r e d ( m , v , n , i ) prepared(m, v, n, i) prepared(m,v,n,i) 消息,又作恶的广播了 f f f 个 p r e p a r e d ( m ′ , v , n , i ) prepared(m', v, n, i) prepared(m′,v,n,i) 消息,此时也只能存在 2 f 2f 2f 个 p r e p a r e d ( m ′ , v , n , i ) prepared(m', v, n, i) prepared(m′,v,n,i) 消息,这不足以达成一致 (达成一致的要求是至少 2 f + 1 2f+1 2f+1个相同的prepared消息)。
综上所述, pre-prepare和prepare两个阶段保证了在同一个 view下,n 和 request 的一一对应关系. 这一步骤带来的好处是,即使发生了 view change,此时最多 f 个节点出错,那么剩余的 2f+1 个节点至少有一个节点保留有最新的 2f+1 个prepare信息。当新的 leader 产生时,最新的 2f+1 个 prepare 消息仍然会被执行,保证了系统的安全性。
4. commit阶段
4.1 广播 commit 消息
对 commit 消息再作下解释,进入 commit 阶段的前提是节点收到了 2f+1 个合法的prepare消息,然而在异步环境下,节点不知道其他节点是否也收到了 2f+1 个prepare 消息,所以,节点向其他节点广播一条 commit 消息,其目的是告诉其他节点:本节点已经收到了 2f+1 个prepare 消息。
backup 进入commit 阶段时, 向其他 backup (包括 primary) 广播一条 commit 消息,具体形式如下:
< C O M M I T , v , n , D ( m ) , i > σ i \\left < COMMIT, v, n, D(m), i \\right >_\\sigma i ⟨COMMIT,v,n,D(m),i⟩σi
其他replica收到commit消息后,验证如下信息:
- 节点 i i i 的签名正确.
- view 的序号和本地 view 序号相同.
- n在[h,H]范围内.
如果上述验证全部通过,节点将该commit信息插入本地log. 如果节点 i i i满足两个条件:
- 节点 i i i 的 p r e p a r e ( m , n , v , i ) prepare(m, n, v,i) prepare(m,n,v,i) 为真,即节点 i i i 也进入commi阶段.
- 节点 i i i 收到 2 f + 1 2f+1 2f+1 (包括自身)一致的 commit 信息, 并且它们与本地的 pre-prepare的 m , v , n m, v, n m,v,n全部相同.
则作出定义 c o m m i t t e d − l o c a l ( m , n , v , i ) committed-local(m, n, v, i) committed−local(m,n,v,i)为真的判断。
4.2 执行 commit
c o m m i t t e d − l o c a l ( m , n , v , i ) committed-local(m, n, v, i) committed−local(m共识协议——RAFT&PBFT