论文链接:https://pmg.csail.mit.edu/papers/osdi99.pdf
BFT (Byzantine Fault Tolerant) 拜占庭容错,指的是在一个分布式系统当中,在有节点可能出现任意行为(包括但不限于崩溃、发送错误数据、出现恶意行为等)的情况下,仍可以正常运行即达成共识。
PBFT 可以保证在一个大小为 $3f+1$ 的分布式网络下,容忍至多 $f$ 个节点的拜占庭错误。
见原文,不赘述。
见:https://dinhtta.github.io/pbft/
Network Failure Model
Byzantine fault tolerant protocols tolerate at most $f$ Byzantine failures. In a distributed system, however, there are two types of failures: node and network. It is important to distinguish them, especially since they determine guarantees about the protocol’s safety and liveness.
Node failure means a node (or server, peer, entity, etc.) behaves arbitrarily. This captures the strongest adversary model. A network failure refers to network partitions which can last for an unbounded amount of time. It can be quantified as the number of nodes being isolated from the rest of the network, although they can still communicate with each other.
Given this distinction, what are being counted toward $f$? In PBFT
- $f$ refers to node failures. The protocol guarantees safety upto $f$ node failures. Safety is independent of network failure. That is, even if the network is severely partition, namely more than $f$ nodes are isolated (but across all partitions there are still fewer than $f$ node failures), the protocol is still safe.
- However, liveness is only guaranteed with fewer than $f$ total failures, i.e. counting both node and network failures. This means at least $2f+1$ nodes must be reachable.
Note that safety being independent of network failures is a strong guarantee, and it is common in most variants of PBFT. Not until Liu et al. recent work, namely XFT, is it relaxed in a way that separates out node and network failures.
要回答上面的大问题首先要理解我们想要 Preprepare + Prepare Phase 保证什么。论文 Section 4.2 已经回答了这个问题,即
$$
prepared(m, v, n, i) \Rightarrow \lnot prepared(m', v, n, j), \forall i,j,m,m', s.t. D(m') \neq D(m)
$$
即我们要保证在同一个 view 内,每一个 sequence number 只对应唯一一个 prepared message。
首先我们可以构造一个如果只有 $2f$ 个 matching 就能打破上述原则的反例。
接下来我们尝试用 Quorum 的思想来证明。使用反证法:如果每个节点都有 $2f+1$ 个 matching,但是最后仍然出现了两个 Replica $a \neq b$,使得
$$
prepared(m, v, n, a) \land prepared(m', v, n, b) \land D(m) \neq D(m')
$$
根据题设,有 $2f+1$ 个节点向 $a$ 发送了 $\langle Prepare, v, n, d, i \rangle _{\sigma_i}$,有 $2f+1$ 个节点向 $b$ 发送了 $\langle Prepare, v, n, d', i \rangle _{\sigma_i}$。根据容斥原理,至少有
$$
2 \times (2f + 1) - (3f+1) = f + 1
$$
个节点向 $a, b$ 分别发送了不同的消息。这样的行为毫无疑问是 malicious 的,所以至少存在 $f+1$ 个恶意节点,与至多有 $f$ 个恶意节点的协议假设矛盾。证毕。
首先,Commit Phase 是 View Change 的副产物。后面的章节会详细解释 View Change,在这个阶段我们只需要知道 View Change 用来解决 Primary 作恶时的 Liveness 问题。而 Commit Phase 就是用来解决 View Change 过程中 Safety 的问题,即在 View 切换的前后:
$$
Committed(n, m, v, i) \Rightarrow \lnot Committed(n, m', v', j), \forall D(m) \neq D(m'), v' > v
$$
现在我们假设 Commit Phase 不存在,即在节点达成 Prepared 的时候就直接给 Client 发送 Reply。考虑下图的情况:
可以发现反例非常容易构造,我们甚至构造出了 $f$ 个节点使用了 $n+1$ 的 Sequence Number,但是剩余节点以及 New Primary 没有的情况。
从上面这个例子已经可以看出,Commit Phase 主要就是需要保障一个 Sequence Number 在跨 View 的时候不能被 Malicious Primary 或者 Network Partition 影响,使得被重复使用,破坏 Safety。
增加一个 Commit Phase 的主要功能,就是 只有在知道有一定数量的其他 Replica 已经处于 Prepared 状态之后再进行 Commit,这个数量一定要保证能够在 View Change 的时候至少有一个节点能够证明这个请求已经 Prepared。
因为注意到上图:在节点 Commit 的时候,很多节点没有达到 Prepared 状态,无法在 Network Partition 的时候提供证据向新的 Primary 证明这个请求已经被 Commit。综上所述,这就是 Commit Phase 存在的意义。
上一节提到,在 Commit 前,我们至少要保证有足够多的 Replica 已经处于 Prepared 阶段,使得在 Network Partition 出现的时候仍然能够向 Primary 提供信息,告诉 Primary 一个请求已经被 Commit。那这个数量到底应该是多少呢?通过简单的估算其实就可以得到。
已知 New Primary 需要 $2f$ 个除了自己以外的 View Change 请求。最悲观地考虑,出现了最大限度的 Network Partition,即有 $f$ 个节点无法通信。在这个极限情况下的极限情况是这 $f$ 个 Replica 都处于 Prepared 状态却无法与 Primary 通信。而其余 $2f+1$ 个节点中又有 $f$ 个 malicious node,可以假装不知道自己 Prepared 了。
所以,在那 $2f+1$ 个节点中至少需要 $f+1$ 个节点处于 Prepared 状态才能保证 New Primary 收到 Commit 记录,再算上 Network Partition 的 $f$ 个 Replica,一共得有 $2f+1$ 个节点处于 Prepared 状态才能保证信息能够在 Network Partition 和 View Change 的情况下送达 New Primary。
上述文字选取的是极端情况,有一条不成立即为反例。所以 $2f$ 个 Prepared 却仍然失败的反例和没有 Commit Phase 一样非常好构造,这里不再赘述。
理解了 Commit Phase 的 $2f+1$ 便不难发现,这里 $2f$ 这个数目的选取是和 Committed 数目的选取是相关的。
两个 $2f+1$ (实际上 View Change 算上 New Primary 也是 $2f+1$) 在总共 $3f+1$ 的池子里,Intersection (Quorum) 的大小总是不小于 $f+1$ 个 Replica 的。这样就保证了总有一个 Non-faulty Replica 位于最终的 Quorum 当中(faulty replica 可以隐瞒不报,装作不知道,所以一定需要 non-faulty replica),即既是 Prepared,又没有被 Network Partition 和 Malicious Replica 影响到。
这个就非常 Intuitive 了,因为这样必定能有一个 Non-faulty Replica 回复。
注意到 View Change 的时候需要附上所有的记录来证明自己是正常节点,这所带来的开销随着时间的推移显然是不可接受的,所以我们需要想办法回收一部分 log。
因为 $f+1$ 保证了至少有一个 Non-faulty Node 进行了 Checkpoint,也就是在没有 Network Partition 的情况下必定可以从网络中访问到这个 Checkpoint。
但是这里其实有一个问题:如果 Network Partition 了呢?注意到 PBFT 只在没有 Network Fault 的情况下 Guarantee Liveness,所以在那种情况下,需要请求 Checkpoint 的节点就 In-dark 了。如果这样的情况足够多,Liveness 也就无法保证了。
View Change 主要是为了解决没有 Network Fault 的情况下的 Liveness 问题。当一个 Replica 的请求迟迟无法完成的时候就会 Trigger View Change。因为请求无法完成无非几种情况:
View Change 在第二种情况下其实并不能解决问题,但是可以解决第一种情况的问题。这就是 View Change 的 Intuition。
注意到 Primary 可以故意不给某些节点发请求,即 Primary 作恶。在这种情况下,这些节点既不会触发 View Change,也不会做任何事情,也就是字面意义上的 In-Dark。
由于前面的论证,PBFT 已经保证了 Safety,同时在没有 Network fault 的情况下也保证了 Liveness,所以这样的 In-Dark 并不会有什么特别大的影响。
只有当 In-Dark Replica 的数量多到使得 Consensus 无法达成了,才会 trigger View Change,使得协议能够推进下去。
其他小的点:
论文链接:https://pmg.csail.mit.edu/papers/osdi99.pdf
BFT (Byzantine Fault Tolerant) 拜占庭容错,指的是在一个分布式系统当中,在有节点可能出现任意行为(包括但不限于崩溃、发送错误数据、出现恶意行为等)的情况下,仍可以正常运行即达成共识。
PBFT 可以保证在一个大小为 $3f+1$ 的分布式网络下,容忍至多 $f$ 个节点的拜占庭错误。
见原文,不赘述。
见:https://dinhtta.github.io/pbft/
Network Failure Model
Byzantine fault tolerant protocols tolerate at most $f$ Byzantine failures. In a distributed system, however, there are two types of failures: node and network. It is important to distinguish them, especially since they determine guarantees about the protocol’s safety and liveness.
Node failure means a node (or server, peer, entity, etc.) behaves arbitrarily. This captures the strongest adversary model. A network failure refers to network partitions which can last for an unbounded amount of time. It can be quantified as the number of nodes being isolated from the rest of the network, although they can still communicate with each other.
Given this distinction, what are being counted toward $f$? In PBFT
- $f$ refers to node failures. The protocol guarantees safety upto $f$ node failures. Safety is independent of network failure. That is, even if the network is severely partition, namely more than $f$ nodes are isolated (but across all partitions there are still fewer than $f$ node failures), the protocol is still safe.
- However, liveness is only guaranteed with fewer than $f$ total failures, i.e. counting both node and network failures. This means at least $2f+1$ nodes must be reachable.
Note that safety being independent of network failures is a strong guarantee, and it is common in most variants of PBFT. Not until Liu et al. recent work, namely XFT, is it relaxed in a way that separates out node and network failures.
要回答上面的大问题首先要理解我们想要 Preprepare + Prepare Phase 保证什么。论文 Section 4.2 已经回答了这个问题,即
$$
prepared(m, v, n, i) \Rightarrow \lnot prepared(m', v, n, j), \forall i,j,m,m', s.t. D(m') \neq D(m)
$$
即我们要保证在同一个 view 内,每一个 sequence number 只对应唯一一个 prepared message。
首先我们可以构造一个如果只有 $2f$ 个 matching 就能打破上述原则的反例。
接下来我们尝试用 Quorum 的思想来证明。使用反证法:如果每个节点都有 $2f+1$ 个 matching,但是最后仍然出现了两个 Replica $a \neq b$,使得
$$
prepared(m, v, n, a) \land prepared(m', v, n, b) \land D(m) \neq D(m')
$$
根据题设,有 $2f+1$ 个节点向 $a$ 发送了 $\langle Prepare, v, n, d, i \rangle _{\sigma_i}$,有 $2f+1$ 个节点向 $b$ 发送了 $\langle Prepare, v, n, d', i \rangle _{\sigma_i}$。根据容斥原理,至少有
$$
2 \times (2f + 1) - (3f+1) = f + 1
$$
个节点向 $a, b$ 分别发送了不同的消息。这样的行为毫无疑问是 malicious 的,所以至少存在 $f+1$ 个恶意节点,与至多有 $f$ 个恶意节点的协议假设矛盾。证毕。
首先,Commit Phase 是 View Change 的副产物。后面的章节会详细解释 View Change,在这个阶段我们只需要知道 View Change 用来解决 Primary 作恶时的 Liveness 问题。而 Commit Phase 就是用来解决 View Change 过程中 Safety 的问题,即在 View 切换的前后:
$$
Committed(n, m, v, i) \Rightarrow \lnot Committed(n, m', v', j), \forall D(m) \neq D(m'), v' > v
$$
现在我们假设 Commit Phase 不存在,即在节点达成 Prepared 的时候就直接给 Client 发送 Reply。考虑下图的情况:
可以发现反例非常容易构造,我们甚至构造出了 $f$ 个节点使用了 $n+1$ 的 Sequence Number,但是剩余节点以及 New Primary 没有的情况。
从上面这个例子已经可以看出,Commit Phase 主要就是需要保障一个 Sequence Number 在跨 View 的时候不能被 Malicious Primary 或者 Network Partition 影响,使得被重复使用,破坏 Safety。
增加一个 Commit Phase 的主要功能,就是 只有在知道有一定数量的其他 Replica 已经处于 Prepared 状态之后再进行 Commit,这个数量一定要保证能够在 View Change 的时候至少有一个节点能够证明这个请求已经 Prepared。
因为注意到上图:在节点 Commit 的时候,很多节点没有达到 Prepared 状态,无法在 Network Partition 的时候提供证据向新的 Primary 证明这个请求已经被 Commit。综上所述,这就是 Commit Phase 存在的意义。
上一节提到,在 Commit 前,我们至少要保证有足够多的 Replica 已经处于 Prepared 阶段,使得在 Network Partition 出现的时候仍然能够向 Primary 提供信息,告诉 Primary 一个请求已经被 Commit。那这个数量到底应该是多少呢?通过简单的估算其实就可以得到。
已知 New Primary 需要 $2f$ 个除了自己以外的 View Change 请求。最悲观地考虑,出现了最大限度的 Network Partition,即有 $f$ 个节点无法通信。在这个极限情况下的极限情况是这 $f$ 个 Replica 都处于 Prepared 状态却无法与 Primary 通信。而其余 $2f+1$ 个节点中又有 $f$ 个 malicious node,可以假装不知道自己 Prepared 了。
所以,在那 $2f+1$ 个节点中至少需要 $f+1$ 个节点处于 Prepared 状态才能保证 New Primary 收到 Commit 记录,再算上 Network Partition 的 $f$ 个 Replica,一共得有 $2f+1$ 个节点处于 Prepared 状态才能保证信息能够在 Network Partition 和 View Change 的情况下送达 New Primary。
上述文字选取的是极端情况,有一条不成立即为反例。所以 $2f$ 个 Prepared 却仍然失败的反例和没有 Commit Phase 一样非常好构造,这里不再赘述。
理解了 Commit Phase 的 $2f+1$ 便不难发现,这里 $2f$ 这个数目的选取是和 Committed 数目的选取是相关的。
两个 $2f+1$ (实际上 View Change 算上 New Primary 也是 $2f+1$) 在总共 $3f+1$ 的池子里,Intersection (Quorum) 的大小总是不小于 $f+1$ 个 Replica 的。这样就保证了总有一个 Non-faulty Replica 位于最终的 Quorum 当中(faulty replica 可以隐瞒不报,装作不知道,所以一定需要 non-faulty replica),即既是 Prepared,又没有被 Network Partition 和 Malicious Replica 影响到。
这个就非常 Intuitive 了,因为这样必定能有一个 Non-faulty Replica 回复。
注意到 View Change 的时候需要附上所有的记录来证明自己是正常节点,这所带来的开销随着时间的推移显然是不可接受的,所以我们需要想办法回收一部分 log。
因为 $f+1$ 保证了至少有一个 Non-faulty Node 进行了 Checkpoint,也就是在没有 Network Partition 的情况下必定可以从网络中访问到这个 Checkpoint。
但是这里其实有一个问题:如果 Network Partition 了呢?注意到 PBFT 只在没有 Network Fault 的情况下 Guarantee Liveness,所以在那种情况下,需要请求 Checkpoint 的节点就 In-dark 了。如果这样的情况足够多,Liveness 也就无法保证了。
View Change 主要是为了解决没有 Network Fault 的情况下的 Liveness 问题。当一个 Replica 的请求迟迟无法完成的时候就会 Trigger View Change。因为请求无法完成无非几种情况:
View Change 在第二种情况下其实并不能解决问题,但是可以解决第一种情况的问题。这就是 View Change 的 Intuition。
注意到 Primary 可以故意不给某些节点发请求,即 Primary 作恶。在这种情况下,这些节点既不会触发 View Change,也不会做任何事情,也就是字面意义上的 In-Dark。
由于前面的论证,PBFT 已经保证了 Safety,同时在没有 Network fault 的情况下也保证了 Liveness,所以这样的 In-Dark 并不会有什么特别大的影响。
只有当 In-Dark Replica 的数量多到使得 Consensus 无法达成了,才会 trigger View Change,使得协议能够推进下去。
其他小的点: