Blockchain Framework Tendermint Getting Started Tutorial

Tendermint is a modular blockchain application framework that can achieve Byzantine Fault Tolerance (BFT). It mainly includes two parts:


  • Tendermint Core:

    • Implemented a p2p network; shared blocks and transactions between nodes;

    • The Byzantine fault-tolerant consensus algorithm is implemented, and the transaction order that does not change is determined;

  • ABCI Interface, the specific logic processing layer, can be implemented based on different languages ​​(Golang, JS); at this layer, operations such as transaction verification processing and query are implemented.


These two parts will correspond to two different processes respectively. Core and ABCI establish three connections:


  • A connection used to verify the transaction, after the transaction verification is passed, it will be broadcast to the mempoll;

  • a proposal for the block;

  • The last connection is used to query the status of the application;


The following figure is the Workflow of the two:

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

Core and ABCI communication


Tendermint-based Key-Value Storage Example


Tendermint has a built-in KV storage application example, we can run this example:


Install


You need to install tendermint and abci-cli first:


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


Verify that the installation was successful:


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


start up


Initialize node configuration:


tendermint init


Start the KV storage application:


abci-cli kvstore


Start the Tendermint node:


tendermint node --consensus.create_empty_blocks=false


The latter parameter is to prohibit the Tendermint node from periodically generating empty blocks.


Create transaction


Create a storage with key name and value hbliu in Tendermint:


➜  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/


Copyright statement: The content comes from the Internet, and the copyright belongs to the original creator. Unless we cannot confirm, we will indicate the author and source. If there is any infringement, please let us know, we will delete it immediately and apologize. thanks.


640?wx_fmt=png

Architecture Digest

ID:ArchDigest

Internet Application Architecture丨Architecture Technology丨Large Websites丨Big Data丨Machine Learning

640?wx_fmt=jpeg

For more exciting articles, please click below: Read the original text

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326041863&siteId=291194637