第一个 CometBFT 应用

作为一个通用区块链引擎,CometBFT 并不依赖于你想运行的具体应用。因此,要运行一条能够完成实际任务的完整区块链,你必须启动两个程序:一个是 CometBFT,另一个是你的应用,而这个应用可以使用任何编程语言编写。 CometBFT 负责所有 p2p 和共识逻辑,只在交易需要校验,或已经准备好执行和提交时,将交易转发给应用。 在本指南中,我们将向你展示一些使用 CometBFT 运行应用的示例。

安装

我们首先要使用的应用是用 Go 编写的。要安装它们,你需要先安装 Go,将 $GOPATH/bin 加入你的 $PATH,并启用 Go modules。如果你使用 bash,请按照以下说明操作:
echo export GOPATH=\"\$HOME/go\" >> ~/.bash_profile
echo export PATH=\"\$PATH:\$GOPATH/bin\" >> ~/.bash_profile
然后运行
go get github.com/cometbft/cometbft
cd $GOPATH/src/github.com/cometbft/cometbft
make install_abci
现在你应该已经安装好了 abci-cli;运行 abci-cli 可以查看命令列表:
Usage:
  abci-cli [command]

Available Commands:
  batch            run a batch of abci commands against an application
  check_tx         validate a transaction
  commit           commit the application state and return the Merkle root hash
  completion       Generate the autocompletion script for the specified shell
  console          start an interactive ABCI console for multiple commands
  echo             have the application echo a message
  finalize_block   deliver a block of transactions to the application
  help             Help about any command
  info             get some info about the application
  kvstore          ABCI demo example
  prepare_proposal prepare proposal
  process_proposal process proposal
  query            query the application state
  test             run integration tests
  version          print ABCI console version

Flags:
      --abci string        either socket or grpc (default "socket")
      --address string     address of application socket (default "tcp://0.0.0.0:26658")
  -h, --help               help for abci-cli
      --log_level string   set the logger level (default "debug")
  -v, --verbose            print the command and results as if it were a console session

Use "abci-cli [command] --help" for more information about a command.
你会注意到其中有一个 kvstore 命令,这是一个使用 Go 编写的示例应用。 现在,我们来运行一个应用。

KVStore:第一个示例

