1. 程式人生 > >拜占庭共識Tendermint介紹及簡單入門

拜占庭共識Tendermint介紹及簡單入門

1.Tendermint是什麼

  Tenermint 是一個軟體,用於在多臺機器安全一致地複製一個應用。所謂安全,指的是即使有多達 1/3 的機器出現任意故障的情況下, Tendermint 仍然能夠正常工作。所謂一致,指的是每一個正常工作的機器都會有著同樣的交易日誌,計算相同的狀態。安全一致的複製是分散式系統中一個至關重要的問題:從貨幣到選舉,到基礎設施規劃,它在廣泛應用的容錯中承擔了一個極其重要的角色。

  能夠容忍機器以任何一種,甚至包括危害系統的方式發生故障,被稱為拜占庭容錯(BFT)。拜占庭理論已經有幾十年的歷史,但是很大程度上,直到最近像比特幣,以太坊這樣區塊鏈技術的成功,它的軟體實現才得以進一步發展。區塊鏈技術只是以一種現代化的方式對 BFT 的再形式化,而且重點關注 p2p 網路和密碼驗證。區塊鏈這個名詞來源於交易的處理方式,通過區塊的批量方式處理交易,每個塊包含了前一個塊的加密雜湊,以此來形成一個鏈。實際上,區塊鏈資料庫真正地優化了 BFT 設計。

  Tendermint 包含了兩個主要的技術元件:一個區塊鏈共識引擎和一個通用的應用程式介面。共識引擎,叫做 Tendermint Core,保證了每一臺機器以相同的順序記錄同一筆交易。應用程式介面,叫做應用程式區塊連結口(ABCI),保證了交易可以通過任何一種程式語言進行處理。與其他預先打包內建狀態機(比如鍵值儲存或者一個奇怪的指令碼語言)的區塊鏈和共識方案不同,開發者可以使用 Tendermint 實現應用的 BFT 狀態機複製,而這些應用可以用任何語言編寫,而且開發環境對開發者也十分友好。
  Tendermint 的設計原則是易使用,易理解,高效能,對於各種分散式應用都十分有用。
  Tendermint 說明文件:

https://tendermint.readthedocs.io/en/master/
  Tendermint 地址:https://github.com/tendermint/tendermint

Tendermint 與其他技術的比較

  大體上, Tendermint 與兩類軟體很類似。第一類包含了分散式的鍵值儲存,比如 Zookeeper,etcd 和 consul,它們都使用了非拜占庭容錯共識。第二類就是 “區塊鏈技術”,它既包括了像比特幣和以太坊這樣的加密貨幣,也包括了像 Hyperledger Burrow 這樣的分散式賬本設計。

Zookeeper, etcd, consul

  Zookeeper,etcd 和 consul 都是在一個經典的非拜占庭容錯共識演算法上, 實現了一個鍵值儲存。Zookeeper 使用了 Paxos 一個叫做 Zookeeper Atomic Broadcast 的版本,而 etcd 和 consul 則使用了更年輕,也更簡單的 Raft 共識演算法。一個典型的叢集由 3-5 臺機器構成,雖然可以承受 1/2 的機器發生問題,但是隻要發生一次拜占庭故障,整個系統就可能被摧毀。它們每一個都提供了一個稍微有別於鍵值儲存的實現,但是都將關注點放在提供分散式系統的基礎服務上,比如動態配置,服務發現,鎖定,領導人選取等等。
Tendermint 是一個本質上類似的軟體,不過有兩點關鍵不同:它是拜占庭容錯的,這意味著它可以承受 1/3 機器發生任意形式的故障 – 包括黑客和惡意攻擊。
  它並不像鍵值儲存,是針對某一指定型別的應用。相反,它關注於任意的狀態機複製,因此開發者可以量身打造適合自己的應用邏輯,從鍵值儲存到加密貨幣到電子投票平臺,甚至更多的應用都可適用。

