Skip to content

fix(cli): wire --proofs-history into node launcher - #982

Draft
0xOsiris wants to merge 1 commit into
mainfrom
fix/wire-proofs-history
Draft

fix(cli): wire --proofs-history into node launcher#982
0xOsiris wants to merge 1 commit into
mainfrom
fix/wire-proofs-history

Conversation

@0xOsiris

@0xOsiris 0xOsiris commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Problem

WorldChainArgs flattens op-reth's RollupArgs, so clap accepts --proofs-history,
--proofs-history.window, --proofs-history.storage-path, --proofs-history.storage-version
and --proofs-history.verification-interval. But bin/world-chain/src/main.rs called the plain
builder.node(node).launch(), and proofs_history appeared nowhere else in crates/ or bin/.

An operator who set --proofs-history got no ExEx, no RPC override, no warning, no metric
a silent no-op. This matters right now: eth_getProof at historical blocks is timing out on
alphanet (MDBX -96000) because reth rebuilds a revert overlay past EPOCH_SLOTS (32 blocks)
while the proof workers query ~450 blocks back.

Change

New bin/world-chain/src/proofs_history.rs mirrors
reth_optimism_node::proof_history::launch_node. Upstream's version cannot be reused: it is
hardcoded to OpNode/OpChainSpec, while this binary launches
WorldChainNode<WorldChainDefaultContext> over WorldChainSpec.

When --proofs-history is set the launcher:

  1. resolves the storage path (default <datadir>/historical-proofs) and opens
    MdbxProofsStorage (v1) or MdbxProofsStorageV2 (v2);
  2. installs the proofs-history ExEx (OpProofsExEx) with the configured window and
    verification interval;
  3. replaces eth_getProof (http/ws/ipc + auth) and debug_executePayload /
    debug_executionWitness (http/ws/ipc), and adds debug_proofsSyncStatus;
  4. spawns a critical task reporting the proofs-DB MDBX gauges on
    --metrics.push-gateway-interval.

OpProofsExEx<Node, Storage> is bounded on Node: FullNodeComponents, not on OpNode, so it
attaches to the World Chain node adapter without modification.

Deps added at the pinned rev 423d93e6374a65f3a83c1ed5e29c5998c972a5da:
reth-optimism-exex and reth-optimism-trie, both with features = ["metrics"] (matching
op-reth's own crates/node; without it OpProofsStorage degrades to a bare type alias and
DatabaseMetrics is not implemented).

Flag off = unchanged

When --proofs-history is false the launcher does exactly what main.rs did before:
builder.node(node).launch() with no hooks registered. No storage is opened, no ExEx installed,
no RPC method touched.

add_ons.rs interaction (OpDebugWitnessApi)

They do not conflict — the proofs-history override deliberately wins, and the ordering is
correct.

  • WorldChainAddOns::launch_add_ons registers op-reth's re-execution-based OpDebugWitnessApi
    (crates/node/src/add_ons.rs:408, :448). That type only serves debug_executePayload.
  • reth runs the add-ons ext(...) closure first, then the builder-registered
    extend_rpc_modules hooks (reth-2.3.0 crates/node/builder/src/rpc.rs:1161-1168). Our hook is
    therefore applied last.
  • replace_configured = remove_*_methods(names) then merge_*, so the earlier registration is
    removed before ours is merged. No RegisterMethodError for a duplicate method name, and no
    dependence on registration order beyond "ours is last".

Net effect with the flag on: debug_executePayload is served from the proofs DB instead of
re-executing over a live state overlay; debug_executionWitness replaces reth's stock
DebugApi implementation. With the flag off, OpDebugWitnessApi behaves exactly as today.

Two consequences worth reviewing:

  1. Auth port asymmetry (inherited from op-reth). The hook calls replace_auth_methods only
    for EthApiExt. On the authenticated engine port, debug_executionWitness remains reth's
    stock re-execution implementation — only eth_getProof is redirected to the proofs DB.
  2. Namespace gating. replace_configured merges into whichever transports exist, not into
    whichever namespaces were selected. With --http enabled, --proofs-history exposes
    debug_executePayload, debug_executionWitness and debug_proofsSyncStatus on HTTP/WS/IPC
    even when debug is absent from --http.api. This is upstream op-reth behaviour, but this
    repo is otherwise deliberate about namespace gating (cf. the simulate handling in
    crates/cli/src/cli.rs).

Blocker before this flag is usable

