Skip to content

Commit b9385a5

Browse files
blockifier_reexecution: use StateReaderAndContractManager in reexecution crate
1 parent c6dfa24 commit b9385a5

File tree

6 files changed

+100
-28
lines changed

6 files changed

+100
-28
lines changed

crates/blockifier_reexecution/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ apollo_gateway_config.workspace = true
1616
apollo_rpc_execution.workspace = true
1717
apollo_sierra_compilation_config.workspace = true
1818
assert_matches.workspace = true
19-
blockifier = { workspace = true, features = ["reexecution"] }
19+
blockifier = { workspace = true, features = ["reexecution", "cairo_native"] }
2020
clap = { workspace = true, features = ["cargo", "derive"] }
2121
flate2.workspace = true
2222
google-cloud-storage.workspace = true

crates/blockifier_reexecution/src/main.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use std::fs;
22
use std::path::Path;
3+
use std::sync::Arc;
34

45
use apollo_gateway_config::config::RpcStateReaderConfig;
56
use blockifier_reexecution::state_reader::offline_state_reader::OfflineConsecutiveStateReaders;
67
use blockifier_reexecution::state_reader::test_state_reader::ConsecutiveTestStateReaders;
78
use blockifier_reexecution::state_reader::utils::{
9+
create_contract_class_manager,
810
execute_single_transaction_from_json,
911
get_block_numbers_for_reexecution,
1012
guess_chain_id_from_node_url,
@@ -197,18 +199,22 @@ async fn main() {
197199
rpc_args.node_url
198200
);
199201

200-
let config = RpcStateReaderConfig::from_url(rpc_args.node_url.clone());
202+
let rpc_state_reader_config = RpcStateReaderConfig::from_url(rpc_args.node_url.clone());
203+
let contract_class_manager = create_contract_class_manager();
201204

202205
// RPC calls are "synchronous IO" (see, e.g., https://stackoverflow.com/questions/74547541/when-should-you-use-tokios-spawn-blocking)
203206
// for details), so should be executed in a blocking thread.
204207
// TODO(Aner): make only the RPC calls blocking, not the whole function.
205208
tokio::task::spawn_blocking(move || {
206-
reexecute_and_verify_correctness(ConsecutiveTestStateReaders::new(
207-
BlockNumber(block_number - 1),
208-
Some(config),
209-
rpc_args.parse_chain_id(),
210-
false,
211-
))
209+
reexecute_and_verify_correctness(
210+
ConsecutiveTestStateReaders::new(
211+
BlockNumber(block_number - 1),
212+
Some(rpc_state_reader_config),
213+
rpc_args.parse_chain_id(),
214+
false,
215+
),
216+
&contract_class_manager,
217+
)
212218
})
213219
.await
214220
.unwrap();
@@ -227,6 +233,8 @@ async fn main() {
227233

228234
let (node_url, chain_id) = (rpc_args.node_url.clone(), rpc_args.parse_chain_id());
229235

236+
let contract_class_manager = create_contract_class_manager();
237+
230238
// RPC calls are "synchronous IO" (see, e.g., https://stackoverflow.com/questions/74547541/when-should-you-use-tokios-spawn-blocking)
231239
// for details), so should be executed in a blocking thread.
232240
// TODO(Aner): make only the RPC calls blocking, not the whole function.
@@ -236,6 +244,7 @@ async fn main() {
236244
node_url,
237245
chain_id,
238246
transaction_path,
247+
&contract_class_manager,
239248
)
240249
})
241250
.await
@@ -251,10 +260,14 @@ async fn main() {
251260
let block_numbers = parse_block_numbers_args(block_numbers);
252261
println!("Computing reexecution data for blocks {block_numbers:?}.");
253262

263+
let contract_class_manager = Arc::new(create_contract_class_manager());
264+
254265
let mut task_set = tokio::task::JoinSet::new();
255266
for block_number in block_numbers {
256267
let full_file_path = block_full_file_path(directory_path.clone(), block_number);
257268
let (node_url, chain_id) = (rpc_args.node_url.clone(), rpc_args.parse_chain_id());
269+
let contract_class_manager_shared = Arc::clone(&contract_class_manager);
270+
258271
// RPC calls are "synchronous IO" (see, e.g., https://stackoverflow.com/questions/74547541/when-should-you-use-tokios-spawn-blocking)
259272
// for details), so should be executed in a blocking thread.
260273
// TODO(Aner): make only the RPC calls blocking, not the whole function.
@@ -266,6 +279,7 @@ async fn main() {
266279
full_file_path,
267280
node_url,
268281
chain_id,
282+
&contract_class_manager_shared,
269283
)
270284
})
271285
.await
@@ -281,12 +295,16 @@ async fn main() {
281295
let block_numbers = parse_block_numbers_args(block_numbers);
282296
println!("Reexecuting blocks {block_numbers:?}.");
283297

298+
let contract_class_manager = Arc::new(create_contract_class_manager());
299+
284300
let mut task_set = tokio::task::JoinSet::new();
285301
for block in block_numbers {
286302
let full_file_path = block_full_file_path(directory_path.clone(), block);
303+
let contract_class_manager_shared = Arc::clone(&contract_class_manager);
287304
task_set.spawn(async move {
288305
reexecute_and_verify_correctness(
289306
OfflineConsecutiveStateReaders::new_from_file(&full_file_path).unwrap(),
307+
&contract_class_manager_shared,
290308
);
291309
println!("Reexecution test for block {block} passed successfully.");
292310
});

crates/blockifier_reexecution/src/state_reader/offline_state_reader.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ use blockifier::bouncer::BouncerConfig;
88
use blockifier::context::BlockContext;
99
use blockifier::execution::contract_class::RunnableCompiledClass;
1010
use blockifier::state::cached_state::{CommitmentStateDiff, StateMaps};
11+
use blockifier::state::contract_class_manager::ContractClassManager;
1112
use blockifier::state::errors::StateError;
1213
use blockifier::state::global_cache::CompiledClasses;
1314
use blockifier::state::state_api::{StateReader, StateResult};
14-
use blockifier::state::state_reader_and_contract_manager::FetchCompiledClasses;
15+
use blockifier::state::state_reader_and_contract_manager::{
16+
FetchCompiledClasses,
17+
StateReaderAndContractManager,
18+
};
1519
use blockifier::transaction::transaction_execution::Transaction as BlockifierTransaction;
1620
use serde::{Deserialize, Serialize};
1721
use starknet_api::block::{BlockHash, BlockHashAndNumber, BlockInfo, BlockNumber, StarknetVersion};
@@ -209,14 +213,20 @@ impl OfflineStateReader {
209213
self,
210214
block_context_next_block: BlockContext,
211215
transaction_executor_config: Option<TransactionExecutorConfig>,
212-
) -> ReexecutionResult<TransactionExecutor<OfflineStateReader>> {
216+
contract_class_manager: &ContractClassManager,
217+
) -> ReexecutionResult<TransactionExecutor<StateReaderAndContractManager<OfflineStateReader>>>
218+
{
213219
let old_block_number = BlockNumber(
214220
block_context_next_block.block_info().block_number.0
215221
- constants::STORED_BLOCK_HASH_BUFFER,
216222
);
217223
let hash = self.old_block_hash;
218-
Ok(TransactionExecutor::<OfflineStateReader>::pre_process_and_create(
219-
self,
224+
let state_reader_and_contract_manager = StateReaderAndContractManager {
225+
state_reader: self,
226+
contract_class_manager: contract_class_manager.clone(),
227+
};
228+
Ok(TransactionExecutor::<StateReaderAndContractManager<OfflineStateReader>>::pre_process_and_create(
229+
state_reader_and_contract_manager,
220230
block_context_next_block,
221231
Some(BlockHashAndNumber { number: old_block_number, hash }),
222232
transaction_executor_config.unwrap_or_default(),
@@ -255,13 +265,20 @@ impl OfflineConsecutiveStateReaders {
255265
}
256266
}
257267

258-
impl ConsecutiveReexecutionStateReaders<OfflineStateReader> for OfflineConsecutiveStateReaders {
268+
impl ConsecutiveReexecutionStateReaders<StateReaderAndContractManager<OfflineStateReader>>
269+
for OfflineConsecutiveStateReaders
270+
{
259271
fn pre_process_and_create_executor(
260272
self,
261273
transaction_executor_config: Option<TransactionExecutorConfig>,
262-
) -> ReexecutionResult<TransactionExecutor<OfflineStateReader>> {
263-
self.offline_state_reader_prev_block
264-
.get_transaction_executor(self.block_context_next_block, transaction_executor_config)
274+
contract_class_manager: &ContractClassManager,
275+
) -> ReexecutionResult<TransactionExecutor<StateReaderAndContractManager<OfflineStateReader>>>
276+
{
277+
self.offline_state_reader_prev_block.get_transaction_executor(
278+
self.block_context_next_block,
279+
transaction_executor_config,
280+
contract_class_manager,
281+
)
265282
}
266283

267284
fn get_next_block_txs(&self) -> ReexecutionResult<Vec<BlockifierTransaction>> {

crates/blockifier_reexecution/src/state_reader/reexecution_state_reader.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use apollo_rpc_execution::DEPRECATED_CONTRACT_SIERRA_SIZE;
22
use blockifier::blockifier::config::TransactionExecutorConfig;
33
use blockifier::blockifier::transaction_executor::TransactionExecutor;
44
use blockifier::state::cached_state::CommitmentStateDiff;
5+
use blockifier::state::contract_class_manager::ContractClassManager;
56
use blockifier::state::errors::StateError;
67
use blockifier::state::global_cache::CompiledClasses;
78
use blockifier::state::state_api::{StateReader, StateResult};
@@ -131,6 +132,7 @@ pub trait ConsecutiveReexecutionStateReaders<S: StateReader> {
131132
fn pre_process_and_create_executor(
132133
self,
133134
transaction_executor_config: Option<TransactionExecutorConfig>,
135+
contract_class_manager: &ContractClassManager,
134136
) -> ReexecutionResult<TransactionExecutor<S>>;
135137

136138
fn get_next_block_txs(&self) -> ReexecutionResult<Vec<BlockifierTransaction>>;

crates/blockifier_reexecution/src/state_reader/test_state_reader.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@ use blockifier::bouncer::BouncerConfig;
1414
use blockifier::context::BlockContext;
1515
use blockifier::execution::contract_class::RunnableCompiledClass;
1616
use blockifier::state::cached_state::CommitmentStateDiff;
17+
use blockifier::state::contract_class_manager::ContractClassManager;
1718
use blockifier::state::errors::StateError;
1819
use blockifier::state::global_cache::CompiledClasses;
1920
use blockifier::state::state_api::{StateReader, StateResult};
20-
use blockifier::state::state_reader_and_contract_manager::FetchCompiledClasses;
21+
use blockifier::state::state_reader_and_contract_manager::{
22+
FetchCompiledClasses,
23+
StateReaderAndContractManager,
24+
};
2125
use blockifier::transaction::transaction_execution::Transaction as BlockifierTransaction;
2226
use serde::Serialize;
2327
use serde_json::{json, to_value};
@@ -285,14 +289,20 @@ impl TestStateReader {
285289
self,
286290
block_context_next_block: BlockContext,
287291
transaction_executor_config: Option<TransactionExecutorConfig>,
288-
) -> ReexecutionResult<TransactionExecutor<TestStateReader>> {
292+
contract_class_manager: &ContractClassManager,
293+
) -> ReexecutionResult<TransactionExecutor<StateReaderAndContractManager<TestStateReader>>>
294+
{
289295
let old_block_number = BlockNumber(
290296
block_context_next_block.block_info().block_number.0
291297
- constants::STORED_BLOCK_HASH_BUFFER,
292298
);
293299
let old_block_hash = self.get_old_block_hash(old_block_number)?;
294-
Ok(TransactionExecutor::<TestStateReader>::pre_process_and_create(
295-
self,
300+
let state_reader_and_contract_manager = StateReaderAndContractManager {
301+
state_reader: self,
302+
contract_class_manager: contract_class_manager.clone(),
303+
};
304+
Ok(TransactionExecutor::<StateReaderAndContractManager<TestStateReader>>::pre_process_and_create(
305+
state_reader_and_contract_manager,
296306
block_context_next_block,
297307
Some(BlockHashAndNumber { number: old_block_number, hash: old_block_hash }),
298308
transaction_executor_config.unwrap_or_default(),
@@ -453,14 +463,19 @@ impl ConsecutiveTestStateReaders {
453463
}
454464
}
455465

456-
impl ConsecutiveReexecutionStateReaders<TestStateReader> for ConsecutiveTestStateReaders {
466+
impl ConsecutiveReexecutionStateReaders<StateReaderAndContractManager<TestStateReader>>
467+
for ConsecutiveTestStateReaders
468+
{
457469
fn pre_process_and_create_executor(
458470
self,
459471
transaction_executor_config: Option<TransactionExecutorConfig>,
460-
) -> ReexecutionResult<TransactionExecutor<TestStateReader>> {
472+
contract_class_manager: &ContractClassManager,
473+
) -> ReexecutionResult<TransactionExecutor<StateReaderAndContractManager<TestStateReader>>>
474+
{
461475
self.last_block_state_reader.get_transaction_executor(
462476
self.next_block_state_reader.get_block_context()?,
463477
transaction_executor_config,
478+
contract_class_manager,
464479
)
465480
}
466481

crates/blockifier_reexecution/src/state_reader/utils.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ use std::sync::LazyLock;
66
use apollo_gateway_config::config::RpcStateReaderConfig;
77
use apollo_rpc_execution::{ETH_FEE_CONTRACT_ADDRESS, STRK_FEE_CONTRACT_ADDRESS};
88
use assert_matches::assert_matches;
9+
use blockifier::blockifier::config::ContractClassManagerConfig;
910
use blockifier::context::{ChainInfo, FeeTokenAddresses};
1011
use blockifier::state::cached_state::{CachedState, CommitmentStateDiff, StateMaps};
12+
use blockifier::state::contract_class_manager::ContractClassManager;
1113
use blockifier::state::state_api::StateReader;
1214
use indexmap::IndexMap;
1315
use pretty_assertions::assert_eq;
@@ -39,6 +41,13 @@ pub static RPC_NODE_URL: LazyLock<String> = LazyLock::new(|| {
3941
.unwrap_or_else(|_| "https://free-rpc.nethermind.io/mainnet-juno/".to_string())
4042
});
4143

44+
pub fn create_contract_class_manager() -> ContractClassManager {
45+
let mut contract_class_manager_config = ContractClassManagerConfig::default();
46+
contract_class_manager_config.cairo_native_run_config.run_cairo_native = true;
47+
contract_class_manager_config.cairo_native_run_config.wait_on_native_compilation = true;
48+
ContractClassManager::start(contract_class_manager_config)
49+
}
50+
4251
pub fn guess_chain_id_from_node_url(node_url: &str) -> ReexecutionResult<ChainId> {
4352
match (
4453
node_url.contains("mainnet"),
@@ -223,17 +232,19 @@ impl From<CommitmentStateDiff> for ComparableStateDiff {
223232
}
224233

225234
pub fn reexecute_and_verify_correctness<
226-
S: StateReader + Send + Sync + Clone + 'static,
235+
S: StateReader + Send + Sync + 'static,
227236
T: ConsecutiveReexecutionStateReaders<S>,
228237
>(
229238
consecutive_state_readers: T,
239+
contract_class_manager: &ContractClassManager,
230240
) -> Option<CachedState<S>> {
231241
let expected_state_diff = consecutive_state_readers.get_next_block_state_diff().unwrap();
232242

233243
let all_txs_in_next_block = consecutive_state_readers.get_next_block_txs().unwrap();
234244

235-
let mut transaction_executor =
236-
consecutive_state_readers.pre_process_and_create_executor(None).unwrap();
245+
let mut transaction_executor = consecutive_state_readers
246+
.pre_process_and_create_executor(None, contract_class_manager)
247+
.unwrap();
237248

238249
let execution_results = transaction_executor.execute_txs(&all_txs_in_next_block, None);
239250
// Verify all transactions executed successfully.
@@ -257,6 +268,7 @@ pub fn reexecute_block_for_testing(block_number: u64) {
257268

258269
reexecute_and_verify_correctness(
259270
OfflineConsecutiveStateReaders::new_from_file(&full_file_path).unwrap(),
271+
&create_contract_class_manager(),
260272
);
261273

262274
println!("Reexecution test for block {block_number} passed successfully.");
@@ -267,6 +279,7 @@ pub fn write_block_reexecution_data_to_file(
267279
full_file_path: String,
268280
node_url: String,
269281
chain_id: ChainId,
282+
contract_class_manager: &ContractClassManager,
270283
) {
271284
let config = RpcStateReaderConfig::from_url(node_url);
272285

@@ -283,10 +296,16 @@ pub fn write_block_reexecution_data_to_file(
283296
let old_block_hash = consecutive_state_readers.get_old_block_hash().unwrap();
284297

285298
// Run the reexecution test and get the state maps and contract class mapping.
286-
let block_state = reexecute_and_verify_correctness(consecutive_state_readers).unwrap();
299+
let block_state =
300+
reexecute_and_verify_correctness(consecutive_state_readers, contract_class_manager)
301+
.unwrap();
287302
let serializable_data_prev_block = SerializableDataPrevBlock {
288303
state_maps: block_state.get_initial_reads().unwrap().into(),
289-
contract_class_mapping: block_state.state.get_contract_class_mapping_dumper().unwrap(),
304+
contract_class_mapping: block_state
305+
.state
306+
.state_reader
307+
.get_contract_class_mapping_dumper()
308+
.unwrap(),
290309
};
291310

292311
// Write the reexecution data to a json file.
@@ -309,6 +328,7 @@ pub fn execute_single_transaction_from_json(
309328
node_url: String,
310329
chain_id: ChainId,
311330
transaction_json_path: String,
331+
contract_class_manager: &ContractClassManager,
312332
) -> ReexecutionResult<()> {
313333
// Load transaction from a JSON file.
314334
let json_content = read_to_string(&transaction_json_path).unwrap_or_else(|_| {
@@ -341,7 +361,7 @@ pub fn execute_single_transaction_from_json(
341361

342362
// Create transaction executor.
343363
let mut transaction_executor =
344-
consecutive_state_readers.pre_process_and_create_executor(None)?;
364+
consecutive_state_readers.pre_process_and_create_executor(None, contract_class_manager)?;
345365

346366
// Execute transaction (should be single element).
347367
let execution_results = transaction_executor.execute_txs(&blockifier_tx, None);

0 commit comments

Comments
 (0)