Context
is the setting in which transactions execute, and is the sum of all pertinent information at runtime. Here you will find out what transaction context means in detail and learn more about the important elements that together form the execution context.
Transactions execute in a context. The context includes information about the current state of the application, the block, and the transaction.
Context is represented as data structures that carry information about the current state of the application and are intended to be passed from function to function. Context provides access to branched storage, that is a safe branch of the entire state, as well as useful objects and information, like gasMeter
, block height, and consensus parameters.
The Cosmos SDK context is a custom data structure that contains Go's stdlib context as its base. It has many additional types within its definition that are specific to the Cosmos SDK.
Context is integral to transaction processing as it allows modules to easily access their respective store in the multistore and retrieve transactional context such as the block header and gas meter.
The context has the following properties:
BaseApp
contains a CommitMultiStore
, which is provided when a context is created. Calling the KVStore()
and TransientStore()
methods allows modules to fetch their respective KVStore
s using their unique StoreKey
s.Every transaction is processed by various parts of the Cosmos SDK and consensus engine (for example CometBFT) throughout its lifecycle, some of which do not have any understanding of transaction types. Thus, transactions are marshaled into a generic []byte
type using some kind of encoding format such as Amino.
VoteInfo
: a list of the ABCI type VoteInfo
, which includes the name of a validator and a boolean indicating whether they have signed the block.gasMeter
for the transaction currently being processed, using the context and a blockGasMeter
for the entire block it belongs to.Users specify how much in fees they wish to pay for the execution of their transaction. These gas meters keep track of how much gas has been used in the transaction or block so far. If the gas meter runs out, execution halts.
CheckTx
mode: a boolean value indicating whether a transaction should be processed in CheckTx
or DeliverTx
mode.Consensus Parameters
, which specifies certain limits for the blockchain, such as maximum gas for a block.types/
. Clients can subscribe or query for these events. These events are collected through DeliverTx
, BeginBlock
, and EndBlock
and are returned to CometBFT for indexing.A context is an immutable data structure that carries request-scoped data across APIs and processes. Contexts are also designed to enable concurrency and to be used in Go routines.
A basic context is defined in the Golang Context Package (opens new window).
Contexts are intended to be immutable: they should never be edited. The convention is to instead create a child context from its parent using a With
function. The Golang Context Package documentation instructs developers to explicitly pass a context ctx
(opens new window) as the first argument of a process.
The context contains a MultiStore
, which allows for branching and caching functionality using CacheMultiStore
. Queries in CacheMultiStore
are cached to avoid future round trips.
Each KVStore
is branched in a safe and isolated ephemeral storage. Processes are free to write changes to the CacheMultiStore
. If a state-transition sequence is performed without issue, the store branch can be committed to the underlying store at the end of the sequence, or it can be disregarded if something goes wrong.
The usage pattern for context is as follows:
ctx
from its parent process, which provides information needed to perform the process.ctx.ms
is a branched store, meaning that a branch of the multistore is made so that the process can make changes to the state as it executes without changing the original ctx.ms
. This is useful to protect the underlying multistore in case the changes need to be reverted at some point in the execution.ctx
as it is executing. It may call a subprocess and pass ctx
to them as needed.ctx
is simply discarded. If it is successful, the changes made to the CacheMultiStore
can be committed to the original ctx.ms via Write()
.Prior to calling runMsgs
on any messages in the transaction, app.cacheTxContext()
is used to branch and cache the context and multistore:
runMsgCtx
, the context with the branched store is used in runMsgs
to return a result.checkTxMode
, there is no need to write the changes. The result is returned immediately.deliverTxMode
and the result indicates a successful run over all the messages, the branched multistore is written back to the original.Game deadline
When a game is created or a move is played, the game needs to set its deadline some time in the future. The time it takes as now comes from the context.
To get this, you need a function that looks like:
After that, it is a matter of serializing this data so it is stored alongside the other parameters of the game, and of deserializing it when checking whether it has reached the deadline.
Gas costs
Another point where the context is explicitly used is when you want to make your players pay with gas for operations you specify. This gas fee comes on top of the configured standard fee for transactions on your chain. Propose some ratios, which would have to be adjusted so they make sense compared to the base transaction costs:
So you define the cost:
Next you add the line in your MsgCreateGame
handler, which already has access to the context:
As for the refund when rejecting, you have to make sure that you are not trying to refund more than what was already consumed:
If you want to go beyond out-of-context code samples like the above and see in more detail how to define these features, go to Run Your Own Cosmos Chain.
More precisely, you can jump to:
To summarize, this section has explored: