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