Skip to content

feat(payload): add state_gas_used metric for TIP-1016 state gas tracking#3372

Open
fgimenez wants to merge 44 commits intotip1016from
fgimenez/state-gas-metric
Open

feat(payload): add state_gas_used metric for TIP-1016 state gas tracking#3372
fgimenez wants to merge 44 commits intotip1016from
fgimenez/state-gas-metric

Conversation

@fgimenez
Copy link
Copy Markdown
Member

Adds state_gas_used histogram and gauge to TempoPayloadBuilderMetrics, accumulating per-tx state gas via execute_transaction_with_result_closure across pool, subblock, and system transactions. Pre-T3 this will always be
zero; post-T3 it captures the state gas dimension split out by TIP-1016.

rakita and others added 30 commits March 27, 2026 16:40
Bump dependencies to EIP-8037 (State Gas Reservoir Model) branches:
- reth: 2a94eed → ff2f857e (eip8037 branch)
- revm: patched via local path at 3a29466d (rakita/state-gas branch)
- alloy-evm: patched to a8da352a (eip8037 branch)
- revm-inspectors: patched to 50676ae7 (eip8037 branch)

Adapt to API changes: PrecompileOutput now uses GasTracker instead of
gas_used/gas_refunded fields, PrecompileResult error type changed to
PrecompileFailure, InitialAndFloorGas.initial_gas renamed to
initial_total_gas, Handler trait methods gained EIP-8037 parameters,
ResultGas removed with_limit(), and commit_transaction returns GasOutput.
Let `?` auto-convert via `From<PrecompileError> for PrecompileFailure`
instead of wrapping explicitly with `PrecompileFailure::from(...)`.
Remove serde-bincode-compat features and RlpBincode impls removed
upstream, drop redundant SignedTransaction/InMemorySize impls now
covered by blanket impls, and migrate spent() to total_gas_spent()
for EIP-8037.
Bump dependencies to EIP-8037 (State Gas Reservoir Model) branches:
- reth: 2a94eed → ff2f857e (eip8037 branch)
- revm: patched via local path at 3a29466d (rakita/state-gas branch)
- alloy-evm: patched to a8da352a (eip8037 branch)
- revm-inspectors: patched to 50676ae7 (eip8037 branch)

Adapt to API changes: PrecompileOutput now uses GasTracker instead of
gas_used/gas_refunded fields, PrecompileResult error type changed to
PrecompileFailure, InitialAndFloorGas.initial_gas renamed to
initial_total_gas, Handler trait methods gained EIP-8037 parameters,
ResultGas removed with_limit(), and commit_transaction returns GasOutput.
Bump dependencies to EIP-8037 (State Gas Reservoir Model) branches:
- reth: 2a94eed → ff2f857e (eip8037 branch)
- revm: patched via local path at 3a29466d (rakita/state-gas branch)
- alloy-evm: patched to a8da352a (eip8037 branch)
- revm-inspectors: patched to 50676ae7 (eip8037 branch)

