区块链|PBFT算法流程补充(二)(算法正确性证明及优化)

本文为万向区块链技术中心研究组撰写,文章尝试对PBFT算法的正确性证明以及算法优化等内容作一个介绍。

1. PBFT算法正确性证明 本部分介绍PBFT算法的正确性证明。

1.1 安全性(Safety)证明 PBFT算法提供的安全性(safety)的具体含义是,对于所有本地确认(commit locally)的客户端请求来说,系统中所有正常副本节点都会就这些请求的消息序号达成一致。

上述的“达成一致”,其含义又分为两种:
同一视图中的消息序号一致:对于所有在同一视图中本地确认的客户端请求来说,各正常副本节点就其消息序号会达成一致。
新旧视图中的消息序号一致:对于在新旧视图中本地确认的客户端请求来说,各正常副本节点就其消息序号会达成一致。

接下来分别证明上述两种“一致”是成立的。

1. 在同一视图中,任何一个请求 m ,如果其已经本地确认过,也就是说,至少对于某一个正常副本节点 i 来说,prepared(m, v, n, i) 为 true , 之前已经证明过,此时,对于任意的正常副本节点 j (j也可以是 i) 来说,prepared(m’, v, n, j) 都为 false 。这里 m’ 是不同于 m 的另一个请求,也就是说 D(m’) 不等于 D(m) 。这就意味着对于所有在同一视图中本地确认的客户端请求来说,各正常副本节点就其消息序号会达成一致,第一个性质成立。

2. 现在考虑存在视图变更的情况。首先,在视图 v 中,对于任意一个请求 m 来说,如果其在 某个正常副本节点 i 完成了本地确认,假设其消息序号为 n 。那么,就有 committed(m, v, n) 为 true 。 这也意味着存在一个节点集合R1, 其中至少含有 f+1 个正常副本节点,并且对于其中每一个节点 i ,prepared(m, v, n, i) 为 true。

然后,考虑系统最终变更视图到 v' 的情况。在从视图 v 变更到 v' 的过程中,此时变更没有完成,正常副本节点在接收到 new-view 消息之前,不会接受视图 v' 上的预准备消息。

但是,对于视图 v 变更到 v'的任意一个有效的 new-view 消息来说,其中包含 2f+1 个有效的view-change 消息。这些消息来自不同的副本节点,记它们组成的集合为R2。R1和R2至少有一个相同的元素,也就是相同的节点。不然的话,它们总的节点个数将为(f+1) + (2f+1) = 3f+2,这与我们假定的系统总节点个数 3f+1 不符。

因此,假设这个共同的正常副本节点为 k 。对于请求 m 来说,只有可能存在下面两种情况:new-view 消息中,存在 view-change 消息,其中包含的最新稳定检查点对应的消息序号大于 m 的序号 n 。new-view 消息中所有的 view-change 消息中包含的最新稳定检查点对应的消息序号不大于m的序号n。

对于第一种情况,根据视图变更协议,新视图 v' 中,所有正常副本节点不会接受序号为n或小于n的消息。

对于第二种情况,m 将会被传播到新视图 v'中,因为根据视图变更协议,min-s≤n。视图变更完成后,在 v' 中,算法将针对编号为 n 的请求 m 重新运行三阶段协议。这就使得所有正常副本节点会达成一致,而不会出现下面这种情况:
另一个不同于 m 的请求 m' , 其在视图 v 中分配的序号为 n ,且在新视图中 v' 完成本地确认。
综合上面 1 和 2 的证明,就证明了算法在同一视图和视图变更过程中,都会保证本地确认的请求的序号在所有正常副本节点中会达成一致,从而保证了算法的安全性(safety)。

1.2 活性(Liveness)保证 对于PBFT算法来说,为了保证系统的活性(liveness),当节点无法执行客户端请求时,需要变更到新的视图。同时,视图变更也需要进行合理控制,只在需要时才进行,否则频繁的视图变更会影响到系统的活性。这就需要保证以下两点:
系统中至少 2f+1 个正常副本节点处于同一视图中时,这种状态尽可能长时间地保持;
每次视图变更时,上述时间间隔需要快速增长,比如以指数形式增长。

PBFT算法通过如下三种方法来保证上述两点:
1. 为了防止视图变更太快开始,当一个节点发送 view-change 消息后,在等待接收 2f+1 个 view-change消息时,会同时启动定时器,其超时时间设置为 T。如果视图变更没有在 T 时间内完成,或者在新视图中请求没有在该时间间隔内完成,则会触发新的视图变更。此时,算法会调整超时时间,将其设置为原来的两倍,即 2T 。
2. 除了上述的定时器超时触发节点发送 view-change 消息外,当其接收到来自 f+1 个不同节点的有效view-change 消息,并且变更的目标视图大于节点当前视图时,也会触发节点发送 view-change 消息。这可以防止节点过晚启动视图变更。
3. 基于上述第二点的规则,失效节点无法通过故意发送 view-change 消息来触发频繁的视图变更从而干扰系统的运行。因为失效节点最多只能发送 f 条消息,达不到 f+1 的触发条件。失效节点是主节点时,可能会触发视图变更,但是连续的视图变更最多只会是 f 个,之后主节点就是正常节点。因此,基于以上的规则,系统可以保证活性。

2. PBFT算法的优化 本部分介绍PBFT算法的优化。这些优化方式应用于算法的正常操作中,可以提升算法的性能,同时可以保持系统的安全性和活性。

2.1 减少系统通信量 可以采用三种方法减少系统通信量:
1. 向客户端发送回复的消息摘要,而不是回复的原始内容客户端指定一个特定的副本节点,从该节点接收完整的回复内容,而只从其他所有节点处接收回复的摘要。通过判读摘要与回复的一致性以及对回复计数,可以确保接收到正确的回复。如果客户端接收不到正确结果,就会按正常流程重新请求系统,并接收不同节点的完整回复。
2. 请求在副本节点prepared后,节点即试探性地执行请求,并发送结果。客户端只要收到 2f+1 个匹配的结果,就可以确保该结果的正确性。也就是说,该请求最终会确认(至少f+1 个正常副本节点的本地确认)。如果客户端无法得到正确结果,就重新发送请求,系统执行正常流程。一个被试探性执行的请求,有可能在视图变更过程中被中断,并被替换为一个空请求。此时,已经执行过请求的节点可以通过 new-view 消息中的最新的稳定检查点或本地的检查点来更新状态(取决于哪个序号更大)。
3. 针对只读操作,客户端将请求广播到每一个副本节点。各节点判断请求确实为只读且满足条件后,直接执行请求,并发送回复到客户端。客户端收到 2f+1 个相同的回复,即为正确结果;否则客户端之前设置的重发请求定时器将触发超时,使得客
户端重发请求,系统执行正常流程。
这种优化的前提条件是,副本节点在执行请求之前,需确保之前所有请求都已确认,并且被执行。

2.1 加快消息验证速度 使用公钥签名的方式验证消息存在如下不足:
类似于RSA这样的签名算法,签名速度比较慢;
其他公钥密码系统,如椭圆曲线公钥密码系统,虽然签名更快,但是验签更慢。

PBFT算法实际上在正常流程中采用 MAC(Message Authentication Code,消息验证码) 认证消息,因为它具有如下优点,使得算法相对于之前的算法性能提升了一个数量级以上:
MAC 计算速度快;
通过适当优化,可以减少其长度;
通过对authenticator(vector of MAC)的使用,可以使验证时间为常量,而生成时间只随着节点数量线性增长。

具体来说,PBFT算法中使用 MAC 和公钥签名的具体场景是:
所有正常操作流程中使用 MAC 验证消息;
视图变更中的消息:view-change, new-view,以及出现错误时,使用公钥签名。这些场景的出现频率相
对较低,从而对算法的性能影响较小。

相关阅读:
PBFT算法流程
【区块链|PBFT算法流程补充(二)(算法正确性证明及优化)】PBFT算法流程补充(一):视图变更、垃圾回收及状态机不确定性

    推荐阅读