From 7f1af063f67f62dc25c900cbbd1a88f3d1c756e8 Mon Sep 17 00:00:00 2001 From: Mario Rugiero Date: Tue, 21 Mar 2023 20:05:59 -0300 Subject: [PATCH] perf: store hints linearly This avoids costly `HashMap` queries --- CHANGELOG.md | 6 + vm/src/serde/deserialize_program.rs | 168 +++++++++++++++++----------- vm/src/types/program.rs | 105 ++++++++++++++++- vm/src/utils.rs | 16 ++- vm/src/vm/hooks.rs | 40 +++---- vm/src/vm/runners/cairo_runner.rs | 63 ++++++----- vm/src/vm/vm_core.rs | 74 ++++++------ 7 files changed, 305 insertions(+), 167 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2542b504f..59c6784623 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ #### Upcoming Changes +* perf: change `Program::shared_program_data::hints` from `HashMap>>` to `Vec>` and refer to them as ranges stored in a `Vec<_>` indexed by PC with run time reductions of up to 12% [#931](https://github.com/lambdaclass/cairo-vm/pull/931) + BREAKING: + * `get_hint_dictionary(&self, &[HintReference], &mut dyn HintProcessor) -> Result>, VirtualMachineError>` -> + `get_hint_data(self, &[HintReference], &mut dyn HintProcessor) -> Result, VirtualMachineError>` + * Hook methods receive `&[Box]` rather than `&HashMap>>` + * chore: update dependencies, particularly lamdaworks 0.1.2 -> 0.1.3 [#1323](https://github.com/lambdaclass/cairo-vm/pull/1323) * fix: fix `UINT256_MUL_DIV_MOD` hint [#1320](https://github.com/lambdaclass/cairo-vm/pull/1320) diff --git a/vm/src/serde/deserialize_program.rs b/vm/src/serde/deserialize_program.rs index 3c4155d9b5..c8fd99aa64 100644 --- a/vm/src/serde/deserialize_program.rs +++ b/vm/src/serde/deserialize_program.rs @@ -418,9 +418,12 @@ pub fn parse_program_json( } } + let (hints, hints_ranges) = Program::flatten_hints(&program_json.hints); + let shared_program_data = SharedProgramData { data: program_json.data, - hints: program_json.hints, + hints, + hints_ranges, main: entrypoint_pc, start, end, @@ -446,6 +449,7 @@ pub fn parse_program_json( mod tests { use super::*; use assert_matches::assert_matches; + use core::num::NonZeroUsize; use felt::felt_str; use num_traits::One; use num_traits::Zero; @@ -616,7 +620,7 @@ mod tests { MaybeRelocatable::Int(Felt252::new(2345108766317314046_i64)), ]; - let mut hints: HashMap> = HashMap::new(); + let mut hints = HashMap::new(); hints.insert( 0, vec![HintParams { @@ -793,6 +797,25 @@ mod tests { ); } + fn get_hints_as_map(program: &Program) -> HashMap> { + let (hints, ranges) = ( + &program.shared_program_data.hints, + &program.shared_program_data.hints_ranges, + ); + let mut hints_map = HashMap::new(); + + for (pc, range) in ranges.iter().enumerate() { + let Some((start, len)) = range else { + continue; + }; + // Associate the PC with its corresponding hints by mapping them + // to the elements in the proper range converted to vec. + hints_map.insert(pc, hints[*start..start + len.get()].to_vec()); + } + + hints_map + } + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn deserialize_program_test() { @@ -812,43 +835,53 @@ mod tests { MaybeRelocatable::Int(Felt252::new(2345108766317314046_i64)), ]; - let mut hints: HashMap> = HashMap::new(); - hints.insert( - 0, - vec![HintParams { - code: "memory[ap] = segments.add()".to_string(), - accessible_scopes: vec![ - String::from("starkware.cairo.common.alloc"), - String::from("starkware.cairo.common.alloc.alloc"), - ], - flow_tracking_data: FlowTrackingData { - ap_tracking: ApTracking { - group: 0, - offset: 0, + let hints: HashMap<_, _> = [ + ( + 0, + vec![HintParams { + code: "memory[ap] = segments.add()".to_string(), + accessible_scopes: vec![ + String::from("starkware.cairo.common.alloc"), + String::from("starkware.cairo.common.alloc.alloc"), + ], + flow_tracking_data: FlowTrackingData { + ap_tracking: ApTracking { + group: 0, + offset: 0, + }, + reference_ids: HashMap::new(), }, - reference_ids: HashMap::new(), - }, - }], - ); - hints.insert( - 46, - vec![HintParams { - code: "import math".to_string(), - accessible_scopes: vec![String::from("__main__"), String::from("__main__.main")], - flow_tracking_data: FlowTrackingData { - ap_tracking: ApTracking { - group: 5, - offset: 0, + }], + ), + ( + 46, + vec![HintParams { + code: "import math".to_string(), + accessible_scopes: vec![ + String::from("__main__"), + String::from("__main__.main"), + ], + flow_tracking_data: FlowTrackingData { + ap_tracking: ApTracking { + group: 5, + offset: 0, + }, + reference_ids: HashMap::new(), }, - reference_ids: HashMap::new(), - }, - }], - ); + }], + ), + ] + .into(); + let mut hints_ranges = vec![None; 47]; + hints_ranges[0] = Some((0, NonZeroUsize::new(1).unwrap())); + hints_ranges[46] = Some((1, NonZeroUsize::new(1).unwrap())); 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.hints, hints); + + let program_hints = get_hints_as_map(&program); + assert_eq!(program_hints, hints); } /// Deserialize a program without an entrypoint. @@ -871,43 +904,50 @@ mod tests { MaybeRelocatable::Int(Felt252::new(2345108766317314046_i64)), ]; - let mut hints: HashMap> = HashMap::new(); - hints.insert( - 0, - vec![HintParams { - code: "memory[ap] = segments.add()".to_string(), - accessible_scopes: vec![ - String::from("starkware.cairo.common.alloc"), - String::from("starkware.cairo.common.alloc.alloc"), - ], - flow_tracking_data: FlowTrackingData { - ap_tracking: ApTracking { - group: 0, - offset: 0, + let hints: HashMap<_, _> = [ + ( + 0, + vec![HintParams { + code: "memory[ap] = segments.add()".to_string(), + accessible_scopes: vec![ + String::from("starkware.cairo.common.alloc"), + String::from("starkware.cairo.common.alloc.alloc"), + ], + flow_tracking_data: FlowTrackingData { + ap_tracking: ApTracking { + group: 0, + offset: 0, + }, + reference_ids: HashMap::new(), }, - reference_ids: HashMap::new(), - }, - }], - ); - hints.insert( - 46, - vec![HintParams { - code: "import math".to_string(), - accessible_scopes: vec![String::from("__main__"), String::from("__main__.main")], - flow_tracking_data: FlowTrackingData { - ap_tracking: ApTracking { - group: 5, - offset: 0, + }], + ), + ( + 46, + vec![HintParams { + code: "import math".to_string(), + accessible_scopes: vec![ + String::from("__main__"), + String::from("__main__.main"), + ], + flow_tracking_data: FlowTrackingData { + ap_tracking: ApTracking { + group: 5, + offset: 0, + }, + reference_ids: HashMap::new(), }, - reference_ids: HashMap::new(), - }, - }], - ); + }], + ), + ] + .into(); 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.hints, hints); + + let program_hints = get_hints_as_map(&program); + assert_eq!(program_hints, hints); } #[test] diff --git a/vm/src/types/program.rs b/vm/src/types/program.rs index 2b0b2b709d..eb679f5dcb 100644 --- a/vm/src/types/program.rs +++ b/vm/src/types/program.rs @@ -14,6 +14,7 @@ use crate::{ }; #[cfg(feature = "cairo-1-hints")] use cairo_lang_starknet::casm_contract_class::CasmContractClass; +use core::num::NonZeroUsize; use felt::{Felt252, PRIME_STR}; #[cfg(feature = "std")] @@ -43,7 +44,8 @@ use std::path::Path; #[derive(Clone, Default, Debug, PartialEq, Eq)] pub(crate) struct SharedProgramData { pub(crate) data: Vec, - pub(crate) hints: HashMap>, + pub(crate) hints: Vec, + pub(crate) hints_ranges: Vec>, pub(crate) main: Option, //start and end labels will only be used in proof-mode pub(crate) start: Option, @@ -83,12 +85,16 @@ impl Program { constants.insert(key.clone(), value); } } + + let (hints, hints_ranges) = Self::flatten_hints(&hints); + let shared_program_data = SharedProgramData { data, - hints, main, start: None, end: None, + hints, + hints_ranges, error_message_attributes, instruction_locations, identifiers, @@ -101,6 +107,33 @@ impl Program { }) } + pub(crate) fn flatten_hints( + hints: &HashMap>, + ) -> (Vec, Vec>) { + let bounds = hints + .iter() + .map(|(pc, hs)| (*pc, hs.len())) + .reduce(|(max_pc, full_len), (pc, len)| (max_pc.max(pc), full_len + len)); + + let Some((max_pc, full_len)) = bounds else { + return (Vec::new(), Vec::new()); + }; + + let mut hints_values = Vec::with_capacity(full_len); + let mut hints_ranges = vec![None; max_pc + 1]; + + 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_values.extend_from_slice(&hs[..]); + } + + (hints_values, hints_ranges) + } + #[cfg(feature = "std")] pub fn from_file(path: &Path, entrypoint: Option<&str>) -> Result { let file_content = std::fs::read(path)?; @@ -267,6 +300,71 @@ mod tests { 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, Vec::new()); + assert_eq!(program.shared_program_data.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_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[s..e].to_vec())) + .collect(); + assert_eq!(program_hints, hints); } #[test] @@ -870,7 +968,8 @@ mod tests { fn default_program() { let shared_program_data = SharedProgramData { data: Vec::new(), - hints: HashMap::new(), + hints: Vec::new(), + hints_ranges: Vec::new(), main: None, start: None, end: None, diff --git a/vm/src/utils.rs b/vm/src/utils.rs index 9d9810fca0..f8fa9ed03d 100644 --- a/vm/src/utils.rs +++ b/vm/src/utils.rs @@ -258,7 +258,8 @@ pub mod test_utils { ( $( $builtin_name: expr ),* ) => {{ let shared_program_data = SharedProgramData { data: crate::stdlib::vec::Vec::new(), - hints: crate::stdlib::collections::HashMap::new(), + hints: crate::stdlib::vec::Vec::new(), + hints_ranges: crate::stdlib::vec::Vec::new(), main: None, start: None, end: None, @@ -342,10 +343,12 @@ pub mod test_utils { impl From for Program { fn from(val: ProgramFlat) -> Self { + let (hints, hints_ranges) = Program::flatten_hints(&val.hints); Program { shared_program_data: Arc::new(SharedProgramData { data: val.data, - hints: val.hints, + hints, + hints_ranges, main: val.main, start: val.start, end: val.end, @@ -920,7 +923,8 @@ mod test { fn program_macro() { let shared_data = SharedProgramData { data: Vec::new(), - hints: HashMap::new(), + hints: Vec::new(), + hints_ranges: Vec::new(), main: None, start: None, end: None, @@ -944,7 +948,8 @@ mod test { fn program_macro_with_builtin() { let shared_data = SharedProgramData { data: Vec::new(), - hints: HashMap::new(), + hints: Vec::new(), + hints_ranges: Vec::new(), main: None, start: None, end: None, @@ -969,7 +974,8 @@ mod test { fn program_macro_custom_definition() { let shared_data = SharedProgramData { data: Vec::new(), - hints: HashMap::new(), + hints: Vec::new(), + hints_ranges: Vec::new(), main: Some(2), start: None, end: None, diff --git a/vm/src/vm/hooks.rs b/vm/src/vm/hooks.rs index b902d8cc2f..b0b6e3c484 100644 --- a/vm/src/vm/hooks.rs +++ b/vm/src/vm/hooks.rs @@ -26,7 +26,7 @@ type BeforeFirstStepHookFunc = Arc< dyn Fn( &mut VirtualMachine, &mut CairoRunner, - &HashMap>>, + &[Box], ) -> Result<(), VirtualMachineError> + Sync + Send, @@ -37,7 +37,7 @@ type StepHookFunc = Arc< &mut VirtualMachine, &mut dyn HintProcessor, &mut ExecutionScopes, - &HashMap>>, + &[Box], &HashMap, ) -> Result<(), VirtualMachineError> + Sync @@ -72,10 +72,10 @@ impl VirtualMachine { pub fn execute_before_first_step( &mut self, runner: &mut CairoRunner, - hint_data_dictionary: &HashMap>>, + hint_data: &[Box], ) -> Result<(), VirtualMachineError> { if let Some(hook_func) = self.hooks.clone().before_first_step { - (hook_func)(self, runner, hint_data_dictionary)?; + (hook_func)(self, runner, hint_data)?; } Ok(()) @@ -85,17 +85,11 @@ impl VirtualMachine { &mut self, hint_executor: &mut dyn HintProcessor, exec_scope: &mut ExecutionScopes, - hint_data_dictionary: &HashMap>>, + hint_data: &[Box], constants: &HashMap, ) -> Result<(), VirtualMachineError> { if let Some(hook_func) = self.hooks.clone().pre_step_instruction { - (hook_func)( - self, - hint_executor, - exec_scope, - hint_data_dictionary, - constants, - )?; + (hook_func)(self, hint_executor, exec_scope, hint_data, constants)?; } Ok(()) @@ -105,17 +99,11 @@ impl VirtualMachine { &mut self, hint_executor: &mut dyn HintProcessor, exec_scope: &mut ExecutionScopes, - hint_data_dictionary: &HashMap>>, + hint_data: &[Box], constants: &HashMap, ) -> Result<(), VirtualMachineError> { if let Some(hook_func) = self.hooks.clone().post_step_instruction { - (hook_func)( - self, - hint_executor, - exec_scope, - hint_data_dictionary, - constants, - )?; + (hook_func)(self, hint_executor, exec_scope, hint_data, constants)?; } Ok(()) @@ -160,7 +148,7 @@ mod tests { fn before_first_step_hook( _vm: &mut VirtualMachine, _runner: &mut CairoRunner, - _hint_data: &HashMap>>, + _hint_data: &[Box], ) -> Result<(), VirtualMachineError> { Err(VirtualMachineError::Unexpected) } @@ -169,7 +157,7 @@ mod tests { _vm: &mut VirtualMachine, _hint_processor: &mut dyn HintProcessor, _exec_scope: &mut ExecutionScopes, - _hint_data: &HashMap>>, + _hint_data: &[Box], _constants: &HashMap, ) -> Result<(), VirtualMachineError> { Err(VirtualMachineError::Unexpected) @@ -179,7 +167,7 @@ mod tests { _vm: &mut VirtualMachine, _hint_processor: &mut dyn HintProcessor, _exec_scope: &mut ExecutionScopes, - _hint_data: &HashMap>>, + _hint_data: &[Box], _constants: &HashMap, ) -> Result<(), VirtualMachineError> { Err(VirtualMachineError::Unexpected) @@ -230,7 +218,7 @@ mod tests { fn before_first_step_hook( _vm: &mut VirtualMachine, _runner: &mut CairoRunner, - _hint_data: &HashMap>>, + _hint_data: &[Box], ) -> Result<(), VirtualMachineError> { Ok(()) } @@ -239,7 +227,7 @@ mod tests { _vm: &mut VirtualMachine, _hint_processor: &mut dyn HintProcessor, _exec_scope: &mut ExecutionScopes, - _hint_data: &HashMap>>, + _hint_data: &[Box], _constants: &HashMap, ) -> Result<(), VirtualMachineError> { Ok(()) @@ -249,7 +237,7 @@ mod tests { _vm: &mut VirtualMachine, _hint_processor: &mut dyn HintProcessor, _exec_scope: &mut ExecutionScopes, - _hint_data: &HashMap>>, + _hint_data: &[Box], _constants: &HashMap, ) -> Result<(), VirtualMachineError> { Ok(()) diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 026cabb719..d0fff4ff45 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -507,29 +507,26 @@ impl CairoRunner { } /// Gets the data used by the HintProcessor to execute each hint - pub fn get_hint_data_dictionary( + pub fn get_hint_data( &self, references: &[HintReference], hint_executor: &mut dyn HintProcessor, - ) -> Result>>, VirtualMachineError> { - let mut hint_data_dictionary = HashMap::>>::new(); - for (hint_index, hints) in self.program.shared_program_data.hints.iter() { - for hint in hints { - let hint_data = hint_executor.compile_hint( - &hint.code, - &hint.flow_tracking_data.ap_tracking, - &hint.flow_tracking_data.reference_ids, - references, - ); - hint_data_dictionary - .entry(*hint_index) - .or_default() - .push(hint_data.map_err(|_| { - VirtualMachineError::CompileHintFail(hint.code.clone().into_boxed_str()) - })?); - } - } - Ok(hint_data_dictionary) + ) -> Result>, VirtualMachineError> { + self.program + .shared_program_data + .hints + .iter() + .map(|hint| { + hint_executor + .compile_hint( + &hint.code, + &hint.flow_tracking_data.ap_tracking, + &hint.flow_tracking_data.reference_ids, + references, + ) + .map_err(|_| VirtualMachineError::CompileHintFail(hint.code.clone().into())) + }) + .collect() } pub fn get_constants(&self) -> &HashMap { @@ -547,16 +544,21 @@ impl CairoRunner { hint_processor: &mut dyn HintProcessor, ) -> Result<(), VirtualMachineError> { let references = &self.program.shared_program_data.reference_manager; - let hint_data_dictionary = self.get_hint_data_dictionary(references, hint_processor)?; - + let hint_data = self.get_hint_data(references, hint_processor)?; #[cfg(feature = "hooks")] - vm.execute_before_first_step(self, &hint_data_dictionary)?; - + vm.execute_before_first_step(self, &hint_data)?; while vm.run_context.pc != address && !hint_processor.consumed() { + let hint_data = self + .program + .shared_program_data + .hints_ranges + .get(vm.run_context.pc.offset) + .and_then(|r| r.and_then(|(s, l)| hint_data.get(s..s + l.get()))) + .unwrap_or(&[]); vm.step( hint_processor, &mut self.exec_scopes, - &hint_data_dictionary, + hint_data, &self.program.constants, )?; hint_processor.consume_step(); @@ -577,17 +579,24 @@ impl CairoRunner { hint_processor: &mut dyn HintProcessor, ) -> Result<(), VirtualMachineError> { let references = &self.program.shared_program_data.reference_manager; - let hint_data_dictionary = self.get_hint_data_dictionary(references, hint_processor)?; + let hint_data = self.get_hint_data(references, hint_processor)?; 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_ranges + .get(vm.run_context.pc.offset) + .and_then(|r| r.and_then(|(s, l)| hint_data.get(s..s + l.get()))) + .unwrap_or(&[]); vm.step( hint_processor, &mut self.exec_scopes, - &hint_data_dictionary, + hint_data, &self.program.constants, )?; } diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index c34244308c..d584fc255d 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -446,15 +446,13 @@ impl VirtualMachine { &mut self, hint_executor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, - hint_data_dictionary: &HashMap>>, + hint_data: &[Box], constants: &HashMap, ) -> Result<(), VirtualMachineError> { - if let Some(hint_list) = hint_data_dictionary.get(&self.run_context.pc.offset) { - for (hint_index, hint_data) in hint_list.iter().enumerate() { - hint_executor - .execute_hint(self, exec_scopes, hint_data, constants) - .map_err(|err| VirtualMachineError::Hint(Box::new((hint_index, err))))? - } + 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(()) } @@ -488,26 +486,16 @@ impl VirtualMachine { &mut self, hint_executor: &mut dyn HintProcessor, exec_scopes: &mut ExecutionScopes, - hint_data_dictionary: &HashMap>>, + hint_data: &[Box], constants: &HashMap, ) -> Result<(), VirtualMachineError> { - self.step_hint(hint_executor, exec_scopes, hint_data_dictionary, constants)?; + self.step_hint(hint_executor, exec_scopes, hint_data, constants)?; #[cfg(feature = "hooks")] - self.execute_pre_step_instruction( - hint_executor, - exec_scopes, - hint_data_dictionary, - constants, - )?; + self.execute_pre_step_instruction(hint_executor, exec_scopes, hint_data, constants)?; self.step_instruction()?; #[cfg(feature = "hooks")] - self.execute_post_step_instruction( - hint_executor, - exec_scopes, - hint_data_dictionary, - constants, - )?; + self.execute_post_step_instruction(hint_executor, exec_scopes, hint_data, constants)?; Ok(()) } @@ -2662,7 +2650,7 @@ mod tests { vm.step( &mut hint_processor, exec_scopes_ref!(), - &HashMap::new(), + &Vec::new(), &HashMap::new(), ), Ok(()) @@ -2891,8 +2879,8 @@ mod tests { vm.step( &mut hint_processor, exec_scopes_ref!(), - &HashMap::new(), - &HashMap::new(), + &Vec::new(), + &HashMap::new() ), Ok(()) ); @@ -2973,8 +2961,8 @@ mod tests { vm.step( &mut hint_processor, exec_scopes_ref!(), - &HashMap::new(), - &HashMap::new(), + &Vec::new(), + &HashMap::new() ), Ok(()) ); @@ -3069,8 +3057,8 @@ mod tests { vm.step( &mut hint_processor, exec_scopes_ref!(), - &HashMap::new(), - &HashMap::new(), + &Vec::new(), + &HashMap::new() ), Ok(()) ); @@ -3090,8 +3078,8 @@ mod tests { vm.step( &mut hint_processor, exec_scopes_ref!(), - &HashMap::new(), - &HashMap::new(), + &Vec::new(), + &HashMap::new() ), Ok(()) ); @@ -3112,8 +3100,8 @@ mod tests { vm.step( &mut hint_processor, exec_scopes_ref!(), - &HashMap::new(), - &HashMap::new(), + &Vec::new(), + &HashMap::new() ), Ok(()) ); @@ -3632,13 +3620,10 @@ 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_dictionary = HashMap::from([( - 0_usize, - vec![any_box!(HintProcessorData::new_default( - "memory[ap] = segments.add()".to_string(), - HashMap::new(), - ))], - )]); + let hint_data = vec![any_box!(HintProcessorData::new_default( + "memory[ap] = segments.add()".to_string(), + HashMap::new(), + ))]; //Initialzie registers run_context!(vm, 3, 2, 2); @@ -3673,12 +3658,17 @@ 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!(), - &hint_data_dictionary, - &HashMap::new(), + hint_data, + &HashMap::new() ), Ok(()) ); @@ -4217,7 +4207,7 @@ mod tests { fn before_first_step_hook( _vm: &mut VirtualMachine, _runner: &mut CairoRunner, - _hint_data: &HashMap>>, + _hint_data: &[Box], ) -> Result<(), VirtualMachineError> { Err(VirtualMachineError::Unexpected) }