Skip to content
Merged
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
2 changes: 2 additions & 0 deletions Cargo.lock

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

7 changes: 6 additions & 1 deletion crates/starknet_os_runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ repository.workspace = true
license-file.workspace = true
description = "Runs transactions through the Starknet OS and returns Cairo PIE and OS output."

[features]
cairo_native = ["blockifier/cairo_native"]

[dependencies]
blockifier.workspace = true
blockifier_reexecution.workspace = true
cairo-lang-starknet-classes.workspace = true
cairo-lang-utils.workspace = true
cairo-vm.workspace = true
indexmap.workspace = true
starknet-rust.workspace = true
starknet-rust-core.workspace = true
starknet-types-core.workspace = true
starknet_api.workspace = true
starknet_os.workspace = true
starknet_patricia.workspace = true
Expand All @@ -23,7 +29,6 @@ url.workspace = true
[dev-dependencies]
blockifier = { workspace = true, features = ["testing"] }
rstest.workspace = true
starknet-types-core.workspace = true

[lints]
workspace = true
89 changes: 83 additions & 6 deletions crates/starknet_os_runner/src/classes_provider.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,51 @@
use std::collections::{BTreeMap, HashSet};

use blockifier::execution::contract_class::{CompiledClassV1, RunnableCompiledClass};
use blockifier::state::state_api::StateReader;
use blockifier::state::state_reader_and_contract_manager::{
FetchCompiledClasses,
StateReaderAndContractManager,
};
use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass;
use cairo_lang_utils::bigint::BigUintAsHex;
use cairo_vm::types::relocatable::MaybeRelocatable;
use starknet_api::core::{ClassHash, CompiledClassHash};
use starknet_api::deprecated_contract_class::ContractClass;
use starknet_types_core::felt::Felt;

use crate::errors::ClassesProviderError;

/// Converts a `CompiledClassV1` to a `CasmContractClass` for OS execution.
/// Note: Some fields are not preserved in `CompiledClassV1` and are set to default values:
/// - `compiler_version`: Set to empty string
/// - `hints`: Set to empty (OS doesn't use them from this struct for Cairo 1 contracts)
/// - `pythonic_hints`: Set to None
fn compiled_class_v1_to_casm(class: &CompiledClassV1) -> CasmContractClass {
// TODO(Aviv): Consider using dummy prime since it is not used in the OS.
let prime = Felt::prime();

let bytecode: Vec<BigUintAsHex> = class
.program
.iter_data()
.map(|maybe_relocatable| match maybe_relocatable {
MaybeRelocatable::Int(felt) => BigUintAsHex { value: felt.to_biguint() },
_ => panic!("Expected all bytecode elements to be MaybeRelocatable::Int"),
})
.collect();

CasmContractClass {
prime,
compiler_version: String::new(),
bytecode,
bytecode_segment_lengths: Some(class.bytecode_segment_felt_sizes().into()),
hints: Vec::new(),
pythonic_hints: None,
entry_points_by_type: (&class.entry_points_by_type).into(),
}
}

/// The classes required for a Starknet OS run.
/// Matches the fields in `StarknetOsInput` and `OsBlockInput`.
/// Matches the fields in `StarknetOsInput`.
pub struct ClassesInput {
/// Deprecated (Cairo 0) contract classes.
/// Maps ClassHash to the contract class definition.
pub deprecated_compiled_classes: BTreeMap<ClassHash, ContractClass>,
/// Cairo 1+ contract classes (CASM).
/// Maps CompiledClassHash to the CASM contract class definition.
pub compiled_classes: BTreeMap<CompiledClassHash, CasmContractClass>,
Expand All @@ -22,5 +56,48 @@ pub trait ClassesProvider {
fn get_classes(
&self,
executed_class_hashes: &HashSet<ClassHash>,
) -> Result<ClassesInput, ClassesProviderError>;
) -> Result<ClassesInput, ClassesProviderError> {
let mut compiled_classes = BTreeMap::new();

// TODO(Aviv): Parallelize the fetching of classes.
for &class_hash in executed_class_hashes {
let (compiled_class_hash, casm) = self.fetch_class(class_hash)?;
compiled_classes.insert(compiled_class_hash, casm);
}
Ok(ClassesInput { compiled_classes })
}

/// Fetches class by class hash.
fn fetch_class(
&self,
class_hash: ClassHash,
) -> Result<(CompiledClassHash, CasmContractClass), ClassesProviderError>;
}

impl<S: FetchCompiledClasses> ClassesProvider for StateReaderAndContractManager<S> {
/// Fetch class from the state reader and contract manager.
/// Returns error if the class is deprecated.
fn fetch_class(
&self,
class_hash: ClassHash,
) -> Result<(CompiledClassHash, CasmContractClass), ClassesProviderError> {
let compiled_class = self.get_compiled_class(class_hash)?;
// TODO(Aviv): Make sure that the state reader is not returning dummy compiled class hash.
let compiled_class_hash = self.get_compiled_class_hash_v2(class_hash, &compiled_class)?;
match compiled_class {
RunnableCompiledClass::V0(_v0) => {
Err(ClassesProviderError::DeprecatedContractError(class_hash))
}
RunnableCompiledClass::V1(compiled_class_v1) => {
let casm = compiled_class_v1_to_casm(&compiled_class_v1);
Ok((compiled_class_hash, casm))
}
#[cfg(feature = "cairo_native")]
RunnableCompiledClass::V1Native(compiled_class_v1_native) => {
let compiled_class_v1 = compiled_class_v1_native.casm();
let casm = compiled_class_v1_to_casm(&compiled_class_v1);
Ok((compiled_class_hash, casm))
}
}
}
}
8 changes: 8 additions & 0 deletions crates/starknet_os_runner/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use blockifier::state::errors::StateError;
use blockifier_reexecution::errors::ReexecutionError;
use starknet_api::core::ClassHash;
use starknet_os::errors::StarknetOsError;
use starknet_rust::providers::ProviderError;
use thiserror::Error;
Expand Down Expand Up @@ -43,4 +45,10 @@ pub enum ProofProviderError {
pub enum ClassesProviderError {
#[error("Failed to get classes: {0}")]
GetClassesError(String),
#[error(
"Starknet os does not support deprecated contract classes, class hash: {0} is deprecated"
)]
DeprecatedContractError(ClassHash),
#[error(transparent)]
StateError(#[from] StateError),
}
7 changes: 4 additions & 3 deletions crates/starknet_os_runner/src/runner.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::collections::{BTreeMap, HashMap};

use blockifier::state::contract_class_manager::ContractClassManager;
use starknet_api::block::{BlockHash, BlockNumber};
Expand Down Expand Up @@ -51,7 +51,7 @@ where
// Execute virtual block and get execution data.
let mut execution_data = self.virtual_block_executor.execute(
block_number,
contract_class_manager,
contract_class_manager.clone(),
txs.clone(),
)?;

Expand Down Expand Up @@ -121,7 +121,8 @@ where
Ok(OsHints {
os_input: StarknetOsInput {
os_block_inputs: vec![os_block_input],
deprecated_compiled_classes: classes.deprecated_compiled_classes,
// We do not support deprecated contract classes.
deprecated_compiled_classes: BTreeMap::new(),
compiled_classes: classes.compiled_classes,
},
// TODO(Aviv): choose os hints config.
Expand Down
Loading