1. 程式人生 > >區塊鏈時代的拜占庭容錯:Tendermint(四)

區塊鏈時代的拜占庭容錯:Tendermint(四)

原文題目:《Tendermint: Byzantine Fault Tolerance in the Age of Blockchains》

原文作者:Ethan Buchman

翻譯:潘振東

校對:杜滿想

本文為節選

 

構建應用

Tendermint被設計成為可複製的最終確定性狀態機的通用的演算法。它使用Tendermint套接字協議(TMSP)標準化共識引擎和狀態機之間的溝通,使得應用開發者可以用任何語言去構建他們的狀態機,並通過這種方式自動複製了基於Tendermit的BFT演算法。

 

背景

網際網路上的應用程式通常可以表徵為包含兩個基本要素:

  • 引擎:處理核心安全性,網路,複製。這通常像一個網路伺服器,如Apache或Nginx,可以構建Web應用程式,或者構建分散式應用程式的一致性演算法。

  • 狀態機:處理交易的實際應用程式邏輯,從引擎接收並更新內部狀態。

這種引擎和狀態機結構的分離使應用程式開發人員可以用任何程式語言編寫想要的應用程式的狀態機,在引擎之上可能專門定義其效能,安全性,可用性,支援性和其他考慮因素。與Web伺服器及其應用程式不同,後者通常採用的形式是程序通過公共閘道器介面(CGI)協議使用套接字進行通訊。而共識演算法一般來說要以更少的可用性或者更少的通用性介面來構建應用程式。像zookeeper,etcd,consul和其他分散式鍵值對儲存應用一樣,提供HTTP介面到簡單鍵值對應用程式的特定例項,還有一些更有趣的功能,如原子比較和交換操作並推送通知。但他們沒有給應用程式開發人員控制狀態機程式碼本身。

比特幣的成功以及源源不斷對區塊鏈技術的興趣產生了要對狀態機執行進行高級別的超越共識引擎的控制需求。通過構建更多高階應用直接進入共識,使用者,開發商,監管機構等等,可以在任意狀態機上實現更大的安全保障,遠遠超出鍵值對儲存,如貨幣,交易所,供應鏈管理 - 治理等等。它之所以引起了這麼多人的注意,是因為這個系統巨大的潛力是允許集體執行前執行程式碼。它實際上是對許多方面的重新發明法律制度,使用分散式共識演算法和確定性可執行合同,而不是警察,律師,法官,陪審團和個人喜好。這對人類社會發展的影響是爆炸性的,就像引入民主法治一樣。Tendermint旨在提供基本的介面和共識引擎可以構建此類應用程式。

 

Tendermint 套接字協議

Tendermint套接字協議(TMSP)定義了共識引擎和應用程式狀態機之間通訊的核心介面。這個介面定義包括一系列的訊息型別,使用Google’s Protocol Buffers (一個長度作為字首通過套接字傳輸的協議),一系列的訊息型別,他們的引數,返回值和用途都在圖5.1中,整體的結構和訊息流程也在圖5.2中。

圖5.1

Golang定義的TMSP Application interface,TMSP訊息被定義為使用Google’s Protocal Buffers,序列化格式是通過TMSP套接字傳輸之前將長度作為字首,返回值包括一個程式碼,和HTTP的狀態碼類似,代表了任意的錯誤資訊,0表示沒有錯誤,訊息在客戶端快取直到一個flush訊息被髮出,在這個點所有的快取訊息都會被髮出。服務端設計的是非同步化的,訊息返回必須是和請求相匹配的正確的順序。

圖5.2

共識邏輯與應用程式邏輯進行通訊是通過TMSP(套接字協議)。維護兩個sockets(套接字),一個用於mempool檢查新交易的有效性,另一個用於執行共識的新提交的塊。

TMSP協議被實現為一個有序的非同步的服務,訊息型別請求和返回是成對的,當一個特殊的訊息型別出現的時候,清空並通過連線推送快取的所有訊息然後等待訊息。

在TMSP協議有兩種訊息是核心,AppendTx 和Commit,一旦塊由共識產生,引擎就會在塊上呼叫AppendTx處理每個塊中的交易,將其傳遞給應用程式狀態機處理。如果交易有效,則會導致應用程式中的狀態轉換。

一旦所有AppendTx呼叫返回,共識引擎呼叫Commit,使得應用程式提交到最新狀態,並將其永久儲存到磁碟。

 

分離協議和執行

