Cosmos SDK 链对外提供三种交互接口:命令行界面(CLI)、gRPC API 和 REST API。它们是在同一套底层链逻辑之上的不同访问方式。用户和开发者可以根据自己的使用场景选择最合适的接口,而不会影响链处理或验证交易的方式。

用户如何与链交互

用户执行的每一种操作都属于以下两类之一:
  • 交易:会改变状态的操作,会广播到网络并被打包进区块中(发送代币、委托质押、对提案投票)
  • 查询:只读请求,直接从当前链状态返回数据,不经过共识流程
这两类操作都可以通过 CLI、gRPC 和 REST 接口访问。它们的区别在于请求的构造和传输方式,而不在于它们能做什么。 这些接口本身都不会影响共识。交易由共识引擎(CometBFT)负责验证和排序;这些接口只是传输机制,用来将已签名交易发送到网络并返回结果。 关于这些接口之下的交易与查询模型,参见交易、消息与查询。

接口对比

所有端点默认都绑定到 localhost,如需通过公共互联网访问,必须显式配置。
接口默认端口最适合说明
CLI—开发、测试和节点运维最适合操作员和开发者工作流
gRPC9090钱包、后端服务和 SDK 客户端浏览器中不支持(需要 HTTP/2)
REST1317Web 应用、脚本以及不支持 gRPC 的环境当 gRPC 不可用时使用;REST 默认关闭
CometBFT RPC26657共识与区块链数据查询仅限共识层数据

CLI

CLI 是开发者和操作员在终端中与链交互的主要工具。大多数 Cosmos SDK 链会提供一个单独的二进制程序,同时充当服务端进程和 CLI 客户端。通常会在二进制名称后追加 d 后缀,以表示它是守护进程,例如 exampled 或 simd。 如需亲手体验运行本地区块链并使用 CLI,可参见运行与测试教程。 当 CLI 作为客户端使用时,它会构造交易或查询,在需要时进行签名,并通过节点客户端接口提交。 要了解如何运行本地节点并使用 CLI,参见运行本地节点。

使用 CLI

CLI 命令分为两类:
  • query 命令用于从链状态中获取信息
  • tx 命令用于构造并广播交易
示例命令:
exampled query counter count
exampled tx counter add 10 \
  --from mykey \
  --chain-id example-1 \
  --gas auto \
  --gas-adjustment 1.3 \
  --fees 1000stake
  • --from 指定签名密钥
  • --gas auto 让 CLI 估算 gas 用量
  • --gas-adjustment 对估算值应用一个安全系数
  • --fees 指定交易手续费
Gas 用于限制一笔交易可执行的计算工作量。完整的 gas 模型见执行上下文、Gas 与事件。 如需示例链的完整 CLI 参考,请参见“运行与测试”教程中的 CLI 参考。

模块如何通过 AutoCLI 暴露 CLI 命令

在现代 Cosmos SDK 应用中,模块通过 AutoCLI 暴露 CLI 命令。AutoCLI 会读取模块的 protobuf 服务定义并自动生成 CLI 命令,无需模块手写 Cobra 命令样板代码。本节中的 counter 示例片段来自最小 counter 模块示例。参见从零构建模块教程。 模块通过在其 AppModule 上实现 AutoCLIOptions() 来接入 AutoCLI:
func (a AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
	return &autocliv1.ModuleOptions{
		Query: &autocliv1.ServiceCommandDescriptor{
			Service:              "example.counter.Query",
			EnhanceCustomCommand: true,
			RpcCommandOptions: []*autocliv1.RpcCommandOptions{
				{
					RpcMethod: "Count",
					Use:       "count",
					Short:     "Query the current counter value",
				},
			},
		},
		Tx: &autocliv1.ServiceCommandDescriptor{
			Service:              "example.counter.Msg",
			EnhanceCustomCommand: true,
			RpcCommandOptions: []*autocliv1.RpcCommandOptions{
				{
					RpcMethod:      "Add",
					Use:            "add [amount]",
					Short:          "Add to the counter",
					PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "add"}},
				},
			},
		},
	}
}
AutoCLI 使用这段配置生成 exampled tx counter add 和 exampled query counter count 命令。Service 字段指定 protobuf 服务名,而 RpcCommandOptions 将各个 RPC 方法映射为带有位置参数、标志和帮助文本的 CLI 子命令。 应用结构体上的 AutoCliOpts() 方法会从所有模块收集这些选项,并在启动时传递给 AutoCLI 框架:
func (app *ExampleApp) AutoCliOpts() autocli.AppOptions {
	modules := make(map[string]appmodule.AppModule)
	for _, m := range app.ModuleManager.Modules {
		if moduleWithName, ok := m.(module.HasName); ok {
			moduleName := moduleWithName.Name()
			if appModule, ok := moduleWithName.(appmodule.AppModule); ok {
				modules[moduleName] = appModule
			}
		}
	}

	return autocli.AppOptions{
		Modules:               modules,
		ModuleOptions:         runtimeservices.ExtractAutoCLIOptions(app.ModuleManager.Modules),
		AddressCodec:          authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()),
		ValidatorAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()),
		ConsensusAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()),
	}
}
这一步会收集模块选项和地址编解码器,并将它们交给 AutoCLI,由后者把生成出的命令挂接到根命令上。

