概述本节说明如何运行一个区块链节点。本教程使用的应用是 simapp,对应的 CLI 二进制为 simd。
前置阅读

1. 初始化链

在运行节点之前,先初始化链及其创世文件。使用 init 子命令:

# The argument <moniker> is the custom username of your node, it should be human-readable.
simd init <moniker> --chain-id my-test-chain
上述命令会创建节点运行所需的全部配置文件,以及一个默认的创世文件,该文件定义了网络的初始状态。
默认情况下,这些配置文件都位于 ~/.simapp 中,但你可以通过为每个命令传入 --home 标志来覆盖该目录位置, 或者设置 $APPD_HOME 环境变量(其中 APPD 是二进制名称)。
Windows 用户:请将 ~/.simapp 替换为 %USERPROFILE%\.simapp(或 PowerShell 中的 $HOME\.simapp)。对于本教程中的 jq 和 sed 命令,请通过 Chocolatey 安装(choco install jq sed),或使用 Git Bash/WSL2。
~/.simapp 文件夹具有以下结构:
.                                   # ~/.simapp
  |- data                           # Contains the databases used by the node.
  |- config/
      |- app.toml                   # Application-related configuration file.
      |- config.toml                # CometBFT-related configuration file.
      |- genesis.json               # The genesis file.
      |- node_key.json              # Private key to use for node authentication in the p2p protocol.
      |- priv_validator_key.json    # Private key to use as a validator in the consensus protocol.

2. 更新配置项(可选)

如需修改配置文件中的字段值(例如 genesis.json),可使用 jq(安装 和 文档)以及 sed 命令。下面列出几个示例。

# to change the chain-id
jq '.chain_id = "testing"' genesis.json > temp.json && mv temp.json genesis.json


# to enable the api server
sed -i '/\[api\]/,+3 s/enable = false/enable = true/' app.toml


# to change the voting_period
jq '.app_state.gov.voting_params.voting_period = "600s"' genesis.json > temp.json && mv temp.json genesis.json


# to change the inflation
jq '.app_state.mint.minter.inflation = "0.300000000000000000"' genesis.json > temp.json && mv temp.json genesis.json

客户端交互

实例化节点时,gRPC 和 REST 默认仅绑定到 localhost,以避免节点在未知情况下暴露给公众。建议不要在没有代理的情况下直接暴露这些端点,代理应能够在节点与公众之间处理负载均衡或身份验证。
常用工具之一是 nginx。

3. 添加创世账户

在本教程前面,你已经在 keyring 中创建了一个账户,名称为 my_validator,使用的是 test keyring backend。 现在,你可以在链的创世文件中为该账户分配一些 stake 代币。这样做也能确保你的链知道这个账户的存在:
simd genesis add-genesis-account $MY_VALIDATOR_ADDRESS 100000000000stake
回顾一下,$MY_VALIDATOR_ADDRESS 是一个变量,保存了keyring中 my_validator 密钥的地址。还要注意,Cosmos SDK 中的代币采用 {amount}{denom} 格式:amount 是一个 18 位精度的小数值,denom 是带有面额键的唯一代币标识符(例如 atom 或 uatom)。这里分配的是 stake 代币,因为在 simapp 中,stake 是用于质押的代币标识符。对于你自己的链,如果有自己的质押 denom,则应改用对应的代币标识符。

4. 创建创世交易

现在你的账户已经有了一些代币,你需要向链中添加一个验证者。验证者是特殊的全节点,会参与共识过程(由底层共识引擎实现),从而向链中添加新区块。任何账户都可以声明自己想成为验证者运营者,但只有获得足够委托的账户才能进入活跃集合(例如,在 Cosmos Hub 中,只有委托量最高的前 125 个验证者候选人才能成为验证者)。在本指南中,你的本地节点(通过上面的 init 命令创建)将被加入为链的一个验证者。链首次启动前,可以通过包含在创世文件中的一种特殊交易 gentx 来声明验证者:
  1. 创建一个 gentx。
