github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/docs/rfc/rfc-015-abci++-tx-mutation.md (about) 1 # RFC 015: ABCI++ TX Mutation 2 3 ## Changelog 4 5 - 23-Feb-2022: Initial draft (@williambanfield). 6 - 28-Feb-2022: Revised draft (@williambanfield). 7 8 ## Abstract 9 10 A previous version of the ABCI++ specification detailed a mechanism for proposers to replace transactions 11 in the proposed block. This scheme required the proposer to construct new transactions 12 and mark these new transactions as replacing other removed transactions. The specification 13 was ambiguous as to how the replacement may be communicated to peer nodes. 14 This RFC discusses issues with this mechanism and possible solutions. 15 16 ## Background 17 18 ### What is the proposed change? 19 20 A previous version of the ABCI++ specification proposed mechanisms for adding, removing, and replacing 21 transactions in a proposed block. To replace a transaction, the application running 22 `ProcessProposal` could mark a transaction as replaced by other application-supplied 23 transactions by returning a new transaction marked with the `ADDED` flag setting 24 the `new_hashes` field of the removed transaction to contain the list of transaction hashes 25 that replace it. In that previous specification for ABCI++, the full use of the 26 `new_hashes` field is left somewhat ambiguous. At present, these hashes are not 27 gossiped and are not eventually included in the block to signal replacement to 28 other nodes. The specification did indicate that the transactions specified in 29 the `new_hashes` field will be removed from the mempool but it's not clear how 30 peer nodes will learn about them. 31 32 ### What systems would be affected by adding transaction replacement? 33 34 The 'transaction' is a central building block of a Tendermint blockchain, so adding 35 a mechanism for transaction replacement would require changes to many aspects of Tendermint. 36 37 The following is a rough list of the functionality that this mechanism would affect: 38 39 #### Transaction indexing 40 41 Tendermint's indexer stores transactions and transaction results using the hash of the executed 42 transaction [as the key][tx-result-index] and the ABCI results and transaction bytes as the value. 43 44 To allow transaction replacement, the replaced transactions would need to stored as well in the 45 indexer, likely as a mapping of original transaction to list of transaction hashes that replaced 46 the original transaction. 47 48 #### Transaction inclusion proofs 49 50 The result of a transaction query includes a Merkle proof of the existence of the 51 transaction in the block chain. This [proof is built][inclusion-proof] as a merkle tree 52 of the hashes of all of the transactions in the block where the queried transaction was executed. 53 54 To allow transaction replacement, these proofs would need to be updated to prove 55 that a replaced transaction was included by replacement in the block. 56 57 #### RPC-based transaction query parameters and results 58 59 Tendermint's RPC allows clients to retrieve information about transactions via the 60 `/tx_search` and `/tx` RPC endpoints. 61 62 RPC query results containing replaced transactions would need to be updated to include 63 information on replaced transactions, either by returning results for all of the replaced 64 transactions, or by including a response with just the hashes of the replaced transactions 65 which clients could proceed to query individually. 66 67 #### Mempool transaction removal 68 69 Additional logic would need to be added to the Tendermint mempool to clear out replaced 70 transactions after each block is executed. Tendermint currently removes executed transactions 71 from the mempool, so this would be a pretty straightforward change. 72 73 ## Discussion 74 75 ### What value may be added to Tendermint by introducing transaction replacement? 76 77 Transaction replacement would would enable applications to aggregate or disaggregate transactions. 78 79 For aggregation, a set of transactions that all related work, such as transferring 80 tokens between the same two accounts, could be replaced with a single transaction, 81 i.e. one that transfers a single sum from one account to the other. 82 Applications that make frequent use of aggregation may be able to achieve a higher throughput. 83 Aggregation would decrease the space occupied by a single client-submitted transaction in the block, allowing 84 more client-submitted transactions to be executed per block. 85 86 For disaggregation, a very complex transaction could be split into multiple smaller transactions. 87 This may be useful if an application wishes to perform more fine-grained indexing on intermediate parts 88 of a multi-part transaction. 89 90 ### Drawbacks to transaction replacement 91 92 Transaction replacement would require updating and shimming many of the places that 93 Tendermint records and exposes information about executed transactions. While 94 systems within Tendermint could be updated to account for transaction replacement, 95 such a system would leave new issues and rough edges. 96 97 #### No way of guaranteeing correct replacement 98 99 If a user issues a transaction to the network and the transaction is replaced, the 100 user has no guarantee that the replacement was correct. For example, suppose a set of users issue 101 transactions A, B, and C and they are all aggregated into a new transaction, D. 102 There is nothing guaranteeing that D was constructed correctly from the inputs. 103 The only way for users to ensure D is correct would be if D contained all of the 104 information of its constituent transactions, in which case, nothing is really gained by the replacement. 105 106 #### Replacement transactions not signed by submitter 107 108 Abstractly, Tendermint simply views transactions as a ball of bytes and therefore 109 should be fine with replacing one for another. However, many applications require 110 that transactions submitted to the chain be signed by some private key to authenticate 111 and authorize the transaction. Replaced transactions could not be signed by the 112 submitter, only by the application node. Therefore, any use of transaction replacement 113 could not contain authorization from the submitter and would either need to grant 114 application-submitted transactions power to perform application logic on behalf 115 of a user without their consent. 116 117 Granting this power to application-submitted transactions would be very dangerous 118 and therefore might not be of much value to application developers. 119 Transaction replacement might only be really safe in the case of application-submitted 120 transactions or for transactions that require no authorization. For such transactions, 121 it's quite not quite clear what the utility of replacement is: the application can already 122 generate any transactions that it wants. The fact that such a transaction was a replacement 123 is not particularly relevant to participants in the chain since the application is 124 merely replacing its own transactions. 125 126 #### New vector for censorship 127 128 Depending on the implementation, transaction replacement may allow a node signal 129 to the rest of the chain that some transaction should no longer be considered for execution. 130 Honest nodes will use the replacement mechanism to signal that a transaction has been aggregated. 131 Malicious nodes will be granted a new vector for censoring transactions. 132 There is no guarantee that a replaced transactions is actually executed at all. 133 A malicious node could censor a transaction by simply listing it as replaced. 134 Honest nodes seeing the replacement would flush the transaction from their mempool 135 and not execute or propose it it in later blocks. 136 137 ### Transaction tracking implementations 138 139 This section discusses possible ways to flesh out the implementation of transaction replacement. 140 Specifically, this section proposes a few alternative ways that Tendermint blockchains could 141 track and store transaction replacements. 142 143 #### Include transaction replacements in the block 144 145 One option to track transaction replacement is to include information on the 146 transaction replacement within the block. An additional structure may be added 147 the block of the following form: 148 149 ```proto 150 message Block { 151 ... 152 repeated Replacement replacements = 5; 153 } 154 155 message Replacement { 156 bytes included_tx_key = 1; 157 repeated bytes replaced_txs_keys = 2; 158 } 159 ``` 160 161 Applications executing `PrepareProposal` would return the list of replacements and 162 Tendermint would include an encoding of these replacements in the block that is gossiped 163 and committed. 164 165 Tendermint's transaction indexing would include a new mapping for each replaced transaction 166 key to the committed transaction. 167 Transaction inclusion proofs would be updated to include these additional new transaction 168 keys in the Merkle tree and queries for transaction hashes that were replaced would return 169 information indicating that the transaction was replaced along with the hash of the 170 transaction that replaced it. 171 172 Block validation of gossiped blocks would be updated to check that each of the 173 `included_txs_key` matches the hash of some transaction in the proposed block. 174 175 Implementing the changes described in this section would allow Tendermint to gossip 176 and index transaction replacements as part of block propagation. These changes would 177 still require the application to certify that the replacements were valid. This 178 validation may be performed in one of two ways: 179 180 1. **Applications optimistically trust that the proposer performed a legitimate replacement.** 181 182 In this validation scheme, applications would not verify that the substitution 183 is valid during consensus and instead simply trust that the proposer is correct. 184 This would have the drawback of allowing a malicious proposer to remove transactions 185 it did not want executed. 186 187 2. **Applications completely validate transaction replacement.** 188 189 In this validation scheme, applications that allow replacement would check that 190 each listed replaced transaction was correctly reflected in the replacement transaction. 191 In order to perform such validation, the node would need to have the replaced transactions 192 locally. This could be accomplished one of a few ways: by querying the mempool, 193 by adding an additional p2p gossip channel for transaction replacements, or by including the replaced transactions 194 in the block. Replacement validation via mempool querying would require the node 195 to have received all of the replaced transactions in the mempool which is far from 196 guaranteed. Adding an additional gossip channel would make gossiping replaced transactions 197 a requirement for consensus to proceed, since all nodes would need to receive all replacement 198 messages before considering a block valid. Finally, including replaced transactions in 199 the block seems to obviate any benefit gained from performing a transaction replacement 200 since the replaced transaction and the original transactions would now both appear in the block. 201 202 #### Application defined transaction replacement 203 204 An additional option for allowing transaction replacement is to leave it entirely as a responsibility 205 of the application. The `PrepareProposal` ABCI++ call allows for applications to add 206 new transactions to a proposed block. Applications that wished to implement a transaction 207 replacement mechanism would be free to do so without the newly defined `new_hashes` field. 208 Applications wishing to implement transaction replacement would add the aggregated 209 transactions in the `PrepareProposal` response, and include one additional bookkeeping 210 transaction that listed all of the replacements, with a similar scheme to the `new_hashes` 211 field described in ABCI++. This new bookkeeping transaction could be used by the 212 application to determine which transactions to clear from the mempool in future calls 213 to `CheckTx`. 214 215 The meaning of any transaction in the block is completely opaque to Tendermint, 216 so applications performing this style of replacement would not be able to have the replacement 217 reflected in any most of Tendermint's transaction tracking mechanisms, such as transaction indexing 218 and the `/tx` endpoint. 219 220 #### Application defined Tx Keys 221 222 Tendermint currently uses cryptographic hashes, SHA256, as a key for each transaction. 223 As noted in the section on systems that would require changing, this key is used 224 to identify the transaction in the mempool, in the indexer, and within the RPC system. 225 226 An alternative approach to allowing `ProcessProposal` to specify a set of transaction 227 replacements would be instead to allow the application to specify an additional key or set 228 of keys for each transaction during `ProcessProposal`. This new `secondary_keys` set 229 would be included in the block and therefore gossiped during block propagation. 230 Additional RPC endpoints could be exposed to query by the application-defined keys. 231 232 Applications wishing to implement replacement would leverage this new field by providing the 233 replaced transaction hashes as the `secondary_keys` and checking their validity during 234 `ProcessProposal`. During `RecheckTx` the application would then be responsible for 235 clearing out transactions that matched the `secondary_keys`. 236 237 It is worth noting that something like this would be possible without `secondary_keys`. 238 An application wishing to implement a system like this one could define a replacement 239 transaction, as discussed in the section on application-defined transaction replacement, 240 and use a custom [ABCI event type][abci-event-type] to communicate that the replacement should 241 be indexed within Tendermint's ABCI event indexing. 242 243 ### Complexity to value-add tradeoff 244 245 It is worth remarking that adding a system like this may introduce a decent amount 246 of new complexity into Tendermint. An approach that leaves much of the replacement 247 logic to Tendermint would require altering the core transaction indexing and querying 248 data. In many of the cases listed, a system for transaction replacement is possible 249 without explicitly defining it as part of `PrepareProposal`. Since applications 250 can now add transactions during `PrepareProposal` they can and should leverage this 251 functionality to include additional bookkeeping transactions in the block. It may 252 be worth encouraging applications to discover new and interesting ways to leverage this 253 power instead of immediately solving the problem for them. 254 255 ### References 256 257 [inclusion-proof]: https://github.com/tendermint/tendermint/blob/0fcfaa4568cb700e27c954389c1fcd0b9e786332/types/tx.go#L67 258 [tx-serach-result]: https://github.com/tendermint/tendermint/blob/0fcfaa4568cb700e27c954389c1fcd0b9e786332/rpc/coretypes/responses.go#L267 259 [tx-rpc-func]: https://github.com/tendermint/tendermint/blob/0fcfaa4568cb700e27c954389c1fcd0b9e786332/internal/rpc/core/tx.go#L21 260 [tx-result-index]: https://github.com/tendermint/tendermint/blob/0fcfaa4568cb700e27c954389c1fcd0b9e786332/internal/state/indexer/tx/kv/kv.go#L90 261 [abci-event-type]: https://github.com/tendermint/tendermint/blob/0fcfaa4568cb700e27c954389c1fcd0b9e786332/abci/types/types.pb.go#L3168