From 46443d508e8e4082ac8decdaa44d1a3e9b06decd Mon Sep 17 00:00:00 2001 From: itschaindev Date: Mon, 12 Jan 2026 13:26:03 +0530 Subject: [PATCH 1/6] add verification interval for full block execution --- Cargo.lock | 1 - crates/optimism/bin/src/main.rs | 18 +++++++- crates/optimism/exex/Cargo.toml | 1 - crates/optimism/exex/src/lib.rs | 79 +++++++++++++++++++++++++++------ 4 files changed, 82 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 352dcf9815e..9adeae1b05e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9844,7 +9844,6 @@ version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", - "derive_more", "eyre", "futures", "futures-util", diff --git a/crates/optimism/bin/src/main.rs b/crates/optimism/bin/src/main.rs index 80048eae334..9b462f7874b 100644 --- a/crates/optimism/bin/src/main.rs +++ b/crates/optimism/bin/src/main.rs @@ -77,7 +77,21 @@ struct Args { value_parser = humantime::parse_duration )] pub proofs_history_prune_interval: Duration, -} + /// Verification interval: perform full block execution every N blocks for data integrity. + /// - 0: Disabled (always use fast path with pre-computed data from notifications) + /// - 1: Always verify (always execute blocks, slowest) + /// - N: Verify every Nth block (e.g., 100 = every 100 blocks) + /// + /// Periodic verification helps catch data corruption or consensus bugs while maintaining + /// good performance. Recommended values: 100-1000 for production. + /// + /// CLI: `--proofs-history.verification-interval 100` + #[arg( + long = "proofs-history.verification-interval", + value_name = "PROOFS_HISTORY_VERIFICATION_INTERVAL", + default_value_t = 0 + )] + pub proofs_history_verification_interval: u64,} /// Single entry that handles: /// - no proofs history (plain node), @@ -91,6 +105,7 @@ async fn launch_node( let rollup_args = args.rollup_args.clone(); let proofs_history_window = args.proofs_history_window; let proofs_history_prune_interval = args.proofs_history_prune_interval; + let proofs_history_verification_interval = args.proofs_history_verification_interval; // Start from a plain OpNode builder let mut node_builder = builder.node(OpNode::new(rollup_args)); @@ -125,6 +140,7 @@ async fn launch_node( storage_exec, proofs_history_window, proofs_history_prune_interval, + proofs_history_verification_interval, ) .run() .boxed()) diff --git a/crates/optimism/exex/Cargo.toml b/crates/optimism/exex/Cargo.toml index a182431e27e..cd5f8b2a760 100644 --- a/crates/optimism/exex/Cargo.toml +++ b/crates/optimism/exex/Cargo.toml @@ -31,7 +31,6 @@ alloy-eips.workspace = true # misc eyre.workspace = true futures-util.workspace = true -derive_more.workspace = true tracing.workspace = true [dev-dependencies] diff --git a/crates/optimism/exex/src/lib.rs b/crates/optimism/exex/src/lib.rs index 1b6c6f61760..979355caea9 100644 --- a/crates/optimism/exex/src/lib.rs +++ b/crates/optimism/exex/src/lib.rs @@ -10,7 +10,6 @@ use alloy_consensus::BlockHeader; use alloy_eips::eip1898::BlockWithParent; -use derive_more::Constructor; use futures_util::TryStreamExt; use reth_execution_types::Chain; use reth_exex::{ExExContext, ExExEvent, ExExNotification}; @@ -72,6 +71,10 @@ const MAX_PRUNE_BLOCKS_STARTUP: u64 = 1000; /// let storage_exec = storage.clone(); /// let proofs_history_window = 1_296_000u64; /// let proofs_history_prune_interval = Duration::from_secs(3600); +/// +/// // Verification interval: perform full execution every N blocks +/// let verification_interval = 0; // 0 = disabled, 100 = verify every 100 blocks +/// /// // Can also use install_exex_if along with a boolean flag /// // Set this based on your configuration or CLI args /// let _builder = NodeBuilder::new(config) @@ -84,6 +87,7 @@ const MAX_PRUNE_BLOCKS_STARTUP: u64 = 1000; /// storage_exec, /// proofs_history_window, /// proofs_history_prune_interval, +/// verification_interval, // 0 = no verification, 100 = every 100 blocks /// ) /// .run() /// .boxed()) @@ -91,7 +95,7 @@ const MAX_PRUNE_BLOCKS_STARTUP: u64 = 1000; /// .on_node_started(|_full_node| Ok(())) /// .check_launch(); /// ``` -#[derive(Debug, Constructor)] +#[derive(Debug)] pub struct OpProofsExEx where Node: FullNodeComponents, @@ -106,6 +110,39 @@ where proofs_history_window: u64, /// Interval between proof-storage prune runs proofs_history_prune_interval: Duration, + /// Verification interval: perform full block execution every N blocks for data integrity. + /// If 0, verification is disabled (always use fast path when available). + /// If 1, verification is always enabled (always execute blocks). + verification_interval: u64, +} + +impl OpProofsExEx +where + Node: FullNodeComponents, +{ + /// Create a new OpProofsExEx instance. + /// + /// # Arguments + /// + /// * `verification_interval` - Perform full block execution every N blocks for data integrity. + /// - 0: Never verify (always use fast path when available) + /// - 1: Always verify (always execute blocks) + /// - N: Verify every Nth block (e.g., 100, 1000) + pub fn new( + ctx: ExExContext, + storage: OpProofsStorage, + proofs_history_window: u64, + proofs_history_prune_interval: Duration, + verification_interval: u64, + ) -> Self { + Self { + ctx, + storage, + proofs_history_window, + proofs_history_prune_interval, + verification_interval, + } + } } impl OpProofsExEx @@ -266,6 +303,10 @@ where chain: &Chain, collector: &LiveTrieCollector<'_, Node::Evm, Node::Provider, Storage>, ) -> eyre::Result<()> { + // Check if this block should be verified via full execution + let should_verify = self.verification_interval > 0 && + block_number % self.verification_interval == 0; + // Try to get block data from the chain first // 1. Fast Path: Try to use pre-computed state from the notification if let Some(block) = chain.blocks().get(&block_number) { @@ -274,21 +315,31 @@ where if let (Some(trie_updates), Some(hashed_state)) = (chain.trie_updates_at(block_number), chain.hashed_state_at(block_number)) { - debug!( + // Use fast path only if we're not scheduled to verify this block + if !should_verify { + debug!( + target: "optimism::exex", + block_number, + "Using pre-computed state updates from notification" + ); + + collector + .store_block_updates( + block.block_with_parent(), + (**trie_updates).clone(), + (**hashed_state).clone(), + ) + .await?; + + return Ok(()); + } + + info!( target: "optimism::exex", block_number, - "Using pre-computed state updates from notification" + verification_interval = self.verification_interval, + "Periodic verification: performing full block execution" ); - - collector - .store_block_updates( - block.block_with_parent(), - (**trie_updates).clone(), - (**hashed_state).clone(), - ) - .await?; - - return Ok(()); } debug!( From df6e864873a4e5210b13909b716e33dd7e83ec5b Mon Sep 17 00:00:00 2001 From: itschaindev Date: Mon, 12 Jan 2026 13:32:43 +0530 Subject: [PATCH 2/6] fix lint --- crates/optimism/bin/src/main.rs | 3 ++- crates/optimism/exex/src/lib.rs | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/optimism/bin/src/main.rs b/crates/optimism/bin/src/main.rs index 9b462f7874b..e7fbd15267c 100644 --- a/crates/optimism/bin/src/main.rs +++ b/crates/optimism/bin/src/main.rs @@ -91,7 +91,8 @@ struct Args { value_name = "PROOFS_HISTORY_VERIFICATION_INTERVAL", default_value_t = 0 )] - pub proofs_history_verification_interval: u64,} + pub proofs_history_verification_interval: u64, +} /// Single entry that handles: /// - no proofs history (plain node), diff --git a/crates/optimism/exex/src/lib.rs b/crates/optimism/exex/src/lib.rs index 979355caea9..11781dc44a4 100644 --- a/crates/optimism/exex/src/lib.rs +++ b/crates/optimism/exex/src/lib.rs @@ -120,7 +120,7 @@ impl OpProofsExEx where Node: FullNodeComponents, { - /// Create a new OpProofsExEx instance. + /// Create a new `OpProofsExEx` instance. /// /// # Arguments /// @@ -128,7 +128,7 @@ where /// - 0: Never verify (always use fast path when available) /// - 1: Always verify (always execute blocks) /// - N: Verify every Nth block (e.g., 100, 1000) - pub fn new( + pub const fn new( ctx: ExExContext, storage: OpProofsStorage, proofs_history_window: u64, @@ -305,7 +305,7 @@ where ) -> eyre::Result<()> { // Check if this block should be verified via full execution let should_verify = self.verification_interval > 0 && - block_number % self.verification_interval == 0; + block_number.is_multiple_of(self.verification_interval); // Try to get block data from the chain first // 1. Fast Path: Try to use pre-computed state from the notification From 61c639ac829052b21ef2be4670ca1a6243e214bb Mon Sep 17 00:00:00 2001 From: itschaindev Date: Mon, 12 Jan 2026 15:49:52 +0530 Subject: [PATCH 3/6] doc fix --- docs/vocs/docs/pages/cli/op-reth/node.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/vocs/docs/pages/cli/op-reth/node.mdx b/docs/vocs/docs/pages/cli/op-reth/node.mdx index 2d3a09f4cb2..7463c3bece7 100644 --- a/docs/vocs/docs/pages/cli/op-reth/node.mdx +++ b/docs/vocs/docs/pages/cli/op-reth/node.mdx @@ -1077,7 +1077,7 @@ Rollup: [default: 1296000] --proofs-history.prune-interval - Interval between proof-storage prune runs. Accepts human-friendly durations like "100s", "5m", "1h". Defaults to 15s. + Interval between proof-storage prune runs. Accepts human-friendly durations like "100s", "5m", "1h". Defaults to 1h. - Shorter intervals prune smaller batches more often, so each prune run tends to be faster and the blocking pause for writes is shorter, at the cost of more frequent pauses. - Longer intervals prune larger batches less often, which reduces how often pruning runs, but each run can take longer and block writes for longer. @@ -1085,7 +1085,7 @@ Rollup: CLI: `--proofs-history.prune-interval 10m` - [default: 15s] + [default: 1h] Logging: --log.stdout.format From 449f0bb127a0270a892193a8924ef7c67f7f7834 Mon Sep 17 00:00:00 2001 From: itschaindev Date: Mon, 12 Jan 2026 16:25:59 +0530 Subject: [PATCH 4/6] fix doc --- docs/vocs/docs/pages/cli/op-reth/node.mdx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/vocs/docs/pages/cli/op-reth/node.mdx b/docs/vocs/docs/pages/cli/op-reth/node.mdx index 7463c3bece7..480a028e6e6 100644 --- a/docs/vocs/docs/pages/cli/op-reth/node.mdx +++ b/docs/vocs/docs/pages/cli/op-reth/node.mdx @@ -1077,7 +1077,7 @@ Rollup: [default: 1296000] --proofs-history.prune-interval - Interval between proof-storage prune runs. Accepts human-friendly durations like "100s", "5m", "1h". Defaults to 1h. + Interval between proof-storage prune runs. Accepts human-friendly durations like "100s", "5m", "1h". Defaults to 15s. - Shorter intervals prune smaller batches more often, so each prune run tends to be faster and the blocking pause for writes is shorter, at the cost of more frequent pauses. - Longer intervals prune larger batches less often, which reduces how often pruning runs, but each run can take longer and block writes for longer. @@ -1085,7 +1085,16 @@ Rollup: CLI: `--proofs-history.prune-interval 10m` - [default: 1h] + [default: 15s] + + --proofs-history.verification-interval + Verification interval: perform full block execution every N blocks for data integrity. - 0: Disabled (always use fast path with pre-computed data from notifications) - 1: Always verify (always execute blocks, slowest) - N: Verify every Nth block (e.g., 100 = every 100 blocks) + + Periodic verification helps catch data corruption or consensus bugs while maintaining good performance. Recommended values: 100-1000 for production. + + CLI: `--proofs-history.verification-interval 100` + + [default: 0] Logging: --log.stdout.format From d2c460b11973e7266c13eb18712982390eb2472b Mon Sep 17 00:00:00 2001 From: itschaindev Date: Wed, 14 Jan 2026 03:49:21 +0530 Subject: [PATCH 5/6] pr feedback --- crates/optimism/bin/src/main.rs | 4 ++-- crates/optimism/exex/src/lib.rs | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/crates/optimism/bin/src/main.rs b/crates/optimism/bin/src/main.rs index e7fbd15267c..ad574c96964 100644 --- a/crates/optimism/bin/src/main.rs +++ b/crates/optimism/bin/src/main.rs @@ -78,12 +78,12 @@ struct Args { )] pub proofs_history_prune_interval: Duration, /// Verification interval: perform full block execution every N blocks for data integrity. - /// - 0: Disabled (always use fast path with pre-computed data from notifications) + /// - 0: Disabled (Default) (always use fast path with pre-computed data from notifications) /// - 1: Always verify (always execute blocks, slowest) /// - N: Verify every Nth block (e.g., 100 = every 100 blocks) /// /// Periodic verification helps catch data corruption or consensus bugs while maintaining - /// good performance. Recommended values: 100-1000 for production. + /// good performance. /// /// CLI: `--proofs-history.verification-interval 100` #[arg( diff --git a/crates/optimism/exex/src/lib.rs b/crates/optimism/exex/src/lib.rs index 11781dc44a4..a651a98d225 100644 --- a/crates/optimism/exex/src/lib.rs +++ b/crates/optimism/exex/src/lib.rs @@ -121,13 +121,6 @@ where Node: FullNodeComponents, { /// Create a new `OpProofsExEx` instance. - /// - /// # Arguments - /// - /// * `verification_interval` - Perform full block execution every N blocks for data integrity. - /// - 0: Never verify (always use fast path when available) - /// - 1: Always verify (always execute blocks) - /// - N: Verify every Nth block (e.g., 100, 1000) pub const fn new( ctx: ExExContext, storage: OpProofsStorage, From bd111a116d7da648f4a856b3b960bdf8e915f07c Mon Sep 17 00:00:00 2001 From: Arun Dhyani Date: Wed, 14 Jan 2026 17:57:10 +0530 Subject: [PATCH 6/6] book fixes --- docs/vocs/docs/pages/cli/op-reth/node.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/vocs/docs/pages/cli/op-reth/node.mdx b/docs/vocs/docs/pages/cli/op-reth/node.mdx index 480a028e6e6..28fdcea71ee 100644 --- a/docs/vocs/docs/pages/cli/op-reth/node.mdx +++ b/docs/vocs/docs/pages/cli/op-reth/node.mdx @@ -1088,9 +1088,9 @@ Rollup: [default: 15s] --proofs-history.verification-interval - Verification interval: perform full block execution every N blocks for data integrity. - 0: Disabled (always use fast path with pre-computed data from notifications) - 1: Always verify (always execute blocks, slowest) - N: Verify every Nth block (e.g., 100 = every 100 blocks) + Verification interval: perform full block execution every N blocks for data integrity. - 0: Disabled (Default) (always use fast path with pre-computed data from notifications) - 1: Always verify (always execute blocks, slowest) - N: Verify every Nth block (e.g., 100 = every 100 blocks) - Periodic verification helps catch data corruption or consensus bugs while maintaining good performance. Recommended values: 100-1000 for production. + Periodic verification helps catch data corruption or consensus bugs while maintaining good performance. CLI: `--proofs-history.verification-interval 100`