Skip to content

Commit

Permalink
refactor: revert #11918 and #11445
Browse files Browse the repository at this point in the history
  • Loading branch information
julienrbrt committed May 18, 2022
1 parent 23baecf commit a21f6a4
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 24 deletions.
2 changes: 1 addition & 1 deletion docs/basics/accounts.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ The default implementation of `Keyring` comes from the third-party [`99designs/k

A few notes on the `Keyring` methods:

* `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).
* `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 [`anteHandler`](../core/baseapp.md#antehandler).
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-beta2/proto/cosmos/tx/v1beta1/tx.proto#L49-L64

* `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:
Expand Down
4 changes: 2 additions & 2 deletions docs/basics/app-anatomy.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
* [`TxHandler`](../core/baseapp.md#middleware): to setup middlewares, f.e. used to handle fees and signature verification.
* [`anteHandler`](../core/baseapp.md#antehandler): used to handle fees and signature verification.
* Mount the stores.
* Return the application.

Expand Down Expand Up @@ -146,7 +146,7 @@ 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 `[]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.
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.
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.

Expand Down
18 changes: 9 additions & 9 deletions docs/basics/gas-fees.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 [`GasTxMiddleware` middleware](#middleware).
* 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).

## Gas Meter

Expand All @@ -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 [`GasTxMiddleware` middleware](#middleware), 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 [`AnteHandler`](#antehandler), 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).

Expand All @@ -61,22 +61,22 @@ ctx.BlockGasMeter().ConsumeGas(
)
```

## Middleware
## AnteHandler

The `GasTxMiddleware` is run for every transaction during `CheckTx` and `DeliverTx`, before a Protobuf `Msg` service method for each `sdk.Msg` in the transaction.
The `AnteHandler` is run for every transaction during `CheckTx` and `DeliverTx`, before a Protobuf `Msg` service method for each `sdk.Msg` in the transaction.

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. 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 transactions are of the correct type. Transaction types are defined in the module that implements the `middleware`, and they follow the transaction interface:
* Verify that the transactions 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.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.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`.
* 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`.
* 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 ensures 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 crucial**, 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).
* Set `newCtx.GasMeter` to 0, with a limit of `GasWanted`. **This step is crucial**, 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).

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.
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.

## Next {hide}

Expand Down
24 changes: 12 additions & 12 deletions docs/basics/tx-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 transaction is passed to the middlewares defined in `tx.Handler`. The middlewares will perform additional checks defined in their own `CheckTx`, meaning that they 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 [`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.

### ValidateBasic

Expand All @@ -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).

### Middlewares
### AnteHandler

Middlewares implements the `TxHandler` interface and are defined by `tx.Handler` in `BaseApp`. This architecture allows running 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.
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.

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.
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.

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`.
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`.

### Gas

Expand Down Expand Up @@ -201,18 +201,18 @@ 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 `DeliverTx` from the middleware again. This second check
happens because they may not have seen the same transactions during the addition to Mempool stage\
* **Checks:** Full-nodes call `validateBasicMsgs` and `AnteHandler` 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
middleware will not compare `gas-prices` to the node's `min-gas-prices` since that value is local
`AnteHandler` 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.

* **`RunMsgsTxHandler`:** While `CheckTx` would have exited, `DeliverTx` continues to run
[`RunMsgsTxHandler`](../core/baseapp.md#middlewares) to fully execute each `Msg` within the transaction.
* **`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.
Since the transaction may have messages from different modules, `BaseApp` needs to know which module
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).
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).
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 is responsible for executing each
message in the `Tx` and causes state transitions to persist in `deliverTxState`.

Expand Down

0 comments on commit a21f6a4

Please sign in to comment.