Interacting with a chain
A Cosmos SDK blockchain is a deterministic state machine. Its state changes only when transactions are executed and committed in blocks. Users and applications interact with the blockchain in two fundamental ways:- Transactions modify state and are included in blocks. When a user wants to change something (transfer tokens, delegate stake, submit a governance proposal), they submit a transaction.
- Queries read state and are not included in blocks. When a user wants to inspect something (check a balance, view delegations, read proposal details), they perform a query.
Transactions
A transaction is a signed container that carries one or more actions to be executed on the blockchain. A transaction includes:- Messages - one or more actions you want to execute (send tokens, delegate stake, vote on a proposal)
- Signatures - cryptographic proof that you authorize these actions
- Sequence number - prevents someone from resubmitting your transaction (replay protection)
- Gas limit - the maximum computational resources you’re willing to spend
- Fees - what you pay for the transaction to be processed
x/auth module. Transaction construction and encoding are configured through the SDK’s transaction system (commonly via x/auth/tx).
Messages
A message (sdk.Msg) is the actual instruction inside a transaction. Each message is defined by a specific module and represents a single action. Messages are located in that module’s types package (like x/bank/types or x/staking/types). Modules define which messages they support and the rules for executing them. While the transaction provides the envelope with signatures and fees, the message defines the specific action to execute.
Examples include MsgSend (transfer tokens), MsgDelegate (delegate stake), and MsgVote (vote on proposals).
If a transaction contains multiple messages, they execute in order. The transaction only succeeds if all messages execute successfully; it is an atomic unit.
How messages are defined
Messages in the Cosmos SDK are defined in each module’stypes.proto file using Protocol Buffers (protobuf), which provides deterministic serialization, backward compatibility, and cross-language support. Each message is defined in a .proto file that specifies its fields, data types, and unique identifiers. From this schema, code is generated that allows the message to be constructed, serialized, and validated.
Here’s what an actual transaction looks like in JSON format:
body.messages array, the sender’s public key and sequence in auth_info.signer_infos, the fee and gas limit in auth_info.fee, and the cryptographic signature in the signatures array.
When broadcast, this JSON is serialized into bytes using protobuf, ensuring every validator interprets the transaction identically.
Message order and atomicity
When a transaction contains multiple messages, they are executed in the order they appear in the transaction. For example, a transaction might:- Send tokens to another account.
- Delegate those tokens to a validator.
Blocks and state transitions
A blockchain can be understood as a sequence of blocks. Each block contains an ordered list of transactions. When a new block is committed:- Each transaction in the block is applied to the current state.
- Each transaction executes its messages in order.
- Modules update their portion of state.
- The resulting state becomes the starting point for the next block.
What is a query?
A query retrieves data from the blockchain’s state without modifying it. Queries:- Are read-only
- Do not require signatures
- Are not included in blocks
- Do not change consensus state
- Query an account’s balance (
x/bank) - Query staking delegations (
x/staking) - Query governance proposal details (
x/gov)
How everything fits together
| Transaction Flow | Query Flow |
|---|---|
| |