使用TMSP可以使我們明確區分共識,或者關於交易順序的協議,以及它們在狀態機中的實際執行情況。特別是,我們首先就順序達成共識,並且然後按順序執行交易。這種分離實際上有所提升系統的容錯,但是仍然需要總數3f + 1個節點去容忍f個拜占庭式節點的失敗,只需要2f + 1個節點執行。也就是說,雖然我們仍需要三分之二的多數來排序,我們只需要一半的多數來執行。

另一方面,事實上交易的執行放在排序之後會導致可能是無效的交易,這可能會浪費系統資源。這種情況使用額外的TMSP訊息CheckTx解決的,由mempool呼叫,允許它檢查交易是否會對最新的狀態有效。但請注意,事實上塊中的一次性提交會引起CheckTx處理訊息的複雜性。特別是,應用程式希望維護第二個狀態機只執行主狀態機相關的交易有效性的規則。第二個狀態機由CheckTx訊息更新狀態並在每次提交後重置為最新的已提交狀態。在本質上,第二個狀態機描述了交易池的過濾規則。 

在某種程度上,CheckTx可以用作`樂觀的執行`返回並將結果傳送給交易傳送者,但結果可能是錯誤的,比如一個帶有衝突交易的塊在利息交易之前提交。這種`樂觀的執行`是擴充套件BFT系統的方法的關注焦點,可以很好地適用於交易之間衝突很少的應用程式。與此同時,它增加了客戶端的額外複雜性,因為可能需要處理無效的結果。

 

微服務架構

採用分離關注點作為應用程式設計的策略是從普遍上來看是明智的做法。特別是,許多當今的大規模應用部署採用微服務架構。其中每個功能元件實現為獨立的網路服務,通常封裝在Linux容器中(例如使用Docker)以提高部署效率,可伸縮性和可升級性。

在Tendermint共識之上執行的應用程式通常會被分解成微服務,例如,許多應用程式將使用一個鍵值對儲存用於儲存狀態。為了利用資料儲存的優勢和某些特有功能,將鍵值儲存作為獨立執行的服務很常見,如高效能資料型別或默克而樹。
應用程式的另一個重要的微服務是治理模組,它管理某個TMSP訊息子集,啟用該應用程式控制驗證器集更改。這樣的模組可以在BFT中變成強大系統治理正規化。 

某些應用程式可能為使用者使用本機貨幣或帳戶結構,因此,提供支援基本元素的模組是有用的,例如,處理數字簽名和管理賬戶動態。用微服務構成複雜TMSP應用程式例子還有很多。實際上,人們甚至可以構建一個可以啟動的,包含了使用交易中傳送的資料的子應用程式的應用程式。例如,在交易中包含了一個儲存docker映象的雜湊,以便從一些檔案儲存後端pull下來執行並作為未來的子應用程式執行共識中的交易以導致其執行。這是以太坊使用的方法,允許開發人員將一些程式碼部署到網路中可以通過上面的方式觸發在以太坊虛擬機器中執行交易(智慧合約),以及IBM最近的OpenBlockChain(OBC)專案,它允許開發人員在交易中傳送完整的docker上下文,定義執行任意程式碼以響應發往他們地址的交易的容器。

 

確定性

關於使用TMSP構建應用程式的最為嚴格的忠告是他們必須是確定性的,也就是說,對於複製狀態機而言不保證安全。每個節點在執行時針對同一狀態的同一交易必須獲得相同的結果。這不是Tendermint的獨特要求。比特幣,raft,以太坊,任何其他分散式共識演算法,以及鎖步等多人遊戲必須嚴格具有確定性,以免達成共識失敗。程式語言中有許多非確定性的來源,最明顯的是通過隨機數和時間,但也可以通過使用浮點精度,並通過雜湊表迭代(一些諸如Go之類的語言強制對雜湊表進行隨機迭代程式設計師明確何時需要有序資料結構)。對確定性機制的嚴格限制,以及確定性在每種主流程式語言中的缺失,促使以太坊開發自己的,圖靈完備的,完全確定的虛擬機器,它構成了應用程式開發人員在以太坊區塊鏈之上構建應用程式的平臺。雖然確定性,它有許多特別之處,例如32位元組堆疊字,儲存鍵和儲存值,不支援位元組位移操作,一切都是大數算術。確定性程式設計在實時世界中得到充分研究,例如鎖步,多方遊戲。這類遊戲構成了另一個複製狀態機的例子。並且在許多方面與共識演算法非常相似。鼓勵使用TMSP構建的應用程式開發人員進行學習使用他們的方法,並在實現應用程式時要小心。使用函數語言程式設計語言和證明方法可以啟用正確程式的構建。在另一方面,編譯器也在構建以將可能的非確定性程式轉換為規範化確定性的。

 

