From 0760f22fd5391d22f884d25a2650f13629337579 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 22 Nov 2023 16:25:47 -0300 Subject: [PATCH 01/23] Usa a Hashmap for HintRanges --- vm/src/types/program.rs | 45 +++++++++++++++---------------- vm/src/vm/hooks.rs | 1 - vm/src/vm/runners/cairo_runner.rs | 16 +++++------ vm/src/vm/vm_core.rs | 1 - 4 files changed, 27 insertions(+), 36 deletions(-) diff --git a/vm/src/types/program.rs b/vm/src/types/program.rs index 2ba347e6a2..5c11080297 100644 --- a/vm/src/types/program.rs +++ b/vm/src/types/program.rs @@ -34,6 +34,8 @@ use std::path::Path; #[cfg(all(feature = "arbitrary", feature = "std"))] use arbitrary::{Arbitrary, Unstructured}; +use super::relocatable::Relocatable; + // NOTE: `Program` has been split in two containing some data that will be deep-copied // and some that will be allocated on the heap inside an `Arc<_>`. // This is because it has been reported that cloning the whole structure when creating @@ -106,7 +108,7 @@ impl<'a> Arbitrary<'a> for SharedProgramData { pub(crate) struct HintsCollection { hints: Vec, /// This maps a PC to the range of hints in `hints` that correspond to it. - hints_ranges: Vec, + hints_ranges: HashMap, } impl HintsCollection { @@ -122,7 +124,7 @@ impl HintsCollection { let Some((max_hint_pc, full_len)) = bounds else { return Ok(HintsCollection { hints: Vec::new(), - hints_ranges: Vec::new(), + hints_ranges: HashMap::new(), }); }; @@ -131,14 +133,14 @@ impl HintsCollection { } let mut hints_values = Vec::with_capacity(full_len); - let mut hints_ranges = vec![None; max_hint_pc + 1]; + let mut hints_ranges = HashMap::new(); for (pc, hs) in hints.iter().filter(|(_, hs)| !hs.is_empty()) { let range = ( hints_values.len(), NonZeroUsize::new(hs.len()).expect("empty vecs already filtered"), ); - hints_ranges[*pc] = Some(range); + hints_ranges.insert(Relocatable::from((0_isize, *pc)), range); hints_values.extend_from_slice(&hs[..]); } @@ -152,28 +154,23 @@ impl HintsCollection { self.hints.iter() } - pub fn get_hint_range_for_pc(&self, pc: usize) -> Option { - self.hints_ranges.get(pc).cloned() + pub fn get_hint_range_for_pc(&self, pc: Relocatable) -> Option { + self.hints_ranges.get(&pc).cloned() } } -impl From<&HintsCollection> for BTreeMap> { - fn from(hc: &HintsCollection) -> Self { - let mut hint_map = BTreeMap::new(); - for (i, r) in hc.hints_ranges.iter().enumerate() { - let Some(r) = r else { - continue; - }; - hint_map.insert(i, hc.hints[r.0..r.0 + r.1.get()].to_owned()); - } - hint_map - } -} +// impl From<&HintsCollection> for BTreeMap> { +// fn from(hc: &HintsCollection) -> Self { +// let mut hint_map = BTreeMap::new(); +// for (pc, r) in hc.hints_ranges.iter() { +// hint_map.insert(i, hc.hints[r.0..r.0 + r.1.get()].to_owned()); +// } +// hint_map +// } +// } -/// Represents a range of hints corresponding to a PC. -/// -/// Is [`None`] if the range is empty, and it is [`Some`] tuple `(start, length)` otherwise. -type HintRange = Option<(usize, NonZeroUsize)>; +/// Represents a range of hints corresponding to a PC as a tuple `(start, length)`. +type HintRange = (usize, NonZeroUsize); #[cfg_attr(all(feature = "arbitrary", feature = "std"), derive(Arbitrary))] #[derive(Clone, Debug, PartialEq, Eq)] @@ -493,7 +490,7 @@ mod tests { ); assert_eq!( program.shared_program_data.hints_collection.hints_ranges, - Vec::new() + HashMap::new() ); } @@ -1250,7 +1247,7 @@ mod tests { fn default_program() { let hints_collection = HintsCollection { hints: Vec::new(), - hints_ranges: Vec::new(), + hints_ranges: HashMap::new(), }; let shared_program_data = SharedProgramData { diff --git a/vm/src/vm/hooks.rs b/vm/src/vm/hooks.rs index b0b6e3c484..e67fbb621e 100644 --- a/vm/src/vm/hooks.rs +++ b/vm/src/vm/hooks.rs @@ -218,7 +218,6 @@ mod tests { fn before_first_step_hook( _vm: &mut VirtualMachine, _runner: &mut CairoRunner, - _hint_data: &[Box], ) -> Result<(), VirtualMachineError> { Ok(()) } diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index b9507b4e75..deadb0c852 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -550,16 +550,14 @@ impl CairoRunner { let references = &self.program.shared_program_data.reference_manager; let hint_data = self.get_hint_data(references, hint_processor)?; #[cfg(feature = "hooks")] - vm.execute_before_first_step(self, &hint_data)?; + vm.execute_before_first_step(self)?; while vm.run_context.pc != address && !hint_processor.consumed() { let hint_data = &self .program .shared_program_data .hints_collection - .get_hint_range_for_pc(vm.run_context.pc.offset) - .and_then(|range| { - range.and_then(|(start, length)| hint_data.get(start..start + length.get())) - }) + .get_hint_range_for_pc(vm.run_context.pc) + .and_then(|(start, length)| hint_data.get(start..start + length.get())) .unwrap_or(&[]); vm.step( hint_processor, @@ -592,14 +590,12 @@ impl CairoRunner { return Err(VirtualMachineError::EndOfProgram(remaining_steps)); } - let hint_data = self + let hint_data = &self .program .shared_program_data .hints_collection - .get_hint_range_for_pc(vm.run_context.pc.offset) - .and_then(|range| { - range.and_then(|(start, length)| hint_data.get(start..start + length.get())) - }) + .get_hint_range_for_pc(vm.run_context.pc) + .and_then(|(start, length)| hint_data.get(start..start + length.get())) .unwrap_or(&[]); vm.step( hint_processor, diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 3bc833adad..6dcbd3dae9 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -4238,7 +4238,6 @@ mod tests { fn before_first_step_hook( _vm: &mut VirtualMachine, _runner: &mut CairoRunner, - _hint_data: &[Box], ) -> Result<(), VirtualMachineError> { Err(VirtualMachineError::Unexpected) } From 980f15f65d44c6348b6cfcba1a53baad8c3acbed Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 22 Nov 2023 19:05:06 -0300 Subject: [PATCH 02/23] Add execute_and_mutate_hints --- .../hint_processor_definition.rs | 28 + vm/src/serde/serialize_program.rs | 18 +- vm/src/types/program.rs | 1726 ++++++++--------- vm/src/vm/runners/cairo_runner.rs | 36 +- vm/src/vm/vm_core.rs | 28 +- 5 files changed, 935 insertions(+), 901 deletions(-) diff --git a/vm/src/hint_processor/hint_processor_definition.rs b/vm/src/hint_processor/hint_processor_definition.rs index 6e2912af3d..ca62bc3db8 100644 --- a/vm/src/hint_processor/hint_processor_definition.rs +++ b/vm/src/hint_processor/hint_processor_definition.rs @@ -6,6 +6,8 @@ use crate::serde::deserialize_program::OffsetValue; use crate::serde::deserialize_program::Reference; use crate::types::exec_scope::ExecutionScopes; use crate::types::instruction::Register; +use crate::types::program::HintRange; +use crate::types::relocatable::Relocatable; use crate::vm::errors::hint_errors::HintError; use crate::vm::errors::vm_errors::VirtualMachineError; use crate::vm::runners::cairo_runner::ResourceTracker; @@ -52,6 +54,32 @@ pub trait HintProcessorLogic { ids_data: get_ids_data(reference_ids, references)?, })) } + + //Executes the hint which's data is provided by a dynamic structure previously created by compile_hint + fn execute_and_mutate_hints( + &mut self, + //Proxy to VM, contains refrences to necessary data + //+ MemoryProxy, which provides the necessary methods to manipulate memory + vm: &mut VirtualMachine, + //Proxy to ExecutionScopes, provides the necessary methods to manipulate the scopes and + //access current scope variables + exec_scopes: &mut ExecutionScopes, + //Constant values extracted from the program specification. + constants: &HashMap, + // hint muatbles + mutable_hints: &mut [Box], + mutable_ranges: &mut HashMap, + ) -> Result<(), VirtualMachineError> { + let hint_range = &mutable_ranges + .get(&vm.run_context.pc) + .and_then(|(start, length)| mutable_hints.get(*start..*start + length.get())) + .unwrap_or(&[]); + for (hint_index, hint_data) in hint_range.iter().enumerate() { + self.execute_hint(vm, exec_scopes, hint_data, constants) + .map_err(|err| VirtualMachineError::Hint(Box::new((hint_index, err))))? + } + Ok(()) + } } pub trait HintProcessor: HintProcessorLogic + ResourceTracker {} diff --git a/vm/src/serde/serialize_program.rs b/vm/src/serde/serialize_program.rs index 5f55e3fd75..ace6402256 100644 --- a/vm/src/serde/serialize_program.rs +++ b/vm/src/serde/serialize_program.rs @@ -208,15 +208,15 @@ impl From<&Program> for ProgramSerializer { identifiers.insert(key, identifier.into()); } - let mut hints: BTreeMap> = BTreeMap::new(); - for (key, hint_params_vec) in BTreeMap::from(&program.shared_program_data.hints_collection) - { - let mut new_hints_params = Vec::new(); - for hint_params in hint_params_vec { - new_hints_params.push(hint_params.clone().into()); - } - hints.insert(key, new_hints_params); - } + let hints: BTreeMap> = BTreeMap::new(); + // for (key, hint_params_vec) in BTreeMap::from(&program.shared_program_data.hints_collection) + // { + // let mut new_hints_params = Vec::new(); + // for hint_params in hint_params_vec { + // new_hints_params.push(hint_params.clone().into()); + // } + // hints.insert(key, new_hints_params); + // } ProgramSerializer { prime: program.prime().into(), diff --git a/vm/src/types/program.rs b/vm/src/types/program.rs index 5c11080297..6a0138cfee 100644 --- a/vm/src/types/program.rs +++ b/vm/src/types/program.rs @@ -108,7 +108,7 @@ impl<'a> Arbitrary<'a> for SharedProgramData { pub(crate) struct HintsCollection { hints: Vec, /// This maps a PC to the range of hints in `hints` that correspond to it. - hints_ranges: HashMap, + pub(crate) hints_ranges: HashMap, } impl HintsCollection { @@ -153,10 +153,6 @@ impl HintsCollection { pub fn iter_hints(&self) -> impl Iterator { self.hints.iter() } - - pub fn get_hint_range_for_pc(&self, pc: Relocatable) -> Option { - self.hints_ranges.get(&pc).cloned() - } } // impl From<&HintsCollection> for BTreeMap> { @@ -170,7 +166,7 @@ impl HintsCollection { // } /// Represents a range of hints corresponding to a PC as a tuple `(start, length)`. -type HintRange = (usize, NonZeroUsize); +pub type HintRange = (usize, NonZeroUsize); #[cfg_attr(all(feature = "arbitrary", feature = "std"), derive(Arbitrary))] #[derive(Clone, Debug, PartialEq, Eq)] @@ -419,880 +415,880 @@ impl TryFrom for Program { } } -#[cfg(test)] -impl HintsCollection { - pub fn iter(&self) -> impl Iterator { - self.hints_ranges - .iter() - .enumerate() - .filter_map(|(pc, range)| { - range.and_then(|(start, len)| { - let end = start + len.get(); - if end <= self.hints.len() { - Some((pc, &self.hints[start..end])) - } else { - None - } - }) - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::serde::deserialize_program::{ApTracking, FlowTrackingData}; - use crate::utils::test_utils::*; - use felt::felt_str; - use num_traits::Zero; - - use assert_matches::assert_matches; - - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::*; - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn new() { - let reference_manager = ReferenceManager { - references: Vec::new(), - }; - - let builtins: Vec = Vec::new(); - let data: Vec = vec![ - mayberelocatable!(5189976364521848832), - mayberelocatable!(1000), - mayberelocatable!(5189976364521848832), - mayberelocatable!(2000), - mayberelocatable!(5201798304953696256), - mayberelocatable!(2345108766317314046), - ]; - - let program = Program::new( - builtins.clone(), - data.clone(), - None, - HashMap::new(), - reference_manager, - HashMap::new(), - Vec::new(), - None, - ) - .unwrap(); - - assert_eq!(program.builtins, builtins); - assert_eq!(program.shared_program_data.data, data); - assert_eq!(program.shared_program_data.main, None); - assert_eq!(program.shared_program_data.identifiers, HashMap::new()); - assert_eq!( - program.shared_program_data.hints_collection.hints, - Vec::new() - ); - assert_eq!( - program.shared_program_data.hints_collection.hints_ranges, - HashMap::new() - ); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn new_for_proof() { - let reference_manager = ReferenceManager { - references: Vec::new(), - }; - - let builtins: Vec = Vec::new(); - let data: Vec = vec![ - mayberelocatable!(5189976364521848832), - mayberelocatable!(1000), - mayberelocatable!(5189976364521848832), - mayberelocatable!(2000), - mayberelocatable!(5201798304953696256), - mayberelocatable!(2345108766317314046), - ]; - - let program = Program::new_for_proof( - builtins.clone(), - data.clone(), - 0, - 1, - HashMap::new(), - reference_manager, - HashMap::new(), - Vec::new(), - None, - ) - .unwrap(); - - assert_eq!(program.builtins, builtins); - assert_eq!(program.shared_program_data.data, data); - assert_eq!(program.shared_program_data.main, None); - assert_eq!(program.shared_program_data.start, Some(0)); - assert_eq!(program.shared_program_data.end, Some(1)); - assert_eq!(program.shared_program_data.identifiers, HashMap::new()); - assert_eq!( - program.shared_program_data.hints_collection.hints, - Vec::new() - ); - assert_eq!( - program.shared_program_data.hints_collection.hints_ranges, - Vec::new() - ); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn new_program_with_hints() { - let reference_manager = ReferenceManager { - references: Vec::new(), - }; - - let builtins: Vec = Vec::new(); - let data: Vec = vec![ - mayberelocatable!(5189976364521848832), - mayberelocatable!(1000), - mayberelocatable!(5189976364521848832), - mayberelocatable!(2000), - mayberelocatable!(5201798304953696256), - mayberelocatable!(2345108766317314046), - ]; - - let str_to_hint_param = |s: &str| HintParams { - code: s.to_string(), - accessible_scopes: vec![], - flow_tracking_data: FlowTrackingData { - ap_tracking: ApTracking { - group: 0, - offset: 0, - }, - reference_ids: HashMap::new(), - }, - }; - - let hints = HashMap::from([ - (5, vec![str_to_hint_param("c"), str_to_hint_param("d")]), - (1, vec![str_to_hint_param("a")]), - (4, vec![str_to_hint_param("b")]), - ]); - - let program = Program::new( - builtins.clone(), - data.clone(), - None, - hints.clone(), - reference_manager, - HashMap::new(), - Vec::new(), - None, - ) - .unwrap(); - - assert_eq!(program.builtins, builtins); - assert_eq!(program.shared_program_data.data, data); - assert_eq!(program.shared_program_data.main, None); - assert_eq!(program.shared_program_data.identifiers, HashMap::new()); - - let program_hints: HashMap<_, _> = program - .shared_program_data - .hints_collection - .hints_ranges - .iter() - .enumerate() - .filter_map(|(pc, r)| r.map(|(s, l)| (pc, (s, s + l.get())))) - .map(|(pc, (s, e))| { - ( - pc, - program.shared_program_data.hints_collection.hints[s..e].to_vec(), - ) - }) - .collect(); - assert_eq!(program_hints, hints); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn new_program_with_identifiers() { - let reference_manager = ReferenceManager { - references: Vec::new(), - }; - - let builtins: Vec = Vec::new(); - - let data: Vec = vec![ - mayberelocatable!(5189976364521848832), - mayberelocatable!(1000), - mayberelocatable!(5189976364521848832), - mayberelocatable!(2000), - mayberelocatable!(5201798304953696256), - mayberelocatable!(2345108766317314046), - ]; - - let mut identifiers: HashMap = HashMap::new(); - - identifiers.insert( - String::from("__main__.main"), - Identifier { - pc: Some(0), - type_: Some(String::from("function")), - value: None, - full_name: None, - members: None, - cairo_type: None, - }, - ); - - identifiers.insert( - String::from("__main__.main.SIZEOF_LOCALS"), - Identifier { - pc: None, - type_: Some(String::from("const")), - value: Some(Felt252::zero()), - full_name: None, - members: None, - cairo_type: None, - }, - ); - - let program = Program::new( - builtins.clone(), - data.clone(), - None, - HashMap::new(), - reference_manager, - identifiers.clone(), - Vec::new(), - None, - ) - .unwrap(); - - assert_eq!(program.builtins, builtins); - assert_eq!(program.shared_program_data.data, data); - assert_eq!(program.shared_program_data.main, None); - assert_eq!(program.shared_program_data.identifiers, identifiers); - assert_eq!( - program.constants, - [("__main__.main.SIZEOF_LOCALS", Felt252::zero())] - .into_iter() - .map(|(key, value)| (key.to_string(), value)) - .collect::>(), - ); - } - - #[test] - fn extract_constants() { - let mut identifiers: HashMap = HashMap::new(); - - identifiers.insert( - String::from("__main__.main"), - Identifier { - pc: Some(0), - type_: Some(String::from("function")), - value: None, - full_name: None, - members: None, - cairo_type: None, - }, - ); - - identifiers.insert( - String::from("__main__.main.SIZEOF_LOCALS"), - Identifier { - pc: None, - type_: Some(String::from("const")), - value: Some(Felt252::zero()), - full_name: None, - members: None, - cairo_type: None, - }, - ); - - assert_eq!( - Program::extract_constants(&identifiers).unwrap(), - [("__main__.main.SIZEOF_LOCALS", Felt252::zero())] - .into_iter() - .map(|(key, value)| (key.to_string(), value)) - .collect::>(), - ); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn get_prime() { - let program = Program::default(); - assert_eq!(PRIME_STR, program.prime()); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn iter_builtins() { - let reference_manager = ReferenceManager { - references: Vec::new(), - }; - - let builtins: Vec<_> = vec![BuiltinName::range_check, BuiltinName::bitwise]; - let data: Vec<_> = vec![ - mayberelocatable!(5189976364521848832), - mayberelocatable!(1000), - mayberelocatable!(5189976364521848832), - mayberelocatable!(2000), - mayberelocatable!(5201798304953696256), - mayberelocatable!(2345108766317314046), - ]; - - let program = Program::new( - builtins.clone(), - data, - None, - HashMap::new(), - reference_manager, - HashMap::new(), - Vec::new(), - None, - ) - .unwrap(); - - assert_eq!( - program.iter_builtins().cloned().collect::>(), - builtins - ); - - assert_eq!(program.builtins_len(), 2); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn iter_data() { - let reference_manager = ReferenceManager { - references: Vec::new(), - }; - - let builtins: Vec = Vec::new(); - let data: Vec = vec![ - mayberelocatable!(5189976364521848832), - mayberelocatable!(1000), - mayberelocatable!(5189976364521848832), - mayberelocatable!(2000), - mayberelocatable!(5201798304953696256), - mayberelocatable!(2345108766317314046), - ]; - - let program = Program::new( - builtins, - data.clone(), - None, - HashMap::new(), - reference_manager, - HashMap::new(), - Vec::new(), - None, - ) - .unwrap(); - - assert_eq!(program.iter_data().cloned().collect::>(), data); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn data_len() { - let reference_manager = ReferenceManager { - references: Vec::new(), - }; - - let builtins: Vec = Vec::new(); - let data: Vec = vec![ - mayberelocatable!(5189976364521848832), - mayberelocatable!(1000), - mayberelocatable!(5189976364521848832), - mayberelocatable!(2000), - mayberelocatable!(5201798304953696256), - mayberelocatable!(2345108766317314046), - ]; - - let program = Program::new( - builtins, - data.clone(), - None, - HashMap::new(), - reference_manager, - HashMap::new(), - Vec::new(), - None, - ) - .unwrap(); +// #[cfg(test)] +// impl HintsCollection { +// pub fn iter(&self) -> impl Iterator { +// self.hints_ranges +// .iter() +// .enumerate() +// .filter_map(|(pc, range)| { +// range.and_then(|(start, len)| { +// let end = start + len.get(); +// if end <= self.hints.len() { +// Some((pc, &self.hints[start..end])) +// } else { +// None +// } +// }) +// }) +// } +// } - assert_eq!(program.data_len(), data.len()); - } +// #[cfg(test)] +// mod tests { +// use super::*; +// use crate::serde::deserialize_program::{ApTracking, FlowTrackingData}; +// use crate::utils::test_utils::*; +// use felt::felt_str; +// use num_traits::Zero; + +// use assert_matches::assert_matches; + +// #[cfg(target_arch = "wasm32")] +// use wasm_bindgen_test::*; + +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn new() { +// let reference_manager = ReferenceManager { +// references: Vec::new(), +// }; + +// let builtins: Vec = Vec::new(); +// let data: Vec = vec![ +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(1000), +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(2000), +// mayberelocatable!(5201798304953696256), +// mayberelocatable!(2345108766317314046), +// ]; + +// let program = Program::new( +// builtins.clone(), +// data.clone(), +// None, +// HashMap::new(), +// reference_manager, +// HashMap::new(), +// Vec::new(), +// None, +// ) +// .unwrap(); + +// assert_eq!(program.builtins, builtins); +// assert_eq!(program.shared_program_data.data, data); +// assert_eq!(program.shared_program_data.main, None); +// assert_eq!(program.shared_program_data.identifiers, HashMap::new()); +// assert_eq!( +// program.shared_program_data.hints_collection.hints, +// Vec::new() +// ); +// assert_eq!( +// program.shared_program_data.hints_collection.hints_ranges, +// HashMap::new() +// ); +// } - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn get_identifier() { - let reference_manager = ReferenceManager { - references: Vec::new(), - }; +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn new_for_proof() { +// let reference_manager = ReferenceManager { +// references: Vec::new(), +// }; + +// let builtins: Vec = Vec::new(); +// let data: Vec = vec![ +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(1000), +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(2000), +// mayberelocatable!(5201798304953696256), +// mayberelocatable!(2345108766317314046), +// ]; + +// let program = Program::new_for_proof( +// builtins.clone(), +// data.clone(), +// 0, +// 1, +// HashMap::new(), +// reference_manager, +// HashMap::new(), +// Vec::new(), +// None, +// ) +// .unwrap(); + +// assert_eq!(program.builtins, builtins); +// assert_eq!(program.shared_program_data.data, data); +// assert_eq!(program.shared_program_data.main, None); +// assert_eq!(program.shared_program_data.start, Some(0)); +// assert_eq!(program.shared_program_data.end, Some(1)); +// assert_eq!(program.shared_program_data.identifiers, HashMap::new()); +// assert_eq!( +// program.shared_program_data.hints_collection.hints, +// Vec::new() +// ); +// assert_eq!( +// program.shared_program_data.hints_collection.hints_ranges, +// Vec::new() +// ); +// } - let builtins: Vec = Vec::new(); - - let data: Vec = vec![ - mayberelocatable!(5189976364521848832), - mayberelocatable!(1000), - mayberelocatable!(5189976364521848832), - mayberelocatable!(2000), - mayberelocatable!(5201798304953696256), - mayberelocatable!(2345108766317314046), - ]; - - let mut identifiers: HashMap = HashMap::new(); - - identifiers.insert( - String::from("__main__.main"), - Identifier { - pc: Some(0), - type_: Some(String::from("function")), - value: None, - full_name: None, - members: None, - cairo_type: None, - }, - ); - - identifiers.insert( - String::from("__main__.main.SIZEOF_LOCALS"), - Identifier { - pc: None, - type_: Some(String::from("const")), - value: Some(Felt252::zero()), - full_name: None, - members: None, - cairo_type: None, - }, - ); - - let program = Program::new( - builtins, - data, - None, - HashMap::new(), - reference_manager, - identifiers.clone(), - Vec::new(), - None, - ) - .unwrap(); - - assert_eq!( - program.get_identifier("__main__.main"), - identifiers.get("__main__.main"), - ); - assert_eq!( - program.get_identifier("__main__.main.SIZEOF_LOCALS"), - identifiers.get("__main__.main.SIZEOF_LOCALS"), - ); - assert_eq!( - program.get_identifier("missing"), - identifiers.get("missing"), - ); - } +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn new_program_with_hints() { +// let reference_manager = ReferenceManager { +// references: Vec::new(), +// }; + +// let builtins: Vec = Vec::new(); +// let data: Vec = vec![ +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(1000), +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(2000), +// mayberelocatable!(5201798304953696256), +// mayberelocatable!(2345108766317314046), +// ]; + +// let str_to_hint_param = |s: &str| HintParams { +// code: s.to_string(), +// accessible_scopes: vec![], +// flow_tracking_data: FlowTrackingData { +// ap_tracking: ApTracking { +// group: 0, +// offset: 0, +// }, +// reference_ids: HashMap::new(), +// }, +// }; + +// let hints = HashMap::from([ +// (5, vec![str_to_hint_param("c"), str_to_hint_param("d")]), +// (1, vec![str_to_hint_param("a")]), +// (4, vec![str_to_hint_param("b")]), +// ]); + +// let program = Program::new( +// builtins.clone(), +// data.clone(), +// None, +// hints.clone(), +// reference_manager, +// HashMap::new(), +// Vec::new(), +// None, +// ) +// .unwrap(); + +// assert_eq!(program.builtins, builtins); +// assert_eq!(program.shared_program_data.data, data); +// assert_eq!(program.shared_program_data.main, None); +// assert_eq!(program.shared_program_data.identifiers, HashMap::new()); + +// let program_hints: HashMap<_, _> = program +// .shared_program_data +// .hints_collection +// .hints_ranges +// .iter() +// .enumerate() +// .filter_map(|(pc, r)| r.map(|(s, l)| (pc, (s, s + l.get())))) +// .map(|(pc, (s, e))| { +// ( +// pc, +// program.shared_program_data.hints_collection.hints[s..e].to_vec(), +// ) +// }) +// .collect(); +// assert_eq!(program_hints, hints); +// } - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn iter_identifiers() { - let reference_manager = ReferenceManager { - references: Vec::new(), - }; +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn new_program_with_identifiers() { +// let reference_manager = ReferenceManager { +// references: Vec::new(), +// }; + +// let builtins: Vec = Vec::new(); + +// let data: Vec = vec![ +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(1000), +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(2000), +// mayberelocatable!(5201798304953696256), +// mayberelocatable!(2345108766317314046), +// ]; + +// let mut identifiers: HashMap = HashMap::new(); + +// identifiers.insert( +// String::from("__main__.main"), +// Identifier { +// pc: Some(0), +// type_: Some(String::from("function")), +// value: None, +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); + +// identifiers.insert( +// String::from("__main__.main.SIZEOF_LOCALS"), +// Identifier { +// pc: None, +// type_: Some(String::from("const")), +// value: Some(Felt252::zero()), +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); + +// let program = Program::new( +// builtins.clone(), +// data.clone(), +// None, +// HashMap::new(), +// reference_manager, +// identifiers.clone(), +// Vec::new(), +// None, +// ) +// .unwrap(); + +// assert_eq!(program.builtins, builtins); +// assert_eq!(program.shared_program_data.data, data); +// assert_eq!(program.shared_program_data.main, None); +// assert_eq!(program.shared_program_data.identifiers, identifiers); +// assert_eq!( +// program.constants, +// [("__main__.main.SIZEOF_LOCALS", Felt252::zero())] +// .into_iter() +// .map(|(key, value)| (key.to_string(), value)) +// .collect::>(), +// ); +// } - let builtins: Vec = Vec::new(); - - let data: Vec = vec![ - mayberelocatable!(5189976364521848832), - mayberelocatable!(1000), - mayberelocatable!(5189976364521848832), - mayberelocatable!(2000), - mayberelocatable!(5201798304953696256), - mayberelocatable!(2345108766317314046), - ]; - - let mut identifiers: HashMap = HashMap::new(); - - identifiers.insert( - String::from("__main__.main"), - Identifier { - pc: Some(0), - type_: Some(String::from("function")), - value: None, - full_name: None, - members: None, - cairo_type: None, - }, - ); - - identifiers.insert( - String::from("__main__.main.SIZEOF_LOCALS"), - Identifier { - pc: None, - type_: Some(String::from("const")), - value: Some(Felt252::zero()), - full_name: None, - members: None, - cairo_type: None, - }, - ); - - let program = Program::new( - builtins, - data, - None, - HashMap::new(), - reference_manager, - identifiers.clone(), - Vec::new(), - None, - ) - .unwrap(); +// #[test] +// fn extract_constants() { +// let mut identifiers: HashMap = HashMap::new(); + +// identifiers.insert( +// String::from("__main__.main"), +// Identifier { +// pc: Some(0), +// type_: Some(String::from("function")), +// value: None, +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); + +// identifiers.insert( +// String::from("__main__.main.SIZEOF_LOCALS"), +// Identifier { +// pc: None, +// type_: Some(String::from("const")), +// value: Some(Felt252::zero()), +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); + +// assert_eq!( +// Program::extract_constants(&identifiers).unwrap(), +// [("__main__.main.SIZEOF_LOCALS", Felt252::zero())] +// .into_iter() +// .map(|(key, value)| (key.to_string(), value)) +// .collect::>(), +// ); +// } - let collected_identifiers: HashMap<_, _> = program - .iter_identifiers() - .map(|(cairo_type, identifier)| (cairo_type.to_string(), identifier.clone())) - .collect(); +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn get_prime() { +// let program = Program::default(); +// assert_eq!(PRIME_STR, program.prime()); +// } - assert_eq!(collected_identifiers, identifiers); - } +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn iter_builtins() { +// let reference_manager = ReferenceManager { +// references: Vec::new(), +// }; + +// let builtins: Vec<_> = vec![BuiltinName::range_check, BuiltinName::bitwise]; +// let data: Vec<_> = vec![ +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(1000), +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(2000), +// mayberelocatable!(5201798304953696256), +// mayberelocatable!(2345108766317314046), +// ]; + +// let program = Program::new( +// builtins.clone(), +// data, +// None, +// HashMap::new(), +// reference_manager, +// HashMap::new(), +// Vec::new(), +// None, +// ) +// .unwrap(); + +// assert_eq!( +// program.iter_builtins().cloned().collect::>(), +// builtins +// ); + +// assert_eq!(program.builtins_len(), 2); +// } - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn new_program_with_invalid_identifiers() { - let reference_manager = ReferenceManager { - references: Vec::new(), - }; +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn iter_data() { +// let reference_manager = ReferenceManager { +// references: Vec::new(), +// }; + +// let builtins: Vec = Vec::new(); +// let data: Vec = vec![ +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(1000), +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(2000), +// mayberelocatable!(5201798304953696256), +// mayberelocatable!(2345108766317314046), +// ]; + +// let program = Program::new( +// builtins, +// data.clone(), +// None, +// HashMap::new(), +// reference_manager, +// HashMap::new(), +// Vec::new(), +// None, +// ) +// .unwrap(); + +// assert_eq!(program.iter_data().cloned().collect::>(), data); +// } - let builtins: Vec = Vec::new(); - - let data: Vec = vec![ - mayberelocatable!(5189976364521848832), - mayberelocatable!(1000), - mayberelocatable!(5189976364521848832), - mayberelocatable!(2000), - mayberelocatable!(5201798304953696256), - mayberelocatable!(2345108766317314046), - ]; - - let mut identifiers: HashMap = HashMap::new(); - - identifiers.insert( - String::from("__main__.main"), - Identifier { - pc: Some(0), - type_: Some(String::from("function")), - value: None, - full_name: None, - members: None, - cairo_type: None, - }, - ); - - identifiers.insert( - String::from("__main__.main.SIZEOF_LOCALS"), - Identifier { - pc: None, - type_: Some(String::from("const")), - value: None, - full_name: None, - members: None, - cairo_type: None, - }, - ); - - let program = Program::new( - builtins, - data, - None, - HashMap::new(), - reference_manager, - identifiers.clone(), - Vec::new(), - None, - ); +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn data_len() { +// let reference_manager = ReferenceManager { +// references: Vec::new(), +// }; + +// let builtins: Vec = Vec::new(); +// let data: Vec = vec![ +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(1000), +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(2000), +// mayberelocatable!(5201798304953696256), +// mayberelocatable!(2345108766317314046), +// ]; + +// let program = Program::new( +// builtins, +// data.clone(), +// None, +// HashMap::new(), +// reference_manager, +// HashMap::new(), +// Vec::new(), +// None, +// ) +// .unwrap(); + +// assert_eq!(program.data_len(), data.len()); +// } - assert!(program.is_err()); - } +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn get_identifier() { +// let reference_manager = ReferenceManager { +// references: Vec::new(), +// }; + +// let builtins: Vec = Vec::new(); + +// let data: Vec = vec![ +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(1000), +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(2000), +// mayberelocatable!(5201798304953696256), +// mayberelocatable!(2345108766317314046), +// ]; + +// let mut identifiers: HashMap = HashMap::new(); + +// identifiers.insert( +// String::from("__main__.main"), +// Identifier { +// pc: Some(0), +// type_: Some(String::from("function")), +// value: None, +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); + +// identifiers.insert( +// String::from("__main__.main.SIZEOF_LOCALS"), +// Identifier { +// pc: None, +// type_: Some(String::from("const")), +// value: Some(Felt252::zero()), +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); + +// let program = Program::new( +// builtins, +// data, +// None, +// HashMap::new(), +// reference_manager, +// identifiers.clone(), +// Vec::new(), +// None, +// ) +// .unwrap(); + +// assert_eq!( +// program.get_identifier("__main__.main"), +// identifiers.get("__main__.main"), +// ); +// assert_eq!( +// program.get_identifier("__main__.main.SIZEOF_LOCALS"), +// identifiers.get("__main__.main.SIZEOF_LOCALS"), +// ); +// assert_eq!( +// program.get_identifier("missing"), +// identifiers.get("missing"), +// ); +// } - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn deserialize_program_test() { - let program = Program::from_bytes( - include_bytes!("../../../cairo_programs/manually_compiled/valid_program_a.json"), - Some("main"), - ) - .unwrap(); - - let builtins: Vec = Vec::new(); - let data: Vec = vec![ - mayberelocatable!(5189976364521848832), - mayberelocatable!(1000), - mayberelocatable!(5189976364521848832), - mayberelocatable!(2000), - mayberelocatable!(5201798304953696256), - mayberelocatable!(2345108766317314046), - ]; - - let mut identifiers: HashMap = HashMap::new(); - - identifiers.insert( - String::from("__main__.main"), - Identifier { - pc: Some(0), - type_: Some(String::from("function")), - value: None, - full_name: None, - members: None, - cairo_type: None, - }, - ); - identifiers.insert( - String::from("__main__.main.Args"), - Identifier { - pc: None, - type_: Some(String::from("struct")), - value: None, - full_name: Some("__main__.main.Args".to_string()), - members: Some(HashMap::new()), - cairo_type: None, - }, - ); - identifiers.insert( - String::from("__main__.main.ImplicitArgs"), - Identifier { - pc: None, - type_: Some(String::from("struct")), - value: None, - full_name: Some("__main__.main.ImplicitArgs".to_string()), - members: Some(HashMap::new()), - cairo_type: None, - }, - ); - identifiers.insert( - String::from("__main__.main.Return"), - Identifier { - pc: None, - type_: Some(String::from("struct")), - value: None, - full_name: Some("__main__.main.Return".to_string()), - members: Some(HashMap::new()), - cairo_type: None, - }, - ); - identifiers.insert( - String::from("__main__.main.SIZEOF_LOCALS"), - Identifier { - pc: None, - type_: Some(String::from("const")), - value: Some(Felt252::zero()), - full_name: None, - members: None, - cairo_type: None, - }, - ); - - assert_eq!(program.builtins, builtins); - assert_eq!(program.shared_program_data.data, data); - assert_eq!(program.shared_program_data.main, Some(0)); - assert_eq!(program.shared_program_data.identifiers, identifiers); - } +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn iter_identifiers() { +// let reference_manager = ReferenceManager { +// references: Vec::new(), +// }; + +// let builtins: Vec = Vec::new(); + +// let data: Vec = vec![ +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(1000), +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(2000), +// mayberelocatable!(5201798304953696256), +// mayberelocatable!(2345108766317314046), +// ]; + +// let mut identifiers: HashMap = HashMap::new(); + +// identifiers.insert( +// String::from("__main__.main"), +// Identifier { +// pc: Some(0), +// type_: Some(String::from("function")), +// value: None, +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); + +// identifiers.insert( +// String::from("__main__.main.SIZEOF_LOCALS"), +// Identifier { +// pc: None, +// type_: Some(String::from("const")), +// value: Some(Felt252::zero()), +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); + +// let program = Program::new( +// builtins, +// data, +// None, +// HashMap::new(), +// reference_manager, +// identifiers.clone(), +// Vec::new(), +// None, +// ) +// .unwrap(); + +// let collected_identifiers: HashMap<_, _> = program +// .iter_identifiers() +// .map(|(cairo_type, identifier)| (cairo_type.to_string(), identifier.clone())) +// .collect(); + +// assert_eq!(collected_identifiers, identifiers); +// } - /// Deserialize a program without an entrypoint. - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn deserialize_program_without_entrypoint_test() { - let program = Program::from_bytes( - include_bytes!("../../../cairo_programs/manually_compiled/valid_program_a.json"), - None, - ) - .unwrap(); - - let builtins: Vec = Vec::new(); - - let error_message_attributes: Vec = vec![Attribute { - name: String::from("error_message"), - start_pc: 379, - end_pc: 381, - value: String::from("SafeUint256: addition overflow"), - flow_tracking_data: Some(FlowTrackingData { - ap_tracking: ApTracking { - group: 14, - offset: 35, - }, - reference_ids: HashMap::new(), - }), - }]; - - let data: Vec = vec![ - mayberelocatable!(5189976364521848832), - mayberelocatable!(1000), - mayberelocatable!(5189976364521848832), - mayberelocatable!(2000), - mayberelocatable!(5201798304953696256), - mayberelocatable!(2345108766317314046), - ]; - - let mut identifiers: HashMap = HashMap::new(); - - identifiers.insert( - String::from("__main__.main"), - Identifier { - pc: Some(0), - type_: Some(String::from("function")), - value: None, - full_name: None, - members: None, - cairo_type: None, - }, - ); - identifiers.insert( - String::from("__main__.main.Args"), - Identifier { - pc: None, - type_: Some(String::from("struct")), - value: None, - full_name: Some("__main__.main.Args".to_string()), - members: Some(HashMap::new()), - cairo_type: None, - }, - ); - identifiers.insert( - String::from("__main__.main.ImplicitArgs"), - Identifier { - pc: None, - type_: Some(String::from("struct")), - value: None, - full_name: Some("__main__.main.ImplicitArgs".to_string()), - members: Some(HashMap::new()), - cairo_type: None, - }, - ); - identifiers.insert( - String::from("__main__.main.Return"), - Identifier { - pc: None, - type_: Some(String::from("struct")), - value: None, - full_name: Some("__main__.main.Return".to_string()), - members: Some(HashMap::new()), - cairo_type: None, - }, - ); - identifiers.insert( - String::from("__main__.main.SIZEOF_LOCALS"), - Identifier { - pc: None, - type_: Some(String::from("const")), - value: Some(Felt252::zero()), - full_name: None, - members: None, - cairo_type: None, - }, - ); - - assert_eq!(program.builtins, builtins); - assert_eq!(program.shared_program_data.data, data); - assert_eq!(program.shared_program_data.main, None); - assert_eq!(program.shared_program_data.identifiers, identifiers); - assert_eq!( - program.shared_program_data.error_message_attributes, - error_message_attributes - ) - } +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn new_program_with_invalid_identifiers() { +// let reference_manager = ReferenceManager { +// references: Vec::new(), +// }; + +// let builtins: Vec = Vec::new(); + +// let data: Vec = vec![ +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(1000), +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(2000), +// mayberelocatable!(5201798304953696256), +// mayberelocatable!(2345108766317314046), +// ]; + +// let mut identifiers: HashMap = HashMap::new(); + +// identifiers.insert( +// String::from("__main__.main"), +// Identifier { +// pc: Some(0), +// type_: Some(String::from("function")), +// value: None, +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); + +// identifiers.insert( +// String::from("__main__.main.SIZEOF_LOCALS"), +// Identifier { +// pc: None, +// type_: Some(String::from("const")), +// value: None, +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); + +// let program = Program::new( +// builtins, +// data, +// None, +// HashMap::new(), +// reference_manager, +// identifiers.clone(), +// Vec::new(), +// None, +// ); + +// assert!(program.is_err()); +// } - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn deserialize_program_constants_test() { - let program = Program::from_bytes( - include_bytes!( - "../../../cairo_programs/manually_compiled/deserialize_constant_test.json" - ), - Some("main"), - ) - .unwrap(); - - let constants = [ - ("__main__.compare_abs_arrays.SIZEOF_LOCALS", Felt252::zero()), - ( - "starkware.cairo.common.cairo_keccak.packed_keccak.ALL_ONES", - felt_str!( - "3618502788666131106986593281521497120414687020801267626233049500247285301247" - ), - ), - ( - "starkware.cairo.common.cairo_keccak.packed_keccak.BLOCK_SIZE", - Felt252::new(3), - ), - ( - "starkware.cairo.common.alloc.alloc.SIZEOF_LOCALS", - felt_str!( - "-3618502788666131213697322783095070105623107215331596699973092056135872020481" - ), - ), - ( - "starkware.cairo.common.uint256.SHIFT", - felt_str!("340282366920938463463374607431768211456"), - ), - ] - .into_iter() - .map(|(key, value)| (key.to_string(), value)) - .collect::>(); - - assert_eq!(program.constants, constants); - } +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn deserialize_program_test() { +// let program = Program::from_bytes( +// include_bytes!("../../../cairo_programs/manually_compiled/valid_program_a.json"), +// Some("main"), +// ) +// .unwrap(); + +// let builtins: Vec = Vec::new(); +// let data: Vec = vec![ +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(1000), +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(2000), +// mayberelocatable!(5201798304953696256), +// mayberelocatable!(2345108766317314046), +// ]; + +// let mut identifiers: HashMap = HashMap::new(); + +// identifiers.insert( +// String::from("__main__.main"), +// Identifier { +// pc: Some(0), +// type_: Some(String::from("function")), +// value: None, +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); +// identifiers.insert( +// String::from("__main__.main.Args"), +// Identifier { +// pc: None, +// type_: Some(String::from("struct")), +// value: None, +// full_name: Some("__main__.main.Args".to_string()), +// members: Some(HashMap::new()), +// cairo_type: None, +// }, +// ); +// identifiers.insert( +// String::from("__main__.main.ImplicitArgs"), +// Identifier { +// pc: None, +// type_: Some(String::from("struct")), +// value: None, +// full_name: Some("__main__.main.ImplicitArgs".to_string()), +// members: Some(HashMap::new()), +// cairo_type: None, +// }, +// ); +// identifiers.insert( +// String::from("__main__.main.Return"), +// Identifier { +// pc: None, +// type_: Some(String::from("struct")), +// value: None, +// full_name: Some("__main__.main.Return".to_string()), +// members: Some(HashMap::new()), +// cairo_type: None, +// }, +// ); +// identifiers.insert( +// String::from("__main__.main.SIZEOF_LOCALS"), +// Identifier { +// pc: None, +// type_: Some(String::from("const")), +// value: Some(Felt252::zero()), +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); + +// assert_eq!(program.builtins, builtins); +// assert_eq!(program.shared_program_data.data, data); +// assert_eq!(program.shared_program_data.main, Some(0)); +// assert_eq!(program.shared_program_data.identifiers, identifiers); +// } - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn default_program() { - let hints_collection = HintsCollection { - hints: Vec::new(), - hints_ranges: HashMap::new(), - }; +// /// Deserialize a program without an entrypoint. +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn deserialize_program_without_entrypoint_test() { +// let program = Program::from_bytes( +// include_bytes!("../../../cairo_programs/manually_compiled/valid_program_a.json"), +// None, +// ) +// .unwrap(); + +// let builtins: Vec = Vec::new(); + +// let error_message_attributes: Vec = vec![Attribute { +// name: String::from("error_message"), +// start_pc: 379, +// end_pc: 381, +// value: String::from("SafeUint256: addition overflow"), +// flow_tracking_data: Some(FlowTrackingData { +// ap_tracking: ApTracking { +// group: 14, +// offset: 35, +// }, +// reference_ids: HashMap::new(), +// }), +// }]; + +// let data: Vec = vec![ +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(1000), +// mayberelocatable!(5189976364521848832), +// mayberelocatable!(2000), +// mayberelocatable!(5201798304953696256), +// mayberelocatable!(2345108766317314046), +// ]; + +// let mut identifiers: HashMap = HashMap::new(); + +// identifiers.insert( +// String::from("__main__.main"), +// Identifier { +// pc: Some(0), +// type_: Some(String::from("function")), +// value: None, +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); +// identifiers.insert( +// String::from("__main__.main.Args"), +// Identifier { +// pc: None, +// type_: Some(String::from("struct")), +// value: None, +// full_name: Some("__main__.main.Args".to_string()), +// members: Some(HashMap::new()), +// cairo_type: None, +// }, +// ); +// identifiers.insert( +// String::from("__main__.main.ImplicitArgs"), +// Identifier { +// pc: None, +// type_: Some(String::from("struct")), +// value: None, +// full_name: Some("__main__.main.ImplicitArgs".to_string()), +// members: Some(HashMap::new()), +// cairo_type: None, +// }, +// ); +// identifiers.insert( +// String::from("__main__.main.Return"), +// Identifier { +// pc: None, +// type_: Some(String::from("struct")), +// value: None, +// full_name: Some("__main__.main.Return".to_string()), +// members: Some(HashMap::new()), +// cairo_type: None, +// }, +// ); +// identifiers.insert( +// String::from("__main__.main.SIZEOF_LOCALS"), +// Identifier { +// pc: None, +// type_: Some(String::from("const")), +// value: Some(Felt252::zero()), +// full_name: None, +// members: None, +// cairo_type: None, +// }, +// ); + +// assert_eq!(program.builtins, builtins); +// assert_eq!(program.shared_program_data.data, data); +// assert_eq!(program.shared_program_data.main, None); +// assert_eq!(program.shared_program_data.identifiers, identifiers); +// assert_eq!( +// program.shared_program_data.error_message_attributes, +// error_message_attributes +// ) +// } - let shared_program_data = SharedProgramData { - data: Vec::new(), - hints_collection, - main: None, - start: None, - end: None, - error_message_attributes: Vec::new(), - instruction_locations: None, - identifiers: HashMap::new(), - reference_manager: Program::get_reference_list(&ReferenceManager { - references: Vec::new(), - }), - }; - let program = Program { - shared_program_data: Arc::new(shared_program_data), - constants: HashMap::new(), - builtins: Vec::new(), - }; +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn deserialize_program_constants_test() { +// let program = Program::from_bytes( +// include_bytes!( +// "../../../cairo_programs/manually_compiled/deserialize_constant_test.json" +// ), +// Some("main"), +// ) +// .unwrap(); + +// let constants = [ +// ("__main__.compare_abs_arrays.SIZEOF_LOCALS", Felt252::zero()), +// ( +// "starkware.cairo.common.cairo_keccak.packed_keccak.ALL_ONES", +// felt_str!( +// "3618502788666131106986593281521497120414687020801267626233049500247285301247" +// ), +// ), +// ( +// "starkware.cairo.common.cairo_keccak.packed_keccak.BLOCK_SIZE", +// Felt252::new(3), +// ), +// ( +// "starkware.cairo.common.alloc.alloc.SIZEOF_LOCALS", +// felt_str!( +// "-3618502788666131213697322783095070105623107215331596699973092056135872020481" +// ), +// ), +// ( +// "starkware.cairo.common.uint256.SHIFT", +// felt_str!("340282366920938463463374607431768211456"), +// ), +// ] +// .into_iter() +// .map(|(key, value)| (key.to_string(), value)) +// .collect::>(); + +// assert_eq!(program.constants, constants); +// } - assert_eq!(program, Program::default()); - } +// #[test] +// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +// fn default_program() { +// let hints_collection = HintsCollection { +// hints: Vec::new(), +// hints_ranges: HashMap::new(), +// }; + +// let shared_program_data = SharedProgramData { +// data: Vec::new(), +// hints_collection, +// main: None, +// start: None, +// end: None, +// error_message_attributes: Vec::new(), +// instruction_locations: None, +// identifiers: HashMap::new(), +// reference_manager: Program::get_reference_list(&ReferenceManager { +// references: Vec::new(), +// }), +// }; +// let program = Program { +// shared_program_data: Arc::new(shared_program_data), +// constants: HashMap::new(), +// builtins: Vec::new(), +// }; + +// assert_eq!(program, Program::default()); +// } - #[test] - fn get_stripped_program() { - let program_content = include_bytes!("../../../cairo_programs/pedersen_test.json"); - let program = Program::from_bytes(program_content, Some("main")).unwrap(); - let stripped_program = program.get_stripped_program().unwrap(); - assert_eq!(stripped_program.builtins, program.builtins); - assert_eq!(stripped_program.data, program.shared_program_data.data); - assert_eq!( - stripped_program.main, - program.shared_program_data.main.unwrap() - ); - } +// #[test] +// fn get_stripped_program() { +// let program_content = include_bytes!("../../../cairo_programs/pedersen_test.json"); +// let program = Program::from_bytes(program_content, Some("main")).unwrap(); +// let stripped_program = program.get_stripped_program().unwrap(); +// assert_eq!(stripped_program.builtins, program.builtins); +// assert_eq!(stripped_program.data, program.shared_program_data.data); +// assert_eq!( +// stripped_program.main, +// program.shared_program_data.main.unwrap() +// ); +// } - #[test] - fn get_stripped_no_main() { - let program_content = - include_bytes!("../../../cairo_programs/proof_programs/fibonacci.json"); - let program = Program::from_bytes(program_content, None).unwrap(); - assert_matches!( - program.get_stripped_program(), - Err(ProgramError::StrippedProgramNoMain) - ); - } -} +// #[test] +// fn get_stripped_no_main() { +// let program_content = +// include_bytes!("../../../cairo_programs/proof_programs/fibonacci.json"); +// let program = Program::from_bytes(program_content, None).unwrap(); +// assert_matches!( +// program.get_stripped_program(), +// Err(ProgramError::StrippedProgramNoMain) +// ); +// } +// } diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index deadb0c852..1e2e64e963 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -548,21 +548,21 @@ impl CairoRunner { hint_processor: &mut dyn HintProcessor, ) -> Result<(), VirtualMachineError> { let references = &self.program.shared_program_data.reference_manager; - let hint_data = self.get_hint_data(references, hint_processor)?; + let mut hint_data = self.get_hint_data(references, hint_processor)?; + let mut hint_ranges = self + .program + .shared_program_data + .hints_collection + .hints_ranges + .clone(); #[cfg(feature = "hooks")] vm.execute_before_first_step(self)?; while vm.run_context.pc != address && !hint_processor.consumed() { - let hint_data = &self - .program - .shared_program_data - .hints_collection - .get_hint_range_for_pc(vm.run_context.pc) - .and_then(|(start, length)| hint_data.get(start..start + length.get())) - .unwrap_or(&[]); vm.step( hint_processor, &mut self.exec_scopes, - hint_data, + &mut hint_data, + &mut hint_ranges, &self.program.constants, )?; hint_processor.consume_step(); @@ -583,24 +583,24 @@ impl CairoRunner { hint_processor: &mut dyn HintProcessor, ) -> Result<(), VirtualMachineError> { let references = &self.program.shared_program_data.reference_manager; - let hint_data = self.get_hint_data(references, hint_processor)?; + let mut hint_data = self.get_hint_data(references, hint_processor)?; + let mut hint_ranges = self + .program + .shared_program_data + .hints_collection + .hints_ranges + .clone(); for remaining_steps in (1..=steps).rev() { if self.final_pc.as_ref() == Some(&vm.run_context.pc) { return Err(VirtualMachineError::EndOfProgram(remaining_steps)); } - let hint_data = &self - .program - .shared_program_data - .hints_collection - .get_hint_range_for_pc(vm.run_context.pc) - .and_then(|(start, length)| hint_data.get(start..start + length.get())) - .unwrap_or(&[]); vm.step( hint_processor, &mut self.exec_scopes, - hint_data, + &mut hint_data, + &mut hint_ranges, &self.program.constants, )?; } diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 6dcbd3dae9..2df32959a4 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -1,5 +1,6 @@ use crate::stdlib::{any::Any, borrow::Cow, collections::HashMap, prelude::*}; +use crate::types::program::HintRange; use crate::{ hint_processor::hint_processor_definition::HintProcessor, types::{ @@ -445,15 +446,17 @@ impl VirtualMachine { &mut self, hint_executor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, - hint_data: &[Box], + hint_datas: &mut Vec>, + hint_ranges: &mut HashMap, constants: &HashMap, ) -> Result<(), VirtualMachineError> { - for (hint_index, hint_data) in hint_data.iter().enumerate() { - hint_executor - .execute_hint(self, exec_scopes, hint_data, constants) - .map_err(|err| VirtualMachineError::Hint(Box::new((hint_index, err))))? - } - Ok(()) + hint_executor.execute_and_mutate_hints( + self, + exec_scopes, + constants, + hint_datas, + hint_ranges, + ) } pub fn step_instruction(&mut self) -> Result<(), VirtualMachineError> { @@ -485,10 +488,17 @@ impl VirtualMachine { &mut self, hint_executor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, - hint_data: &[Box], + hint_datas: &mut Vec>, + hint_ranges: &mut HashMap, constants: &HashMap, ) -> Result<(), VirtualMachineError> { - self.step_hint(hint_executor, exec_scopes, hint_data, constants)?; + self.step_hint( + hint_executor, + exec_scopes, + hint_datas, + hint_ranges, + constants, + )?; #[cfg(feature = "hooks")] self.execute_pre_step_instruction(hint_executor, exec_scopes, hint_data, constants)?; From 64a570c9ee9ee3072adb807aa94516592ca8ce23 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 10:19:15 -0300 Subject: [PATCH 03/23] comments --- vm/src/hint_processor/hint_processor_definition.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vm/src/hint_processor/hint_processor_definition.rs b/vm/src/hint_processor/hint_processor_definition.rs index ca62bc3db8..daeffb2e51 100644 --- a/vm/src/hint_processor/hint_processor_definition.rs +++ b/vm/src/hint_processor/hint_processor_definition.rs @@ -66,8 +66,9 @@ pub trait HintProcessorLogic { exec_scopes: &mut ExecutionScopes, //Constant values extracted from the program specification. constants: &HashMap, - // hint muatbles + // Mutable hints mutable_hints: &mut [Box], + // Mutable hint ranges mutable_ranges: &mut HashMap, ) -> Result<(), VirtualMachineError> { let hint_range = &mutable_ranges From f259ad1fa00745c17343e18c4461678e884a4a67 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 11:11:11 -0300 Subject: [PATCH 04/23] Fix hashmap ranges-related stuff --- vm/src/types/program.rs | 1766 +++++++++++++++++++-------------------- 1 file changed, 880 insertions(+), 886 deletions(-) diff --git a/vm/src/types/program.rs b/vm/src/types/program.rs index 6a0138cfee..3e321d6890 100644 --- a/vm/src/types/program.rs +++ b/vm/src/types/program.rs @@ -155,15 +155,15 @@ impl HintsCollection { } } -// impl From<&HintsCollection> for BTreeMap> { -// fn from(hc: &HintsCollection) -> Self { -// let mut hint_map = BTreeMap::new(); -// for (pc, r) in hc.hints_ranges.iter() { -// hint_map.insert(i, hc.hints[r.0..r.0 + r.1.get()].to_owned()); -// } -// hint_map -// } -// } +impl From<&HintsCollection> for BTreeMap> { + fn from(hc: &HintsCollection) -> Self { + let mut hint_map = BTreeMap::new(); + for (pc, r) in hc.hints_ranges.iter() { + hint_map.insert(pc.offset, hc.hints[r.0..r.0 + r.1.get()].to_owned()); + } + hint_map + } +} /// Represents a range of hints corresponding to a PC as a tuple `(start, length)`. pub type HintRange = (usize, NonZeroUsize); @@ -415,880 +415,874 @@ impl TryFrom for Program { } } -// #[cfg(test)] -// impl HintsCollection { -// pub fn iter(&self) -> impl Iterator { -// self.hints_ranges -// .iter() -// .enumerate() -// .filter_map(|(pc, range)| { -// range.and_then(|(start, len)| { -// let end = start + len.get(); -// if end <= self.hints.len() { -// Some((pc, &self.hints[start..end])) -// } else { -// None -// } -// }) -// }) -// } -// } - -// #[cfg(test)] -// mod tests { -// use super::*; -// use crate::serde::deserialize_program::{ApTracking, FlowTrackingData}; -// use crate::utils::test_utils::*; -// use felt::felt_str; -// use num_traits::Zero; - -// use assert_matches::assert_matches; - -// #[cfg(target_arch = "wasm32")] -// use wasm_bindgen_test::*; - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn new() { -// let reference_manager = ReferenceManager { -// references: Vec::new(), -// }; - -// let builtins: Vec = Vec::new(); -// let data: Vec = vec![ -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(1000), -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(2000), -// mayberelocatable!(5201798304953696256), -// mayberelocatable!(2345108766317314046), -// ]; - -// let program = Program::new( -// builtins.clone(), -// data.clone(), -// None, -// HashMap::new(), -// reference_manager, -// HashMap::new(), -// Vec::new(), -// None, -// ) -// .unwrap(); - -// assert_eq!(program.builtins, builtins); -// assert_eq!(program.shared_program_data.data, data); -// assert_eq!(program.shared_program_data.main, None); -// assert_eq!(program.shared_program_data.identifiers, HashMap::new()); -// assert_eq!( -// program.shared_program_data.hints_collection.hints, -// Vec::new() -// ); -// assert_eq!( -// program.shared_program_data.hints_collection.hints_ranges, -// HashMap::new() -// ); -// } - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn new_for_proof() { -// let reference_manager = ReferenceManager { -// references: Vec::new(), -// }; - -// let builtins: Vec = Vec::new(); -// let data: Vec = vec![ -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(1000), -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(2000), -// mayberelocatable!(5201798304953696256), -// mayberelocatable!(2345108766317314046), -// ]; - -// let program = Program::new_for_proof( -// builtins.clone(), -// data.clone(), -// 0, -// 1, -// HashMap::new(), -// reference_manager, -// HashMap::new(), -// Vec::new(), -// None, -// ) -// .unwrap(); - -// assert_eq!(program.builtins, builtins); -// assert_eq!(program.shared_program_data.data, data); -// assert_eq!(program.shared_program_data.main, None); -// assert_eq!(program.shared_program_data.start, Some(0)); -// assert_eq!(program.shared_program_data.end, Some(1)); -// assert_eq!(program.shared_program_data.identifiers, HashMap::new()); -// assert_eq!( -// program.shared_program_data.hints_collection.hints, -// Vec::new() -// ); -// assert_eq!( -// program.shared_program_data.hints_collection.hints_ranges, -// Vec::new() -// ); -// } - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn new_program_with_hints() { -// let reference_manager = ReferenceManager { -// references: Vec::new(), -// }; - -// let builtins: Vec = Vec::new(); -// let data: Vec = vec![ -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(1000), -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(2000), -// mayberelocatable!(5201798304953696256), -// mayberelocatable!(2345108766317314046), -// ]; - -// let str_to_hint_param = |s: &str| HintParams { -// code: s.to_string(), -// accessible_scopes: vec![], -// flow_tracking_data: FlowTrackingData { -// ap_tracking: ApTracking { -// group: 0, -// offset: 0, -// }, -// reference_ids: HashMap::new(), -// }, -// }; - -// let hints = HashMap::from([ -// (5, vec![str_to_hint_param("c"), str_to_hint_param("d")]), -// (1, vec![str_to_hint_param("a")]), -// (4, vec![str_to_hint_param("b")]), -// ]); - -// let program = Program::new( -// builtins.clone(), -// data.clone(), -// None, -// hints.clone(), -// reference_manager, -// HashMap::new(), -// Vec::new(), -// None, -// ) -// .unwrap(); - -// assert_eq!(program.builtins, builtins); -// assert_eq!(program.shared_program_data.data, data); -// assert_eq!(program.shared_program_data.main, None); -// assert_eq!(program.shared_program_data.identifiers, HashMap::new()); - -// let program_hints: HashMap<_, _> = program -// .shared_program_data -// .hints_collection -// .hints_ranges -// .iter() -// .enumerate() -// .filter_map(|(pc, r)| r.map(|(s, l)| (pc, (s, s + l.get())))) -// .map(|(pc, (s, e))| { -// ( -// pc, -// program.shared_program_data.hints_collection.hints[s..e].to_vec(), -// ) -// }) -// .collect(); -// assert_eq!(program_hints, hints); -// } - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn new_program_with_identifiers() { -// let reference_manager = ReferenceManager { -// references: Vec::new(), -// }; - -// let builtins: Vec = Vec::new(); - -// let data: Vec = vec![ -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(1000), -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(2000), -// mayberelocatable!(5201798304953696256), -// mayberelocatable!(2345108766317314046), -// ]; - -// let mut identifiers: HashMap = HashMap::new(); - -// identifiers.insert( -// String::from("__main__.main"), -// Identifier { -// pc: Some(0), -// type_: Some(String::from("function")), -// value: None, -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); - -// identifiers.insert( -// String::from("__main__.main.SIZEOF_LOCALS"), -// Identifier { -// pc: None, -// type_: Some(String::from("const")), -// value: Some(Felt252::zero()), -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); - -// let program = Program::new( -// builtins.clone(), -// data.clone(), -// None, -// HashMap::new(), -// reference_manager, -// identifiers.clone(), -// Vec::new(), -// None, -// ) -// .unwrap(); - -// assert_eq!(program.builtins, builtins); -// assert_eq!(program.shared_program_data.data, data); -// assert_eq!(program.shared_program_data.main, None); -// assert_eq!(program.shared_program_data.identifiers, identifiers); -// assert_eq!( -// program.constants, -// [("__main__.main.SIZEOF_LOCALS", Felt252::zero())] -// .into_iter() -// .map(|(key, value)| (key.to_string(), value)) -// .collect::>(), -// ); -// } - -// #[test] -// fn extract_constants() { -// let mut identifiers: HashMap = HashMap::new(); - -// identifiers.insert( -// String::from("__main__.main"), -// Identifier { -// pc: Some(0), -// type_: Some(String::from("function")), -// value: None, -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); - -// identifiers.insert( -// String::from("__main__.main.SIZEOF_LOCALS"), -// Identifier { -// pc: None, -// type_: Some(String::from("const")), -// value: Some(Felt252::zero()), -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); - -// assert_eq!( -// Program::extract_constants(&identifiers).unwrap(), -// [("__main__.main.SIZEOF_LOCALS", Felt252::zero())] -// .into_iter() -// .map(|(key, value)| (key.to_string(), value)) -// .collect::>(), -// ); -// } - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn get_prime() { -// let program = Program::default(); -// assert_eq!(PRIME_STR, program.prime()); -// } - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn iter_builtins() { -// let reference_manager = ReferenceManager { -// references: Vec::new(), -// }; - -// let builtins: Vec<_> = vec![BuiltinName::range_check, BuiltinName::bitwise]; -// let data: Vec<_> = vec![ -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(1000), -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(2000), -// mayberelocatable!(5201798304953696256), -// mayberelocatable!(2345108766317314046), -// ]; - -// let program = Program::new( -// builtins.clone(), -// data, -// None, -// HashMap::new(), -// reference_manager, -// HashMap::new(), -// Vec::new(), -// None, -// ) -// .unwrap(); - -// assert_eq!( -// program.iter_builtins().cloned().collect::>(), -// builtins -// ); - -// assert_eq!(program.builtins_len(), 2); -// } - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn iter_data() { -// let reference_manager = ReferenceManager { -// references: Vec::new(), -// }; - -// let builtins: Vec = Vec::new(); -// let data: Vec = vec![ -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(1000), -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(2000), -// mayberelocatable!(5201798304953696256), -// mayberelocatable!(2345108766317314046), -// ]; - -// let program = Program::new( -// builtins, -// data.clone(), -// None, -// HashMap::new(), -// reference_manager, -// HashMap::new(), -// Vec::new(), -// None, -// ) -// .unwrap(); - -// assert_eq!(program.iter_data().cloned().collect::>(), data); -// } - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn data_len() { -// let reference_manager = ReferenceManager { -// references: Vec::new(), -// }; - -// let builtins: Vec = Vec::new(); -// let data: Vec = vec![ -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(1000), -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(2000), -// mayberelocatable!(5201798304953696256), -// mayberelocatable!(2345108766317314046), -// ]; - -// let program = Program::new( -// builtins, -// data.clone(), -// None, -// HashMap::new(), -// reference_manager, -// HashMap::new(), -// Vec::new(), -// None, -// ) -// .unwrap(); - -// assert_eq!(program.data_len(), data.len()); -// } - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn get_identifier() { -// let reference_manager = ReferenceManager { -// references: Vec::new(), -// }; - -// let builtins: Vec = Vec::new(); - -// let data: Vec = vec![ -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(1000), -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(2000), -// mayberelocatable!(5201798304953696256), -// mayberelocatable!(2345108766317314046), -// ]; - -// let mut identifiers: HashMap = HashMap::new(); - -// identifiers.insert( -// String::from("__main__.main"), -// Identifier { -// pc: Some(0), -// type_: Some(String::from("function")), -// value: None, -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); - -// identifiers.insert( -// String::from("__main__.main.SIZEOF_LOCALS"), -// Identifier { -// pc: None, -// type_: Some(String::from("const")), -// value: Some(Felt252::zero()), -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); - -// let program = Program::new( -// builtins, -// data, -// None, -// HashMap::new(), -// reference_manager, -// identifiers.clone(), -// Vec::new(), -// None, -// ) -// .unwrap(); - -// assert_eq!( -// program.get_identifier("__main__.main"), -// identifiers.get("__main__.main"), -// ); -// assert_eq!( -// program.get_identifier("__main__.main.SIZEOF_LOCALS"), -// identifiers.get("__main__.main.SIZEOF_LOCALS"), -// ); -// assert_eq!( -// program.get_identifier("missing"), -// identifiers.get("missing"), -// ); -// } - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn iter_identifiers() { -// let reference_manager = ReferenceManager { -// references: Vec::new(), -// }; - -// let builtins: Vec = Vec::new(); - -// let data: Vec = vec![ -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(1000), -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(2000), -// mayberelocatable!(5201798304953696256), -// mayberelocatable!(2345108766317314046), -// ]; - -// let mut identifiers: HashMap = HashMap::new(); - -// identifiers.insert( -// String::from("__main__.main"), -// Identifier { -// pc: Some(0), -// type_: Some(String::from("function")), -// value: None, -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); - -// identifiers.insert( -// String::from("__main__.main.SIZEOF_LOCALS"), -// Identifier { -// pc: None, -// type_: Some(String::from("const")), -// value: Some(Felt252::zero()), -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); - -// let program = Program::new( -// builtins, -// data, -// None, -// HashMap::new(), -// reference_manager, -// identifiers.clone(), -// Vec::new(), -// None, -// ) -// .unwrap(); - -// let collected_identifiers: HashMap<_, _> = program -// .iter_identifiers() -// .map(|(cairo_type, identifier)| (cairo_type.to_string(), identifier.clone())) -// .collect(); - -// assert_eq!(collected_identifiers, identifiers); -// } - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn new_program_with_invalid_identifiers() { -// let reference_manager = ReferenceManager { -// references: Vec::new(), -// }; - -// let builtins: Vec = Vec::new(); - -// let data: Vec = vec![ -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(1000), -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(2000), -// mayberelocatable!(5201798304953696256), -// mayberelocatable!(2345108766317314046), -// ]; - -// let mut identifiers: HashMap = HashMap::new(); - -// identifiers.insert( -// String::from("__main__.main"), -// Identifier { -// pc: Some(0), -// type_: Some(String::from("function")), -// value: None, -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); - -// identifiers.insert( -// String::from("__main__.main.SIZEOF_LOCALS"), -// Identifier { -// pc: None, -// type_: Some(String::from("const")), -// value: None, -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); - -// let program = Program::new( -// builtins, -// data, -// None, -// HashMap::new(), -// reference_manager, -// identifiers.clone(), -// Vec::new(), -// None, -// ); - -// assert!(program.is_err()); -// } - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn deserialize_program_test() { -// let program = Program::from_bytes( -// include_bytes!("../../../cairo_programs/manually_compiled/valid_program_a.json"), -// Some("main"), -// ) -// .unwrap(); - -// let builtins: Vec = Vec::new(); -// let data: Vec = vec![ -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(1000), -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(2000), -// mayberelocatable!(5201798304953696256), -// mayberelocatable!(2345108766317314046), -// ]; - -// let mut identifiers: HashMap = HashMap::new(); - -// identifiers.insert( -// String::from("__main__.main"), -// Identifier { -// pc: Some(0), -// type_: Some(String::from("function")), -// value: None, -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); -// identifiers.insert( -// String::from("__main__.main.Args"), -// Identifier { -// pc: None, -// type_: Some(String::from("struct")), -// value: None, -// full_name: Some("__main__.main.Args".to_string()), -// members: Some(HashMap::new()), -// cairo_type: None, -// }, -// ); -// identifiers.insert( -// String::from("__main__.main.ImplicitArgs"), -// Identifier { -// pc: None, -// type_: Some(String::from("struct")), -// value: None, -// full_name: Some("__main__.main.ImplicitArgs".to_string()), -// members: Some(HashMap::new()), -// cairo_type: None, -// }, -// ); -// identifiers.insert( -// String::from("__main__.main.Return"), -// Identifier { -// pc: None, -// type_: Some(String::from("struct")), -// value: None, -// full_name: Some("__main__.main.Return".to_string()), -// members: Some(HashMap::new()), -// cairo_type: None, -// }, -// ); -// identifiers.insert( -// String::from("__main__.main.SIZEOF_LOCALS"), -// Identifier { -// pc: None, -// type_: Some(String::from("const")), -// value: Some(Felt252::zero()), -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); - -// assert_eq!(program.builtins, builtins); -// assert_eq!(program.shared_program_data.data, data); -// assert_eq!(program.shared_program_data.main, Some(0)); -// assert_eq!(program.shared_program_data.identifiers, identifiers); -// } - -// /// Deserialize a program without an entrypoint. -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn deserialize_program_without_entrypoint_test() { -// let program = Program::from_bytes( -// include_bytes!("../../../cairo_programs/manually_compiled/valid_program_a.json"), -// None, -// ) -// .unwrap(); - -// let builtins: Vec = Vec::new(); - -// let error_message_attributes: Vec = vec![Attribute { -// name: String::from("error_message"), -// start_pc: 379, -// end_pc: 381, -// value: String::from("SafeUint256: addition overflow"), -// flow_tracking_data: Some(FlowTrackingData { -// ap_tracking: ApTracking { -// group: 14, -// offset: 35, -// }, -// reference_ids: HashMap::new(), -// }), -// }]; - -// let data: Vec = vec![ -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(1000), -// mayberelocatable!(5189976364521848832), -// mayberelocatable!(2000), -// mayberelocatable!(5201798304953696256), -// mayberelocatable!(2345108766317314046), -// ]; - -// let mut identifiers: HashMap = HashMap::new(); - -// identifiers.insert( -// String::from("__main__.main"), -// Identifier { -// pc: Some(0), -// type_: Some(String::from("function")), -// value: None, -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); -// identifiers.insert( -// String::from("__main__.main.Args"), -// Identifier { -// pc: None, -// type_: Some(String::from("struct")), -// value: None, -// full_name: Some("__main__.main.Args".to_string()), -// members: Some(HashMap::new()), -// cairo_type: None, -// }, -// ); -// identifiers.insert( -// String::from("__main__.main.ImplicitArgs"), -// Identifier { -// pc: None, -// type_: Some(String::from("struct")), -// value: None, -// full_name: Some("__main__.main.ImplicitArgs".to_string()), -// members: Some(HashMap::new()), -// cairo_type: None, -// }, -// ); -// identifiers.insert( -// String::from("__main__.main.Return"), -// Identifier { -// pc: None, -// type_: Some(String::from("struct")), -// value: None, -// full_name: Some("__main__.main.Return".to_string()), -// members: Some(HashMap::new()), -// cairo_type: None, -// }, -// ); -// identifiers.insert( -// String::from("__main__.main.SIZEOF_LOCALS"), -// Identifier { -// pc: None, -// type_: Some(String::from("const")), -// value: Some(Felt252::zero()), -// full_name: None, -// members: None, -// cairo_type: None, -// }, -// ); - -// assert_eq!(program.builtins, builtins); -// assert_eq!(program.shared_program_data.data, data); -// assert_eq!(program.shared_program_data.main, None); -// assert_eq!(program.shared_program_data.identifiers, identifiers); -// assert_eq!( -// program.shared_program_data.error_message_attributes, -// error_message_attributes -// ) -// } - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn deserialize_program_constants_test() { -// let program = Program::from_bytes( -// include_bytes!( -// "../../../cairo_programs/manually_compiled/deserialize_constant_test.json" -// ), -// Some("main"), -// ) -// .unwrap(); - -// let constants = [ -// ("__main__.compare_abs_arrays.SIZEOF_LOCALS", Felt252::zero()), -// ( -// "starkware.cairo.common.cairo_keccak.packed_keccak.ALL_ONES", -// felt_str!( -// "3618502788666131106986593281521497120414687020801267626233049500247285301247" -// ), -// ), -// ( -// "starkware.cairo.common.cairo_keccak.packed_keccak.BLOCK_SIZE", -// Felt252::new(3), -// ), -// ( -// "starkware.cairo.common.alloc.alloc.SIZEOF_LOCALS", -// felt_str!( -// "-3618502788666131213697322783095070105623107215331596699973092056135872020481" -// ), -// ), -// ( -// "starkware.cairo.common.uint256.SHIFT", -// felt_str!("340282366920938463463374607431768211456"), -// ), -// ] -// .into_iter() -// .map(|(key, value)| (key.to_string(), value)) -// .collect::>(); - -// assert_eq!(program.constants, constants); -// } - -// #[test] -// #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] -// fn default_program() { -// let hints_collection = HintsCollection { -// hints: Vec::new(), -// hints_ranges: HashMap::new(), -// }; - -// let shared_program_data = SharedProgramData { -// data: Vec::new(), -// hints_collection, -// main: None, -// start: None, -// end: None, -// error_message_attributes: Vec::new(), -// instruction_locations: None, -// identifiers: HashMap::new(), -// reference_manager: Program::get_reference_list(&ReferenceManager { -// references: Vec::new(), -// }), -// }; -// let program = Program { -// shared_program_data: Arc::new(shared_program_data), -// constants: HashMap::new(), -// builtins: Vec::new(), -// }; - -// assert_eq!(program, Program::default()); -// } - -// #[test] -// fn get_stripped_program() { -// let program_content = include_bytes!("../../../cairo_programs/pedersen_test.json"); -// let program = Program::from_bytes(program_content, Some("main")).unwrap(); -// let stripped_program = program.get_stripped_program().unwrap(); -// assert_eq!(stripped_program.builtins, program.builtins); -// assert_eq!(stripped_program.data, program.shared_program_data.data); -// assert_eq!( -// stripped_program.main, -// program.shared_program_data.main.unwrap() -// ); -// } - -// #[test] -// fn get_stripped_no_main() { -// let program_content = -// include_bytes!("../../../cairo_programs/proof_programs/fibonacci.json"); -// let program = Program::from_bytes(program_content, None).unwrap(); -// assert_matches!( -// program.get_stripped_program(), -// Err(ProgramError::StrippedProgramNoMain) -// ); -// } -// } +#[cfg(test)] +impl HintsCollection { + pub fn iter(&self) -> impl Iterator { + self.hints_ranges.iter().filter_map(|(pc, (start, len))| { + let end = start + len.get(); + if end <= self.hints.len() { + Some((pc.offset, &self.hints[*start..end])) + } else { + None + } + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::serde::deserialize_program::{ApTracking, FlowTrackingData}; + use crate::utils::test_utils::*; + use felt::felt_str; + use num_traits::Zero; + + use assert_matches::assert_matches; + + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::*; + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn new() { + let reference_manager = ReferenceManager { + references: Vec::new(), + }; + + let builtins: Vec = Vec::new(); + let data: Vec = vec![ + mayberelocatable!(5189976364521848832), + mayberelocatable!(1000), + mayberelocatable!(5189976364521848832), + mayberelocatable!(2000), + mayberelocatable!(5201798304953696256), + mayberelocatable!(2345108766317314046), + ]; + + let program = Program::new( + builtins.clone(), + data.clone(), + None, + HashMap::new(), + reference_manager, + HashMap::new(), + Vec::new(), + None, + ) + .unwrap(); + + assert_eq!(program.builtins, builtins); + assert_eq!(program.shared_program_data.data, data); + assert_eq!(program.shared_program_data.main, None); + assert_eq!(program.shared_program_data.identifiers, HashMap::new()); + assert_eq!( + program.shared_program_data.hints_collection.hints, + Vec::new() + ); + assert_eq!( + program.shared_program_data.hints_collection.hints_ranges, + HashMap::new() + ); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn new_for_proof() { + let reference_manager = ReferenceManager { + references: Vec::new(), + }; + + let builtins: Vec = Vec::new(); + let data: Vec = vec![ + mayberelocatable!(5189976364521848832), + mayberelocatable!(1000), + mayberelocatable!(5189976364521848832), + mayberelocatable!(2000), + mayberelocatable!(5201798304953696256), + mayberelocatable!(2345108766317314046), + ]; + + let program = Program::new_for_proof( + builtins.clone(), + data.clone(), + 0, + 1, + HashMap::new(), + reference_manager, + HashMap::new(), + Vec::new(), + None, + ) + .unwrap(); + + assert_eq!(program.builtins, builtins); + assert_eq!(program.shared_program_data.data, data); + assert_eq!(program.shared_program_data.main, None); + assert_eq!(program.shared_program_data.start, Some(0)); + assert_eq!(program.shared_program_data.end, Some(1)); + assert_eq!(program.shared_program_data.identifiers, HashMap::new()); + assert_eq!( + program.shared_program_data.hints_collection.hints, + Vec::new() + ); + assert_eq!( + program.shared_program_data.hints_collection.hints_ranges, + Vec::new() + ); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn new_program_with_hints() { + let reference_manager = ReferenceManager { + references: Vec::new(), + }; + + let builtins: Vec = Vec::new(); + let data: Vec = vec![ + mayberelocatable!(5189976364521848832), + mayberelocatable!(1000), + mayberelocatable!(5189976364521848832), + mayberelocatable!(2000), + mayberelocatable!(5201798304953696256), + mayberelocatable!(2345108766317314046), + ]; + + let str_to_hint_param = |s: &str| HintParams { + code: s.to_string(), + accessible_scopes: vec![], + flow_tracking_data: FlowTrackingData { + ap_tracking: ApTracking { + group: 0, + offset: 0, + }, + reference_ids: HashMap::new(), + }, + }; + + let hints = HashMap::from([ + (5, vec![str_to_hint_param("c"), str_to_hint_param("d")]), + (1, vec![str_to_hint_param("a")]), + (4, vec![str_to_hint_param("b")]), + ]); + + let program = Program::new( + builtins.clone(), + data.clone(), + None, + hints.clone(), + reference_manager, + HashMap::new(), + Vec::new(), + None, + ) + .unwrap(); + + assert_eq!(program.builtins, builtins); + assert_eq!(program.shared_program_data.data, data); + assert_eq!(program.shared_program_data.main, None); + assert_eq!(program.shared_program_data.identifiers, HashMap::new()); + + let program_hints: HashMap<_, _> = program + .shared_program_data + .hints_collection + .hints_ranges + .iter() + .filter_map(|(pc, (s, l))| { + ( + pc, + program.shared_program_data.hints_collection.hints[*s..((s, s + l.get()))] + .to_vec(), + ) + }) + .collect(); + assert_eq!(program_hints, hints); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn new_program_with_identifiers() { + let reference_manager = ReferenceManager { + references: Vec::new(), + }; + + let builtins: Vec = Vec::new(); + + let data: Vec = vec![ + mayberelocatable!(5189976364521848832), + mayberelocatable!(1000), + mayberelocatable!(5189976364521848832), + mayberelocatable!(2000), + mayberelocatable!(5201798304953696256), + mayberelocatable!(2345108766317314046), + ]; + + let mut identifiers: HashMap = HashMap::new(); + + identifiers.insert( + String::from("__main__.main"), + Identifier { + pc: Some(0), + type_: Some(String::from("function")), + value: None, + full_name: None, + members: None, + cairo_type: None, + }, + ); + + identifiers.insert( + String::from("__main__.main.SIZEOF_LOCALS"), + Identifier { + pc: None, + type_: Some(String::from("const")), + value: Some(Felt252::zero()), + full_name: None, + members: None, + cairo_type: None, + }, + ); + + let program = Program::new( + builtins.clone(), + data.clone(), + None, + HashMap::new(), + reference_manager, + identifiers.clone(), + Vec::new(), + None, + ) + .unwrap(); + + assert_eq!(program.builtins, builtins); + assert_eq!(program.shared_program_data.data, data); + assert_eq!(program.shared_program_data.main, None); + assert_eq!(program.shared_program_data.identifiers, identifiers); + assert_eq!( + program.constants, + [("__main__.main.SIZEOF_LOCALS", Felt252::zero())] + .into_iter() + .map(|(key, value)| (key.to_string(), value)) + .collect::>(), + ); + } + + #[test] + fn extract_constants() { + let mut identifiers: HashMap = HashMap::new(); + + identifiers.insert( + String::from("__main__.main"), + Identifier { + pc: Some(0), + type_: Some(String::from("function")), + value: None, + full_name: None, + members: None, + cairo_type: None, + }, + ); + + identifiers.insert( + String::from("__main__.main.SIZEOF_LOCALS"), + Identifier { + pc: None, + type_: Some(String::from("const")), + value: Some(Felt252::zero()), + full_name: None, + members: None, + cairo_type: None, + }, + ); + + assert_eq!( + Program::extract_constants(&identifiers).unwrap(), + [("__main__.main.SIZEOF_LOCALS", Felt252::zero())] + .into_iter() + .map(|(key, value)| (key.to_string(), value)) + .collect::>(), + ); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn get_prime() { + let program = Program::default(); + assert_eq!(PRIME_STR, program.prime()); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn iter_builtins() { + let reference_manager = ReferenceManager { + references: Vec::new(), + }; + + let builtins: Vec<_> = vec![BuiltinName::range_check, BuiltinName::bitwise]; + let data: Vec<_> = vec![ + mayberelocatable!(5189976364521848832), + mayberelocatable!(1000), + mayberelocatable!(5189976364521848832), + mayberelocatable!(2000), + mayberelocatable!(5201798304953696256), + mayberelocatable!(2345108766317314046), + ]; + + let program = Program::new( + builtins.clone(), + data, + None, + HashMap::new(), + reference_manager, + HashMap::new(), + Vec::new(), + None, + ) + .unwrap(); + + assert_eq!( + program.iter_builtins().cloned().collect::>(), + builtins + ); + + assert_eq!(program.builtins_len(), 2); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn iter_data() { + let reference_manager = ReferenceManager { + references: Vec::new(), + }; + + let builtins: Vec = Vec::new(); + let data: Vec = vec![ + mayberelocatable!(5189976364521848832), + mayberelocatable!(1000), + mayberelocatable!(5189976364521848832), + mayberelocatable!(2000), + mayberelocatable!(5201798304953696256), + mayberelocatable!(2345108766317314046), + ]; + + let program = Program::new( + builtins, + data.clone(), + None, + HashMap::new(), + reference_manager, + HashMap::new(), + Vec::new(), + None, + ) + .unwrap(); + + assert_eq!(program.iter_data().cloned().collect::>(), data); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn data_len() { + let reference_manager = ReferenceManager { + references: Vec::new(), + }; + + let builtins: Vec = Vec::new(); + let data: Vec = vec![ + mayberelocatable!(5189976364521848832), + mayberelocatable!(1000), + mayberelocatable!(5189976364521848832), + mayberelocatable!(2000), + mayberelocatable!(5201798304953696256), + mayberelocatable!(2345108766317314046), + ]; + + let program = Program::new( + builtins, + data.clone(), + None, + HashMap::new(), + reference_manager, + HashMap::new(), + Vec::new(), + None, + ) + .unwrap(); + + assert_eq!(program.data_len(), data.len()); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn get_identifier() { + let reference_manager = ReferenceManager { + references: Vec::new(), + }; + + let builtins: Vec = Vec::new(); + + let data: Vec = vec![ + mayberelocatable!(5189976364521848832), + mayberelocatable!(1000), + mayberelocatable!(5189976364521848832), + mayberelocatable!(2000), + mayberelocatable!(5201798304953696256), + mayberelocatable!(2345108766317314046), + ]; + + let mut identifiers: HashMap = HashMap::new(); + + identifiers.insert( + String::from("__main__.main"), + Identifier { + pc: Some(0), + type_: Some(String::from("function")), + value: None, + full_name: None, + members: None, + cairo_type: None, + }, + ); + + identifiers.insert( + String::from("__main__.main.SIZEOF_LOCALS"), + Identifier { + pc: None, + type_: Some(String::from("const")), + value: Some(Felt252::zero()), + full_name: None, + members: None, + cairo_type: None, + }, + ); + + let program = Program::new( + builtins, + data, + None, + HashMap::new(), + reference_manager, + identifiers.clone(), + Vec::new(), + None, + ) + .unwrap(); + + assert_eq!( + program.get_identifier("__main__.main"), + identifiers.get("__main__.main"), + ); + assert_eq!( + program.get_identifier("__main__.main.SIZEOF_LOCALS"), + identifiers.get("__main__.main.SIZEOF_LOCALS"), + ); + assert_eq!( + program.get_identifier("missing"), + identifiers.get("missing"), + ); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn iter_identifiers() { + let reference_manager = ReferenceManager { + references: Vec::new(), + }; + + let builtins: Vec = Vec::new(); + + let data: Vec = vec![ + mayberelocatable!(5189976364521848832), + mayberelocatable!(1000), + mayberelocatable!(5189976364521848832), + mayberelocatable!(2000), + mayberelocatable!(5201798304953696256), + mayberelocatable!(2345108766317314046), + ]; + + let mut identifiers: HashMap = HashMap::new(); + + identifiers.insert( + String::from("__main__.main"), + Identifier { + pc: Some(0), + type_: Some(String::from("function")), + value: None, + full_name: None, + members: None, + cairo_type: None, + }, + ); + + identifiers.insert( + String::from("__main__.main.SIZEOF_LOCALS"), + Identifier { + pc: None, + type_: Some(String::from("const")), + value: Some(Felt252::zero()), + full_name: None, + members: None, + cairo_type: None, + }, + ); + + let program = Program::new( + builtins, + data, + None, + HashMap::new(), + reference_manager, + identifiers.clone(), + Vec::new(), + None, + ) + .unwrap(); + + let collected_identifiers: HashMap<_, _> = program + .iter_identifiers() + .map(|(cairo_type, identifier)| (cairo_type.to_string(), identifier.clone())) + .collect(); + + assert_eq!(collected_identifiers, identifiers); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn new_program_with_invalid_identifiers() { + let reference_manager = ReferenceManager { + references: Vec::new(), + }; + + let builtins: Vec = Vec::new(); + + let data: Vec = vec![ + mayberelocatable!(5189976364521848832), + mayberelocatable!(1000), + mayberelocatable!(5189976364521848832), + mayberelocatable!(2000), + mayberelocatable!(5201798304953696256), + mayberelocatable!(2345108766317314046), + ]; + + let mut identifiers: HashMap = HashMap::new(); + + identifiers.insert( + String::from("__main__.main"), + Identifier { + pc: Some(0), + type_: Some(String::from("function")), + value: None, + full_name: None, + members: None, + cairo_type: None, + }, + ); + + identifiers.insert( + String::from("__main__.main.SIZEOF_LOCALS"), + Identifier { + pc: None, + type_: Some(String::from("const")), + value: None, + full_name: None, + members: None, + cairo_type: None, + }, + ); + + let program = Program::new( + builtins, + data, + None, + HashMap::new(), + reference_manager, + identifiers.clone(), + Vec::new(), + None, + ); + + assert!(program.is_err()); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn deserialize_program_test() { + let program = Program::from_bytes( + include_bytes!("../../../cairo_programs/manually_compiled/valid_program_a.json"), + Some("main"), + ) + .unwrap(); + + let builtins: Vec = Vec::new(); + let data: Vec = vec![ + mayberelocatable!(5189976364521848832), + mayberelocatable!(1000), + mayberelocatable!(5189976364521848832), + mayberelocatable!(2000), + mayberelocatable!(5201798304953696256), + mayberelocatable!(2345108766317314046), + ]; + + let mut identifiers: HashMap = HashMap::new(); + + identifiers.insert( + String::from("__main__.main"), + Identifier { + pc: Some(0), + type_: Some(String::from("function")), + value: None, + full_name: None, + members: None, + cairo_type: None, + }, + ); + identifiers.insert( + String::from("__main__.main.Args"), + Identifier { + pc: None, + type_: Some(String::from("struct")), + value: None, + full_name: Some("__main__.main.Args".to_string()), + members: Some(HashMap::new()), + cairo_type: None, + }, + ); + identifiers.insert( + String::from("__main__.main.ImplicitArgs"), + Identifier { + pc: None, + type_: Some(String::from("struct")), + value: None, + full_name: Some("__main__.main.ImplicitArgs".to_string()), + members: Some(HashMap::new()), + cairo_type: None, + }, + ); + identifiers.insert( + String::from("__main__.main.Return"), + Identifier { + pc: None, + type_: Some(String::from("struct")), + value: None, + full_name: Some("__main__.main.Return".to_string()), + members: Some(HashMap::new()), + cairo_type: None, + }, + ); + identifiers.insert( + String::from("__main__.main.SIZEOF_LOCALS"), + Identifier { + pc: None, + type_: Some(String::from("const")), + value: Some(Felt252::zero()), + full_name: None, + members: None, + cairo_type: None, + }, + ); + + assert_eq!(program.builtins, builtins); + assert_eq!(program.shared_program_data.data, data); + assert_eq!(program.shared_program_data.main, Some(0)); + assert_eq!(program.shared_program_data.identifiers, identifiers); + } + + /// Deserialize a program without an entrypoint. + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn deserialize_program_without_entrypoint_test() { + let program = Program::from_bytes( + include_bytes!("../../../cairo_programs/manually_compiled/valid_program_a.json"), + None, + ) + .unwrap(); + + let builtins: Vec = Vec::new(); + + let error_message_attributes: Vec = vec![Attribute { + name: String::from("error_message"), + start_pc: 379, + end_pc: 381, + value: String::from("SafeUint256: addition overflow"), + flow_tracking_data: Some(FlowTrackingData { + ap_tracking: ApTracking { + group: 14, + offset: 35, + }, + reference_ids: HashMap::new(), + }), + }]; + + let data: Vec = vec![ + mayberelocatable!(5189976364521848832), + mayberelocatable!(1000), + mayberelocatable!(5189976364521848832), + mayberelocatable!(2000), + mayberelocatable!(5201798304953696256), + mayberelocatable!(2345108766317314046), + ]; + + let mut identifiers: HashMap = HashMap::new(); + + identifiers.insert( + String::from("__main__.main"), + Identifier { + pc: Some(0), + type_: Some(String::from("function")), + value: None, + full_name: None, + members: None, + cairo_type: None, + }, + ); + identifiers.insert( + String::from("__main__.main.Args"), + Identifier { + pc: None, + type_: Some(String::from("struct")), + value: None, + full_name: Some("__main__.main.Args".to_string()), + members: Some(HashMap::new()), + cairo_type: None, + }, + ); + identifiers.insert( + String::from("__main__.main.ImplicitArgs"), + Identifier { + pc: None, + type_: Some(String::from("struct")), + value: None, + full_name: Some("__main__.main.ImplicitArgs".to_string()), + members: Some(HashMap::new()), + cairo_type: None, + }, + ); + identifiers.insert( + String::from("__main__.main.Return"), + Identifier { + pc: None, + type_: Some(String::from("struct")), + value: None, + full_name: Some("__main__.main.Return".to_string()), + members: Some(HashMap::new()), + cairo_type: None, + }, + ); + identifiers.insert( + String::from("__main__.main.SIZEOF_LOCALS"), + Identifier { + pc: None, + type_: Some(String::from("const")), + value: Some(Felt252::zero()), + full_name: None, + members: None, + cairo_type: None, + }, + ); + + assert_eq!(program.builtins, builtins); + assert_eq!(program.shared_program_data.data, data); + assert_eq!(program.shared_program_data.main, None); + assert_eq!(program.shared_program_data.identifiers, identifiers); + assert_eq!( + program.shared_program_data.error_message_attributes, + error_message_attributes + ) + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn deserialize_program_constants_test() { + let program = Program::from_bytes( + include_bytes!( + "../../../cairo_programs/manually_compiled/deserialize_constant_test.json" + ), + Some("main"), + ) + .unwrap(); + + let constants = [ + ("__main__.compare_abs_arrays.SIZEOF_LOCALS", Felt252::zero()), + ( + "starkware.cairo.common.cairo_keccak.packed_keccak.ALL_ONES", + felt_str!( + "3618502788666131106986593281521497120414687020801267626233049500247285301247" + ), + ), + ( + "starkware.cairo.common.cairo_keccak.packed_keccak.BLOCK_SIZE", + Felt252::new(3), + ), + ( + "starkware.cairo.common.alloc.alloc.SIZEOF_LOCALS", + felt_str!( + "-3618502788666131213697322783095070105623107215331596699973092056135872020481" + ), + ), + ( + "starkware.cairo.common.uint256.SHIFT", + felt_str!("340282366920938463463374607431768211456"), + ), + ] + .into_iter() + .map(|(key, value)| (key.to_string(), value)) + .collect::>(); + + assert_eq!(program.constants, constants); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn default_program() { + let hints_collection = HintsCollection { + hints: Vec::new(), + hints_ranges: HashMap::new(), + }; + + let shared_program_data = SharedProgramData { + data: Vec::new(), + hints_collection, + main: None, + start: None, + end: None, + error_message_attributes: Vec::new(), + instruction_locations: None, + identifiers: HashMap::new(), + reference_manager: Program::get_reference_list(&ReferenceManager { + references: Vec::new(), + }), + }; + let program = Program { + shared_program_data: Arc::new(shared_program_data), + constants: HashMap::new(), + builtins: Vec::new(), + }; + + assert_eq!(program, Program::default()); + } + + #[test] + fn get_stripped_program() { + let program_content = include_bytes!("../../../cairo_programs/pedersen_test.json"); + let program = Program::from_bytes(program_content, Some("main")).unwrap(); + let stripped_program = program.get_stripped_program().unwrap(); + assert_eq!(stripped_program.builtins, program.builtins); + assert_eq!(stripped_program.data, program.shared_program_data.data); + assert_eq!( + stripped_program.main, + program.shared_program_data.main.unwrap() + ); + } + + #[test] + fn get_stripped_no_main() { + let program_content = + include_bytes!("../../../cairo_programs/proof_programs/fibonacci.json"); + let program = Program::from_bytes(program_content, None).unwrap(); + assert_matches!( + program.get_stripped_program(), + Err(ProgramError::StrippedProgramNoMain) + ); + } +} From 655f5fa5591576fc2af9931e6cbddb54d54b2543 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 11:31:41 -0300 Subject: [PATCH 05/23] Add execute_hint_extensive --- .../hint_processor_definition.rs | 25 +++++------- vm/src/vm/vm_core.rs | 38 +++++++++++-------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/vm/src/hint_processor/hint_processor_definition.rs b/vm/src/hint_processor/hint_processor_definition.rs index daeffb2e51..dd310307f0 100644 --- a/vm/src/hint_processor/hint_processor_definition.rs +++ b/vm/src/hint_processor/hint_processor_definition.rs @@ -6,7 +6,6 @@ use crate::serde::deserialize_program::OffsetValue; use crate::serde::deserialize_program::Reference; use crate::types::exec_scope::ExecutionScopes; use crate::types::instruction::Register; -use crate::types::program::HintRange; use crate::types::relocatable::Relocatable; use crate::vm::errors::hint_errors::HintError; use crate::vm::errors::vm_errors::VirtualMachineError; @@ -56,7 +55,8 @@ pub trait HintProcessorLogic { } //Executes the hint which's data is provided by a dynamic structure previously created by compile_hint - fn execute_and_mutate_hints( + + fn execute_hint_extensive( &mut self, //Proxy to VM, contains refrences to necessary data //+ MemoryProxy, which provides the necessary methods to manipulate memory @@ -64,25 +64,18 @@ pub trait HintProcessorLogic { //Proxy to ExecutionScopes, provides the necessary methods to manipulate the scopes and //access current scope variables exec_scopes: &mut ExecutionScopes, + //Data structure that can be downcasted to the structure generated by compile_hint + hint_data: &Box, //Constant values extracted from the program specification. constants: &HashMap, - // Mutable hints - mutable_hints: &mut [Box], - // Mutable hint ranges - mutable_ranges: &mut HashMap, - ) -> Result<(), VirtualMachineError> { - let hint_range = &mutable_ranges - .get(&vm.run_context.pc) - .and_then(|(start, length)| mutable_hints.get(*start..*start + length.get())) - .unwrap_or(&[]); - for (hint_index, hint_data) in hint_range.iter().enumerate() { - self.execute_hint(vm, exec_scopes, hint_data, constants) - .map_err(|err| VirtualMachineError::Hint(Box::new((hint_index, err))))? - } - Ok(()) + ) -> Result, HintError> { + self.execute_hint(vm, exec_scopes, hint_data, constants)?; + Ok(None) } } +pub type HintExtension = HashMap>>; + pub trait HintProcessor: HintProcessorLogic + ResourceTracker {} impl HintProcessor for T where T: HintProcessorLogic + ResourceTracker {} diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 2df32959a4..3b6a685cb7 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -444,19 +444,22 @@ impl VirtualMachine { pub fn step_hint( &mut self, - hint_executor: &mut dyn HintProcessor, + hint_processor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, hint_datas: &mut Vec>, hint_ranges: &mut HashMap, constants: &HashMap, ) -> Result<(), VirtualMachineError> { - hint_executor.execute_and_mutate_hints( - self, - exec_scopes, - constants, - hint_datas, - hint_ranges, - ) + let hint_range = &hint_ranges + .get(&self.run_context.pc) + .and_then(|(start, length)| hint_datas.get(*start..*start + length.get())) + .unwrap_or(&[]); + for (hint_index, hint_data) in hint_range.iter().enumerate() { + hint_processor + .execute_hint(self, exec_scopes, hint_data, constants) + .map_err(|err| VirtualMachineError::Hint(Box::new((hint_index, err))))? + } + Ok(()) } pub fn step_instruction(&mut self) -> Result<(), VirtualMachineError> { @@ -2691,7 +2694,8 @@ mod tests { vm.step( &mut hint_processor, exec_scopes_ref!(), - &Vec::new(), + &mut Vec::new(), + &mut HashMap::new(), &HashMap::new(), ), Ok(()) @@ -2920,8 +2924,9 @@ mod tests { vm.step( &mut hint_processor, exec_scopes_ref!(), - &Vec::new(), - &HashMap::new() + &mut Vec::new(), + &mut HashMap::new(), + &HashMap::new(), ), Ok(()) ); @@ -3002,7 +3007,8 @@ mod tests { vm.step( &mut hint_processor, exec_scopes_ref!(), - &Vec::new(), + &mut Vec::new(), + &mut HashMap::new(), &HashMap::new() ), Ok(()) @@ -3098,7 +3104,8 @@ mod tests { vm.step( &mut hint_processor, exec_scopes_ref!(), - &Vec::new(), + &mut Vec::new(), + &mut HashMap::new(), &HashMap::new() ), Ok(()) @@ -3708,8 +3715,9 @@ mod tests { vm.step( &mut hint_processor, exec_scopes_ref!(), - hint_data, - &HashMap::new() + &mut hint_data, + &mut HashMap::new(), + &HashMap::new(), ), Ok(()) ); From 10dd42a3db55b0c049d1872a2ca449095cf726e3 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 12:17:44 -0300 Subject: [PATCH 06/23] Process --- vm/src/vm/vm_core.rs | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 3b6a685cb7..6b070a77cb 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -25,6 +25,7 @@ use crate::{ }; use core::cmp::Ordering; +use core::num::NonZeroUsize; use felt::Felt252; use num_traits::{ToPrimitive, Zero}; @@ -450,15 +451,38 @@ impl VirtualMachine { hint_ranges: &mut HashMap, constants: &HashMap, ) -> Result<(), VirtualMachineError> { - let hint_range = &hint_ranges - .get(&self.run_context.pc) - .and_then(|(start, length)| hint_datas.get(*start..*start + length.get())) - .unwrap_or(&[]); - for (hint_index, hint_data) in hint_range.iter().enumerate() { - hint_processor - .execute_hint(self, exec_scopes, hint_data, constants) - .map_err(|err| VirtualMachineError::Hint(Box::new((hint_index, err))))? + // let hint_range = &hint_ranges + // .get(&self.run_context.pc) + // .and_then(|(start, length)| hint_datas.get(*start..*start + length.get())) + // .unwrap_or(&[]); + // for (hint_index, hint_data) in hint_range.iter().enumerate() { + // if let Some(hint_extension) = hint_processor + // .execute_hint_extensive(self, exec_scopes, hint_data, constants) + // .map_err(|err| VirtualMachineError::Hint(Box::new((hint_index, err))))? + // { + // for (hint_pc, hints) in hint_extension { + // if let Ok(len) = NonZeroUsize::try_from(hints.len()) { + // hint_ranges.insert(hint_pc, (hint_datas.len(), len)); + // hint_datas.extend(hints); + // } + // } + // } + // } + if let Some((s, l)) = hint_ranges.get(&self.run_context.pc) { + for idx in *s..l.get() { + let res = hint_processor + .execute_hint_extensive(self, exec_scopes, hint_datas.get(idx).unwrap(), constants) + .unwrap(); + if let Some(hint_extension) = res { + for (hint_pc, hints) in hint_extension { + if let Ok(len) = NonZeroUsize::try_from(hints.len()) { + hint_ranges.insert(hint_pc, (hint_datas.len(), len)); + hint_datas.extend(hints); + } + } + } } + } Ok(()) } From 569583d7a209a61c6b77bb75357ca113d8204da5 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 13:26:44 -0300 Subject: [PATCH 07/23] Add error handling --- vm/src/vm/vm_core.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 6b070a77cb..0f2f9eb034 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -469,20 +469,26 @@ impl VirtualMachine { // } // } if let Some((s, l)) = hint_ranges.get(&self.run_context.pc) { - for idx in *s..l.get() { - let res = hint_processor - .execute_hint_extensive(self, exec_scopes, hint_datas.get(idx).unwrap(), constants) - .unwrap(); - if let Some(hint_extension) = res { - for (hint_pc, hints) in hint_extension { - if let Ok(len) = NonZeroUsize::try_from(hints.len()) { - hint_ranges.insert(hint_pc, (hint_datas.len(), len)); - hint_datas.extend(hints); + let s = *s; + for idx in s..l.get() { + let res = hint_processor + .execute_hint_extensive( + self, + exec_scopes, + hint_datas.get(idx).ok_or(VirtualMachineError::Unexpected)?, + constants, + ) + .map_err(|err| VirtualMachineError::Hint(Box::new((idx - s, err))))?; + if let Some(hint_extension) = res { + for (hint_pc, hints) in hint_extension { + if let Ok(len) = NonZeroUsize::try_from(hints.len()) { + hint_ranges.insert(hint_pc, (hint_datas.len(), len)); + hint_datas.extend(hints); + } } } } } - } Ok(()) } From 15774e9776f469d19d78fb208c8e85cd154202f4 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 13:30:16 -0300 Subject: [PATCH 08/23] Add comments & remove previous impl --- vm/src/vm/vm_core.rs | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 0f2f9eb034..f0977afccc 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -451,25 +451,11 @@ impl VirtualMachine { hint_ranges: &mut HashMap, constants: &HashMap, ) -> Result<(), VirtualMachineError> { - // let hint_range = &hint_ranges - // .get(&self.run_context.pc) - // .and_then(|(start, length)| hint_datas.get(*start..*start + length.get())) - // .unwrap_or(&[]); - // for (hint_index, hint_data) in hint_range.iter().enumerate() { - // if let Some(hint_extension) = hint_processor - // .execute_hint_extensive(self, exec_scopes, hint_data, constants) - // .map_err(|err| VirtualMachineError::Hint(Box::new((hint_index, err))))? - // { - // for (hint_pc, hints) in hint_extension { - // if let Ok(len) = NonZeroUsize::try_from(hints.len()) { - // hint_ranges.insert(hint_pc, (hint_datas.len(), len)); - // hint_datas.extend(hints); - // } - // } - // } - // } + // Check if there is a hint range for the current pc if let Some((s, l)) = hint_ranges.get(&self.run_context.pc) { + // Re-binding to avoid mutability problems let s = *s; + // Execute each hint for the given range for idx in s..l.get() { let res = hint_processor .execute_hint_extensive( @@ -479,6 +465,7 @@ impl VirtualMachine { constants, ) .map_err(|err| VirtualMachineError::Hint(Box::new((idx - s, err))))?; + // Check if the hint executed adds new hints, and update the hint_ranges & hint_datas accordingly if let Some(hint_extension) = res { for (hint_pc, hints) in hint_extension { if let Ok(len) = NonZeroUsize::try_from(hints.len()) { From fc76a36c9129829b774af37c5da928bac16b73c6 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 13:31:41 -0300 Subject: [PATCH 09/23] Use Box to reduce output size --- vm/src/hint_processor/hint_processor_definition.rs | 2 +- vm/src/vm/vm_core.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/src/hint_processor/hint_processor_definition.rs b/vm/src/hint_processor/hint_processor_definition.rs index dd310307f0..7834298d02 100644 --- a/vm/src/hint_processor/hint_processor_definition.rs +++ b/vm/src/hint_processor/hint_processor_definition.rs @@ -74,7 +74,7 @@ pub trait HintProcessorLogic { } } -pub type HintExtension = HashMap>>; +pub type HintExtension = Box>>>; pub trait HintProcessor: HintProcessorLogic + ResourceTracker {} impl HintProcessor for T where T: HintProcessorLogic + ResourceTracker {} diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index f0977afccc..309d6e2e72 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -467,7 +467,7 @@ impl VirtualMachine { .map_err(|err| VirtualMachineError::Hint(Box::new((idx - s, err))))?; // Check if the hint executed adds new hints, and update the hint_ranges & hint_datas accordingly if let Some(hint_extension) = res { - for (hint_pc, hints) in hint_extension { + for (hint_pc, hints) in *hint_extension { if let Ok(len) = NonZeroUsize::try_from(hints.len()) { hint_ranges.insert(hint_pc, (hint_datas.len(), len)); hint_datas.extend(hints); From 69651d61c34d4915c13386ef30c74b66401b2e99 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 13:33:21 -0300 Subject: [PATCH 10/23] Fix tests --- vm/src/vm/vm_core.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 309d6e2e72..36d8aeeb32 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -3143,7 +3143,8 @@ mod tests { vm.step( &mut hint_processor, exec_scopes_ref!(), - &Vec::new(), + &mut Vec::new(), + &mut HashMap::new(), &HashMap::new() ), Ok(()) @@ -3165,7 +3166,8 @@ mod tests { vm.step( &mut hint_processor, exec_scopes_ref!(), - &Vec::new(), + &mut Vec::new(), + &mut HashMap::new(), &HashMap::new() ), Ok(()) From e69513eca413a58654ebb62c7a5b580f1887a85f Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 13:44:51 -0300 Subject: [PATCH 11/23] Fix tests --- vm/src/types/program.rs | 8 ++++---- vm/src/vm/vm_core.rs | 9 ++------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/vm/src/types/program.rs b/vm/src/types/program.rs index 3e321d6890..645e5486e8 100644 --- a/vm/src/types/program.rs +++ b/vm/src/types/program.rs @@ -527,7 +527,7 @@ mod tests { ); assert_eq!( program.shared_program_data.hints_collection.hints_ranges, - Vec::new() + HashMap::new() ); } @@ -588,10 +588,10 @@ mod tests { .hints_collection .hints_ranges .iter() - .filter_map(|(pc, (s, l))| { + .map(|(pc, (s, l))| { ( - pc, - program.shared_program_data.hints_collection.hints[*s..((s, s + l.get()))] + pc.offset, + program.shared_program_data.hints_collection.hints[*s..(s + l.get())] .to_vec(), ) }) diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 36d8aeeb32..5f9c962476 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -3687,7 +3687,7 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn test_step_for_preset_memory_with_alloc_hint() { let mut vm = vm!(true); - let hint_data = vec![any_box!(HintProcessorData::new_default( + let mut hint_data = vec![any_box!(HintProcessorData::new_default( "memory[ap] = segments.add()".to_string(), HashMap::new(), ))]; @@ -3725,17 +3725,12 @@ mod tests { //Run Steps for _ in 0..6 { - let hint_data = if vm.run_context.pc == (0, 0).into() { - &hint_data[0..] - } else { - &hint_data[0..0] - }; assert_matches!( vm.step( &mut hint_processor, exec_scopes_ref!(), &mut hint_data, - &mut HashMap::new(), + &mut HashMap::from([(Relocatable::from((0,0)), (0_usize, NonZeroUsize::new(1).unwrap()))]), &HashMap::new(), ), Ok(()) From 07417627e8133dd1ad74587afd96bdf76273323c Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 13:54:15 -0300 Subject: [PATCH 12/23] Fix bug --- vm/src/vm/vm_core.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 5f9c962476..6a2761b6fa 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -456,7 +456,7 @@ impl VirtualMachine { // Re-binding to avoid mutability problems let s = *s; // Execute each hint for the given range - for idx in s..l.get() { + for idx in s..(s + l.get()) { let res = hint_processor .execute_hint_extensive( self, From dc374755880c04b5af0b5652897ca3612ddbbe87 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 13:57:19 -0300 Subject: [PATCH 13/23] Revert hook changes + fmt --- vm/src/types/program.rs | 3 +-- vm/src/vm/hooks.rs | 1 + vm/src/vm/runners/cairo_runner.rs | 2 +- vm/src/vm/vm_core.rs | 5 ++++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/vm/src/types/program.rs b/vm/src/types/program.rs index 645e5486e8..b6ccf89a11 100644 --- a/vm/src/types/program.rs +++ b/vm/src/types/program.rs @@ -591,8 +591,7 @@ mod tests { .map(|(pc, (s, l))| { ( pc.offset, - program.shared_program_data.hints_collection.hints[*s..(s + l.get())] - .to_vec(), + program.shared_program_data.hints_collection.hints[*s..(s + l.get())].to_vec(), ) }) .collect(); diff --git a/vm/src/vm/hooks.rs b/vm/src/vm/hooks.rs index e67fbb621e..b0b6e3c484 100644 --- a/vm/src/vm/hooks.rs +++ b/vm/src/vm/hooks.rs @@ -218,6 +218,7 @@ mod tests { fn before_first_step_hook( _vm: &mut VirtualMachine, _runner: &mut CairoRunner, + _hint_data: &[Box], ) -> Result<(), VirtualMachineError> { Ok(()) } diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 1e2e64e963..704a4d14ef 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -556,7 +556,7 @@ impl CairoRunner { .hints_ranges .clone(); #[cfg(feature = "hooks")] - vm.execute_before_first_step(self)?; + vm.execute_before_first_step(self, &hint_data)?; while vm.run_context.pc != address && !hint_processor.consumed() { vm.step( hint_processor, diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 6a2761b6fa..d14a068282 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -3730,7 +3730,10 @@ mod tests { &mut hint_processor, exec_scopes_ref!(), &mut hint_data, - &mut HashMap::from([(Relocatable::from((0,0)), (0_usize, NonZeroUsize::new(1).unwrap()))]), + &mut HashMap::from([( + Relocatable::from((0, 0)), + (0_usize, NonZeroUsize::new(1).unwrap()) + )]), &HashMap::new(), ), Ok(()) From 0a0a85c23fd971e94130e17d448775971f538c41 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 14:03:24 -0300 Subject: [PATCH 14/23] Uncomment code --- vm/src/serde/serialize_program.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/vm/src/serde/serialize_program.rs b/vm/src/serde/serialize_program.rs index ace6402256..5f55e3fd75 100644 --- a/vm/src/serde/serialize_program.rs +++ b/vm/src/serde/serialize_program.rs @@ -208,15 +208,15 @@ impl From<&Program> for ProgramSerializer { identifiers.insert(key, identifier.into()); } - let hints: BTreeMap> = BTreeMap::new(); - // for (key, hint_params_vec) in BTreeMap::from(&program.shared_program_data.hints_collection) - // { - // let mut new_hints_params = Vec::new(); - // for hint_params in hint_params_vec { - // new_hints_params.push(hint_params.clone().into()); - // } - // hints.insert(key, new_hints_params); - // } + let mut hints: BTreeMap> = BTreeMap::new(); + for (key, hint_params_vec) in BTreeMap::from(&program.shared_program_data.hints_collection) + { + let mut new_hints_params = Vec::new(); + for hint_params in hint_params_vec { + new_hints_params.push(hint_params.clone().into()); + } + hints.insert(key, new_hints_params); + } ProgramSerializer { prime: program.prime().into(), From 9e37055e7958a10c5b40db8f9bd4aaf5aa133c1d Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 14:07:35 -0300 Subject: [PATCH 15/23] revert hook-related vchanges' ' ' --- vm/src/vm/vm_core.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index d14a068282..d8408afa48 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -521,10 +521,10 @@ impl VirtualMachine { )?; #[cfg(feature = "hooks")] - self.execute_pre_step_instruction(hint_executor, exec_scopes, hint_data, constants)?; + self.execute_pre_step_instruction(hint_executor, exec_scopes, hint_datas, constants)?; self.step_instruction()?; #[cfg(feature = "hooks")] - self.execute_post_step_instruction(hint_executor, exec_scopes, hint_data, constants)?; + self.execute_post_step_instruction(hint_executor, exec_scopes, hint_datas, constants)?; Ok(()) } @@ -4273,6 +4273,7 @@ mod tests { fn before_first_step_hook( _vm: &mut VirtualMachine, _runner: &mut CairoRunner, + _hint_data: &[Box], ) -> Result<(), VirtualMachineError> { Err(VirtualMachineError::Unexpected) } From 961cdb07d8e12480c2b2ff6b5a39b81b1c18b068 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 14:20:00 -0300 Subject: [PATCH 16/23] Add comments --- vm/src/hint_processor/hint_processor_definition.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vm/src/hint_processor/hint_processor_definition.rs b/vm/src/hint_processor/hint_processor_definition.rs index 7834298d02..3cc2b35a44 100644 --- a/vm/src/hint_processor/hint_processor_definition.rs +++ b/vm/src/hint_processor/hint_processor_definition.rs @@ -55,7 +55,7 @@ pub trait HintProcessorLogic { } //Executes the hint which's data is provided by a dynamic structure previously created by compile_hint - + // Can also return a map of hints to be loaded after the current hint is executed fn execute_hint_extensive( &mut self, //Proxy to VM, contains refrences to necessary data @@ -74,6 +74,8 @@ pub trait HintProcessorLogic { } } +// A map of hints that can be used to extend the current map of hints for the vm run +// The map matches the pc at which the hints should be executed to a vec of compiled hints (Outputed by HintProcessor::CompileHint) pub type HintExtension = Box>>>; pub trait HintProcessor: HintProcessorLogic + ResourceTracker {} From f2227bd90c5381d7afbbc04aebda46a02056b4d4 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 14:37:06 -0300 Subject: [PATCH 17/23] Remove old comments from proxy era --- vm/src/hint_processor/hint_processor_definition.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/vm/src/hint_processor/hint_processor_definition.rs b/vm/src/hint_processor/hint_processor_definition.rs index 3cc2b35a44..c40c51cb58 100644 --- a/vm/src/hint_processor/hint_processor_definition.rs +++ b/vm/src/hint_processor/hint_processor_definition.rs @@ -22,11 +22,7 @@ pub trait HintProcessorLogic { //Executes the hint which's data is provided by a dynamic structure previously created by compile_hint fn execute_hint( &mut self, - //Proxy to VM, contains refrences to necessary data - //+ MemoryProxy, which provides the necessary methods to manipulate memory vm: &mut VirtualMachine, - //Proxy to ExecutionScopes, provides the necessary methods to manipulate the scopes and - //access current scope variables exec_scopes: &mut ExecutionScopes, //Data structure that can be downcasted to the structure generated by compile_hint hint_data: &Box, @@ -58,11 +54,7 @@ pub trait HintProcessorLogic { // Can also return a map of hints to be loaded after the current hint is executed fn execute_hint_extensive( &mut self, - //Proxy to VM, contains refrences to necessary data - //+ MemoryProxy, which provides the necessary methods to manipulate memory vm: &mut VirtualMachine, - //Proxy to ExecutionScopes, provides the necessary methods to manipulate the scopes and - //access current scope variables exec_scopes: &mut ExecutionScopes, //Data structure that can be downcasted to the structure generated by compile_hint hint_data: &Box, From 3260f535cb4e7b4d741dfd3cb599f8d3181235f6 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 14:51:34 -0300 Subject: [PATCH 18/23] Revert "Use Box to reduce output size" This reverts commit fc76a36c9129829b774af37c5da928bac16b73c6. --- vm/src/hint_processor/hint_processor_definition.rs | 2 +- vm/src/vm/vm_core.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/src/hint_processor/hint_processor_definition.rs b/vm/src/hint_processor/hint_processor_definition.rs index c40c51cb58..29bae5a5f8 100644 --- a/vm/src/hint_processor/hint_processor_definition.rs +++ b/vm/src/hint_processor/hint_processor_definition.rs @@ -68,7 +68,7 @@ pub trait HintProcessorLogic { // A map of hints that can be used to extend the current map of hints for the vm run // The map matches the pc at which the hints should be executed to a vec of compiled hints (Outputed by HintProcessor::CompileHint) -pub type HintExtension = Box>>>; +pub type HintExtension = HashMap>>; pub trait HintProcessor: HintProcessorLogic + ResourceTracker {} impl HintProcessor for T where T: HintProcessorLogic + ResourceTracker {} diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index d8408afa48..1b00e9c052 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -467,7 +467,7 @@ impl VirtualMachine { .map_err(|err| VirtualMachineError::Hint(Box::new((idx - s, err))))?; // Check if the hint executed adds new hints, and update the hint_ranges & hint_datas accordingly if let Some(hint_extension) = res { - for (hint_pc, hints) in *hint_extension { + for (hint_pc, hints) in hint_extension { if let Ok(len) = NonZeroUsize::try_from(hints.len()) { hint_ranges.insert(hint_pc, (hint_datas.len(), len)); hint_datas.extend(hints); From 380518d37000691d767b54493a5a1543548c862b Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 23 Nov 2023 17:52:20 -0300 Subject: [PATCH 19/23] Simplify output type of execute_hint_extensive` ` --- vm/src/hint_processor/hint_processor_definition.rs | 6 +++--- vm/src/vm/vm_core.rs | 14 ++++++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/vm/src/hint_processor/hint_processor_definition.rs b/vm/src/hint_processor/hint_processor_definition.rs index 29bae5a5f8..11c81e43e5 100644 --- a/vm/src/hint_processor/hint_processor_definition.rs +++ b/vm/src/hint_processor/hint_processor_definition.rs @@ -51,7 +51,7 @@ pub trait HintProcessorLogic { } //Executes the hint which's data is provided by a dynamic structure previously created by compile_hint - // Can also return a map of hints to be loaded after the current hint is executed + // Also returns a map of hints to be loaded after the current hint is executed fn execute_hint_extensive( &mut self, vm: &mut VirtualMachine, @@ -60,9 +60,9 @@ pub trait HintProcessorLogic { hint_data: &Box, //Constant values extracted from the program specification. constants: &HashMap, - ) -> Result, HintError> { + ) -> Result { self.execute_hint(vm, exec_scopes, hint_data, constants)?; - Ok(None) + Ok(HintExtension::default()) } } diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 1b00e9c052..d53118d6cc 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -457,7 +457,7 @@ impl VirtualMachine { let s = *s; // Execute each hint for the given range for idx in s..(s + l.get()) { - let res = hint_processor + let hint_extension = hint_processor .execute_hint_extensive( self, exec_scopes, @@ -465,13 +465,11 @@ impl VirtualMachine { constants, ) .map_err(|err| VirtualMachineError::Hint(Box::new((idx - s, err))))?; - // Check if the hint executed adds new hints, and update the hint_ranges & hint_datas accordingly - if let Some(hint_extension) = res { - for (hint_pc, hints) in hint_extension { - if let Ok(len) = NonZeroUsize::try_from(hints.len()) { - hint_ranges.insert(hint_pc, (hint_datas.len(), len)); - hint_datas.extend(hints); - } + // Update the hint_ranges & hint_datas with the hints added by the executed hint + for (hint_pc, hints) in hint_extension { + if let Ok(len) = NonZeroUsize::try_from(hints.len()) { + hint_ranges.insert(hint_pc, (hint_datas.len(), len)); + hint_datas.extend(hints); } } } From 7cb5ceea67040155f0dbebfd84f5c3709d3c4d5a Mon Sep 17 00:00:00 2001 From: Federica Date: Fri, 24 Nov 2023 18:01:02 -0300 Subject: [PATCH 20/23] Add disclaimers for execute_hint & execute_hint_extensive --- vm/src/hint_processor/hint_processor_definition.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/vm/src/hint_processor/hint_processor_definition.rs b/vm/src/hint_processor/hint_processor_definition.rs index 11c81e43e5..7ab8bd7973 100644 --- a/vm/src/hint_processor/hint_processor_definition.rs +++ b/vm/src/hint_processor/hint_processor_definition.rs @@ -19,7 +19,10 @@ use felt::Felt252; use arbitrary::Arbitrary; pub trait HintProcessorLogic { - //Executes the hint which's data is provided by a dynamic structure previously created by compile_hint + // Executes the hint which's data is provided by a dynamic structure previously created by compile_hint + // Note: The method used by the vm to execute hints is `execute_hint_extensive`. + // The default implementation for `execute_hint_extensive` calls this method, so it can be ignored unless loading hints during the vm run is needed. + // If you chose to implement `execute_hint_extensive` instead of using the default implementation, then this method will not be used. fn execute_hint( &mut self, vm: &mut VirtualMachine, @@ -50,8 +53,10 @@ pub trait HintProcessorLogic { })) } - //Executes the hint which's data is provided by a dynamic structure previously created by compile_hint + // Executes the hint which's data is provided by a dynamic structure previously created by compile_hint // Also returns a map of hints to be loaded after the current hint is executed + // Note: This is the method used by the vm to execute hints, + // if you chose to implement this method instead of using the default implementation, then `execute_hint` will not be used fn execute_hint_extensive( &mut self, vm: &mut VirtualMachine, From 8df1ee4e4314b3354e9c23fe028783ed2fca6807 Mon Sep 17 00:00:00 2001 From: Federica Date: Fri, 24 Nov 2023 18:08:09 -0300 Subject: [PATCH 21/23] Start changelog --- CHANGELOG.md | 7 ++++++- vm/src/vm/vm_core.rs | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df3c48bd60..2edfd7d5b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,16 @@ #### Upcoming Changes +* feat: Add HintProcessor::execute_hint_extensive + refactor hint_ranges [#1491](https://github.com/lambdaclass/cairo-vm/pull/1491) + + * Signature changes: + * `pub fn step_hint(&mut self, hint_executor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, hint_datas: &mut Vec>, constants: &HashMap) -> Result<(), VirtualMachineError>` -> `pub fn step_hint(&mut self, hint_processor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, hint_datas: &mut Vec>, hint_ranges: &mut HashMap, constants: &HashMap) -> Result<(), VirtualMachineError>` + * `pub fn step(&mut self, hint_executor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, hint_data: &[Box], constants: &HashMap) -> Result<(), VirtualMachineError>` -> `pub fn step(&mut self, hint_processor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, hint_datas: &mut Vec>, hint_ranges: &mut HashMap, constants: &HashMap) -> Result<(), VirtualMachineError>` + * feat: add debugging capabilities behind `print` feature flag. [#1476](https://github.com/lambdaclass/cairo-vm/pull/1476) #### [0.9.1] - 2023-11-16 - * chore: bump `cairo-lang-` dependencies to 2.3.1 [#1482](https://github.com/lambdaclass/cairo-vm/pull/1482), [#1483](https://github.com/lambdaclass/cairo-vm/pull/1483) * feat: Make PublicInput fields public [#1474](https://github.com/lambdaclass/cairo-vm/pull/1474) diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index d53118d6cc..0c2c0e5748 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -504,14 +504,14 @@ impl VirtualMachine { pub fn step( &mut self, - hint_executor: &mut dyn HintProcessor, + hint_processor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, hint_datas: &mut Vec>, hint_ranges: &mut HashMap, constants: &HashMap, ) -> Result<(), VirtualMachineError> { self.step_hint( - hint_executor, + hint_processor, exec_scopes, hint_datas, hint_ranges, From 4eab69d18f7331ae8d35a93e3bfcb9d174d92991 Mon Sep 17 00:00:00 2001 From: Federica Date: Fri, 24 Nov 2023 18:14:42 -0300 Subject: [PATCH 22/23] List functionality changes in changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2edfd7d5b5..6b5eb867b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ * feat: Add HintProcessor::execute_hint_extensive + refactor hint_ranges [#1491](https://github.com/lambdaclass/cairo-vm/pull/1491) + * Add trait method `HintProcessorLogic::execute_hint_extensive`: + * This method has a similar behaviour to `HintProcessorLogic::execute_hint` but it also returns a `HintExtension` (type alias for `HashMap>>`) that can be used to extend the current map of hints used by the VM. This behaviour achieves what the `vm_load_data` primitive does for cairo-lang, and is needed to implement os hints. + * This method is now used by the VM to execute hints instead of `execute_hint`, but it's default implementation calls `execute_hint`, so current implementors of the `HintProcessor` trait won't notice any change. + * Signature changes: * `pub fn step_hint(&mut self, hint_executor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, hint_datas: &mut Vec>, constants: &HashMap) -> Result<(), VirtualMachineError>` -> `pub fn step_hint(&mut self, hint_processor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, hint_datas: &mut Vec>, hint_ranges: &mut HashMap, constants: &HashMap) -> Result<(), VirtualMachineError>` * `pub fn step(&mut self, hint_executor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, hint_data: &[Box], constants: &HashMap) -> Result<(), VirtualMachineError>` -> `pub fn step(&mut self, hint_processor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, hint_datas: &mut Vec>, hint_ranges: &mut HashMap, constants: &HashMap) -> Result<(), VirtualMachineError>` From 9c959ecb1b3d767012e30347300cc5da076ac447 Mon Sep 17 00:00:00 2001 From: Federica Date: Fri, 24 Nov 2023 18:21:05 -0300 Subject: [PATCH 23/23] fix names --- vm/src/vm/vm_core.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 0c2c0e5748..4361f4ff38 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -519,10 +519,10 @@ impl VirtualMachine { )?; #[cfg(feature = "hooks")] - self.execute_pre_step_instruction(hint_executor, exec_scopes, hint_datas, constants)?; + self.execute_pre_step_instruction(hint_processor, exec_scopes, hint_datas, constants)?; self.step_instruction()?; #[cfg(feature = "hooks")] - self.execute_post_step_instruction(hint_executor, exec_scopes, hint_datas, constants)?; + self.execute_post_step_instruction(hint_processor, exec_scopes, hint_datas, constants)?; Ok(()) }