Skip to content

Commit 01cc778

Browse files
starknet_os_runner: c;asses provider using class manager
1 parent dae4ab6 commit 01cc778

File tree

5 files changed

+103
-10
lines changed

5 files changed

+103
-10
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: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@ repository.workspace = true
66
license-file.workspace = true
77
description = "Runs transactions through the Starknet OS and returns Cairo PIE and OS output."
88

9+
[features]
10+
cairo_native = ["blockifier/cairo_native"]
11+
912
[dependencies]
1013
blockifier.workspace = true
1114
blockifier_reexecution.workspace = true
1215
cairo-lang-starknet-classes.workspace = true
16+
cairo-lang-utils.workspace = true
17+
cairo-vm.workspace = true
1318
indexmap.workspace = true
1419
starknet-rust.workspace = true
1520
starknet-rust-core.workspace = true
21+
starknet-types-core.workspace = true
1622
starknet_api.workspace = true
1723
starknet_os.workspace = true
1824
starknet_patricia.workspace = true
@@ -23,7 +29,6 @@ url.workspace = true
2329
[dev-dependencies]
2430
blockifier = { workspace = true, features = ["testing"] }
2531
rstest.workspace = true
26-
starknet-types-core.workspace = true
2732

2833
[lints]
2934
workspace = true
Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,51 @@
11
use std::collections::{BTreeMap, HashSet};
22

3+
use blockifier::execution::contract_class::{CompiledClassV1, RunnableCompiledClass};
4+
use blockifier::state::state_api::StateReader;
5+
use blockifier::state::state_reader_and_contract_manager::{
6+
FetchCompiledClasses,
7+
StateReaderAndContractManager,
8+
};
39
use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass;
10+
use cairo_lang_utils::bigint::BigUintAsHex;
11+
use cairo_vm::types::relocatable::MaybeRelocatable;
412
use starknet_api::core::{ClassHash, CompiledClassHash};
5-
use starknet_api::deprecated_contract_class::ContractClass;
13+
use starknet_types_core::felt::Felt;
614

715
use crate::errors::ClassesProviderError;
816

