Merge PR #5379: New docs V1 (merge master-docs to master)
This commit is contained in:
committed by
Alexander Bezobchuk
parent
7d7821b9af
commit
b18bd06a36
@@ -0,0 +1,20 @@
|
||||
---
|
||||
order: false
|
||||
parent:
|
||||
order: 3
|
||||
---
|
||||
|
||||
# Core Concepts
|
||||
|
||||
This repository contains reference documentation on the core conepts of the Cosmos SDK.
|
||||
|
||||
1. [`Baseapp`](./baseapp.md)
|
||||
2. [Transaction](./transactions.md)
|
||||
3. [Context](./context.md)
|
||||
4. [Node Client](./node.md)
|
||||
5. [Store](./store.md)
|
||||
6. [Encoding](./encoding.md)
|
||||
7. [Events](./events.md)
|
||||
8. [Object-Capabilities](./ocap.md)
|
||||
|
||||
After reading about the core concepts, head on to the [Building Modules documentation](../building-modules/README.md) to learn more about the process of building modules.
|
||||
+104
-115
@@ -1,45 +1,14 @@
|
||||
# BaseApp
|
||||
---
|
||||
order: 1
|
||||
synopsis: This document describes `BaseApp`, the abstraction that implements the core functionalities of an SDK application.
|
||||
---
|
||||
|
||||
## Pre-requisite Reading
|
||||
# Baseapp
|
||||
|
||||
- [Anatomy of an SDK application](../basics/app-anatomy.md)
|
||||
- [Lifecycle of an SDK transaction](../basics/tx-lifecycle.md)
|
||||
## Pre-requisite Readings {hide}
|
||||
|
||||
## Synopsis
|
||||
|
||||
This document describes `BaseApp`, the abstraction that implements the core
|
||||
functionalities of an SDK application.
|
||||
|
||||
- [BaseApp](#baseapp)
|
||||
- [Pre-requisite Reading](#pre-requisite-reading)
|
||||
- [Synopsis](#synopsis)
|
||||
- [Introduction](#introduction)
|
||||
- [Type Definition](#type-definition)
|
||||
- [Constructor](#constructor)
|
||||
- [States](#states)
|
||||
- [InitChain](#initchain)
|
||||
- [CheckTx](#checktx)
|
||||
- [BeginBlock](#beginblock)
|
||||
- [DeliverTx](#delivertx)
|
||||
- [Commit](#commit)
|
||||
- [Routing](#routing)
|
||||
- [Message Routing](#message-routing)
|
||||
- [Query Routing](#query-routing)
|
||||
- [Main ABCI Messages](#main-abci-messages)
|
||||
- [CheckTx](#checktx-1)
|
||||
- [RecheckTx](#rechecktx)
|
||||
- [DeliverTx](#delivertx-1)
|
||||
- [RunTx, AnteHandler and RunMsgs](#runtx-antehandler-and-runmsgs)
|
||||
- [RunTx](#runtx)
|
||||
- [AnteHandler](#antehandler)
|
||||
- [RunMsgs](#runmsgs)
|
||||
- [Other ABCI Messages](#other-abci-messages)
|
||||
- [InitChain](#initchain-1)
|
||||
- [BeginBlock](#beginblock-1)
|
||||
- [EndBlock](#endblock)
|
||||
- [Commit](#commit-1)
|
||||
- [Info](#info)
|
||||
- [Query](#query)
|
||||
- [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq}
|
||||
- [Lifecycle of an SDK transaction](../basics/tx-lifecycle.md) {prereq}
|
||||
|
||||
## Introduction
|
||||
|
||||
@@ -75,18 +44,19 @@ management logic.
|
||||
|
||||
## Type Definition
|
||||
|
||||
The [`BaseApp` type](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/baseapp.go#L53) holds
|
||||
many important parameters for any Cosmos SDK based application. Let us go through the most
|
||||
important components.
|
||||
The `BaseApp` type holds many important parameters for any Cosmos SDK based application.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/baseapp/baseapp.go#L54-L108
|
||||
|
||||
Let us go through the most important components.
|
||||
|
||||
> __Note__: Not all parameters are described, only the most important ones. Refer to the
|
||||
[type definition](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/baseapp.go#L53) for the
|
||||
full list.
|
||||
type definition for the full list.
|
||||
|
||||
First, the important parameters that are initialized during the bootstrapping of the application:
|
||||
|
||||
- [`CommitMultiStore`](./store.md#commit-multi-store): This is the main store of the application,
|
||||
which holds the canonical state that is committed at the [end of each block](#commit-1). This store
|
||||
- [`CommitMultiStore`](./store.md#commitmultistore): This is the main store of the application,
|
||||
which holds the canonical state that is committed at the [end of each block](#commit). This store
|
||||
is **not** cached, meaning it is not used to update the application's volatile (un-committed) states.
|
||||
The `CommitMultiStore` is a multi-store, meaning a store of stores. Each module of the application
|
||||
uses one or multiple `KVStores` in the multi-store to persist their subset of the state.
|
||||
@@ -104,7 +74,7 @@ raw transaction bytes relayed by the underlying Tendermint engine.
|
||||
used to persist data related to the core of the application, like consensus parameters.
|
||||
- [`AnteHandler`](#antehandler): This handler is used to handle signature verification, fee payment,
|
||||
and other pre-message execution checks when a transaction is received. It's executed during
|
||||
[`CheckTx/RecheckTx`](#checktx-1) and [`DeliverTx`](#delivertx-1).
|
||||
[`CheckTx/RecheckTx`](#checktx) and [`DeliverTx`](#delivertx).
|
||||
- [`InitChainer`](../basics/app-anatomy.md#initchainer),
|
||||
[`BeginBlocker` and `EndBlocker`](../basics/app-anatomy.md#beginblocker-and-endblocker): These are
|
||||
the functions executed when the application receives the `InitChain`, `BeginBlock` and `EndBlock`
|
||||
@@ -112,11 +82,11 @@ ABCI messages from the underlying Tendermint engine.
|
||||
|
||||
Then, parameters used to define [volatile states](#volatile-states) (i.e. cached states):
|
||||
|
||||
- `checkState`: This state is updated during [`CheckTx`](#checktx-1), and reset on [`Commit`](#commit-1).
|
||||
- `deliverState`: This state is updated during [`DeliverTx`](#delivertx-1), and set to `nil` on
|
||||
[`Commit`](#commit-1) and gets re-initialized on BeginBlock.
|
||||
- `checkState`: This state is updated during [`CheckTx`](#checktx), and reset on [`Commit`](#commit).
|
||||
- `deliverState`: This state is updated during [`DeliverTx`](#delivertx), and set to `nil` on
|
||||
[`Commit`](#commit) and gets re-initialized on BeginBlock.
|
||||
|
||||
Finally, a few more important parameters:
|
||||
Finally, a few more important parameterd:
|
||||
|
||||
- `voteInfos`: This parameter carries the list of validators whose precommit is missing, either
|
||||
because they did not vote or because the proposer did not include their vote. This information is
|
||||
@@ -124,7 +94,7 @@ carried by the [Context](#context) and can be used by the application for variou
|
||||
punishing absent validators.
|
||||
- `minGasPrices`: This parameter defines the minimum gas prices accepted by the node. This is a
|
||||
**local** parameter, meaning each full-node can set a different `minGasPrices`. It is used in the
|
||||
`AnteHandler` during [`CheckTx`](#checktx-1), mainly as a spam protection mechanism. The transaction
|
||||
`AnteHandler` during [`CheckTx`](#checktx), mainly as a spam protection mechanism. The transaction
|
||||
enters the [mempool](https://tendermint.com/docs/tendermint-core/mempool.html#transaction-ordering)
|
||||
only if the gas prices of the transaction are greater than one of the minimum gas price in
|
||||
`minGasPrices` (e.g. if `minGasPrices == 1uatom,1photon`, the `gas-price` of the transaction must be
|
||||
@@ -144,20 +114,18 @@ func NewBaseApp(
|
||||
```
|
||||
|
||||
The `BaseApp` constructor function is pretty straightforward. The only thing worth noting is the
|
||||
possibility to provide additional [`options`](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/options.go)
|
||||
possibility to provide additional [`options`](https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/baseapp/options.go)
|
||||
to the `BaseApp`, which will execute them in order. The `options` are generally `setter` functions
|
||||
for important parameters, like `SetPruning()` to set pruning options or `SetMinGasPrices()` to set
|
||||
the node's `min-gas-prices`.
|
||||
|
||||
A list of `options` examples can be found
|
||||
[here](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/options.go). Naturally, developers
|
||||
can add additional `options` based on their application's needs.
|
||||
Naturally, developers can add additional `options` based on their application's needs.
|
||||
|
||||
## States
|
||||
## State Updates
|
||||
|
||||
The `BaseApp` maintains two primary volatile states and a root or main state. The main state
|
||||
is the canonical state of the application and the volatile states, `checkState` and `deliverState`,
|
||||
are used to handle state transitions in-between the main state made during [`Commit`](#commit-1).
|
||||
are used to handle state transitions in-between the main state made during [`Commit`](#commit).
|
||||
|
||||
Internally, there is only a single `CommitMultiStore` which we refer to as the main or root state.
|
||||
From this root state, we derive two volatile state through a mechanism called cache-wrapping. The
|
||||
@@ -165,14 +133,14 @@ types can be illustrated as follows:
|
||||
|
||||

|
||||
|
||||
### InitChain
|
||||
### InitChain State Updates
|
||||
|
||||
During `InitChain`, the two volatile states, `checkState` and `deliverState` are set by cache-wrapping
|
||||
the root `CommitMultiStore`. Any subsequent reads and writes happen on cached versions of the `CommitMultiStore`.
|
||||
|
||||

|
||||
|
||||
### CheckTx
|
||||
### CheckTx State Updates
|
||||
|
||||
During `CheckTx`, the `checkState`, which is based off of the last committed state from the root
|
||||
store, is used for any reads and writes. Here we only execute the `AnteHandler` and verify a router
|
||||
@@ -183,15 +151,15 @@ success.
|
||||
|
||||

|
||||
|
||||
### BeginBlock
|
||||
### BeginBlock State Updates
|
||||
|
||||
During `BeginBlock`, the `deliverState` is set for use in subsequent `DeliverTx` ABCI messages. The
|
||||
`deliverState` is based off of the last committed state from the root store and is cache-wrapped.
|
||||
Note, the `deliverState` is set to `nil` on [`Commit`](#commit-1).
|
||||
Note, the `deliverState` is set to `nil` on [`Commit`](#commit).
|
||||
|
||||

|
||||
|
||||
### DeliverTx
|
||||
### DeliverTx State Updates
|
||||
|
||||
The state flow for `DeliverTx` is nearly identical to `CheckTx` except state transitions occur on
|
||||
the `deliverState` and messages in a transaction are executed. Similarly to `CheckTx`, state transitions
|
||||
@@ -201,7 +169,7 @@ the AnteHandler are persisted.
|
||||
|
||||

|
||||
|
||||
### Commit
|
||||
### Commit State Updates
|
||||
|
||||
During `Commit` all the state transitions that occurred in the `deliverState` are finally written to
|
||||
the root `CommitMultiStore` which in turn is committed to disk and results in a new application
|
||||
@@ -216,28 +184,30 @@ When messages and queries are received by the application, they must be routed t
|
||||
|
||||
### Message Routing
|
||||
|
||||
`Message`s need to be routed after they are extracted from transactions, which are sent from the underlying Tendermint engine via the [`CheckTx`](#checktx) and [`DeliverTx`](#delivertx) ABCI messages. To do so, `baseapp` holds a [`router`](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/router.go) which maps `paths` (`string`) to the appropriate module `handler`. Usually, the `path` is the name of the module.
|
||||
[`Message`s](#../building-modules/messages-and-queries.md#messages) need to be routed after they are extracted from transactions, which are sent from the underlying Tendermint engine via the [`CheckTx`](#checktx) and [`DeliverTx`](#delivertx) ABCI messages. To do so, `baseapp` holds a `router` which maps `paths` (`string`) to the appropriate module [`handler`](../building-modules/handler.md). Usually, the `path` is the name of the module.
|
||||
|
||||
The application's `router` is initialized with all the routes using the application's module manager, which itself is initialized with all the application's modules in the application's [constructor](../basics/app-anatomy.md#app-constructor).
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/router.go
|
||||
|
||||
The application's `router` is initilalized with all the routes using the application's [module manager](../building-modules/module-manager.md#manager), which itself is initialized with all the application's modules in the application's [constructor](../basics/app-anatomy.md#app-constructor).
|
||||
|
||||
### Query Routing
|
||||
|
||||
Similar to messages, queries need to be routed to the appropriate module's querier. To do so, `baseapp` holds a [`query router`](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/queryrouter.go), which maps `paths` (`string`) to the appropriate module `querier`. Usually, the `path` is the name of the module.
|
||||
Similar to `message`s, [`queries`](../building-modules/messages-and-queries.md#queries) need to be routed to the appropriate module's [querier](../building-modules/querier.md). To do so, `baseapp` holds a `query router`, which maps module names to module `querier`s. The `queryRouter` is called during the initial stages of `query` processing, which is done via the [`Query` ABCI message](#query).
|
||||
|
||||
Just like the `router`, the `query router` is initialized with all the query routes using the application's module manager, which itself is initialized with all the application's modules in the application's [constructor](../basics/app-anatomy.md#app-constructor).
|
||||
Just like the `router`, the `query router` is initilalized with all the query routes using the application's [module manager](../building-modules/module-manager.md), which itself is initialized with all the application's modules in the application's [constructor](../basics/app-anatomy.md#app-constructor).
|
||||
|
||||
## Main ABCI Messages
|
||||
|
||||
The [Application-Blockchain Interface](https://tendermint.com/docs/spec/abci/) (ABCI) is a generic interface that connects a state-machine with a consensus engine to form a functional full-node. It can be wrapped in any language, and needs to be implemented by each application-specific blockchain built on top of an ABCI-compatible consensus engine like Tendermint.
|
||||
The [Application-Blockchain Interface](https://tendermint.com/docs/spec/abci/) (ABCI) is a generic interface that connects a state-machine with a consensus engine to form a functional full-node. It can be wrapped in any language, and needs to be implemented by each application-specific blockchain built on top of an ABCI-compatible consensus engine like Tendermint.
|
||||
|
||||
The consensus engine handles two main tasks:
|
||||
|
||||
- The networking logic, which mainly consists in gossiping block parts, transactions and consensus votes.
|
||||
- The consensus logic, which results in the deterministic ordering of transactions in the form of blocks.
|
||||
- The consensus logic, which results in the deterministic ordering of transactions in the form of blocks.
|
||||
|
||||
It is **not** the role of the consensus engine to define the state or the validity of transactions. Generally, transactions are handled by the consensus engine in the form of `[]bytes`, and relayed to the application via the ABCI to be decoded and processed. At keys moments in the networking and consensus processes (e.g. beginning of a block, commit of a block, reception of an unconfirmed transaction, ...), the consensus engine emits ABCI messages for the state-machine to act on.
|
||||
It is **not** the role of the consensus engine to define the state or the validity of transactions. Generally, transactions are handled by the consensus engine in the form of `[]bytes`, and relayed to the application via the ABCI to be decoded and processed. At keys moments in the networking and consensus processes (e.g. beginning of a block, commit of a block, reception of an unconfirmed transaction, ...), the consensus engine emits ABCI messages for the state-machine to act on.
|
||||
|
||||
Developers building on top of the Cosmos SDK need not implement the ABCI themselves, as all the ABCI messages are implemented as a set of `baseapp`'s methods in the Cosmos SDK. Let us go through the main ABCI messages that `baseapp` handles: [`CheckTx`](#checktx) and [`DeliverTx`](#delivertx). Note that these ABCI messages are different from the `message`s contained in `transactions`, the purpose of which is to trigger state-transitions.
|
||||
Developers building on top of the Cosmos SDK need not implement the ABCI themselves, as `baseapp` comes with a built-in implementation of the interface. Let us go through the main ABCI messages that `baseapp` implements: [`CheckTx`](#checktx) and [`DeliverTx`](#delivertx)
|
||||
|
||||
### CheckTx
|
||||
|
||||
@@ -247,24 +217,24 @@ transaction is received by a full-node. The role of `CheckTx` is to guard the fu
|
||||
Unconfirmed transactions are relayed to peers only if they pass `CheckTx`.
|
||||
|
||||
`CheckTx()` can perform both _stateful_ and _stateless_ checks, but developers should strive to
|
||||
make them lightweight. In the Cosmos SDK, after decoding transactions, `CheckTx()` is implemented
|
||||
make them lightweight. In the Cosmos SDK, after [decoding transactions](./encoding.md), `CheckTx()` is implemented
|
||||
to do the following checks:
|
||||
|
||||
1. Extract the `message`s from the transaction.
|
||||
2. Perform _stateless_ checks by calling `ValidateBasic()` on each of the `messages`. This is done
|
||||
first, as _stateless_ checks are less computationally expensive than _stateful_ checks. If
|
||||
`ValidateBasic()` fail, `CheckTx` returns before running _stateful_ checks, which saves resources.
|
||||
3. Perform non-module related _stateful_ checks on the account. This step is mainly about checking
|
||||
3. Perform non-module related _stateful_ checks on the [account](../basics/accounts.md). This step is mainly about checking
|
||||
that the `message` signatures are valid, that enough fees are provided and that the sending account
|
||||
has enough funds to pay for said fees. Note that no precise `gas` counting occurs here,
|
||||
as `message`s are not processed. Usually, the `AnteHandler` will check that the `gas` provided
|
||||
has enough funds to pay for said fees. Note that no precise [`gas`](../basics/gas-fees.md) counting occurs here,
|
||||
as `message`s are not processed. Usually, the [`AnteHandler`](../basics/gas-fees.md#antehandler) will check that the `gas` provided
|
||||
with the transaction is superior to a minimum reference gas amount based on the raw transaction size,
|
||||
in order to avoid spam with transactions that provide 0 gas.
|
||||
4. Ensure that a [`Route`](#message-routing) exists for each `message`, but do **not** actually
|
||||
process `message`s. `Message`s only need to be processed when the canonical state need to be updated,
|
||||
which happens during `DeliverTx`.
|
||||
|
||||
Steps 2. and 3. are performed by the `AnteHandler` in the [`RunTx()`](<#runtx()-,antehandler-and-runmsgs()>)
|
||||
Steps 2. and 3. are performed by the [`AnteHandler`](../basics/gas-fees.md#antehandler) in the [`RunTx()`](#runtx-antehandler-and-runmsgs)
|
||||
function, which `CheckTx()` calls with the `runTxModeCheck` mode. During each step of `CheckTx()`, a
|
||||
special [volatile state](#volatile-states) called `checkState` is updated. This state is used to keep
|
||||
track of the temporary changes triggered by the `CheckTx()` calls of each transaction without modifying
|
||||
@@ -279,13 +249,14 @@ is actually included in a block, because `checkState` never gets committed to th
|
||||
`CheckTx` returns a response to the underlying consensus engine of type [`abci.ResponseCheckTx`](https://tendermint.com/docs/spec/abci/abci.html#messages).
|
||||
The response contains:
|
||||
|
||||
- `Code (uint32)`: Response Code. `0` if successful.
|
||||
- `Code (uint32)`: Response Code. `0` if successful.
|
||||
- `Data ([]byte)`: Result bytes, if any.
|
||||
- `Log (string):` The output of the application's logger. May be non-deterministic.
|
||||
- `Info (string):` Additional information. May be non-deterministic.
|
||||
- `GasWanted (int64)`: Amount of gas requested for transaction. It is provided by users when they generate the transaction.
|
||||
- `GasUsed (int64)`: Amount of gas consumed by transaction. During `CheckTx`, this value is computed by multiplying the standard cost of a transaction byte by the size of the raw transaction (click [here](https://github.com/cosmos/cosmos-sdk/blob/master/x/auth/ante.go#L101) for an example).
|
||||
- `Events ([]Event)`: Key-Value events for filtering and indexing transactions (eg. by account or message type).
|
||||
- `GasWanted (int64)`: Amount of gas requested for transaction. It is provided by users when they generate the transaction.
|
||||
- `GasUsed (int64)`: Amount of gas consumed by transaction. During `CheckTx`, this value is computed by multiplying the standard cost of a transaction byte by the size of the raw transaction. Next is an example:
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/auth/ante/basic.go#L104
|
||||
- `Events ([]cmn.KVPair)`: Key-Value tags for filtering and indexing transactions (eg. by account). See [`event`s](./events.md) for more.
|
||||
- `Codespace (string)`: Namespace for the Code.
|
||||
|
||||
#### RecheckTx
|
||||
@@ -301,57 +272,69 @@ This allows certain checks like signature verification can be skipped during `Ch
|
||||
|
||||
When the underlying consensus engine receives a block proposal, each transaction in the block needs to be processed by the application. To that end, the underlying consensus engine sends a `DeliverTx` message to the application for each transaction in a sequential order.
|
||||
|
||||
Before the first transaction of a given block is processed, a [volatile state](#volatile-states) called `deliverState` is initialized during [`BeginBlock`](#beginblock). This state is updated each time a transaction is processed via `DeliverTx()`, and committed to the [main state](#main-state) when the block is [committed](#commit), after what is is set to `nil`.
|
||||
Before the first transaction of a given block is processed, a [volatile state](#volatile-states) called `deliverState` is intialized during [`BeginBlock`](#beginblock). This state is updated each time a transaction is processed via `DeliverTx`, and committed to the [main state](#main-state) when the block is [committed](#commit), after what is is set to `nil`.
|
||||
|
||||
`DeliverTx` performs the **exact same steps as `CheckTx`**, with a little caveat at step 3 and the addition of a fifth step:
|
||||
|
||||
1. The `AnteHandler` does **not** check that the transaction's `gas-prices` is sufficient. That is because the `min-gas-prices` value `gas-prices` is checked against is local to the node, and therefore what is enough for one full-node might not be for another. This means that the proposer can potentially include transactions for free, although they are not incentivised to do so, as they earn a bonus on the total fee of the block they propose.
|
||||
2. For each `message` in the transaction, route to the appropriate module's `handler`. Additional _stateful_ checks are performed, and the cache-wrapped multistore held in `deliverState`'s `context` is updated by the module's `keeper`. If the `handler` returns successfully, the cache-wrapped multistore held in `context` is written to `deliverState` `CacheMultiStore`.
|
||||
2. For each `message` in the transaction, route to the appropriate module's [`handler`](../building-modules/handler.md). Additional _stateful_ checks are performed, and the cache-wrapped multistore held in `deliverState`'s `context` is updated by the module's `keeper`. If the `handler` returns successfully, the cache-wrapped multistore held in `context` is written to `deliverState` `CacheMultiStore`.
|
||||
|
||||
During step 5., each read/write to the store increases the value of `GasConsumed`. You can find the default cost of each operation [here](https://github.com/cosmos/cosmos-sdk/blob/master/store/types/gas.go#L142-L150). At any point, if `GasConsumed > GasWanted`, the function returns with `Code != 0` and `DeliverTx()` fails.
|
||||
During step 5., each read/write to the store increases the value of `GasConsumed`. You can find the default cost of each operation:
|
||||
|
||||
`DeliverTx` returns a response to the underlying consensus engine of type [`abci.ResponseCheckTx`](https://tendermint.com/docs/spec/abci/abci.html#messages). The response contains:
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/gas.go#L142-L150
|
||||
|
||||
- `Code (uint32)`: Response Code. `0` if successful.
|
||||
At any point, if `GasConsumed > GasWanted`, the function returns with `Code != 0` and `DeliverTx` fails.
|
||||
|
||||
`DeliverTx` returns a response to the underlying consensus engine of type [`abci.ResponseDeliverTx`](https://tendermint.com/docs/spec/abci/abci.html#delivertx). The response contains:
|
||||
|
||||
- `Code (uint32)`: Response Code. `0` if successful.
|
||||
- `Data ([]byte)`: Result bytes, if any.
|
||||
- `Log (string):` The output of the application's logger. May be non-deterministic.
|
||||
- `Info (string):` Additional information. May be non-deterministic.
|
||||
- `GasWanted (int64)`: Amount of gas requested for transaction. It is provided by users when they generate the transaction.
|
||||
- `GasUsed (int64)`: Amount of gas consumed by transaction. During `DeliverTx`, this value is computed by multiplying the standard cost of a transaction byte by the size of the raw transaction (click [here](https://github.com/cosmos/cosmos-sdk/blob/master/x/auth/ante.go#L101) for an example), and by adding gas each time a read/write to the store occurs.
|
||||
- `Tags ([]cmn.KVPair)`: Key-Value tags for filtering and indexing transactions (eg. by account).
|
||||
- `GasWanted (int64)`: Amount of gas requested for transaction. It is provided by users when they generate the transaction.
|
||||
- `GasUsed (int64)`: Amount of gas consumed by transaction. During `DeliverTx`, this value is computed by multiplying the standard cost of a transaction byte by the size of the raw transaction, and by adding gas each time a read/write to the store occurs.
|
||||
- `Events ([]cmn.KVPair)`: Key-Value tags for filtering and indexing transactions (eg. by account). See [`event`s](./events.md) for more.
|
||||
- `Codespace (string)`: Namespace for the Code.
|
||||
|
||||
## RunTx, AnteHandler and RunMsgs
|
||||
|
||||
### RunTx
|
||||
|
||||
`RunTx()` is called from `CheckTx()`/`DeliverTx()` to handle the transaction, with `runTxModeCheck` or `runTxModeDeliver` as parameter to differentiate between the two modes of execution. Note that when `RunTx()` receives a transaction, it has already been decoded.
|
||||
`RunTx` is called from `CheckTx`/`DeliverTx` to handle the transaction, with `runTxModeCheck` or `runTxModeDeliver` as parameter to differentiate between the two modes of execution. Note that when `RunTx` receives a transaction, it has already been decoded.
|
||||
|
||||
The first thing `RunTx()` does upon being called is to retrieve the `context`'s `CacheMultiStore` by calling the `getContextForTx()` function with the appropriate mode (either `runTxModeCheck` or `runTxModeDeliver`). This `CacheMultiStore` is a cached version of the main store instantiated during `BeginBlock` for `DeliverTx` and during the `Commit` of the previous block for `CheckTx`. After that, two `defer func()` are called for `gas` management. They are executed when `RunTx()` returns and make sure `gas` is actually consumed, and will throw errors, if any.
|
||||
The first thing `RunTx` does upon being called is to retrieve the `context`'s `CacheMultiStore` by calling the `getContextForTx()` function with the appropriate mode (either `runTxModeCheck` or `runTxModeDeliver`). This `CacheMultiStore` is a cached version of the main store instantiated during `BeginBlock` for `DeliverTx` and during the `Commit` of the previous block for `CheckTx`. After that, two `defer func()` are called for [`gas`](../basics/gas-fees.md) management. They are executed when `runTx` returns and make sure `gas` is actually consumed, and will throw errors, if any.
|
||||
|
||||
After that, `RunTx()` calls `ValidateBasic()` on each `message`in the `Tx`, which runs preliminary _stateless_ validity checks. If any `message` fails to pass `ValidateBasic()`, `RunTx()` returns with an error.
|
||||
|
||||
Then, the [`anteHandler`](#antehandler) of the application is run (if it exists). In preparation of this step, both the `checkState`/`deliverState`'s `context` and `context`'s `CacheMultiStore` are cached-wrapped using the [`cacheTxContext()`](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/baseapp.go#L781-L798) function. This allows `RunTx()` not to commit the changes made to the state during the execution of `anteHandler` if it ends up failing. It also prevents the module implementing the `anteHandler` from writing to state, which is an important part of the [object-capabilities](./ocap.md) of the Cosmos SDK.
|
||||
Then, the [`anteHandler`](#antehandler) of the application is run (if it exists). In preparation of this step, both the `checkState`/`deliverState`'s `context` and `context`'s `CacheMultiStore` are cached-wrapped using the `cacheTxContext()` function.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/baseapp/baseapp.go#L587
|
||||
|
||||
This allows `RunTx` not to commit the changes made to the state during the execution of `anteHandler` if it ends up failing. It also prevents the module implementing the `anteHandler` from writing to state, which is an important part of the [object-capabilities](./ocap.md) of the Cosmos SDK.
|
||||
|
||||
Finally, the [`RunMsgs()`](#runmsgs) function is called to process the `messages`s in the `Tx`. In preparation of this step, just like with the `anteHandler`, both the `checkState`/`deliverState`'s `context` and `context`'s `CacheMultiStore` are cached-wrapped using the `cacheTxContext()` function.
|
||||
|
||||
### AnteHandler
|
||||
|
||||
The `AnteHandler` is a special handler that implements the [`anteHandler` interface](https://github.com/cosmos/cosmos-sdk/blob/master/types/handler.go#L8) and is used to authenticate the transaction before the transaction's internal messages are processed.
|
||||
The `AnteHandler` is a special handler that implements the `anteHandler` interface and is used to authenticate the transaction before the transaction's internal messages are processed.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/handler.go#L8
|
||||
|
||||
The `AnteHandler` is theoretically optional, but still a very important component of public blockchain networks. It serves 3 primary purposes:
|
||||
|
||||
- Be a primary line of defense against spam and second line of defense (the first one being the mempool) against transaction replay with fees deduction and `sequence`checking.
|
||||
- Perform preliminary _stateful_ validity checks like ensuring signatures are valid or that the sender has enough funds to pay for fees.
|
||||
- Play a role in the incentivisation of stakeholders via the collection of transaction fees.
|
||||
- Be a primary line of defense against spam and second line of defense (the first one being the mempool) against transaction replay with fees deduction and [`sequence`](./transactions.md#transaction-generation) checking.
|
||||
- Perform preliminary *stateful* validity checks like ensuring signatures are valid or that the sender has enough funds to pay for fees.
|
||||
- Play a role in the incentivisation of stakeholders via the collection of transaction fees.
|
||||
|
||||
`baseapp` holds an `anteHandler` as parameter, which is initialized in the [application's constructor](../basics/app-anatomy.md#application-constructor). The most widely used `anteHandler` today is that of the [`auth` module](https://github.com/cosmos/cosmos-sdk/blob/master/x/auth/ante.go).
|
||||
`baseapp` holds an `anteHandler` as paraemter, which is initialized in the [application's constructor](../basics/app-anatomy.md#application-constructor). The most widely used `anteHandler` today is that of the [`auth` module](https://github.com/cosmos/cosmos-sdk/blob/master/x/auth/ante/ante.go).
|
||||
|
||||
Click [here](../basics/gas-fees.md#antehandler) for more on the `anteHandler`.
|
||||
|
||||
### RunMsgs
|
||||
|
||||
`RunMsgs()` is called from `RunTx()` with `runTxModeCheck` as parameter to check the existence of a route for each message contained in the transaction, and with `runTxModeDeliver` to actually process the `message`s.
|
||||
`RunMsgs` is called from `RunTx` with `runTxModeCheck` as parameter to check the existence of a route for each message the transaction, and with `runTxModeDeliver` to actually process the `message`s.
|
||||
|
||||
First, it retrieves the `message`'s `route` using the `Msg.Route()` method. Then, using the application's [`router`](#routing) and the `route`, it checks for the existence of a `handler`. At this point, if `mode == runTxModeCheck`, `RunMsgs()` returns. If instead `mode == runTxModeDeliver`, the `handler` function for the message is executed, before `RunMsgs()` returns.
|
||||
First, it retreives the `message`'s `route` using the `Msg.Route()` method. Then, using the application's [`router`](#routing) and the `route`, it checks for the existence of a `handler`. At this point, if `mode == runTxModeCheck`, `RunMsgs` returns. If instead `mode == runTxModeDeliver`, the [`handler`](../building-modules/handler.md) function for the message is executed, before `RunMsgs` returns.
|
||||
|
||||
## Other ABCI Messages
|
||||
|
||||
@@ -359,44 +342,50 @@ First, it retrieves the `message`'s `route` using the `Msg.Route()` method. Then
|
||||
|
||||
The [`InitChain` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.html#initchain) is sent from the underlying Tendermint engine when the chain is first started. It is mainly used to **initialize** parameters and state like:
|
||||
|
||||
- [Consensus Parameters](https://tendermint.com/docs/spec/abci/apps.html#consensus-parameters) via `setConsensusParams`.
|
||||
- [Consensus Parameters](https://tendermint.com/docs/spec/abci/apps.html#consensus-parameters) via `setConsensusParams`.
|
||||
- [`checkState` and `deliverState`](#volatile-states) via `setCheckState` and `setDeliverState`.
|
||||
- The block gas meter, with infinite gas to process genesis transactions.
|
||||
- The [block gas meter](../basics/gas-fees.md#block-gas-meter), with infinite gas to process genesis transactions.
|
||||
|
||||
Finally, the `InitChain(req abci.RequestInitChain)` method of `baseapp` calls the [`initChainer()`](../basics/app-anatomy.md#initchainer) of the application in order to initialize the main state of the application from the [`genesis file`](./genesis.md) and, if defined, call the `InitGenesis` function of each of the application's modules.
|
||||
Finally, the `InitChain(req abci.RequestInitChain)` method of `baseapp` calls the [`initChainer()`](../basics/app-anatomy.md#initchainer) of the application in order to initialize the main state of the application from the `genesis file` and, if defined, call the [`InitGenesis`](../building-modules/genesis.md#initgenesis) function of each of the application's modules.
|
||||
|
||||
### BeginBlock
|
||||
|
||||
The [`BeginBlock` ABCI message](#https://tendermint.com/docs/app-dev/abci-spec.html#beginblock) is sent from the underlying Tendermint engine when a block proposal created by the correct proposer is received, before [`DeliverTx`](#delivertx) is run for each transaction in the block. It allows developers to have logic be executed at the beginning of each block. In the Cosmos SDK, the `BeginBlock(req abci.RequestBeginBlock)` method does the following:
|
||||
|
||||
- Initialize [`deliverState`](#volatile-states) with the latest header using the `req abci.RequestBeginBlock` passed as parameter via the [`setDeliverState`](https://github.com/cosmos/cosmos-sdk/blob/master/baseapp/baseapp.go#L283-L289) function.
|
||||
- Initialize the block gas meter with the `maxGas` limit. The `gas` consumed within the block cannot go above `maxGas`. This parameter is defined in the application's consensus parameters.
|
||||
- Run the application's [`begingBlocker()`](../basics/app-anatomy.md#beginblocker-and-endblock), which mainly runs the `BeginBlocker()` method of each of the application's modules.
|
||||
- Set the [`VoteInfos`](https://tendermint.com/docs/app-dev/abci-spec.html#voteinfo) of the application, i.e. the list of validators whose _precommit_ for the previous block was included by the proposer of the current block. This information is carried into the [`Context`](./context.md) so that it can be used during `DeliverTx` and `EndBlock`.
|
||||
- Initialize [`deliverState`](#volatile-states) with the latest header using the `req abci.RequestBeginBlock` passed as parameter via the `setDeliverState` function.
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/baseapp/baseapp.go#L387-L397
|
||||
This function also resets the [main gas meter](../basics/gas-fees.md#main-gas-meter).
|
||||
- Initialize the [block gas meter](../basics/gas-fees.md#block-gas-meter) with the `maxGas` limit. The `gas` consumed within the block cannot go above `maxGas`. This parameter is defined in the application's consensus parameters.
|
||||
- Run the application's [`beginBlocker()`](../basics/app-anatomy.md#beginblocker-and-endblock), which mainly runs the [`BeginBlocker()`](../building-modules/beginblock-endblock.md#beginblock) method of each of the application's modules.
|
||||
- Set the [`VoteInfos`](https://tendermint.com/docs/app-dev/abci-spec.html#voteinfo) of the application, i.e. the list of validators whose *precommit* for the previous block was included by the proposer of the current block. This information is carried into the [`Context`](./context.md) so that it can be used during `DeliverTx` and `EndBlock`.
|
||||
|
||||
### EndBlock
|
||||
|
||||
The [`EndBlock` ABCI message](#https://tendermint.com/docs/app-dev/abci-spec.html#endblock) is sent from the underlying Tendermint engine after [`DeliverTx`](#delivertx) as been run for each transaction n the block. It allows developers to have logic be executed at the end of each block. In the Cosmos SDK, the bulk `EndBlock(req abci.RequestEndBlock)` method is to run the application's [`endBlocker()`](../basics/app-anatomy.md#beginblocker-and-endblock), which mainly runs the `EndBlocker()` method of each of the application's modules.
|
||||
The [`EndBlock` ABCI message](#https://tendermint.com/docs/app-dev/abci-spec.html#endblock) is sent from the underlying Tendermint engine after [`DeliverTx`](#delivertx) as been run for each transaction in the block. It allows developers to have logic be executed at the end of each block. In the Cosmos SDK, the bulk `EndBlock(req abci.RequestEndBlock)` method is to run the application's [`EndBlocker()`](../basics/app-anatomy.md#beginblocker-and-endblock), which mainly runs the [`EndBlocker()`](../building-modules/beginblock-endblock.md#beginblock) method of each of the application's modules.
|
||||
|
||||
### Commit
|
||||
|
||||
The [`Commit` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.html#commit) is sent from the underlying Tendermint engine after the full-node has received _precommits_ from 2/3+ of validators (weighted by voting power). On the `baseapp` end, the `Commit(res abci.ResponseCommit)` function is implemented to commit all the valid state transitions that occured during `BeginBlock()`, `DeliverTx()` and `EndBlock()` and to reset state for the next block.
|
||||
The [`Commit` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.html#commit) is sent from the underlying Tendermint engine after the full-node has received *precommits* from 2/3+ of validators (weighted by voting power). On the `baseapp` end, the `Commit(res abci.ResponseCommit)` function is implemented to commit all the valid state transitions that occured during `BeginBlock`, `DeliverTx` and `EndBlock` and to reset state for the next block.
|
||||
|
||||
To commit state-transitions, the `Commit` function calls the `Write()` function on `deliverState.ms`, where `deliverState.ms` is a cached multistore of the main store `app.cms`. Then, the `Commit` function sets `checkState` to the latest header (obtained from `deliverState.ctx.BlockHeader`) and `deliverState` to `nil`.
|
||||
To commit state-transitions, the `Commit` function calls the `Write()` function on `deliverState.ms`, where `deliverState.ms` is a cached multistore of the main store `app.cms`. Then, the `Commit` function sets `checkState` to the latest header (obtbained from `deliverState.ctx.BlockHeader`) and `deliverState` to `nil`.
|
||||
|
||||
Finally, `Commit` returns the hash of the commitment of `app.cms` back to the underlying consensus engine. This hash is used as a reference in the header of the next block.
|
||||
Finally, `Commit` returns the hash of the commitment of `app.cms` back to the underlying consensus engine. This hash is used as a reference in the header of the next block.
|
||||
|
||||
### Info
|
||||
|
||||
The [`Info` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.html#info) is a simple query from the underlying consensus engine, notably used to sync the latter with the application during a handshake that happens on startup. When called, the `Info(res abci.ResponseInfo)` function from `baseapp` will return the application's name, version and the hash of the last commit of `app.cms`.
|
||||
The [`Info` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.html#info) is a simple query from the underlying consensus engine, notably used to sync the latter with the application during a handshake that happens on startup. When called, the `Info(res abci.ResponseInfo)` function from `baseapp` will return the application's name, version and the hash of the last commit of `app.cms`.
|
||||
|
||||
### Query
|
||||
### Query
|
||||
|
||||
The [`Query` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.html#query) is used to serve queries received from the underlying consensus engine, including queries received via RPC like Tendermint RPC. It is the main entrypoint to build interfaces with the application. The application must respect a few rules when implementing the `Query` method, which are outlined [here](https://tendermint.com/docs/app-dev/abci-spec.html#query).
|
||||
The [`Query` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.html#query) is used to serve queries received from the underlying consensus engine, including queries received via RPC like Tendermint RPC. It is the main entrypoint to build interfaces with the application. The application must respect a few rules when implementing the `Query` method, which are outlined [here](https://tendermint.com/docs/app-dev/abci-spec.html#query).
|
||||
|
||||
The `baseapp` implementation of the `Query(req abci.RequestQuery)` method is a simple dispatcher serving 4 main categories of queries:
|
||||
Each `query` comes with a `path`, which contains multiple `string`s. By convention, the first element of the `path` (`path[0]`) contains the category of `query` (`app`, `p2p`, `store` or `custom`). The `baseapp` implementation of the `Query(req abci.RequestQuery)` method is a simple dispatcher serving these 4 main categories of queries:
|
||||
|
||||
- Application-related queries like querying the application's version, which are served via the `handleQueryApp` method.
|
||||
- Direct queries to the multistore, which are served by the `handlerQueryStore` method. These direct queries are different from custom queries which go through `app.queryRouter`, and are mainly used by third-party service provider like block explorers.
|
||||
- Direct queries to the multistore, which are served by the `handlerQueryStore` method. These direct queryeis are different from custom queries which go through `app.queryRouter`, and are mainly used by third-party service provider like block explorers.
|
||||
- P2P queries, which are served via the `handleQueryP2P` method. These queries return either `app.addrPeerFilter` or `app.ipPeerFilter` that contain the list of peers filtered by address or IP respectively. These lists are first initialized via `options` in `baseapp`'s [constructor](#constructor).
|
||||
- Custom queries, which encompass most queries, are served via the `handleQueryCustom` method. The `handleQueryCustom` cache-wraps the multistore before using the `queryRoute` obtained from [`app.queryRouter`](#query-routing) to map the query to the appropriate module's `querier`.
|
||||
|
||||
## Next {hide}
|
||||
|
||||
Learn more about [transactions](./transactions.md) {hide}
|
||||
@@ -0,0 +1,117 @@
|
||||
---
|
||||
order: 3
|
||||
synopsis: The `context` is a data structure intended to be passed from function to function that carries information about the current state of the application. It holds a cached copy of the entire state as well as useful objects and information like `gasMeter`, `block height`, `consensus parameters` and more.
|
||||
---
|
||||
|
||||
# Context
|
||||
|
||||
## Pre-requisites Readings {hide}
|
||||
|
||||
- [Anatomy of an SDK Application](../basics/app-anatomy.md) {prereq}
|
||||
- [Lifecycle of a Transaction](../basics/tx-lifecycle.md) {prereq}
|
||||
|
||||
## Context Definition
|
||||
|
||||
The SDK `Context` is a custom data structure that contains Go's stdlib [`context`](https://golang.org/pkg/context) as its base, and has many additional types within its definition that are specific to the Cosmos SDK. he `Context` is integral to transaction processing in that it allows modules to easily access their respective [store](./store.md#base-layer-kvstores) in the [`multistore`](./store.md#multistore) and retrieve transactional context such as the block header and gas meter.
|
||||
|
||||
```go
|
||||
type Context struct {
|
||||
ctx context.Context
|
||||
ms MultiStore
|
||||
header abci.Header
|
||||
chainID string
|
||||
txBytes []byte
|
||||
logger log.Logger
|
||||
voteInfo []abci.VoteInfo
|
||||
gasMeter GasMeter
|
||||
blockGasMeter GasMeter
|
||||
checkTx bool
|
||||
minGasPrice DecCoins
|
||||
consParams *abci.ConsensusParams
|
||||
eventManager *EventManager
|
||||
}
|
||||
```
|
||||
|
||||
- **Context:** The base type is a Go [Context](https://golang.org/pkg/context), which is explained further in the [Go Context Package](#go-context-package) section below.
|
||||
- **Multistore:** Every application's `BaseApp` contains a [`CommitMultiStore`](./store.md#multistore) which is provided when a `Context` is created. Calling the `KVStore()` and `TransientStore()` methods allows modules to fetch their respective [`KVStore`](./store.md#base-layer-kvstores) using their unique `StoreKey`.
|
||||
- **ABCI Header:** The [header](https://tendermint.com/docs/spec/abci/abci.html#header) is an ABCI type. It carries important information about the state of the blockchain, such as block height and proposer of the current block.
|
||||
- **Chain ID:** The unique identification number of the blockchain a block pertains to.
|
||||
- **Transaction Bytes:** The `[]byte` representation of a transaction being processed using the context. Every transaction is processed by various parts of the SDK and consensus engine (e.g. Tendermint) throughout its [lifecycle](../basics/tx-lifecycle.md), some of which to not have any understanding of transaction types. Thus, transactions are marshaled into the generic `[]byte` type using some kind of [encoding format](./encoding.md) such as [Amino](./encoding.md).
|
||||
- **Logger:** A `logger` from the Tendermint libraries. Learn more about logs [here](https://tendermint.com/docs/tendermint-core/how-to-read-logs.html#how-to-read-logs). Modules call this method to create their own unique module-specific logger.
|
||||
- **VoteInfo:** A list of the ABCI type [`VoteInfo`](https://tendermint.com/docs/spec/abci/abci.html#voteinfo), which includes the name of a validator and a boolean indicating whether they have signed the block.
|
||||
- **Gas Meters:** Specifically, a [`gasMeter`](../basics/gas-fees.md#main-gas-meter) for the transaction currently being processed using the context and a [`blockGasMeter`](../basics/gas-fees.md#block-gas-meter) 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](../basics/gas-fees.md) 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.
|
||||
- **Min Gas Price:** The minimum [gas](../basics/gas-fees.md) price a node is willing to take in order to include a transaction in its block. This price is a local value configured by each node individually, and should therefore **not be used in any functions used in sequences leading to state-transitions**.
|
||||
- **Consensus Params:** The ABCI type [Consensus Parameters](https://tendermint.com/docs/spec/abci/apps.html#consensus-parameters), which specify certain limits for the blockchain, such as maximum gas for a block.
|
||||
- **Event Manager:** The event manager allows any caller with access to a `Context` to emit [`Events`](./events.md). Modules may define module specific
|
||||
`Events` by defining various `Types` and `Attributes` or use the common definitions found in `types/`. Clients can subscribe or query for these `Events`. These `Events` are collected throughout `DeliverTx`, `BeginBlock`, and `EndBlock` and are returned to Tendermint for indexing. For example:
|
||||
|
||||
```go
|
||||
ctx.EventManager().EmitEvent(sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory)),
|
||||
)
|
||||
```
|
||||
|
||||
## Go Context Package
|
||||
|
||||
A basic `Context` is defined in the [Golang Context Package](https://golang.org/pkg/context). 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 goroutines.
|
||||
|
||||
Contexts are intended to be **immutable**; they should never be edited. Instead, the convention is
|
||||
to create a child context from its parent using a `With` function. For example:
|
||||
|
||||
``` go
|
||||
childCtx = parentCtx.WithBlockHeader(header)
|
||||
```
|
||||
|
||||
The [Golang Context Package](https://golang.org/pkg/context) documentation instructs developers to
|
||||
explicitly pass a context `ctx` as the first argument of a process.
|
||||
|
||||
## Cache Wrapping
|
||||
|
||||
The `Context` contains a `MultiStore`, which allows for cache-wrapping functionality: a `CacheMultiStore`
|
||||
where each `KVStore` is is wrapped with an ephemeral cache. Processes are free to write changes to
|
||||
the `CacheMultiStore`, then write the changes back to the original state or disregard them if something
|
||||
goes wrong. The pattern of usage for a Context is as follows:
|
||||
|
||||
1. A process receives a Context `ctx` from its parent process, which provides information needed to
|
||||
perform the process.
|
||||
2. The `ctx.ms` is **cache wrapped**, i.e. a cached copy of the [multistore](./store.md#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.
|
||||
3. The process may read and write from `ctx` as it is executing. It may call a subprocess and pass
|
||||
`ctx` to it as needed.
|
||||
4. When a subprocess returns, it checks if the result is a success or failure. If a failure, nothing
|
||||
needs to be done - the cache wrapped `ctx` is simply discarded. If successful, the changes made to
|
||||
the cache-wrapped `MultiStore` can be committed to the original `ctx.ms` via `Write()`.
|
||||
|
||||
For example, here is a snippet from the [`runTx`](./baseapp.md#runtx-and-runmsgs) function in
|
||||
[`baseapp`](./baseapp.md):
|
||||
|
||||
```go
|
||||
runMsgCtx, msCache := app.cacheTxContext(ctx, txBytes)
|
||||
result = app.runMsgs(runMsgCtx, msgs, mode)
|
||||
result.GasWanted = gasWanted
|
||||
|
||||
if mode != runTxModeDeliver {
|
||||
return result
|
||||
}
|
||||
|
||||
if result.IsOK() {
|
||||
msCache.Write()
|
||||
}
|
||||
```
|
||||
|
||||
Here is the process:
|
||||
|
||||
1. Prior to calling `runMsgs` on the message(s) in the transaction, it uses `app.cacheTxContext()`
|
||||
to cache-wrap the context and multistore.
|
||||
2. The cache-wrapped context, `runMsgCtx`, is used in `runMsgs` to return a result.
|
||||
3. If the process is running in [`checkTxMode`](./baseapp.md#checktx), there is no need to write the
|
||||
changes - the result is returned immediately.
|
||||
4. If the process is running in [`deliverTxMode`](./baseapp.md#delivertx) and the result indicates
|
||||
a successful run over all the messages, the cached multistore is written back to the original.
|
||||
|
||||
## Next {hide}
|
||||
|
||||
Learn about the [node client](./node.md) {hide}
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
order: 6
|
||||
synopsis: The `codec` is used everywhere in the Cosmos SDK to encode and decode structs and interfaces. The specific codec used in the Cosmos SDK is called `go-amino`
|
||||
---
|
||||
|
||||
# Encoding
|
||||
|
||||
## Pre-requisite Readings {hide}
|
||||
|
||||
- [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq}
|
||||
|
||||
## Encoding
|
||||
|
||||
Every Cosmos SDK application exposes a global `codec` to marshal/unmarshal structs and interfaces in order to store and/or transfer them. As of now, the `codec` used in the Cosmos SDK is [go-amino](https://github.com/tendermint/go-amino), which possesses the following important properties:
|
||||
|
||||
- Interface support.
|
||||
- Deterministic encoding of value (which is required considering that blockchains are deterministic replicated state-machines).
|
||||
- Upgradeable schemas.
|
||||
|
||||
The application's `codec` is typically initialized in the [application's constructor function](../basics/app-anatomy.md#constructor-function), where it is also passed to each of the application's modules via the [basic manager](../building-modules/module-manager.md#basic-manager).
|
||||
|
||||
Among other things, the `codec` is used by module's [`keeper`s](../building-modules/keeper.md) to marshal objects into `[]byte` before storing them in the module's [`KVStore`](./store.md#kvstore), or to unmarshal them from `[]byte` when retrieving them:
|
||||
|
||||
```go
|
||||
// typical pattern to marshal an object to []byte before storing it
|
||||
bz := keeper.cdc.MustMarshalBinaryBare(object)
|
||||
|
||||
//typical pattern to unmarshal an object from []byte when retrieving it
|
||||
keeper.cdc.MustUnmarshalBinaryBare(bz, &object)
|
||||
```
|
||||
|
||||
Alternatively, it is possible to use `MustMarshalBinaryLengthPrefixed`/`MustUnmarshalBinaryLengthPrefixed` instead of `MustMarshalBinaryBare`/`MustUnmarshalBinaryBare` for the same encoding prefixed by a `uvarint` encoding of the object to encode.
|
||||
|
||||
Another important use of the `codec` is the encoding and decoding of [transactions](./transactions.md). Transactions are defined at the Cosmos SDK level, but passed to the underlying consensus engine in order to be relayed to other peers. Since the underlying consensus engine is agnostic to the application, it only accepts transactions in the form of `[]byte`. The encoding is done by an object called `TxEncoder` and the decoding by an object called `TxDecoder`.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/tx_msg.go#L45-L49
|
||||
|
||||
A standard implementation of both these objects can be found in the [`auth` module](https://github.com/cosmos/cosmos-sdk/blob/master/x/auth):
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/auth/types/stdtx.go#L241-L266
|
||||
|
||||
## Next {hide}
|
||||
|
||||
Learn about [events](./events.md) {hide}
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
order: 7
|
||||
synopsis: "`Event`s are objects that contain information about the execution of the application. They are mainly used by service providers like block explorers and wallet to track the execution of various messages and index transactions."
|
||||
---
|
||||
|
||||
# Events
|
||||
|
||||
## Pre-Requisite Readings {hide}
|
||||
|
||||
- [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq}
|
||||
|
||||
## Events
|
||||
|
||||
`Event`s are implemented in the Cosmos SDK as an alias of the ABCI `event` type.
|
||||
|
||||
+++ https://github.com/tendermint/tendermint/blob/bc572217c07b90ad9cee851f193aaa8e9557cbc7/abci/types/types.pb.go#L2661-L2667
|
||||
|
||||
They contain:
|
||||
|
||||
- A **`type`** of type `string`, which can refer to the type of action that led to the `event`'s emission (e.g. a certain value going above a threshold), or to the type of `message` if the event is triggered at the end of that `message` processing.
|
||||
- A list of `attributes`, which are key-value pairs that give more information about the `event`.
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/events.go#L51-L56
|
||||
|
||||
`Event`s are returned to the underlying consensus engine in the response of the following ABCI messages: [`CheckTx`](./baseapp.md#checktx), [`DeliverTx`](./baseapp.md#delivertx), [`BeginBlock`](./baseapp.md#beginblock) and [`EndBlock`](./baseapp.md#endblock).
|
||||
|
||||
Typically, `event` `type`s and `attributes` are defined on a **per-module basis** in the module's `/internal/types/events.go` file, and triggered from the module's [`handler`](../building-modules/handler.md) via the [`EventManager`](#eventmanager).
|
||||
|
||||
## EventManager
|
||||
|
||||
In Cosmos SDK applications, `event`s are generally managed by an object called the `EventManager`. It is implemented as a simple wrapper around a slice of `event`s:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/events.go#L16-L20
|
||||
|
||||
The `EventManager` comes with a set of useful methods to manage `event`s. Among them, the one that is used the most by module and application developers is the `EmitEvent` method, which registers an `event` in the `EventManager`.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/events.go#L29-L31
|
||||
|
||||
Typically, module developers will implement event emission via the `EventManager` in the [`handler`](../building-modules/handler.md) of modules, as well as in the [`BeginBlocker` and/or`EndBlocker` functions](../building-modules/beginblock-endblock.md). The `EventManager` is accessed via the context [`ctx`](./context.md), and event emission generally follows this pattern:
|
||||
|
||||
```go
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
eventType, // e.g. sdk.EventTypeMessage for a message, types.CustomEventType for a custom event defined in the module
|
||||
sdk.NewAttribute(attributeKey, attributeValue),
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
See the [`handler` concept doc](../building-modules/handler.md) for a more detailed view on how to typically implement `events` and use the `EventManager` in modules.
|
||||
|
||||
## Subscribing to `events`
|
||||
|
||||
It is possible to subscribe to `events` via [Tendermint's Websocket](https://tendermint.com/docs/app-dev/subscribing-to-events-via-websocket.html#subscribing-to-events-via-websocket). This is done by calling the `subscribe` RPC method via Websocket:
|
||||
|
||||
```
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "subscribe",
|
||||
"id": "0",
|
||||
"params": {
|
||||
"query": "tm.event='eventCategory' AND type.attribute='attributeValue'"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The main `eventCategory` you can subscribe to are:
|
||||
|
||||
- `NewBlock`: Contains `events` triggered during `BeginBlock` and `EndBlock`.
|
||||
- `Tx`: Contains `events` triggered during `DeliverTx` (i.e. transaction processing).
|
||||
- `ValidatorSetUpdates`: Contains validator set updates for the block.
|
||||
|
||||
These events are triggered from the `state` package after a block is committed. You can get the full list of `event` categories [here](https://godoc.org/github.com/tendermint/tendermint/types#pkg-constants).
|
||||
|
||||
The `type` and `attribute` value of the `query` allow you to filter the specific `event` you are looking for. For example, a `transfer` transaction triggers an `event` of type `Transfer` and has `Recipient` and `Sender` as `attributes` (as defined in the [`events` file of the `bank` module](https://github.com/cosmos/cosmos-sdk/blob/master/x/bank/internal/types/events.go)). Subscribing to this `event` would be done like so:
|
||||
|
||||
```
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "subscribe",
|
||||
"id": "0",
|
||||
"params": {
|
||||
"query": "tm.event='Tx' AND transfer.sender='senderAddress'"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
where `senderAddress` is an address following the [`AccAddress`](../basics/accounts.md#addresses) format.
|
||||
|
||||
## Next {hide}
|
||||
|
||||
Learn about [object-capabilities](./ocap.md) {hide}
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
order: 4
|
||||
synopsis: The main endpoint of an SDK application is the daemon client, otherwise known as the full-node client. The full-node runs the state-machine, starting from a genesis file. It connects to peers running the same client in order to receive and relay transactions, block proposals and signatures. The full-node is constituted of the application, defined with the Cosmos SDK, and of a consensus engine connected to the application via the ABCI.
|
||||
---
|
||||
|
||||
# Node Client (Daemon)
|
||||
|
||||
## Pre-requisite Readings {hide}
|
||||
|
||||
- [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq}
|
||||
|
||||
## `main` function
|
||||
|
||||
The full-node client of any SDK application is built by running a `main` function. The client is generally named by appending the `-d` suffix to the application name (e.g. `appd` for an application named `app`), and the `main` function is defined in a `./cmd/appd/main.go` file. Running this function creates an executable `.appd` that comes with a set of commands. For an app named `app`, the main command is [`appd start`](#start-command), which starts the full-node.
|
||||
|
||||
In general, developers will implement the `main.go` function with the following structure:
|
||||
|
||||
- First, a [`codec`](./encoding.md) is instanciated for the application.
|
||||
- Then, the `config` is retrieved and config parameters are set. This mainly involves setting the bech32 prefixes for [addresses and pubkeys](../basics/accounts.md#addresses-and-pubkeys).
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/config.go#L10-L21
|
||||
- Using [cobra](https://github.com/spf13/cobra), the root command of the full-node client is created. After that, all the custom commands of the application are added using the `AddCommand()` method of `rootCmd`.
|
||||
- Add default server commands to `rootCmd` using the `server.AddCommands(ctx, cdc, rootCmd, newApp, exportAppStateAndTMValidators)` method. These commands are separated from the ones added above since they are standard and defined at SDK level. They should be shared by all SDK-based applications. They include the most important command: the [`start` command](#start-command).
|
||||
- Prepare and execute the `executor`.
|
||||
+++ https://github.com/tendermint/tendermint/blob/bc572217c07b90ad9cee851f193aaa8e9557cbc7/libs/cli/setup.go#L75-L78
|
||||
|
||||
See an example of `main` function from the [`gaia`](https://github.com/cosmos/gaia) application:
|
||||
|
||||
+++ https://github.com/cosmos/gaia/blob/f41a660cdd5bea173139965ade55bd25d1ee3429/cmd/gaiad/main.go
|
||||
|
||||
## `start` command
|
||||
|
||||
The `start` command is defined in the `/server` folder of the Cosmos SDK. It is added to the root command of the full-node client in the [`main` function](#main-function) and called by the end-user to start their node:
|
||||
|
||||
```go
|
||||
// For an example app named "app", the following command starts the full-node
|
||||
|
||||
appd start
|
||||
```
|
||||
|
||||
As a reminder, the full-node is composed of three conceptual layers: the networking layer, the consensus layer and the application layer. The first two are generally bundled together in an entity called the consensus engine (Tendermint Core by default), while the third is the state-machine defined with the help of the Cosmos SDK. Currently, the Cosmos SDK uses Tendermint as the default consensus engine, meaning the start command is implemented to boot up a Tendermint node.
|
||||
|
||||
The flow of the `start` command is pretty straightforward. First, it retrieves the `config` from the `context` in order to open the `db` (a [`leveldb`](https://github.com/syndtr/goleveldb) instance by default). This `db` contains the latest known state of the application (empty if the application is started from the first time.
|
||||
|
||||
With the `db`, the `start` command creates a new instance of the application using an `appCreator` function:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/server/start.go#L144
|
||||
|
||||
Note that an `appCreator` is a function that fulfills the `AppCreator` signature. In practice, the [constructor the application](../basics/app-anatomy.md#constructor-function) is passed as the `appCreator`.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/server/constructors.go#L17-L25
|
||||
|
||||
Then, the instance of `app` is used to instanciate a new Tendermint node:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/server/start.go#L153-L163
|
||||
|
||||
The Tendermint node can be created with `app` because the latter satisfies the [`abci.Application` interface](https://github.com/tendermint/tendermint/blob/bc572217c07b90ad9cee851f193aaa8e9557cbc7/abci/types/application.go#L11-L26) (given that `app` extends [`baseapp`](./baseapp.md)). As part of the `NewNode` method, Tendermint makes sure that the height of the application (i.e. number of blocks since genesis) is equal to the height of the Tendermint node. The difference between these two heights should always be negative or null. If it is strictly negative, `NewNode` will replay blocks until the height of the application reaches the height of the Tendermint node. Finally, if the height of the application is `0`, the Tendermint node will call [`InitChain`](./baseapp.md#initchain) on the application to initialize the state from the genesis file.
|
||||
|
||||
Once the Tendermint node is instanciated and in sync with the application, the node can be started:
|
||||
|
||||
```go
|
||||
if err := tmNode.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
```
|
||||
|
||||
Upon starting, the node will bootstrap its RPC and P2P server and start dialing peers. During handshake with its peers, if the node realizes they are ahead, it will query all the blocks sequentially in order to catch up. Then, it will wait for new block proposals and block signatures from validators in order to make progress.
|
||||
|
||||
## Next {hide}
|
||||
|
||||
Learn about the [store](./store.md) {hide}
|
||||
+8
-13
@@ -1,13 +1,12 @@
|
||||
---
|
||||
order: false
|
||||
order: 8
|
||||
---
|
||||
|
||||
# Object-Capability Model
|
||||
|
||||
## Intro
|
||||
|
||||
When thinking about security, it is good to start with a specific threat
|
||||
model. Our threat model is the following:
|
||||
When thinking about security, it is good to start with a specific threat model. Our threat model is the following:
|
||||
|
||||
> We assume that a thriving ecosystem of Cosmos-SDK modules that are easy to compose into a blockchain application will contain faulty or malicious modules.
|
||||
|
||||
@@ -67,14 +66,10 @@ var sumValue := externalModule.ComputeSumValue(*account)
|
||||
```
|
||||
|
||||
In the Cosmos SDK, you can see the application of this principle in the
|
||||
[gaia app](../gaia/app/app.go).
|
||||
gaia app.
|
||||
|
||||
```go
|
||||
// register message routes
|
||||
app.Router().
|
||||
AddRoute(bank.RouterKey, bank.NewHandler(app.bankKeeper)).
|
||||
AddRoute(staking.RouterKey, staking.NewHandler(app.stakingKeeper)).
|
||||
AddRoute(distr.RouterKey, distr.NewHandler(app.distrKeeper)).
|
||||
AddRoute(slashing.RouterKey, slashing.NewHandler(app.slashingKeeper)).
|
||||
AddRoute(gov.RouterKey, gov.NewHandler(app.govKeeper))
|
||||
```
|
||||
+++ https://github.com/cosmos/gaia/blob/master/app/app.go#L197-L209
|
||||
|
||||
## Next
|
||||
|
||||
Learn about [building modules](../building-modules/intro.md) {hide}
|
||||
@@ -0,0 +1,237 @@
|
||||
---
|
||||
order: 5
|
||||
synopsis: A store is a data structure that holds the state of the application.
|
||||
---
|
||||
|
||||
# Store
|
||||
|
||||
## Pre-requisite Readings {hide}
|
||||
|
||||
- [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq}
|
||||
|
||||
## Introduction to SDK Stores
|
||||
|
||||
The Cosmos SDK comes with a large set of stores to persist the state of applications. By default, the main store of SDK applications is a `multistore`, i.e. a store of stores. Developers can add any number of key-value stores to the multistore, depending on their application needs. The multistore exists to support the modularity of the Cosmos SDK, as it lets each module declare and manage their own subset of the state. Key-value stores in the multistore can only be accessed with a specific capability `key`, which is typically held in the [`keeper`](../building-modules/keeper.md) of the module that declared the store.
|
||||
|
||||
```
|
||||
+-----------------------------------------------------+
|
||||
| |
|
||||
| +--------------------------------------------+ |
|
||||
| | | |
|
||||
| | KVStore 1 - Manage by keeper of Module 1 |
|
||||
| | | |
|
||||
| +--------------------------------------------+ |
|
||||
| |
|
||||
| +--------------------------------------------+ |
|
||||
| | | |
|
||||
| | KVStore 2 - Manage by keeper of Module 2 | |
|
||||
| | | |
|
||||
| +--------------------------------------------+ |
|
||||
| |
|
||||
| +--------------------------------------------+ |
|
||||
| | | |
|
||||
| | KVStore 3 - Manage by keeper of Module 2 | |
|
||||
| | | |
|
||||
| +--------------------------------------------+ |
|
||||
| |
|
||||
| +--------------------------------------------+ |
|
||||
| | | |
|
||||
| | KVStore 4 - Manage by keeper of Module 3 | |
|
||||
| | | |
|
||||
| +--------------------------------------------+ |
|
||||
| |
|
||||
| +--------------------------------------------+ |
|
||||
| | | |
|
||||
| | KVStore 5 - Manage by keeper of Module 4 | |
|
||||
| | | |
|
||||
| +--------------------------------------------+ |
|
||||
| |
|
||||
| Main Multistore |
|
||||
| |
|
||||
+-----------------------------------------------------+
|
||||
|
||||
Application's State
|
||||
```
|
||||
|
||||
### Store Interface
|
||||
|
||||
At its very core, a Cosmos SDK `store` is an object that holds a `CacheWrapper` and implements a `GetStoreType()` method:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L12-L15
|
||||
|
||||
The `GetStoreType` is a simple method that returns the type of store, whereas a `CacheWrapper` is a simple interface that specifies cache-wrapping and `Write` methods:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L217-L238
|
||||
|
||||
Cache-wrapping is used ubiquitously in the Cosmos SDK and required to be implemented on every store type. A cache-wrapper creates a light snapshot of a store that can be passed around and updated without affecting the main underlying store. This is used to trigger temporary state-transitions that may be reverted later should an error occur. If a state-transition sequence is performed without issue, the cached store can be comitted to the underlying store at the end of the sequence.
|
||||
|
||||
### Commit Store
|
||||
|
||||
A commit store is a store that has the ability to commit changes made to the underlying tree or db. The Cosmos SDK differentiates simple stores from commit stores by extending the basic store interfaces with a `Committer`:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L24-L28
|
||||
|
||||
The `Committer` is an interface that defines methods to persist changes to disk:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L17-L22
|
||||
|
||||
The `CommitID` is a deterministic commit of the state tree. Its hash is returned to the underlying consensus engine and stored in the block header. Note that commit store interfaces exist for various purposes, one of which is to make sure not every object can commit the store. As part of the [object-capabilities model](./ocap.md) of the Cosmos SDK, only `baseapp` should have the ability to commit stores. For example, this is the reason why the `ctx.KVStore()` method by which modules typically access stores returns a `KVStore` and not a `CommitKVStore`.
|
||||
|
||||
The Cosmos SDK comes with many types of stores, the most used being [`CommitMultiStore`](#multistore), [`KVStore`](#kvstore) and [`GasKv` store](#gaskv-store). [Other types of stores](#other-stores) include `Transient` and `TraceKV` stores.
|
||||
|
||||
## Multistore
|
||||
|
||||
### Multistore Interface
|
||||
|
||||
Each Cosmos SDK application holds a multistore at its root to persist its state. The multistore is a store of `KVStores` that follows the `Multistore` interface:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L83-L112
|
||||
|
||||
If tracing is enabled, then cache-wrapping the multistore will wrap all the underlying `KVStore` in [`TraceKv.Store`](#tracekv-store) before caching them.
|
||||
|
||||
### CommitMultiStore
|
||||
|
||||
The main type of `Multistore` used in the Cosmos SDK is `CommitMultiStore`, which is an extension of the `Multistore` interface:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L120-L158
|
||||
|
||||
As for concrete implementation, the [`rootMulti.Store`] is the go-to implementation of the `CommitMultiStore` interface.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/rootmulti/store.go#L27-L43
|
||||
|
||||
The `rootMulti.Store` is a base-layer multistore built around a `db` on top of which multiple `KVStores` can be mounted, and is the default multistore store used in [`baseapp`](./baseapp.md).
|
||||
|
||||
### CacheMultiStore
|
||||
|
||||
Whenever the `rootMulti.Store` needs to be cached-wrapped, a [`cachemulti.Store`](https://github.com/cosmos/cosmos-sdk/blob/master/store/cachemulti/store.go) is used.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/cachemulti/store.go#L17-L28
|
||||
|
||||
`cachemulti.Store` cache wraps all substores in its constructor and hold them in `Store.stores`. `Store.GetKVStore()` returns the store from `Store.stores`, and `Store.Write()` recursively calls `CacheWrap.Write()` on all the substores.
|
||||
|
||||
## Base-layer KVStores
|
||||
|
||||
### `KVStore` and `CommitKVStore` Interfaces
|
||||
|
||||
A `KVStore` is a simple key-value store used to store and retrieve data. A `CommitKVStore` is a `KVStore` that also implements a `Committer`. By default, stores mounted in `baseapp`'s main `CommitMultiStore` are `CommitKVStore`s. The `KVStore` interface is primarily used to restrict modules from accessing the committer.
|
||||
|
||||
Individual `KVStore`s are used by modules to manage a subset of the global state. `KVStores` can be accessed by objects that hold a specific key. This `key` should only be exposed to the [`keeper`](../building-modules/keeper.md) of the module that defines the store.
|
||||
|
||||
`CommitKVStore`s are declared by proxy of their respective `key` and mounted on the application's [multistore](#multistore) in the [main application file](../basics/app-anatomy.md#core-application-file). In the same file, the `key` is also passed to the module's `keeper` that is responsible for managing the store.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L163-L193
|
||||
|
||||
Apart from the traditional `Get` and `Set` methods, a `KVStore` is expected to implement an `Iterator()` method which returns an `Iterator` object. The `Iterator()` method is used to iterate over a domain of keys, typically keys that share a common prefix. Here is a common pattern of using an `Iterator` that might be found in a module's `keeper`:
|
||||
|
||||
```go
|
||||
store := ctx.KVStore(keeper.storeKey)
|
||||
iterator := sdk.KVStorePrefixIterator(store, prefix) // proxy for store.Iterator
|
||||
|
||||
defer iterator.Close()
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
var object types.Object
|
||||
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &object)
|
||||
|
||||
if cb(object) {
|
||||
break
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `IAVL` Store
|
||||
|
||||
The default implementation of `KVStore` and `CommitKVStore` used in `baseapp` is the `iavl.Store`.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/iavl/store.go#L32-L47
|
||||
|
||||
`iavl` stores are based around an [IAVL Tree](https://github.com/tendermint/iavl), a self-balancing binary tree which guarantees that:
|
||||
|
||||
- `Get` and `Set` operations are O(log n), where n is the number of elements in the tree.
|
||||
- Iteration efficiently returns the sorted elements within the range.
|
||||
- Each tree version is immutable and can be retrieved even after a commit (depending on the pruning settings).
|
||||
|
||||
### `DbAdapter` Store
|
||||
|
||||
`dbadapter.Store` is a adapter for `dbm.DB` making it fulfilling the `KVStore` interface.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/dbadapter/store.go#L13-L16
|
||||
|
||||
`dbadapter.Store` embeds `dbm.DB`, meaning most of the `KVStore` interface functions are implemented. The other functions (mostly miscellaneous) are manually implemented. This store is primarily used within [Transient Stores](#transient-stores)
|
||||
|
||||
### `Transient` Store
|
||||
|
||||
`Transient.Store` is a base-layer `KVStore` which is automatically discarded at the end of the block.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/transient/store.go#L14-L17
|
||||
|
||||
`Transient.Store` is a `dbadapter.Store` with a `dbm.NewMemDB()`. All `KVStore` methods are reused. When `Store.Commit()` is called, a new `dbadapter.Store` is assigned, discarding previous reference and making it garbage collected.
|
||||
|
||||
This type of store is useful to persist information that is only relevant per-block. One example would be to store parameter changes (i.e. a bool set to `true` if a parameter changed in a block).
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/params/subspace/subspace.go#L24-L32
|
||||
|
||||
Transient stores are typically accessed via the [`context`](./context.md) via the `TransientStore()` method:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/context.go#L215-L218
|
||||
|
||||
## KVStore Wrappers
|
||||
|
||||
### CacheKVStore
|
||||
|
||||
`cachekv.Store` is a wrapper `KVStore` which provides buffered writing / cached reading functionalities over the underlying `KVStore`.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/cachekv/store.go#L26-L33
|
||||
|
||||
This is the type used whenever an IAVL Store needs to be cache-wrapped (typically when setting value that might be reverted later).
|
||||
|
||||
#### `Get`
|
||||
|
||||
`Store.Get()` checks `Store.cache` first in order to find if there is any cached value associated with the key. If the value exists, the function returns it. If not, the function calls `Store.parent.Get()`, sets the key-value pair to the `Store.cache`, and returns it.
|
||||
|
||||
#### `Set`
|
||||
|
||||
`Store.Set()` sets the key-value pair to the `Store.cache`. `cValue` has the field dirty bool which indicates whether the cached value is different from the underlying value. When `Store.Set()` cache new pair, the `cValue.dirty` is set `true` so when `Store.Write()` is called it can be written to the underlying store.
|
||||
|
||||
#### `Iterator`
|
||||
|
||||
`Store.Iterator()` have to traverse on both caches items and the original items. In `Store.iterator()`, two iterators are generated for each of them, and merged. `memIterator` is essentially a slice of the `KVPairs`, used for cached items. `mergeIterator` is a combination of two iterators, where traverse happens ordered on both iterators.
|
||||
|
||||
### `GasKv` Store
|
||||
|
||||
Cosmos SDK applications use [`gas`](../basics/gas-fees.md) to track resources usage and prevent spam. [`GasKv.Store`](https://github.com/cosmos/cosmos-sdk/blob/master/store/gaskv/store.go) is a `KVStore` wrapper that enables automatic gas consumption each time a read or write to the store is made. It is the solution of choice to track storage usage in Cosmos SDK applications.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/gaskv/store.go#L11-L17
|
||||
|
||||
When methods of the parent `KVStore` are called, `GasKv.Store` automatically consumes appropriate amount of gas depending on the `Store.gasConfig`:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/gas.go#L141-L150
|
||||
|
||||
By default, all `KVStores` are wrapped in `GasKv.Stores` when retrieved. This is done in the `KVStore()` method of the [`context`](./context.md):
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/context.go#L210-L213
|
||||
|
||||
In this case, the default gas configuration is used:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/gas.go#L152-L163
|
||||
|
||||
### `TraceKv` Store
|
||||
|
||||
`tracekv.Store` is a wrapper `KVStore` which provides operation tracing functionalities over the underlying `KVStore`. It is applied automatically by the Cosmos SDK on all `KVStore` if tracing is enabled on the parent `MultiStore`.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/tracekv/store.go#L20-L43
|
||||
|
||||
When each `KVStore` methods are called, `tracekv.Store` automatically logs `traceOperation` to the `Store.writer`. `traceOperation.Metadata` is filled with `Store.context` when it is not nil. `TraceContext` is a `map[string]interface{}`.
|
||||
|
||||
### `Prefix` Store
|
||||
|
||||
`prefix.Store` is a wrapper `KVStore` which provides automatic key-prefixing functionalities over the underlying `KVStore`.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/prefix/store.go#L17-L20
|
||||
|
||||
When `Store.{Get, Set}()` is called, the store forwards the call to its parent, with the key prefixed with the `Store.prefix`.
|
||||
|
||||
When `Store.Iterator()` is called, it does not simply prefix the `Store.prefix`, since it does not work as intended. In that case, some of the elements are traversed even they are not starting with the prefix.
|
||||
|
||||
## Next {hide}
|
||||
|
||||
Learn about [encoding](./encoding.md) {hide}
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
order: 2
|
||||
synopsis: "`Transactions` are objects created by end-users to trigger state changes in the application."
|
||||
---
|
||||
|
||||
# Transactions
|
||||
|
||||
## Pre-requisite Readings {hide}
|
||||
|
||||
* [Anatomy of an SDK Application](../basics/app-anatomy.md) {prereq}
|
||||
|
||||
## Transactions
|
||||
|
||||
Transactions are comprised of metadata held in [contexts](./context.md) and [messages](../building-modules/messages-and-queries.md) that trigger state changes within a module through the module's [Handler](../building-modules/handler.md).
|
||||
|
||||
When users want to interact with an application and make state changes (e.g. sending coins), they create transactions. Each of a transaction's `message`s must be signed using the private key associated with the appropriate account(s), before the transaction is broadcasted to the network. A transaction must then be included in a block, validated, and approved by the network through the consensus process. To read more about the lifecycle of a transaction, click [here](../basics/tx-lifecycle.md).
|
||||
|
||||
## Type Definition
|
||||
|
||||
Transaction objects are SDK types that implement the `Tx` interface
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/tx_msg.go#L34-L41
|
||||
|
||||
It contains the following methods:
|
||||
|
||||
* **GetMsgs:** unwraps the transaction and returns a list of its message(s) - one transaction may have one or multiple [messages](../building-modules/messages-and-queries.md#messages), which are defined by module developers.
|
||||
* **ValidateBasic:** includes lightweight, [*stateless*](../basics/tx-lifecycle.md#types-of-checks) checks used by ABCI messages [`CheckTx`](./baseapp.md#checktx) and [`DeliverTx`](./baseapp.md#delivertx) to make sure transactions are not invalid. For example, the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/master/x/auth) module's `StdTx` `ValidateBasic` function checks that its transactions are signed by the correct number of signers and that the fees do not exceed what the user's maximum. Note that this function is to be distinct from the `ValidateBasic` functions for *`messages`*, which perform basic validity checks on messages only. For example, when [`runTx`](./baseapp.md#runtx) is checking a transaction created from the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/master/x/auth/spec) module, it first runs `ValidateBasic` on each message, then runs the `auth` module AnteHandler which calls `ValidateBasic` for the transaction itself.
|
||||
* **TxEncoder:** Nodes running the consensus engine (e.g. Tendermint Core) are responsible for gossiping transactions and ordering them into blocks, but only handle them in the generic `[]byte` form. Transactions are always [marshaled](./encoding.md) (encoded) before they are relayed to nodes, which compacts them to facilitate gossiping and helps maintain the consensus engine's separation from from application logic. The Cosmos SDK allows developers to specify any deterministic encoding format for their applications; the default is Amino.
|
||||
* **TxDecoder:** [ABCI](https://tendermint.com/docs/spec/abci/) calls from the consensus engine to the application, such as `CheckTx` and `DeliverTx`, are used to process transaction data to determine validity and state changes. Since transactions are passed in as `txBytes []byte`, they need to first be unmarshaled (decoded) using `TxDecoder` before any logic is applied.
|
||||
|
||||
The most used implementation of the `Tx` interface is [`StdTx` from the `auth` module](https://github.com/cosmos/cosmos-sdk/blob/master/x/auth/types/stdtx.go). As a developer, using `StdTx` as your transaction format is as simple as importing the `auth` module in your application (which can be done in the [constructor of the application](../basics/app-anatomy.md#constructor-function))
|
||||
|
||||
## Transaction Process
|
||||
|
||||
A transaction is created by an end-user through one of the possible [interfaces](#interfaces). In the process, two contexts and an array of [messages](#messages) are created, which are then used to [generate](#transaction-generation) the transaction itself. The actual state changes triggered by transactions are enabled by the [handlers](#handlers). The rest of the document will describe each of these components, in this order.
|
||||
|
||||
### CLI and REST Interfaces
|
||||
|
||||
Application developers create entrypoints to the application by creating a [command-line interface](../interfaces/cli.md) and/or [REST interface](../interfaces/rest.md), typically found in the application's `./cmd` folder. These interfaces allow users to interact with the application through command-line or through HTTP requests.
|
||||
|
||||
For the [command-line interface](../building-modules/module-interfaces.md#cli), module developers create subcommands to add as children to the application top-level transaction command `TxCmd`. For [HTTP requests](../building-modules/module-interfaces.md#rest), module developers specify acceptable request types, register REST routes, and create HTTP Request Handlers.
|
||||
|
||||
When users interact with the application's interfaces, they invoke the underlying modules' handlers or command functions, directly creating messages.
|
||||
|
||||
### Messages
|
||||
|
||||
**`Message`s** are module-specific objects that trigger state transitions within the scope of the module they belong to. Module developers define the `message`s for their module by implementing the `Msg` interface, and also define a [`Handler`](../building-modules/handler.md) to process them.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/tx_msg.go#L8-L29
|
||||
|
||||
`Message`s in a module are typically defined in a `msgs.go` file (though not always), and one handler with multiple functions to handle each of the module's `message`s is defined in a `handler.go` file.
|
||||
|
||||
Note: module `messages` are not to be confused with [ABCI Messages](https://tendermint.com/docs/spec/abci/abci.html#messages) which define interactions between the Tendermint and application layers.
|
||||
|
||||
To learn more about `message`s, click [here](../building-modules/messages-and-queries.md#messages).
|
||||
|
||||
While messages contain the information for state transition logic, a transaction's other metadata and relevant information are stored in the `TxBuilder` and `CLIContext`.
|
||||
|
||||
### Transaction Generation
|
||||
|
||||
Transactions are first created by end-users through an `appcli tx` command through the command-line or a POST request to an HTTPS server. For details about transaction creation, click [here](../basics/tx-lifecycle.md#transaction-creation).
|
||||
|
||||
[`Contexts`](https://godoc.org/context) are immutable objects that contain all the information needed to process a request. In the process of creating a transaction through the `auth` module (though it is not mandatory to create transactions this way), two contexts are created: the [`CLIContext`](../interfaces/query-lifecycle.md#clicontext) and `TxBuilder`. Both are automatically generated and do not need to be defined by application developers, but do require input from the transaction creator (e.g. using flags through the CLI).
|
||||
|
||||
The `TxBuilder` contains data closely related with the processing of transactions.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/auth/types/txbuilder.go#L18-L31
|
||||
|
||||
- `TxEncoder` defined by the developer for this type of transaction. Used to encode messages before being processed by nodes running Tendermint.
|
||||
- `Keybase` that manages the user's keys and is used to perform signing operations.
|
||||
- `AccountNumber` from which this transaction originated.
|
||||
- `Sequence`, the number of transactions that the user has sent out, used to prevent replay attacks.
|
||||
- `Gas` option chosen by the users for how to calculate how much gas they will need to pay. A common option is "auto" which generates an automatic estimate.
|
||||
- `GasAdjustment` to adjust the estimate of gas by a scalar value, used to avoid underestimating the amount of gas required.
|
||||
- `SimulateAndExecute` option to simply simulate the transaction execution without broadcasting.
|
||||
- `ChainID` representing which blockchain this transaction pertains to.
|
||||
- `Memo` to send with the transaction.
|
||||
- `Fees`, the maximum amount the user is willing to pay in fees. Alternative to specifying gas prices.
|
||||
- `GasPrices`, the amount per unit of gas the user is willing to pay in fees. Alternative to specifying fees.
|
||||
|
||||
The `CLIContext` is initialized using the application's `codec` and data more closely related to the user interaction with the interface, holding data such as the output to the user and the broadcast mode. Read more about `CLIContext` [here](../interfaces/query-lifecycle.md#clicontext).
|
||||
|
||||
Every message in a transaction must be signed by the addresses specified by `GetSigners`. The signing process must be handled by a module, and the most widely used one is the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/master/x/auth/spec) module. Signing is automatically performed when the transaction is created, unless the user choses to generate and sign separately. The `TxBuilder` (namely, the `KeyBase`) is used to perform the signing operations, and the `CLIContext` is used to broadcast transactions.
|
||||
|
||||
### Handlers
|
||||
|
||||
Since `message`s are module-specific types, each module needs a [`handler`](../building-modules/handler.md) to process all of its `message` types and trigger state changes within the module's scope. This design puts more responsibility on module developers, allowing application developers to reuse common functionalities without having to implement state transition logic repetitively. To read more about `handler`s, click [here](../building-modules/handler.md).
|
||||
|
||||
## Next {hide}
|
||||
|
||||
Learn about the [context](./context.md) {hide}
|
||||
Reference in New Issue
Block a user