feat(eip8130): account-abstraction receipt#3753
Conversation
Add the EIP-8130 receipt surface so AA transactions report their extra execution data through `eth_getTransactionReceipt`: - A `BaseReceipt::Eip8130` consensus variant wrapping the standard receipt with the per-phase `phaseStatuses` array, plus its node-local Compact persistence. - The executor publishes `phaseStatuses` for each EIP-8130 transaction via a thread-local handoff (`Eip8130PhaseStatuses`) consumed by the receipt builder. - RPC `BaseTransactionReceipt` gains the AA fields (`payer`, `status`, `phaseStatuses`, `metadata`), derived in the receipt response builder. Also relocates the balance-monitor unit tests into a sibling test module.
…e-status drop Address review feedback on the receipt PR: - Revert the balance-monitor unit tests back to a colocated `#[cfg(test)] mod tests` block in `monitor.rs`, per the project convention against standalone `tests.rs` modules. This drops the unrelated test relocation entirely. - Add a `debug_assert!` in the `no_std` `Eip8130PhaseStatuses::set` so a future caller that drops non-empty statuses (which `take` could not recover) fails loudly instead of silently; EIP-8130 execution is `std`-gated, so statuses are always empty here today.
Move the `Eip8130PhaseStatuses::set` handoff to after the journal teardown (`take_logs`/`checkpoint_commit`/`commit_tx`/local+frame clear), so the only code between publishing the statuses and the receipt builder's `take` is the allocation-free result construction. This closes the window where a panic in the journal teardown could leave stale per-phase statuses in the thread-local slot for the next transaction on the same thread.
…adata Address review feedback on the EIP-8130 receipt PR: - Panic safety: clear the phase-status thread-local at the start of every `execute` so a value leaked by an earlier transaction (e.g. a panic caught between its `set` and the receipt builder's `take`) can never be misattributed to the current transaction's receipt. - Empty metadata: omit empty EIP-8130 metadata from `eth_getTransactionReceipt` rather than serializing it as `"0x"`, matching how empty `phaseStatuses` is skipped. Locked by an assertion in the empty-calls test. - Add a sponsored-payer receipt test (declared payer != sender) pinning the `tx.payer.unwrap_or(sender)` precedence. - Add a Compact round-trip test pinning that `eip8130_phase_statuses` survives encode/decode as the trailing field.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
xenoliss
left a comment
There was a problem hiding this comment.
nit: the phase-status handoff relies on reth executing each tx as execute -> build_receipt sequentially on one thread, but no test covers >1 EIP-8130 tx per block. We might want to add a 2-tx case (one with a reverting phase) to lock the per-tx attribution against future executor changes.
Add an end-to-end test that mines two EIP-8130 transactions into a single block — one fully successful and one whose second phase reverts — and asserts each receipt carries its own `phaseStatuses`. This locks the per-transaction attribution of the thread-local executor->receipt-builder handoff (`Eip8130PhaseStatuses`), which relies on reth driving each tx as `execute` -> `build_receipt` sequentially on one thread. A regression that leaked or swapped one tx's statuses would surface here even though the single-8130-tx-per-block tests would still pass.
Review SummaryOverall: Clean implementation. The EIP-8130 receipt plumbing is well-structured, the thread-local handoff is justified by the reth receipt builder API constraints, and the backward-compatible ArchitectureThe Thread-local handoff (
|
✅ base-std fork tests: all 616 passedbase/base is fully in sync with the base-std spec.
|
Summary
Adds the EIP-8130 receipt surface so AA transactions
report their extra execution data through
eth_getTransactionReceiptBaseReceipt::Eip8130variant wrapping the standardreceipt with the per-phase
phaseStatusesarray, plus its node-local Compact(de)serialization for storage.
while running a transaction's
callsand publishes it to the receipt buildervia a single-threaded thread-local slot (
Eip8130PhaseStatuses); the receiptbuilder takes it immediately after execution. The slot is cleared at the start
of every
executeso a value leaked by an earlier transaction (e.g. a paniccaught between its
setand the builder'stake) can never be misattributed.Rationale is documented on the type (the receipt builder is generic over the
EVM and has no typed channel for per-tx metadata).
BaseTransactionReceiptgains the AA fields (payer,status,phaseStatuses,metadata), derived in the receipt responsebuilder. Empty
metadatais omitted rather than serialized as"0x",matching how empty
phaseStatusesis skipped.Test plan
cargo testforbase-common-consensus,base-common-evm,base-common-rpc-types,base-execution-eip8130-rpc-node(incl. the newend-to-end
tests/receipt.rs, covering self-pay, phase statuses, and thesponsored-payer precedence) — all pass.
cargo check --workspace --all-featurescargo clippy --all-features --all-targetson touched crates — clean.cargo +nightly fmt --all -- --check— clean.