HyperLedger Fabric共識演算法

2021-09-29 18:36:46 字數 3606 閱讀 3740

當前在聯盟鏈的應用場景中,使用的共識演算法有3種:solo、kafka和pbft(拜占庭容錯)。

在hyperledger fabric中的solo模式的共識演算法,是最簡單的一種共識演算法,只有乙個排序節點(order)接收客戶端peer節點訊息,並完成排序,按照order節點的排序結果進行生成區塊和上鏈處理。此種模式只能在測試環境中使用,不適合生產環境大規模使用。

由一組orderer節點組成排序服務節點,與kafka集群進行對接,利用kafka完成訊息的共識功能。

客戶端peer節點向orderer節點集**送訊息後,經過orderer節點組的背書後,封裝成kafka訊息格式,然後發往kafka集群,完成交易資訊的統一排序。如果聯盟鏈中有多個channel,在kafka中實現就是按照每個channel乙個topic的設定,每個channel都有一條鏈。

此部分內容介紹摘自:共識演算法:pbft、raft

pbft演算法的提出主要是為了解決拜占庭將軍問題。什麼是拜占庭將軍問題呢?拜占庭位於如今的土耳其的伊斯坦堡,是古代東羅馬帝國的首都。拜占庭羅馬帝國國土遼闊,為了達到防禦目的,每塊封地都駐紮一支由將軍統領的軍隊,每個軍隊都分隔很遠,將軍與將軍之間只能靠信差傳遞訊息。 在戰爭的時候,拜占庭軍隊內所有將軍必需達成一致的共識,決定是否有贏的機會才去攻打敵人的陣營。但是,在軍隊內有可能存有叛徒和敵軍的間諜,左右將軍們的決定影響將軍們達成一致共識。在已知有將軍是叛徒的情況下,其餘忠誠的將軍如何達成一致協議的問題,這就是拜占庭將軍問題。

要讓這個問題有解,有乙個十分重要的前提,那就是通道必須是可靠的。如果通道不能保證可靠,那麼拜占庭問題無解。關於通道可靠問題,會引出兩軍問題。兩軍問題的結論是,在乙個不可靠的通訊鏈路上試圖通過通訊以達成一致是基本不可能或者十分困難的。

在聯盟鏈的場景下,預設通道都是可靠的。

拜占庭將軍問題最早是由leslie lamport與另外兩人在2023年發表的**《the byzantine generals problem 》提出的, 他證明了在將軍總數大於3f ,背叛者為f 或者更少時,忠誠的將軍可以達成命令上的一致,即3f+1<=n。演算法複雜度為o(n(f+1))。而miguel castro (卡斯楚)和barbara liskov(利斯科夫)在2023年發表的**《practical byzantine fault tolerance》中首次提出pbft演算法,該演算法容錯數量也滿足3*f+1<=n,演算法複雜度為o(n^2).

因為pbft演算法的除了需要支援容錯故障節點之外,還需要支援容錯作惡節點。假設集群節點數為n,有問題的節點為f。有問題的節點中,可以既是故障節點,也可以是作惡節點,或者只是故障節點或者只是作惡節點。那麼會產生以下兩種極端情況:

pbft演算法的基本流程主要有以下四步:

如下圖所示:

演算法的核心三個階段分別是pre-prepare階段(預準備階段),prepare階段(準備階段),commit階段(提交階段)。圖中的c代表客戶端,0,1,2,3代表節點的編號,打叉的3代表可能是故障節點或者是問題節點,這裡表現的行為就是對其它節點的請求無響應。0是主節點。整個過程大致是:

什麼是checkpoint呢?checkpoint就是當前節點處理的最新請求序號。前文已經提到主節點收到請求是會給請求記錄編號的。比如乙個節點正在共識的乙個請求編號是101,那麼對於這個節點,它的checkpoint就是101.

那什麼是stable checkpoint(穩定檢查點)呢?stable checkpoint就是大部分節點(2*f+1)已經共識完成的最大請求序號。比如系統有4個節點,三個節點都已經共識完了的請求編號是213.那麼這個213就是stable checkpoint了。

那設定這個stable checkpoint有什麼作用呢?最大的目的就是減少記憶體的占用。因為每個節點應該記錄下之前曾經共識過什麼請求,但如果一直記錄下去,資料會越來越大,所以應該有乙個機制來實現對資料的刪除。那怎麼刪呢?很簡單,比如現在的穩定檢查點是213,那麼代表213號之前的記錄已經共識過的了,所以之前的記錄就可以刪掉了。

