引言
上一篇寫了分散式一致性協議相關理論與演算法,那些演算法不可用於區塊鏈系統之中,不可防止作惡情況,只能容忍節點當機、網路分割槽等情況。
這節,我們一起看看區塊鏈中常用的共識演算法。先來看看為什麼分散式網路需要共識?
兩軍問題
如圖,白軍軍隊實力強大,且居於要地,藍軍被白軍隔開成為了兩個軍隊,只有兩個藍軍達成一致(具體幾點幾分開始進攻白軍),方可戰勝白軍。但藍軍1、藍軍2要想達成一致,必須使用信使穿過白軍領地進行互相通訊,才能同時進攻取勝。但由於白軍可能抓捕信使,導致兩方藍軍無法達成共識情況。所以兩軍問題表達的是,通道不可信(訊息丟失,超時等),如果存在可信通道,則兩軍問題可解。
兩軍通訊,就像TCP的三次握手,需要雙方傳送並且得到反饋才能確認彼此以收到正確訊息達到共識。
拜占庭將軍問題
拜占庭將軍問題是一個共識問題: 首先是由萊斯利·蘭伯特(Leslie Lamport)及其他兩人於1982年提出,被稱為Byzantine Failure。核心描述是軍中可能有叛徒,卻要保證進攻一致。與分散式系統類比,節點中有作惡節點,也可能被黑客攻擊。
![](data:image/svg+xml;utf8,<?xml version="1.0"?>)
圖是醜了一點,大家將就了[捂臉哭]。
拜占庭帝國想要進攻一個強大的城市,為此派出了10支軍隊去包圍這個敵人。這個敵人雖不比拜占庭帝國,但也足以抵禦5支常規拜占庭軍隊的同時襲擊。基於一些原因,這10支軍隊不能集合在一起單點突破,必須在分開的包圍狀態下同時攻擊。他們任一支軍隊單獨進攻都毫無勝算,除非有至少6支軍隊同時襲擊才能攻下敵國。他們分散在敵國的四周,依靠通訊兵相互通訊來協商進攻意向及進攻時間。困擾這些將軍的問題是,他們不確定他們中是否有叛徒,叛徒可能擅自變更進攻意向或者進攻時間。在這種狀態下,拜占庭將軍們能否找到一種分散式的協議來讓他們能夠遠端協商,從而贏取戰鬥?這就是著名的拜占庭將軍問題。
應該明確的是,拜占庭將軍問題中並不去考慮通訊兵是否會被截獲或無法傳達資訊等問題,即訊息傳遞的通道是可信安全的。Lamport已經證明了在訊息可能丟失的不可靠通道上試圖通過訊息傳遞的方式達到一致性是不可能的。以下已假定通道是安全可靠的
這個問題說到底是一個關於一致性和正確性的演算法問題,這個演算法是針對的是忠誠的將軍,因為叛徒可以不傳,或者亂傳訊息搗亂。我們就是要在有叛徒的干擾下,找到一個容忍干擾的演算法——BFT(Byzantine fault tolerance)拜占庭容錯。
可以看出,兩軍問題是拜占庭將軍問題的特例。
什麼可以稱為拜占庭錯誤?
作惡節點,或者被黑客攻擊的節點。節點當機、網路分割槽、超時等都不是拜占庭錯誤。
如何解決拜占庭將軍問題?
司令副官模型
拜占庭將軍問題中:每一個將軍都需要與所有將軍進行通訊,已得知其他將軍的進攻安排,從而達到共識。所以拜占庭將軍問題可簡化為司令——副官模型。一個司令,多個副官,需要一致性協議保證,司令發出的命令,多個副官可以得到一致的結果。
一個司令把自己的命令傳遞給n-1個副官,使得:
一致性:所有忠誠的副官遵守一個命令(結果集中的大多數 n/2+1)。
正確性:若司令是忠誠的,每一個忠誠的副官遵守他發出的命令。(若將軍是作惡的,則只需要遵守第一條)
BFT為什麼需要節點數n>=3f+1?
f為拜占庭錯誤節點數,也是BFT可以容忍的叛徒數量。
反證法,如果n<3f+1 即當f= 1時,n = 3。
如果司令是忠誠的,一個副官忠誠,一個副官叛徒。當司令傳送進攻命令給兩個副官,兩個副官會彼此詢問司令的命令是什麼,這時候叛徒副官就會偽造假命令,說司令給他的命令是撤退,那忠誠副官就懵了,因為他收到的是進攻命令,此時忠誠副官不知道司令是叛徒還是另一個副官是叛徒。
如果司令是叛徒,兩個副官是忠誠的。司令分別給兩個副官一個進攻,一個撤退;兩個副官通訊時發現彼此收到的命令不一致,也無法達成共識。
所以得出n<3f+1時無法達到拜占庭容錯,需要n>=3f+1。具體推導可看參考裡的論文,或者李永樂老師的視訊。
PBFT(Practical Byzantine Fault Tolerance)
BFT假設通道沒有問題,也就是不考慮訊息不可達、訊息丟失、亂序、重複、網路分割槽等情況。Miguel Castro (卡斯特羅)和 Barbara Liskov (利斯科夫)在1999年發表的論文《 Practical Byzantine Fault Tolerance 》中首次提出 pbft 演算法,該演算法容錯數量也滿足 3f+1<=n。
pbft 演算法的基本流程主要有以下四步:
本作品採用《CC 協議》,轉載必須註明作者和本文連結