Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions crates/blockifier/src/state/global_cache.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::sync::Arc;

use starknet_api::class_cache::GlobalContractCache;
use starknet_api::contract_class::ContractClass;
use starknet_api::state::SierraContractClass;

use crate::execution::contract_class::{CompiledClassV0, CompiledClassV1, RunnableCompiledClass};
#[cfg(feature = "cairo_native")]
use crate::execution::native::contract_class::NativeCompiledClassV1;
use crate::state::state_api::StateResult;

pub const GLOBAL_CONTRACT_CACHE_SIZE_FOR_TEST: usize = 600;

Expand Down Expand Up @@ -36,6 +38,32 @@ impl CompiledClasses {
},
}
}

/// Create a CompiledClasses object from a ContractClass.
/// If the ContractClass is a Cairo 1 contract class, the sierra contract class is required
/// as CompiledClasses::V1 objects contains a SierraContractClass.
pub fn from_contract_class(
contract_class: &ContractClass,
sierra_contract_class: Option<SierraContractClass>,
) -> StateResult<CompiledClasses> {
match contract_class {
ContractClass::V0(deprecated_class) => {
Ok(CompiledClasses::V0(CompiledClassV0::try_from(deprecated_class.clone())?))
}
ContractClass::V1(versioned_casm) => {
let sierra_contract_class =
if let Some(sierra_contract_class) = sierra_contract_class {
sierra_contract_class
} else {
panic!("Expected Sierra contract class, got None");
};
Ok(CompiledClasses::V1(
CompiledClassV1::try_from(versioned_casm.clone())?,
Arc::new(sierra_contract_class.clone()),
))
}
}
}
}

pub type RawClassCache = GlobalContractCache<CompiledClasses>;
Expand Down
2 changes: 1 addition & 1 deletion crates/blockifier_reexecution/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ apollo_gateway_config.workspace = true
apollo_rpc_execution.workspace = true
apollo_sierra_compilation_config.workspace = true
assert_matches.workspace = true
blockifier = { workspace = true, features = ["reexecution"] }
blockifier = { workspace = true, features = ["cairo_native", "reexecution"] }
clap = { workspace = true, features = ["cargo", "derive"] }
flate2.workspace = true
google-cloud-storage.workspace = true
Expand Down
34 changes: 26 additions & 8 deletions crates/blockifier_reexecution/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use std::fs;
use std::path::Path;
use std::sync::Arc;