那什麼是高低水位呢?下面以乙個示意圖來進行解釋。

舉個例子:如果b當前的checkpoint已經為1034,而a的checkpoint還是1039,假如有新請求給b處理時,b會選擇等待,等到a節點也處理到和b差不多的請求編號時,比如a也處理到1112了,這時會有乙個機制更新所有節點的stabel checkpoint ,比如可以把stabel checkpoint設定成1100,於是b又可以處理新的請求了,如果l保持100不變,這時的高水位就會變成1100+100=1200了。

當主節點掛了(超時無響應)或者從節點集體認為主節點是問題節點時,就會觸發viewchange事件,viewchange完成後,檢視編號將會加1。

下圖展示viewchange的三個階段流程:

如圖所示,viewchange會有三個階段,分別是view-change,view-change-ack和new-view階段。從節點認為主節點有問題時,會向其它節點傳送view-change訊息,當前存活的節點編號最小的節點將成為新的主節點。當新的主節點收到2f個其它節點的view-change訊息,則證明有足夠多人的節點認為主節點有問題,於是就會向其它節點廣播

new-view訊息。注意:從節點不會發起new-view事件。對於主節點,傳送new-view訊息後會繼續執行上個檢視未處理完的請求,從pre-prepare階段開始。其它節點驗證new-view訊息通過後,就會處理主節點發來的pre-prepare訊息,這時執行的過程就是前面描述的pbft過程。到這時,正式進入 v+1(檢視編號加1)的時代了。

為了更清晰的展現viewchange這個過程和一些細節,下面以流程圖來表示這個過程。

上圖里紅色字型部分的o集合會包含哪些pre-prepare訊息呢?假設o集合裡訊息的編號範圍:(min~max),則min為v集合最小的stable checkpoint,max為v集合中最大序號的prepare訊息。最後一步執行o集合裡的pre-preapare訊息,每條訊息會有兩種情況: 如果max-min>0,則產生訊息;如果max-min=0,則產生訊息。

pbft演算法,核心過程有三個階段,分別是pre-prepare(預準備)階段,prepare(準備)階段和commit(提交)階段。對於pre-prepare階段,主節點廣播pre-prepare訊息給其它節點即可,因此通訊次數為n-1;對於prepare階段,每個節點如果同意請求後,都需要向其它節點再 廣播parepare訊息,所以總的通訊次數為n(n-1),即n2-n;對於commit階段,每個節點如果達到prepared狀態後,都需要向其它節點廣播commit訊息,所以總的通訊次數也為n*(n-1),即n2-n。所以總通訊次數為(n-1)+(n2-n)+(n2-n),即2n2-n-1,因此pbft演算法複雜度為o(n2)。

對於pbft演算法,共識過程就是:老大向我傳送命令時,當我認為老大的命令是有問題時,我會拒絕執行。就算我認為老大的命令是對的,我還會問下團隊的其它成員老大的命令是否是對的,只有大多數人(2f+1)都認為老大的命令是對的時候,我才會去執行命令。那什麼時候重選老大呢?老大掛了當然要重選,如果大多數人都認為老大不稱職或者有問題時,我們也會重新選擇老大。

Hyperledger Fabric 背書策略

背書策略是為了告知peer節點,交易是否被正確的背書。當peer接收到乙個交易到時候,它將會invoke與交易相關的chaincode的vscc validation system chaincode 作為交易驗證流的一部分,來驗證交易的有效性。recall that a transaction c...

Hyperledger Fabric網路節點架構

fabric網路節點的組成如下圖 客戶端必須連線到某乙個peer節點或者排序服務節點才可以與區塊鏈網路通訊。peer節點主要負責通過執行鏈碼 chaincode 實現對賬本的讀寫操作。所有的peer節點都是記賬節點 committer 負責維護狀態資料和賬本的副本。部分peer節點根據背書策略的設定...

Hyperledger Fabric(私有資料)

如果某個通道上的一組組織需要將該資料與該通道上的其他組織保密,他們可以選擇建立乙個新通道,只包含需要訪問資料的組織。但是,在每種情況下建立單獨的通道會產生額外的管理開銷 維護鏈碼版本,策略,msp等 並且不允許你希望所有通道參與者在保持部分資料私有的情況下檢視交易的用例。這就是為什麼從v1.2開始,...