阅读建议
Honey Badger BFT应用了很多前人的研究,进行了巧妙的构造和优化,初次学习往往难以理解。在阅读时可以先大致了解各个构造块的基本作用,再了解总体的共识过程。之后回过头来深入研究各个构造块的原理,特别是BA算法,是整个协议的核心内容。
背景知识
FLP定理指出,在异步网络中,不可能存在一个确定性的共识协议。在FLP定理的指导下,共识协议设计往往需要作出妥协——要么弱化网络条件的限制,要么引入随机性。我们常见的PBFT、Raft等,就是在半同步网络下实现了一致性,但这类共识在网络条件变化时,其吞吐量会显著降低。而以往的异步共识协议同样效率低下,完全无法满足实际需求。本文介绍的Honey Badger BFT则是第一个具备可行性的异步共识协议。
基本构造块
阈值加密(threshold encryption)
传统的非对称加密算法包含一对密钥(公钥pkpkpk和私钥sksksk),其中pkpkpk用于消息加密,sksksk用于解密。
而门限加密则将私钥sksksk分为nnn份(ski,i∈(1,...,n)sk_i,i \in(1, ..., n)ski,i∈(1,...,n)),对于pkpkpk加密的密文CCC,每个子密钥skisk_iski都可以生成一个解密块σi\sigma_iσi,至少ttt个解密块合成后才能最终解密得到原始消息mmm。阈值签名算法类似,只是把加密改成了签名。

可靠广播协议(RBC,Reliable broadcast)
由于在分布式系统中,并不存在这样的广播信道,使得节点只需要发送一次消息,就能使网络中的所有节点都接收到,消息任然需要系统成员之间通过点对点的通信来传播。
而 RBC协议则是用来保证消息传播的一致性,各节点遵循RBC协议进行通信,最终能达到广播消息的效果,即网络中的所有节点都能以相同的顺序接收到相同的消息。
Honey Badger论文中使用了基于纠删码的可靠广播协议(Reliable broadcast with erasure codes)。
如图所示,消息发送方PiP_iPi发送消息vvv的步骤如下:
- PiP_iPi用纠删码将消息vvv分为NNN块,每块以sjs_jsj表示;
- PiP_iPi以sjs_jsj为叶子节点构造Merkle树,hhh为Merkle根,bjb_jbj为sjs_jsj的验证路径;
- PiP_iPi将sjs_jsj和对应的Merkle树验证信息分别发送给其他所有节点,表示为VAL(h,bj,sj)\texttt{VAL}(h,b_j,s_j)VAL(h,bj,sj);
- 收到VAL\texttt{VAL}VAL消息后,将其广播ECHO(h,bj,sj)\texttt{ECHO}(h,b_j,s_j)ECHO(h,bj,sj);
- 收到ECHO(h,bj,sj)\texttt{ECHO}(h,b_j,s_j)ECHO(h,bj,sj)消息,验证Merkle树对应的路径是否正确,若不正确则忽略;
- 收到N−fN-fN−f个不同的ECHO\texttt{ECHO}ECHO消息后,从中选择%N-2f%个,重新计算Merkle根h′h'h′,判断是否满足h′=hh'=hh′=h,若等式成立则广播READY(h)\texttt{READY}(h)READY(h);
- 收到f+1f+1f+1个READY(h)\texttt{READY}(h)READY(h)消息后,如果没有发送过READY(h)\texttt{READY}(h)READY(h),那么广播READY(h)\texttt{READY}(h)READY(h);
- 收到2f+12f+12f+1个READY(h)\texttt{READY}(h)READY(h)消息后,待接收到N−2fN-2fN−2f个ECHO(h,bj,sj)\texttt{ECHO}(h,b_j,s_j)ECHO(h,bj,sj)消息后,即可解码出消息vvv。
说明:
- RBC协议的核心在于通过Echo\texttt{Echo}Echo传递消息,通过Reday\texttt{Reday}Reday表明消息已经发送完毕。
- 在基于纠删码的RBC协议中,sjs_jsj的NNN个消息中有2f2f2f个是冗余消息,用于防止恶意和失效节点。该协议通过调动全网节点发送消息分块sjs_jsj来代替单个leader直接向全网广播消息,避免了leader的带宽瓶颈。
- 论文中的算法表述容易造成误导,比如图中红框部分,实际含义是:在节点PiP_iPi构造出VAL(h,bj,sj)\texttt{VAL}(h,b_j,s_j)VAL(h,bj,sj)后,将其作为RBC协议的输入,“upon receiving”是指RBC协议收到VAL\texttt{VAL}VAL后,相当于PiP_iPi调用了RBC协议,而不是说将VAL\texttt{VAL}VAL发送给了其他人,后续的算法也要注意这种表述。
-
- 该协议的复杂度为O(N∣v∣+λN2logN)O\left(N|v|+\lambda N^{2} \log N\right)O(N∣v∣+λN2logN),当消息本身足够大时(∣v∣≫λN2logN|v| \gg{\lambda N^{2} \log N}∣v∣≫λN2logN ),复杂度可以表示为O(N∣v∣)O(N|v|)O(N∣v∣),等价于发送方向所有节点一对一直接发送消息的复杂度,因此说是渐进最优的。

