Skip to content

Commit 56285d5

Browse files
starknet_os_runner: c;asses provider using class manager
1 parent f231222 commit 56285d5

File tree

4 files changed

+98
-8
lines changed

4 files changed

+98
-8
lines changed

Cargo.lock

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

crates/starknet_os_runner/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ description = "Runs transactions through the Starknet OS and returns Cairo PIE a
1010
blockifier.workspace = true
1111
blockifier_reexecution.workspace = true
1212
cairo-lang-starknet-classes.workspace = true
13+
cairo-lang-utils.workspace = true
14+
cairo-vm.workspace = true
1315
indexmap.workspace = true
1416
starknet-rust.workspace = true
1517
starknet-rust-core.workspace = true
18+
starknet-types-core.workspace = true
1619
starknet_api.workspace = true
1720
starknet_os.workspace = true
1821
starknet_patricia.workspace = true
@@ -23,7 +26,6 @@ url.workspace = true
2326
[dev-dependencies]
2427
blockifier = { workspace = true, features = ["testing"] }
2528
rstest.workspace = true
26-
starknet-types-core.workspace = true
2729

2830
[lints]
2931
workspace = true
Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,110 @@
11
use std::collections::{BTreeMap, HashSet};
22

3+
use blockifier::execution::contract_class::{CompiledClassV1, RunnableCompiledClass};
4+
use blockifier::state::contract_class_manager::ContractClassManager;
35
use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass;
6+
use cairo_lang_utils::bigint::BigUintAsHex;
7+
use cairo_vm::types::relocatable::MaybeRelocatable;
8+
use starknet_api::contract_class::compiled_class_hash::{HashVersion, HashableCompiledClass};
9+
use starknet_api::contract_class::ContractClass;
410
use starknet_api::core::{ClassHash, CompiledClassHash};
5-
use starknet_api::deprecated_contract_class::ContractClass;
11+
use starknet_api::deprecated_contract_class::ContractClass as DeprecatedContractClass;
12+
use starknet_types_core::felt::Felt;
613

714
use crate::errors::ClassesProviderError;
815

916
/// The classes required for a Starknet OS run.
10-
/// Matches the fields in `StarknetOsInput` and `OsBlockInput`.
17+
/// Matches the fields in `StarknetOsInput`.
1118
pub struct ClassesInput {
1219
/// Deprecated (Cairo 0) contract classes.
1320
/// Maps ClassHash to the contract class definition.
14-
pub deprecated_compiled_classes: BTreeMap<ClassHash, ContractClass>,
21+
pub deprecated_compiled_classes: BTreeMap<ClassHash, DeprecatedContractClass>,
1522
/// Cairo 1+ contract classes (CASM).
1623
/// Maps CompiledClassHash to the CASM contract class definition.
1724
pub compiled_classes: BTreeMap<CompiledClassHash, CasmContractClass>,
1825
}
1926

2027
pub trait ClassesProvider {
21-
/// Fetches all classes required for the OS run based on the executed class hashes.
28+
/// Fetches a class from an external source (e.g., storage, network).
29+
/// Called when the class is not found in the `ContractClassManager`.
30+
fn fetch_class(&self, class_hash: ClassHash) -> Result<ContractClass, ClassesProviderError>;
31+
32+
/// Gets all classes required for the OS run.
33+
///
34+
/// For each class hash:
35+
/// 1. Tries to get the class from `ContractClassManager` first
36+
/// 2. Falls back to `fetch_class` if not found in manager
37+
/// 3. Converts to the appropriate format for OS execution
2238
fn get_classes(
2339
&self,
2440
executed_class_hashes: &HashSet<ClassHash>,
25-
) -> Result<ClassesInput, ClassesProviderError>;
41+
contract_class_manager: &ContractClassManager,
42+
) -> Result<ClassesInput, ClassesProviderError> {
43+
let mut deprecated_compiled_classes = BTreeMap::new();
44+
let mut compiled_classes = BTreeMap::new();
45+
46+
for &class_hash in executed_class_hashes {
47+
// Try manager first.
48+
if let Some(runnable) = contract_class_manager.get_runnable(&class_hash) {
49+
match runnable {
50+
RunnableCompiledClass::V0(_) => {
51+
unimplemented!("V0 class conversion from manager not yet supported")
52+
}
53+
RunnableCompiledClass::V1(v1) => {
54+
let casm = Self::compiled_class_v1_to_casm(&v1);
55+
// TODO(Aviv): The state reader in the contract class manager does not
56+
// support get compiled class hash v2. We need to
57+
// implement this in the state reader.
58+
let compiled_class_hash = contract_class_manager
59+
.get_compiled_class_hash_v2(&class_hash)
60+
.unwrap_or_else(|| casm.hash(&HashVersion::V2));
61+
compiled_classes.insert(compiled_class_hash, casm);
62+
}
63+
}
64+
continue;
65+
}
66+
67+
// Fallback to fetch.
68+
match self.fetch_class(class_hash)? {
69+
ContractClass::V0(deprecated_class) => {
70+
deprecated_compiled_classes.insert(class_hash, deprecated_class);
71+
}
72+
ContractClass::V1((casm, _sierra_version)) => {
73+
let compiled_hash = casm.hash(&HashVersion::V2);
74+
compiled_classes.insert(compiled_hash, casm);
75+
}
76+
}
77+
}
78+
79+
Ok(ClassesInput { deprecated_compiled_classes, compiled_classes })
80+
}
81+
82+
/// Converts a `CompiledClassV1` to a `CasmContractClass` for OS execution.
83+
/// Note: Some fields are not preserved in `CompiledClassV1` and are set to default values:
84+
/// - `compiler_version`: Set to empty string
85+
/// - `hints`: Set to empty (OS doesn't use them from this struct)
86+
/// - `pythonic_hints`: Set to None
87+
fn compiled_class_v1_to_casm(class: &CompiledClassV1) -> CasmContractClass {
88+
// TODO(Aviv): Consider using dummy prime since it is not used in the OS.
89+
let prime = Felt::prime();
90+
91+
let bytecode: Vec<BigUintAsHex> = class
92+
.program
93+
.iter_data()
94+
.map(|maybe_relocatable| match maybe_relocatable {
95+
MaybeRelocatable::Int(felt) => BigUintAsHex { value: felt.to_biguint() },
96+
_ => panic!("Expected all bytecode elements to be MaybeRelocatable::Int"),
97+
})
98+
.collect();
99+
100+
CasmContractClass {
101+
prime,
102+
compiler_version: String::new(),
103+
bytecode,
104+
bytecode_segment_lengths: Some(class.bytecode_segment_felt_sizes().into()),
105+
hints: Vec::new(),
106+
pythonic_hints: None,
107+
entry_points_by_type: (&class.entry_points_by_type).into(),
108+
}
109+
}
26110
}

crates/starknet_os_runner/src/runner.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ where
5151
// 1. Execute virtual block and get execution data.
5252
let mut execution_data = self.virtual_block_executor.execute(
5353
block_number,
54-
contract_class_manager,
54+
contract_class_manager.clone(),
5555
txs.clone(),
5656
)?;
5757

@@ -63,7 +63,9 @@ where
6363
};
6464

6565
// Fetch classes.
66-
let classes = self.classes_provider.get_classes(&execution_data.executed_class_hashes)?;
66+
let classes = self
67+
.classes_provider
68+
.get_classes(&execution_data.executed_class_hashes, &contract_class_manager)?;
6769

6870
// Fetch storage proofs.
6971
let storage_proofs =

0 commit comments

Comments
 (0)