simd genesis gentx my_validator 100000000stake --chain-id my-test-chain --keyring-backend test
  1. 将 gentx 添加到创世文件中:
simd genesis collect-gentxs
一个 gentx 会完成三件事:
  1. 将你创建的验证者账户注册为验证者运营者账户(即控制该验证者的账户)。
  2. 为其自我委托给定 amount 数量的质押代币。
  3. 将运营者账户与一个用于签署区块的 CometBFT 节点公钥关联起来。如果未提供 --pubkey 标志,则默认使用上面通过 simd init 命令创建的本地节点公钥。
如需了解更多 gentx 信息,可使用以下命令:
simd genesis gentx --help

5. 使用 app.toml 和 config.toml 配置节点

Cosmos SDK 会自动在 ~/.simapp/config 中生成两个配置文件:
  • config.toml:用于配置 CometBFT,更多信息请参阅 CometBFT 文档,
  • app.toml:由 Cosmos SDK 生成,用于配置你的应用,例如状态裁剪策略、遥测、gRPC 和 REST 服务器配置、状态同步等。
这两个文件都带有大量注释,请直接参考它们来调整你的节点配置。 一个需要调整的示例配置是 app.toml 中的 minimum-gas-prices 字段,它定义了验证者节点愿意接受的处理交易的最低 gas 价格。根据不同链的设置,它可能为空字符串,也可能不是。如果它为空,请务必为该字段设置一个值,例如 10token,否则节点会在启动时停止。出于本教程目的,最低 gas 价格设置为 0:
 # The minimum gas prices a validator is willing to accept for processing a
 # transaction. A transaction's fees must meet the minimum of any denomination
 # specified in this config (e.g. 0.25token1;0.0001token2).
 minimum-gas-prices = "0stake"
当你运行的是一个节点(而不是验证者)且不希望运行应用 mempool 时,将 max-txs 字段设置为 -1。
[mempool]

# Setting max-txs to 0 will allow for an unbounded amount of transactions in the mempool.

# Setting max_txs to negative 1 (-1) will disable transactions from being inserted into the mempool.

# Setting max_txs to a positive number (> 0) will limit the number of transactions in the mempool, by the specified amount.
#

# Note, this configuration only applies to SDK built-in app-side mempool

# implementations.
max-txs = "-1"

6. 启动节点

现在一切都已设置完成,你终于可以启动节点了:
simd start
你应该会看到区块不断产生。

节点启动时会发生什么

start 命令(定义于 server/start.go)会按以下顺序启动全节点:
  1. 打开包含最新持久化状态的 db(默认是 LevelDB)。首次启动时,这里是空的。
  2. 通过 appCreator 函数创建一个新的应用实例,该函数就是应用构造函数。
  3. 使用该应用实例化一个 CometBFT 节点。作为 node.New 的一部分,CometBFT 会检查应用的区块高度是否与自身一致。如果应用落后,它会重放区块以追赶进度。如果高度为 0,它会调用 InitChain 根据创世文件初始化状态。
  4. 一旦同步完成,节点会启动其 RPC 和 P2P 服务器并开始连接对等节点。在握手期间,如果节点落后于其对等节点,它会按顺序查询缺失的区块。追上后,它会等待新的区块提案和验证者签名。
上一条命令可以让你运行单个节点。这已经足够支撑下一节关于如何与该节点交互的内容,但你也可能希望同时运行多个节点,并观察它们之间如何达成共识。 最直接的方式是在不同终端窗口中再次运行相同的命令。这当然可行。不过,也可以利用 Docker Compose 来运行一个本地网络。如果你需要了解如何使用 Docker Compose 搭建自己的本地网络,可以参考 Cosmos SDK 的 docker-compose.yml。

独立运行的 App/CometBFT

默认情况下,Cosmos SDK 会让 CometBFT 与应用在同一进程内运行。 如果你希望让应用和 CometBFT 分别在不同进程中运行, 请使用 --with-comet=false 标志启动应用, 并将 config.toml 中的 rpc.laddr 设置为 CometBFT 节点的 RPC 地址。

