From 2c95d3bc81bce0f7d45d4ac1244854d01da4013f Mon Sep 17 00:00:00 2001 From: Aner Ben Efraim Date: Sun, 3 Nov 2024 14:16:50 +0200 Subject: [PATCH] chore(blockifier_reexecution): serialize reexecution data to file --- crates/blockifier/Cargo.toml | 1 + crates/blockifier/src/state/cached_state.rs | 7 ++ crates/blockifier_reexecution/Cargo.toml | 2 +- crates/blockifier_reexecution/src/main.rs | 65 ++++++++++++++++++- .../state_reader/reexecution_state_reader.rs | 4 +- .../src/state_reader/rpc_https_test.rs | 4 +- .../src/state_reader/test_state_reader.rs | 23 ++++--- .../src/state_reader/utils.rs | 2 +- 8 files changed, 93 insertions(+), 15 deletions(-) diff --git a/crates/blockifier/Cargo.toml b/crates/blockifier/Cargo.toml index 69bfac8392..91a021fb75 100644 --- a/crates/blockifier/Cargo.toml +++ b/crates/blockifier/Cargo.toml @@ -12,6 +12,7 @@ workspace = true [features] cairo_native = ["dep:cairo-native"] jemalloc = ["dep:tikv-jemallocator"] +reexecution = ["transaction_serde"] testing = ["rand", "rstest", "starknet_api/testing"] transaction_serde = [] diff --git a/crates/blockifier/src/state/cached_state.rs b/crates/blockifier/src/state/cached_state.rs index d9a4a598f6..f78f1b5307 100644 --- a/crates/blockifier/src/state/cached_state.rs +++ b/crates/blockifier/src/state/cached_state.rs @@ -294,6 +294,13 @@ impl Default for CachedState CachedState { + pub fn get_initial_reads(&self) -> StateResult { + Ok(self.cache.borrow().initial_reads.clone()) + } +} + pub type StorageEntry = (ContractAddress, StorageKey); #[derive(Debug, Default, derive_more::IntoIterator)] diff --git a/crates/blockifier_reexecution/Cargo.toml b/crates/blockifier_reexecution/Cargo.toml index dcf234df12..c6e61486c7 100644 --- a/crates/blockifier_reexecution/Cargo.toml +++ b/crates/blockifier_reexecution/Cargo.toml @@ -9,7 +9,7 @@ license.workspace = true blockifier_regression_https_testing = [] [dependencies] -blockifier = { workspace = true, features = ["transaction_serde"] } +blockifier = { workspace = true, features = ["reexecution"] } cairo-lang-starknet-classes.workspace = true cairo-lang-utils.workspace = true clap = { workspace = true, features = ["cargo", "derive"] } diff --git a/crates/blockifier_reexecution/src/main.rs b/crates/blockifier_reexecution/src/main.rs index fa55a680db..7cecf38ac7 100644 --- a/crates/blockifier_reexecution/src/main.rs +++ b/crates/blockifier_reexecution/src/main.rs @@ -1,7 +1,9 @@ use blockifier_reexecution::assert_eq_state_diff; +use blockifier_reexecution::state_reader::reexecution_state_reader::ReexecutionStateReader; use blockifier_reexecution::state_reader::test_state_reader::{ ConsecutiveStateReaders, ConsecutiveTestStateReaders, + SerializableOfflineReexecutionData, }; use blockifier_reexecution::state_reader::utils::JSON_RPC_VERSION; use clap::{Args, Parser, Subcommand}; @@ -92,6 +94,67 @@ fn main() { assert_eq_state_diff!(expected_state_diff, actual_state_diff); println!("RPC test passed successfully."); } - Command::WriteRpcRepliesToJson { .. } => todo!(), + + Command::WriteRpcRepliesToJson { + url_and_block_number: SharedArgs { node_url, block_number }, + directory_path, + } => { + let directory_path = directory_path.unwrap_or(format!( + "./crates/blockifier_reexecution/resources/block_{block_number}/" + )); + + // TODO(Aner): refactor to reduce code duplication. + let config = RpcStateReaderConfig { + url: node_url, + json_rpc_version: JSON_RPC_VERSION.to_string(), + }; + + let ConsecutiveTestStateReaders { last_block_state_reader, next_block_state_reader } = + ConsecutiveTestStateReaders::new(BlockNumber(block_number - 1), Some(config), true); + + let block_info_next_block = next_block_state_reader.get_block_info().unwrap(); + + let starknet_version = next_block_state_reader.get_starknet_version().unwrap(); + + let state_diff_next_block = next_block_state_reader.get_state_diff().unwrap(); + + let transactions_next_block = next_block_state_reader.get_all_txs_in_block().unwrap(); + + let blockifier_transactions_next_block = &last_block_state_reader + .api_txs_to_blockifier_txs_next_block(transactions_next_block.clone()) + .unwrap(); + + let mut transaction_executor = last_block_state_reader + .get_transaction_executor( + next_block_state_reader.get_block_context().unwrap(), + None, + ) + .unwrap(); + + transaction_executor.execute_txs(blockifier_transactions_next_block); + + let block_state = transaction_executor.block_state.unwrap(); + let initial_reads = block_state.get_initial_reads().unwrap(); + + let contract_class_mapping = + block_state.state.get_contract_class_mapping_dumper().unwrap(); + + let serializable_offline_reexecution_data = SerializableOfflineReexecutionData { + state_maps: initial_reads.into(), + block_info_next_block, + starknet_version, + transactions_next_block, + contract_class_mapping, + state_diff_next_block, + }; + + serializable_offline_reexecution_data + .write_to_file(&directory_path, "reexecution_data.json") + .unwrap(); + + println!( + "RPC replies required for reexecuting block {block_number} written to json file." + ); + } } } diff --git a/crates/blockifier_reexecution/src/state_reader/reexecution_state_reader.rs b/crates/blockifier_reexecution/src/state_reader/reexecution_state_reader.rs index 2a4aa61909..b2b4eba74d 100644 --- a/crates/blockifier_reexecution/src/state_reader/reexecution_state_reader.rs +++ b/crates/blockifier_reexecution/src/state_reader/reexecution_state_reader.rs @@ -12,7 +12,7 @@ use super::compile::{legacy_to_contract_class_v0, sierra_to_contact_class_v1}; use crate::state_reader::errors::ReexecutionError; use crate::state_reader::test_state_reader::ReexecutionResult; -pub(crate) trait ReexecutionStateReader { +pub trait ReexecutionStateReader { fn get_contract_class(&self, class_hash: &ClassHash) -> StateResult; fn get_class_info(&self, class_hash: ClassHash) -> ReexecutionResult { @@ -35,7 +35,7 @@ pub(crate) trait ReexecutionStateReader { } // TODO(Aner): extend/refactor to accomodate all types of transactions. - fn api_txs_to_blockifier_txs( + fn api_txs_to_blockifier_txs_next_block( &self, txs_and_hashes: Vec<(Transaction, TransactionHash)>, ) -> ReexecutionResult> { diff --git a/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs b/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs index cf05977972..bfe5c4fc65 100644 --- a/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs +++ b/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs @@ -200,5 +200,7 @@ pub fn test_get_statediff_rpc(test_state_reader: TestStateReader) { #[case(EXAMPLE_DECLARE_V3_BLOCK_NUMBER)] pub fn test_get_all_blockifier_tx_in_block(#[case] block_number: u64) { let state_reader = TestStateReader::new_for_testing(BlockNumber(block_number)); - state_reader.api_txs_to_blockifier_txs(state_reader.get_all_txs_in_block().unwrap()).unwrap(); + state_reader + .api_txs_to_blockifier_txs_next_block(state_reader.get_all_txs_in_block().unwrap()) + .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 c2effd18e5..18cd882ff1 100644 --- a/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs +++ b/crates/blockifier_reexecution/src/state_reader/test_state_reader.rs @@ -66,12 +66,12 @@ pub struct OfflineReexecutionData { #[derive(Serialize, Deserialize)] pub struct SerializableOfflineReexecutionData { - state_maps: ReexecutionStateMaps, - contract_class_mapping: StarknetContractClassMapping, - block_info_next_block: BlockInfo, - starknet_version: StarknetVersion, - transactions_next_block: Vec<(Transaction, TransactionHash)>, - state_diff_next_block: CommitmentStateDiff, + pub state_maps: ReexecutionStateMaps, + pub block_info_next_block: BlockInfo, + pub starknet_version: StarknetVersion, + pub transactions_next_block: Vec<(Transaction, TransactionHash)>, + pub state_diff_next_block: CommitmentStateDiff, + pub contract_class_mapping: StarknetContractClassMapping, } impl SerializableOfflineReexecutionData { @@ -99,7 +99,7 @@ impl From for OfflineReexecutionData { contract_class_mapping: value.contract_class_mapping, }; let transactions_next_block = offline_state_reader_prev_block - .api_txs_to_blockifier_txs(value.transactions_next_block) + .api_txs_to_blockifier_txs_next_block(value.transactions_next_block) .expect("Failed to convert starknet-api transactions to blockifier transactions."); Self { offline_state_reader_prev_block, @@ -361,6 +361,10 @@ impl TestStateReader { class_hash_to_compiled_class_hash: declared_classes, }) } + + pub fn get_contract_class_mapping_dumper(&self) -> Option { + self.contract_class_mapping_dumper.lock().unwrap().clone() + } } impl ReexecutionStateReader for TestStateReader { @@ -449,8 +453,9 @@ impl ConsecutiveStateReaders for ConsecutiveTestStateReaders { } fn get_next_block_txs(&self) -> ReexecutionResult> { - self.next_block_state_reader - .api_txs_to_blockifier_txs(self.next_block_state_reader.get_all_txs_in_block()?) + self.next_block_state_reader.api_txs_to_blockifier_txs_next_block( + self.next_block_state_reader.get_all_txs_in_block()?, + ) } fn get_next_block_state_diff(&self) -> ReexecutionResult { diff --git a/crates/blockifier_reexecution/src/state_reader/utils.rs b/crates/blockifier_reexecution/src/state_reader/utils.rs index 68cc27b45c..11bdf0f035 100644 --- a/crates/blockifier_reexecution/src/state_reader/utils.rs +++ b/crates/blockifier_reexecution/src/state_reader/utils.rs @@ -52,7 +52,7 @@ pub(crate) fn disjoint_hashmap_union( } #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub(crate) struct ReexecutionStateMaps { +pub struct ReexecutionStateMaps { nonces: HashMap, class_hashes: HashMap, storage: HashMap>,