gRPC

gRPC 是与 Cosmos 链交互的主要编程接口。它使用 Protocol Buffers 来定义强类型的请求与响应结构,并支持为多种编程语言生成客户端。 每个模块通过两个 protobuf 服务暴露其功能:
  • Query 服务,用于只读访问模块状态
  • Msg 服务,用于执行会改变状态的操作
这些服务定义在模块的 query.proto 和 tx.proto 文件中。Cosmos SDK 的 protobuf 定义发布在 buf.build/cosmos/cosmos-sdk。

模块如何暴露 gRPC 服务

模块在应用启动期间通过 RegisterServices 注册其 gRPC 服务:
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
err := app.ModuleManager.RegisterServices(app.configurator)
每个模块都会实现 RegisterServices,将服务实现连接到应用路由器:
func (am AppModule) RegisterServices(cfg module.Configurator) {
	types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
	types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServer(am.keeper))
}
RegisterMsgServer 会将传入的 Msg 服务调用路由到模块的 MsgServer 实现。RegisterQueryServer 会将传入的 Query 服务调用路由到模块的 QueryServer 实现。

如何与 gRPC 交互

使用生成的客户端连接到节点的 gRPC 端点(默认:localhost:9090):
conn, _ := grpc.NewClient("localhost:9090", grpc.WithTransportCredentials(insecure.NewCredentials()))
queryClient := countertypes.NewQueryClient(conn)

resp, _ := queryClient.Count(ctx, &countertypes.QueryCountRequest{})
gRPC 服务器可在 app.toml 中配置:
  • grpc.enable = true|false — 启用或禁用 gRPC 服务器(默认:true)
  • grpc.address = {string} — 服务器绑定的 ip:port(默认:localhost:9090)
  • grpc.max-recv-msg-size — 服务器可接收的最大消息字节数(默认:10MB)
  • grpc.max-send-msg-size — 服务器可发送的最大消息字节数(默认:math.MaxInt32)
对于归档节点部署,grpc.historical-grpc-address-block-range 会将 gRPC 后端地址映射到包含上下限的区块高度范围,从而把历史查询路由到保存该段链历史的节点上。该值是一个 JSON 字符串,例如:'{"archive-node-1:9090": [0, 1000000]}'。留空(默认值)即可禁用。 更多使用示例见与节点交互。

通过 gRPC-gateway 提供 REST

Cosmos SDK 还提供 REST API。REST 端点不是手写的;它们会基于 gRPC 使用的同一套 protobuf 定义,通过 gRPC-gateway 自动生成。 gRPC-gateway 会读取 .proto 文件中的 HTTP 注解,并生成一个反向代理,把 REST 请求转换为 gRPC 调用:
service Query {
  rpc Count(QueryCountRequest) returns (QueryCountResponse) {
    option (google.api.http) = {
      get: "/example/counter/v1/count"
    };
  }
}
这个注解会让 gRPC-gateway 生成一个 GET /example/counter/v1/count HTTP 端点。网关接收 HTTP 请求,将其编组为 QueryCountRequest,调用 gRPC 的 Count 处理器,并以 JSON 形式返回响应。

注册 REST 路由