17+
/// Converts a `CompiledClassV1` to a `CasmContractClass` for OS execution.
18+
/// Note: Some fields are not preserved in `CompiledClassV1` and are set to default values:
19+
/// - `compiler_version`: Set to empty string
20+
/// - `hints`: Set to empty (OS doesn't use them from this struct for Cairo 1 contracts)
21+
/// - `pythonic_hints`: Set to None
22+
fn compiled_class_v1_to_casm(class: &CompiledClassV1) -> CasmContractClass {
23+
// TODO(Aviv): Consider using dummy prime since it is not used in the OS.
24+
let prime = Felt::prime();
25+
26+
let bytecode: Vec<BigUintAsHex> = class
27+
.program
28+
.iter_data()
29+
.map(|maybe_relocatable| match maybe_relocatable {
30+
MaybeRelocatable::Int(felt) => BigUintAsHex { value: felt.to_biguint() },
31+
_ => panic!("Expected all bytecode elements to be MaybeRelocatable::Int"),
32+
})
33+
.collect();
34+
35+
CasmContractClass {
36+
prime,
37+
compiler_version: String::new(),
38+
bytecode,
39+
bytecode_segment_lengths: Some(class.bytecode_segment_felt_sizes().into()),
40+
hints: Vec::new(),
41+
pythonic_hints: None,
42+
entry_points_by_type: (&class.entry_points_by_type).into(),
43+
}
44+
}
45+
946
/// The classes required for a Starknet OS run.
10-
/// Matches the fields in `StarknetOsInput` and `OsBlockInput`.
47+
/// Matches the fields in `StarknetOsInput`.
1148
pub struct ClassesInput {
12-
/// Deprecated (Cairo 0) contract classes.
13-
/// Maps ClassHash to the contract class definition.
14-
pub deprecated_compiled_classes: BTreeMap<ClassHash, ContractClass>,
1549
/// Cairo 1+ contract classes (CASM).
1650
/// Maps CompiledClassHash to the CASM contract class definition.
1751
pub compiled_classes: BTreeMap<CompiledClassHash, CasmContractClass>,
@@ -22,5 +56,48 @@ pub trait ClassesProvider {
2256
fn get_classes(
2357
&self,
2458
executed_class_hashes: &HashSet<ClassHash>,
25-
) -> Result<ClassesInput, ClassesProviderError>;
59+
) -> Result<ClassesInput, ClassesProviderError> {
60+
let mut compiled_classes = BTreeMap::new();
61+
62+
// TODO(Aviv): Parallelize the fetching of classes.
63+
for &class_hash in executed_class_hashes {
64+
let (compiled_class_hash, casm) = self.fetch_class(class_hash)?;
65+
compiled_classes.insert(compiled_class_hash, casm);
66+
}
67+
Ok(ClassesInput { compiled_classes })
68+
}
69+
70+
/// Fetches class by class hash.
71+
fn fetch_class(
72+
&self,
73+
class_hash: ClassHash,
74+
) -> Result<(CompiledClassHash, CasmContractClass), ClassesProviderError>;
75+
}
76+
77+
impl<S: FetchCompiledClasses> ClassesProvider for StateReaderAndContractManager<S> {
78+
/// Fetch class from the state reader and contract manager.
79+
/// Returns error if the class is deprecated.
80+
fn fetch_class(
81+
&self,
82+
class_hash: ClassHash,
83+
) -> Result<(CompiledClassHash, CasmContractClass), ClassesProviderError> {
84+
let compiled_class = self.get_compiled_class(class_hash)?;
85+
// TODO(Aviv): Make sure that the state reader is not returning dummy compiled class hash.
86+
let compiled_class_hash = self.get_compiled_class_hash_v2(class_hash, &compiled_class)?;
87+
match compiled_class {
88+
RunnableCompiledClass::V0(_v0) => {
89+
Err(ClassesProviderError::DeprecatedContractError(class_hash))
90+
}
91+
RunnableCompiledClass::V1(compiled_class_v1) => {
92+
let casm = compiled_class_v1_to_casm(&compiled_class_v1);
93+
Ok((compiled_class_hash, casm))
94+
}
95+
#[cfg(feature = "cairo_native")]
96+
RunnableCompiledClass::V1Native(compiled_class_v1_native) => {
97+
let compiled_class_v1 = compiled_class_v1_native.casm();
98+
let casm = compiled_class_v1_to_casm(&compiled_class_v1);
99+
Ok((compiled_class_hash, casm))
100+
}
101+
}
102+
}
26103
}

crates/starknet_os_runner/src/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
use blockifier::state::errors::StateError;
12
use blockifier_reexecution::errors::ReexecutionError;
3+
use starknet_api::core::ClassHash;
24
use starknet_os::errors::StarknetOsError;
35
use starknet_rust::providers::ProviderError;
46
use thiserror::Error;
@@ -43,4 +45,10 @@ pub enum ProofProviderError {
4345
pub enum ClassesProviderError {
4446
#[error("Failed to get classes: {0}")]
4547
GetClassesError(String),
48+
#[error(
49+
"Starknet os does not support deprecated contract classes, class hash: {0} is deprecated"
50+
)]
51+
DeprecatedContractError(ClassHash),
52+
#[error(transparent)]
53+
StateError(#[from] StateError),
4654
}

crates/starknet_os_runner/src/runner.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashMap;
1+
use std::collections::{BTreeMap, HashMap};
22

33
use blockifier::state::contract_class_manager::ContractClassManager;
44
use starknet_api::block::{BlockHash, BlockNumber};
@@ -51,7 +51,7 @@ where
5151
// 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

@@ -121,7 +121,8 @@ where
121121
Ok(OsHints {
122122
os_input: StarknetOsInput {
123123
os_block_inputs: vec![os_block_input],
124-
deprecated_compiled_classes: classes.deprecated_compiled_classes,
124+
// We do not support deprecated contract classes.
125+
deprecated_compiled_classes: BTreeMap::new(),
125126
compiled_classes: classes.compiled_classes,
126127
},
127128
// TODO(Aviv): choose os hints config.

0 commit comments

Comments
 (0)