Bitcoin, Ethereum, etc.

  在比特幣和以太坊這樣的傳統加密貨幣下出現了 Tendermint,它的目的在於提供一個比比特幣的工作量證明更加有效和安全的共識演算法。在早期,Tendermint 內建了一個簡單的貨幣來參與共識,使用者必須向一個保證金賬戶中“繫結”一定數量的貨幣,如果他們表現不端,這些錢就會被收回 – 這一點使得 Tendermint 成為一個 POS 演算法。
  自那時起,Tendermint 就進化為一個能夠承載任意應用狀態的通用區塊鏈共識引擎。這意味著它可以成為其他區塊鏈軟體共識引擎的一個即插即用的替代品。所以基於當前的以太坊程式碼庫,無論是用何種語言, Rust,Go,Haskell,任何人都可以使用 Tendermint 共識執行一個 ABCI 應用。實際上,我們已經完成了這一點(ethermint)。此外,我們也計劃為 Bitcoin,ZCash,和其他確定性的應用完成同樣的工作。另一個基於 Tendermint 構建的加密貨幣應用是 Cosmos。

Fabric, Burrow

  Fabric 0.6 採用了與 Tendermint 類似的方法,但是它更關注對狀態的管理,並且要求所有的應用行為能夠在多個 docker 容器,叫做 “chaincode” 的模組中執行。它使用了來自 IBM (augmented to handle potentially non-deterministic chaincode) 的 PBFT 實現。通過擴充套件 Tendermint 來處理未來工作中存在的不確定性,在 Tendermint 中通過一個 ABCI 應用實現這個基於 docker 的行為是完全有可能的。Burrow 是一個以太坊虛擬機器和以太坊交易機制的實現,同時附帶有名字註冊,許可權和天然合約,可替代區塊鏈 API 等額外特性。它使用 Tendermint 作為它的共識引擎,提供一個特殊的應用狀態。

2. 什麼是 ABCI (應用區塊連結口)

區塊鏈應用介面(Application BlockChain Interface,ABCI)允許應用的拜占庭容錯複製可以由任意一種程式語言編寫。
  Tendermint Core (“共識引擎”)通過一個滿足 ABCI 標準的 socket 協議與應用進行交流。
  舉個大家比較熟悉的例子,比特幣。比特幣是一個加密貨幣區塊鏈,其中的每個節點維護了一個完全經過審計的 UTXO 資料庫。如果有人想要在 ABCI 之上建立一個類似比特幣的系統,Tendermint Core 將會負責:

  • 在節點間共享區塊和交易
  • 建立交易(區塊鏈)的標準/不可變順序

而應用將會負責:

  • 維護 UTXO 資料庫
  • 驗證交易的加密簽名
  • 阻止花費尚未存在的交易
  • 允許客戶端查詢 UTXO 資料庫

ABCI 包含了 3 個主要的訊息型別,它們由 core 傳送至應用,應用會對訊息產生相應的回覆:
  DeliverTx 訊息是應用的主要部分。鏈中的每筆交易都通過這個訊息進行傳送。應用需要基於當前狀態,應用協議,和交易的加密證書上,去驗證接收到 DeliverTx 訊息的每筆交易,。一個經過驗證的交易然後需要去更新應用狀態 – 比如通過將繫結一個值到鍵值儲存,或者通過更新 UTXO 資料庫。
  CheckTx 訊息類似於 DeliverTx,但是它僅用於驗證交易。Tendermint Core 的記憶體池首先通過 CheckTx 檢驗一筆交易的有效性,並且只將有效交易中繼到其他節點。比如,一個應用可能會檢查在交易中不斷增長的序列號,如果序列號過時,CheckTx 就會返回一個錯誤。又或者,他們可能使用一個基於容量的系統,該系統需要對每筆交易重新更新容量。
  Commit 訊息用於計算當前應用狀態的一個加密保證(cryptographic commitment),這個加密保證會被放到下一個區塊頭。這有一些比較方便的屬性。現在,更新狀態時的不一致性會被認為是區塊鏈的分支,分支會捕獲所有的程式設計錯誤。這同樣也簡化了保障輕節點客戶端安全的開發,因為 Merkel-hash 證明可以通過在區塊雜湊上的檢查得到驗證,區塊鏈雜湊由一個 quorum 簽署。
  一個應用可能有多個 ABCI socket 連線。Tendermint Core 給應用建立了三個 ABCI 連線:一個用於記憶體池廣播時的交易驗證,一個用於執行提交區塊時的共識引擎,還有一個用於查詢應用狀態。
  很顯然,在建立區塊鏈時,應用的設計者需要非常小心地設計他們的訊息處理,這個架構提供一個範例。下圖闡釋了通過 ABCI 的訊息流:
  這裡寫圖片描述