REST 路由在 RegisterAPIRoutes 中注册:
func (app *ExampleApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
	clientCtx := apiSvr.ClientCtx
	// Register new tx routes from grpc-gateway.
	authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
	// Register new CometBFT queries routes from grpc-gateway.
	cmtservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
	// Register node gRPC service for grpc-gateway.
	nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
	// Register grpc-gateway routes for all modules.
	app.BasicModuleManager.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
}
REST 服务器可在 app.toml 中配置:
  • api.enable = true|false — 启用或禁用 REST 服务器(默认:false)
  • api.address = {string} — 服务器绑定的 ip:port(默认:tcp://localhost:1317)

Swagger

当 REST 服务器和 Swagger 都启用时,节点会在 http://localhost:1317/swagger/ 暴露 Swagger(OpenAPI v2)规范。Swagger 会列出所有 REST 端点、请求参数和响应模式,并提供基于浏览器的界面来浏览 REST API。 两者默认都处于禁用状态。可在 app.toml 中启用:
api.enable = true
api.swagger = true
如需为你自己的自定义模块生成 Swagger 文档,请参见 Cosmos SDK 中的 proto-swagger-gen script。

CometBFT RPC

CometBFT 还公开了其自有的 RPC 服务器,它独立于 Cosmos SDK。它提供共识和区块链数据,并在 config.toml 的 rpc 表下进行配置(默认值:tcp://localhost:26657)。所有 CometBFT RPC 端点的 OpenAPI 规范可在 CometBFT 文档 中查看。 部分 CometBFT RPC 端点与 Cosmos SDK 直接相关:
  • /abci_query — 向应用查询状态。path 参数支持:
    • 任意 protobuf 全限定服务方法,例如 /cosmos.bank.v1beta1.Query/AllBalances
    • /app/simulate — 模拟一笔交易并返回 gas 使用量
    • /app/version — 返回应用版本
    • /store/{storeName}/key — 在指定名称的存储中直接按键查找
    • /store/{storeName}/subspace — 在指定名称的存储中按前缀扫描
    • /p2p/filter/addr/{addr} 和 /p2p/filter/id/{id} — 按地址或节点 ID 过滤对等节点
  • /broadcast_tx_sync、/broadcast_tx_async、/broadcast_tx_commit — 将已签名交易广播给对等节点。CLI、gRPC 和 REST 接口在底层都使用这些 CometBFT RPC。
CometBFT 服务上的两个 gRPC 方法会返回 ABCI 区块结果:GetBlockResults(按高度)和 GetLatestBlockResults。它们会公开 finalize_block_events 和每笔交易的结果。

端到端交互流程

为了说明这些接口如何连接起来,下面展示一笔 counter add 交易从用户终端到链上状态变更的路径。此示例沿用了最小 counter 模块示例的 CLI 形式。参见从零构建一个模块教程。
用户运行:exampled tx counter add 10 --from mykey --chain-id example-1
  ↓
CLI(AutoCLI 生成的命令)
  构造 MsgAddRequest{Sender: mykey, Add: 10}
  使用 mykey 对交易签名
  编码为 protobuf 字节
  ↓
通过节点客户端接口广播
  ↓
节点:CheckTx
  AnteHandler 验证签名、扣除费用、计量 gas
  交易进入 mempool
  ↓
CometBFT:区块提议与共识
  ↓
FinalizeBlock:执行交易
  AnteHandler 再次运行(finalizeBlock 模式)
  MsgServiceRouter 将 MsgAddRequest 路由到 counter 模块的 MsgServer
  MsgServer.Add 调用 keeper.AddCount
  Keeper 读取当前计数,加上 10,写入新的计数
  ↓
Commit:状态变更被持久化
  ↓
用户收到 code 为 0 的 TxResponse
查询的路径更短,并且完全绕过共识:
用户运行:exampled query counter count
  ↓
CLI(AutoCLI 生成的命令)
  构造 QueryCountRequest{}
  直接发送到节点的 gRPC 查询端点
  ↓
GRPCQueryRouter 路由到 counter QueryServer
  QueryServer.Count 调用 keeper.GetCount
  Keeper 从存储中读取当前计数
  ↓
向用户返回 QueryCountResponse{Count: 10}
查询不会进入 mempool,不会被包含进区块,也不会经过 AnteHandler。它们读取已提交的状态并立即返回。

接口与共识

CLI、gRPC 和 REST 接口都是传输层。它们负责构造、签名和传递消息,但并不参与共识,也不会影响区块执行的确定性。
  • 交易只有在通过 CheckTx 并被纳入提议区块之后,才会成为共识的一部分。用于提交交易的接口不会影响其验证方式或排序方式。
  • 查询会完全绕过交易流水线。它们从节点读取已提交状态,且永远不会到达共识引擎。
  • 网络中的任意节点都可以提供查询服务或接受交易提交。无论使用哪个节点或哪种接口,结果始终都是相同的已提交状态。
这种分离意味着,修改模块的 CLI 或 REST 表层(例如重命名命令、添加新查询)永远不需要链升级。只有消息类型、keeper 逻辑或状态模式的变更才会影响共识。下一节 SDK 中的测试 将展示在这些行为接入完成后,如何对其进行测试。
A Cosmos SDK chain exposes three external interfaces for interacting with it: a command-line interface (CLI), a gRPC API, and a REST API. Each is a different surface over the same underlying chain logic. Users and developers can choose whichever interface suits their use case without affecting how the chain processes or validates transactions.

How users interact with a chain

Every operation a user performs falls into one of two categories:
  • Transactions: state-changing operations broadcast to the network and included in blocks (send tokens, delegate stake, vote on a proposal)
  • Queries: read-only requests that return data from the current chain state without going through consensus
Both categories are accessible through the CLI, gRPC, and REST interfaces. The interfaces differ in how requests are constructed and transmitted, not in what they can do. None of these interfaces affect consensus. Transactions are validated and ordered by the consensus engine (CometBFT); the interfaces are simply delivery mechanisms that carry signed transactions to the network and return results. For the transaction and query model underneath these interfaces, see Transactions, Messages, and Queries.

Interface comparison

All endpoints default to localhost and must be configured to be accessible over the public internet.
InterfaceDefault portBest forNotes
CLI—Development, testing, and node operationsBest for operator and developer workflows
gRPC9090Wallets, backend services, and SDK clientsNot supported in browsers (requires HTTP/2)
REST1317Web applications, scripts, and environments without gRPC supportUse when gRPC is unavailable; REST is disabled by default
CometBFT RPC26657Consensus and blockchain data queriesLimited to consensus-layer data

CLI

The CLI is the primary tool for developers and operators interacting with a chain from the terminal. Most Cosmos SDK chains ship a single binary that acts as both the server process and the CLI client. It is common to append a d suffix to the binary name to indicate that it is a daemon process, such as exampled or simd. For a hands-on walkthrough of running a local chain and using the CLI, see the Running and Testing tutorial. When used as a client, the CLI constructs a transaction or query, signs it if required, and submits it through the node client interface. To learn how to run a local node and use the CLI, see Run a Local Node.

Using the CLI

CLI commands are organized into two categories:
  • query commands retrieve information from chain state
  • tx commands construct and broadcast transactions
Example commands:
exampled query counter count
exampled tx counter add 10 \
  --from mykey \
  --chain-id example-1 \
  --gas auto \
  --gas-adjustment 1.3 \
  --fees 1000stake
  • --from specifies the signing key
  • --gas auto asks the CLI to estimate gas usage
  • --gas-adjustment applies a safety multiplier to the estimate
  • --fees specifies the transaction fee
Gas limits the computational work a transaction can perform. The full gas model is explained in Execution Context, Gas, and Events. For a full CLI reference for the example chain, see CLI reference in the Running and Testing tutorial.

How modules expose CLI commands with AutoCLI

In modern Cosmos SDK applications, modules expose CLI commands through AutoCLI. AutoCLI reads a module’s protobuf service definitions and generates CLI commands automatically, without requiring modules to hand-write Cobra command boilerplate. The counter snippets in this section are from the minimal counter module example. See the Build a Module from Scratch tutorial. A module opts into AutoCLI by implementing AutoCLIOptions() on its AppModule:
func (a AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
	return &autocliv1.ModuleOptions{
		Query: &autocliv1.ServiceCommandDescriptor{
			Service:              "example.counter.Query",
			EnhanceCustomCommand: true,
			RpcCommandOptions: []*autocliv1.RpcCommandOptions{
				{
					RpcMethod: "Count",
					Use:       "count",
					Short:     "Query the current counter value",
				},
			},
		},
		Tx: &autocliv1.ServiceCommandDescriptor{
			Service:              "example.counter.Msg",
			EnhanceCustomCommand: true,
			RpcCommandOptions: []*autocliv1.RpcCommandOptions{
				{
					RpcMethod:      "Add",
					Use:            "add [amount]",
					Short:          "Add to the counter",
					PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "add"}},
				},
			},
		},
	}
}
AutoCLI uses this configuration to generate the exampled tx counter add and exampled query counter count commands. The Service field names the protobuf service, and RpcCommandOptions maps individual RPC methods to CLI subcommands with positional arguments, flags, and help text. The AutoCliOpts() method on the application struct collects these options from all modules and passes them to the AutoCLI framework at startup:
func (app *ExampleApp) AutoCliOpts() autocli.AppOptions {
	modules := make(map[string]appmodule.AppModule)
	for _, m := range app.ModuleManager.Modules {
		if moduleWithName, ok := m.(module.HasName); ok {
			moduleName := moduleWithName.Name()
			if appModule, ok := moduleWithName.(appmodule.AppModule); ok {
				modules[moduleName] = appModule
			}
		}
	}

	return autocli.AppOptions{
		Modules:               modules,
		ModuleOptions:         runtimeservices.ExtractAutoCLIOptions(app.ModuleManager.Modules),
		AddressCodec:          authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()),
		ValidatorAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()),
		ConsensusAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()),
	}
}
This collects module options and address codecs and hands them to AutoCLI, which wires the generated commands into the root command.

gRPC

gRPC is the primary programmatic interface for interacting with a Cosmos chain. It uses Protocol Buffers to define strongly typed request and response structures and supports generated clients for many programming languages. Each module exposes its functionality through two protobuf services:
  • A Query service for read-only access to module state
  • A Msg service for state-changing operations
These services are defined in the module’s query.proto and tx.proto files. The protobuf definitions for the Cosmos SDK are published at buf.build/cosmos/cosmos-sdk.

How modules expose gRPC services

Modules register their gRPC services during application startup via RegisterServices:
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
err := app.ModuleManager.RegisterServices(app.configurator)
Each module implements RegisterServices to connect service implementations to the application routers:
func (am AppModule) RegisterServices(cfg module.Configurator) {
	types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
	types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServer(am.keeper))
}
RegisterMsgServer routes incoming Msg service calls to the module’s MsgServer implementation. RegisterQueryServer routes incoming Query service calls to the module’s QueryServer implementation.

How to interact with gRPC

Connect to the node’s gRPC endpoint (default: localhost:9090) using a generated client:
conn, _ := grpc.NewClient("localhost:9090", grpc.WithTransportCredentials(insecure.NewCredentials()))
queryClient := countertypes.NewQueryClient(conn)

resp, _ := queryClient.Count(ctx, &countertypes.QueryCountRequest{})
The gRPC server can be configured in app.toml:
  • grpc.enable = true|false — enables or disables the gRPC server (default: true)
  • grpc.address = {string} — the ip:port the server binds to (default: localhost:9090)
  • grpc.max-recv-msg-size — maximum message size in bytes the server can receive (default: 10MB)
  • grpc.max-send-msg-size — maximum message size in bytes the server can send (default: math.MaxInt32)
