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