docs: update docs for Check/DeliverTx middlewares (#11918)
Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>
This commit is contained in:
parent
b0edb6d3ef
commit
9d8beff497
@ -235,8 +235,8 @@ func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBloc
|
||||
|
||||
// CheckTx implements the ABCI interface and executes a tx in CheckTx mode. In
|
||||
// CheckTx mode, messages are not executed. This means messages are only validated
|
||||
// and only the AnteHandler is executed. State is persisted to the BaseApp's
|
||||
// internal CheckTx state if the AnteHandler passes. Otherwise, the ResponseCheckTx
|
||||
// and only the wired middlewares are executed. State is persisted to the BaseApp's
|
||||
// internal CheckTx state if the middlewares' CheckTx pass. Otherwise, the ResponseCheckTx
|
||||
// will contain releveant error information. Regardless of tx execution outcome,
|
||||
// the ResponseCheckTx will contain relevant gas execution context.
|
||||
func (app *BaseApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx {
|
||||
|
||||
@ -18,8 +18,7 @@ type customTxHandler struct {
|
||||
|
||||
var _ tx.Handler = customTxHandler{}
|
||||
|
||||
// CustomTxMiddleware is being used in tests for testing
|
||||
// custom pre-`runMsgs` logic (also called antehandlers before).
|
||||
// CustomTxMiddleware is being used in tests for testing custom pre-`runMsgs` logic.
|
||||
func CustomTxHandlerMiddleware(handler handlerFun) tx.Middleware {
|
||||
return func(txHandler tx.Handler) tx.Handler {
|
||||
return customTxHandler{
|
||||
|
||||
@ -220,7 +220,7 @@ While the app developer can define and compose the middlewares of their choice,
|
||||
| Middleware | Description |
|
||||
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| RunMsgsTxHandler | This is the base `tx.Handler`. It replaces the old baseapp's `runMsgs`, and executes a transaction's `Msg`s. |
|
||||
| TxDecoderMiddleware | This middleware takes in transaction raw bytes, and decodes them into a `sdk.Tx`. It replaces the `baseapp.txDecoder` field, so that BaseApp stays as thin as possible. Since most middlewares read the contents of the `sdk.Tx`, the TxDecoderMiddleware should be run first in the middelware stack. |
|
||||
| TxDecoderMiddleware | This middleware takes in transaction raw bytes, and decodes them into a `sdk.Tx`. It replaces the `baseapp.txDecoder` field, so that BaseApp stays as thin as possible. Since most middlewares read the contents of the `sdk.Tx`, the TxDecoderMiddleware should be run first in the middleware stack. |
|
||||
| {Antehandlers} | Each antehandler is converted to its own middleware. These middlewares perform signature verification, fee deductions and other validations on the incoming transaction. |
|
||||
| IndexEventsTxMiddleware | This is a simple middleware that chooses which events to index in Tendermint. Replaces `baseapp.indexEvents` (which unfortunately still exists in baseapp too, because it's used to index Begin/EndBlock events) |
|
||||
| RecoveryTxMiddleware | This index recovers from panics. It replaces baseapp.runTx's panic recovery described in [ADR-022](./adr-022-custom-panic-handling.md). |
|
||||
|
||||
@ -131,16 +131,16 @@ For user interactions, `PubKey` is formatted using Protobufs JSON ([ProtoMarshal
|
||||
|
||||
A `Keyring` is an object that stores and manages accounts. In the Cosmos SDK, a `Keyring` implementation follows the `Keyring` interface:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keyring/keyring.go#L51-L89
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/crypto/keyring/keyring.go#L54-L101
|
||||
|
||||
The default implementation of `Keyring` comes from the third-party [`99designs/keyring`](https://github.com/99designs/keyring) library.
|
||||
|
||||
A few notes on the `Keyring` methods:
|
||||
|
||||
* `Sign(uid string, payload []byte) ([]byte, sdkcrypto.PubKey, error)` strictly deals with the signature of the `payload` bytes. You must prepare and encode the transaction into a canonical `[]byte` form. Because protobuf is not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](../architecture/adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the Cosmos SDK by default, it is deferred to the [`anteHandler`](../core/baseapp.md#antehandler).
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/proto/cosmos/tx/v1beta1/tx.proto#L47-L64
|
||||
* `Sign(uid string, msg []byte) ([]byte, types.PubKey, error)` strictly deals with the signature of the `msg` bytes. You must prepare and encode the transaction into a canonical `[]byte` form. Because protobuf is not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](../architecture/adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the Cosmos SDK by default, it is deferred to the [`SigVerificationMiddleware middleware`](../core/baseapp.md#middleware).
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/proto/cosmos/tx/v1beta1/tx.proto#L49-L64
|
||||
|
||||
* `NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error)` creates a new account based on the [`bip44 path`](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) and persists it on disk. The `PrivKey` is **never stored unencrypted**, instead it is [encrypted with a passphrase](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/armor.go) before being persisted. In the context of this method, the key type and sequence number refer to the segment of the BIP44 derivation path (for example, `0`, `1`, `2`, ...) that is used to derive a private and a public key from the mnemonic. Using the same mnemonic and derivation path, the same `PrivKey`, `PubKey` and `Address` is generated. The following keys are supported by the keyring:
|
||||
* `NewAccount(uid, mnemonic, bip39Passphrase, hdPath string, algo SignatureAlgo) (*Record, error)` creates a new account based on the [`bip44 path`](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) and persists it on disk. The `PrivKey` is **never stored unencrypted**, instead it is [encrypted with a passphrase](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/crypto/armor.go) before being persisted. In the context of this method, the key type and sequence number refer to the segment of the BIP44 derivation path (for example, `0`, `1`, `2`, ...) that is used to derive a private and a public key from the mnemonic. Using the same mnemonic and derivation path, the same `PrivKey`, `PubKey` and `Address` is generated. The following keys are supported by the keyring:
|
||||
|
||||
* `secp256k1`
|
||||
* `ed25519`
|
||||
|
||||
@ -53,13 +53,13 @@ The first thing defined in `app.go` is the `type` of the application. It is gene
|
||||
|
||||
See an example of application type definition from `simapp`, the Cosmos SDK's own app used for demo and testing purposes:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/app.go#L145-L187
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/simapp/app.go#L151-L195
|
||||
|
||||
### Constructor Function
|
||||
|
||||
This function constructs a new application of the type defined in the section above. It must fulfill the `AppCreator` signature in order to be used in the [`start` command](../core/node.md#start-command) of the application's daemon command.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/types/app.go#L48-L50
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/server/types/app.go#L57-L59
|
||||
|
||||
Here are the main actions performed by this function:
|
||||
|
||||
@ -73,7 +73,7 @@ Here are the main actions performed by this function:
|
||||
* Set the remainder of application's parameters:
|
||||
* [`InitChainer`](#initchainer): used to initialize the application when it is first started.
|
||||
* [`BeginBlocker`, `EndBlocker`](#beginblocker-and-endlbocker): called at the beginning and the end of every block).
|
||||
* [`anteHandler`](../core/baseapp.md#antehandler): used to handle fees and signature verification.
|
||||
* [`TxHandler`](../core/baseapp.md#middleware): to setup middlewares, f.e. used to handle fees and signature verification.
|
||||
* Mount the stores.
|
||||
* Return the application.
|
||||
|
||||
@ -81,7 +81,7 @@ Note that this function only creates an instance of the app, while the actual st
|
||||
|
||||
See an example of application constructor from `simapp`:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/app.go#L198-L441
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/simapp/app.go#L207-L456
|
||||
|
||||
### InitChainer
|
||||
|
||||
@ -145,8 +145,8 @@ Note that `sdk.Msg`s are bundled in [transactions](../core/transactions.md), and
|
||||
|
||||
When a valid block of transactions is received by the full-node, Tendermint relays each one to the application via [`DeliverTx`](https://docs.tendermint.com/master/spec/abci/apps.html#delivertx). Then, the application handles the transaction:
|
||||
|
||||
1. Upon receiving the transaction, the application first unmarshalls it from `[]bytes`.
|
||||
2. Then, it verifies a few things about the transaction like [fee payment and signatures](#gas-fees.md#antehandler) before extracting the `Msg`(s) contained in the transaction.
|
||||
1. Upon receiving the transaction, the application first unmarshalls it from `[]byte`.
|
||||
2. Then, it verifies a few things about the transaction like [fee payment and signatures](./gas-fees.md#middleware) before extracting the `Msg`(s) contained in the transaction.
|
||||
3. `sdk.Msg`s are encoded using Protobuf [`Any`s](#register-codec). By analyzing each `Any`'s `type_url`, baseapp's `msgServiceRouter` routes the `sdk.Msg` to the corresponding module's `Msg` service.
|
||||
4. If the message is successfully processed, the state is updated.
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ This document describes the default strategies to handle gas and fees within a C
|
||||
In the Cosmos SDK, `gas` is a special unit that is used to track the consumption of resources during execution. `gas` is typically consumed whenever read and writes are made to the store, but it can also be consumed if expensive computation needs to be done. It serves two main purposes:
|
||||
|
||||
* Make sure blocks are not consuming too many resources and will be finalized. This is implemented by default in the Cosmos SDK via the [block gas meter](#block-gas-meter).
|
||||
* Prevent spam and abuse from end-user. To this end, `gas` consumed during [`message`](../building-modules/messages-and-queries.md#messages) execution is typically priced, resulting in a `fee` (`fees = gas * gas-prices`). `fees` generally have to be paid by the sender of the `message`. Note that the Cosmos SDK does not enforce `gas` pricing by default, as there may be other ways to prevent spam (e.g. bandwidth schemes). Still, most applications will implement `fee` mechanisms to prevent spam. This is done via the [`AnteHandler`](#antehandler).
|
||||
* Prevent spam and abuse from end-user. To this end, `gas` consumed during [`message`](../building-modules/messages-and-queries.md#messages) execution is typically priced, resulting in a `fee` (`fees = gas * gas-prices`). `fees` generally have to be paid by the sender of the `message`. Note that the Cosmos SDK does not enforce `gas` pricing by default, as there may be other ways to prevent spam (e.g. bandwidth schemes). Still, most applications will implement `fee` mechanisms to prevent spam. This is done via the [`GasTxMiddleware` middleware](#middleware).
|
||||
|
||||
## Gas Meter
|
||||
|
||||
@ -42,7 +42,7 @@ By default, the Cosmos SDK makes use of two different gas meters, the [main gas
|
||||
|
||||
### Main Gas Meter
|
||||
|
||||
`ctx.GasMeter()` is the main gas meter of the application. The main gas meter is initialized in `BeginBlock` via `setDeliverState`, and then tracks gas consumption during execution sequences that lead to state-transitions, i.e. those originally triggered by [`BeginBlock`](../core/baseapp.md#beginblock), [`DeliverTx`](../core/baseapp.md#delivertx) and [`EndBlock`](../core/baseapp.md#endblock). At the beginning of each `DeliverTx`, the main gas meter **must be set to 0** in the [`AnteHandler`](#antehandler), so that it can track gas consumption per-transaction.
|
||||
`ctx.GasMeter()` is the main gas meter of the application. The main gas meter is initialized in `BeginBlock` via `setDeliverState`, and then tracks gas consumption during execution sequences that lead to state-transitions, i.e. those originally triggered by [`BeginBlock`](../core/baseapp.md#beginblock), [`DeliverTx`](../core/baseapp.md#delivertx) and [`EndBlock`](../core/baseapp.md#endblock). At the beginning of each `DeliverTx`, the main gas meter **must be set to 0** in the [`GasTxMiddleware` middleware](#middleware), so that it can track gas consumption per-transaction.
|
||||
|
||||
Gas consumption can be done manually, generally by the module developer in the [`BeginBlocker`, `EndBlocker`](../building-modules/beginblock-endblock.md) or [`Msg` service](../building-modules/msg-services.md), but most of the time it is done automatically whenever there is a read or write to the store. This automatic gas consumption logic is implemented in a special store called [`GasKv`](../core/store.md#gaskv-store).
|
||||
|
||||
@ -61,28 +61,22 @@ ctx.BlockGasMeter().ConsumeGas(
|
||||
)
|
||||
```
|
||||
|
||||
## AnteHandler
|
||||
## Middleware
|
||||
|
||||
The `AnteHandler` is run for every transaction during `CheckTx` and `DeliverTx`, before a Protobuf `Msg` service method for each `sdk.Msg` in the transaction. `AnteHandler`s have the following signature:
|
||||
The `GasTxMiddleware` is run for every transaction during `CheckTx` and `DeliverTx`, before a Protobuf `Msg` service method for each `sdk.Msg` in the transaction.
|
||||
|
||||
```go
|
||||
// AnteHandler authenticates transactions, before their internal messages are handled.
|
||||
// If newCtx.IsZero(), ctx is used instead.
|
||||
type AnteHandler func(ctx Context, tx Tx, simulate bool) (newCtx Context, result Result, abort bool)
|
||||
```
|
||||
The `GasTxMiddleware` is not implemented in the core Cosmos SDK but in a module. That said, most applications today use the default implementation defined in the [`auth` module](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth/middleware). Here is what the `middleware` is intended to do in a normal Cosmos SDK application:
|
||||
|
||||
The `anteHandler` is not implemented in the core Cosmos SDK but in a module. This gives the possibility to developers to choose which version of `AnteHandler` fits their application's needs. That said, most applications today use the default implementation defined in the [`auth` module](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth). Here is what the `anteHandler` is intended to do in a normal Cosmos SDK application:
|
||||
|
||||
* Verify that the transaction are of the correct type. Transaction types are defined in the module that implements the `anteHandler`, and they follow the transaction interface:
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/tx_msg.go#L49-L57
|
||||
* Verify that the transaction are of the correct type. Transaction types are defined in the module that implements the `middleware`, and they follow the transaction interface:
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/types/tx_msg.go#L38-L46
|
||||
This enables developers to play with various types for the transaction of their application. In the default `auth` module, the default transaction type is `Tx`:
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/proto/cosmos/tx/v1beta1/tx.proto#L12-L25
|
||||
* Verify signatures for each [`message`](../building-modules/messages-and-queries.md#messages) contained in the transaction. Each `message` should be signed by one or multiple sender(s), and these signatures must be verified in the `anteHandler`.
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/proto/cosmos/tx/v1beta1/tx.proto#L13-L26
|
||||
* Verify signatures for each [`message`](../building-modules/messages-and-queries.md#messages) contained in the transaction. Each `message` should be signed by one or multiple sender(s), and these signatures must be verified by a `middleware`.
|
||||
* During `CheckTx`, verify that the gas prices provided with the transaction is greater than the local `min-gas-prices` (as a reminder, gas-prices can be deducted from the following equation: `fees = gas * gas-prices`). `min-gas-prices` is a parameter local to each full-node and used during `CheckTx` to discard transactions that do not provide a minimum amount of fees. This ensure that the mempool cannot be spammed with garbage transactions.
|
||||
* Verify that the sender of the transaction has enough funds to cover for the `fees`. When the end-user generates a transaction, they must indicate 2 of the 3 following parameters (the third one being implicit): `fees`, `gas` and `gas-prices`. This signals how much they are willing to pay for nodes to execute their transaction. The provided `gas` value is stored in a parameter called `GasWanted` for later use.
|
||||
* Set `newCtx.GasMeter` to 0, with a limit of `GasWanted`. **This step is extremely important**, as it not only makes sure the transaction cannot consume infinite gas, but also that `ctx.GasMeter` is reset in-between each `DeliverTx` (`ctx` is set to `newCtx` after `anteHandler` is run, and the `anteHandler` is run each time `DeliverTx` is called).
|
||||
* Set `newCtx.GasMeter` to 0, with a limit of `GasWanted`. **This step is extremely important**, as it not only makes sure the transaction cannot consume infinite gas, but also that `ctx.GasMeter` is reset in-between each `DeliverTx` (`ctx.GasMeter` is set by the middleware each time `DeliverTx` is called).
|
||||
|
||||
As explained above, the `anteHandler` returns a maximum limit of `gas` the transaction can consume during execution called `GasWanted`. The actual amount consumed in the end is denominated `GasUsed`, and we must therefore have `GasUsed =< GasWanted`. Both `GasWanted` and `GasUsed` are relayed to the underlying consensus engine when [`DeliverTx`](../core/baseapp.md#delivertx) returns.
|
||||
As explained above, the middleware returns a maximum limit of `gas` the transaction can consume during execution called `GasWanted`. The actual amount consumed in the end is denominated `GasUsed`, and we must therefore have `GasUsed =< GasWanted`. Both `GasWanted` and `GasUsed` are relayed to the underlying consensus engine when [`DeliverTx`](../core/baseapp.md#delivertx) returns.
|
||||
|
||||
## Next {hide}
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ are not empty, enforcing nonnegative numbers, and other logic specified in the d
|
||||
**_Stateful_** checks validate transactions and messages based on a committed state. Examples
|
||||
include checking that the relevant values exist and are able to be transacted with, the address
|
||||
has sufficient funds, and the sender is authorized or has the correct ownership to transact.
|
||||
At any given moment, full-nodes typically have [multiple versions](../core/baseapp.md#volatile-states)
|
||||
At any given moment, full-nodes typically have [multiple versions](../core/baseapp.md#state-updates)
|
||||
of the application's internal state for different purposes. For example, nodes will execute state
|
||||
changes while in the process of verifying transactions, but still need a copy of the last committed
|
||||
state in order to answer queries - they should not respond using state with uncommitted changes.
|
||||
@ -79,7 +79,7 @@ through several steps, beginning with decoding `Tx`.
|
||||
|
||||
### Decoding
|
||||
|
||||
When `Tx` is received by the application from the underlying consensus engine (e.g. Tendermint), it is still in its [encoded](../core/encoding.md) `[]byte` form and needs to be unmarshaled in order to be processed. Then, the [`runTx`](../core/baseapp.md#runtx-and-runmsgs) function is called to run in `runTxModeCheck` mode, meaning the function will run all checks but exit before executing messages and writing state changes.
|
||||
When `Tx` is received by the application from the underlying consensus engine (e.g. Tendermint), it is still in its [encoded](../core/encoding.md) `[]byte` form and needs to be unmarshaled in order to be processed. Then, the transaction is passed to the middlewares defined in `tx.Handler`. The middlewares will performe additional checks defined in their own `CheckTx`, meaning the they will run all checks but exit before executing messages and writing state changes.
|
||||
|
||||
### ValidateBasic
|
||||
|
||||
@ -96,13 +96,13 @@ Example, if the message is to send coins from one address to another, `ValidateB
|
||||
|
||||
See also [Msg Service Validation](../building-modules/msg-services.md#Validation).
|
||||
|
||||
### AnteHandler
|
||||
### Middlewares
|
||||
|
||||
After the ValidateBasic checks, the `AnteHandler`s are run. Technically, they are optional, but in practice, they are very often present to perform signature verification, gas calculation, fee deduction and other core operations related to blockchain transactions.
|
||||
Middlewares implements the `TxHandler` interface and are defined by `tx.Handler` in `BaseApp`. This architecture allows to run the middlewares logic in the `CheckTx` and `DeliverTx` phases. Technically, they are optional, but in practice, they are very often present to perform signature verification, gas calculation, fee deduction and other core operations related to blockchain transactions.
|
||||
|
||||
A copy of the cached context is provided to the `AnteHandler`, which performs limited checks specified for the transaction type. Using a copy allows the AnteHandler to do stateful checks for `Tx` without modifying the last committed state, and revert back to the original if the execution fails.
|
||||
A copy of the cached context is provided to the middleware, which performs limited checks specified for the transaction type. Using a copy allows the Middleware to do stateful checks for `Tx` without modifying the last committed state, and revert back to the original if the execution fails.
|
||||
|
||||
For example, the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth/spec) module `AnteHandler` checks and increments sequence numbers, checks signatures and account numbers, and deducts fees from the first signer of the transaction - all state changes are made using the `checkState`.
|
||||
For example, the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth/spec) middlewares can check and increment sequence numbers, check signatures and account numbers, and deduct fees from the first signer of the transaction - all state changes are made using the `checkState`.
|
||||
|
||||
### Gas
|
||||
|
||||
@ -201,19 +201,19 @@ Instead of using their `checkState`, full-nodes use `deliverState`:
|
||||
* **Decoding:** Since `DeliverTx` is an ABCI call, `Tx` is received in the encoded `[]byte` form.
|
||||
Nodes first unmarshal the transaction, using the [`TxConfig`](./app-anatomy#register-codec) defined in the app, then call `runTx` in `runTxModeDeliver`, which is very similar to `CheckTx` but also executes and writes state changes.
|
||||
|
||||
* **Checks:** Full-nodes call `validateBasicMsgs` and the `AnteHandler` again. This second check
|
||||
* **Checks:** Full-nodes call `validateBasicMsgs` and the `DeliverTx` from the middleware again. This second check
|
||||
happens because they may not have seen the same transactions during the addition to Mempool stage\
|
||||
and a malicious proposer may have included invalid ones. One difference here is that the
|
||||
`AnteHandler` will not compare `gas-prices` to the node's `min-gas-prices` since that value is local
|
||||
middleware will not compare `gas-prices` to the node's `min-gas-prices` since that value is local
|
||||
to each node - differing values across nodes would yield nondeterministic results.
|
||||
|
||||
* **`MsgServiceRouter`:** While `CheckTx` would have exited, `DeliverTx` continues to run
|
||||
[`runMsgs`](../core/baseapp.md#runtx-and-runmsgs) to fully execute each `Msg` within the transaction.
|
||||
* **`RunMsgsTxHandler`:** While `CheckTx` would have exited, `DeliverTx` continues to run
|
||||
[`RunMsgsTxHandler`](../core/baseapp.md#middlewares) to fully execute each `Msg` within the transaction.
|
||||
Since the transaction may have messages from different modules, `BaseApp` needs to know which module
|
||||
to find the appropriate handler. This is achieved using `BaseApp`'s `MsgServiceRouter` so that it can be processed by the module's Protobuf [`Msg` service](../building-modules/msg-services.md).
|
||||
to find the appropriate handler. This is achieved using `RunMsgsTxHandler`'s `MsgServiceRouter` so that it can be processed by the module's Protobuf [`Msg` service](../building-modules/msg-services.md).
|
||||
For `LegacyMsg` routing, the `Route` function is called via the [module manager](../building-modules/module-manager.md) to retrieve the route name and find the legacy [`Handler`](../building-modules/msg-services.md#handler-type) within the module.
|
||||
|
||||
* **`Msg` service:** a Protobuf `Msg` service, a step up from `AnteHandler`, is responsible for executing each
|
||||
* **`Msg` service:** a Protobuf `Msg` service is responsible for executing each
|
||||
message in the `Tx` and causes state transitions to persist in `deliverTxState`.
|
||||
|
||||
* **Gas:** While a `Tx` is being delivered, a `GasMeter` is used to keep track of how much
|
||||
|
||||
@ -23,11 +23,11 @@ Protobuf generates a `MsgServer` interface based on a definition of `Msg` servic
|
||||
|
||||
When possible, the existing module's [`Keeper`](keeper.md) should implement `MsgServer`, otherwise a `msgServer` struct that embeds the `Keeper` can be created, typically in `./keeper/msg_server.go`:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc1/x/bank/keeper/msg_server.go#L14-L16
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/x/bank/keeper/msg_server.go#L14:L16
|
||||
|
||||
`msgServer` methods can retrieve the `sdk.Context` from the `context.Context` parameter method using the `sdk.UnwrapSDKContext`:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc1/x/bank/keeper/msg_server.go#L27-L28
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/x/bank/keeper/msg_server.go#L27-L28
|
||||
|
||||
`sdk.Msg` processing usually follows these 3 steps:
|
||||
|
||||
|
||||
@ -11,15 +11,15 @@ This repository contains reference documentation on the core concepts of the Cos
|
||||
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. [gRPC, REST and Tendermint Endpoints](./grpc_rest.md)
|
||||
8. [Command-Line Interface](./cli.md)
|
||||
9. [Events](./events.md)
|
||||
10. [Telemetry](./telemetry.md)
|
||||
11. [Object-Capabilities](./ocap.md)
|
||||
12. [RunTx recovery middleware](./runtx_middleware.md)
|
||||
4. [CheckTx and DeliverTx middlewares](./middleware.md)
|
||||
5. [Node Client](./node.md)
|
||||
6. [Store](./store.md)
|
||||
7. [Encoding](./encoding.md)
|
||||
8. [gRPC, REST and Tendermint Endpoints](./grpc_rest.md)
|
||||
9. [Command-Line Interface](./cli.md)
|
||||
10. [Events](./events.md)
|
||||
11. [Telemetry](./telemetry.md)
|
||||
12. [Object-Capabilities](./ocap.md)
|
||||
13. [Simulation](./simulation.md)
|
||||
14. [Protobuf documentation](./proto-docs.md)
|
||||
15. [In-Place Store Migrations](./upgrade.md)
|
||||
|
||||
@ -15,9 +15,9 @@ This document describes `BaseApp`, the abstraction that implements the core func
|
||||
|
||||
`BaseApp` is a base type that implements the core of a Cosmos SDK application, namely:
|
||||
|
||||
* The [Application Blockchain Interface](#abci), for the state-machine to communicate with the underlying consensus engine (e.g. Tendermint).
|
||||
* The [Application Blockchain Interface](#main-abci-messages), for the state-machine to communicate with the underlying consensus engine (e.g. Tendermint).
|
||||
* [Service Routers](#service-routers), to route messages and queries to the appropriate module.
|
||||
* Different [states](#states), as the state-machine can have different volatile states updated based on the ABCI message received.
|
||||
* Different [states](#state-updates), as the state-machine can have different volatile states updated based on the ABCI message received.
|
||||
|
||||
The goal of `BaseApp` is to provide the fundamental layer of a Cosmos SDK application
|
||||
that developers can easily extend to build their own custom application. Usually,
|
||||
@ -45,7 +45,7 @@ management logic.
|
||||
|
||||
The `BaseApp` type holds many important parameters for any Cosmos SDK based application.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/baseapp/baseapp.go#L46-L131
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/baseapp/baseapp.go#L44-L131
|
||||
|
||||
Let us go through the most important components.
|
||||
|
||||
@ -60,25 +60,21 @@ First, the important parameters that are initialized during the bootstrapping of
|
||||
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.
|
||||
* Database: The `db` is used by the `CommitMultiStore` to handle data persistence.
|
||||
* [`Msg` Service Router](#msg-service-router): The `msgServiceRouter` facilitates the routing of `sdk.Msg` requests to the appropriate
|
||||
module `Msg` service for processing. Here a `sdk.Msg` refers to the transaction component that needs to be
|
||||
processed by a service in order to update the application state, and not to ABCI message which implements
|
||||
the interface between the application and the underlying consensus engine.
|
||||
* [gRPC Query Router](#grpc-query-router): The `grpcQueryRouter` facilitates the routing of gRPC queries to the
|
||||
appropriate module for it to be processed. These queries are not ABCI messages themselves, but they
|
||||
are relayed to the relevant module's gRPC `Query` service.
|
||||
* [`TxDecoder`](https://godoc.org/github.com/cosmos/cosmos-sdk/types#TxDecoder): It is used to decode
|
||||
raw transaction bytes relayed by the underlying Tendermint engine.
|
||||
* [`ParamStore`](#paramstore): The parameter store used to get and set application 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
|
||||
* [`TxHandler`](#middlewares): This handler is used to set middlewares. Middlewares can, for instace, handle signature verification,
|
||||
fee payment, and other pre-message execution checks when a transaction is received. It's executed during
|
||||
[`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`
|
||||
ABCI messages from the underlying Tendermint engine.
|
||||
|
||||
Then, parameters used to define [volatile states](#volatile-states) (i.e. cached states):
|
||||
Then, parameters used to define [volatile states](#state-updates) (i.e. cached states):
|
||||
|
||||
* `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
|
||||
@ -92,7 +88,7 @@ Finally, a few more important parameters:
|
||||
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), mainly as a spam protection mechanism. The transaction
|
||||
`TxHandler` during [`CheckTx`](#checktx), mainly as a spam protection mechanism. The transaction
|
||||
enters the [mempool](https://docs.tendermint.com/master/tendermint-core/mempool/)
|
||||
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
|
||||
@ -142,9 +138,8 @@ To avoid unnecessary roundtrip to the main state, all reads to the branched stor
|
||||
### 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 service router
|
||||
exists for every message in the transaction. Note, when we execute the `AnteHandler`, we branch
|
||||
the already branched `checkState`. This has the side effect that if the `AnteHandler` fails,
|
||||
store, is used for any reads and writes. Here we only execute the wired middlewares `CheckTx` and verify a service router
|
||||
exists for every message in the transaction. Note, that if the a middleware's `CheckTx` fails,
|
||||
the state transitions won't be reflected in the `checkState` -- i.e. `checkState` is only updated on
|
||||
success.
|
||||
|
||||
@ -164,7 +159,7 @@ The state flow for `DeliverTx` is nearly identical to `CheckTx` except state tra
|
||||
the `deliverState` and messages in a transaction are executed. Similarly to `CheckTx`, state transitions
|
||||
occur on a doubly branched state -- `deliverState`. Successful message execution results in
|
||||
writes being committed to `deliverState`. Note, if message execution fails, state transitions from
|
||||
the AnteHandler are persisted.
|
||||
the middlewares are persisted.
|
||||
|
||||

|
||||
|
||||
@ -187,21 +182,13 @@ on-chain governance.
|
||||
|
||||
## Service Routers
|
||||
|
||||
When messages and queries are received by the application, they must be routed to the appropriate module in order to be processed. Routing is done via `BaseApp`, which holds a `msgServiceRouter` for messages, and a `grpcQueryRouter` for queries.
|
||||
|
||||
### `Msg` Service Router
|
||||
|
||||
[`sdk.Msg`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 `msgServiceRouter` which maps fully-qualified service methods (`string`, defined in each module's Protobuf `Msg` service) to the appropriate module's `MsgServer` implementation.
|
||||
|
||||
The [default `msgServiceRouter` included in `BaseApp`](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/baseapp/msg_service_router.go) is stateless. However, some applications may want to make use of more stateful routing mechanisms such as allowing governance to disable certain routes or point them to new modules for upgrade purposes. For this reason, the `sdk.Context` is also passed into each [route handler inside `msgServiceRouter`](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/baseapp/msg_service_router.go#L31-L32). For a stateless router that doesn't want to make use of this, you can just ignore the `ctx`.
|
||||
|
||||
The application's `msgServiceRouter` is initialized with all the routes using the application's [module manager](../building-modules/module-manager.md#manager) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../basics/app-anatomy.md#app-constructor).
|
||||
When messages and queries are received by the application, they must be routed to the appropriate module in order to be processed. Routing is done via `BaseApp`, with `queryRouter` for queries and `grpcQueryRouter` for gRPC queries.
|
||||
|
||||
### gRPC Query Router
|
||||
|
||||
Similar to `sdk.Msg`s, [`queries`](../building-modules/messages-and-queries.md#queries) need to be routed to the appropriate module's [`Query` service](../building-modules/query-services.md). To do so, `BaseApp` holds a `grpcQueryRouter`, which maps modules' fully-qualified service methods (`string`, defined in their Protobuf `Query` gRPC) to their `QueryServer` implementation. The `grpcQueryRouter` is called during the initial stages of query processing, which can be either by directly sending a gRPC query to the gRPC endpoint, or via the [`Query` ABCI message](#query) on the Tendermint RPC endpoint.
|
||||
[`Queries`](../building-modules/messages-and-queries.md#queries) need to be routed to the appropriate module's [`Query` service](../building-modules/query-services.md). To do so, `BaseApp` holds a `grpcQueryRouter`, which maps modules' fully-qualified service methods (`string`, defined in their Protobuf `Query` gRPC) to their `QueryServer` implementation. The `grpcQueryRouter` is called during the initial stages of query processing, which can be either by directly sending a gRPC query to the gRPC endpoint, or via the [`Query` ABCI message](#query) on the Tendermint RPC endpoint.
|
||||
|
||||
Just like the `msgServiceRouter`, the `grpcQueryRouter` is initialized with all the query routes using the application's [module manager](../building-modules/module-manager.md) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../basics/app-anatomy.md#app-constructor).
|
||||
The `grpcQueryRouter` is initialized with all the query routes using the application's [module manager](../building-modules/module-manager.md) (via the `RegisterServices` method), which itself is initialized with all the application's modules in the application's [constructor](../basics/app-anatomy.md#app-constructor).
|
||||
|
||||
## Main ABCI Messages
|
||||
|
||||
@ -236,18 +223,17 @@ to do the following checks:
|
||||
3. Perform non-module related _stateful_ checks on the [account](../basics/accounts.md). This step is mainly about checking
|
||||
that the `sdk.Msg` 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`](../basics/gas-fees.md) counting occurs here,
|
||||
as `sdk.Msg`s are not processed. Usually, the [`AnteHandler`](../basics/gas-fees.md#antehandler) will check that the `gas` provided
|
||||
as `sdk.Msg`s are not processed. Usually, the [`middleware`](../basics/gas-fees.md#middleware) 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.
|
||||
|
||||
`CheckTx` does **not** process `sdk.Msg`s - they 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`](../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
|
||||
the [main canonical state](#main-state) . For example, when a transaction goes through `CheckTx()`, the
|
||||
transaction's fees are deducted from the sender's account in `checkState`. If a second transaction is
|
||||
Steps 2. and 3. are performed by the [`middlewares`](../basics/gas-fees.md#middleware)' `CheckTx()`.
|
||||
During each step of `CheckTx()`, a special [volatile state](#state-updates) 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 the [main canonical state](#main-state) . For example, when a transaction goes through `CheckTx()`,
|
||||
the transaction's fees are deducted from the sender's account in `checkState`. If a second transaction is
|
||||
received from the same account before the first is processed, and the account has consumed all its
|
||||
funds in `checkState` during the first transaction, the second transaction will fail `CheckTx`() and
|
||||
be rejected. In any case, the sender's account will not actually pay the fees until the transaction
|
||||
@ -280,16 +266,16 @@ 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 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`.
|
||||
Before the first transaction of a given block is processed, a [volatile state](#state-updates) 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.
|
||||
1. The `GasTxMiddleware` 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 `sdk.Msg` in the transaction, route to the appropriate module's Protobuf [`Msg` service](../building-modules/msg-services.md). Additional _stateful_ checks are performed, and the branched multistore held in `deliverState`'s `context` is updated by the module's `keeper`. If the `Msg` service returns successfully, the branched multistore held in `context` is written to `deliverState` `CacheMultiStore`.
|
||||
|
||||
During the additional fifth step outlined in (2), each read/write to the store increases the value of `GasConsumed`. You can find the default cost of each operation:
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/store/types/gas.go#L164-L175
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/store/types/gas.go#L230-L241
|
||||
|
||||
At any point, if `GasConsumed > GasWanted`, the function returns with `Code != 0` and `DeliverTx` fails.
|
||||
|
||||
@ -304,45 +290,32 @@ At any point, if `GasConsumed > GasWanted`, the function returns with `Code != 0
|
||||
* `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
|
||||
## Middlewares
|
||||
|
||||
### RunTx
|
||||
Middlewares implement the `tx.Handler` interface. They are called within BaseApp `CheckTx` and `DeliverTx`, allowing to run custom logic before or after the transaction is processed. They are primaraly used to authenticate the transaction before the transaction's internal messages are processed, but also to perform additional checks on the transaction itself.
|
||||
|
||||
`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.
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/types/tx/middleware.go#L62:L68
|
||||
|
||||
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 branch of the main store, with cache functionality (for query requests), 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 `sdk.Msg`in the `Tx`, which runs preliminary _stateless_ validity checks. If any `sdk.Msg` 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 branched using the `cacheTxContext()` function.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/baseapp/baseapp.go#L623-L630
|
||||
|
||||
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 `sdk.Msg`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 branched using the `cacheTxContext()` function.
|
||||
|
||||
### AnteHandler
|
||||
|
||||
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/v0.40.0-rc3/types/handler.go#L6-L8
|
||||
|
||||
The `AnteHandler` is theoretically optional, but still a very important component of public blockchain networks. It serves 3 primary purposes:
|
||||
Middlewares are theoretically optional, but still a very important component of public blockchain networks. They have 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`](./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 that is initialized in the [application's constructor](../basics/app-anatomy.md#application-constructor). The most widely used `anteHandler` is the [`auth` module](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/x/auth/ante/ante.go).
|
||||
`BaseApp` holds a `txHandler` as parameter that is initialized in the [application's constructor](../basics/app-anatomy.md#application-constructor). The most widely used `middlewares` are the [`auth` module middlewares](https://github.com/cosmos/cosmos-sdk/blob/main/x/auth/middleware).
|
||||
|
||||
Click [here](../basics/gas-fees.md#antehandler) for more on the `anteHandler`.
|
||||
`NewDefaultTxHandler` groups a number a `middlewares` that are commonly used:
|
||||
|
||||
### RunMsgs
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/x/auth/middleware/middleware.go#L89:L130
|
||||
|
||||
`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 `sdk.Msg`s.
|
||||
Click [here](../basics/gas-fees.md#middleware) for more on these `middlewares`.
|
||||
|
||||
First, it retrieves the `sdk.Msg`'s fully-qualified type name, by checking the `type_url` of the Protobuf `Any` representing the `sdk.Msg`. Then, using the application's [`msgServiceRouter`](#msg-service-router), it checks for the existence of `Msg` service method related to that `type_url`. At this point, if `mode == runTxModeCheck`, `RunMsgs` returns. Otherwise, if `mode == runTxModeDeliver`, the [`Msg` service](../building-modules/msg-services.md) RPC is executed, before `RunMsgs` returns.
|
||||
### RunMsgsTxHandler
|
||||
|
||||
`RunMsgsTxHandler` is a middleware that runs the `sdk.Msg`s in the transaction.
|
||||
When being called from `DeliverTx` or `SimulateTx`, it retrieves the `sdk.Msg`'s fully-qualified type name, by checking the `type_url` of the Protobuf `Any` representing the `sdk.Msg`. Then, using its [`msgServiceRouter`](#msg-service-router), it checks for the existence of `Msg` service method related to that `type_url`. At this point the [`Msg` service](../building-modules/msg-services.md) RPC is executed, before returning.
|
||||
|
||||
Note: When its `CheckTx` method is called, the `RunMsgsTxHandler` does not do anything as messages are not run during `CheckTx`.
|
||||
|
||||
## Other ABCI Messages
|
||||
|
||||
@ -351,7 +324,7 @@ First, it retrieves the `sdk.Msg`'s fully-qualified type name, by checking the `
|
||||
The [`InitChain` ABCI message](https://docs.tendermint.com/master/spec/abci/abci.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://docs.tendermint.com/master/spec/abci/apps.html#consensus-parameters) via `setConsensusParams`.
|
||||
* [`checkState` and `deliverState`](#volatile-states) via `setCheckState` and `setDeliverState`.
|
||||
* [`checkState` and `deliverState`](#state-updates) via `setCheckState` and `setDeliverState`.
|
||||
* 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` and, if defined, call the [`InitGenesis`](../building-modules/genesis.md#initgenesis) function of each of the application's modules.
|
||||
@ -360,7 +333,7 @@ Finally, the `InitChain(req abci.RequestInitChain)` method of `BaseApp` calls th
|
||||
|
||||
The [`BeginBlock` ABCI message](https://docs.tendermint.com/master/spec/abci/abci.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` function.
|
||||
* Initialize [`deliverState`](#state-updates) 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.
|
||||
|
||||
@ -72,32 +72,9 @@ goes wrong. The pattern of usage for a Context is as follows:
|
||||
needs to be done - the branch `ctx` is simply discarded. If successful, the changes made to
|
||||
the `CacheMultiStore` 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):
|
||||
For example, here is a snippet from the [`CustomTxHandlerMiddleware`](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/baseapp/custom_txhandler_test.go#L23) used in tests:
|
||||
|
||||
```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 branch and cache the context and multistore.
|
||||
2. `runMsgCtx` - the context with branched store, 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 branched multistore is written back to the original.
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/baseapp/custom_txhandler_test.go#L62:L97
|
||||
|
||||
## Next {hide}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
order: 3
|
||||
order: 4
|
||||
-->
|
||||
|
||||
# Middlewares
|
||||
@ -10,11 +10,11 @@ order: 3
|
||||
## Pre-requisite Readings
|
||||
|
||||
* [Anatomy of a Cosmos SDK Application](../basics/app-anatomy.md) {prereq}
|
||||
* [Transactons](transactions.md) {prereq}
|
||||
* [Transactions](transactions.md) {prereq}
|
||||
|
||||
## Middlewares
|
||||
|
||||
The SDK Baseapp's implementation of ABCI CheckTx, DeliverTx, and Baseapp's own Simulate methods use a middleware-based design. Middlewares can add logic to be executed before or after a transaction handler execution. Middlewares are like an `antehandler` with the added feature of being able to add post-transaction handler execution. Middlewares allow us to solve use cases like transaction Tips and refund unused gas (issue [#2150](https://github.com/cosmos/cosmos-sdk/issues/2150)).
|
||||
The SDK Baseapp's implementation of ABCI CheckTx, DeliverTx, and Baseapp's own Simulate methods use a middleware-based design. Middlewares can add logic to be executed before or after a transaction handler execution. Middlewares are like the previous notion of `antehandler` with the added feature of being able to add post-transaction handler execution. Middlewares allow us to solve use cases like transaction Tips and refund unused gas (issue [#2150](https://github.com/cosmos/cosmos-sdk/issues/2150)).
|
||||
|
||||
### Type Definition
|
||||
|
||||
@ -107,7 +107,7 @@ While BaseApp holds a reference to a `tx.Handler`, this `tx.Handler` itself is d
|
||||
|
||||
Then, the app developer can compose multiple middlewares on top of the base `tx.Handler`. Each middleware can run pre-and-post-processing logic around its next middleware, as described in the section above. Conceptually, as an example, given the middlewares `A`, `B`, and `C` and the base `tx.Handler` `H` the stack looks like:
|
||||
|
||||

|
||||

|
||||
|
||||
```text
|
||||
A.pre
|
||||
@ -143,11 +143,11 @@ While the app developer can define and compose the middlewares of their choice,
|
||||
| Middleware | Description |
|
||||
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| RunMsgsTxHandler | This is the base `tx.Handler`. It replaces the old baseapp's `runMsgs`, and executes a transaction's `Msg`s. |
|
||||
| TxDecoderMiddleware | This middleware takes in transaction raw bytes, and decodes them into a `sdk.Tx`. It replaces the `baseapp.txDecoder` field, so that BaseApp stays as thin as possible. Since most middlewares read the contents of the `sdk.Tx`, the TxDecoderMiddleware should be run first in the middelware stack. |
|
||||
| TxDecoderMiddleware | This middleware takes in transaction raw bytes, and decodes them into a `sdk.Tx`. It replaces the `baseapp.txDecoder` field, so that BaseApp stays as thin as possible. Since most middlewares read the contents of the `sdk.Tx`, the TxDecoderMiddleware should be run first in the middleware stack. |
|
||||
| {Antehandlers} | Each antehandler is converted to its own middleware. These middlewares perform signature verification, fee deductions and other validations on the incoming transaction. |
|
||||
| IndexEventsTxMiddleware | This is a simple middleware that chooses which events to index in Tendermint. Replaces `baseapp.indexEvents` (which unfortunately still exists in baseapp too, because it's used to index Begin/EndBlock events) |
|
||||
| RecoveryTxMiddleware | This index recovers from panics. It replaces baseapp.runTx's panic recovery described in [ADR-022](./adr-022-custom-panic-handling.md). |
|
||||
| GasTxMiddleware | This replaces the [`Setup`](https://github.com/cosmos/cosmos-sdk/blob/v0.43.0/x/auth/ante/setup.go) Antehandler. It sets a GasMeter on sdk.Context. Note that before, GasMeter was set on sdk.Context inside the antehandlers, and there was some mess around the fact that antehandlers had their own panic recovery system so that the GasMeter could be read by baseapp's recovery system. Now, this mess is all removed: one middleware sets GasMeter, another one handles recovery. |
|
||||
| GasTxMiddleware | This replaces the [`Setup`](https://github.com/cosmos/cosmos-sdk/blob/v0.45.3/x/auth/ante/setup.go) Antehandler. It sets a GasMeter on sdk.Context. Note that before, GasMeter was set on sdk.Context inside the antehandlers, and there was some mess around the fact that antehandlers had their own panic recovery system so that the GasMeter could be read by baseapp's recovery system. Now, this mess is all removed: one middleware sets GasMeter, another one handles recovery. |
|
||||
| TipMiddleware | This pays for transaction fees using another denom than the native fee denom of the chain. [`docs`](tips.md) |
|
||||
| SigGasConsumeMiddleware | SigGasConsumeMiddleware consumes parameter-defined amount of gas for each signature. |
|
||||
| SigVerificationMiddleware | verifies all signatures for a tx and return an error if any are invalid |
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<!--
|
||||
order: 16
|
||||
order: 14
|
||||
-->
|
||||
|
||||
# Protobuf Documentation
|
||||
|
||||
This file has been replaced by [Cosmos-SDK Buf Proto-docs](https://buf.build/cosmos/cosmos-sdk/docs/main)
|
||||
See [Cosmos-SDK Buf Proto-docs](https://buf.build/cosmos/cosmos-sdk/docs/main)
|
||||
|
||||
@ -1,73 +0,0 @@
|
||||
<!--
|
||||
order: 13
|
||||
-->
|
||||
|
||||
# RunTx recovery middleware
|
||||
|
||||
`BaseApp.runTx()` function handles Golang panics that might occur during transactions execution, for example, keeper has faced an invalid state and paniced.
|
||||
Depending on the panic type different handler is used, for instance the default one prints an error log message.
|
||||
Recovery middleware is used to add custom panic recovery for Cosmos SDK application developers.
|
||||
|
||||
More context could be found in the corresponding [ADR-022](../architecture/adr-022-custom-panic-handling.md).
|
||||
|
||||
Implementation could be found in the [recovery.go](https://github.com/cosmos/cosmos-sdk/tree/v0.46.0-alpha2/x/auth/middleware/recovery.go) file.
|
||||
|
||||
## Interface
|
||||
|
||||
```go
|
||||
type RecoveryHandtree/v0.46.0-alpha2
|
||||
```
|
||||
|
||||
`recoveryObj` is a return value for `recover()` function from the `buildin` Golang package.
|
||||
|
||||
**Contract:**
|
||||
|
||||
* RecoveryHandler returns `nil` if `recoveryObj` wasn't handled and should be passed to the next recovery middleware;
|
||||
* RecoveryHandler returns a non-nil `error` if `recoveryObj` was handled;
|
||||
|
||||
## Custom RecoveryHandler register
|
||||
|
||||
`BaseApp.AddRunTxRecoveryHandler(handlers ...RecoveryHandler)`
|
||||
|
||||
BaseApp method adds recovery middleware to the default recovery chain.
|
||||
|
||||
## Example
|
||||
|
||||
Lets assume we want to emit the "Consensus failure" chain state if some particular error occurred.
|
||||
|
||||
We have a module keeper that panics:
|
||||
|
||||
```go
|
||||
func (k FooKeeper) Do(obj interface{}) {
|
||||
if obj == nil {
|
||||
// that shouldn't happen, we need to crash the app
|
||||
err := sdkErrors.Wrap(fooTypes.InternalError, "obj is nil")
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
By default that panic would be recovered and an error message will be printed to log. To override that behaviour we should register a custom RecoveryHandler:
|
||||
|
||||
```go
|
||||
// Cosmos SDK application constructor
|
||||
customHandler := func(recoveryObj interface{}) error {
|
||||
err, ok := recoveryObj.(error)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if fooTypes.InternalError.Is(err) {
|
||||
panic(fmt.Errorf("FooKeeper did panic with error: %w", err))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
baseApp := baseapp.NewBaseApp(...)
|
||||
baseApp.AddRunTxRecoveryHandler(customHandler)
|
||||
```
|
||||
|
||||
## Next {hide}
|
||||
|
||||
Learn about the [IBC](./../ibc/README.md) protocol {hide}
|
||||
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
order: 14
|
||||
order: 13
|
||||
-->
|
||||
|
||||
# Cosmos Blockchain Simulator
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
order: 15
|
||||
order: 14
|
||||
-->
|
||||
|
||||
# Transaction Tips
|
||||
@ -14,9 +14,9 @@ Transaction tips is a new solution for cross-chain transaction fees payment, whe
|
||||
|
||||
Assuming we have two chains, A and B, we define the following terms:
|
||||
|
||||
- **the tipper**: this is the initiator of the transaction, who wants to execute a `Msg` on chain A, but doesn't have any native chain A tokens, only chain B tokens. In our example above, the tipper is the Osmosis (chain B) user wanting to vote on a Cosmos Hub (chain A) proposal.
|
||||
- **the fee payer**: this is the party that will relay and broadcast the final transaction on chain A, and has chain A tokens. The tipper doesn't need to trust the feepayer.
|
||||
- **the target chain**: the chain where the `Msg` is executed, chain A in this case.
|
||||
* **the tipper**: this is the initiator of the transaction, who wants to execute a `Msg` on chain A, but doesn't have any native chain A tokens, only chain B tokens. In our example above, the tipper is the Osmosis (chain B) user wanting to vote on a Cosmos Hub (chain A) proposal.
|
||||
* **the fee payer**: this is the party that will relay and broadcast the final transaction on chain A, and has chain A tokens. The tipper doesn't need to trust the feepayer.
|
||||
* **the target chain**: the chain where the `Msg` is executed, chain A in this case.
|
||||
|
||||
## Transaction Tips Flow
|
||||
|
||||
@ -42,12 +42,12 @@ Notice that this document doesn't sign over the final chain A fees. Instead, it
|
||||
|
||||
4. From the signed `AuxSignerData` document, the fee payer constructs a transaction, using the following algorithm:
|
||||
|
||||
- use as `TxBody` the exact `AuxSignerData.SignDocDirectAux.body_bytes`, to not alter the original intent of the tipper,
|
||||
- create an `AuthInfo` with:
|
||||
- `AuthInfo.Tip` copied from `AuxSignerData.SignDocDirectAux.Tip`,
|
||||
- `AuthInfo.Fee` chosen by the fee payer, which should cover for the transaction gas, but also be small enough so that the tip/fee exchange rate is economically interesting for the fee payer,
|
||||
- `AuthInfo.SignerInfos` has two signers: the first signer is the tipper, using the public key, sequence and sign mode specified in `AuxSignerData`; and the second signer is the fee payer, using their favorite sign mode,
|
||||
- a `Signatures` array with two items: the tipper's signature from `AuxSignerData.Sig`, and the final fee payer's signature.
|
||||
* use as `TxBody` the exact `AuxSignerData.SignDocDirectAux.body_bytes`, to not alter the original intent of the tipper,
|
||||
* create an `AuthInfo` with:
|
||||
* `AuthInfo.Tip` copied from `AuxSignerData.SignDocDirectAux.Tip`,
|
||||
* `AuthInfo.Fee` chosen by the fee payer, which should cover for the transaction gas, but also be small enough so that the tip/fee exchange rate is economically interesting for the fee payer,
|
||||
* `AuthInfo.SignerInfos` has two signers: the first signer is the tipper, using the public key, sequence and sign mode specified in `AuxSignerData`; and the second signer is the fee payer, using their favorite sign mode,
|
||||
* a `Signatures` array with two items: the tipper's signature from `AuxSignerData.Sig`, and the final fee payer's signature.
|
||||
|
||||
5. Broadcast the final transaction signed by the two parties to the target chain. Once included, the Cosmos SDK will trigger a transfer of the `Tip` specified in the transaction from the tipper address to the fee payer address.
|
||||
|
||||
@ -63,8 +63,8 @@ In the future, we imagine a market where fee payers will compete to include tran
|
||||
|
||||
As we mentioned in the flow above, the tipper signs over the `SignDocDirectAux`, and the fee payer signs over the whole final transaction. As such, both parties might use different sign modes.
|
||||
|
||||
- The tipper MUST use `SIGN_MODE_DIRECT_AUX` or `SIGN_MODE_LEGACY_AMINO_JSON`. That is because the tipper needs to sign over the body, the tip, but not the other signers' information and not over the fee (which is unknown to the tipper).
|
||||
- The fee payer MUST use `SIGN_MODE_DIRECT` or `SIGN_MODE_LEGACY_AMINO_JSON`. The fee payer signs over the whole transaction.
|
||||
* The tipper MUST use `SIGN_MODE_DIRECT_AUX` or `SIGN_MODE_LEGACY_AMINO_JSON`. That is because the tipper needs to sign over the body, the tip, but not the other signers' information and not over the fee (which is unknown to the tipper).
|
||||
* The fee payer MUST use `SIGN_MODE_DIRECT` or `SIGN_MODE_LEGACY_AMINO_JSON`. The fee payer signs over the whole transaction.
|
||||
|
||||
For example, if the fee payer signs the whole transaction with `SIGN_MODE_DIRECT_AUX`, it will be rejected by the node, as that would introduce malleability issues (`SIGN_MODE_DIRECT_AUX` doesn't sign over fees).
|
||||
|
||||
|
||||
@ -20,12 +20,12 @@ When users want to interact with an application and make state changes (e.g. sen
|
||||
|
||||
Transaction objects are Cosmos SDK types that implement the `Tx` interface
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/tx_msg.go#L49-L57
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/types/tx_msg.go#L38-L46
|
||||
|
||||
It contains the following methods:
|
||||
|
||||
* **GetMsgs:** unwraps the transaction and returns a list of contained `sdk.Msg`s - one transaction may have one or multiple messages, which are defined by module developers.
|
||||
* **ValidateBasic:** 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/main/x/auth) module's `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 `sdk.Msg` [`ValidateBasic`](../basics/tx-lifecycle.md#ValidateBasic) methods, which perform basic validity checks on messages only. When [`runTx`](./baseapp.md#runtx) is checking a transaction created from the [`auth`](https://github.com/cosmos/cosmos-sdk/tree/main/x/auth/spec) module, it first runs `ValidateBasic` on each message, then runs the `auth` module AnteHandler which calls `ValidateBasic` for the transaction itself.
|
||||
* **ValidateBasic:** 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/main/x/auth) module's `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 `sdk.Msg` [`ValidateBasic`](../basics/tx-lifecycle.md#ValidateBasic) methods, which perform basic validity checks on messages only. When using [`ValidateBasicMiddleware`](https://github.com/cosmos/cosmos-sdk/blob/main/x/auth/spec/03_middlewares.md), `ValidateBasic` is called on each message, and then the middleware calls `ValidateBasic` for the transaction itself.
|
||||
|
||||
As a developer, you should rarely manipulate `Tx` directly, as `Tx` is really an intermediate type used for transaction generation. Instead, developers should prefer the `TxBuilder` interface, which you can learn more about [below](#transaction-generation).
|
||||
|
||||
|
||||
@ -84,8 +84,8 @@ Note that **Tendermint only handles transaction bytes**. It has no knowledge of
|
||||
|
||||
Here are the most important messages of the ABCI:
|
||||
|
||||
* `CheckTx`: When a transaction is received by Tendermint Core, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. A special handler called the [`AnteHandler`](../basics/gas-fees.md#antehandler) is used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://docs.tendermint.com/v0.34/tendermint-core/mempool.html#mempool) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet.
|
||||
* `DeliverTx`: When a [valid block](https://docs.tendermint.com/v0.34/spec/blockchain/blockchain.html#validation) is received by Tendermint Core, each transaction in the block is passed to the application via `DeliverTx` in order to be processed. It is during this stage that the state transitions occur. The `AnteHandler` executes again along with the actual [`Msg` service](../building-modules/msg-services.md) RPC for each message in the transaction.
|
||||
* `CheckTx`: When a transaction is received by Tendermint Core, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. The [middlewares](../basics/gas-fees.md#middleware) `CheckTx` are used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://docs.tendermint.com/v0.34/tendermint-core/mempool.html#mempool) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet.
|
||||
* `DeliverTx`: When a [valid block](https://docs.tendermint.com/v0.34/spec/blockchain/blockchain.html#validation) is received by Tendermint Core, each transaction in the block is passed to the application via `DeliverTx` in order to be processed. It is during this stage that the state transitions occur. The `middleware` executes its defined `DeliverTx`, along with the actual [`Msg` service](../building-modules/msg-services.md) RPC for each message in the transaction.
|
||||
* `BeginBlock`/`EndBlock`: These messages are executed at the beginning and the end of each block, whether the block contains transaction or not. It is useful to trigger automatic execution of logic. Proceed with caution though, as computationally expensive loops could slow down your blockchain, or even freeze it if the loop is infinite.
|
||||
|
||||
Find a more detailed view of the ABCI methods from the [Tendermint docs](https://docs.tendermint.com/v0.35/introduction/what-is-tendermint.html#abci-overview).
|
||||
|
||||
@ -129,7 +129,7 @@ MY_VALIDATOR_ADDRESS=$(simd keys show my_validator -a --keyring-backend test)
|
||||
|
||||
This command generates a new 24-word mnemonic phrase, persists it to the relevant backend, and outputs information about the keypair. If this keypair will be used to hold value-bearing tokens, be sure to write down the mnemonic phrase somewhere safe!
|
||||
|
||||
By default, the keyring generates a `secp256k1` keypair. The keyring also supports `ed25519` keys, which may be created by passing the `--algo ed25519` flag. A keyring can of course hold both types of keys simultaneously, and the Cosmos SDK's `x/auth` module (in particular its [AnteHandlers](../core/baseapp.md#antehandler)) supports natively these two public key algorithms.
|
||||
By default, the keyring generates a `secp256k1` keypair. The keyring also supports `ed25519` keys, which may be created by passing the `--algo ed25519` flag. A keyring can of course hold both types of keys simultaneously, and the Cosmos SDK's `x/auth` module (in particular its [middlewares](../core/baseapp.md#middleware)) supports natively these two public key algorithms.
|
||||
|
||||
## Next {hide}
|
||||
|
||||
|
||||
1
go.mod
1
go.mod
@ -24,6 +24,7 @@ require (
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/handlers v1.5.1
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
|
||||
|
||||
@ -41,7 +41,7 @@ message TxResponse {
|
||||
string timestamp = 12;
|
||||
// Events defines all the events emitted by processing a transaction. Note,
|
||||
// these events include those emitted by processing all the messages and those
|
||||
// emitted from the ante handler. Whereas Logs contains the events, with
|
||||
// emitted from the middleware. Whereas Logs contains the events, with
|
||||
// additional metadata, emitted only by processing the messages.
|
||||
//
|
||||
// Since: cosmos-sdk 0.42.11, 0.44.5, 0.45
|
||||
|
||||
@ -5,9 +5,11 @@ type Handler func(ctx Context, msg Msg) (*Result, error)
|
||||
|
||||
// AnteHandler authenticates transactions, before their internal messages are handled.
|
||||
// If newCtx.IsZero(), ctx is used instead.
|
||||
// DEPRECATED: use middleware instead
|
||||
type AnteHandler func(ctx Context, tx Tx, simulate bool) (newCtx Context, err error)
|
||||
|
||||
// AnteDecorator wraps the next AnteHandler to perform custom pre- and post-processing.
|
||||
// DEPRECATED: use middleware instead
|
||||
type AnteDecorator interface {
|
||||
AnteHandle(ctx Context, tx Tx, simulate bool, next AnteHandler) (newCtx Context, err error)
|
||||
}
|
||||
@ -26,6 +28,7 @@ type AnteDecorator interface {
|
||||
// transactions to be processed with an infinite gasmeter and open a DOS attack vector.
|
||||
// Use `ante.SetUpContextDecorator` or a custom Decorator with similar functionality.
|
||||
// Returns nil when no AnteDecorator are supplied.
|
||||
// DEPRECATED: use middleware instead
|
||||
func ChainAnteDecorators(chain ...AnteDecorator) AnteHandler {
|
||||
if len(chain) == 0 {
|
||||
return nil
|
||||
|
||||
@ -76,8 +76,7 @@ func gasContext(ctx sdk.Context, tx sdk.Tx, isSimulate bool) (sdk.Context, error
|
||||
// all transactions must implement GasTx
|
||||
gasTx, ok := tx.(GasTx)
|
||||
if !ok {
|
||||
// Set a gas meter with limit 0 as to prevent an infinite gas meter attack
|
||||
// during runTx.
|
||||
// Set a gas meter with limit 0 as to prevent an infinite gas meter attack execution.
|
||||
newCtx := setGasMeter(ctx, 0, isSimulate)
|
||||
return newCtx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be GasTx")
|
||||
}
|
||||
|
||||
@ -13,26 +13,26 @@ Note that the middlewares are called on both `CheckTx` and `DeliverTx`, as Tende
|
||||
|
||||
The auth module provides:
|
||||
|
||||
- one `tx.Handler`, called `RunMsgsTxHandler`, which routes each `sdk.Msg` from a transaction to the correct module `Msg` service, and runs each `sdk.Msg` to perform state transitions,
|
||||
- a set of middlewares that are recursively chained together around the base `tx.Handler` in the following order (the first middleware's `pre`-hook is run first, and `post`-hook is run last):
|
||||
* one `tx.Handler`, called `RunMsgsTxHandler`, which routes each `sdk.Msg` from a transaction to the correct module `Msg` service, and runs each `sdk.Msg` to perform state transitions,
|
||||
* a set of middlewares that are recursively chained together around the base `tx.Handler` in the following order (the first middleware's `pre`-hook is run first, and `post`-hook is run last):
|
||||
|
||||
- `NewTxDecoderMiddleware`: Decodes the transaction bytes from ABCI `CheckTx` and `DeliverTx` into the SDK transaction type. This middleware is generally called first, as most middlewares logic rely on a decoded SDK transaction.
|
||||
- `GasTxMiddleware`: Sets the `GasMeter` in the `Context`.
|
||||
- `RecoveryTxMiddleware`: Wraps the next middleware with a defer clause to recover from any downstream panics in the middleware chain to return an error with information on gas provided and gas used.
|
||||
- `RejectExtensionOptionsMiddleware`: Rejects all extension options which can optionally be included in protobuf transactions.
|
||||
- `IndexEventsTxMiddleware`: Choose which events to index in Tendermint. Make sure no events are emitted outside of this middleware.
|
||||
- `ValidateBasicMiddleware`: Calls `tx.ValidateBasic` and returns any non-nil error.
|
||||
- `TxTimeoutHeightMiddleware`: Check for a `tx` height timeout.
|
||||
- `ValidateMemoMiddleware`: Validates `tx` memo with application parameters and returns any non-nil error.
|
||||
- `ConsumeGasTxSizeMiddleware`: Consumes gas proportional to the `tx` size based on application parameters.
|
||||
- `DeductFeeMiddleware`: Deducts the `FeeAmount` from first signer of the `tx`. If the `x/feegrant` module is enabled and a fee granter is set, it deducts fees from the fee granter account.
|
||||
- `SetPubKeyMiddleware`: Sets the pubkey from a `tx`'s signers that does not already have its corresponding pubkey saved in the state machine and in the current context.
|
||||
- `ValidateSigCountMiddleware`: Validates the number of signatures in the `tx` based on app-parameters.
|
||||
- `SigGasConsumeMiddleware`: Consumes parameter-defined amount of gas for each signature. This requires pubkeys to be set in context for all signers as part of `SetPubKeyMiddleware`.
|
||||
- `SigVerificationMiddleware`: Verifies all signatures are valid. This requires pubkeys to be set in context for all signers as part of `SetPubKeyMiddleware`.
|
||||
- `IncrementSequenceMiddleware`: Increments the account sequence for each signer to prevent replay attacks.
|
||||
- `WithBranchedStore`: Creates a new MultiStore branch, discards downstream writes if the downstream returns error.
|
||||
- `ConsumeBlockGasMiddleware`: Consume block gas.
|
||||
- `TipMiddleware`: Transfer tips to the fee payer in transactions with tips.
|
||||
* `NewTxDecoderMiddleware`: Decodes the transaction bytes from ABCI `CheckTx` and `DeliverTx` into the SDK transaction type. This middleware is generally called first, as most middlewares logic rely on a decoded SDK transaction.
|
||||
* `GasTxMiddleware`: Sets the `GasMeter` in the `Context`.
|
||||
* `RecoveryTxMiddleware`: Wraps the next middleware with a defer clause to recover from any downstream panics in the middleware chain to return an error with information on gas provided and gas used.
|
||||
* `RejectExtensionOptionsMiddleware`: Rejects all extension options which can optionally be included in protobuf transactions.
|
||||
* `IndexEventsTxMiddleware`: Choose which events to index in Tendermint. Make sure no events are emitted outside of this middleware.
|
||||
* `ValidateBasicMiddleware`: Calls `tx.ValidateBasic` and returns any non-nil error.
|
||||
* `TxTimeoutHeightMiddleware`: Check for a `tx` height timeout.
|
||||
* `ValidateMemoMiddleware`: Validates `tx` memo with application parameters and returns any non-nil error.
|
||||
* `ConsumeGasTxSizeMiddleware`: Consumes gas proportional to the `tx` size based on application parameters.
|
||||
* `DeductFeeMiddleware`: Deducts the `FeeAmount` from first signer of the `tx`. If the `x/feegrant` module is enabled and a fee granter is set, it deducts fees from the fee granter account.
|
||||
* `SetPubKeyMiddleware`: Sets the pubkey from a `tx`'s signers that does not already have its corresponding pubkey saved in the state machine and in the current context.
|
||||
* `ValidateSigCountMiddleware`: Validates the number of signatures in the `tx` based on app-parameters.
|
||||
* `SigGasConsumeMiddleware`: Consumes parameter-defined amount of gas for each signature. This requires pubkeys to be set in context for all signers as part of `SetPubKeyMiddleware`.
|
||||
* `SigVerificationMiddleware`: Verifies all signatures are valid. This requires pubkeys to be set in context for all signers as part of `SetPubKeyMiddleware`.
|
||||
* `IncrementSequenceMiddleware`: Increments the account sequence for each signer to prevent replay attacks.
|
||||
* `WithBranchedStore`: Creates a new MultiStore branch, discards downstream writes if the downstream returns error.
|
||||
* `ConsumeBlockGasMiddleware`: Consume block gas.
|
||||
* `TipMiddleware`: Transfer tips to the fee payer in transactions with tips.
|
||||
|
||||
This default list of middlewares can be instantiated using the `NewDefaultTxHandler` function. If a chain wants to tweak the list of middlewares, they can create their own `NewTxHandler` function using the same template as `NewDefaultTxHandler`, and chain new middlewares in the `ComposeMiddleware` function.
|
||||
|
||||
@ -13,7 +13,7 @@ This document specifies the auth module of the Cosmos SDK.
|
||||
|
||||
The auth module is responsible for specifying the base transaction and account types
|
||||
for an application, since the SDK itself is agnostic to these particulars. It contains
|
||||
the ante handler, where all basic transaction validity checks (signatures, nonces, auxiliary fields)
|
||||
the middlewares, where all basic transaction validity checks (signatures, nonces, auxiliary fields)
|
||||
are performed, and exposes the account keeper, which allows other modules to read, write, and modify accounts.
|
||||
|
||||
This module is used in the Cosmos Hub.
|
||||
@ -24,8 +24,7 @@ This module is used in the Cosmos Hub.
|
||||
* [Gas & Fees](01_concepts.md#gas-&-fees)
|
||||
2. **[State](02_state.md)**
|
||||
* [Accounts](02_state.md#accounts)
|
||||
3. **[AnteHandlers](03_antehandlers.md)**
|
||||
* [Handlers](03_antehandlers.md#handlers)
|
||||
3. **[Middlewares](03_middlewares.md)**
|
||||
4. **[Keepers](04_keepers.md)**
|
||||
* [Account Keeper](04_keepers.md#account-keeper)
|
||||
5. **[Vesting](05_vesting.md)**
|
||||
|
||||
@ -80,7 +80,7 @@ Example cmd:
|
||||
|
||||
## Granted Fee Deductions
|
||||
|
||||
Fees are deducted from grants in the `x/auth` ante handler. To learn more about how ante handlers work, read the [Auth Module AnteHandlers Guide](../../auth/spec/03_antehandlers.md).
|
||||
Fees are deducted from grants in the `x/auth` middleware. To learn more about how middlewares work, read the [Auth Module Middlewares Guide](../../auth/spec/03_middlewares.md).
|
||||
|
||||
## Gas
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ func (msg MsgUnjail) GetSignBytes() []byte {
|
||||
return sdk.MustSortJSON(bz)
|
||||
}
|
||||
|
||||
// ValidateBasic validity check for the AnteHandler
|
||||
// ValidateBasic does a sanity check on the provided message
|
||||
func (msg MsgUnjail) ValidateBasic() error {
|
||||
if _, err := sdk.ValAddressFromBech32(msg.ValidatorAddr); err != nil {
|
||||
return sdkerrors.ErrInvalidAddress.Wrapf("validator input address: %s", err)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user