# Transactions
In this section you will dive into the various functions and features of making transactions in the interchain:
- Transactions and Messages
- Signing Transactions
- Generating Transactions
- Broadcasting Transactions
- Introducing the CLI, the gRPC service, the REST API, and the CometBFT RPC service
Transactions are objects created by end-users to trigger state changes in applications. They are comprised of metadata that defines a context, and one or more sdk.Msg
(opens new window) that trigger state changes within a module through the module’s Protobuf message service.
# Transaction process from an end-user perspective
While there is much to explore as you journey through the stack, begin by understanding the transaction process from a user perspective:
TxBuilder
. TxBuilder
is the preferred way to generate a transaction.Deciding and signing are the main interactions of a user. Generating and broadcasting are attended to by the user interface and other automation.
# Transaction objects
Transaction objects are Cosmos SDK types that implement the Tx
(opens new window) interface. They contain the following methods:
GetMsgs
(opens new window): unwraps the transaction and returns a list of containedsdk.Msg
(opens new window). One transaction may have one or multiple messages.ValidateBasic
(opens new window): includes lightweight, stateless checks used by the ABCI messages'CheckTx
andDeliverTx
to make sure transactions are not invalid. For example, theTx
(opens new window)ValidateBasic
(opens new window) function checks that its transactions are signed by the correct number of signers and that the fees do not exceed the user's maximum.
This function is different from the ValidateBasic
(opens new window) functions for sdk.Msg
, which perform basic validity checks on messages only. For example, runTX
first runs ValidateBasic
on each message when it checks a transaction created from the auth module. Then it runs the auth module's AnteHandler
(opens new window), which calls ValidateBasic
for the transaction itself.
You should rarely manipulate a Tx
object directly. It is an intermediate type used for transaction generation. Developers usually use the TxBuilder
(opens new window) interface.
# Messages
Transaction messages are not to be confused with ABCI messages, which define interactions between CometBFT and application layers.
Messages or sdk.Msg
(opens new window) are module-specific objects that trigger state transitions within the scope of the module they belong to. Module developers define module messages by adding methods to the Protobuf Msg
service and defining a MsgServer
. Each sdk.Msg
is related to exactly one Protobuf Msg
service RPC defined inside each module's tx.proto
file. A Cosmos SDK app router automatically maps every sdk.Msg
to a corresponding RPC service, which routes it to the appropriate method. Protobuf generates a MsgServer
interface for each module's Msg
service and the module developer implements this interface.
This design puts more responsibility on module developers. It allows application developers to reuse common functionalities without having to repetitively implement state transition logic. While messages contain the information for the state transition logic, a transaction's other metadata and relevant information are stored in the TxBuilder
and Context
.
# Signing Transactions
Every message in a transaction must be signed by the addresses specified by its GetSigners
(opens new window). The Cosmos SDK currently allows signing transactions in two different ways:
SIGN_MODE_DIRECT
(opens new window) (preferred): the most used implementation of theTx
interface is the ProtobufTx
(opens new window) message, which is used inSIGN_MODE_DIRECT
. Once signed by all signers, theBodyBytes
,AuthInfoBytes
, andSignatures
(opens new window) are gathered intoTxRaw
(opens new window), whose serialized bytes (opens new window) are broadcast over the network.SIGN_MODE_LEGACY_AMINO_JSON
(opens new window): the legacy implementation of theTx
interface is theStdTx
(opens new window) struct fromx/auth
. The document signed by all signers isStdSignDoc
(opens new window), which is encoded into bytes (opens new window) using Amino JSON. Once all signatures are gathered intoStdTx
,StdTx
is serialized using Amino JSON and these bytes are broadcast over the network. This method is being deprecated.
# Generating transactions
The TxBuilder
interface contains metadata closely related to the generation of transactions. The end-user can freely set these parameters for the transaction to be generated:
Msgs
(opens new window): the array of messages included in the transaction.GasLimit
(opens new window): an option chosen by the users for how to calculate the gas amount they are willing to spend.Memo
(opens new window): a note or comment to send with the transaction.FeeAmount
(opens new window): the maximum amount the user is willing to pay in fees.TimeoutHeight
(opens new window): the block height until which the transaction is valid.Signatures
(opens new window): the array of signatures from all signers of the transaction.
As there are currently two modes for signing transactions, there are also two implementations of TxBuilder
. There is a wrapper for SIGN_MODE_DIRECT
and the StdTxBuilder
(opens new window) for SIGN_MODE_LEGACY_AMINO_JSON
. The two possibilities should normally be hidden because end-users should prefer the overarching TxConfig
(opens new window) interface. TxConfig
is an app-wide (opens new window) configuration for managing transactions accessible from the context. Most importantly, it holds the information about whether to sign each transaction with SIGN_MODE_DIRECT
or SIGN_MODE_LEGACY_AMINO_JSON
.
A new TxBuilder
will be instantiated with the appropriate sign mode by calling txBuilder := txConfig.NewTxBuilder()
. TxConfig
will correctly encode the bytes either using SIGN_MODE_DIRECT
or SIGN_MODE_LEGACY_AMINO_JSON
once TxBuilder
is correctly populated with the setters of the fields described previously.
This is a pseudo-code snippet of how to generate and encode a transaction using the TxEncoder()
method:
# Broadcasting the transaction
Once the transaction bytes are generated and signed, there are three primary ways of broadcasting the transaction:
- Using the command-line interface (CLI).
- Using gRPC.
- Using REST endpoints.
Application developers create entrypoints to the application by creating a command-line interface typically found in the application's ./cmd
folder, gRPC, and/or REST interface. These interfaces allow users to interact with the application.
# CLI
For the command-line interface (CLI) module developers create subcommands to add as children to the application top-level transaction command TxCmd
(opens new window).
CLI commands bundle all the steps of transaction processing into one simple command:
- Creating messages.
- Generating transactions.
- Signing.
- Broadcasting.
# gRPC
The principal usage of gRPC is in the context of module query services. The Cosmos SDK also exposes other module-agnostic gRPC services. One of these is the Tx
service, which exposes a handful of utility functions such as simulating a transaction or querying a transaction, and also one method to broadcast transactions (opens new window).
See this code example (opens new window) for more insight.
# REST
Each gRPC method has its corresponding REST endpoint generated using gRPC-gateway. Rather than using gRPC, you can also use HTTP to broadcast the same transaction on the POST
/cosmos/tx/v1beta1/txs
endpoint.
See this code example (opens new window) for more details.
# CometBFT RPC
The three methods presented previously are higher abstractions on the CometBFT RPC /broadcast_tx_{async,sync,commit}
endpoints. You can use the Tendermint RPC endpoints (opens new window) to directly broadcast the transaction through CometBFT if you wish to.
CometBFT supports the following RPC protocols:
- URI over HTTP.
- JSONRPC over HTTP.
- JSONRPC over WebSockets.
For more information on broadcasting with CometBFT RPC, see the documentation on Tendermint RPC transactions broadcast APIs (opens new window).
# Code example
Previously, the ABCI application knew of a single transaction type: a checkers move with four int
. This is no longer sufficient with multiple games. You need to conform to its Tx
expectations, which means that you must create messages which are then placed into a transaction.
See the section on messages to learn how to do that.
To summarize, this section has explored:
- How transactions are objects created by end-users to trigger state changes in an application module through that module's Protobuf message service.
- How transaction messages are not to be confused with ABCI messages, which define interactions between CometBFT and application layers.
- How deciding and signing transactions are the main interactions of a user, whereas generating and broadcasting transactions are attended to by the user interface and other automation.
- How the modular nature of the Cosmos SDK places more responsibility on module developers to effectively code transaction processes, so application developers can reuse common functionalities without having to repetitively implement state transition logic.