For archive node setups, grpc.historical-grpc-address-block-range maps gRPC backend addresses to inclusive block height ranges, so historical queries are routed to the node holding that slice of chain history. The value is a JSON string, for example: '{"archive-node-1:9090": [0, 1000000]}'. Leave it empty (the default) to disable. For more usage examples, see Interact with the Node.

REST via gRPC-gateway

The Cosmos SDK also exposes a REST API. REST endpoints are not written by hand; they are generated automatically from the same protobuf definitions used by gRPC, using gRPC-gateway. gRPC-gateway reads HTTP annotations in the .proto files and generates a reverse proxy that translates REST requests into gRPC calls:
service Query {
  rpc Count(QueryCountRequest) returns (QueryCountResponse) {
    option (google.api.http) = {
      get: "/example/counter/v1/count"
    };
  }
}
This annotation causes gRPC-gateway to generate a GET /example/counter/v1/count HTTP endpoint. The gateway receives the HTTP request, marshals it into a QueryCountRequest, calls the gRPC Count handler, and returns the response as JSON.

Registering REST routes

REST routes are registered in RegisterAPIRoutes:
func (app *ExampleApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
	clientCtx := apiSvr.ClientCtx
	// Register new tx routes from grpc-gateway.
	authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
	// Register new CometBFT queries routes from grpc-gateway.
	cmtservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
	// Register node gRPC service for grpc-gateway.
	nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
	// Register grpc-gateway routes for all modules.
	app.BasicModuleManager.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
}
The REST server can be configured in app.toml:
  • api.enable = true|false — enables or disables the REST server (default: false)
  • api.address = {string} — the ip:port the server binds to (default: tcp://localhost:1317)

Swagger

When the REST server and Swagger are both enabled, the node exposes a Swagger (OpenAPI v2) specification at http://localhost:1317/swagger/. Swagger lists all REST endpoints, request parameters, and response schemas, and provides a browser-based interface for exploring the REST API. Both are disabled by default. Enable them in app.toml:
api.enable = true
api.swagger = true
To generate Swagger documentation for your own custom modules, see the proto-swagger-gen script in the Cosmos SDK.

CometBFT RPC

CometBFT also exposes its own RPC server, independent of the Cosmos SDK. It serves consensus and blockchain data and is configured under the rpc table in config.toml (default: tcp://localhost:26657). An OpenAPI specification of all CometBFT RPC endpoints is available in the CometBFT documentation. Some CometBFT RPC endpoints are directly related to the Cosmos SDK:
  • /abci_query — queries the application for state. The path parameter accepts:
    • any protobuf fully-qualified service method, for example /cosmos.bank.v1beta1.Query/AllBalances
    • /app/simulate — simulate a transaction and return gas usage
    • /app/version — return the application version
    • /store/{storeName}/key — direct key lookup in a named store
    • /store/{storeName}/subspace — prefix scan in a named store
    • /p2p/filter/addr/{addr} and /p2p/filter/id/{id} — filter peers by address or node ID
  • /broadcast_tx_sync, /broadcast_tx_async, /broadcast_tx_commit — broadcast a signed transaction to peers. The CLI, gRPC, and REST interfaces all use these CometBFT RPCs under the hood.
Two gRPC methods on the CometBFT service return ABCI block results: GetBlockResults (by height) and GetLatestBlockResults. These expose finalize_block_events and per-transaction results.

End-to-end interaction flow

To illustrate how these interfaces connect, here is the path of a counter add transaction from the user’s terminal to a state change on the chain. This example follows the minimal counter module example’s CLI shape. See the Build a Module from Scratch tutorial.
User runs: exampled tx counter add 10 --from mykey --chain-id example-1
  ↓
CLI (AutoCLI generated command)
  Constructs MsgAddRequest{Sender: mykey, Add: 10}
  Signs the transaction with mykey
  Encodes to protobuf bytes
  ↓
Broadcast through the node client interface
  ↓
Node: CheckTx
  AnteHandler verifies signature, deducts fee, meters gas
  Transaction enters the mempool
  ↓
CometBFT: block proposal and consensus
  ↓
FinalizeBlock: transaction executed
  AnteHandler runs again (finalizeBlock mode)
  MsgServiceRouter routes MsgAddRequest → counter module MsgServer
  MsgServer.Add calls keeper.AddCount
  Keeper reads current count, adds 10, writes new count
  ↓
Commit: state change persisted
  ↓
User receives TxResponse with code 0
A query follows a shorter path that bypasses consensus entirely:
User runs: exampled query counter count
  ↓
CLI (AutoCLI generated command)
  Constructs QueryCountRequest{}
  Sends directly to node gRPC query endpoint
  ↓
GRPCQueryRouter routes to counter QueryServer
  QueryServer.Count calls keeper.GetCount
  Keeper reads current count from store
  ↓
QueryCountResponse{Count: 10} returned to user
Queries do not enter the mempool, are not included in blocks, and do not pass through the AnteHandler. They read committed state and return immediately.

Interfaces and consensus

The CLI, gRPC, and REST interfaces are transport layers. They construct, sign, and deliver messages, but they do not participate in consensus and cannot affect the determinism of block execution.
  • Transactions become part of consensus only after they pass CheckTx and are included in a proposed block. The interface used to submit the transaction has no bearing on how it is validated or ordered.
  • Queries bypass the transaction pipeline entirely. They read committed state from a node and never reach the consensus engine.
  • Any node in the network can serve queries or accept transaction submissions. The result is always the same committed state, regardless of which node or which interface is used.
This separation means that changing the CLI or REST surface of a module (renaming a command, adding a new query) never requires a chain upgrade. Only changes to message types, keeper logic, or state schema affect consensus. The next section, Testing in the SDK, shows how to test those behaviors once they are wired up.