From abf1a7e344bacd10fd1d1fd3b97c5580b69a8d6e Mon Sep 17 00:00:00 2001 From: lightsing Date: Tue, 26 Aug 2025 16:29:14 +0800 Subject: [PATCH 1/8] fix block hash assertion --- crates/bin/src/helpers/verifier.rs | 4 +- crates/core/src/error.rs | 27 +--- crates/core/src/verifier/ethereum.rs | 2 +- crates/core/src/verifier/scroll.rs | 210 ++++++++------------------- crates/primitives/src/types.rs | 10 +- 5 files changed, 78 insertions(+), 175 deletions(-) diff --git a/crates/bin/src/helpers/verifier.rs b/crates/bin/src/helpers/verifier.rs index f0a916cc..688475b5 100644 --- a/crates/bin/src/helpers/verifier.rs +++ b/crates/bin/src/helpers/verifier.rs @@ -25,12 +25,10 @@ pub fn verify_catch_panics( vec![witness], chain_spec, #[cfg(feature = "scroll")] - verifier::StateCommitMode::Block, - #[cfg(feature = "scroll")] None::>>, ) .inspect_err(|e| { - if let VerificationError::BlockRootMismatch { bundle_state, .. } = e { + if let VerificationError::RootMismatch { bundle_state, .. } = e { let dump_dir = env::temp_dir() .join("dumps") .join(format!("{chain_id}-{block_number}")); diff --git a/crates/core/src/error.rs b/crates/core/src/error.rs index f2cd6e33..fadce5bb 100644 --- a/crates/core/src/error.rs +++ b/crates/core/src/error.rs @@ -17,6 +17,9 @@ pub enum VerificationError { /// The witnesses are not sequential. #[error("witnesses are not sequential")] NonSequentialWitnesses, + /// The parent hash of a block does not match the hash of the previous block. + #[error("parent hash of a block does not match the hash of the previous block")] + ParentHashMismatch, /// Error while recovering signer from an ECDSA signature. #[error("invalid signature: {0}")] InvalidSignature(#[from] SignatureError), @@ -30,7 +33,7 @@ pub enum VerificationError { #[error( "state root in witness doesn't match with state root executed: expected {expected}, actual {actual}" )] - BlockRootMismatch { + RootMismatch { /// Root after in trace expected: B256, /// Root after in revm @@ -39,37 +42,21 @@ pub enum VerificationError { #[cfg(not(target_os = "zkvm"))] bundle_state: Box, }, - /// Root mismatch error - #[error( - "state root in last witness doesn't match with state root executed: expected {expected}, actual {actual}" - )] - ChunkRootMismatch { - /// Root after in trace - expected: B256, - /// Root after in revm - actual: B256, - }, } impl VerificationError { - /// Create a new [`VerificationError::BlockRootMismatch`] variant. + /// Create a new [`VerificationError::RootMismatch`] variant. #[inline] - pub fn block_root_mismatch( + pub fn root_mismatch( expected: B256, actual: B256, #[cfg(not(target_os = "zkvm"))] bundle_state: impl Into>, ) -> Self { - VerificationError::BlockRootMismatch { + VerificationError::RootMismatch { expected, actual, #[cfg(not(target_os = "zkvm"))] bundle_state: bundle_state.into(), } } - - /// Create a new [`VerificationError::ChunkRootMismatch`] variant. - #[inline] - pub fn chunk_root_mismatch(expected: B256, actual: B256) -> Self { - VerificationError::ChunkRootMismatch { expected, actual } - } } diff --git a/crates/core/src/verifier/ethereum.rs b/crates/core/src/verifier/ethereum.rs index c56038e7..3c8b0fe9 100644 --- a/crates/core/src/verifier/ethereum.rs +++ b/crates/core/src/verifier/ethereum.rs @@ -78,7 +78,7 @@ pub fn run( block.state_root, post_state_root ); - return Err(VerificationError::block_root_mismatch( + return Err(VerificationError::root_mismatch( block.state_root, post_state_root, #[cfg(not(target_os = "zkvm"))] diff --git a/crates/core/src/verifier/scroll.rs b/crates/core/src/verifier/scroll.rs index e6f1c8d0..d5b81fff 100644 --- a/crates/core/src/verifier/scroll.rs +++ b/crates/core/src/verifier/scroll.rs @@ -1,8 +1,8 @@ -use crate::{DatabaseError, EvmDatabase, EvmExecutor, VerificationError}; +use crate::{EvmDatabase, EvmExecutor, VerificationError}; use itertools::Itertools; use sbv_kv::{nohash::NoHashMap, null::NullProvider}; use sbv_primitives::{ - B256, Bytes, U256, + B256, Bytes, chainspec::ChainSpec, ext::{BlockWitnessChunkExt, BlockWitnessExt}, types::{ @@ -20,6 +20,7 @@ use std::{collections::BTreeMap, sync::Arc}; derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize), rkyv(derive(Debug, Hash, PartialEq, Eq)) )] +#[deprecated(note = "StateCommitMode is no longer used and will be removed in future versions.")] pub enum StateCommitMode { /// Commit state by chunk. Chunk, @@ -48,7 +49,6 @@ pub struct VerifyResult { pub fn run( witnesses: Vec, chain_spec: Arc, - state_commit_mode: StateCommitMode, compression_ratios: Option< impl IntoIterator>> + Clone, >, @@ -68,6 +68,8 @@ pub fn run( let nodes_provider = manually_drop_on_zkvm!(nodes_provider); let pre_state_root = witnesses[0].prev_state_root; + let post_state_root = witnesses.last().unwrap().header.state_root; + let blocks = witnesses .into_iter() .map(|w| { @@ -76,39 +78,68 @@ pub fn run( }) .collect::>, _>>()?; - let mut args = ExecuteInnerArgs { - code_db: &code_db, - nodes_provider: &nodes_provider, + if !blocks + .iter() + .tuple_windows() + .all(|(a, b)| a.hash() == b.header().parent_hash) + { + return Err(VerificationError::ParentHashMismatch); + } + + let mut db = manually_drop_on_zkvm!(EvmDatabase::new_from_root( + code_db, pre_state_root, - blocks: &blocks, - chain_spec: chain_spec.clone(), - defer_commit: true, - compression_ratios, - }; + &nodes_provider, + NullProvider, + )?); + + let mut gas_used = 0; + + let mut execute_block = |block, compression_ratio| -> Result<(), VerificationError> { + let output = manually_drop_on_zkvm!( + EvmExecutor::new(chain_spec.clone(), &db, block, compression_ratio).execute()? + ); + + gas_used += output.gas_used; + + db.update( + &nodes_provider, + BTreeMap::from_iter(output.state.state.clone()).iter(), + )?; - let result = match state_commit_mode { - StateCommitMode::Chunk | StateCommitMode::Block => { - args.defer_commit = matches!(state_commit_mode, StateCommitMode::Chunk); - execute(args)? + let post_state_root = db.commit_changes(); + if block.state_root != post_state_root { + dev_error!( + "Block #{} root mismatch: root after in trace = {:x}, root after in reth = {:x}", + block.number, + block.state_root, + post_state_root + ); + return Err(VerificationError::root_mismatch( + block.state_root, + post_state_root, + #[cfg(not(target_os = "zkvm"))] + output.state, + )); } - StateCommitMode::Auto => match execute(args.clone()) { - Ok(result) => result, - Err(VerificationError::Database(DatabaseError::PartialStateTrie(_e))) => { - dev_warn!( - "Failed to execute with defer commit enabled: {_e}; retrying with defer commit disabled" - ); - #[cfg(target_os = "zkvm")] - { - println!("failed to update db: {_e}; retrying with defer commit disabled"); - } - args.defer_commit = false; - execute(args)? - } - Err(e) => return Err(e), - }, + + Ok(()) }; - let (post_state_root, withdraw_root, gas_used) = result; + if let Some(compression_ratios) = compression_ratios { + for (block, compression_ratios) in blocks.iter().zip_eq(compression_ratios) { + execute_block( + block, + Some(compression_ratios.into_iter().map(|u| u.into())), + )?; + } + } else { + for block in blocks.iter() { + execute_block(block, None)?; + } + } + + let withdraw_root = db.withdraw_root()?; Ok(VerifyResult { blocks, @@ -144,107 +175,6 @@ fn make_providers(witnesses: &[BlockWitness]) -> (CodeDb, NodesProvider) { (code_db, nodes_provider) } -#[derive(Clone)] -pub(super) struct ExecuteInnerArgs<'a, I> { - pub(super) code_db: &'a CodeDb, - pub(super) nodes_provider: &'a NodesProvider, - pub(super) pre_state_root: B256, - pub(super) blocks: &'a [RecoveredBlock], - pub(super) chain_spec: Arc, - pub(super) defer_commit: bool, - pub(super) compression_ratios: Option, -} - -#[inline] -fn execute( - ExecuteInnerArgs { - code_db, - nodes_provider, - pre_state_root, - blocks, - chain_spec, - defer_commit, - compression_ratios, - }: ExecuteInnerArgs, -) -> Result<(B256, B256, u64), VerificationError> -where - II: IntoIterator, - I: IntoIterator, - R: Into, -{ - let mut gas_used = 0; - - let mut db = manually_drop_on_zkvm!(EvmDatabase::new_from_root( - code_db, - pre_state_root, - nodes_provider, - NullProvider, - )?); - - let mut execute_block = |block, compression_ratio| -> Result<(), VerificationError> { - let output = manually_drop_on_zkvm!( - EvmExecutor::new(chain_spec.clone(), &db, block, compression_ratio).execute()? - ); - - gas_used += output.gas_used; - - db.update( - nodes_provider, - BTreeMap::from_iter(output.state.state.clone()).iter(), - )?; - - if !defer_commit { - let post_state_root = db.commit_changes(); - if block.state_root != post_state_root { - dev_error!( - "Block #{} root mismatch: root after in trace = {:x}, root after in reth = {:x}", - block.number, - block.state_root, - post_state_root - ); - return Err(VerificationError::block_root_mismatch( - block.state_root, - post_state_root, - #[cfg(not(target_os = "zkvm"))] - output.state, - )); - } - dev_info!("Block #{} verified successfully", block.number); - } else { - dev_info!("Block #{} executed successfully", block.number); - } - - Ok(()) - }; - - if let Some(compression_ratios) = compression_ratios { - for (block, compression_ratios) in blocks.iter().zip_eq(compression_ratios) { - execute_block( - block, - Some(compression_ratios.into_iter().map(|u| u.into())), - )?; - } - } else { - for block in blocks { - execute_block(block, None)?; - } - } - - let post_state_root = db.commit_changes(); - let expected_state_root = blocks.last().unwrap().state_root; - if expected_state_root != post_state_root { - dev_error!( - "Final state root mismatch: expected {expected_state_root:x}, found {post_state_root:x}", - ); - return Err(VerificationError::chunk_root_mismatch( - expected_state_root, - post_state_root, - )); - } - let withdraw_root = db.withdraw_root()?; - Ok((post_state_root, withdraw_root, gas_used)) -} - #[cfg(test)] mod tests { use super::*; @@ -264,13 +194,7 @@ mod tests { let witness: BlockWitness = serde_json::from_str(witness_json).unwrap(); let chain_spec = build_chain_spec_force_hardfork(Chain::from_id(witness.chain_id), Hardfork::EuclidV2); - run( - vec![witness], - chain_spec, - StateCommitMode::Block, - None::>>, - ) - .unwrap(); + run(vec![witness], chain_spec, None::>>).unwrap(); } #[rstest::rstest] @@ -282,12 +206,6 @@ mod tests { let witness: BlockWitness = serde_json::from_str(witness_json).unwrap(); let chain_spec = build_chain_spec_force_hardfork(Chain::from_id(witness.chain_id), Hardfork::Feynman); - run( - vec![witness], - chain_spec, - StateCommitMode::Block, - None::>>, - ) - .unwrap(); + run(vec![witness], chain_spec, None::>>).unwrap(); } } diff --git a/crates/primitives/src/types.rs b/crates/primitives/src/types.rs index f27eee50..db5b4231 100644 --- a/crates/primitives/src/types.rs +++ b/crates/primitives/src/types.rs @@ -66,7 +66,7 @@ pub mod revm { pub mod reth { /// Re-export types from `reth-primitives-types` pub mod primitives { - pub use reth_primitives::RecoveredBlock; + pub use reth_primitives::{RecoveredBlock, SealedBlock}; #[cfg(not(feature = "scroll"))] pub use reth_primitives::{Block, BlockBody, EthPrimitives, Receipt, TransactionSigned}; @@ -125,7 +125,7 @@ pub mod witness { Header, consensus::{SignerRecoverable, TxEnvelope}, eips::eip4895::Withdrawals, - reth::primitives::{Block, BlockBody, RecoveredBlock}, + reth::primitives::{Block, BlockBody, RecoveredBlock, SealedBlock}, }, }; use reth_primitives_traits::serde_bincode_compat::BincodeReprFor; @@ -210,11 +210,11 @@ pub mod witness { withdrawals: self.withdrawals, }; - Ok(RecoveredBlock::new_unhashed( - Block { + Ok(RecoveredBlock::new_sealed( + SealedBlock::seal_slow(Block { header: self.header, body, - }, + }), senders, )) } From 4ec7e7dbd40e68ee5a64f1613eb492409a6f2ccc Mon Sep 17 00:00:00 2001 From: lightsing Date: Tue, 26 Aug 2025 16:39:15 +0800 Subject: [PATCH 2/8] chunk mode ok --- crates/bin/src/helpers/verifier.rs | 8 +- crates/core/src/error.rs | 6 +- crates/core/src/verifier/scroll.rs | 212 ++++++++++++++++++++--------- 3 files changed, 158 insertions(+), 68 deletions(-) diff --git a/crates/bin/src/helpers/verifier.rs b/crates/bin/src/helpers/verifier.rs index 688475b5..0322b344 100644 --- a/crates/bin/src/helpers/verifier.rs +++ b/crates/bin/src/helpers/verifier.rs @@ -25,10 +25,16 @@ pub fn verify_catch_panics( vec![witness], chain_spec, #[cfg(feature = "scroll")] + verifier::StateCommitMode::Auto, + #[cfg(feature = "scroll")] None::>>, ) .inspect_err(|e| { - if let VerificationError::RootMismatch { bundle_state, .. } = e { + if let VerificationError::RootMismatch { + bundle_state: Some(bundle_state), + .. + } = e + { let dump_dir = env::temp_dir() .join("dumps") .join(format!("{chain_id}-{block_number}")); diff --git a/crates/core/src/error.rs b/crates/core/src/error.rs index fadce5bb..85565086 100644 --- a/crates/core/src/error.rs +++ b/crates/core/src/error.rs @@ -40,7 +40,7 @@ pub enum VerificationError { actual: B256, /// The bundle state at the time of the mismatch. #[cfg(not(target_os = "zkvm"))] - bundle_state: Box, + bundle_state: Option>, }, } @@ -50,13 +50,13 @@ impl VerificationError { pub fn root_mismatch( expected: B256, actual: B256, - #[cfg(not(target_os = "zkvm"))] bundle_state: impl Into>, + #[cfg(not(target_os = "zkvm"))] bundle_state: Option>, ) -> Self { VerificationError::RootMismatch { expected, actual, #[cfg(not(target_os = "zkvm"))] - bundle_state: bundle_state.into(), + bundle_state, } } } diff --git a/crates/core/src/verifier/scroll.rs b/crates/core/src/verifier/scroll.rs index d5b81fff..a1a4bb13 100644 --- a/crates/core/src/verifier/scroll.rs +++ b/crates/core/src/verifier/scroll.rs @@ -1,8 +1,8 @@ -use crate::{EvmDatabase, EvmExecutor, VerificationError}; +use crate::{DatabaseError, EvmDatabase, EvmExecutor, VerificationError}; use itertools::Itertools; use sbv_kv::{nohash::NoHashMap, null::NullProvider}; use sbv_primitives::{ - B256, Bytes, + B256, Bytes, U256, chainspec::ChainSpec, ext::{BlockWitnessChunkExt, BlockWitnessExt}, types::{ @@ -20,7 +20,6 @@ use std::{collections::BTreeMap, sync::Arc}; derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize), rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[deprecated(note = "StateCommitMode is no longer used and will be removed in future versions.")] pub enum StateCommitMode { /// Commit state by chunk. Chunk, @@ -49,6 +48,7 @@ pub struct VerifyResult { pub fn run( witnesses: Vec, chain_spec: Arc, + state_commit_mode: StateCommitMode, compression_ratios: Option< impl IntoIterator>> + Clone, >, @@ -68,8 +68,6 @@ pub fn run( let nodes_provider = manually_drop_on_zkvm!(nodes_provider); let pre_state_root = witnesses[0].prev_state_root; - let post_state_root = witnesses.last().unwrap().header.state_root; - let blocks = witnesses .into_iter() .map(|w| { @@ -78,68 +76,39 @@ pub fn run( }) .collect::>, _>>()?; - if !blocks - .iter() - .tuple_windows() - .all(|(a, b)| a.hash() == b.header().parent_hash) - { - return Err(VerificationError::ParentHashMismatch); - } - - let mut db = manually_drop_on_zkvm!(EvmDatabase::new_from_root( - code_db, + let mut args = ExecuteInnerArgs { + code_db: &code_db, + nodes_provider: &nodes_provider, pre_state_root, - &nodes_provider, - NullProvider, - )?); - - let mut gas_used = 0; - - let mut execute_block = |block, compression_ratio| -> Result<(), VerificationError> { - let output = manually_drop_on_zkvm!( - EvmExecutor::new(chain_spec.clone(), &db, block, compression_ratio).execute()? - ); - - gas_used += output.gas_used; - - db.update( - &nodes_provider, - BTreeMap::from_iter(output.state.state.clone()).iter(), - )?; - - let post_state_root = db.commit_changes(); - if block.state_root != post_state_root { - dev_error!( - "Block #{} root mismatch: root after in trace = {:x}, root after in reth = {:x}", - block.number, - block.state_root, - post_state_root - ); - return Err(VerificationError::root_mismatch( - block.state_root, - post_state_root, - #[cfg(not(target_os = "zkvm"))] - output.state, - )); - } - - Ok(()) + blocks: &blocks, + chain_spec: chain_spec.clone(), + defer_commit: true, + compression_ratios, }; - if let Some(compression_ratios) = compression_ratios { - for (block, compression_ratios) in blocks.iter().zip_eq(compression_ratios) { - execute_block( - block, - Some(compression_ratios.into_iter().map(|u| u.into())), - )?; + let result = match state_commit_mode { + StateCommitMode::Chunk | StateCommitMode::Block => { + args.defer_commit = matches!(state_commit_mode, StateCommitMode::Chunk); + execute(args)? } - } else { - for block in blocks.iter() { - execute_block(block, None)?; - } - } + StateCommitMode::Auto => match execute(args.clone()) { + Ok(result) => result, + Err(VerificationError::Database(DatabaseError::PartialStateTrie(_e))) => { + dev_warn!( + "Failed to execute with defer commit enabled: {_e}; retrying with defer commit disabled" + ); + #[cfg(target_os = "zkvm")] + { + println!("failed to update db: {_e}; retrying with defer commit disabled"); + } + args.defer_commit = false; + execute(args)? + } + Err(e) => return Err(e), + }, + }; - let withdraw_root = db.withdraw_root()?; + let (post_state_root, withdraw_root, gas_used) = result; Ok(VerifyResult { blocks, @@ -175,6 +144,109 @@ fn make_providers(witnesses: &[BlockWitness]) -> (CodeDb, NodesProvider) { (code_db, nodes_provider) } +#[derive(Clone)] +pub(super) struct ExecuteInnerArgs<'a, I> { + pub(super) code_db: &'a CodeDb, + pub(super) nodes_provider: &'a NodesProvider, + pub(super) pre_state_root: B256, + pub(super) blocks: &'a [RecoveredBlock], + pub(super) chain_spec: Arc, + pub(super) defer_commit: bool, + pub(super) compression_ratios: Option, +} + +#[inline] +fn execute( + ExecuteInnerArgs { + code_db, + nodes_provider, + pre_state_root, + blocks, + chain_spec, + defer_commit, + compression_ratios, + }: ExecuteInnerArgs, +) -> Result<(B256, B256, u64), VerificationError> +where + II: IntoIterator, + I: IntoIterator, + R: Into, +{ + let mut gas_used = 0; + + let mut db = manually_drop_on_zkvm!(EvmDatabase::new_from_root( + code_db, + pre_state_root, + nodes_provider, + NullProvider, + )?); + + let mut execute_block = |block, compression_ratio| -> Result<(), VerificationError> { + let output = manually_drop_on_zkvm!( + EvmExecutor::new(chain_spec.clone(), &db, block, compression_ratio).execute()? + ); + + gas_used += output.gas_used; + + db.update( + nodes_provider, + BTreeMap::from_iter(output.state.state.clone()).iter(), + )?; + + if !defer_commit { + let post_state_root = db.commit_changes(); + if block.state_root != post_state_root { + dev_error!( + "Block #{} root mismatch: root after in trace = {:x}, root after in reth = {:x}", + block.number, + block.state_root, + post_state_root + ); + return Err(VerificationError::root_mismatch( + block.state_root, + post_state_root, + #[cfg(not(target_os = "zkvm"))] + Some(Box::new(output.state)), + )); + } + dev_info!("Block #{} verified successfully", block.number); + } else { + dev_info!("Block #{} executed successfully", block.number); + } + + Ok(()) + }; + + if let Some(compression_ratios) = compression_ratios { + for (block, compression_ratios) in blocks.iter().zip_eq(compression_ratios) { + execute_block( + block, + Some(compression_ratios.into_iter().map(|u| u.into())), + )?; + } + } else { + for block in blocks { + execute_block(block, None)?; + } + } + + let post_state_root = db.commit_changes(); + let expected_state_root = blocks.last().unwrap().state_root; + if expected_state_root != post_state_root { + dev_error!( + "Final state root mismatch: expected {expected_state_root:x}, found {post_state_root:x}", + ); + return Err(VerificationError::root_mismatch( + expected_state_root, + post_state_root, + #[cfg(not(target_os = "zkvm"))] + None, + )); + } + let withdraw_root = db.withdraw_root()?; + Ok((post_state_root, withdraw_root, gas_used)) +} + #[cfg(test)] mod tests { use super::*; @@ -194,7 +266,13 @@ mod tests { let witness: BlockWitness = serde_json::from_str(witness_json).unwrap(); let chain_spec = build_chain_spec_force_hardfork(Chain::from_id(witness.chain_id), Hardfork::EuclidV2); - run(vec![witness], chain_spec, None::>>).unwrap(); + run( + vec![witness], + chain_spec, + StateCommitMode::Block, + None::>>, + ) + .unwrap(); } #[rstest::rstest] @@ -206,6 +284,12 @@ mod tests { let witness: BlockWitness = serde_json::from_str(witness_json).unwrap(); let chain_spec = build_chain_spec_force_hardfork(Chain::from_id(witness.chain_id), Hardfork::Feynman); - run(vec![witness], chain_spec, None::>>).unwrap(); + run( + vec![witness], + chain_spec, + StateCommitMode::Block, + None::>>, + ) + .unwrap(); } } From 7bc260ba0e27d41ce5184f9a243771528bed0b16 Mon Sep 17 00:00:00 2001 From: lightsing Date: Tue, 26 Aug 2025 16:45:15 +0800 Subject: [PATCH 3/8] fix ethereum mode --- crates/core/src/verifier/ethereum.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/core/src/verifier/ethereum.rs b/crates/core/src/verifier/ethereum.rs index 3c8b0fe9..52330972 100644 --- a/crates/core/src/verifier/ethereum.rs +++ b/crates/core/src/verifier/ethereum.rs @@ -82,7 +82,7 @@ pub fn run( block.state_root, post_state_root, #[cfg(not(target_os = "zkvm"))] - output.state, + Some(Box::new(output.state)), )); } dev_info!("Block #{} verified successfully", block.number); From ff8c97e439a4bcdd7dd097aa87e1bd7aed099d70 Mon Sep 17 00:00:00 2001 From: lightsing Date: Tue, 26 Aug 2025 16:47:29 +0800 Subject: [PATCH 4/8] fix revert --- crates/core/src/verifier/scroll.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/core/src/verifier/scroll.rs b/crates/core/src/verifier/scroll.rs index a1a4bb13..137f4f6c 100644 --- a/crates/core/src/verifier/scroll.rs +++ b/crates/core/src/verifier/scroll.rs @@ -76,6 +76,14 @@ pub fn run( }) .collect::>, _>>()?; + if !blocks + .iter() + .tuple_windows() + .all(|(a, b)| a.hash() == b.parent_hash) + { + return Err(VerificationError::ParentHashMismatch); + } + let mut args = ExecuteInnerArgs { code_db: &code_db, nodes_provider: &nodes_provider, From b44c8624d7597b7d37ee802ed44c2edd31bce607 Mon Sep 17 00:00:00 2001 From: lightsing Date: Tue, 26 Aug 2025 16:51:45 +0800 Subject: [PATCH 5/8] Revert "fix revert" This reverts commit ff8c97e439a4bcdd7dd097aa87e1bd7aed099d70. --- crates/core/src/verifier/scroll.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/crates/core/src/verifier/scroll.rs b/crates/core/src/verifier/scroll.rs index 137f4f6c..a1a4bb13 100644 --- a/crates/core/src/verifier/scroll.rs +++ b/crates/core/src/verifier/scroll.rs @@ -76,14 +76,6 @@ pub fn run( }) .collect::>, _>>()?; - if !blocks - .iter() - .tuple_windows() - .all(|(a, b)| a.hash() == b.parent_hash) - { - return Err(VerificationError::ParentHashMismatch); - } - let mut args = ExecuteInnerArgs { code_db: &code_db, nodes_provider: &nodes_provider, From 01644435c0a378e4c6302307016ec4d68d8dde45 Mon Sep 17 00:00:00 2001 From: lightsing Date: Tue, 26 Aug 2025 16:51:45 +0800 Subject: [PATCH 6/8] Revert "fix ethereum mode" This reverts commit 7bc260ba0e27d41ce5184f9a243771528bed0b16. --- crates/core/src/verifier/ethereum.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/core/src/verifier/ethereum.rs b/crates/core/src/verifier/ethereum.rs index 52330972..3c8b0fe9 100644 --- a/crates/core/src/verifier/ethereum.rs +++ b/crates/core/src/verifier/ethereum.rs @@ -82,7 +82,7 @@ pub fn run( block.state_root, post_state_root, #[cfg(not(target_os = "zkvm"))] - Some(Box::new(output.state)), + output.state, )); } dev_info!("Block #{} verified successfully", block.number); From 1b9aa95e992c0766d9da554c7191aa03fe4c472b Mon Sep 17 00:00:00 2001 From: lightsing Date: Tue, 26 Aug 2025 16:51:45 +0800 Subject: [PATCH 7/8] Revert "chunk mode ok" This reverts commit 4ec7e7dbd40e68ee5a64f1613eb492409a6f2ccc. --- crates/bin/src/helpers/verifier.rs | 8 +- crates/core/src/error.rs | 6 +- crates/core/src/verifier/scroll.rs | 212 +++++++++-------------------- 3 files changed, 68 insertions(+), 158 deletions(-) diff --git a/crates/bin/src/helpers/verifier.rs b/crates/bin/src/helpers/verifier.rs index 0322b344..688475b5 100644 --- a/crates/bin/src/helpers/verifier.rs +++ b/crates/bin/src/helpers/verifier.rs @@ -25,16 +25,10 @@ pub fn verify_catch_panics( vec![witness], chain_spec, #[cfg(feature = "scroll")] - verifier::StateCommitMode::Auto, - #[cfg(feature = "scroll")] None::>>, ) .inspect_err(|e| { - if let VerificationError::RootMismatch { - bundle_state: Some(bundle_state), - .. - } = e - { + if let VerificationError::RootMismatch { bundle_state, .. } = e { let dump_dir = env::temp_dir() .join("dumps") .join(format!("{chain_id}-{block_number}")); diff --git a/crates/core/src/error.rs b/crates/core/src/error.rs index 85565086..fadce5bb 100644 --- a/crates/core/src/error.rs +++ b/crates/core/src/error.rs @@ -40,7 +40,7 @@ pub enum VerificationError { actual: B256, /// The bundle state at the time of the mismatch. #[cfg(not(target_os = "zkvm"))] - bundle_state: Option>, + bundle_state: Box, }, } @@ -50,13 +50,13 @@ impl VerificationError { pub fn root_mismatch( expected: B256, actual: B256, - #[cfg(not(target_os = "zkvm"))] bundle_state: Option>, + #[cfg(not(target_os = "zkvm"))] bundle_state: impl Into>, ) -> Self { VerificationError::RootMismatch { expected, actual, #[cfg(not(target_os = "zkvm"))] - bundle_state, + bundle_state: bundle_state.into(), } } } diff --git a/crates/core/src/verifier/scroll.rs b/crates/core/src/verifier/scroll.rs index a1a4bb13..d5b81fff 100644 --- a/crates/core/src/verifier/scroll.rs +++ b/crates/core/src/verifier/scroll.rs @@ -1,8 +1,8 @@ -use crate::{DatabaseError, EvmDatabase, EvmExecutor, VerificationError}; +use crate::{EvmDatabase, EvmExecutor, VerificationError}; use itertools::Itertools; use sbv_kv::{nohash::NoHashMap, null::NullProvider}; use sbv_primitives::{ - B256, Bytes, U256, + B256, Bytes, chainspec::ChainSpec, ext::{BlockWitnessChunkExt, BlockWitnessExt}, types::{ @@ -20,6 +20,7 @@ use std::{collections::BTreeMap, sync::Arc}; derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize), rkyv(derive(Debug, Hash, PartialEq, Eq)) )] +#[deprecated(note = "StateCommitMode is no longer used and will be removed in future versions.")] pub enum StateCommitMode { /// Commit state by chunk. Chunk, @@ -48,7 +49,6 @@ pub struct VerifyResult { pub fn run( witnesses: Vec, chain_spec: Arc, - state_commit_mode: StateCommitMode, compression_ratios: Option< impl IntoIterator>> + Clone, >, @@ -68,6 +68,8 @@ pub fn run( let nodes_provider = manually_drop_on_zkvm!(nodes_provider); let pre_state_root = witnesses[0].prev_state_root; + let post_state_root = witnesses.last().unwrap().header.state_root; + let blocks = witnesses .into_iter() .map(|w| { @@ -76,39 +78,68 @@ pub fn run( }) .collect::>, _>>()?; - let mut args = ExecuteInnerArgs { - code_db: &code_db, - nodes_provider: &nodes_provider, + if !blocks + .iter() + .tuple_windows() + .all(|(a, b)| a.hash() == b.header().parent_hash) + { + return Err(VerificationError::ParentHashMismatch); + } + + let mut db = manually_drop_on_zkvm!(EvmDatabase::new_from_root( + code_db, pre_state_root, - blocks: &blocks, - chain_spec: chain_spec.clone(), - defer_commit: true, - compression_ratios, - }; + &nodes_provider, + NullProvider, + )?); + + let mut gas_used = 0; + + let mut execute_block = |block, compression_ratio| -> Result<(), VerificationError> { + let output = manually_drop_on_zkvm!( + EvmExecutor::new(chain_spec.clone(), &db, block, compression_ratio).execute()? + ); + + gas_used += output.gas_used; + + db.update( + &nodes_provider, + BTreeMap::from_iter(output.state.state.clone()).iter(), + )?; - let result = match state_commit_mode { - StateCommitMode::Chunk | StateCommitMode::Block => { - args.defer_commit = matches!(state_commit_mode, StateCommitMode::Chunk); - execute(args)? + let post_state_root = db.commit_changes(); + if block.state_root != post_state_root { + dev_error!( + "Block #{} root mismatch: root after in trace = {:x}, root after in reth = {:x}", + block.number, + block.state_root, + post_state_root + ); + return Err(VerificationError::root_mismatch( + block.state_root, + post_state_root, + #[cfg(not(target_os = "zkvm"))] + output.state, + )); } - StateCommitMode::Auto => match execute(args.clone()) { - Ok(result) => result, - Err(VerificationError::Database(DatabaseError::PartialStateTrie(_e))) => { - dev_warn!( - "Failed to execute with defer commit enabled: {_e}; retrying with defer commit disabled" - ); - #[cfg(target_os = "zkvm")] - { - println!("failed to update db: {_e}; retrying with defer commit disabled"); - } - args.defer_commit = false; - execute(args)? - } - Err(e) => return Err(e), - }, + + Ok(()) }; - let (post_state_root, withdraw_root, gas_used) = result; + if let Some(compression_ratios) = compression_ratios { + for (block, compression_ratios) in blocks.iter().zip_eq(compression_ratios) { + execute_block( + block, + Some(compression_ratios.into_iter().map(|u| u.into())), + )?; + } + } else { + for block in blocks.iter() { + execute_block(block, None)?; + } + } + + let withdraw_root = db.withdraw_root()?; Ok(VerifyResult { blocks, @@ -144,109 +175,6 @@ fn make_providers(witnesses: &[BlockWitness]) -> (CodeDb, NodesProvider) { (code_db, nodes_provider) } -#[derive(Clone)] -pub(super) struct ExecuteInnerArgs<'a, I> { - pub(super) code_db: &'a CodeDb, - pub(super) nodes_provider: &'a NodesProvider, - pub(super) pre_state_root: B256, - pub(super) blocks: &'a [RecoveredBlock], - pub(super) chain_spec: Arc, - pub(super) defer_commit: bool, - pub(super) compression_ratios: Option, -} - -#[inline] -fn execute( - ExecuteInnerArgs { - code_db, - nodes_provider, - pre_state_root, - blocks, - chain_spec, - defer_commit, - compression_ratios, - }: ExecuteInnerArgs, -) -> Result<(B256, B256, u64), VerificationError> -where - II: IntoIterator, - I: IntoIterator, - R: Into, -{ - let mut gas_used = 0; - - let mut db = manually_drop_on_zkvm!(EvmDatabase::new_from_root( - code_db, - pre_state_root, - nodes_provider, - NullProvider, - )?); - - let mut execute_block = |block, compression_ratio| -> Result<(), VerificationError> { - let output = manually_drop_on_zkvm!( - EvmExecutor::new(chain_spec.clone(), &db, block, compression_ratio).execute()? - ); - - gas_used += output.gas_used; - - db.update( - nodes_provider, - BTreeMap::from_iter(output.state.state.clone()).iter(), - )?; - - if !defer_commit { - let post_state_root = db.commit_changes(); - if block.state_root != post_state_root { - dev_error!( - "Block #{} root mismatch: root after in trace = {:x}, root after in reth = {:x}", - block.number, - block.state_root, - post_state_root - ); - return Err(VerificationError::root_mismatch( - block.state_root, - post_state_root, - #[cfg(not(target_os = "zkvm"))] - Some(Box::new(output.state)), - )); - } - dev_info!("Block #{} verified successfully", block.number); - } else { - dev_info!("Block #{} executed successfully", block.number); - } - - Ok(()) - }; - - if let Some(compression_ratios) = compression_ratios { - for (block, compression_ratios) in blocks.iter().zip_eq(compression_ratios) { - execute_block( - block, - Some(compression_ratios.into_iter().map(|u| u.into())), - )?; - } - } else { - for block in blocks { - execute_block(block, None)?; - } - } - - let post_state_root = db.commit_changes(); - let expected_state_root = blocks.last().unwrap().state_root; - if expected_state_root != post_state_root { - dev_error!( - "Final state root mismatch: expected {expected_state_root:x}, found {post_state_root:x}", - ); - return Err(VerificationError::root_mismatch( - expected_state_root, - post_state_root, - #[cfg(not(target_os = "zkvm"))] - None, - )); - } - let withdraw_root = db.withdraw_root()?; - Ok((post_state_root, withdraw_root, gas_used)) -} - #[cfg(test)] mod tests { use super::*; @@ -266,13 +194,7 @@ mod tests { let witness: BlockWitness = serde_json::from_str(witness_json).unwrap(); let chain_spec = build_chain_spec_force_hardfork(Chain::from_id(witness.chain_id), Hardfork::EuclidV2); - run( - vec![witness], - chain_spec, - StateCommitMode::Block, - None::>>, - ) - .unwrap(); + run(vec![witness], chain_spec, None::>>).unwrap(); } #[rstest::rstest] @@ -284,12 +206,6 @@ mod tests { let witness: BlockWitness = serde_json::from_str(witness_json).unwrap(); let chain_spec = build_chain_spec_force_hardfork(Chain::from_id(witness.chain_id), Hardfork::Feynman); - run( - vec![witness], - chain_spec, - StateCommitMode::Block, - None::>>, - ) - .unwrap(); + run(vec![witness], chain_spec, None::>>).unwrap(); } } From 499c28de3328dce43a0ded419fab77ff8da986fa Mon Sep 17 00:00:00 2001 From: lightsing Date: Thu, 28 Aug 2025 12:33:18 +0800 Subject: [PATCH 8/8] fix --- crates/core/src/verifier/scroll.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/core/src/verifier/scroll.rs b/crates/core/src/verifier/scroll.rs index d5b81fff..0e48faab 100644 --- a/crates/core/src/verifier/scroll.rs +++ b/crates/core/src/verifier/scroll.rs @@ -20,7 +20,6 @@ use std::{collections::BTreeMap, sync::Arc}; derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize), rkyv(derive(Debug, Hash, PartialEq, Eq)) )] -#[deprecated(note = "StateCommitMode is no longer used and will be removed in future versions.")] pub enum StateCommitMode { /// Commit state by chunk. Chunk,