diff --git a/docs/docs/core/00-baseapp.md b/docs/docs/core/00-baseapp.md index 7713f3c9ab..4df251ac3f 100644 --- a/docs/docs/core/00-baseapp.md +++ b/docs/docs/core/00-baseapp.md @@ -130,20 +130,21 @@ Naturally, developers can add additional `options` based on their application's ## State Updates -The `BaseApp` maintains two primary volatile states and a root or main state. The main state -is the canonical state of the application and the volatile states, `checkState` and `deliverState`, +The `BaseApp` maintains four primary volatile states and a root or main state. The main state +is the canonical state of the application and the volatile states, `checkState`, `deliverState`, `prepareProposalState`, `processPreposalState`, are used to handle state transitions in-between the main state made during [`Commit`](#commit). Internally, there is only a single `CommitMultiStore` which we refer to as the main or root state. -From this root state, we derive two volatile states by using a mechanism called _store branching_ (performed by `CacheWrap` function). +From this root state, we derive four volatile states by using a mechanism called _store branching_ (performed by `CacheWrap` function). The types can be illustrated as follows: -![Types](./baseapp_state_types.png) +![Types](./baseapp_state.png) ### InitChain State Updates -During `InitChain`, the two volatile states, `checkState` and `deliverState` are set by branching -the root `CommitMultiStore`. Any subsequent reads and writes happen on branched versions of the `CommitMultiStore`. +During `InitChain`, the four volatile states, `checkState`, `prepareProposalState`, `processProposalState` +and `deliverState` are set by branching the root `CommitMultiStore`. Any subsequent reads and writes happen +on branched versions of the `CommitMultiStore`. To avoid unnecessary roundtrip to the main state, all reads to the branched store are cached. ![InitChain](./baseapp_state-initchain.png) @@ -151,7 +152,7 @@ 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 +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, the state transitions won't be reflected in the `checkState` @@ -159,6 +160,30 @@ This has the side effect that if the `AnteHandler` fails, the state transitions ![CheckTx](./baseapp_state-checktx.png) +### PrepareProposal State Updates + +During `PrepareProposal`, the `prepareProposalState` is set by branching the root `CommitMultiStore`. +The `prepareProposalState` is used for any reads and writes that occur during the `PrepareProposal` phase. +The function uses the `Select()` method of the mempool to iterate over the transactions. `runTx` is then called, +which encodes and validates each transaction and from there the `AnteHandler` is executed. +If successful, valid transactions are returned inclusive of the events, tags, and data generated +during the execution of the proposal. +The described behavior is that of the default handler, applications have the flexibility to define their own +[custom mempool handlers](https://docs.cosmos.network/main/building-apps/app-mempool#custom-mempool-handlers). + +![ProcessProposal](./baseapp_state-prepareproposal.png) + +### ProcessProposal State Updates + +During `ProcessProposal`, the `processProposalState` is set based off of the last committed state +from the root store and is used to process a signed proposal received from a validator. +In this state, `runTx` is called and the `AnteHandler` is executed and the context used in this state is built with information +from the header and the main state, including the minimum gas prices, which are also set. +Again we want to highlight that the described behavior is that of the default handler and applications have the flexibility to define their own +[custom mempool handlers](https://docs.cosmos.network/main/building-apps/app-mempool#custom-mempool-handlers). + +![ProcessProposal](./baseapp_state-processproposal.png) + ### BeginBlock State Updates During `BeginBlock`, the `deliverState` is set for use in subsequent `DeliverTx` ABCI messages. The @@ -233,8 +258,30 @@ Developers building on top of the Cosmos SDK need not implement the ABCI themsel ### Prepare Proposal +The `PrepareProposal` function is part of the new methods introduced in Application Blockchain Interface (ABCI++) in Tendermint and is an important part of the application's overall governance system. In the Cosmos SDK, it allows the application to have more fine-grained control over the transactions that are processed, and ensures that only valid transactions are committed to the blockchain. + +Here is how the `PrepareProposal` function can be implemented: + +1. Extract the `sdk.Msg`s from the transaction. +2. Perform _stateful_ checks by calling `Validate()` on each of the `sdk.Msg`'s. This is done after _stateless_ checks as _stateful_ checks are more computationally expensive. If `Validate()` fails, `PrepareProposal` returns before running further checks, which saves resources. +3. Perform any additional checks that are specific to the application, such as checking account balances, or ensuring that certain conditions are met before a transaction is proposed.hey are processed by the consensus engine, if necessary. +5. Return the updated transactions to be processed by the consensus engine + +Note that, unlike `CheckTx()`, `PrepareProposal` process `sdk.Msg`s, so it can directly update the state. However, unlike `DeliverTx()`, it does not commit the state updates. It's important to exercise caution when using `PrepareProposal` as incorrect coding could affect the overall liveness of the network. + +It's important to note that `PrepareProposal` complements the `ProcessProposal` method which is executed after this method. The combination of these two methods means that it is possible to guarantee that no invalid transactions are ever committed. Furthermore, such a setup can give rise to other interesting use cases such as Oracles, threshold decryption and more. + +`PrepareProposal` returns a response to the underlying consensus engine of type [`abci.ResponseCheckTx`](https://github.com/tendermint/tendermint/blob/v0.37.x/spec/abci/abci++_methods.md#processproposal). The response contains: + +* `Code (uint32)`: Response Code. `0` if successful. +* `Data ([]byte)`: Result bytes, if any. +* `Log (string):` The output of the application's logger. May be non-deterministic. +* `Info (string):` Additional information. May be non-deterministic. + + ### Process Proposal -The `ProcessProposal` function is part of the new methods introduced in Application Blockchain Interface (ABCI++) in Tendermint. This function is called by the BaseApp as part of the ABCI message flow, and is executed during the `BeginBlock` phase of the consensus process. The purpose of this function is to give more control to the application for block validation, allowing it to check all transactions in a proposed block before the validator sends the prevote for the block. It allows a validator to perform application-dependent work in a proposed block, enabling features such as immediate block execution, and allows the Application to reject invalid blocks. + +The `ProcessProposal` function is called by the BaseApp as part of the ABCI message flow, and is executed during the `BeginBlock` phase of the consensus process. The purpose of this function is to give more control to the application for block validation, allowing it to check all transactions in a proposed block before the validator sends the prevote for the block. It allows a validator to perform application-dependent work in a proposed block, enabling features such as immediate block execution, and allows the Application to reject invalid blocks. The `ProcessProposal` function performs several key tasks, including: @@ -253,10 +300,11 @@ However, developers must exercise greater caution when using these methods. Inco `ProcessProposal` returns a response to the underlying consensus engine of type [`abci.ResponseCheckTx`](https://github.com/tendermint/tendermint/blob/v0.37.x/spec/abci/abci++_methods.md#processproposal). The response contains: -* `Code (uint32)`: Response Code. `0` if successful. -* `Data ([]byte)`: Result bytes, if any. -* `Log (string):` The output of the application's logger. May be non-deterministic. -* `Info (string):` Additional information. May be non-deterministic. +* `Code (uint32)`: Response Code. `0` if successful. +* `Data ([]byte)`: Result bytes, if any. +* `Log (string):` The output of the application's logger. May be non-deterministic. +* `Info (string):` Additional information. May be non-deterministic. + ### CheckTx diff --git a/docs/docs/core/baseapp_state-initchain.png b/docs/docs/core/baseapp_state-initchain.png index d03e88ef2a..167b4fad9e 100644 Binary files a/docs/docs/core/baseapp_state-initchain.png and b/docs/docs/core/baseapp_state-initchain.png differ diff --git a/docs/docs/core/baseapp_state-prepareproposal.png b/docs/docs/core/baseapp_state-prepareproposal.png new file mode 100644 index 0000000000..146e804b09 Binary files /dev/null and b/docs/docs/core/baseapp_state-prepareproposal.png differ diff --git a/docs/docs/core/baseapp_state-processproposal.png b/docs/docs/core/baseapp_state-processproposal.png new file mode 100644 index 0000000000..fb6012378d Binary files /dev/null and b/docs/docs/core/baseapp_state-processproposal.png differ diff --git a/docs/docs/core/baseapp_state.png b/docs/docs/core/baseapp_state.png new file mode 100644 index 0000000000..5cf54fdb4a Binary files /dev/null and b/docs/docs/core/baseapp_state.png differ diff --git a/docs/docs/core/baseapp_state_types.png b/docs/docs/core/baseapp_state_types.png deleted file mode 100644 index a7f91a6093..0000000000 Binary files a/docs/docs/core/baseapp_state_types.png and /dev/null differ