一種用於區塊鏈的拜占庭容錯演算法
張錚文 erik@vcage.com
摘要
本文提出了一種改進的拜占庭容錯演算法,使其能夠適用於區塊鏈系統。我們假設在此網路中,訊息可能會丟失、損壞、延遲、重複傳送,並且接受的順序與傳送的順序不一致。此外,節點的行為可以是任意的:可以隨時加入、退出網路,可以丟棄訊息、偽造訊息、停止工作等,還可能發生各種人為或非人為的故障。我們的演算法對由 ? 個共識節點組成的共識系統,提供 ? = ⌊ (?−1) / 3 ⌋ 的容錯能力,這種容錯能力同時包含安全性和可用性,並適用於任何網路環境。
概述
區塊鏈是一種去中心化的分散式賬本系統,它可以用於登記和發行數字化資產、產權憑證、積分等,並以點對點的方式進行轉賬、支付和交易。區塊鏈技術最早是由中本聰在一個密碼學的郵件列表中提出的 [1],也就是比特幣。此後,基於區塊鏈技術的各種應用紛紛出現,比如基於區塊鏈的電子現金系統、基於區塊鏈的股權交易系統、基於區塊鏈的智慧合約系統等。區塊鏈系統與傳統的中心化賬本系統相比,具有完全公開、不可篡改、防止多重支付等優點,並且不依賴於任何的可信第三方。
然而,和任何分散式系統一樣,區塊鏈系統會面臨網路延遲、傳輸錯誤、軟體錯誤、安全漏洞、黑客入侵等問題。此外,去中心化的特點決定了此係統的任何一個參與者都不能被信任,可能會出現惡意節點,以及因各方利益不一致導致的資料分歧等問題。
為了防範這些潛在的錯誤,區塊鏈系統需要一個高效的共識機制來確保每一個節點都有一個唯一公認的全域性賬本。傳統的針對某些特定問題的容錯方法,並不能完全解決分散式系統以及區塊鏈系統的容錯問題,人們需要一種能夠容忍任何種類錯誤的容錯方案。
比特幣採用工作量證明機制 [1],非常巧妙地解決了這個問題。但是代價也很明顯,那就是鉅額的電力成本和資源浪費。此外,新的區塊鏈必須尋找到一種與之不同的雜湊演算法,用於避免來自比特幣的算力攻擊,如萊特幣採用了與比特幣的 SHA256 不同的 SCRYPT 演算法。 拜占庭容錯技術是一種解決分散式系統容錯問題的通用方案 [5]。本文在 Castro 和 Liskov 於 1999 年提出的 Practical Byzantine Fault Tolerance(PBFT)[3] 的基礎上,提出了一種改進的拜占庭容錯演算法,使其能夠適用於區塊鏈系統。
系統模型
區塊鏈是一個分散式賬本系統,參與者通過點對點網路連線,所有訊息都通過廣播的形式來傳送。系統中存在兩種角色:普通節點和共識節點。普通節點使用系統來進行轉賬、交易等操作,並接受賬本中的資料;共識節點負責向全網提供記賬服務,並維護全域性賬本。 我們假設在此網路中,訊息可能會丟失、損壞、延遲、重複傳送,並且接受的順序與傳送的順序不一致。此外,節點的行為可以是任意的:可以隨時加入、退出網路,可以丟棄訊息、偽造訊息、停止工作等,還可能發生各種人為或非人為的故障。 我們採用密碼學技術來保證訊息傳遞的完整性和真實性,訊息的傳送者要對訊息的雜湊值進行簽名。我們定義 〈?〉?? 是節點 ? 對訊息 ? 的電子簽名,D(?)是訊息 ? 的雜湊值。如果沒有特殊說明,本文所規定的簽名都是對訊息雜湊值的簽名。
演算法
我們的演算法同時提供了安全性和可用性,只要參與共識的錯誤節點不超過 ⌊ (?−1) / 3 ⌋,就能保證整個系統正常運作,其中 ? = |?|表示參與共識的節點總數,? 是共識節點的集合。令 ? = ⌊ (?−1) / 3 ⌋,則 ? 就表示系統所容許的錯誤節點的最大數量。由於實際上全域性賬本僅由共識節點來維護,因此係統中的普通節點不參與共識演算法,但可以看到完整的共識過程。 參與共識的節點,需要維護一個狀態表,用於記錄當前的共識狀態。一次共識從開始到結束所使用的資料集合,稱為檢視。如果在當前檢視內無法達成共識,則需要更換檢視。我們為每一個檢視分配一個編號 ?,編號從 0 開始,並逐漸遞增,直到達成共識為止。 我們為每一個參與共識的節點分配一個編號,從 0 開始,最後一個節點的編號為 ? − 1。每一輪共識都需要有一個節點來充當議長,其它節點則為議員。議長的編號 ? 由如下的演算法來決定:假設當前共識的區塊高度為ℎ,則 ? = (ℎ − ?) ??? ?,其中 ? 的取值範圍為 0 ≤ ? < ?。每一次共識產生一個區塊,並附有至少 ? − ? 個共識節點的簽名。一旦有新的區塊產生,則立即開始新一輪的共識,同時重置 ? = 0。
一般流程
假設系統要求每次產生區塊的時間間隔為 ?,則在一切正常的情況下,演算法按照以下流程執行:
任意節點向全網廣播交易資料,並附上傳送者的簽名;
所有共識節點均獨立監聽全網的交易資料,並記錄在記憶體;
議長在經過時間 ? 後,傳送 〈??????????????,ℎ,?,?,?????,〈?????〉??〉;
議員 ? 在收到提案後,傳送 〈???????????????,ℎ,?,?,〈?????〉??〉;
任意節點在收到至少 ? − ? 個 〈?????〉?? 後,共識達成併發布完整的區塊;
任意節點在收到完整區塊後,將包含的交易從記憶體中刪除,並開始下一輪共識;
該演算法要求參與共識的節點中,至少有 ? − ? 個節點具有相同的初始狀態:即對於所有的節點 ?,具有相同的區塊高度 ℎ 和檢視編號 ?。而這個要求很容易達成:通過區塊同步來達到ℎ的一致性,通過檢視更換來達到 ? 的一致性。區塊同步不在本文討論範疇,不再贅述。檢視更換的規則見下文。
節點在監聽全網交易以及在收到提案後,需要對交易進行合法性驗證。如果發現非法交易,則不能將其寫入記憶體池;如果非法交易包含在提案中,則放棄本次共識並立即開始檢視更換。
交易的驗證流程如下:
交易的資料格式是否符合系統規則,如果不符合則判定為非法;
交易在區塊鏈中是否已經存在,如果存在則判定為非法;
交易的所有合約指令碼是否都正確執行,如果沒有則判定為非法;
交易中有沒有多重支付行為,如果有則判定為非法;
如果以上判定都不符合,則為合法交易;
檢視更換
當節點 ? 在經過 2?+1 ⋅ ? 的時間間隔後仍未達成共識,或接收到包含非法交易的提案後,開始進入檢視更換流程:
令 ? = 1,?? = ? + ?;
節點 ? 發出檢視更換請求 〈?ℎ????????,ℎ,?,?,??〉;
任意節點收到至少 ? − ? 個來自不同 ? 的相同 ?? 後,檢視更換達成,令 ? = ?? 並開始共識;
如果在經過 2?+1 ⋅ ? 的時間間隔後,檢視更換仍未達成,則 ? 遞增並回到第 2 步;
隨著 ? 的增加,超時的等待時間也會呈指數級增加,可以避免頻繁的檢視更換操作,並使各節點儘快對 ? 達成一致。
而在檢視更換達成之前,原來的檢視 ? 依然有效,由此避免了因偶然性的網路延遲超時而導致不必要的檢視更換。
流程圖
容錯能力
我們的演算法對由 ? 個共識節點組成的共識系統,提供 ? = ⌊ (?−1) / 3 ⌋ 的容錯能力,這種容錯能力同時包含安全性和可用性,並適用於任何網路環境。由於節點的請求資料包含傳送者的簽名,惡意的共識節點無法偽造請求,它只能試圖將系統的狀態回退到過去,從而使系統發生“分叉”。
我們假設系統所在的網路環境,恰好將所有共識節點分割成 3 個部分,即:? = ?1 ∪ ?2 ∪ ?,且 ?1 ∩ ?2 = ∅,?1 ∩ ? = ∅,?2 ∩ ? = ∅。假設 ?1 和 ?2 都由誠實的共識節點組成,且已形成網路孤島,各自只能與自己所在集合內的節點通訊;? 全部都是惡意共識節點且已經合謀,可以統一行動;此外,? 的網路條件允許它們和任意節點進行通訊,包括 ?1 和 ?2。 如果 ? 想要使系統發生“分叉”,只需與 ?1 達成共識併發布區塊,並在不通知 ?2 的情況下與之達成第二次共識,“撤銷”與 ?1 的共識。
若想滿足這個條件,需滿足:|?1| + |?| ≥ ? − ?,且|?2| + |?| ≥ ? − ?。在最壞的情況下,|?| = ?,即惡意節點的數量達到系統所能容忍的最大值,則上述關係變為: |?1| ≥ ? − 2?,且|?2| ≥ ? − 2?。兩式相加:|?1| + |?2| ≥ 2? − 4?,化簡後:? ≤ 3?。已知 ? = ⌊ (?−1) / 3 ⌋ ,與上式矛盾,故可證明系統在容錯範圍內無法被分叉。
參考文獻
[1] Nakamoto S. Bitcoin: A peer-to-peer electronic cash system[J]. 2008.
[2] Lamport L, Shostak R, Pease M. The Byzantine generals problem[J]. ACM Transactions on Programming Languages and Systems (TOPLAS), 1982, 4(3): 382-401.
[3] Castro M, Liskov B. Practical Byzantine fault tolerance[C]//OSDI. 1999, 99: 173
[4] Bracha G, Toueg S. Asynchronous consensus and broadcast protocols[J]. Journal of the ACM (JACM), 1985, 32(4): 824-840.
[5] 範捷, 易樂天, 舒繼武. 拜占庭系統技術研究綜述[J]. 軟體學報, 2013, 6: 012.
原文連結:docs.neo.org/zh-cn/basic…