日志

日志提供了一种查看节点运行情况的方式。默认日志级别是 info。这是一个全局级别,所有 info 日志都会输出到终端。如果你希望输出到终端的是特定日志而不是全部日志,可以通过设置 module:log_level 来实现。 config.toml 中的示例:
log_level: "state:info,p2p:info,consensus:info,x/staking:info,x/ibc:info,*error"

详细日志级别

某些操作(例如链升级)会在更高日志级别启用时输出额外日志。你可以通过 --verbose_log_level 标志来控制:
simd start --verbose_log_level debug
有关日志的更多信息,请参阅日志概览。

状态同步

状态同步是指节点同步区块链最新状态或接近最新状态的过程。这对于不想同步全部历史区块的用户很有用。更多内容请阅读 CometBFT 文档。 状态同步依赖快照机制。你可以在这里了解 SDK 如何处理快照。

本地状态同步

本地状态同步与普通状态同步类似,不同之处在于它基于本地状态快照,而不是通过 p2p 网络提供的快照。启动本地状态同步的步骤与普通状态同步相近,但在设计上有一些不同考虑。
  1. 如状态同步文档所述,必须在 config.toml 中设置高度和哈希值,并配置若干 RPC 服务器(上面的链接中包含具体说明)。
  2. 运行 <appd> snapshot restore <height> <format> 以恢复本地快照(注意:首先要使用 load 命令从文件中加载它)。
  3. 在快照导入后引导 Comet 状态,以便启动节点。这可以通过引导命令 <app> comet bootstrap-state 完成

快照命令

Cosmos SDK 提供了用于管理快照的命令。 可以在应用中通过以下代码片段将这些命令添加到 cmd/<app>/root.go:
import (
    
  "github.com/cosmos/cosmos-sdk/client/snapshot"
)

func initRootCmd(/* ... */) {
  // ...
  rootCmd.AddCommand(
    snapshot.Cmd(appCreator),
  )
}
然后,可以在 <appd> snapshots [command] 下使用以下命令:
  • list:列出本地快照
  • load:将快照归档文件加载到快照存储中
  • restore:从本地快照恢复应用状态
  • export:将应用状态导出到快照存储中
  • dump:将快照导出为可移植归档格式
  • delete:删除本地快照

恭喜!

你的节点现已运行并开始生成区块。你已经成功从零初始化了一条 Cosmos SDK 区块链。

后续步骤


SynopsisThis section explains how to run a blockchain node. The application used in this tutorial is simapp, and its corresponding CLI binary simd.
Prerequisite Readings

1. Initialize the chain

Before running the node, initialize the chain and its genesis file. Use the init subcommand:
# The argument <moniker> is the custom username of your node, it should be human-readable.
simd init <moniker> --chain-id my-test-chain
The command above creates all the configuration files needed for your node to run, as well as a default genesis file, which defines the initial state of the network.
All these configuration files are in ~/.simapp by default, but you can overwrite the location of this folder by passing the --home flag to each command, or set an $APPD_HOME environment variable (where APPD is the name of the binary).
Windows users: Replace ~/.simapp with %USERPROFILE%\.simapp (or $HOME\.simapp in PowerShell). For jq and sed commands in this tutorial, install via Chocolatey (choco install jq sed) or use Git Bash/WSL2.
The ~/.simapp folder has the following structure:
.                                   # ~/.simapp
  |- data                           # Contains the databases used by the node.
  |- config/
      |- app.toml                   # Application-related configuration file.
      |- config.toml                # CometBFT-related configuration file.
      |- genesis.json               # The genesis file.
      |- node_key.json              # Private key to use for node authentication in the p2p protocol.
      |- priv_validator_key.json    # Private key to use as a validator in the consensus protocol.

2. Update configuration settings (optional)

