-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(starknet_os): move deprecated_compiled_class hints implement…
…ation (#4655)
- Loading branch information
1 parent
fa86db8
commit d45ab33
Showing
3 changed files
with
141 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
140 changes: 1 addition & 139 deletions
140
crates/starknet_os/src/hints/hint_implementation/deprecated_compiled_class.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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( | ||
¶ms.code, | ||
¶ms.flow_tracking_data.ap_tracking, | ||
¶ms.flow_tracking_data.reference_ids, | ||
&refs, | ||
)?; | ||
compiled_hints.push(compiled_hint); | ||
} | ||
hint_extension.insert(abs_pc, compiled_hints); | ||
} | ||
|
||
Ok(hint_extension) | ||
} | ||
pub mod implementation; |
139 changes: 139 additions & 0 deletions
139
crates/starknet_os/src/hints/hint_implementation/deprecated_compiled_class/implementation.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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( | ||
¶ms.code, | ||
¶ms.flow_tracking_data.ap_tracking, | ||
¶ms.flow_tracking_data.reference_ids, | ||
&refs, | ||
)?; | ||
compiled_hints.push(compiled_hint); | ||
} | ||
hint_extension.insert(abs_pc, compiled_hints); | ||
} | ||
|
||
Ok(hint_extension) | ||
} |