- 该协议的复杂度为O(N∣v∣+λN2logN)O\left(N|v|+\lambda N^{2} \log N\right)O(N∣v∣+λN2logN),当消息本身足够大时(∣v∣≫λN2logN|v| \gg{\lambda N^{2} \log N}∣v∣≫λN2logN ),复杂度可以表示为O(N∣v∣)O(N|v|)O(N∣v∣),等价于发送方向所有节点一对一直接发送消息的复杂度,因此说是渐进最优的。
二进制共识(BA,Binary Agreement)和公共硬币(Common Coin)
BA算法使全网节点对一个二进制比特的值达成共识,即全网共同生成0或1。BA算法满足以下属性:
- 一致性(Agreement):如果任何正确的节点输出比特bbb,那么每个正确的节点都会输出bbb。
- 中止性(Termination):如果所有正确的节点都接收到了输入,则每个正确的节点都能产生输出。
- 有效性(Validity):如果有任何正确的节点输出了bbb,则至少有一个正确的节点接收bbb作为输入。
BA算法流程如下:
- 接收输入binputb_{input}binput后,设置est0:=binput\texttt{est}_0:=b_{input}est0:=binput,并在后续每轮中进行如下操作(以第rrr轮为例):
- 广播BVALr(b)\texttt{BVAL}_r(b)BVALr(b)
- 设置bin_valuesr(b):={}\texttt{bin{\_}values}_r(b):=\{\}bin_valuesr(b):={}
- 从f+1f+1f+1个节点接收到BVALr(b)\texttt{BVAL}_r(b)BVALr(b)后,如果还没有发送过BVALr(b)\texttt{BVAL}_r(b)BVALr(b),那么广播BVALr(b)\texttt{BVAL}_r(b)BVALr(b)
- 从2f+12f+12f+1个节点接收到BVALr(b)\texttt{BVAL}_r(b)BVALr(b)后,设置bin_valuesr(b)=bin_valuesr∪{b}\texttt{bin{\_}values}_r(b)=\texttt{bin{\_}values}_r\cup\{b\}bin_valuesr(b)=bin_valuesr∪{b}
- 当bin_valuesr(b)≠∅\texttt{bin{\_}values}_r(b)\neq \emptysetbin_valuesr(b)=∅时
- 广播 AUXr(w)\texttt{AUX}_r(w)AUXr(w),其中w∈bin_valuesrw \in \texttt{bin{\_}values}_rw∈bin_valuesr
- 等至少接收到N−fN-fN−f个AUXr\texttt{AUX}_rAUXr消息后,此时这些消息中包含的bbb值的集合vals\texttt{vals}vals为bin_valuesr\texttt{bin{\_}values}_rbin_valuesr的子集(因为在本步骤运行的时候,可能还会收到其他的BVALr\texttt{BVAL}_rBVALr加入bin_valuesr\texttt{bin{\_}values}_rbin_valuesr)
- s←Coinr⋅GetCoin()s \leftarrow \texttt{Coin}_{r} \cdot \texttt{GetCoin}()s←Coinr⋅GetCoin()
- 如果vals={b}\texttt{vals}=\{b\}vals={b},则
- estr+1:=b\texttt{est}_{r+1}:=bestr+1:=b
- 如果(b=s%2)(b=s\%2)(b=s%2)则输出bbb
- 否则estr+1:=s%2\texttt{est}_{r+1}:=s\%2estr+1:=s%2
- 继续循环,直到在某一轮输出值bbb,且对于r′>rr'>rr′>r,有Coinr′=b\texttt{Coin}_{r'}=bCoinr′=b。

