Skip to content

Commit 3674a3f

Browse files
blockifier_reexecution: impl FetchedCompiledClass for test and offline state readers
1 parent 57367bb commit 3674a3f

File tree

9 files changed

+124
-2
lines changed

9 files changed

+124
-2
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/blockifier/src/state/errors.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ pub enum StateError {
3232
/// Represents all unexpected errors that may occur while reading from state.
3333
#[error("Failed to read from state: {0}.")]
3434
StateReadError(String),
35-
#[error("Missing Sierra class for CASM class with hash {:#066x}.", **.0)]
36-
MissingSierra(ClassHash),
35+
#[error("Missing Sierra class.")]
36+
MissingSierra(),
3737
#[error("Missing compiled class hash v2 for class with hash {:#064x}.", **.0)]
3838
MissingCompiledClassHashV2(ClassHash),
3939
}

crates/blockifier/src/state/global_cache.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
use std::sync::Arc;
22

33
use starknet_api::class_cache::GlobalContractCache;
4+
use starknet_api::contract_class::ContractClass;
45
use starknet_api::state::SierraContractClass;
56

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

1012
pub const GLOBAL_CONTRACT_CACHE_SIZE_FOR_TEST: usize = 600;
1113

@@ -36,6 +38,30 @@ impl CompiledClasses {
3638
},
3739
}
3840
}
41+
42+
/// Converts a [`starknet_api::contract_class::ContractClass`] into the corresponding
43+
/// [`CompiledClasses`].
44+
///
45+
/// For `V1` (Cairo 1) classes, a matching `SierraContractClass` must be provided.
46+
/// For `V0` classes, this argument should be `None`.
47+
pub fn from_contract_class(
48+
contract_class: &ContractClass,
49+
sierra_contract_class: Option<SierraContractClass>,
50+
) -> StateResult<CompiledClasses> {
51+
match contract_class {
52+
ContractClass::V0(deprecated_class) => {
53+
Ok(CompiledClasses::V0(CompiledClassV0::try_from(deprecated_class.clone())?))
54+
}
55+
ContractClass::V1(versioned_casm) => {
56+
let sierra_contract_class =
57+
sierra_contract_class.expect("V1 contract class requires Sierra class");
58+
Ok(CompiledClasses::V1(
59+
CompiledClassV1::try_from(versioned_casm.clone())?,
60+
Arc::new(sierra_contract_class.clone()),
61+
))
62+
}
63+
}
64+
}
3965
}
4066

4167
pub type RawClassCache = GlobalContractCache<CompiledClasses>;

crates/blockifier_reexecution/src/state_reader/offline_state_reader.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ use blockifier::context::BlockContext;
99
use blockifier::execution::contract_class::RunnableCompiledClass;
1010
use blockifier::state::cached_state::{CommitmentStateDiff, StateMaps};
1111
use blockifier::state::errors::StateError;
12+
use blockifier::state::global_cache::CompiledClasses;
1213
use blockifier::state::state_api::{StateReader, StateResult};
14+
use blockifier::state::state_reader_and_contract_manager::FetchCompiledClasses;
1315
use blockifier::transaction::transaction_execution::Transaction as BlockifierTransaction;
1416
use serde::{Deserialize, Serialize};
1517
use starknet_api::block::{BlockHash, BlockHashAndNumber, BlockInfo, BlockNumber, StarknetVersion};
@@ -191,6 +193,17 @@ impl ReexecutionStateReader for OfflineStateReader {
191193
}
192194
}
193195