To change field values in configuration files (for example, genesis.json), use jq (installation & docs) and sed commands. A few examples are listed here.
# to change the chain-id
jq '.chain_id = "testing"' genesis.json > temp.json && mv temp.json genesis.json

# to enable the api server
sed -i '/\[api\]/,+3 s/enable = false/enable = true/' app.toml

# to change the voting_period
jq '.app_state.gov.voting_params.voting_period = "600s"' genesis.json > temp.json && mv temp.json genesis.json

# to change the inflation
jq '.app_state.mint.minter.inflation = "0.300000000000000000"' genesis.json > temp.json && mv temp.json genesis.json

Client Interaction

When instantiating a node, gRPC and REST are defaulted to localhost to avoid unknown exposure of your node to the public. It is recommended not to expose these endpoints without a proxy that can handle load balancing or authentication set up between your node and the public.
A commonly used tool for this is nginx.

3. Add genesis accounts

Earlier in this tutorial, you created an account in the keyring named my_validator under the test keyring backend. Now, you can grant this account some stake tokens in your chain’s genesis file. Doing so will also make sure your chain is aware of this account’s existence:
simd genesis add-genesis-account $MY_VALIDATOR_ADDRESS 100000000000stake
Recall that $MY_VALIDATOR_ADDRESS is a variable that holds the address of the my_validator key in the keyring. Also note that the tokens in the Cosmos SDK have the {amount}{denom} format: amount is an 18-digit-precision decimal number, and denom is the unique token identifier with its denomination key (e.g., atom or uatom). Here, stake tokens are granted, as stake is the token identifier used for staking in simapp. For your own chain with its own staking denom, that token identifier should be used instead.

4. Create genesis transaction

Now that your account has some tokens, you need to add a validator to your chain. Validators are special full-nodes that participate in the consensus process (implemented in the underlying consensus engine) in order to add new blocks to the chain. Any account can declare its intention to become a validator operator, but only those with sufficient delegation get to enter the active set (for example, only the top 125 validator candidates with the most delegation get to be validators in the Cosmos Hub). For this guide, your local node (created via the init command above) will be added as a validator of your chain. Validators can be declared before a chain is first started via a special transaction included in the genesis file called a gentx:
  1. Create a gentx.
simd genesis gentx my_validator 100000000stake --chain-id my-test-chain --keyring-backend test
  1. Add the gentx to the genesis file:
simd genesis collect-gentxs
A gentx does three things:
  1. Registers the validator account you created as a validator operator account (i.e., the account that controls the validator).
  2. Self-delegates the provided amount of staking tokens.
  3. Link the operator account with a CometBFT node pubkey that will be used for signing blocks. If no --pubkey flag is provided, it defaults to the local node pubkey created via the simd init command above.
For more information on gentx, use the following command:
simd genesis gentx --help

5. Configure the node using app.toml and config.toml

The Cosmos SDK automatically generates two configuration files inside ~/.simapp/config:
  • config.toml: used to configure the CometBFT, learn more on CometBFT’s documentation,
  • app.toml: generated by the Cosmos SDK, and used to configure your app, such as state pruning strategies, telemetry, gRPC and REST server configuration, state sync…
Both files are heavily commented, please refer to them directly to tweak your node. One example config to tweak is the minimum-gas-prices field inside app.toml, which defines the minimum gas prices the validator node is willing to accept for processing a transaction. Depending on the chain, it might be an empty string or not. If it’s empty, make sure to edit the field with some value, for example 10token, or else the node will halt on startup. For the purposes of this tutorial, the minimum gas price is set to 0:
 # The minimum gas prices a validator is willing to accept for processing a
 # transaction. A transaction's fees must meet the minimum of any denomination
 # specified in this config (e.g. 0.25token1;0.0001token2).
 minimum-gas-prices = "0stake"