论文中使用了基于阈值签名的公共硬币方案实现BA算法(即上述的GetCoin()\texttt{GetCoin}()GetCoin())。
算法中sid\texttt{sid}sid是一个唯一的随机数,可以看做是coin\texttt{coin}coin的名字 - 可信设置环节:由一个可信的分发方运行pk,{ski}←ThresholdSetuppk,\{sk_i\} \leftarrow \texttt{ThresholdSetup}pk,{ski}←ThresholdSetup来生成公共公钥和私钥碎片{ski}\{sk_i\}{ski},skisk_iski对应发放给PiP_iPi
- 当调用GetCoincoin\texttt{GetCoincoin}GetCoincoin时,广播ThresholdSignpk(ski,sid)\texttt{ThresholdSign}_{pk}(sk_i,\texttt{sid})ThresholdSignpk(ski,sid)
- 在接收到至少f+1f+1f+1个签名碎片后,将其合成为完整签名:sig←ThresholdCombinepk(ski,sid)\texttt{sig} \leftarrow \texttt{ThresholdCombine}_{pk}(sk_i,\texttt{sid})sig←ThresholdCombinepk(ski,sid),并用公钥验证ThresholdVerifypk(sid)\texttt{ThresholdVerify}_{pk}(\texttt{sid})ThresholdVerifypk(sid),若合法,则生成签名

说明: - 各方首先生成一个同样的一个二进制数bbb
- 之后通过一个公共的硬币来判断是否要取这个bbb作为最终的输出,如果不满足判断条件,那就进入下一轮,重复上述步骤
异步公共子集(ACS,Asynchronous Common Subset)
简而言之,网络中的各节点通过各自的输入,最终能经过ACS达成共识,生成一个一致的结果。ACS满足以下属性:
- Validity(有效性):如果一个正确的节点输出了集合v\textbf{v}v,那么∣v∣>N−f|\textbf{v}|>N-f∣v∣>N−f,且v\textbf{v}v至少包含N−2fN-2fN−2f个正确节点的输入
- Agreement(一致性):如果一个正确的节点输出了集合v\textbf{v}v,那么每个节点都会输出集合v\textbf{v}v。
- Totality(全局性):如果N−fN-fN−f个正确节点收到了输入,那么所有正确节点都会产生输出。
而ACS又是基于上述的RBC协议和BA算法来实现的。各个节点通过RBC协议广播自己对BA算法的输入,即所有节点并发地运行BA算法,最终形成一个长度为NNN的二进制值列表,由这个二进制列表来决定最终提交哪些交易。
ACS流程如下:
- 以{RBCi}N\{\texttt{RBC}_i\}_N{RBCi}N来表示RBC协议的NNN个实例,PiP_iPi对应为{RBCi}\{\texttt{RBC}_i\}{RBCi}的发送方。{BAi}N\{\texttt{BA}_i\}_N{BAi}N代表BA算法的NNN个实例。
- 接收到输入viv_ivi后,将其输入到RBCi\texttt{RBC}_iRBCi广播
- 在收到从RBCj\texttt{RBC}_jRBCj发送的vjv_jvj后,如果给BAi\texttt{BA}_iBAi输入,那么对BAi\texttt{BA}_iBAi输入1
- 如果已经接收到了至少N−fN-fN−f个BA\texttt{BA}BA实例传递的值 1 ,那么后续所有还未输入的BA\texttt{BA}BA实例都输入为0
- 一旦所有的BA\texttt{BA}BA实例都完成,令C⊂[1,...,N]C \subset{[1,...,N]}C⊂[1,...,N]表示为每个生成 1 的BA 实例的索引。等待每个RBCj\texttt{RBC}_jRBCj的输出vjv_jvj,其中j∈Cj \in Cj∈C。最终输出Uj∈CvjU_{j \in C^{v_j}}Uj∈Cvj。