196+
impl FetchCompiledClasses for OfflineStateReader {
197+
fn get_compiled_classes(&self, class_hash: ClassHash) -> StateResult<CompiledClasses> {
198+
let contract_class = self.get_contract_class(&class_hash)?;
199+
self.starknet_core_contract_class_to_compiled_classes(&contract_class)
200+
}
201+
202+
fn is_declared(&self, class_hash: ClassHash) -> StateResult<bool> {
203+
self.is_contract_class_declared(class_hash)
204+
}
205+
}
206+
194207
impl OfflineStateReader {
195208
pub fn get_transaction_executor(
196209
self,

crates/blockifier_reexecution/src/state_reader/reexecution_state_reader.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ 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::errors::StateError;
6+
use blockifier::state::global_cache::CompiledClasses;
57
use blockifier::state::state_api::{StateReader, StateResult};
68
use blockifier::transaction::account_transaction::ExecutionFlags;
79
use blockifier::transaction::transaction_execution::Transaction as BlockifierTransaction;
810
use starknet_api::block::{BlockHash, BlockNumber};
911
use starknet_api::contract_class::{ClassInfo, SierraVersion};
1012
use starknet_api::core::ClassHash;
13+
use starknet_api::state::SierraContractClass;
1114
use starknet_api::test_utils::MAX_FEE;
1215
use starknet_api::transaction::{Transaction, TransactionHash};
1316
use starknet_core::types::ContractClass as StarknetContractClass;
@@ -92,6 +95,34 @@ pub trait ReexecutionStateReader {
9295
}
9396

9497
fn get_old_block_hash(&self, old_block_number: BlockNumber) -> ReexecutionResult<BlockHash>;
98+
99+
fn is_contract_class_declared(&self, class_hash: ClassHash) -> StateResult<bool> {
100+
match self.get_contract_class(&class_hash) {
101+
Err(StateError::UndeclaredClassHash(_)) => Ok(false),
102+
Err(err) => Err(err),
103+
Ok(contract_class) => Ok(matches!(contract_class, StarknetContractClass::Sierra(_))),
104+
}
105+
}
106+
107+
/// Converts a `starknet_core::types::ContractClass` to `CompiledClasses`.
108+
fn starknet_core_contract_class_to_compiled_classes(
109+
&self,
110+
contract_class: &StarknetContractClass,
111+
) -> StateResult<CompiledClasses> {
112+
match contract_class {
113+
StarknetContractClass::Sierra(flat_sierra) => {
114+
let (class_v1, _) = sierra_to_versioned_contract_class_v1(flat_sierra.clone())?;
115+
let sierra = SierraContractClass::from(flat_sierra.clone());
116+
117+
Ok(CompiledClasses::from_contract_class(&class_v1, Some(sierra))?)
118+
}
119+
StarknetContractClass::Legacy(legacy) => {
120+
let class_v0 = legacy_to_contract_class_v0(legacy.clone())?;
121+
122+
Ok(CompiledClasses::from_contract_class(&class_v0, None)?)
123+
}
124+
}
125+
}
95126
}
96127

97128
/// Trait of the functions \ queries required for reexecution.

crates/blockifier_reexecution/src/state_reader/test_state_reader.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ use blockifier::context::BlockContext;
1515
use blockifier::execution::contract_class::RunnableCompiledClass;
1616
use blockifier::state::cached_state::CommitmentStateDiff;
1717
use blockifier::state::errors::StateError;
18+
use blockifier::state::global_cache::CompiledClasses;
1819
use blockifier::state::state_api::{StateReader, StateResult};
20+
use blockifier::state::state_reader_and_contract_manager::FetchCompiledClasses;
1921
use blockifier::transaction::transaction_execution::Transaction as BlockifierTransaction;
2022
use serde::Serialize;
2123
use serde_json::{json, to_value};
@@ -152,6 +154,19 @@ impl StateReader for TestStateReader {
152154
}
153155
}
154156

