PBFT演算法簡介

2021-10-04 17:41:49 字數 4191 閱讀 6482

pbft(practical byzantine fault tolerance)演算法,是乙個能夠容忍拜占庭錯誤的分布式系統共識演算法。

首先這裡需要解釋上面幾個名詞:

拜占庭錯誤:

所謂拜占庭錯誤,通俗來講,可以理解**為的故意作惡導致的錯誤,相對於普通的宕機錯誤,拜占庭錯誤是一種有目的的作惡行為。之所以叫拜占庭錯誤,是因為這類共識一開始是要解決leslie lamport提出的「拜占庭將軍問題」

所謂的拜占庭將軍問題,就是一組拜占庭將軍約定分兵共同攻打一座城池,在是否發起總攻的問題上,拜占庭將軍之間需要通過信使交換訊息來得到最後的決定,當且僅當大部分將軍得到相同的結果(攻打或者撤退),才不會導致因為兵力不足攻打城池失敗。由於叛徒的存在,將軍可能會故意散布虛假訊息,偽造訊息等方式影響其他將軍的最終決策。這個共識問題也就是拜占庭將軍問題,而拜占庭錯誤則是指在分布式系統中,節點可以通過製造各種錯誤來影響其他節點的共識。

分布式系統與共識:

分布式系統是指該系統是由多個點對點的地位平等的節點組成系統,整個系統對外表現成乙個單一的系統,因此需要在節點和節點之間對系統的狀態形成一致性結果,即所謂的共識。

pbft到底解決了什麼問題?

簡單來說,pbft只是解決了乙個系統對系統操作的排序問題。我們知道,系統的當前的狀態 = 初始狀態 + 一些列有序狀態資料操作。將資料操作看做是一筆交易,則pbft就是解決在乙個可能出現拜占庭錯誤的分布式節點中如何對交易的順序達成共識的問題。

pbft是怎麼做的?

pbft將交易的排序問題分解成三部分,一部分是交易的提出(proposal),一部分是交易的投票,一部分是交易的提交(commit)。所謂commit,即是將該筆交易放在乙個特定的順位執行。

pbft要達到的效果是:在拜占庭節點(可能出現拜占庭錯誤的節點) 數量不超過1/3的條件下,系統中非拜占庭節點之間的狀態是一致的

pbft的思路是,只要保證每乙個proposal都是唯一且有序的&每一筆被commit的交易都對應乙個proposal&每乙個被commit的交易都會被超2/3的節點commit

上圖是pbft演算法流程圖,結合圖形說明pbft是如何完成上面所說的三個目標:

1. 「每乙個proposal都是唯一且有序的」

要實現這個效果非常簡單,只要給每乙個proposal賦值乙個序號n,同時每乙個非拜占庭節點約定不接受兩個具有相同的n值的proposal。因此,對於非拜占庭節點而言,每乙個被接收的proposal都是唯一且有序的。

2. 「每一筆被commit的交易都對應乙個proposal」

pbft演算法流程可以看做由無數的輪次組成,在每一輪中,有乙個proposal被提出,節點通過「少數服從多數」原則決定乙個proposal是否被commit。即,每乙個被commit的交易,首先是乙個proposal。

3. 「每乙個被commit的交易都會被超2/3的節點commit」

非拜占庭節點如何在乙個靠訊息通訊的分布式節點網路中保證自己commit的交易會被超過2/3的節點commit?可以繼續把這個條件拆分成兩個:1)確定乙個proposal被超過2/3得節點投票;2)確定超過2/3的節點都確認了條件1)

之所以需要同時滿足條件1)和2),是因為在乙個存在拜占庭節點網路中,節點自己接收到的訊息和其他節點接收到的訊息不一定是完全一樣的,原因是拜占庭節點可能會傳播虛假偽造的訊息,即從每乙個節點看到的「檢視」(view)不一定是一樣的。

pbft是如何保證條件1)和2)?

1)在pbft中,節點的通訊訊息使用非對稱加密來保證真實性。所謂非對稱加密,即對於乙個原文,用金鑰a加密之後,只能用乙個不同的金鑰b解密,反之亦然。因此,只要每乙個節點都有乙個公開的金鑰(公鑰),以及乙個私密的金鑰(私鑰),並使用私鑰來加密自己需要傳輸的訊息,就可以使得其他節點使用這個節點的公鑰來解密得到真實的訊息。對於任意乙個proposal的投票資訊,節點需要收集所有其他節點的投票資訊,即圖中prepare標註的部分——每乙個節點都會將自己的投票訊息廣播以便其他節點收集。只要節點收集到超過2/3個節點的投票訊息,就可以保證在本地節點的檢視中,序列號n對應的就是被投票的proposal。