Adapt to API changes: PrecompileOutput now uses GasTracker instead of
gas_used/gas_refunded fields, PrecompileResult error type changed to
PrecompileFailure, InitialAndFloorGas.initial_gas renamed to
initial_total_gas, Handler trait methods gained EIP-8037 parameters,
ResultGas removed with_limit(), and commit_transaction returns GasOutput.
…(TIP-1016) (#2734)

Closes CHAIN-791

Adds block-level plumbing to track execution gas and storage creation
gas separately in `TempoBlockExecutor`.

- Added `cumulative_full_gas_used` and `cumulative_storage_creation_gas`
fields to `TempoBlockExecutor`
- `commit_transaction` now computes `execution_gas = full_gas -
storage_creation_gas` and only execution gas counts toward block gas
limits (`non_shared_gas_left`, `non_payment_gas_left`)
- Receipts and `cumulative_full_gas_used` continue to track full gas
(execution + storage creation)
- `finish()` returns execution gas (not full gas) for the block header
gas field
- `storage_creation_gas` is hardcoded to `0` with a TODO — it will be
populated once handler-level tracking lands (CHAIN-789 / PR #2714)

Note: hardfork gating is not required. With `storage_creation_gas = 0`,
all gas accounting is identical to the current behavior. The hardfork
gate (T2) lives in the handler layer, not here. This is pure plumbing
that becomes active only when upstream EVM tracking is enabled.
… (TIP-1016) (#2714)

Closes CHAIN-789

Introduces state gas tracking in the EVM handler for the T2 hardfork.
State gas separates the cost of state-touching operations (account
creation, contract deployment) from execution gas, enabling the
reservoir model and tx cap bypass for state-heavy transactions.

`crates/evm/src/lib.rs`:
- Set `cfg_env.enable_state_gas = spec.is_t2()` in both `evm_env` and
`next_evm_env`

`crates/revm/src/handler.rs`
- `adjusted_initial_gas`: propagate `initial_state_gas` through
`InitialAndFloorGas::new_with_state_gas`
- `calculate_aa_batch_intrinsic_gas`: track `new_account_state_gas +
create_state_gas` for AA CREATE calls
- Multi-call gas reconstruction: use flattened `Gas::new_spent` +
`erase_cost` pattern (robust under EIP-8037 reservoir model) and
accumulate `state_gas_spent` across calls
- Tx gas limit cap bypass: upstream revm already skips the cap check
when `enable_state_gas` is true
- `reimburse_caller`: no changes needed — `gas.used()` already includes
state gas through the reservoir flattening in `last_frame_result`
Co-authored-by: rakita <rakita@users.noreply.github.com>
…or of inner executor's block_regular_gas_used
fgimenez and others added 10 commits March 27, 2026 17:29
…erflow in revm's execution/first_frame_input subtraction
…bc7, reth to b25459035f

- reth-primitives-traits and reth-codecs now from crates.io (extracted from reth repo)
- Remove TempoPayloadBuilderAttributes (PayloadBuilderAttributes trait removed upstream)
- Add payload_id() to TempoPayloadAttributes PayloadAttributes impl
- Update BuildArguments::new(), builder.finish(), EthBuiltPayload::new() signatures
- Add into_result() to TxResult impl, rename tx_gas_used -> cumulative_tx_gas_used
- Remove EngineApiMessageVersion from fork_choice_updated() calls
- Update Decompress impl to use reth_codecs::DecompressError
- Rename tx_gas_used -> cumulative_tx_gas_used in test
- Add missing gas_used arg to into_precompile_result
- Remove EngineApiMessageVersion from fork_choice_updated calls in tests
- Remove unused PayloadId import
- finish() returns cumulative_tx_gas_used - block_state_gas_used for TIP-1016
  (state gas exempted from block capacity, charged to users via receipts)
- Fix adjusted_initial_gas: evm_initial_gas already includes state gas in new revm
- Fix validate_initial_tx_gas: initial_total_gas already includes initial_state_gas
- Use saturating_sub for gas subtractions to prevent overflow
- Update test assertions for new gas model behavior
Root cause: In the new revm, initial_total_gas must include initial_state_gas.
Tempo's nonce==0 and auth list gas additions were adding the execution portion
(e.g. 5000) to initial_total_gas but a much larger state portion (e.g. 245000)
to initial_state_gas, violating the invariant.

Fix: Add both execution + state portions to initial_total_gas when adding state
gas, maintaining initial_total_gas >= initial_state_gas.

Also fix adjusted_initial_gas to not double-count state gas since evm_initial_gas
already includes init_and_floor_gas.initial_state_gas in the new revm.

- Fix nonce==0 gas additions in validate_initial_tx_gas and AA batch path
- Fix auth list gas additions
- Fix validation check (total already includes state)
- Increase tip20 test gas limit for higher intrinsic gas
@fgimenez fgimenez requested review from rakita and shekhirin March 30, 2026 15:20
@fgimenez fgimenez requested a review from 0xKitsune as a code owner March 30, 2026 15:20
@fgimenez fgimenez added the A-observability Related to tracing, metrics, logs and other observability tools label Mar 30, 2026
@fgimenez fgimenez requested review from klkvr and mattsse as code owners March 30, 2026 15:20
@fgimenez fgimenez force-pushed the fgimenez/state-gas-metric branch from 1420f88 to 0c4d3cf Compare March 30, 2026 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-observability Related to tracing, metrics, logs and other observability tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants