rpc: add Reth-compatible format for debug_executionWitness#21509
Draft
lupin012 wants to merge 2 commits into
Draft
rpc: add Reth-compatible format for debug_executionWitness#21509lupin012 wants to merge 2 commits into
lupin012 wants to merge 2 commits into
Conversation
1a352c3 to
5927fa4
Compare
Add --rpc.witness.gethcompat flag to select the output format: - default (off): Reth-compatible — headers RLP-encoded, keys populated, EIP-7702 delegation codes filtered out - --rpc.witness.gethcompat: Geth-compatible — headers as JSON objects, keys null (previous behaviour) Also remove the unused mode *string parameter from the ExecutionWitness interface, extract a sortedCodesSlice helper to eliminate duplicated sort-and-collect logic, and avoid a second GetAccessedCode() call by integrating the EIP-7702 filter into collectAccessedState. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5927fa4 to
837fde9
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a configurable output format for debug_executionWitness, defaulting to a Reth-compatible (canonical) wire format while allowing a Geth-compatible mode via --rpc.witness.gethcompat. This fits into Erigon’s RPC daemon/debug API surface, aiming to improve cross-client compatibility for witness consumers and stateless verification.
Changes:
- Add a
witnessGethCompatswitch toDebugAPIImpland plumb a new CLI/config flag (rpc.witness.gethcompat) through rpcdaemon/node config. - Change witness header serialization to be either JSON objects (Geth mode) or RLP-encoded bytes (Reth mode), and adjust the witness result shape accordingly.
- Refactor witness code collection to support stateless verification with an internal
allCodesset and add EIP-7702 delegation-code filtering in Reth mode.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| rpc/jsonrpc/debug_execution_witness.go | Core witness result format switch (JSON vs RLP headers), code/key collection changes, and stateless verifier adjustments. |
| rpc/jsonrpc/debug_api.go | Adds witnessGethCompat to DebugAPIImpl and extends constructor signature. |
| rpc/jsonrpc/daemon.go | Wires cfg.WitnessGethCompat into NewPrivateDebugAPI. |
| rpc/jsonrpc/debug_api_test.go | Updates debug API tests for new NewPrivateDebugAPI signature and adjusts witness assertions. |
| rpc/jsonrpc/gen_traces_test.go | Updates test to match new NewPrivateDebugAPI signature. |
| cmd/utils/flags.go | Introduces rpc.witness.gethcompat CLI flag definition. |
| node/cli/default_flags.go | Registers the new witness compat flag in default flags. |
| node/cli/flags.go | Plumbs WitnessGethCompat into embedded rpcdaemon HTTP config. |
| cmd/rpcdaemon/cli/httpcfg/http_cfg.go | Adds WitnessGethCompat to rpcdaemon HTTP config struct. |
| cmd/rpcdaemon/cli/config.go | Exposes rpc.witness.gethcompat as a cobra persistent flag. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
523
to
524
| // Keys is always null (reserved for future use, included for Geth compatibility) | ||
| Keys []hexutil.Bytes `json:"keys"` |
Comment on lines
794
to
806
| t.Run("by block number", func(t *testing.T) { | ||
| // Test with block number 1 | ||
| blockNum := rpc.BlockNumber(1) | ||
| result, err := api.ExecutionWitness(ctx, rpc.BlockNumberOrHash{BlockNumber: &blockNum}) | ||
|
|
||
| require.NoError(t, err) | ||
| require.NotNil(t, result) | ||
| require.NotNil(t, result.State, "State should not be nil") | ||
| require.Nil(t, result.Keys, "Keys must remain nil (Geth compatibility)") | ||
| if len(result.Headers) > 0 { | ||
| require.NotNil(t, result.Keys, "Keys must be set in Reth-compatible mode") | ||
| if len(result.headerByNumber) > 0 { | ||
| require.Contains(t, result.headerByNumber, uint64(0), "parent header (block 0) must be present in lookup map when Headers is non-empty") | ||
| } | ||
| }) |
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.
Before this PR the debug_executionWitness () returns data according Geth.
This PR permit to return debug_executionWitness () in two formats: Reth (canonical) [default] and Geth using a config param
In debug_execution_witness.go:
ExecutionWitnessResult.Headers changed from []map[string]any to any (holds either JSON objects or RLP-encoded bytes depending on the flag)
Added internal allCodes field for stateless verification (unfiltered: accessed + newly deployed code)
New witnessHeadersToJSON and witnessHeadersToRLP serialisation helpers
New filterEIP7702Codes — removes EIP-7702 delegation designator codes and their targets from codes in Reth-compat mode
collectAccessedState accepts gethCompat bool and integrates the EIP-7702 filter internally, avoiding a second GetAccessedCode() call
collectAccessedHeaders now returns []*types.Header; serialisation to wire format happens at the call site
Storage keys: emit key.Bytes() only (previously addr || key composite)
Local sortedCodesSlice helper eliminates the duplicated sort-and-collect pattern used for both SortedCodes and AllCodes
Stateless verifier uses allCodes instead of Codes so contracts deployed within the block are available during re-execution
Reth-compatible (defualt):
--rpc.witness.gethcompat: Geth-compatible:
I've run some tests on Hive (50 blocks), and Erigon returns the exact same responses as Geth and Reth (canonical) for all fields except for state.
For the state field in a few tests on hive:
It's possible that these extra/missing nodes aren't actually essential for the witness.
I haven't run any tests on mainnet comparing with Reth (canonical), but
I have run a few mainnet tests comparing with Geth using the --rpc.witness.gethcompat flag