157+
impl FetchCompiledClasses for TestStateReader {
158+
fn get_compiled_classes(&self, class_hash: ClassHash) -> StateResult<CompiledClasses> {
159+
let contract_class =
160+
retry_request!(self.retry_config, || self.get_contract_class(&class_hash))?;
161+
162+
self.starknet_core_contract_class_to_compiled_classes(&contract_class)
163+
}
164+
165+
fn is_declared(&self, class_hash: ClassHash) -> StateResult<bool> {
166+
self.is_contract_class_declared(class_hash)
167+
}
168+
}
169+
155170
impl TestStateReader {
156171
pub fn new(
157172
config: &RpcStateReaderConfig,

crates/starknet_api/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ semver.workspace = true
3232
serde = { workspace = true, features = ["derive", "rc"] }
3333
serde_json.workspace = true
3434
sha3.workspace = true
35+
starknet-core.workspace = true
3536
starknet-crypto.workspace = true
3637
starknet-types-core = { workspace = true, features = ["hash"] }
3738
strum = { workspace = true, features = ["derive"] }

crates/starknet_api/src/rpc_transaction.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::collections::HashMap;
77
use apollo_sizeof::SizeOf;
88
use cairo_lang_starknet_classes::contract_class::ContractEntryPoints as CairoLangContractEntryPoints;
99
use serde::{Deserialize, Serialize};
10+
use starknet_core::types::EntryPointsByType as StarknetCoreEntryPointsByType;
1011
use strum::EnumVariantNames;
1112
use strum_macros::{EnumDiscriminants, EnumIter, IntoStaticStr};
1213

@@ -680,6 +681,16 @@ impl From<CairoLangContractEntryPoints> for EntryPointByType {
680681
}
681682
}
682683

684+
impl From<StarknetCoreEntryPointsByType> for EntryPointByType {
685+
fn from(value: StarknetCoreEntryPointsByType) -> Self {
686+
Self {
687+
constructor: value.constructor.into_iter().map(EntryPoint::from).collect(),
688+
external: value.external.into_iter().map(EntryPoint::from).collect(),
689+
l1handler: value.l1_handler.into_iter().map(EntryPoint::from).collect(),
690+
}
691+
}
692+
}
693+
683694
impl EntryPointByType {
684695
pub fn from_hash_map(entry_points_by_type: HashMap<EntryPointType, Vec<EntryPoint>>) -> Self {
685696
macro_rules! get_entrypoint_by_type {

crates/starknet_api/src/state.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use cairo_lang_starknet_classes::contract_class::ContractEntryPoint as CairoLang
99
use indexmap::IndexMap;
1010
use serde::{Deserialize, Serialize};
1111
use sha3::Digest;
12+
use starknet_core::types::{FlattenedSierraClass, SierraEntryPoint};
1213
use starknet_types_core::felt::Felt;
1314
use starknet_types_core::hash::{Poseidon, StarkHash as SNTypsCoreStarkHash};
1415

@@ -270,6 +271,17 @@ impl SierraContractClass {
270271
}
271272
}
272273

274+
impl From<FlattenedSierraClass> for SierraContractClass {
275+
fn from(flattened_sierra: FlattenedSierraClass) -> Self {
276+
Self {
277+
sierra_program: flattened_sierra.sierra_program,
278+
contract_class_version: flattened_sierra.contract_class_version,
279+
entry_points_by_type: flattened_sierra.entry_points_by_type.into(),
280+
abi: flattened_sierra.abi,
281+
}
282+
}
283+
}
284+
273285
#[derive(Clone, Debug, Deserialize)]
274286
pub struct ContractClassComponentHashes {
275287
contract_class_version: Felt,
@@ -327,6 +339,18 @@ impl From<CairoLangContractEntryPoint> for EntryPoint {
327339
}
328340
}
329341

342+
impl From<SierraEntryPoint> for EntryPoint {
343+
fn from(entry_point: SierraEntryPoint) -> Self {
344+
Self {
345+
function_idx: FunctionIndex(
346+
usize::try_from(entry_point.function_idx)
347+
.expect("Function index should fit in a usize"),
348+
),
349+
selector: EntryPointSelector(entry_point.selector),
350+
}
351+
}
352+
}
353+
330354
#[derive(
331355
Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord,
332356
)]

0 commit comments

Comments
 (0)