crates/cli/src/app.rs rejects Commands::OpProofs(_) ("this OP-specific command is not yet
supported with WorldChainSpec"). Upstream op_proofs::Command::execute is bounded on
C: ChainSpecParser<ChainSpec = OpChainSpec>, so it cannot simply be enabled.

OpProofsExEx::run starts with ensure_initialized(), which errors if the proofs DB has no
proof window — and a failing ExEx panics a critical task and takes the node down. So today,
--proofs-history on this binary turns a silent no-op into a loud startup failure. That is the
correct direction under "no hidden failures", but the DB must be seedable before the flag is
useful. Needs a follow-up (a World Chain proofs init path).

Upstream clap bug found while testing

RollupArgs::proofs_history declares
default_value_ifs([("proofs-history.storage-path", ArgPredicate::IsPresent, "true")]), but clap
matches default_value_ifs predicates by arg id (storage_path, the field name), not by long
name. The predicate never fires: --proofs-history.storage-path /x alone does not enable the
feature. proofs_history_storage_path_alone_does_not_enable pins current behaviour so a future
op-reth fix surfaces as a test failure instead of a silent behaviour change.

Verification

  • cargo check -p world-chain — clean.
  • RUSTFLAGS="-D warnings" cargo +nightly clippy -p world-chain -p world-chain-cli --all-features
    — clean.
  • cargo +nightly fmt --all --check — clean.
  • cargo nextest run -p world-chain-cli — 34/34 pass.
  • Not verified: no node has been launched with --proofs-history. Needs a devnet/alphanet run
    against a seeded proofs DB to confirm the ExEx attaches, the RPC overrides answer, and
    eth_getProof at ~450 blocks back stops timing out.

🤖 Generated with Claude Code


Note

Medium Risk
Changes node launch path and replaces critical RPC (eth_getProof, debug witness) when enabled; unseeded proofs DB can fail the ExEx at startup, though default-off preserves prior behavior.

Overview
Fixes a silent no-op: --proofs-history and related rollup flags were already parsed via flattened RollupArgs, but the binary only called plain builder.node(node).launch() with no ExEx or RPC hooks.

Node startup is delegated to new proofs_history::launch_node. When the flag is off, behavior is unchanged (direct launch). When on, it opens v1/v2 MDBX proofs storage under the resolved datadir path, installs OpProofsExEx, replaces eth_getProof and debug proof/witness RPC handlers (including auth eth), and reports proofs-DB metrics on the push-gateway interval.

Workspace/binary deps add reth-optimism-exex and reth-optimism-trie (with metrics). CLI tests lock proofs-history default off, explicit --proofs-history enabling it, and that --proofs-history.storage-path alone does not turn the feature on (upstream clap default_value_ifs quirk).

Reviewed by Cursor Bugbot for commit 420e93d. Configure here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

Base and PR measured on the same runner in the same workflow run.

Benchmark Base PR Change
flashblock_validation_launch_flashblock_sequence_eth_transfers/stream/4fb_x_125tx 29.4±0.17ms 29.0±0.57ms 🟢 -0.99%
flashblock_validation_launch_flashblock_sequence_eth_transfers/stream/4fb_x_250tx 57.7±0.42ms 56.6±0.65ms 🟢 -1.96%
flashblock_validation_launch_flashblock_sequence_eth_transfers/stream/4fb_x_50tx 12.3±0.09ms 12.3±0.13ms 🟢 +0.00%
flashblock_validation_launch_flashblock_sequence_eth_transfers_with_bal/stream/4fb_x_125tx 35.3±0.33ms 35.6±0.38ms 🟡 +1.00%
flashblock_validation_launch_flashblock_sequence_eth_transfers_with_bal/stream/4fb_x_250tx 75.4±0.29ms 75.6±0.51ms 🟢 +0.00%
flashblock_validation_launch_flashblock_sequence_eth_transfers_with_bal/stream/4fb_x_50tx 14.6±0.27ms 14.7±0.19ms 🟢 +0.00%
flashblock_validation_launch_flashblock_sequence_fib/stream/4fb_x_125tx 27.2±0.04ms 27.5±0.08ms 🟡 +1.00%
flashblock_validation_launch_flashblock_sequence_fib/stream/4fb_x_250tx 53.5±0.14ms 53.5±0.07ms 🟢 +0.00%
flashblock_validation_launch_flashblock_sequence_fib/stream/4fb_x_50tx 11.4±0.02ms 11.3±0.03ms 🟢 -0.99%
flashblock_validation_launch_flashblock_sequence_fib_with_bal/stream/4fb_x_125tx 29.2±0.17ms 29.2±0.21ms 🟢 +0.00%
flashblock_validation_launch_flashblock_sequence_fib_with_bal/stream/4fb_x_250tx 55.9±0.20ms 56.3±0.32ms 🟡 +1.00%
flashblock_validation_launch_flashblock_sequence_fib_with_bal/stream/4fb_x_50tx 13.7±0.12ms 13.6±0.34ms 🟢 -0.99%
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254/stream/4fb_x_10tx 136.1±0.40ms 136.0±0.39ms 🟢 +0.00%
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254/stream/4fb_x_12tx 163.4±0.52ms 163.1±0.54ms 🟢 +0.00%
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254/stream/4fb_x_5tx 68.8±0.21ms 68.5±0.18ms 🟢 +0.00%
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254_with_bal/stream/4fb_x_10tx 23.1±2.24ms 24.4±1.02ms 🟡 +6.00%
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254_with_bal/stream/4fb_x_12tx 27.0±0.76ms 26.9±0.29ms 🟢 +0.00%
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254_with_bal/stream/4fb_x_5tx 18.3±0.67ms 18.3±0.30ms 🟢 +0.00%
flashblock_validation_process_flashblock_eth_transfers/txs/1000 49.4±0.22ms 49.8±0.14ms 🟡 +1.00%
flashblock_validation_process_flashblock_eth_transfers/txs/50 2.7±0.01ms 2.7±0.01ms 🟢 +0.00%
flashblock_validation_process_flashblock_eth_transfers/txs/500 24.7±0.03ms 25.1±0.31ms 🟡 +1.00%
flashblock_validation_process_flashblock_eth_transfers_with_bal/txs/1000 50.2±0.16ms 50.6±0.22ms 🟡 +1.00%
flashblock_validation_process_flashblock_eth_transfers_with_bal/txs/50 3.2±0.05ms 3.2±0.04ms 🟢 -0.99%
flashblock_validation_process_flashblock_eth_transfers_with_bal/txs/500 25.7±0.15ms 25.8±0.08ms 🟢 +0.00%
flashblock_validation_process_flashblock_fib/txs/1000 48.5±0.15ms 48.5±0.08ms 🟢 +0.00%
flashblock_validation_process_flashblock_fib/txs/50 2.6±0.01ms 2.6±0.01ms 🟢 +0.00%
flashblock_validation_process_flashblock_fib/txs/500 24.3±0.10ms 24.3±0.06ms 🟢 +0.00%
flashblock_validation_process_flashblock_fib_with_bal/txs/1000 48.9±0.11ms 48.9±0.15ms 🟢 +0.00%
flashblock_validation_process_flashblock_fib_with_bal/txs/50 3.1±0.03ms 3.1±0.06ms 🟡 +1.00%
flashblock_validation_process_flashblock_fib_with_bal/txs/500 24.9±0.07ms 24.9±0.08ms 🟢 +0.00%
flashblock_validation_process_flashblock_world_id_like_bn254/txs/10 33.9±0.03ms 33.9±0.08ms 🟢 +0.00%
flashblock_validation_process_flashblock_world_id_like_bn254/txs/25 84.3±0.08ms 84.4±0.24ms 🟢 +0.00%
flashblock_validation_process_flashblock_world_id_like_bn254/txs/50 169.4±0.52ms 168.3±0.37ms 🟢 -0.99%
flashblock_validation_process_flashblock_world_id_like_bn254_with_bal/txs/10 5.9±0.39ms 6.0±0.40ms 🟡 +2.00%
flashblock_validation_process_flashblock_world_id_like_bn254_with_bal/txs/25 7.8±0.09ms 7.7±0.09ms 🟢 -0.99%
flashblock_validation_process_flashblock_world_id_like_bn254_with_bal/txs/50 14.2±0.06ms 14.2±0.06ms 🟢 +0.00%

🔴 regression > 10%  ·  🟡 slower  ·  🟢 faster. A regression > 10% fails the check.

Raw critcmp output
group                                                                                              base                                   pr
-----                                                                                              ----                                   --
flashblock_validation_launch_flashblock_sequence_eth_transfers/stream/4fb_x_125tx                  1.01     29.4±0.17ms        ? ?/sec    1.00     29.0±0.57ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_eth_transfers/stream/4fb_x_250tx                  1.02     57.7±0.42ms        ? ?/sec    1.00     56.6±0.65ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_eth_transfers/stream/4fb_x_50tx                   1.00     12.3±0.09ms        ? ?/sec    1.00     12.3±0.13ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_eth_transfers_with_bal/stream/4fb_x_125tx         1.00     35.3±0.33ms        ? ?/sec    1.01     35.6±0.38ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_eth_transfers_with_bal/stream/4fb_x_250tx         1.00     75.4±0.29ms        ? ?/sec    1.00     75.6±0.51ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_eth_transfers_with_bal/stream/4fb_x_50tx          1.00     14.6±0.27ms        ? ?/sec    1.00     14.7±0.19ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_fib/stream/4fb_x_125tx                            1.00     27.2±0.04ms        ? ?/sec    1.01     27.5±0.08ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_fib/stream/4fb_x_250tx                            1.00     53.5±0.14ms        ? ?/sec    1.00     53.5±0.07ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_fib/stream/4fb_x_50tx                             1.01     11.4±0.02ms        ? ?/sec    1.00     11.3±0.03ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_fib_with_bal/stream/4fb_x_125tx                   1.00     29.2±0.17ms        ? ?/sec    1.00     29.2±0.21ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_fib_with_bal/stream/4fb_x_250tx                   1.00     55.9±0.20ms        ? ?/sec    1.01     56.3±0.32ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_fib_with_bal/stream/4fb_x_50tx                    1.01     13.7±0.12ms        ? ?/sec    1.00     13.6±0.34ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254/stream/4fb_x_10tx             1.00    136.1±0.40ms        ? ?/sec    1.00    136.0±0.39ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254/stream/4fb_x_12tx             1.00    163.4±0.52ms        ? ?/sec    1.00    163.1±0.54ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254/stream/4fb_x_5tx              1.00     68.8±0.21ms        ? ?/sec    1.00     68.5±0.18ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254_with_bal/stream/4fb_x_10tx    1.00     23.1±2.24ms        ? ?/sec    1.06     24.4±1.02ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254_with_bal/stream/4fb_x_12tx    1.00     27.0±0.76ms        ? ?/sec    1.00     26.9±0.29ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254_with_bal/stream/4fb_x_5tx     1.00     18.3±0.67ms        ? ?/sec    1.00     18.3±0.30ms        ? ?/sec
flashblock_validation_process_flashblock_eth_transfers/txs/1000                                    1.00     49.4±0.22ms        ? ?/sec    1.01     49.8±0.14ms        ? ?/sec
flashblock_validation_process_flashblock_eth_transfers/txs/50                                      1.00      2.7±0.01ms        ? ?/sec    1.00      2.7±0.01ms        ? ?/sec
flashblock_validation_process_flashblock_eth_transfers/txs/500                                     1.00     24.7±0.03ms        ? ?/sec    1.01     25.1±0.31ms        ? ?/sec
flashblock_validation_process_flashblock_eth_transfers_with_bal/txs/1000                           1.00     50.2±0.16ms        ? ?/sec    1.01     50.6±0.22ms        ? ?/sec
flashblock_validation_process_flashblock_eth_transfers_with_bal/txs/50                             1.01      3.2±0.05ms        ? ?/sec    1.00      3.2±0.04ms        ? ?/sec
flashblock_validation_process_flashblock_eth_transfers_with_bal/txs/500                            1.00     25.7±0.15ms        ? ?/sec    1.00     25.8±0.08ms        ? ?/sec
flashblock_validation_process_flashblock_fib/txs/1000                                              1.00     48.5±0.15ms        ? ?/sec    1.00     48.5±0.08ms        ? ?/sec
flashblock_validation_process_flashblock_fib/txs/50                                                1.00      2.6±0.01ms        ? ?/sec    1.00      2.6±0.01ms        ? ?/sec
flashblock_validation_process_flashblock_fib/txs/500                                               1.00     24.3±0.10ms        ? ?/sec    1.00     24.3±0.06ms        ? ?/sec
flashblock_validation_process_flashblock_fib_with_bal/txs/1000                                     1.00     48.9±0.11ms        ? ?/sec    1.00     48.9±0.15ms        ? ?/sec
flashblock_validation_process_flashblock_fib_with_bal/txs/50                                       1.00      3.1±0.03ms        ? ?/sec    1.01      3.1±0.06ms        ? ?/sec
flashblock_validation_process_flashblock_fib_with_bal/txs/500                                      1.00     24.9±0.07ms        ? ?/sec    1.00     24.9±0.08ms        ? ?/sec
flashblock_validation_process_flashblock_world_id_like_bn254/txs/10                                1.00     33.9±0.03ms        ? ?/sec    1.00     33.9±0.08ms        ? ?/sec
flashblock_validation_process_flashblock_world_id_like_bn254/txs/25                                1.00     84.3±0.08ms        ? ?/sec    1.00     84.4±0.24ms        ? ?/sec
flashblock_validation_process_flashblock_world_id_like_bn254/txs/50                                1.01    169.4±0.52ms        ? ?/sec    1.00    168.3±0.37ms        ? ?/sec
flashblock_validation_process_flashblock_world_id_like_bn254_with_bal/txs/10                       1.00      5.9±0.39ms        ? ?/sec    1.02      6.0±0.40ms        ? ?/sec
flashblock_validation_process_flashblock_world_id_like_bn254_with_bal/txs/25                       1.01      7.8±0.09ms        ? ?/sec    1.00      7.7±0.09ms        ? ?/sec
flashblock_validation_process_flashblock_world_id_like_bn254_with_bal/txs/50                       1.00     14.2±0.06ms        ? ?/sec    1.00     14.2±0.06ms        ? ?/sec

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant