You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
9.7 KiB

  1. # RFC 011: Remove Gas From Tendermint
  2. ## Changelog
  3. - 03-Feb-2022: Initial draft (@williambanfield).
  4. - 10-Feb-2022: Update in response to feedback (@williambanfield).
  5. - 11-Feb-2022: Add reflection on MaxGas during consensus (@williambanfield).
  6. ## Abstract
  7. In the v0.25.0 release, Tendermint added a mechanism for tracking 'Gas' in the mempool.
  8. At a high level, Gas allows applications to specify how much it will cost the network,
  9. often in compute resources, to execute a given transaction. While such a mechanism is common
  10. in blockchain applications, it is not generalizable enough to be a maintained as a part
  11. of Tendermint. This RFC explores the possibility of removing the concept of Gas from
  12. Tendermint while still allowing applications the power to control the contents of
  13. blocks to achieve similar goals.
  14. ## Background
  15. The notion of Gas was included in the original Ethereum whitepaper and exists as
  16. an important feature of the Ethereum blockchain.
  17. The [whitepaper describes Gas][eth-whitepaper-messages] as an Anti-DoS mechanism. The Ethereum Virtual Machine
  18. provides a Turing complete execution platform. Without any limitations, malicious
  19. actors could waste computation resources by directing the EVM to perform large
  20. or even infinite computations. Gas serves as a metering mechanism to prevent this.
  21. Gas appears to have been added to Tendermint multiple times, initially as part of
  22. a now defunct `/vm` package, and in its most recent iteration [as part of v0.25.0][gas-add-pr]
  23. as a mechanism to limit the transactions that will be included in the block by an additional
  24. parameter.
  25. Gas has gained adoption within the Cosmos ecosystem [as part of the Cosmos SDK][cosmos-sdk-gas].
  26. The SDK provides facilities for tracking how much 'Gas' a transaction is expected to take
  27. and a mechanism for tracking how much gas a transaction has already taken.
  28. Non-SDK applications also make use of the concept of Gas. Anoma appears to implement
  29. [a gas system][anoma-gas] to meter the transactions it executes.
  30. While the notion of gas is present in projects that make use of Tendermint, it is
  31. not a concern of Tendermint's. Tendermint's value and goal is producing blocks
  32. via a distributed consensus algorithm. Tendermint relies on the application specific
  33. code to decide how to handle the transactions Tendermint has produced (or if the
  34. application wants to consider them at all). Gas is an application concern.
  35. Our implementation of Gas is not currently enforced by consensus. Our current validation check that
  36. occurs during block propagation does not verify that the block is under the configured `MaxGas`.
  37. Ensuring that the transactions in a proposed block do not exceed `MaxGas` would require
  38. input from the application during propagation. The `ProcessProposal` method introduced
  39. as part of ABCI++ would enable such input but would further entwine Tendermint and
  40. the application. The issue of checking `MaxGas` during block propagation is important
  41. because it demonstrates that the feature as it currently exists is not implemented
  42. as fully as it perhaps should be.
  43. Our implementation of Gas is causing issues for node operators and relayers. At
  44. the moment, transactions that overflow the configured 'MaxGas' can be silently rejected
  45. from the mempool. Overflowing MaxGas is the _only_ way that a transaction can be considered
  46. invalid that is not directly a result of failing the `CheckTx`. Operators, and the application,
  47. do not know that a transaction was removed from the mempool for this reason. A stateless check
  48. of this nature is exactly what `CheckTx` exists for and there is no reason for the mempool
  49. to keep track of this data separately. A special [MempoolError][add-mempool-error] field
  50. was added in v0.35 to communicate to clients that a transaction failed after `CheckTx`.
  51. While this should alleviate the pain for operators wishing to understand if their
  52. transaction was included in the mempool, it highlights that the abstraction of
  53. what is included in the mempool is not currently well defined.
  54. Removing Gas from Tendermint and the mempool would allow for the mempool to be a better
  55. abstraction: any transaction that arrived at `CheckTx` and passed the check will either be
  56. a candidate for a later block or evicted after a TTL is reached or to make room for
  57. other, higher priority transactions. All other transactions are completely invalid and can be discarded forever.
  58. Removing gas will not be completely straightforward. It will mean ensuring that
  59. equivalent functionality can be implemented outside of the mempool using the mempool's API.
  60. ## Discussion
  61. This section catalogs the functionality that will need to exist within the Tendermint
  62. mempool to allow Gas to be removed and replaced by application-side bookkeeping.
  63. ### Requirement: Provide Mempool Tx Sorting Mechanism
  64. Gas produces a market for inclusion in a block. On many networks, a [gas fee][cosmos-sdk-fees] is
  65. included in pending transactions. This fee indicates how much a user is willing to
  66. pay per unit of execution and the fees are distributed to validators.
  67. Validators wishing to extract higher gas fees are incentivized to include transactions
  68. with the highest listed gas fees into each block. This produces a natural ordering
  69. of the pending transactions. Applications wishing to implement a gas mechanism need
  70. to be able to order the transactions in the mempool. This can trivially be accomplished
  71. by sorting transactions using the `priority` field available to applications as part of
  72. v0.35's `ResponseCheckTx` message.
  73. ### Requirement: Allow Application-Defined Block Resizing
  74. When creating a block proposal, Tendermint pulls a set of possible transactions out of
  75. the mempool to include in the next block. Tendermint uses MaxGas to limit the set of transactions
  76. it pulls out of the mempool fetching a set of transactions whose sum is less than MaxGas.
  77. By removing gas tracking from Tendermint's mempool, Tendermint will need to provide a way for
  78. applications to determine an acceptable set of transactions to include in the block.
  79. This is what the new ABCI++ `PrepareProposal` method is useful for. Applications
  80. that wish to limit the contents of a block by an application-defined limit may
  81. do so by removing transactions from the proposal it is passed during `PrepareProposal`.
  82. Applications wishing to reach parity with the current Gas implementation may do
  83. so by creating an application-side limit: filtering out transactions from
  84. `PrepareProposal` the cause the proposal the exceed the maximum gas. Additionally,
  85. applications can currently opt to have all transactions in the mempool delivered
  86. during `PrepareProposal` by passing `-1` for `MaxGas` and `MaxBytes` into
  87. [ReapMaxBytesMaxGas][reap-max-bytes-max-gas].
  88. ### Requirement: Handle Transaction Metadata
  89. Moving the gas mechanism into applications adds an additional piece of complexity
  90. to applications. The application must now track how much gas it expects a transaction
  91. to consume. The mempool currently handles this bookkeeping responsibility and uses the estimated
  92. gas to determine the set of transactions to include in the block. In order to task
  93. the application with keeping track of this metadata, we should make it easier for the
  94. application to do so. In general, we'll want to keep only one copy of this type
  95. of metadata in the program at a time, either in the application or in Tendermint.
  96. The following sections are possible solutions to the problem of storing transaction
  97. metadata without duplication.
  98. #### Metadata Handling: EvictTx Callback
  99. A possible approach to handling transaction metadata is by adding a new `EvictTx`
  100. ABCI method. Whenever the mempool is removing a transaction, either because it has
  101. reached its TTL or because it failed `RecheckTx`, `EvictTx` would be called with
  102. the transaction hash. This would indicate to the application that it could free any
  103. metadata it was storing about the transaction such as the computed gas fee.
  104. Eviction callbacks are pretty common in caching systems, so this would be very
  105. well-worn territory.
  106. #### Metadata Handling: Application-Specific Metadata Field(s)
  107. An alternative approach to handling transaction metadata would be would be the
  108. addition of a new application-metadata field in the `ResponseCheckTx`. This field
  109. would be a protocol buffer message whose contents were entirely opaque to Tendermint.
  110. The application would be responsible for marshalling and unmarshalling whatever data
  111. it stored in this field. During `PrepareProposal`, the application would be passed
  112. this metadata along with the transaction, allowing the application to use it to perform
  113. any necessary filtering.
  114. If either of these proposed metadata handling techniques are selected, it's likely
  115. useful to enable applications to gossip metadata along with the transaction it is
  116. gossiping. This could easily take the form of an opaque proto message that is
  117. gossiped along with the transaction.
  118. ## References
  119. [eth-whitepaper-messages]: https://ethereum.org/en/whitepaper/#messages-and-transactions
  120. [gas-add-pr]: https://github.com/tendermint/tendermint/pull/2360
  121. [cosmos-sdk-gas]: https://github.com/cosmos/cosmos-sdk/blob/c00cedb1427240a730d6eb2be6f7cb01f43869d3/docs/basics/gas-fees.md
  122. [cosmos-sdk-fees]: https://github.com/cosmos/cosmos-sdk/blob/c00cedb1427240a730d6eb2be6f7cb01f43869d3/docs/basics/tx-lifecycle.md#gas-and-fees
  123. [anoma-gas]: https://github.com/anoma/anoma/blob/6974fe1532a59db3574fc02e7f7e65d1216c1eb2/docs/src/specs/ledger.md#transaction-execution
  124. [cosmos-sdk-fee]: https://github.com/cosmos/cosmos-sdk/blob/c00cedb1427240a730d6eb2be6f7cb01f43869d3/types/tx/tx.pb.go#L780-L794
  125. [issue-7750]: https://github.com/tendermint/tendermint/issues/7750
  126. [reap-max-bytes-max-gas]: https://github.com/tendermint/tendermint/blob/1ac58469f32a98f1c0e2905ca1773d9eac7b7103/internal/mempool/types.go#L45
  127. [add-mempool-error]: https://github.com/tendermint/tendermint/blob/205bfca66f6da1b2dded381efb9ad3792f9404cf/rpc/coretypes/responses.go#L239