kvstore 应用是一个Merkle 树,它只是简单地存储所有交易。如果交易中包含 =,例如 key=value,那么 value 会以 key 为键存储在 Merkle 树中。否则,整笔交易的字节会同时作为键和值存储。 我们先启动一个 kvstore 应用。
abci-cli kvstore
在另一个终端中,我们可以启动 CometBFT。你应该已经安装好了 CometBFT 二进制文件。如果还没有,请按照这里的步骤操作。如果你此前从未运行过 CometBFT,请使用:
cometbft init
cometbft node
如果你之前使用过 CometBFT,可能需要先运行 cometbft unsafe-reset-all 来重置数据,以便启动一条新的区块链。然后你可以运行 cometbft node 来启动 CometBFT 并连接到应用。更多细节请参阅使用 CometBFT 的指南。 你应该会看到 CometBFT 正在持续出块。我们可以通过以下方式获取 CometBFT 节点的状态:
curl -s localhost:26657/status
这里的 -s 只是让 curl 静默输出。若想获得更易读的输出,可以将结果通过管道传给 jq 或 json_pp 之类的工具。 现在我们向 kvstore 发送一些交易。
curl -s 'localhost:26657/broadcast_tx_commit?tx="abcd"'
注意 URL 外层使用了单引号('),这样可以确保双引号(")不会被 bash 转义。这条命令发送了一笔字节内容为 abcd 的交易,因此 abcd 会在 Merkle 树中同时作为键和值存储。返回结果应类似于:
{
  "jsonrpc": "2.0",
  "id": "",
  "result": {
    "check_tx": {},
    "deliver_tx": {
      "tags": [
        {
          "key": "YXBwLmNyZWF0b3I=",
          "value": "amFl"
        },
        {
          "key": "YXBwLmtleQ==",
          "value": "YWJjZA=="
        }
      ]
    },
    "hash": "9DF66553F98DE3C26E3C3317A3E4CED54F714E39",
    "height": 14
  }
}
我们可以通过查询应用来确认这笔交易已经生效,并且值已经被存储:
curl -s 'localhost:26657/abci_query?data="abcd"'
结果应类似于:
{
  "jsonrpc": "2.0",
  "id": "",
  "result": {
    "response": {
      "log": "exists",
      "index": "-1",
      "key": "YWJjZA==",
      "value": "YWJjZA=="
    }
  }
}
注意结果中的 value(YWJjZA==);这是 abcd 的 ASCII 内容经过 base64 编码后的结果。你可以在 Python 2 shell 中运行 "YWJjZA==".decode('base64') 来验证,或者在 Python 3 shell 中运行 import codecs; codecs.decode(b"YWJjZA==", 'base64').decode('ascii')。后续版本会继续改进这一点,使这类输出更适合人类阅读。 现在我们试着设置不同的键和值:
curl -s 'localhost:26657/broadcast_tx_commit?tx="name=satoshi"'
现在如果我们查询 name,应该会得到 satoshi,或者它的 base64 形式 c2F0b3NoaQ==:
curl -s 'localhost:26657/abci_query?data="name"'
你可以再尝试一些其他交易和查询,确认一切都运行正常。

First CometBFT App

As a general-purpose blockchain engine, CometBFT is agnostic to the application you want to run. So, to run a complete blockchain that does something useful, you must start two programs: one is CometBFT, the other is your application, which can be written in any programming language. CometBFT handles all the p2p and consensus logic, and just forwards transactions to the application when they need to be validated, or when they’re ready to be executed and committed. In this guide, we show you some examples of how to run an application using CometBFT.

Install

The first apps we will work with are written in Go. To install them, you need to install Go, put $GOPATH/bin in your $PATH, and enable Go modules. If you use bash, follow these instructions:
echo export GOPATH=\"\$HOME/go\" >> ~/.bash_profile
echo export PATH=\"\$PATH:\$GOPATH/bin\" >> ~/.bash_profile
Then run
go get github.com/cometbft/cometbft
cd $GOPATH/src/github.com/cometbft/cometbft
make install_abci
Now you should have the abci-cli installed; run abci-cli to see the list of commands:
Usage:
  abci-cli [command]

Available Commands:
  batch            run a batch of abci commands against an application
  check_tx         validate a transaction
  commit           commit the application state and return the Merkle root hash
  completion       Generate the autocompletion script for the specified shell
  console          start an interactive ABCI console for multiple commands
  echo             have the application echo a message
  finalize_block   deliver a block of transactions to the application
  help             Help about any command
  info             get some info about the application
  kvstore          ABCI demo example
  prepare_proposal prepare proposal
  process_proposal process proposal
  query            query the application state
  test             run integration tests
  version          print ABCI console version

Flags:
      --abci string        either socket or grpc (default "socket")
      --address string     address of application socket (default "tcp://0.0.0.0:26658")
  -h, --help               help for abci-cli
      --log_level string   set the logger level (default "debug")
  -v, --verbose            print the command and results as if it were a console session

Use "abci-cli [command] --help" for more information about a command.
You’ll notice the kvstore command, an example application written in Go. Now, let’s run an app!

KVStore - A First Example

The kvstore app is a Merkle tree that just stores all transactions. If the transaction contains an =, e.g., key=value, then the value is stored under the key in the Merkle tree. Otherwise, the full transaction bytes are stored as the key and the value. Let’s start a kvstore application.
abci-cli kvstore
In another terminal, we can start CometBFT. You should already have the CometBFT binary installed. If not, follow the steps from here. If you have never run CometBFT before, use:
cometbft init
cometbft node
If you have used CometBFT, you may want to reset the data for a new blockchain by running cometbft unsafe-reset-all. Then you can run cometbft node to start CometBFT and connect to the app. For more details, see the guide on using CometBFT. You should see CometBFT making blocks! We can get the status of our CometBFT node as follows:
curl -s localhost:26657/status
The -s just silences curl. For nicer output, pipe the result into a tool like jq or json_pp. Now let’s send some transactions to the kvstore.
curl -s 'localhost:26657/broadcast_tx_commit?tx="abcd"'
Note the single quote (') around the URL, which ensures that the double quotes (") are not escaped by bash. This command sent a transaction with bytes abcd, so abcd will be stored as both the key and the value in the Merkle tree. The response should look something like:
{
  "jsonrpc": "2.0",
  "id": "",
  "result": {
    "check_tx": {},
    "deliver_tx": {
      "tags": [
        {
          "key": "YXBwLmNyZWF0b3I=",
          "value": "amFl"
        },
        {
          "key": "YXBwLmtleQ==",
          "value": "YWJjZA=="
        }
      ]
    },
    "hash": "9DF66553F98DE3C26E3C3317A3E4CED54F714E39",
    "height": 14
  }
}
We can confirm that our transaction worked and the value got stored by querying the app:
curl -s 'localhost:26657/abci_query?data="abcd"'
The result should look like:
{
  "jsonrpc": "2.0",
  "id": "",
  "result": {
    "response": {
      "log": "exists",
      "index": "-1",
      "key": "YWJjZA==",
      "value": "YWJjZA=="
    }
  }
}
Note the value in the result (YWJjZA==); this is the base64 encoding of the ASCII of abcd. You can verify this in a Python 2 shell by running "YWJjZA==".decode('base64') or in a Python 3 shell by running import codecs; codecs.decode(b"YWJjZA==", 'base64').decode('ascii'). Stay tuned for a future release that makes this output more human-readable. Now let’s try setting a different key and value:
curl -s 'localhost:26657/broadcast_tx_commit?tx="name=satoshi"'
Now if we query for name, we should get satoshi, or c2F0b3NoaQ== in base64:
curl -s 'localhost:26657/abci_query?data="name"'
Try some other transactions and queries to make sure everything is working!