3. 共識概述

  Tendermint 是一個易於理解,大部分操作為非同步的 BFT 共識協議。下圖是一個簡單的狀態機,它展示了協議遵循的規則:
這裡寫圖片描述
  協議中的參與者叫著 “驗證人”(validator)。他們輪流對交易區塊進行提議,並對這些區塊進行投票。區塊會被提交到鏈上,每一個塊佔據一個“高度”(height)。提交塊可能會失敗,如果失敗,協議就會開始下一輪的提交,並且一個新的驗證人會繼續提交那個高度的區塊。要想成功提交一個塊,需要有兩個階段的投票:“預投票”(pre-vote)和“預提交”(pre-commit)。在同一輪提交中,只有超過 2/3 的驗證人對同一個塊進行了預提交,這個塊才能被提交到鏈上。
  上圖右下角有一對夫婦在跳波卡舞,因為驗證人做的事情就像是在跳波卡舞。當超過 2/3 的驗證人對同一個塊進行了預投票,我們就把它叫做一個“波卡”(polka)。每一個預提交都必須被同一輪中的一個波卡所證明。
  由於一些原因,驗證人可能在提交一個塊時失敗:當前提議者可能離線了,或者網路非常慢。Tendermint 允許他們證實一個驗證人應該被跳過。在進行下一輪的投票前,驗證人會等待一小段時間從提議者那裡接收一個完整的提議塊。這種對於超時的依賴,使得 Tendermint 成為了一個弱同步協議,而非一個非同步協議。但是,協議的剩餘部分都是非同步的,只有在接收到超過 2/3 的驗證人集合時,驗證人才會採取下一步操作。Tendermint 能夠簡化的一個原因就是它使用了同樣的機制來提交一個塊和跳過直接進入下一輪。
  基於不到 1/3 的驗證人是拜占庭節點的前提,Tendermint 保證了永遠都不會違背其安全性 – 也就是說,驗證人永遠不會在同一高度提交衝突塊。為了達到這一點,它引入了一些 “鎖定”(locking)的規則,這些規則對流程圖中的路徑進行了模組化。一旦一個驗證人預提交了一個塊,它就被“鎖定”在了那個塊上。然後,
1. 它必須為被鎖定的那個塊進行預投票
2. 只有在之後的輪中,有了那個塊的一個波卡,它才能夠解鎖,併為一個新塊進行預提交。

4. 簡單入門

下載編譯

mkdir -p $GOPATH/src/github.com/tendermint
cd $GOPATH/src/github.com/tendermint
git clone https://github.com/tendermint/tendermint.git
cd tendermint

linux環境編譯:

make get_tools
make get_vendor_deps
make install

Windows環境編譯:

cd cmd\tendermint
go build

程式設計完成得到tendermint.exe檔案

下載編譯abci

go get -u github.com/tendermint/abci/cmd/abci-cli
cd cmd/abci-cli
go build

程式設計完成得到abci-cli.exe

啟動KVStore 第一個例子

tendermint啟動:

tendermint.exe init --home d:\tendermint
tendermint.exe node --home d:\tendermint

kvstore啟動:

.\abci-cli kvstore

測試
可以使用postman進行測試

## 檢視狀態
curl -s localhost:46657/status
## 新建tx
curl -s 'localhost:46657/broadcast_tx_commit?tx="abcd"'
## 查詢新建的tx
curl -s 'localhost:46657/abci_query?data="abcd"'

啟動Counter 第二個例子

tendermint啟動:

tendermint.exe unsafe_reset_all
tendermint.exe node --home d:\tendermint

kvstore啟動:

.\abci-cli counter --serial

測試

## 建立成功
curl localhost:46657/broadcast_tx_commit?tx=0x00
## 建立失敗
curl localhost:46657/broadcast_tx_commit?tx=0x05
##檢視
curl localhost:46657/abci_query?path="tx"

總結

  tendermint是一款非常強大的共識軟體,不過目前尚未到1.0版本。官方基於tendermint修改了Ethereum的共識協議完成了,同時官方基於tendermint 構建了cosmos公有鏈。
  tendermint還可以用於在聯盟鏈中作為共識協議,比如祕猿cryptape聯盟鏈使用tendermint來做共識。
  總的來說,tendermint不管在共有鏈還是聯盟鏈中都是大有可為的,值得深入學習研究。筆者在後續 的文章將講講tendermint的深入使用和原理。