use apollo_gateway_config::config::RpcStateReaderConfig;
use blockifier_reexecution::state_reader::offline_state_reader::OfflineConsecutiveStateReaders;
use blockifier_reexecution::state_reader::test_state_reader::ConsecutiveTestStateReaders;
use blockifier_reexecution::state_reader::online_state_reader::ConsecutiveOnlineStateReaders;
use blockifier_reexecution::state_reader::utils::{
create_contract_class_manager,
execute_single_transaction_from_json,
get_block_numbers_for_reexecution,
guess_chain_id_from_node_url,
Expand Down Expand Up @@ -197,18 +199,22 @@ async fn main() {
rpc_args.node_url
);

let config = RpcStateReaderConfig::from_url(rpc_args.node_url.clone());
let rpc_state_reader_config = RpcStateReaderConfig::from_url(rpc_args.node_url.clone());
let contract_class_manager = create_contract_class_manager();

// RPC calls are "synchronous IO" (see, e.g., https://stackoverflow.com/questions/74547541/when-should-you-use-tokios-spawn-blocking)
// for details), so should be executed in a blocking thread.
// TODO(Aner): make only the RPC calls blocking, not the whole function.
tokio::task::spawn_blocking(move || {
reexecute_and_verify_correctness(ConsecutiveTestStateReaders::new(
BlockNumber(block_number - 1),
Some(config),
rpc_args.parse_chain_id(),
false,
))
reexecute_and_verify_correctness(
ConsecutiveOnlineStateReaders::new(
BlockNumber(block_number - 1),
Some(rpc_state_reader_config),
rpc_args.parse_chain_id(),
false,
),
&contract_class_manager,
)
})
.await
.unwrap();
Expand All @@ -227,6 +233,8 @@ async fn main() {

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

let contract_class_manager = create_contract_class_manager();

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

let contract_class_manager = Arc::new(create_contract_class_manager());

let mut task_set = tokio::task::JoinSet::new();
for block_number in block_numbers {
let full_file_path = block_full_file_path(directory_path.clone(), block_number);
let (node_url, chain_id) = (rpc_args.node_url.clone(), rpc_args.parse_chain_id());
let contract_class_manager_shared = Arc::clone(&contract_class_manager);

// RPC calls are "synchronous IO" (see, e.g., https://stackoverflow.com/questions/74547541/when-should-you-use-tokios-spawn-blocking)
// for details), so should be executed in a blocking thread.
// TODO(Aner): make only the RPC calls blocking, not the whole function.
Expand All @@ -266,6 +279,7 @@ async fn main() {
full_file_path,
node_url,
chain_id,
&contract_class_manager_shared,
)
})
.await
Expand All @@ -281,12 +295,16 @@ async fn main() {
let block_numbers = parse_block_numbers_args(block_numbers);
println!("Reexecuting blocks {block_numbers:?}.");

let contract_class_manager = Arc::new(create_contract_class_manager());

let mut task_set = tokio::task::JoinSet::new();
for block in block_numbers {
let full_file_path = block_full_file_path(directory_path.clone(), block);
let contract_class_manager_shared = Arc::clone(&contract_class_manager);
task_set.spawn(async move {
reexecute_and_verify_correctness(
OfflineConsecutiveStateReaders::new_from_file(&full_file_path).unwrap(),
&contract_class_manager_shared,
);
println!("Reexecution test for block {block} passed successfully.");
});
Expand Down
2 changes: 1 addition & 1 deletion crates/blockifier_reexecution/src/state_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ pub mod reexecution_test;
#[cfg(all(test, feature = "blockifier_regression_https_testing"))]
pub mod rpc_https_test;
pub mod serde_utils;
pub mod test_state_reader;
pub mod online_state_reader;
pub mod utils;
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ use blockifier::bouncer::BouncerConfig;
use blockifier::context::BlockContext;
use blockifier::execution::contract_class::RunnableCompiledClass;
use blockifier::state::cached_state::{CommitmentStateDiff, StateMaps};
use blockifier::state::contract_class_manager::ContractClassManager;
use blockifier::state::errors::StateError;
use blockifier::state::global_cache::CompiledClasses;
use blockifier::state::state_api::{StateReader, StateResult};
use blockifier::state::state_reader_and_contract_manager::{
FetchCompiledClasses,
StateReaderAndContractManager,
};
use blockifier::transaction::transaction_execution::Transaction as BlockifierTransaction;
use serde::{Deserialize, Serialize};
use starknet_api::block::{BlockHash, BlockHashAndNumber, BlockInfo, BlockNumber, StarknetVersion};
Expand All @@ -28,7 +34,7 @@ use crate::state_reader::reexecution_state_reader::{
ConsecutiveReexecutionStateReaders,
ReexecutionStateReader,
};
use crate::state_reader::test_state_reader::StarknetContractClassMapping;
use crate::state_reader::online_state_reader::StarknetContractClassMapping;
use crate::state_reader::utils::{get_chain_info, ReexecutionStateMaps};

pub struct OfflineReexecutionData {
Expand Down Expand Up @@ -191,19 +197,36 @@ impl ReexecutionStateReader for OfflineStateReader {
}
}

impl FetchCompiledClasses for OfflineStateReader {
fn get_compiled_classes(&self, class_hash: ClassHash) -> StateResult<CompiledClasses> {
let contract_class = self.get_contract_class(&class_hash)?;
self.starknet_core_contract_class_to_compiled_classes(&contract_class)
}

fn is_declared(&self, class_hash: ClassHash) -> StateResult<bool> {
self.is_contract_class_declared(class_hash)
}
}

impl OfflineStateReader {
pub fn get_transaction_executor(
self,
block_context_next_block: BlockContext,
transaction_executor_config: Option<TransactionExecutorConfig>,
) -> ReexecutionResult<TransactionExecutor<OfflineStateReader>> {
contract_class_manager: &ContractClassManager,
) -> ReexecutionResult<TransactionExecutor<StateReaderAndContractManager<OfflineStateReader>>>
{
let old_block_number = BlockNumber(
block_context_next_block.block_info().block_number.0
- constants::STORED_BLOCK_HASH_BUFFER,
);
let hash = self.old_block_hash;
Ok(TransactionExecutor::<OfflineStateReader>::pre_process_and_create(
self,
let state_reader_and_contract_manager = StateReaderAndContractManager {
state_reader: self,
contract_class_manager: contract_class_manager.clone(),
};
Ok(TransactionExecutor::<StateReaderAndContractManager<OfflineStateReader>>::pre_process_and_create(
state_reader_and_contract_manager,
block_context_next_block,
Some(BlockHashAndNumber { number: old_block_number, hash }),
transaction_executor_config.unwrap_or_default(),
Expand Down Expand Up @@ -242,13 +265,20 @@ impl OfflineConsecutiveStateReaders {
}
}

impl ConsecutiveReexecutionStateReaders<OfflineStateReader> for OfflineConsecutiveStateReaders {
impl ConsecutiveReexecutionStateReaders<StateReaderAndContractManager<OfflineStateReader>>
for OfflineConsecutiveStateReaders
{
fn pre_process_and_create_executor(
self,
transaction_executor_config: Option<TransactionExecutorConfig>,
) -> ReexecutionResult<TransactionExecutor<OfflineStateReader>> {
self.offline_state_reader_prev_block
.get_transaction_executor(self.block_context_next_block, transaction_executor_config)
contract_class_manager: &ContractClassManager,
) -> ReexecutionResult<TransactionExecutor<StateReaderAndContractManager<OfflineStateReader>>>
{
self.offline_state_reader_prev_block.get_transaction_executor(
self.block_context_next_block,
transaction_executor_config,
contract_class_manager,
)
}

fn get_next_block_txs(&self) -> ReexecutionResult<Vec<BlockifierTransaction>> {
Expand Down
Loading
Loading