fix(anvil): preserve custom request fields#15806
Conversation
48837d6 to
5fb60c0
Compare
5fb60c0 to
897be34
Compare
Decode Tempo transaction extensions fallibly and retain network-specific fields in eth_simulateV1 payloads and fork forwarding. This avoids lossy request reconstruction and keeps malformed extension values from being silently ignored. Co-authored-by: jxom <7336481+jxom@users.noreply.github.com>
897be34 to
5d19aec
Compare
mattsse
left a comment
There was a problem hiding this comment.
The RPC boundary now preserves extension fields and historical-fork forwarding is fixed, but the local simulation path still drops them.
[P1] crates/anvil/src/eth/backend/mem/mod.rs:5100-5101 immediately replaces each WithOtherFields<TransactionRequest> with request.inner. For a local eth_simulateV1 request this discards calls and every other Tempo extension before both execution and response construction. A calls-only type-0x76 batch can therefore be simulated as an empty top-level creation, or reconstructed later as a malformed Tempo transaction. This leaves the original failure mode in place whenever the requested block is handled by local state rather than forwarded to a historical fork.
Suggested fix: keep the WithOtherFields value intact and parse it once with FoundryTransactionRequest::try_from_rpc_request(request, self.is_tempo()). For the Tempo variant, construct the native TempoTxEnv from the complete request (including calls, authorization, nonce/validity, and fee fields), execute it through the Tempo transaction path, and reuse that same parsed request when building the simulated transaction response. The Ethereum path can continue using build_call_env. If local Tempo execution must remain out of scope, reject these extensions explicitly instead of silently dropping them, although that would not provide the preservation behavior this PR is intended to add.
Please add an end-to-end raw-RPC regression under crates/anvil/tests/it/tempo.rs: spawn NodeConfig::test_tempo(), call eth_simulateV1 without a historical block using a calls-only type: "0x76" request containing two distinguishable calls, and set returnFullTransactions: true. Assert that the RPC succeeds, the simulated call status is successful, observable return data or logs prove that both calls executed, and the returned transaction has type 0x76 with calls exactly equal to the submitted array. This exercises the local branch and catches both execution-time and response-time field loss.
Description
This supersedes #15804 by preserving the complete set of Tempo request extensions, including batched calls, through Anvil’s transaction-building path; a follow-up PR extending those semantics across local simulation and execution paths will come later.
FoundryTransactionRequestnow decodes all known Tempo extensions fallibly and preserves consensus fields during typed transaction round-trips. The Tempo-aware transaction-building path rejects conflicting explicit transaction types and only infers Tempo extensions when Anvil is running with the Tempo network enabled. Calls-only Tempo batches are built without a synthetic creation call, while requests without an explicit gas limit use a conservative fallback rather than an extension-free estimate.eth_simulateV1now deserializes calls as extensible transaction requests and preserves their structured extension fields when simulation is delegated to a historical fork. This PR only changes request representation, fork forwarding, and transaction construction; it does not add local Tempo request execution. A follow-up PR will apply Tempo semantics acrosseth_call,eth_estimateGas,eth_createAccessList, call-many, tracing, and localeth_simulateV1, including Tempo-aware response envelopes and transaction-root construction.The implementation and review were completed with AI assistance.