1. 程式人生 > >區塊鏈框架 Tendermint 入門教程

區塊鏈框架 Tendermint 入門教程

Tendermint 是一個模組化的區塊鏈應用框架, 能夠實現拜占庭容錯 (BFT), 它主要包括兩部分:

  • Tendermint Core:

    • 實現了 p2p 網路;在節點之間共享區塊和交易;

    • 實現了拜占庭容錯的共識演算法,確定了不更改改的交易順序;

  • ABCI Interface,具體的邏輯處理層,可以基於不同的語言 (Golang, JS) 來實現;在這一層實現交易的驗證處理以及查詢等操作。

這兩部分會分別對應兩個不同的程序,Core 和 ABCI 建立了三個連線:

  • 一個用於驗證交易的連線,交易驗證通過後會被廣播到 mempoll 裡;

  • 一個用於區塊的 proposal;

  • 最後一個連線用於查詢應用的狀態;

下圖是兩者的 Workflow:

640?wx_fmt=png&wxfrom=5&wx_lazy=1

Core and ABCI communication

基於 Tendermint 的 Key-Value 儲存示例

Tendermint 內建了一個 KV 儲存的應用示例,我們可以跑下這個示例:

安裝

需要先安裝好 tendermint 和 abci-cli:

go get -u github.com/tendermint/tendermint/cmd/tendermint
go get -u github.com/tendermint/abci
cd $GOPATH/src/github.com/tendermint/abci
make install

驗證是否安裝成功:

➜  blog git:(hexo) ✗ which tendermint
/Users/hbliu/go/bin/tendermint
➜  blog git:(hexo) ✗ which abci-cli
/Users/hbliu/go/bin/abci-cli

啟動

初始化節點配置:

tendermint init

啟動 KV 儲存應用:

abci-cli kvstore

啟動 Tendermint 節點:

tendermint node --consensus.create_empty_blocks=false

其中後面的引數是禁止 Tendermint 節點定期產生空的 block。

建立交易

在 Tendermint 中建立 key 為 name, value 為 hbliu 的儲存:

➜  blog git:(hexo) ✗ curl -s 'localhost:46657/broadcast_tx_commit?tx="name=hbliu"'
{
  "jsonrpc": "2.0",
  "id": "",
  "result": {
    "check_tx": {
      "fee": {}
    },
    "deliver_tx": {
      "tags": [
        {
          "key": "YXBwLmNyZWF0b3I=",
          "value": "amFl"
        },
        {
          "key": "YXBwLmtleQ==",
          "value": "bmFtZQ=="
        }
      ],
      "fee": {}
    },
    "hash": "BA0C60A3F391B35DEAE8A7E6E0491E9B2E0BA497",
    "height": 2
  }
}

返回的 Response 中的 key 和 value 使用了 base64 進行了編碼, 我們可以通過命令 base64 對其進行解碼:

➜  blog git:(hexo) ✗ echo "YXBwLmtleQ==" | base64 -D
app.key
➜  blog git:(hexo) ✗ echo "bmFtZQ==" | base64 -D
name

查詢下我們之前的資訊有沒有成功寫入:

➜  blog git:(hexo) ✗ curl -s 'localhost:46657/abci_query?data="name"'
{
  "jsonrpc": "2.0",
  "id": "",
  "result": {
    "response": {
      "log": "exists",
      "index": "-1",
      "key": "bmFtZQ==",
      "value": "aGJsaXU="
    }
  }
}
➜  blog git:(hexo) ✗ echo "bmFtZQ==" | base64 -D
name
➜  blog git:(hexo) ✗ echo "aGJsaXU=" | base64 -D
hbliu

在瀏覽器中開啟 http://localhost:46657 可以顯示當前所有支援的 API。

示例程式碼介紹

上述示例的程式碼儲存在 Github(https://github.com/tendermint/abci/blob/master/example/kvstore/kvstore.go) 上。下面我們對這部分程式碼做一個簡單的介紹。

在我們呼叫 broadcast_tx_commit 的時候,會先呼叫 CheckTx,驗證通過後會把 TX 加入到 mempool 裡。在 kvstore 示例中沒有對 transaction 做檢查,直接通過:

func (app *KVStoreApplication) CheckTx(tx []byte) types.ResponseCheckTx {
   return types.ResponseCheckTx{Code: code.CodeTypeOK}
}

放到 mempool 裡的 TX 會被定期廣播到所有節點。當 Tendermint 選出了 Proposal 節點後,它便會從 mempool 裡選出一系列的 TXs,將它們組成一個 Block,廣播給所有的節點。節點在收到 Block 後,會對 Block 裡的所有 TX 執行 DeliverTX 操作,同時對 Block 執行 Commit 操作。

我們呼叫 broadcast_tx_commit 返回的結果其實就是 DeliverTX 返回的結果:

func (app *KVStoreApplication) DeliverTx(tx []byte) types.ResponseDeliverTx {
   var key, value []byte
   parts := bytes.Split(tx, []byte("="))
   if len(parts) == 2 {
       key, value = parts[0], parts[1]
   } else {
       key, value = tx, tx
   }
   app.state.db.Set(prefixKey(key), value)
   app.state.Size += 1
   tags := []cmn.KVPair{
       {[]byte("app.creator"), []byte("jae")},
       {[]byte("app.key"), key},
   }
   return types.ResponseDeliverTx{Code: code.CodeTypeOK, Tags: tags}
}

可以看出它會從輸入引數中解析出 key 和 value,最後儲存在應用的 State 中。

當所有的 TX 被處理完之後需要呼叫 Commit 來更新整個區塊的狀態,包括高度加 1 等:

func (app *KVStoreApplication) Commit() types.ResponseCommit {
   // Using a memdb - just return the big endian size of the db
   appHash := make([]byte, 8)
   binary.PutVarint(appHash, app.state.Size)
   app.state.AppHash = appHash
   app.state.Height += 1
   saveState(app.state)
   return types.ResponseCommit{Data: appHash}
}

References

  • Tendermint Introduction(http://tendermint.readthedocs.io/projects/tools/en/develop/introduction.html

出處:https://hiberabyss.github.io/2018/04/02/tendermint-introduction-1/

版權申明:內容來源網路,版權歸原創者所有。除非無法確認,我們都會標明作者及出處,如有侵權煩請告知,我們會立即刪除並表示歉意。謝謝。

640?wx_fmt=png

架構文摘

ID:ArchDigest

網際網路應用架構丨架構技術丨大型網站丨大資料丨機器學習

640?wx_fmt=jpeg

更多精彩文章,請點選下方:閱讀原文