Skip to content

Commit

Permalink
refactor(starknet_os): move deprecated_compiled_class hints implement…
Browse files Browse the repository at this point in the history
…ation (#4655)
  • Loading branch information
rotem-starkware authored Mar 4, 2025
1 parent fa86db8 commit d45ab33
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 140 deletions.
2 changes: 1 addition & 1 deletion crates/starknet_os/src/hints/enum_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use crate::hints::hint_implementation::compiled_class::{
set_ap_to_segment_hash,
validate_compiled_class_facts_post_execution,
};
use crate::hints::hint_implementation::deprecated_compiled_class::{
use crate::hints::hint_implementation::deprecated_compiled_class::implementation::{
load_deprecated_class,
load_deprecated_class_facts,
load_deprecated_class_inner,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,139 +1 @@
use std::any::Any;
use std::collections::{HashMap, HashSet};

use blockifier::execution::contract_class::{CompiledClassV0, RunnableCompiledClass};
use blockifier::state::state_api::StateReader;
use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::insert_value_from_var_name;
use cairo_vm::hint_processor::hint_processor_definition::{
HintExtension,
HintProcessorLogic,
HintReference,
};
use cairo_vm::serde::deserialize_program::{HintParams, ReferenceManager};
use cairo_vm::types::relocatable::Relocatable;
use cairo_vm::vm::errors::hint_errors::HintError as VmHintError;
use starknet_api::core::ClassHash;
use starknet_api::deprecated_contract_class::ContractClass;
use starknet_types_core::felt::Felt;

use crate::hints::error::{OsHintError, OsHintExtensionResult, OsHintResult};
use crate::hints::types::HintArgs;
use crate::hints::vars::{CairoStruct, Ids, Scope};
use crate::vm_utils::get_address_of_nested_fields;

pub(crate) fn load_deprecated_class_facts<S: StateReader>(
HintArgs { hint_processor, vm, exec_scopes, ids_data, ap_tracking, .. }: HintArgs<'_, S>,
) -> OsHintResult {
// TODO(Nimrod): See if we can avoid cloning here.
let deprecated_compiled_classes: HashMap<ClassHash, CompiledClassV0> = hint_processor
.execution_helper
.cached_state
.class_hash_to_class
.borrow()
.iter()
.filter_map(|(class_hash, class)| {
if let RunnableCompiledClass::V0(deprecated_class) = class {
Some((*class_hash, deprecated_class.clone()))
} else {
None
}
})
.collect();
// TODO(Rotem): see if we can avoid cloning here.
let deprecated_class_hashes: HashSet<ClassHash> =
HashSet::from_iter(deprecated_compiled_classes.keys().cloned());
exec_scopes.insert_value(Scope::DeprecatedClassHashes.into(), deprecated_class_hashes);

insert_value_from_var_name(
Ids::NCompiledClassFacts.into(),
deprecated_compiled_classes.len(),
vm,
ids_data,
ap_tracking,
)?;
let scoped_classes: Box<dyn Any> = Box::new(deprecated_compiled_classes.into_iter());
exec_scopes
.enter_scope(HashMap::from([(Scope::CompiledClassFacts.to_string(), scoped_classes)]));

Ok(())
}

pub(crate) fn load_deprecated_class_inner<S: StateReader>(
HintArgs { .. }: HintArgs<'_, S>,
) -> OsHintResult {
todo!()
}

pub(crate) fn load_deprecated_class<S: StateReader>(
HintArgs { hint_processor, vm, exec_scopes, ids_data, ap_tracking, .. }: HintArgs<'_, S>,
) -> OsHintExtensionResult {
let computed_hash_addr = get_address_of_nested_fields(
ids_data,
Ids::CompiledClassFact,
CairoStruct::DeprecatedCompiledClassFact,
vm,
ap_tracking,
&["hash".to_string()],
&hint_processor.execution_helper.os_program,
)?;
let computed_hash = vm.get_integer(computed_hash_addr)?;
let expected_hash = exec_scopes.get::<Felt>(Scope::CompiledClassHash.into())?;

if computed_hash.as_ref() != &expected_hash {
return Err(OsHintError::AssertionFailed {
message: format!(
"Computed compiled_class_hash is inconsistent with the hash in the os_input. \
Computed hash = {computed_hash}, Expected hash = {expected_hash}."
),
});
}

let dep_class = exec_scopes.get::<ContractClass>(Scope::CompiledClass.into())?;

// TODO(Rotem): see if we can avoid cloning here.
let hints: HashMap<String, Vec<HintParams>> =
serde_json::from_value(dep_class.program.hints.clone()).map_err(|e| {
OsHintError::SerdeJsonError { error: e, value: dep_class.program.hints }
})?;
let ref_manager: ReferenceManager =
serde_json::from_value(dep_class.program.reference_manager.clone()).map_err(|e| {
OsHintError::SerdeJsonError { error: e, value: dep_class.program.reference_manager }
})?;

let refs = ref_manager
.references
.iter()
.map(|r| HintReference::from(r.clone()))
.collect::<Vec<HintReference>>();

let byte_code_ptr_addr = get_address_of_nested_fields(
ids_data,
Ids::CompiledClass,
CairoStruct::DeprecatedCompiledClass,
vm,
ap_tracking,
&["bytecode_ptr".to_string()],
&hint_processor.execution_helper.os_program,
)?;
let byte_code_ptr = vm.get_relocatable(byte_code_ptr_addr)?;

let mut hint_extension = HintExtension::new();

for (pc, hints_params) in hints.into_iter() {
let rel_pc = pc.parse().map_err(|_| VmHintError::WrongHintData)?;
let abs_pc = Relocatable::from((byte_code_ptr.segment_index, rel_pc));
let mut compiled_hints = Vec::new();
for params in hints_params.into_iter() {
let compiled_hint = hint_processor.compile_hint(
&params.code,
&params.flow_tracking_data.ap_tracking,
&params.flow_tracking_data.reference_ids,
&refs,
)?;
compiled_hints.push(compiled_hint);
}
hint_extension.insert(abs_pc, compiled_hints);
}

Ok(hint_extension)
}
pub mod implementation;
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
use std::any::Any;
use std::collections::{HashMap, HashSet};

use blockifier::execution::contract_class::{CompiledClassV0, RunnableCompiledClass};
use blockifier::state::state_api::StateReader;
use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::insert_value_from_var_name;
use cairo_vm::hint_processor::hint_processor_definition::{
HintExtension,
HintProcessorLogic,
HintReference,
};
use cairo_vm::serde::deserialize_program::{HintParams, ReferenceManager};
use cairo_vm::types::relocatable::Relocatable;
use cairo_vm::vm::errors::hint_errors::HintError as VmHintError;
use starknet_api::core::ClassHash;
use starknet_api::deprecated_contract_class::ContractClass;
use starknet_types_core::felt::Felt;

use crate::hints::error::{OsHintError, OsHintExtensionResult, OsHintResult};
use crate::hints::types::HintArgs;
use crate::hints::vars::{CairoStruct, Ids, Scope};
use crate::vm_utils::get_address_of_nested_fields;

pub(crate) fn load_deprecated_class_facts<S: StateReader>(
HintArgs { hint_processor, vm, exec_scopes, ids_data, ap_tracking, .. }: HintArgs<'_, S>,
) -> OsHintResult {
// TODO(Nimrod): See if we can avoid cloning here.
let deprecated_compiled_classes: HashMap<ClassHash, CompiledClassV0> = hint_processor
.execution_helper
.cached_state
.class_hash_to_class
.borrow()
.iter()
.filter_map(|(class_hash, class)| {
if let RunnableCompiledClass::V0(deprecated_class) = class {
Some((*class_hash, deprecated_class.clone()))
} else {
None
}
})
.collect();
// TODO(Rotem): see if we can avoid cloning here.
let deprecated_class_hashes: HashSet<ClassHash> =
HashSet::from_iter(deprecated_compiled_classes.keys().cloned());
exec_scopes.insert_value(Scope::DeprecatedClassHashes.into(), deprecated_class_hashes);

insert_value_from_var_name(
Ids::NCompiledClassFacts.into(),
deprecated_compiled_classes.len(),
vm,
ids_data,
ap_tracking,
)?;
let scoped_classes: Box<dyn Any> = Box::new(deprecated_compiled_classes.into_iter());
exec_scopes
.enter_scope(HashMap::from([(Scope::CompiledClassFacts.to_string(), scoped_classes)]));

Ok(())
}

pub(crate) fn load_deprecated_class_inner<S: StateReader>(
HintArgs { .. }: HintArgs<'_, S>,
) -> OsHintResult {
todo!()
}

pub(crate) fn load_deprecated_class<S: StateReader>(
HintArgs { hint_processor, vm, exec_scopes, ids_data, ap_tracking, .. }: HintArgs<'_, S>,
) -> OsHintExtensionResult {
let computed_hash_addr = get_address_of_nested_fields(
ids_data,
Ids::CompiledClassFact,
CairoStruct::DeprecatedCompiledClassFact,
vm,
ap_tracking,
&["hash".to_string()],
&hint_processor.execution_helper.os_program,
)?;
let computed_hash = vm.get_integer(computed_hash_addr)?;
let expected_hash = exec_scopes.get::<Felt>(Scope::CompiledClassHash.into())?;

if computed_hash.as_ref() != &expected_hash {
return Err(OsHintError::AssertionFailed {
message: format!(
"Computed compiled_class_hash is inconsistent with the hash in the os_input. \
Computed hash = {computed_hash}, Expected hash = {expected_hash}."
),
});
}

let dep_class = exec_scopes.get::<ContractClass>(Scope::CompiledClass.into())?;

// TODO(Rotem): see if we can avoid cloning here.
let hints: HashMap<String, Vec<HintParams>> =
serde_json::from_value(dep_class.program.hints.clone()).map_err(|e| {
OsHintError::SerdeJsonError { error: e, value: dep_class.program.hints }
})?;
let ref_manager: ReferenceManager =
serde_json::from_value(dep_class.program.reference_manager.clone()).map_err(|e| {
OsHintError::SerdeJsonError { error: e, value: dep_class.program.reference_manager }
})?;

let refs = ref_manager
.references
.iter()
.map(|r| HintReference::from(r.clone()))
.collect::<Vec<HintReference>>();

let byte_code_ptr_addr = get_address_of_nested_fields(
ids_data,
Ids::CompiledClass,
CairoStruct::DeprecatedCompiledClass,
vm,
ap_tracking,
&["bytecode_ptr".to_string()],
&hint_processor.execution_helper.os_program,
)?;
let byte_code_ptr = vm.get_relocatable(byte_code_ptr_addr)?;

let mut hint_extension = HintExtension::new();

for (pc, hints_params) in hints.into_iter() {
let rel_pc = pc.parse().map_err(|_| VmHintError::WrongHintData)?;
let abs_pc = Relocatable::from((byte_code_ptr.segment_index, rel_pc));
let mut compiled_hints = Vec::new();
for params in hints_params.into_iter() {
let compiled_hint = hint_processor.compile_hint(
&params.code,
&params.flow_tracking_data.ap_tracking,
&params.flow_tracking_data.reference_ids,
&refs,
)?;
compiled_hints.push(compiled_hint);
}
hint_extension.insert(abs_pc, compiled_hints);
}

Ok(hint_extension)
}

0 comments on commit d45ab33

Please sign in to comment.