簡單證明如下:假設系統中的節點總數為3f+1,系統中至多有f個拜占庭節點,節點a和b都接收到了關於(n,proposal),(n,proposal1)的超過2/3,即存在至少2f+1個節點投票了(n,proposal)以及至少2f+1個節點至少投票了(n,proposal1)。因為節點總數為3f+1,因為至少存在2f+1+2f+1-3f-1=f+1個節點既投了(n,proposal)又投了(n,proposal),即所謂的拜占庭節點,與假設矛盾,因此,不會出現同乙個序列化n,不同的proposal會同時被超過2/3的節點投票。

可以看到,只要滿足條件1),有且僅有乙個唯一的(n,proposal)會被超過2/3的節點投票。

2)條件1)對於乙個節點而言,只是本地看到的檢視,為了保證本地檢視也是全域性檢視,節點需要將在條件1被滿足之後,通過廣播通知所有其他節點,當乙個節點接收到超過2/3的節點傳送了針對同乙個(n,proposal)條件1)被滿足的通知,即可確定超過2/3的節點的檢視和本地檢視一致。即條件2)被滿足。

當然,上述的演算法流程只是保證了演算法的安全性(safety),即,對於非拜占庭節點而言,最終commit的proposal的順序一定是一致的。但是沒***演算法的活性(liveness)。

所謂活性,是指整個系統在持續不斷地形成共識。

活性的關鍵在於提出proposal的節點是否為非拜占庭節點,如果是,則通過上述演算法流程,最終該proposal會被commit,如果提出proposal的節點是拜占庭節點,則可能非拜占庭節點之間收到的proposal都是不一致的,當然就不可能達成條件1)。

要解決演算法的活性問題,乙個可行的方案是超時機制,因為無法實現知道哪個節點是非拜占庭節點,所以如果非拜占庭節點發現當前負責提出proposal的節點遲遲不能提出有效的proposal,就會觸發超時機制處理,從而挑選乙個新的節點負責提出proposal(leader節點)。

挑選新的leader節點,本質上也是一次共識,原則上需要首先提出乙個proposal來指定乙個節點當選,然後經過上述的共識流程來commit這個proposal從而實現leader的選舉。然而這樣是行不通的,因為需要挑選leader的原因就是現在proposal無法正常被提出。因此,leader的更換不能由proposal發起,而是應該按照乙個約定規則來確定下乙個當選leader的節點,當當前leader節點變成拜占庭節點後,所有其他節點會傳送乙個超時的投票給下乙個應該當選leader的節點,而該節點在接收到超過2/3節點的投票時,正式成為了新的leader。這個過程也就是pbft中所謂的view-change。

來復盤一下pbft演算法,整體上來看,整個演算法是分為三個階段,即,proposal的提出,proposal的投票,proposal的提交。每乙個階段都可以達到乙個具體的條件和目標,而三個條件和目標的達成之後,即可保證演算法的安全性。將演算法拆解成上述的三個階段解決了系統共識的安全性問題,但是同時也引入了乙個演算法活性問題,即僅僅依靠上述的三個階段的拆分是無法使得整個分布式系統持續的共識。pbft的做法是將活性的解決用共識本身來解決,即所謂的view-change階段來保證能夠在有限的時間內挑選乙個非拜占庭節點來當選leader,從而保證了上述階段的第乙個——proposal的提出。

本質上來說,pbft就是乙個使用「少數服從多數」原則來達成共識的演算法。但是同時pbft做了關鍵的基礎同步——包括節點的總數量,節點的檢視值(檢視值是挑選leader節點規則演算法的輸入值,只要檢視值一致,輸出的當選leader就一致),檢視超時時間等等。在理解pbft演算法的時候,需要結合演算法的假設前提以及演算法的規則本身。書不盡言,有興趣的同學可以繼續研究一下pbft演算法原文。筆者個人覺得lamport的**用詞精準,邏輯縝密,值得好好探索。

PBFT 拜占庭共識演算法

pbft演算法是根據拜占庭問題演變而來的拜占庭共識演算法。在拜占庭問題被提出後一直有各種共識演算法來解決拜占庭問題,但是無論從執行流程的複雜度還是演算法效率來說,pbft是目前公認效率最好的演算法。該演算法是miguel castro 卡斯楚 和barbara liskov 利斯科夫 在1999年提...

PBFT演算法 持續更新

bft是區塊鏈共識演算法中,需要解決的乙個核心問題。以位元幣和以太訪為代表的pow,eos為代表的dpos,以及今後以太訪逐漸替換的共識演算法pos,這些都是公鏈演算法,解決的是共識節點眾多情況下的bft 而pbft是在聯盟鏈共識節點較少的情況下bft的一種解決方案。pbft演算法由於每個副本節點都...

PBFT 拜占庭容錯演算法

根據 practical byzantine fault tolerance and proactive recovery 整理 practical byzantine fault tolerance and proactive recoverym.castro and b.liskov.2002....