When running a node (not a validator!) and not wanting to run the application mempool, set the max-txs field to -1.
[mempool]
# Setting max-txs to 0 will allow for an unbounded amount of transactions in the mempool.
# Setting max_txs to negative 1 (-1) will disable transactions from being inserted into the mempool.
# Setting max_txs to a positive number (> 0) will limit the number of transactions in the mempool, by the specified amount.
#
# Note, this configuration only applies to SDK built-in app-side mempool
# implementations.
max-txs = "-1"

6. Start the node

Now that everything is set up, you can finally start your node:
simd start
You should see blocks come in.

What happens when the node starts

The start command (defined in server/start.go) boots up the full-node in the following sequence:
  1. It opens the db (LevelDB by default) containing the latest persisted state. On first start, this is empty.
  2. It creates a new instance of the application via an appCreator function, which is the application constructor.
  3. It instantiates a CometBFT node using the application. As part of node.New, CometBFT checks that the application’s block height matches its own. If the application is behind, it replays blocks to catch up. If the height is 0, it calls InitChain to initialize state from the genesis file.
  4. Once in sync, the node starts its RPC and P2P servers and begins dialing peers. During the handshake, if the node is behind its peers, it queries missing blocks sequentially. Once caught up, it waits for new block proposals and validator signatures.
The previous command allows you to run a single node. This is enough for the next section on interacting with this node, but you may wish to run multiple nodes at the same time, and see how consensus happens between them. The naive way would be to run the same commands again in separate terminal windows. This is possible. However, Docker Compose can be leveraged to run a localnet. If you need inspiration on how to set up your own localnet with Docker Compose, refer to the Cosmos SDK’s docker-compose.yml.

Standalone App/CometBFT

By default, the Cosmos SDK runs CometBFT in-process with the application If you want to run the application and CometBFT in separate processes, start the application with the --with-comet=false flag and set rpc.laddr in config.toml to the CometBFT node’s RPC address.

Logging

Logging provides a way to see what is going on with a node. The default logging level is info. This is a global level and all info logs will be outputted to the terminal. If you would like to filter specific logs to the terminal instead of all, then setting module:log_level is how this can work. Example in config.toml:
log_level: "state:info,p2p:info,consensus:info,x/staking:info,x/ibc:info,*error"

Verbose log level

Some operations, such as chain upgrades, emit additional log messages when a higher log level is active. You can control this with the --verbose_log_level flag:
simd start --verbose_log_level debug
See the Log Overview for more information on logging.

State Sync

State sync is the act in which a node syncs the latest or close to the latest state of a blockchain. This is useful for users who don’t want to sync all the blocks in history. Read more in CometBFT documentation. State sync works thanks to snapshots. Read how the SDK handles snapshots here.

Local State Sync

Local state sync works similarly to normal state sync except that it works off a local snapshot of state instead of one provided via the p2p network. The steps to start local state sync are similar to normal state sync with a few different design considerations.
  1. As mentioned in the state sync documentation, one must set a height and hash in the config.toml along with a few RPC servers (the aforementioned link has instructions on how to do this).
  2. Run <appd> snapshot restore <height> <format> to restore a local snapshot (note: first load it from a file with the load command).
  3. Bootstrapping Comet state to start the node after the snapshot has been ingested. This can be done with the bootstrap command <app> comet bootstrap-state

Snapshots Commands

The Cosmos SDK provides commands for managing snapshots. These commands can be added in an app with the following snippet in cmd/<app>/root.go:
import (
    
  "github.com/cosmos/cosmos-sdk/client/snapshot"
)

func initRootCmd(/* ... */) {
  // ...
  rootCmd.AddCommand(
    snapshot.Cmd(appCreator),
  )
}
Then the following commands are available at <appd> snapshots [command]:
  • list: list local snapshots
  • load: Load a snapshot archive file into snapshot store
  • restore: Restore app state from local snapshot
  • export: Export app state to snapshot store
  • dump: Dump the snapshot as portable archive format
  • delete: Delete a local snapshot

Congratulations!

Your node is now running and producing blocks. You have successfully initialized a Cosmos SDK blockchain from scratch.

Next steps