论文对ACS的具体执行给出了图例解释:
从节点0的角度,他会收到来自节点1∼3(N=4,f=1)1\sim3(N=4,f=1)1∼3(N=4,f=1)的RBC广播,图中给出了三种不同的情况
- 正常情况下,节点0收到了节点1的广播RBC1\texttt{RBC}_1RBC1,则对BA1\texttt{BA}_1BA1输入1(1等价于yes)
- 节点0接收到RBC2\texttt{RBC}_2RBC2时已经收到了N−fN-fN−f个BA\texttt{BA}BA输出1,因此他对BA2\texttt{BA}_2BA2输入0,但由于其他节点已经收到了RBC2\texttt{RBC}_2RBC2并为BA2\texttt{BA}_2BA2输入1,因此最终BA2\texttt{BA}_2BA2仍然输出1
- RBC3\texttt{RBC}_3RBC3还未完成,BA3\texttt{BA}_3BA3就已经被输入0,且由于其他节点也没有为BA3\texttt{BA}_3BA3投票,因此最终BA3\texttt{BA}_3BA3输出0

说明
- 各方用RBC广播将自己的值viv_ivi,也会从RBC中接收其他节点的值vjv_jvj,同时运行NNN个BABABA算法,如果接收到了vjv_jvj,那对应的BAj\texttt{BA}_jBAj输入1
- 如果在N−fN-fN−f个BA\texttt{BA}BA算法中都已经输入了1,那后续其他的BA\texttt{BA}BA算法都输出0
- NNN个BABABA算法完成后,节点选择那些输出为1的BA算法所对应的vkv_kvk消息,由于BABABA算法的一致性,网络中所有节点都会作出相同的选择,即最终所有节点都选择了相同的消息vkv_kvk
共识流程
在了解了上述的构建块后,下面以节点PiP_iPi的角度,阐述Honey Badger BFT的共识流程。其中BBB是系统设定参数,rrr表示在第rrr轮。
- 节点PiP_iPi从自己的交易池的前BBB个交易中随机选择⌊B/N⌋\lfloor B / N\rfloor⌊B/N⌋个作为提案(proposed\texttt{proposed}proposed)
- 将提案加密x:=TPKE.Enc(PK,proposed)x:=\texttt{TPKE.Enc(PK,proposed)}x:=TPKE.Enc(PK,proposed)
- 将xxx作为ACS[r]\texttt{ACS}[r]ACS[r]的输入
- 从ACS[r]\texttt{ACS}[r]ACS[r]中接收{vj}j∈S\{v_j\}_{j \in S}{vj}j∈S,其中S⊂[1,...,N]S \subset [1,...,N]S⊂[1,...,N],
- 对于所有j∈Sj \in Sj∈S:
- 令ej:=TPKE.DecShare(SKi,vj)e_j:=\texttt{TPKE.DecShare}(SK_i,v_j)ej:=TPKE.DecShare(SKi,vj)
- 广播DEC(r,j,i,ej)\texttt{DEC}(r,j,i,e_j)DEC(r,j,i,ej)
- 从DEC(r,j,i,e(j,k))\texttt{DEC}(r,j,i,e_(j,k))DEC(r,j,i,e(j,k))接收至少f+1f+1f+1个消息
- 解码yj:=TPKE.Dec(PKi,{k,ej,k})y_j:=\texttt{TPKE.Dec}(PK_i,\{k,e_{j,k}\})yj:=TPKE.Dec(PKi,{k,ej,k})
- 令blockr:=sorted(Uj∈Cvj)\texttt{block}_r:=\texttt{sorted}(U_{j \in C^{v_j}})blockr:=sorted(Uj∈Cvj),sorted\texttt{sorted}sorted即对收集的交易排序,组成为区块blockr\texttt{block}_rblockr
- 设置buf:=buf-blockr\texttt{buf}:=\texttt{buf-block}_rbuf:=buf-blockr

说明: - 第一步中,随机选择交易是为了各个节点选择的交易尽可能不同(同一笔交易可能被发给了不同节点拿来构造区块)
- 将提案加密是为了防止审查攻击,以防止一些恶意节点在ACS中故意不给包含特定交易的节点投票
- 最终通过ACS生成一个共识列表(即在ACS中,BA输出为1的节点),各节点对成功共识的提案进行解密,生成解密碎片(share),收集到足够的碎片即可解密出交易内容
- 将交易构造成一个区块后即可上链,同时各节点将已经成功共识的交易从自己的交易池中删去。
HoneyBadgerBFT是一种异步共识协议,克服了异步网络中确定性共识的难题。它利用阈值加密、可靠广播协议、二进制共识和ACS来确保安全性与效率。协议通过RBC保证消息一致性,BA算法达成二进制比特共识,最后通过ACS形成一致的结果。这一创新设计解决了传统共识协议在网络条件变化时性能下降的问题。

5711

被折叠的 条评论
为什么被折叠?



