Skip to content

Commit c567eec

Browse files
starknet_os_runner: add hints to casm from contract class
1 parent 051c702 commit c567eec

File tree

6 files changed

+55
-6
lines changed

6 files changed

+55
-6
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/starknet_os_runner/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ url.workspace = true
3232

3333
[dev-dependencies]
3434
blockifier = { workspace = true, features = ["testing"] }
35+
blockifier_test_utils.workspace = true
3536
rstest.workspace = true
3637

3738
[lints]

crates/starknet_os_runner/src/classes_provider.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ use std::collections::{BTreeMap, HashSet};
22
use std::sync::Arc;
33

44
use async_trait::async_trait;
5-
use blockifier::execution::contract_class::{CompiledClassV1, RunnableCompiledClass};
5+
use blockifier::execution::contract_class::{
6+
program_hints_to_casm_hints,
7+
CompiledClassV1,
8+
RunnableCompiledClass,
9+
};
610
use blockifier::state::state_api::StateReader;
711
use blockifier::state::state_reader_and_contract_manager::{
812
FetchCompiledClasses,
@@ -22,7 +26,9 @@ use crate::errors::ClassesProviderError;
2226
/// - `compiler_version`: Set to empty string
2327
/// - `hints`: Set to empty (OS doesn't use them from this struct for Cairo 1 contracts)
2428
/// - `pythonic_hints`: Set to None
25-
fn compiled_class_v1_to_casm(class: &CompiledClassV1) -> CasmContractClass {
29+
pub(crate) fn compiled_class_v1_to_casm(
30+
class: &CompiledClassV1,
31+
) -> Result<CasmContractClass, ClassesProviderError> {
2632
// TODO(Aviv): Consider using dummy prime since it is not used in the OS.
2733
let prime = Felt::prime();
2834

@@ -35,15 +41,15 @@ fn compiled_class_v1_to_casm(class: &CompiledClassV1) -> CasmContractClass {
3541
})
3642
.collect();
3743

38-
CasmContractClass {
44+
Ok(CasmContractClass {
3945
prime,
4046
compiler_version: String::new(),
4147
bytecode,
4248
bytecode_segment_lengths: Some(class.bytecode_segment_felt_sizes().into()),
43-
hints: Vec::new(),
49+
hints: program_hints_to_casm_hints(&class.program.shared_program_data.hints_collection)?,
4450
pythonic_hints: None,
4551
entry_points_by_type: (&class.entry_points_by_type).into(),
46-
}
52+
})
4753
}
4854

4955
/// Fetch class from the state reader and contract manager.
@@ -65,7 +71,7 @@ where
6571
Err(ClassesProviderError::DeprecatedContractError(class_hash))
6672
}
6773
RunnableCompiledClass::V1(compiled_class_v1) => {
68-
let casm = compiled_class_v1_to_casm(&compiled_class_v1);
74+
let casm = compiled_class_v1_to_casm(&compiled_class_v1)?;
6975
Ok((compiled_class_hash, casm))
7076
}
7177
#[cfg(feature = "cairo_native")]
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use blockifier::execution::contract_class::CompiledClassV1;
2+
use blockifier::test_utils::contracts::FeatureContractTrait;
3+
use blockifier_test_utils::cairo_versions::{CairoVersion, RunnableCairo1};
4+
use blockifier_test_utils::contracts::FeatureContract;
5+
use starknet_api::contract_class::ContractClass;
6+
7+
use crate::classes_provider::compiled_class_v1_to_casm;
8+
9+
/// Tests the round-trip conversion: CasmContractClass -> CompiledClassV1 -> CasmContractClass
10+
/// Verifies that all relevant fields are preserved (except compiler_version and pythonic_hints
11+
/// which are not loaded to the OS).
12+
#[test]
13+
fn test_compiled_class_v1_to_casm_round_trip() {
14+
// Get a test contract that has hints and entry points.
15+
let feature_contract =
16+
FeatureContract::TestContract(CairoVersion::Cairo1(RunnableCairo1::Casm));
17+
let (mut original_casm, sierra_version) = match feature_contract.get_class() {
18+
ContractClass::V1(versioned_casm) => versioned_casm,
19+
_ => panic!("Expected ContractClass::V1"),
20+
};
21+
22+
// Ignore fields that are not loaded to the OS.
23+
original_casm.compiler_version = String::new();
24+
original_casm.pythonic_hints = None;
25+
26+
// Convert CasmContractClass to CompiledClassV1.
27+
let compiled_class_v1 = CompiledClassV1::try_from((original_casm.clone(), sierra_version))
28+
.expect("Failed to convert CasmContractClass to CompiledClassV1");
29+
30+
// Convert back to CasmContractClass using compiled_class_v1_to_casm.
31+
let round_tripped_casm = compiled_class_v1_to_casm(&compiled_class_v1)
32+
.expect("Failed to convert CompiledClassV1 back to CasmContractClass");
33+
34+
// Verify that the round-tripped CasmContractClass is equal to the original.
35+
assert_eq!(round_tripped_casm, original_casm);
36+
}

crates/starknet_os_runner/src/errors.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use blockifier::state::errors::StateError;
22
use blockifier_reexecution::errors::ReexecutionError;
3+
use cairo_vm::types::errors::program_errors::ProgramError;
34
use starknet_api::core::ClassHash;
45
use starknet_os::errors::StarknetOsError;
56
use starknet_rust::providers::ProviderError;
@@ -49,4 +50,6 @@ pub enum ClassesProviderError {
4950
DeprecatedContractError(ClassHash),
5051
#[error(transparent)]
5152
StateError(#[from] StateError),
53+
#[error(transparent)]
54+
ContractClassConversionError(#[from] ProgramError),
5255
}

crates/starknet_os_runner/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ pub mod runner;
44
pub mod storage_proofs;
55
pub mod virtual_block_executor;
66

7+
#[cfg(test)]
8+
mod classes_provider_test;
79
#[cfg(test)]
810
mod storage_proofs_test;
911
#[cfg(test)]

0 commit comments

Comments
 (0)