Repository navigation
Conversation
…ndle in eth_callMany and debug_traceCallMany With a state override, eth_callMany and debug_traceCallMany built the precompile set once from the base block's rules and set it on the EVM of every bundle. A bundle that moves the block past a fork with a block override then ran with the old fork's precompiles: a call to a BLS12-381 precompile after Prague ran against an empty account. Without a state override the EVM already picked the bundle's own set, so the same request gave different results depending on the override. Override still runs once, before the bundles, because it changes the state. Each bundle now gets a fresh set for its own rules, with the same code overrides and precompile moves applied.
Collaborator
|
Looks good. Ship. |
lupin012
marked this pull request as ready for review
October 26, 2026 10:57
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
Static review found no blocking issues in the focused change, and regression coverage addresses the reported failure; tests were not executed.
No open issues 🎉
What changed in this PR
This PR makes eth_callMany and debug_traceCallMany select overridden precompiles using each bundle’s fork rules, while preserving one-time state override application.
Changes:
- Extracts shared precompile override logic and adds a state-independent
ActivePrecompileshelper. - Rebuilds the precompile set after each bundle’s block overrides.
- Adds Prague fork-crossing regression coverage for both methods, with and without state overrides.
| File | Description |
|---|---|
rpc/jsonrpc/tracing.go |
Rebuilds overridden precompiles per tracing bundle. |
rpc/jsonrpc/eth_callMany.go |
Selects precompiles using each bundle’s overridden block context. |
rpc/jsonrpc/eth_callMany_test.go |
Tests fork-crossing precompile selection in both methods. |
rpc/ethapi/state_overrides.go |
Separates precompile override logic from state mutation. |
Review effort: Balanced
…compiles_per_bundle # Conflicts: # rpc/ethapi/state_overrides.go
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
With a state override,
eth_callManyanddebug_traceCallManybuild the precompile set once, from the base block's rules, and callSetPrecompileswith it on the EVM of every bundle. A bundle can move the block forward with a block override ontimeornumber. If this crosses a fork, the bundle runs with the old fork's precompiles: for example, after Prague a call to0x0b(BLS12-381 G1ADD) runs against an empty account.Without a state override,
activePrecompilesis nil andNewEVMalready selects the bundle's own set. So the same request gave different results depending on whether it carried a state override.Change
StateOverrides.Overrideis unchanged in behavior. Its precompile loop moved tooverridePrecompiles.StateOverrides.ActivePrecompiles(rules): a fresh precompile set forrules, with the same code overrides and precompile moves applied, without touching the state. It returns nil when there are no overrides.eth_callManyanddebug_traceCallManystill callOverrideonce, before the bundles, because it changes the state. Each bundle now gets its set fromActivePrecompiles(blockCtx.Rules(chainConfig)), after its block override.Other clients
eth_callManyanddebug_traceCallManyare not in execution-apis, so the reference is the behavior of the closest methods in other clients:eth_call(doCall) applies the block overrides first and builds the precompile set from the overridden block context.eth_simulateV1builds the set per block.debug_traceCallManywith overrides through itseth_simulateV1executor, so every bundle uses the spec of its own block.This change gives the same behavior: the precompile set follows the bundle's block.
Test
TestCallManyBundleCrossingForkUsesItsPrecompilesruns a bundle that moves past a Prague fork and calls0x0b, for both methods, with and without a state override. Before the fix, only the two cases with a state override failed (empty output instead of the 128-byte result).Note
#24741 changes the
deletecondition inside the loop that this PR moves tooverridePrecompiles. Whichever merges second needs a small manual rebase.