github.com/cosmos/cosmos-sdk@v0.50.10/docs/architecture/adr-060-abci-1.0.md (about)

     1  # ADR 60: ABCI 1.0 Integration (Phase I)
     2  
     3  ## Changelog
     4  
     5  * 2022-08-10: Initial Draft (@alexanderbez, @tac0turtle)
     6  * Nov 12, 2022: Update `PrepareProposal` and `ProcessProposal` semantics per the
     7    initial implementation [PR](https://github.com/cosmos/cosmos-sdk/pull/13453) (@alexanderbez)
     8  
     9  ## Status
    10  
    11  ACCEPTED
    12  
    13  ## Abstract
    14  
    15  This ADR describes the initial adoption of [ABCI 1.0](https://github.com/tendermint/tendermint/blob/master/spec/abci%2B%2B/README.md),
    16  the next evolution of ABCI, within the Cosmos SDK. ABCI 1.0 aims to provide
    17  application developers with more flexibility and control over application and
    18  consensus semantics, e.g. in-application mempools, in-process oracles, and
    19  order-book style matching engines.
    20  
    21  ## Context
    22  
    23  Tendermint will release ABCI 1.0. Notably, at the time of this writing,
    24  Tendermint is releasing v0.37.0 which will include `PrepareProposal` and `ProcessProposal`.
    25  
    26  The `PrepareProposal` ABCI method is concerned with a block proposer requesting
    27  the application to evaluate a series of transactions to be included in the next
    28  block, defined as a slice of `TxRecord` objects. The application can either
    29  accept, reject, or completely ignore some or all of these transactions. This is
    30  an important consideration to make as the application can essentially define and
    31  control its own mempool allowing it to define sophisticated transaction priority
    32  and filtering mechanisms, by completely ignoring the `TxRecords` Tendermint
    33  sends it, favoring its own transactions. This essentially means that the Tendermint
    34  mempool acts more like a gossip data structure.
    35  
    36  The second ABCI method, `ProcessProposal`, is used to process the block proposer's
    37  proposal as defined by `PrepareProposal`. It is important to note the following
    38  with respect to `ProcessProposal`:
    39  
    40  * Execution of `ProcessProposal` must be deterministic.
    41  * There must be coherence between `PrepareProposal` and `ProcessProposal`. In
    42    other words, for any two correct processes *p* and *q*, if *q*'s Tendermint
    43  	calls `RequestProcessProposal` on *u<sub>p</sub>*, *q*'s Application returns
    44  	ACCEPT in `ResponseProcessProposal`.
    45  
    46  It is important to note that in ABCI 1.0 integration, the application
    47  is NOT responsible for locking semantics -- Tendermint will still be responsible
    48  for that. In the future, however, the application will be responsible for locking,
    49  which allows for parallel execution possibilities.
    50  
    51  ## Decision
    52  
    53  We will integrate ABCI 1.0, which will be introduced in Tendermint
    54  v0.37.0, in the next major release of the Cosmos SDK. We will integrate ABCI 1.0
    55  methods on the `BaseApp` type. We describe the implementations of the two methods
    56  individually below.
    57  
    58  Prior to describing the implementation of the two new methods, it is important to
    59  note that the existing ABCI methods, `CheckTx`, `DeliverTx`, etc, still exist and
    60  serve the same functions as they do now.
    61  
    62  ### `PrepareProposal`
    63  
    64  Prior to evaluating the decision for how to implement `PrepareProposal`, it is
    65  important to note that `CheckTx` will still be executed and will be responsible
    66  for evaluating transaction validity as it does now, with one very important
    67  *additive* distinction.
    68  
    69  When executing transactions in `CheckTx`, the application will now add valid
    70  transactions, i.e. passing the AnteHandler, to its own mempool data structure.
    71  In order to provide a flexible approach to meet the varying needs of application
    72  developers, we will define both a mempool interface and a data structure utilizing
    73  Golang generics, allowing developers to focus only on transaction
    74  ordering. Developers requiring absolute full control can implement their own
    75  custom mempool implementation.
    76  
    77  We define the general mempool interface as follows (subject to change):
    78  
    79  ```go
    80  type Mempool interface {
    81  	// Insert attempts to insert a Tx into the app-side mempool returning
    82  	// an error upon failure.
    83  	Insert(sdk.Context, sdk.Tx) error
    84  
    85  	// Select returns an Iterator over the app-side mempool. If txs are specified,
    86  	// then they shall be incorporated into the Iterator. The Iterator must
    87  	// closed by the caller.
    88  	Select(sdk.Context, [][]byte) Iterator
    89  
    90  	// CountTx returns the number of transactions currently in the mempool.
    91  	CountTx() int
    92  
    93  	// Remove attempts to remove a transaction from the mempool, returning an error
    94  	// upon failure.
    95  	Remove(sdk.Tx) error
    96  }
    97  
    98  // Iterator defines an app-side mempool iterator interface that is as minimal as
    99  // possible. The order of iteration is determined by the app-side mempool
   100  // implementation.
   101  type Iterator interface {
   102  	// Next returns the next transaction from the mempool. If there are no more
   103  	// transactions, it returns nil.
   104  	Next() Iterator
   105  
   106  	// Tx returns the transaction at the current position of the iterator.
   107  	Tx() sdk.Tx
   108  }
   109  ```
   110  
   111  We will define an implementation of `Mempool`, defined by `nonceMempool`, that
   112  will cover most basic application use-cases. Namely, it will prioritize transactions
   113  by transaction sender, allowing for multiple transactions from the same sender.
   114  
   115  The default app-side mempool implementation, `nonceMempool`, will operate on a 
   116  single skip list data structure. Specifically, transactions with the lowest nonce
   117  globally are prioritized. Transactions with the same nonce are prioritized by
   118  sender address.
   119  
   120  ```go
   121  type nonceMempool struct {
   122  	txQueue *huandu.SkipList
   123  }
   124  ```
   125  
   126  Previous discussions<sup>1</sup> have come to the agreement that Tendermint will
   127  perform a request to the application, via `RequestPrepareProposal`, with a certain
   128  amount of transactions reaped from Tendermint's local mempool. The exact amount
   129  of transactions reaped will be determined by a local operator configuration.
   130  This is referred to as the "one-shot approach" seen in discussions.
   131  
   132  When Tendermint reaps transactions from the local mempool and sends them to the
   133  application via `RequestPrepareProposal`, the application will have to evaluate
   134  the transactions. Specifically, it will need to inform Tendermint if it should
   135  reject and or include each transaction. Note, the application can even *replace*
   136  transactions entirely with other transactions.
   137  
   138  When evaluating transactions from `RequestPrepareProposal`, the application will
   139  ignore *ALL* transactions sent to it in the request and instead reap up to
   140  `RequestPrepareProposal.max_tx_bytes` from it's own mempool.
   141  
   142  Since an application can technically insert or inject transactions on `Insert`
   143  during `CheckTx` execution, it is recommended that applications ensure transaction
   144  validity when reaping transactions during `PrepareProposal`. However, what validity
   145  exactly means is entirely determined by the application.
   146  
   147  The Cosmos SDK will provide a default `PrepareProposal` implementation that simply
   148  select up to `MaxBytes` *valid* transactions.
   149  
   150  However, applications can override this default implementation with their own
   151  implementation and set that on `BaseApp` via `SetPrepareProposal`.
   152  
   153  
   154  ### `ProcessProposal`
   155  
   156  The `ProcessProposal` ABCI method is relatively straightforward. It is responsible
   157  for ensuring validity of the proposed block containing transactions that were
   158  selected from the `PrepareProposal` step. However, how an application determines
   159  validity of a proposed block depends on the application and its varying use cases.
   160  For most applications, simply calling the `AnteHandler` chain would suffice, but
   161  there could easily be other applications that need more control over the validation
   162  process of the proposed block, such as ensuring txs are in a certain order or
   163  that certain transactions are included. While this theoretically could be achieved
   164  with a custom `AnteHandler` implementation, it's not the cleanest UX or the most
   165  efficient solution.
   166  
   167  Instead, we will define an additional ABCI interface method on the existing
   168  `Application` interface, similar to the existing ABCI methods such as `BeginBlock`
   169  or `EndBlock`. This new interface method will be defined as follows:
   170  
   171  ```go
   172  ProcessProposal(sdk.Context, abci.RequestProcessProposal) error {}
   173  ```
   174  
   175  Note, we must call `ProcessProposal` with a new internal branched state on the
   176  `Context` argument as we cannot simply just use the existing `checkState` because
   177  `BaseApp` already has a modified `checkState` at this point. So when executing
   178  `ProcessProposal`, we create a similar branched state, `processProposalState`,
   179  off of `deliverState`. Note, the `processProposalState` is never committed and
   180  is completely discarded after `ProcessProposal` finishes execution.
   181  
   182  The Cosmos SDK will provide a default implementation of `ProcessProposal` in which
   183  all transactions are validated using the CheckTx flow, i.e. the AnteHandler, and
   184  will always return ACCEPT unless any transaction cannot be decoded.
   185  
   186  ### `DeliverTx`
   187  
   188  Since transactions are not truly removed from the app-side mempool during
   189  `PrepareProposal`, since `ProcessProposal` can fail or take multiple rounds and
   190  we do not want to lose transactions, we need to finally remove the transaction
   191  from the app-side mempool during `DeliverTx` since during this phase, the
   192  transactions are being included in the proposed block.
   193  
   194  Alternatively, we can keep the transactions as truly being removed during the
   195  reaping phase in `PrepareProposal` and add them back to the app-side mempool in
   196  case `ProcessProposal` fails.
   197  
   198  ## Consequences
   199  
   200  ### Backwards Compatibility
   201  
   202  ABCI 1.0 is naturally not backwards compatible with prior versions of the Cosmos SDK
   203  and Tendermint. For example, an application that requests `RequestPrepareProposal`
   204  to the same application that does not speak ABCI 1.0 will naturally fail.
   205  
   206  However, in the first phase of the integration, the existing ABCI methods as we
   207  know them today will still exist and function as they currently do.
   208  
   209  ### Positive
   210  
   211  * Applications now have full control over transaction ordering and priority.
   212  * Lays the groundwork for the full integration of ABCI 1.0, which will unlock more
   213    app-side use cases around block construction and integration with the Tendermint
   214    consensus engine.
   215  
   216  ### Negative
   217  
   218  * Requires that the "mempool", as a general data structure that collects and stores
   219    uncommitted transactions will be duplicated between both Tendermint and the
   220    Cosmos SDK.
   221  * Additional requests between Tendermint and the Cosmos SDK in the context of
   222    block execution. Albeit, the overhead should be negligible.
   223  * Not backwards compatible with previous versions of Tendermint and the Cosmos SDK.
   224  
   225  ## Further Discussions
   226  
   227  It is possible to design the app-side implementation of the `Mempool[T MempoolTx]`
   228  in many different ways using different data structures and implementations. All
   229  of which have different tradeoffs. The proposed solution keeps things simple
   230  and covers cases that would be required for most basic applications. There are
   231  tradeoffs that can be made to improve performance of reaping and inserting into
   232  the provided mempool implementation.
   233  
   234  ## References
   235  
   236  * https://github.com/tendermint/tendermint/blob/master/spec/abci%2B%2B/README.md
   237  * [1] https://github.com/tendermint/tendermint/issues/7750#issuecomment-1076806155
   238  * [2] https://github.com/tendermint/tendermint/issues/7750#issuecomment-1075717151