fix(cli): wire --proofs-history into node launcher - #982
Draft
0xOsiris wants to merge 1 commit into
Draft
Conversation
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
0xOsiris
requested review from
0xForerunner,
Dzejkop,
Kemperino,
alessandromazza98,
cichaczem,
karankurbur,
kilianglas,
murph and
piohei
as code owners
August 4, 2026 22:54
0xOsiris
marked this pull request as draft
August 4, 2026 23:00
Contributor
Benchmark ResultsBase and PR measured on the same runner in the same workflow run.
Raw
|
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.
Problem
WorldChainArgsflattens op-reth'sRollupArgs, so clap accepts--proofs-history,--proofs-history.window,--proofs-history.storage-path,--proofs-history.storage-versionand
--proofs-history.verification-interval. Butbin/world-chain/src/main.rscalled the plainbuilder.node(node).launch(), andproofs_historyappeared nowhere else incrates/orbin/.An operator who set
--proofs-historygot no ExEx, no RPC override, no warning, no metric —a silent no-op. This matters right now:
eth_getProofat historical blocks is timing out onalphanet (MDBX
-96000) because reth rebuilds a revert overlay pastEPOCH_SLOTS(32 blocks)while the proof workers query ~450 blocks back.
Change
New
bin/world-chain/src/proofs_history.rsmirrorsreth_optimism_node::proof_history::launch_node. Upstream's version cannot be reused: it ishardcoded to
OpNode/OpChainSpec, while this binary launchesWorldChainNode<WorldChainDefaultContext>overWorldChainSpec.When
--proofs-historyis set the launcher:<datadir>/historical-proofs) and opensMdbxProofsStorage(v1) orMdbxProofsStorageV2(v2);proofs-historyExEx (OpProofsExEx) with the configured window andverification interval;
eth_getProof(http/ws/ipc + auth) anddebug_executePayload/debug_executionWitness(http/ws/ipc), and addsdebug_proofsSyncStatus;--metrics.push-gateway-interval.OpProofsExEx<Node, Storage>is bounded onNode: FullNodeComponents, not onOpNode, so itattaches to the World Chain node adapter without modification.
Deps added at the pinned rev
423d93e6374a65f3a83c1ed5e29c5998c972a5da:reth-optimism-exexandreth-optimism-trie, both withfeatures = ["metrics"](matchingop-reth's own
crates/node; without itOpProofsStoragedegrades to a bare type alias andDatabaseMetricsis not implemented).Flag off = unchanged
When
--proofs-historyis false the launcher does exactly whatmain.rsdid before:builder.node(node).launch()with no hooks registered. No storage is opened, no ExEx installed,no RPC method touched.
add_ons.rsinteraction (OpDebugWitnessApi)They do not conflict — the proofs-history override deliberately wins, and the ordering is
correct.
WorldChainAddOns::launch_add_onsregisters op-reth's re-execution-basedOpDebugWitnessApi(
crates/node/src/add_ons.rs:408,:448). That type only servesdebug_executePayload.ext(...)closure first, then the builder-registeredextend_rpc_moduleshooks (reth-2.3.0 crates/node/builder/src/rpc.rs:1161-1168). Our hook istherefore applied last.
replace_configured=remove_*_methods(names)thenmerge_*, so the earlier registration isremoved before ours is merged. No
RegisterMethodErrorfor a duplicate method name, and nodependence on registration order beyond "ours is last".
Net effect with the flag on:
debug_executePayloadis served from the proofs DB instead ofre-executing over a live state overlay;
debug_executionWitnessreplaces reth's stockDebugApiimplementation. With the flag off,OpDebugWitnessApibehaves exactly as today.Two consequences worth reviewing:
replace_auth_methodsonlyfor
EthApiExt. On the authenticated engine port,debug_executionWitnessremains reth'sstock re-execution implementation — only
eth_getProofis redirected to the proofs DB.replace_configuredmerges into whichever transports exist, not intowhichever namespaces were selected. With
--httpenabled,--proofs-historyexposesdebug_executePayload,debug_executionWitnessanddebug_proofsSyncStatuson HTTP/WS/IPCeven when
debugis absent from--http.api. This is upstream op-reth behaviour, but thisrepo is otherwise deliberate about namespace gating (cf. the
simulatehandling incrates/cli/src/cli.rs).Blocker before this flag is usable
crates/cli/src/app.rsrejectsCommands::OpProofs(_)("this OP-specific command is not yetsupported with WorldChainSpec"). Upstream
op_proofs::Command::executeis bounded onC: ChainSpecParser<ChainSpec = OpChainSpec>, so it cannot simply be enabled.OpProofsExEx::runstarts withensure_initialized(), which errors if the proofs DB has noproof window — and a failing ExEx panics a critical task and takes the node down. So today,
--proofs-historyon this binary turns a silent no-op into a loud startup failure. That is thecorrect direction under "no hidden failures", but the DB must be seedable before the flag is
useful. Needs a follow-up (a World Chain
proofs initpath).Upstream clap bug found while testing
RollupArgs::proofs_historydeclaresdefault_value_ifs([("proofs-history.storage-path", ArgPredicate::IsPresent, "true")]), but clapmatches
default_value_ifspredicates by arg id (storage_path, the field name), not by longname. The predicate never fires:
--proofs-history.storage-path /xalone does not enable thefeature.
proofs_history_storage_path_alone_does_not_enablepins current behaviour so a futureop-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.--proofs-history. Needs a devnet/alphanet runagainst a seeded proofs DB to confirm the ExEx attaches, the RPC overrides answer, and
eth_getProofat ~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-historyand related rollup flags were already parsed via flattenedRollupArgs, but the binary only called plainbuilder.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, installsOpProofsExEx, replaceseth_getProofand debug proof/witness RPC handlers (including auth eth), and reports proofs-DB metrics on the push-gateway interval.Workspace/binary deps add
reth-optimism-exexandreth-optimism-trie(withmetrics). CLI tests lock proofs-history default off, explicit--proofs-historyenabling it, and that--proofs-history.storage-pathalone does not turn the feature on (upstream clapdefault_value_ifsquirk).Reviewed by Cursor Bugbot for commit 420e93d. Configure here.