一种基于分权的双主节点PBFT区块链衍生共识算法——DPNPBFT
摘要
本文提出了双主节点派生的实用拜占庭容错(DPNPBFT)来实现上述三种性能的最佳平衡。首先,DPNPBFT基于权力分离的思想选择双主节点。两个主节点检查平衡并相互监督,以避免作为单个主节点系统的过度中心化。它还降低了副本节点的通信复杂度,副本节点仅与主节点通信。此外,我们设计的 DPNPBFT 架构获得了实用的 49% 容错率,接近当前主流的工作量证明和权益证明算法。实验结果表明,DPPNBFT具有O(N)级的通信复杂度和优异的抗主机节点恶意性能。 DPNPBFT每秒交易数稳定在1700,证明DPNPBFT对于大规模物联网具有最佳的性能平衡和优异的综合性能。
关键词:区块链、PBFT、共识算法、通信复杂性。
主要贡献
1)首先,在分析当前著名的PBFT衍生算法的基础上,本文提出了一种算法,即双主节点衍生的PBFT共识算法(DPNPBFT)。与单主节点PBFT衍生算法相比,该算法大大提高了系统的安全性。与传统PBFT算法
O
(
N
2
)
\mathrm{O(N^{2})}
O(N2) 级的通信复杂度相比,DPNPBFT通信复杂度可以降低到
O
(
N
)
\mathrm{O(N^{})}
O(N)级。具体来说,通信数量大约为 5N-2,这使得模型具有可扩展性。
2)其次,与传统的大多数PBFT算法33%的容错率相比,DPNPBFT的容错率可以提高到49%,其容错率几乎与PoS和PoW算法持平。
3)第三,对DPPNBFT算法的抗恶意主节点性能、通信复杂度和TPS性能进行分析和验证。然后综合比较了几种算法的优缺点。
DPNPBFT
DPNPBFT中,主要分为三个过程,每个过程分别是:共识过程、视图切换和日志压缩。由于双主节点机制和完整阶段的引入,DPPNBFT共识过程和视图切换过程比PBFT更加复杂,但也更好地保证了抵御主节点作恶的能力和算法的最终一致性。日志压缩与PBFT算法一致,这里不再赘述。
A. 共识过程
1)初始节点的选择
首先是初始双主节点的选择。初始双主节点选择通过以下公式执行: 验证主节点 (P1) 已被选择:
P1=V mod N
(
1
)
\text{P1=V mod N}\quad(1)
P1=V mod N(1)
广播主节点(P2)选择:
P2
=
RAND (C
P
1
ANs)
(
2
)
\text{P2}=\text{RAND (C}_{P1}\text{ANs)}\quad(2)
P2=RAND (CP1ANs)(2)
各符号含义如表1所示:
符号 | 代表意义 |
---|---|
V | 表示当前的视图编号 |
N | 广播消息到主节点的唯一递增序列号 |
RAND() | 随机选择一个节点 |
C U A {C}_U{A} CUA | 集合 U 中集合 A 的补集 |
P1 | 选择的 P1 节点 |
ANs \text{ANs} ANs | 所有节点的集合 |
2)共识阶段
DPNPBFT 共识流程如下:首先,客户端同时向主节点 1 和主节点 2 发送需要共识的消息。主节点1(P1节点)负责广播客户端发送的需要在链上达成共识的消息。主节点2将验证该节点返回的消息。如果验证通过,则会广播到所有节点。各节点检查无误后回复客户端。客户端收到f+2个相同回复后确认已达成共识,并再次向各节点发送完成消息,为下一次消息共识做好准备。具体流程如图1所示。
与PBFT不同的是,
(1)DPNPBFT基于分发和验证两个功能设置了双主节点。 P1为广播主节点,P2为验证主节点。 (2)DPNPBFT与PBFT广播信息的分发方式完全不同。
(3) DPNPBFT 增加了一个完整的阶段来保证最终的一致性。
按照个人理解右上角的P1再一次给所有节点发送预准备消息是错的,与下面的算法实现的阶段图也不符合。
其中,(1)保证了抵御单个主节点作恶的能力,(2)大大降低了PBFT的通信复杂度。
请求阶段
客户端C向节点P1和P2发送请求消息。以下所有具体消息格式将在下表中给出。
预准备阶段:
P1节点向除P2之外的所有副本节点发送pre-prepare(预准备)消息,并缓存消息R(客户端请求消息封装为R)。备份节点验证以下信息并缓存R消息:
·未收到其他预准备消息。
·客户端请求签名正确,P1签名正确。
·确认当前视图为v,高度为h,R的H( R )值正确。
检查阶段
各备份节点(包括P1节点)确认无误后,向P2节点发送检查消息。
提交阶段
P2节点接收各节点发给它的检查消息。检查阶段在时间到期后预设一个GST(全局稳定时间),并验证以下信息:
- v和h值相同的备份节点的数量。 H( R) 与每个客户端发送的Request消息匹配的备份节点的数量。
- i的值应该不同。
- check_state为1且签名正确的节点数量。
同时,满足上述条件的校验消息被视为有效消息,参与计数并缓存消息R。当数量达到f+2(不包括自身)时,可以回复对方节点提交消息并回复客户端回复消息。
消息 | 消息的详细格式 |
---|---|
request· | < < R E Q U E S T > , t , i d , s i g c > <<REQUEST>,t,id,sig_{c}> <<REQUEST>,t,id,sigc> |
pre-prepare | < < P R E − P R E A R E , v , h , H ( R ) , P 1 > , R , s i g P 1 > <<PRE-PREARE,v,h,H(R),P1>,\mathrm{R,sig_{P1}}> <<PRE−PREARE,v,h,H(R),P1>,R,sigP1> |
check | < < C H E C K , v , h , H ( R ) , i > , c h e c k s t a t e ( 1 o r 0 ) , s i g i > <<CHECK,v,h,H(R),i>,check_\mathrm{state}(1\mathrm{~or~}0),\mathrm{sig}_{i}> <<CHECK,v,h,H(R),i>,checkstate(1 or 0),sigi> |
commit | ≪ C O M M I T , v , h , H ( R ) , P 2 > , s i g s e t ( r i 1 , r i 2 . . . ) , s i g P 2 > \ll COMMIT,v,h,H(R),\mathrm{P2}>,sig_{set(r_{i1},r_{i2}...)},sig_{P2}> ≪COMMIT,v,h,H(R),P2>,sigset(ri1,ri2...),sigP2> |
reply | < < R E P L Y , v , h , H ( R ) , i > , s i g i > <<REPLY,v,h,H(R),i>,sig_i> <<REPLY,v,h,H(R),i>,sigi> |
complete | < < C O M P L E T E , v , h , H ( R ) > , R , s i g c > <<COMPLETE,v,h,H(R)>,R,sig_{c}> <<COMPLETE,v,h,H(R)>,R,sigc> |
符号 | 代表意义 |
---|---|
t· | 当前时间 |
id | 发起请求的客户端ID |
s i g x sig_x sigx | X的数字签名 |
h | 区块高度 |
H( R) | 消息R的哈希值 |
R | 客户端请求消息 |
check_state | 1或0;1表示检查通过,0表示检查未通过 |
Symbol | 代表意义 |
其中,P2节点将构造sig_set()签名集,签名集中的每个元素包括: 1) 节点对其发送的检查消息的摘要的签名。 2) 节点数量。 P2 广播提交消息。
回复阶段
每个节点都会收到P2节点发送的提交消息,并在回复阶段预设一个全局稳定时间(GST)。时间到期后,各节点会验证以下信息:
将commit消息与自己本地的缓存消息进行比较,看是否相同(如果本地没有对应的缓存数据,则不会响应)。
上述条件全部通过后,将pre-preare阶段缓存的消息写入本地链式数据结构,回复客户端回复消息。
完成阶段
客户端收到f+2个节点的回复消息后确认已达成共识,然后广播完整的消息。
已经响应客户端回复的节点不再响应该消息,准备进入下一次共识。未响应或本地没有消息缓存的节点被迫写入消息并准备进入下一次共识。
所有消息的详细格式如表2所示。
DPNPBFT算法中符号的定义如表3所示:
图2中的*是我们新添加的完整流程。具体流程描述如下:
B. DPNPBFT视图切换
各副本节点收到重选消息:
<
<
R
E
−
E
L
E
C
T
I
O
N
,
E
x
c
l
u
d
e
I
D
P
1
>
,
s
i
g
P
2
>
<<\mathrm{RE-ELECTION,Exclude_ID_{P1}>,sig_{P2}}>
<<RE−ELECTION,ExcludeIDP1>,sigP2> 或者
<
<
<
P
R
E
−
P
R
E
P
A
R
E
P
1
→
P
2
>
,
m
a
t
h
r
m
R
E
−
E
L
E
C
T
I
O
N
,
E
x
c
l
u
d
e
I
D
P
1
>
,
s
i
g
P
2
>
\begin{aligned}<<<PRE&-PREPARE_{P1\to P2}>,mathrm{RE-ELECTION,Exclude_ID_{P1}>,}sig_{P2}>\end{aligned}
<<<PRE−PREPAREP1→P2>,mathrmRE−ELECTION,ExcludeIDP1>,sigP2>
然后与本地同一视图下收到的(或未收到的)消息进行比较,判断是否广播了视图切换消息。与传统PBFT的区别在于,重选消息中的P1和P2节点在视图切换过程中将不再被选为主节点,其余视图切换过程与传统PBFT相同。
C.容错分析
DPNPBFT 的容错性能由以下公式确定:
当节点总数为奇数时:
2
f
+
3
=
N
(
3
)
2\mathrm{f}+3=\mathrm{N}\quad(3)
2f+3=N(3)
当节点总数为偶数时:
2
f
+
2
=
N
(
4
)
2\mathrm{f}+2=\mathrm{N}\quad(4)
2f+2=N(4)
节点容错率可以统一为:
f
=
[
(
N
−
2
)
/
2
]
(
5
)
\mathrm{f=[(N-2)/2]}\quad(5)
f=[(N−2)/2](5)
其中,[]表示舍入函数,f表示拜占庭节点数,N表示节点总数。
DPNPBFT 容错率随节点总数的变化如图 3 所示。根据公式(5)和图 3,我们可以很容易地得出,在节点规模为 100 时,DPNPBFT 的容错率为 49%。随着节点总数的增加将接近50%。
DPNPBFT 容错分析
在本节中,我们详细介绍 DPNPBFT 共识算法在不同情况下的操作。
A.副本节点是拜占庭节点
副本节点宕机如图4所示。当宕机节点数量没有达到最大容错率时,这是副本节点宕机最常见的情况。 DPNPBFT 算法对这种情况的反应如下:
(2)正常副本节点回复检查消息,错误副本节点不回复或者回复错误消息。 P2节点接收所有检查消息。
(3)副本节点宕机(或发送错误消息):如果P2节点的正常计数可以接受f+2条相同(不包括自身)检查消息,则共识将正常进行。
(4)副本节点宕机(或发送错误消息):如果P2节点的正常计数无法接受f+2个相同(不包括自身)检查消息,则会超过最大容错率制度和共识无法达成。
B.P1节点是拜占庭节点
1)P1 节点已关闭(或部分消息已发送)
如图5和图6所示,主节点的两种作恶方式最终都会得到相同的处理结果。在提交阶段,P2节点接收到客户端发送的请求,但没有收到其他节点的任何响应或者只收到部分响应,不满足f+2的条件。因此判断P1节点无效。在提交阶段,它向每个节点发送重选消息-1。以下所有具体消息格式将在下表中给出。每个副本节点检查是否收到P1消息,如果没有,则发起view-change。
2)P1是一个拜占庭节点
如图7所示,不同的线路类型代表发送的不同消息。此时P2节点最多收到两条相同的消息,不满足f+2条件,P2节点向提交阶段的各个节点发送重选消息-2:
各个副本节点收到消息后,检查自己的pre-prepare消息与P2节点收到的pre-prepare是否一致。如果不一致,他们会发起视图更改;如果它们一致,则不会发起视图更改。
C.P2 节点是拜占庭节点
P2 节点接收到的消息都经过各个副本节点的签名和验证,因此向每个节点发送不同的消息是不可行的。因此,P2节点的恶意方式只是宕机和部分发送。
1)P2宕机
P2节点宕机时的情况如图8所示。 P2宕机后的commit过程中,GST后P1没有收到P2节点的commit消息,向各节点发送重选消息-3:各节点检查是否收到P2消息,如果没有则发起观点改变。如果收到,则不会启动视图更改。
2)P2发送部分消息
第一种情况(图9):P2节点发送部分时包含P1节点,此时P1节点不会发送重选消息,所有收到的节点都会回复客户端,如果能超过f+1,则共识成功,对于保证最终一致性,客户端会向节点回复一条完整的消息,表明大部分节点的共识已经完成,在提交阶段没有收到消息的副本节点会直接将消息R存储在此时本地收到消息后完成,然后准备进入下一轮共识。
如果每个副本节点都收到P2节点commit消息,继续正常执行,如果没有收到,则发起view-change请求。
如果客户端能收到f+1个有效回复,则共识继续正常执行,并返回一条完整的消息,让提交阶段未收到P2消息的节点写入消息,保证最终一致性。如果客户端无法收到f+1个有效回复,它将继续view-change请求。
D.P1 和 P2 节点同时宕机
P1 和 P2 节点同时宕机,则GST过后,客户端C会发起向各节点发送重选消息,各节点进行验证并发起视图切换。