天天看點

拜占庭共識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 的消息流:

  

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

3. 共識概述

  Tendermint 是一個易于了解,大部分操作為異步的 BFT 共識協定。下圖是一個簡單的狀态機,它展示了協定遵循的規則:

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

  協定中的參與者叫着 “驗證人”(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:/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啟動:

測試

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

總結

  tendermint是一款非常強大的共識軟體,不過目前尚未到1.0版本。官方基于tendermint修改了Ethereum的共識協定完成了ethermint,同時官方基于tendermint 建構了cosmos公有鍊。

  tendermint還可以用于在聯盟鍊中作為共識協定,比如秘猿cryptape聯盟鍊使用tendermint來做共識。

  總的來說,tendermint不管在共有鍊還是聯盟鍊中都是大有可為的,值得深入學習研究。筆者在後續 的文章将講講tendermint的深入使用和原理。

繼續閱讀