diff --git a/crates/blockifier_reexecution/src/main.rs b/crates/blockifier_reexecution/src/main.rs index 4e76297ea3..205f4dd96b 100644 --- a/crates/blockifier_reexecution/src/main.rs +++ b/crates/blockifier_reexecution/src/main.rs @@ -1,14 +1,13 @@ -use blockifier::state::cached_state::CachedState; -use blockifier::state::state_api::StateReader; -use blockifier_reexecution::assert_eq_state_diff; use blockifier_reexecution::state_reader::test_state_reader::{ - ConsecutiveStateReaders, ConsecutiveTestStateReaders, OfflineConsecutiveStateReaders, SerializableDataPrevBlock, SerializableOfflineReexecutionData, }; -use blockifier_reexecution::state_reader::utils::JSON_RPC_VERSION; +use blockifier_reexecution::state_reader::utils::{ + reexecute_and_verify_correctness, + JSON_RPC_VERSION, +}; use clap::{Args, Parser, Subcommand}; use starknet_api::block::BlockNumber; use starknet_gateway::config::RpcStateReaderConfig; @@ -69,26 +68,6 @@ enum Command { #[derive(Debug, Args)] struct GlobalOptions {} -pub fn reexecution_test>( - consecutive_state_readers: T, -) -> Option> { - let expected_state_diff = consecutive_state_readers.get_next_block_state_diff().unwrap(); - - let all_txs_in_next_block = consecutive_state_readers.get_next_block_txs().unwrap(); - - let mut transaction_executor = - consecutive_state_readers.get_transaction_executor(None).unwrap(); - - transaction_executor.execute_txs(&all_txs_in_next_block); - // Finalize block and read actual statediff. - let (actual_state_diff, _, _) = - transaction_executor.finalize().expect("Couldn't finalize block"); - - assert_eq_state_diff!(expected_state_diff, actual_state_diff); - - transaction_executor.block_state -} - /// Main entry point of the blockifier reexecution CLI. fn main() { let args = BlockifierReexecutionCliArgs::parse(); @@ -102,7 +81,7 @@ fn main() { json_rpc_version: JSON_RPC_VERSION.to_string(), }; - reexecution_test(ConsecutiveTestStateReaders::new( + reexecute_and_verify_correctness(ConsecutiveTestStateReaders::new( BlockNumber(block_number - 1), Some(config), false, @@ -133,7 +112,7 @@ fn main() { let old_block_hash = consecutive_state_readers.get_old_block_hash().unwrap(); // Run the reexecution test and get the state maps and contract class mapping. - let block_state = reexecution_test(consecutive_state_readers).unwrap(); + let block_state = reexecute_and_verify_correctness(consecutive_state_readers).unwrap(); let serializable_data_prev_block = SerializableDataPrevBlock { state_maps: block_state.get_initial_reads().unwrap().into(), contract_class_mapping: block_state @@ -161,7 +140,7 @@ fn main() { "./crates/blockifier_reexecution/resources/block_{block_number}" )) + "/reexecution_data.json"; - reexecution_test( + reexecute_and_verify_correctness( OfflineConsecutiveStateReaders::new_from_file(&full_file_path).unwrap(), ); diff --git a/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs b/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs index 50b4802fc4..2500e748be 100644 --- a/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs +++ b/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs @@ -88,16 +88,16 @@ pub struct SerializableOfflineReexecutionData { impl SerializableOfflineReexecutionData { pub fn write_to_file(&self, file_path: &str, file_name: &str) -> ReexecutionResult<()> { fs::create_dir_all(file_path) - .unwrap_or_else(|_| panic!("Failed to create directory {file_path}.")); + .unwrap_or_else(|err| panic!("Failed to create directory {file_path}. Error: {err}")); let full_file_path = file_path.to_owned() + "/" + file_name; fs::write(full_file_path.clone(), serde_json::to_string_pretty(&self)?) - .unwrap_or_else(|_| panic!("Failed to write to file {full_file_path}.")); + .unwrap_or_else(|err| panic!("Failed to write to file {full_file_path}. Error: {err}")); Ok(()) } pub fn read_from_file(full_file_path: &str) -> ReexecutionResult { - let file_content = fs::read_to_string(full_file_path).unwrap_or_else(|_| { - panic!("Failed to read reexecution data from file {full_file_path}.") + let file_content = fs::read_to_string(full_file_path).unwrap_or_else(|err| { + panic!("Failed to read reexecution data from file {full_file_path}. Error: {err}") }); Ok(serde_json::from_str(&file_content)?) } diff --git a/crates/blockifier_reexecution/src/state_reader/utils.rs b/crates/blockifier_reexecution/src/state_reader/utils.rs index 11bdf0f035..81349c190b 100644 --- a/crates/blockifier_reexecution/src/state_reader/utils.rs +++ b/crates/blockifier_reexecution/src/state_reader/utils.rs @@ -1,7 +1,8 @@ use std::collections::{BTreeMap, HashMap}; use blockifier::context::{ChainInfo, FeeTokenAddresses}; -use blockifier::state::cached_state::{CommitmentStateDiff, StateMaps}; +use blockifier::state::cached_state::{CachedState, CommitmentStateDiff, StateMaps}; +use blockifier::state::state_api::StateReader; use indexmap::IndexMap; use papyrus_execution::{ETH_FEE_CONTRACT_ADDRESS, STRK_FEE_CONTRACT_ADDRESS}; use pretty_assertions::assert_eq; @@ -13,7 +14,12 @@ use starknet_api::test_utils::read_json_file; use starknet_gateway::config::RpcStateReaderConfig; use starknet_types_core::felt::Felt; +use crate::assert_eq_state_diff; use crate::state_reader::errors::ReexecutionError; +use crate::state_reader::test_state_reader::{ + ConsecutiveStateReaders, + OfflineConsecutiveStateReaders, +}; pub const RPC_NODE_URL: &str = "https://free-rpc.nethermind.io/mainnet-juno/"; pub const JSON_RPC_VERSION: &str = "2.0"; @@ -166,17 +172,47 @@ impl From for ComparableStateDiff { } } +pub fn reexecute_and_verify_correctness< + S: StateReader + Send + Sync, + T: ConsecutiveStateReaders, +>( + consecutive_state_readers: T, +) -> Option> { + let expected_state_diff = consecutive_state_readers.get_next_block_state_diff().unwrap(); + + let all_txs_in_next_block = consecutive_state_readers.get_next_block_txs().unwrap(); + + let mut transaction_executor = + consecutive_state_readers.get_transaction_executor(None).unwrap(); + + transaction_executor.execute_txs(&all_txs_in_next_block); + // Finalize block and read actual statediff. + let (actual_state_diff, _, _) = + transaction_executor.finalize().expect("Couldn't finalize block"); + + assert_eq_state_diff!(expected_state_diff, actual_state_diff); + + transaction_executor.block_state +} + +pub fn reexecute_block_for_testing(block_number: u64) { + // In tests we are already in the blockifier_reexecution directory. + let full_file_path = format!("./resources/block_{block_number}/reexecution_data.json"); + + reexecute_and_verify_correctness( + OfflineConsecutiveStateReaders::new_from_file(&full_file_path).unwrap(), + ); + + println!("Reexecution test for block {block_number} passed successfully."); +} + /// Asserts equality between two `CommitmentStateDiff` structs, ignoring insertion order. #[macro_export] macro_rules! assert_eq_state_diff { ($expected_state_diff:expr, $actual_state_diff:expr $(,)?) => { pretty_assertions::assert_eq!( - blockifier_reexecution::state_reader::utils::ComparableStateDiff::from( - $expected_state_diff, - ), - blockifier_reexecution::state_reader::utils::ComparableStateDiff::from( - $actual_state_diff, - ), + $crate::state_reader::utils::ComparableStateDiff::from($expected_state_diff,), + $crate::state_reader::utils::ComparableStateDiff::from($actual_state_diff,), "Expected and actual state diffs do not match.", ); };