終止性

如果說確定性是為了保證安全很嚴格,那麼交易執行的終止性就是為了嚴格的保證存活。然而,它不是一般的可以確定給定程式是否因單個輸入而停止,更不用說所有這些問題,這個問題被稱為停機問題。

以太坊的虛擬機器通過計量解決問題,具體來說,在執行中的每個操作收費。這樣,交易就保證在發起者資金不足時終止。這樣的計量在更一般的情況下,可以通過編譯程式的編譯器實現計量他們自己的版本。

沒有顯著的開銷就很難解決這個問題。在本質上,驗證器無法判斷執行是處於無限迴圈中還是隻是緩慢,但幾乎完成。可以使用Tendermint共識協議決定交易超時,超過三分之二的驗證人必須同意交易超時,因此被視為無效(即對狀態沒有影響)。但是,我們沒有在這裡進一步實踐這個想法,留待未來的工作。同時,預計應用程式將在進行全面測試之前部署在任何共識系統中,監控和治理機制在達成共識的情況下,將用來恢復系統失敗。

 

舉個例子

在本節中,將介紹和討論越來越複雜的TMSP應用程式,特別是CheckTx和管理mempool。

Merkleeyes

TMSP應用程式的一個簡單示例是基於Merkle樹的鍵值儲存。Tendermint提供Merkleeyes,這是一個包裝的TMSP應用程式,一個自平衡的Merkle二元搜尋樹。交易的第一個位元組確定交易是get,set還是delete操作。對於get,delete操作,剩餘的位元組是鍵(key)。對於set操作,其餘位元組是包含鍵和值的序列化列表。Merkleeyes可能使用CheckTx的簡單實現對交易進行解碼,以確保其格式正確。也可以實現更高階的CheckTx,get和delete操作對未知key無效。呼叫Commit後,將新增最新更新進入Merkle樹,重新計算所有雜湊值,樹的最新狀態也在磁碟上提交儲存。

請注意,Merkleeyes被設計為其他TMSP應用使用的基於Merkle樹的鍵值儲存的模組。而不是單獨的TMSP應用程式,雖然TMSP介面的簡單性使它適用於兩者。

貨幣應用

一個更重要的完整例項是一個簡單的貨幣,用的賬戶結構由以太坊創立,每個使用者都有一個公鑰和一個基於該公鑰的帶有餘額的賬戶,該帳戶還包含一個序列號,等於帳戶傳送的交易數量。交易可以從賬戶傳送資金,如果它們包括正確的序列號,並由正確的私鑰簽名。沒有序列號,系統容易受到重放攻擊,可以重播從帳戶中扣除帳戶的已簽名交易,從而導致借記多次發生。此外,防止重放攻擊在多鏈環境中,交易簽名應包括網路或區塊鏈識別符號。

一個支援貨幣職能的應用程式自然具有比鍵值儲存更多的邏輯。特別是,某些交易明顯無效,例如簽名無效,序列號不正確或傳送超過發起人帳戶餘額的金額。這些情況都可以通過CheckTx檢查。

此外,必須在CheckTx中維護補充應用程式狀態是為了在更新時更新序列號和帳戶餘額當同時在mempool中有多個涉及相同帳戶的交易時。呼叫commit時,將重置補充應用程式狀態到最新的提交狀態。任何仍在mempool中的交易都可以通過CheckTx重播最新狀態。

以太坊

以太坊使用已經描述的機制來過濾掉mempool中的交易,但它也在虛擬機器中執行一些交易,它會更新狀態並返回結果。虛擬機器執行沒有在CheckTx中完成,因為它們包含在塊中,它更昂貴且嚴重依賴交易的最終順序。

 

總結

TMSP提供了一種簡單而靈活的方法來構建任意應用程式,可以用任何程式語言,繼承複製自Tendermint一致性演算法的BFT狀態機。它扮演的角色大致類似於共識引擎和一個應用程式。例如,CGI扮演為Apache和Wordpress。但是,應用程式開發人員必須特別注意確保他們的應用程式是確定性的,並確保交易執行終止。

 

相關閱讀:

區塊鏈時代的拜占庭容錯:Tendermint(一)

區塊鏈時代的拜占庭容錯:Tendermint(二)

區塊鏈時代的拜占庭容錯:Tendermint(三)