diff --git a/CHANGELOG.md b/CHANGELOG.md index e6e11d7e2d..a6cc1ead78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ #### Upcoming Changes +* Refactor `Program` to optimize `Program::clone` [#999](https://github.com/lambdaclass/cairo-rs/pull/999) + * Breaking change: many fields that were (unnecessarily) public become hidden by the refactor. + * Add missing `\n` character in traceback string [#997](https://github.com/lambdaclass/cairo-rs/pull/997) * BugFix: Add missing `\n` character after traceback lines when the filename is missing ("Unknown Location") diff --git a/src/serde/deserialize_program.rs b/src/serde/deserialize_program.rs index 51d8d69829..95b3204d96 100644 --- a/src/serde/deserialize_program.rs +++ b/src/serde/deserialize_program.rs @@ -1,9 +1,11 @@ -use crate::stdlib::{collections::HashMap, fmt, prelude::*}; +use crate::stdlib::{collections::HashMap, fmt, prelude::*, sync::Arc}; use crate::{ serde::deserialize_utils, types::{ - errors::program_errors::ProgramError, instruction::Register, program::Program, + errors::program_errors::ProgramError, + instruction::Register, + program::{Program, SharedProgramData}, relocatable::MaybeRelocatable, }, vm::runners::builtin_runner::{ @@ -373,10 +375,24 @@ pub fn parse_program_json( None => None, }; - Ok(Program { + let shared_program_data = SharedProgramData { builtins: program_json.builtins, - prime: PRIME_STR.to_string(), data: program_json.data, + hints: program_json.hints, + main: entrypoint_pc, + start, + end, + error_message_attributes: program_json + .attributes + .into_iter() + .filter(|attr| attr.name == "error_message") + .collect(), + instruction_locations: program_json + .debug_info + .map(|debug_info| debug_info.instruction_locations), + }; + Ok(Program { + shared_program_data: Arc::new(shared_program_data), constants: { let mut constants = HashMap::new(); for (key, value) in program_json.identifiers.iter() { @@ -391,20 +407,8 @@ pub fn parse_program_json( constants }, - main: entrypoint_pc, - start, - end, - hints: program_json.hints, reference_manager: program_json.reference_manager, identifiers: program_json.identifiers, - error_message_attributes: program_json - .attributes - .into_iter() - .filter(|attr| attr.name == "error_message") - .collect(), - instruction_locations: program_json - .debug_info - .map(|debug_info| debug_info.instruction_locations), }) } @@ -805,14 +809,10 @@ mod tests { }], ); - assert_eq!( - program.prime, - "0x800000000000011000000000000000000000000000000000000000000000001".to_string() - ); - assert_eq!(program.builtins, builtins); - assert_eq!(program.data, data); - assert_eq!(program.main, Some(0)); - assert_eq!(program.hints, hints); + assert_eq!(program.shared_program_data.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); } /// Deserialize a program without an entrypoint. @@ -867,14 +867,10 @@ mod tests { }], ); - assert_eq!( - program.prime, - "0x800000000000011000000000000000000000000000000000000000000000001".to_string() - ); - assert_eq!(program.builtins, builtins); - assert_eq!(program.data, data); - assert_eq!(program.main, None); - assert_eq!(program.hints, hints); + assert_eq!(program.shared_program_data.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); } #[test] diff --git a/src/types/program.rs b/src/types/program.rs index 75b9f3de0e..0106c9d43a 100644 --- a/src/types/program.rs +++ b/src/types/program.rs @@ -1,4 +1,4 @@ -use crate::stdlib::{collections::HashMap, prelude::*}; +use crate::stdlib::{collections::HashMap, prelude::*, sync::Arc}; use crate::{ serde::deserialize_program::{ @@ -8,33 +8,56 @@ use crate::{ types::{errors::program_errors::ProgramError, relocatable::MaybeRelocatable}, }; use felt::{Felt252, PRIME_STR}; -use serde::{Deserialize, Serialize}; #[cfg(feature = "std")] use std::path::Path; -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct Program { +// 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 +// a `CairoRunner` becomes a bottleneck, but the following solutions were tried and +// discarded: +// - Store only a reference in `CairoRunner` rather than cloning; this doesn't work +// because then we need to introduce explicit lifetimes, which broke `cairo-rs-py` +// since PyO3 doesn't support Python objects containing structures with lifetimes. +// - Directly pass an `Arc` to `CairoRunner::new()` and simply copy that: +// there was a prohibitive performance hit of 10-15% when doing so, most likely +// either because of branch mispredictions or the extra level of indirection going +// through a random location on the heap rather than the likely-to-be-cached spot +// on the stack. +// +// So, the compromise was to identify which data was less used and avoid copying that, +// using `Arc<_>`, while the most accessed fields remain on the stack for the main +// loop to access. The fields in `SharedProgramData` are either preprocessed and +// copied explicitly (_in addition_ to the clone of `Program`) or are used only in +// exceptional circumstances, such as when reconstructing a backtrace on execution +// failures. +// Fields in `Program` (other than `SharedProgramData` itself) are used by the main logic. +#[derive(Clone, Default, Debug, PartialEq, Eq)] +pub(crate) struct SharedProgramData { pub builtins: Vec, - pub prime: String, pub data: Vec, - pub constants: HashMap, + pub hints: HashMap>, pub main: Option, //start and end labels will only be used in proof-mode pub start: Option, pub end: Option, - pub hints: HashMap>, - pub reference_manager: ReferenceManager, - pub identifiers: HashMap, pub error_message_attributes: Vec, pub instruction_locations: Option>, } +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Program { + pub(crate) shared_program_data: Arc, + pub constants: HashMap, + pub reference_manager: ReferenceManager, + pub identifiers: HashMap, +} + impl Program { #[allow(clippy::too_many_arguments)] pub fn new( builtins: Vec, - prime: String, data: Vec, main: Option, hints: HashMap>, @@ -43,10 +66,18 @@ impl Program { error_message_attributes: Vec, instruction_locations: Option>, ) -> Result { - Ok(Self { + let shared_program_data = SharedProgramData { builtins, - prime, data, + hints, + main, + start: None, + end: None, + error_message_attributes, + instruction_locations, + }; + Ok(Self { + shared_program_data: Arc::new(shared_program_data), constants: { let mut constants = HashMap::new(); for (key, value) in identifiers.iter() { @@ -61,14 +92,8 @@ impl Program { constants }, - main, - start: None, - end: None, - hints, reference_manager, identifiers, - error_message_attributes, - instruction_locations, }) } @@ -81,25 +106,21 @@ impl Program { pub fn from_bytes(bytes: &[u8], entrypoint: Option<&str>) -> Result { deserialize_and_parse_program(bytes, entrypoint) } + + pub fn primer() -> &'static str { + PRIME_STR + } } impl Default for Program { fn default() -> Self { - Program { - builtins: Vec::new(), - prime: PRIME_STR.to_string(), - data: Vec::new(), + Self { + shared_program_data: Arc::new(SharedProgramData::default()), constants: HashMap::new(), - main: None, - start: None, - end: None, - hints: HashMap::new(), reference_manager: ReferenceManager { references: Vec::new(), }, identifiers: HashMap::new(), - error_message_attributes: Vec::new(), - instruction_locations: None, } } } @@ -133,7 +154,6 @@ mod tests { let program = Program::new( builtins.clone(), - felt::PRIME_STR.to_string(), data.clone(), None, HashMap::new(), @@ -144,9 +164,9 @@ mod tests { ) .unwrap(); - assert_eq!(program.builtins, builtins); - assert_eq!(program.data, data); - assert_eq!(program.main, None); + assert_eq!(program.shared_program_data.builtins, builtins); + assert_eq!(program.shared_program_data.data, data); + assert_eq!(program.shared_program_data.main, None); assert_eq!(program.identifiers, HashMap::new()); } @@ -196,7 +216,6 @@ mod tests { let program = Program::new( builtins.clone(), - felt::PRIME_STR.to_string(), data.clone(), None, HashMap::new(), @@ -207,9 +226,9 @@ mod tests { ) .unwrap(); - assert_eq!(program.builtins, builtins); - assert_eq!(program.data, data); - assert_eq!(program.main, None); + assert_eq!(program.shared_program_data.builtins, builtins); + assert_eq!(program.shared_program_data.data, data); + assert_eq!(program.shared_program_data.main, None); assert_eq!(program.identifiers, identifiers); assert_eq!( program.constants, @@ -266,7 +285,6 @@ mod tests { let program = Program::new( builtins, - felt::PRIME_STR.to_string(), data, None, HashMap::new(), @@ -356,10 +374,9 @@ mod tests { }, ); - assert_eq!(program.prime, PRIME_STR.to_string()); - assert_eq!(program.builtins, builtins); - assert_eq!(program.data, data); - assert_eq!(program.main, Some(0)); + assert_eq!(program.shared_program_data.builtins, builtins); + assert_eq!(program.shared_program_data.data, data); + assert_eq!(program.shared_program_data.main, Some(0)); assert_eq!(program.identifiers, identifiers); } @@ -456,12 +473,14 @@ mod tests { }, ); - assert_eq!(program.prime, PRIME_STR.to_string()); - assert_eq!(program.builtins, builtins); - assert_eq!(program.data, data); - assert_eq!(program.main, None); + assert_eq!(program.shared_program_data.builtins, builtins); + assert_eq!(program.shared_program_data.data, data); + assert_eq!(program.shared_program_data.main, None); assert_eq!(program.identifiers, identifiers); - assert_eq!(program.error_message_attributes, error_message_attributes) + assert_eq!( + program.shared_program_data.error_message_attributes, + error_message_attributes + ) } #[test] @@ -506,23 +525,25 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn default_program() { - let program = Program { + let shared_program_data = SharedProgramData { builtins: Vec::new(), - prime: PRIME_STR.to_string(), data: Vec::new(), - constants: HashMap::new(), + hints: HashMap::new(), main: None, start: None, end: None, - hints: HashMap::new(), + error_message_attributes: Vec::new(), + instruction_locations: None, + }; + let program = Program { + shared_program_data: Arc::new(shared_program_data), + constants: HashMap::new(), reference_manager: ReferenceManager { references: Vec::new(), }, identifiers: HashMap::new(), - error_message_attributes: Vec::new(), - instruction_locations: None, }; - assert_eq!(program, Program::default()) + assert_eq!(program, Program::default()); } } diff --git a/src/utils.rs b/src/utils.rs index 5df7791258..574b34959e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -236,39 +236,72 @@ pub mod test_utils { } pub(crate) use cairo_runner; + pub(crate) use crate::stdlib::sync::Arc; + pub(crate) use crate::types::program::Program; + pub(crate) use crate::types::program::SharedProgramData; macro_rules! program { //Empty program () => { Program::default() }; //Program with builtins - ( $( $builtin_name: expr ),* ) => { - Program { + ( $( $builtin_name: expr ),* ) => {{ + let shared_program_data = SharedProgramData { builtins: vec![$( $builtin_name ),*], - prime: "0x800000000000011000000000000000000000000000000000000000000000001".to_string(), data: crate::stdlib::vec::Vec::new(), - constants: crate::stdlib::collections::HashMap::new(), + hints: crate::stdlib::collections::HashMap::new(), main: None, start: None, end: None, - hints: crate::stdlib::collections::HashMap::new(), + error_message_attributes: crate::stdlib::vec::Vec::new(), + instruction_locations: None, + }; + Program { + shared_program_data: Arc::new(shared_program_data), + constants: crate::stdlib::collections::HashMap::new(), reference_manager: ReferenceManager { references: crate::stdlib::vec::Vec::new(), }, identifiers: crate::stdlib::collections::HashMap::new(), - error_message_attributes: crate::stdlib::vec::Vec::new(), - instruction_locations: None, } - }; + }}; // Custom program definition - ($($field:ident = $value:expr),* $(,)?) => { + ($(constants = $value:expr),* $(,)?) => { + Program { + $( + constants: $value, + )* + ..Default::default() + } + }; + ($(refence_manager = $value:expr),* $(,)?) => { Program { + $( + reference_manager: $value, + )* + ..Default::default() + } + }; + ($(identifiers = $value:expr),* $(,)?) => { + Program { + $( + identifiers: $value, + )* + ..Default::default() + } + }; + ($($field:ident = $value:expr),* $(,)?) => {{ + let shared_data = SharedProgramData { $( $field: $value, )* ..Default::default() + }; + Program { + shared_program_data: Arc::new(shared_data), + ..Default::default() } - } + }}; } pub(crate) use program; @@ -841,44 +874,47 @@ mod test { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn program_macro() { - let program = Program { + let shared_data = SharedProgramData { builtins: Vec::new(), - prime: "0x800000000000011000000000000000000000000000000000000000000000001".to_string(), data: Vec::new(), - constants: HashMap::new(), + hints: HashMap::new(), main: None, start: None, end: None, - hints: HashMap::new(), + error_message_attributes: Vec::new(), + instruction_locations: None, + }; + let program = Program { + shared_program_data: Arc::new(shared_data), + constants: HashMap::new(), reference_manager: ReferenceManager { references: Vec::new(), }, identifiers: HashMap::new(), - error_message_attributes: Vec::new(), - instruction_locations: None, }; - assert_eq!(program, program!()) } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn program_macro_with_builtin() { - let program = Program { + let shared_data = SharedProgramData { builtins: vec![BuiltinName::range_check], - prime: "0x800000000000011000000000000000000000000000000000000000000000001".to_string(), data: Vec::new(), - constants: HashMap::new(), + hints: HashMap::new(), main: None, start: None, end: None, - hints: HashMap::new(), + error_message_attributes: Vec::new(), + instruction_locations: None, + }; + let program = Program { + shared_program_data: Arc::new(shared_data), + constants: HashMap::new(), reference_manager: ReferenceManager { references: Vec::new(), }, identifiers: HashMap::new(), - error_message_attributes: Vec::new(), - instruction_locations: None, }; assert_eq!(program, program![BuiltinName::range_check]) @@ -887,21 +923,23 @@ mod test { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn program_macro_custom_definition() { - let program = Program { + let shared_data = SharedProgramData { builtins: vec![BuiltinName::range_check], - prime: "0x800000000000011000000000000000000000000000000000000000000000001".to_string(), data: Vec::new(), - constants: HashMap::new(), + hints: HashMap::new(), main: Some(2), start: None, end: None, - hints: HashMap::new(), + error_message_attributes: Vec::new(), + instruction_locations: None, + }; + let program = Program { + shared_program_data: Arc::new(shared_data), + constants: HashMap::new(), reference_manager: ReferenceManager { references: Vec::new(), }, identifiers: HashMap::new(), - error_message_attributes: Vec::new(), - instruction_locations: None, }; assert_eq!( diff --git a/src/vm/errors/vm_exception.rs b/src/vm/errors/vm_exception.rs index a3a67aefa8..1949d19460 100644 --- a/src/vm/errors/vm_exception.rs +++ b/src/vm/errors/vm_exception.rs @@ -58,7 +58,7 @@ pub fn get_error_attr_value( vm: &VirtualMachine, ) -> Option { let mut errors = String::new(); - for attribute in &runner.program.error_message_attributes { + for attribute in &runner.program.shared_program_data.error_message_attributes { if attribute.start_pc <= pc && attribute.end_pc > pc { errors.push_str(&format!( "Error message: {}\n", @@ -78,7 +78,12 @@ pub fn get_location( runner: &CairoRunner, hint_index: Option, ) -> Option { - let instruction_location = runner.program.instruction_locations.as_ref()?.get(&pc)?; + let instruction_location = runner + .program + .shared_program_data + .instruction_locations + .as_ref()? + .get(&pc)?; if let Some(index) = hint_index { instruction_location .hints @@ -931,7 +936,7 @@ cairo_programs/bad_programs/bad_usort.cairo:64:5: (pc=0:60) // This reference should be rejected when substituting the error attribute references let runner = cairo_runner!(program); let vm = vm!(); - let attribute = &program.error_message_attributes[0]; + let attribute = &program.shared_program_data.error_message_attributes[0]; assert_eq!( substitute_error_message_references(attribute, &runner, &vm), format!( @@ -972,7 +977,7 @@ cairo_programs/bad_programs/bad_usort.cairo:64:5: (pc=0:60) // This reference should be rejected when substituting the error attribute references let runner = cairo_runner!(program); let vm = vm!(); - let attribute = &program.error_message_attributes[0]; + let attribute = &program.shared_program_data.error_message_attributes[0]; assert_eq!( substitute_error_message_references(attribute, &runner, &vm), format!( diff --git a/src/vm/runners/cairo_runner.rs b/src/vm/runners/cairo_runner.rs index 40769b912b..eb0b9c5eb0 100644 --- a/src/vm/runners/cairo_runner.rs +++ b/src/vm/runners/cairo_runner.rs @@ -79,6 +79,7 @@ pub struct CairoRunner { final_pc: Option, pub program_base: Option, execution_base: Option, + entrypoint: Option, initial_ap: Option, initial_fp: Option, initial_pc: Option, @@ -115,6 +116,7 @@ impl CairoRunner { final_pc: None, program_base: None, execution_base: None, + entrypoint: program.shared_program_data.main, initial_ap: None, initial_fp: None, initial_pc: None, @@ -147,10 +149,14 @@ impl CairoRunner { BuiltinName::keccak, BuiltinName::poseidon, ]; - if !is_subsequence(&self.program.builtins, &builtin_ordered_list) { + if !is_subsequence( + &self.program.shared_program_data.builtins, + &builtin_ordered_list, + ) { return Err(RunnerError::DisorderedBuiltins); }; - let mut program_builtins: HashSet<&BuiltinName> = self.program.builtins.iter().collect(); + let mut program_builtins: HashSet<&BuiltinName> = + self.program.shared_program_data.builtins.iter().collect(); let mut builtin_runners = Vec::::new(); if self.layout.builtins.output { @@ -275,11 +281,16 @@ impl CairoRunner { } } - for builtin_name in &self.program.builtins { + for builtin_name in &self.program.shared_program_data.builtins { initialize_builtin(*builtin_name, vm); } for builtin_name in starknet_preset_builtins { - if !self.program.builtins.contains(&builtin_name) { + if !self + .program + .shared_program_data + .builtins + .contains(&builtin_name) + { initialize_builtin(builtin_name, vm) } } @@ -319,14 +330,14 @@ impl CairoRunner { }; self.initial_pc = Some(initial_pc); vm.segments - .load_data(prog_base, &self.program.data) + .load_data(prog_base, &self.program.shared_program_data.data) .map_err(RunnerError::MemoryInitializationError)?; // Mark all addresses from the program segment as accessed let base = self .program_base .unwrap_or_else(|| Relocatable::from((0, 0))); - for i in 0..self.program.data.len() { + for i in 0..self.program.shared_program_data.data.len() { vm.segments.memory.mark_as_accessed((base + i)?); } } @@ -393,7 +404,10 @@ impl CairoRunner { self.execution_public_memory = Some(Vec::from_iter(0..stack_prefix.len())); self.initialize_state( vm, - self.program.start.ok_or(RunnerError::NoProgramStart)?, + self.program + .shared_program_data + .start + .ok_or(RunnerError::NoProgramStart)?, stack_prefix, )?; self.initial_fp = Some( @@ -404,10 +418,14 @@ impl CairoRunner { ); self.initial_ap = self.initial_fp; return Ok(self.program_base.as_ref().ok_or(RunnerError::NoProgBase)? - + self.program.end.ok_or(RunnerError::NoProgramEnd)?); + + self + .program + .shared_program_data + .end + .ok_or(RunnerError::NoProgramEnd)?); } let return_fp = vm.segments.add(); - if let Some(main) = &self.program.main { + if let Some(main) = &self.entrypoint { let main_clone = *main; Ok(self.initialize_function_entrypoint( vm, @@ -473,7 +491,7 @@ impl CairoRunner { hint_executor: &mut dyn HintProcessor, ) -> Result>>, VirtualMachineError> { let mut hint_data_dictionary = HashMap::>>::new(); - for (hint_index, hints) in self.program.hints.iter() { + 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, @@ -495,7 +513,7 @@ impl CairoRunner { } pub fn get_program_builtins(&self) -> &Vec { - &self.program.builtins + &self.program.shared_program_data.builtins } pub fn run_until_pc( @@ -822,7 +840,7 @@ impl CairoRunner { if !self.run_ended { return Err(RunnerError::FinalizeNoEndRun); } - let size = self.program.data.len(); + let size = self.program.shared_program_data.data.len(); let mut public_memory = Vec::with_capacity(size); for i in 0..size { public_memory.push((i, 0_usize)) @@ -965,7 +983,7 @@ impl CairoRunner { /// is specified. pub fn set_entrypoint(&mut self, new_entrypoint: Option<&str>) -> Result<(), ProgramError> { let new_entrypoint = new_entrypoint.unwrap_or("main"); - self.program.main = Some( + self.entrypoint = Some( self.program .identifiers .get(&format!("__main__.{new_entrypoint}")) @@ -3532,7 +3550,8 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn finalize_segments_run_ended_not_emptyproof_mode_empty_execution_public_memory() { let mut program = program!(); - program.data = vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; + Arc::get_mut(&mut program.shared_program_data).unwrap().data = + vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; //Program data len = 8 let mut cairo_runner = cairo_runner!(program, "plain", true); cairo_runner.program_base = Some(Relocatable::from((0, 0))); @@ -3565,7 +3584,8 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn finalize_segments_run_ended_not_emptyproof_mode_with_execution_public_memory() { let mut program = program!(); - program.data = vec_data![(1), (2), (3), (4)]; + Arc::get_mut(&mut program.shared_program_data).unwrap().data = + vec_data![(1), (2), (3), (4)]; //Program data len = 4 let mut cairo_runner = cairo_runner!(program, "plain", true); cairo_runner.program_base = Some(Relocatable::from((0, 0))); @@ -4131,7 +4151,10 @@ mod tests { ); let runner = cairo_runner!(program); - assert_eq!(&program.builtins, runner.get_program_builtins()); + assert_eq!( + &program.shared_program_data.builtins, + runner.get_program_builtins() + ); } #[test] @@ -4158,7 +4181,7 @@ mod tests { cairo_runner .set_entrypoint(None) .expect("Call to `set_entrypoint()` failed."); - assert_eq!(cairo_runner.program.main, Some(0)); + assert_eq!(cairo_runner.entrypoint, Some(0)); } #[test] @@ -4198,7 +4221,7 @@ mod tests { cairo_runner .set_entrypoint(Some("alternate_main")) .expect("Call to `set_entrypoint()` failed."); - assert_eq!(cairo_runner.program.main, Some(1)); + assert_eq!(cairo_runner.entrypoint, Some(1)); } /// Test that set_entrypoint() fails when the entrypoint doesn't exist. @@ -4226,14 +4249,15 @@ mod tests { cairo_runner .set_entrypoint(Some("nonexistent_main")) .expect_err("Call to `set_entrypoint()` succeeded (should've failed)."); - assert_eq!(cairo_runner.program.main, None); + assert_eq!(cairo_runner.entrypoint, None); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn read_return_values_test() { let mut program = program!(); - program.data = vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; + Arc::get_mut(&mut program.shared_program_data).unwrap().data = + vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; //Program data len = 8 let mut cairo_runner = cairo_runner!(program, "plain", true); cairo_runner.program_base = Some(Relocatable::from((0, 0))); @@ -4256,7 +4280,8 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn read_return_values_test_with_run_not_ended() { let mut program = program!(); - program.data = vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; + Arc::get_mut(&mut program.shared_program_data).unwrap().data = + vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; //Program data len = 8 let mut cairo_runner = cairo_runner!(program, "plain", true); cairo_runner.program_base = Some(Relocatable::from((0, 0))); @@ -4273,7 +4298,8 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn read_return_values_test_with_segments_finalized() { let mut program = program!(); - program.data = vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; + Arc::get_mut(&mut program.shared_program_data).unwrap().data = + vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; //Program data len = 8 let mut cairo_runner = cairo_runner!(program, "plain", true); cairo_runner.program_base = Some(Relocatable::from((0, 0))); @@ -4291,7 +4317,8 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn read_return_values_updates_builtin_stop_ptr_one_builtin_empty() { let mut program = program![BuiltinName::output]; - program.data = vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; + Arc::get_mut(&mut program.shared_program_data).unwrap().data = + vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; //Program data len = 8 let mut cairo_runner = cairo_runner!(program, "all_cairo", true); cairo_runner.program_base = Some(Relocatable::from((0, 0))); @@ -4321,7 +4348,8 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn read_return_values_updates_builtin_stop_ptr_one_builtin_one_element() { let mut program = program![BuiltinName::output]; - program.data = vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; + Arc::get_mut(&mut program.shared_program_data).unwrap().data = + vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; //Program data len = 8 let mut cairo_runner = cairo_runner!(program, "all_cairo", true); cairo_runner.program_base = Some(Relocatable::from((0, 0))); @@ -4351,7 +4379,8 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn read_return_values_updates_builtin_stop_ptr_two_builtins() { let mut program = program![BuiltinName::output, BuiltinName::bitwise]; - program.data = vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; + Arc::get_mut(&mut program.shared_program_data).unwrap().data = + vec_data![(1), (2), (3), (4), (5), (6), (7), (8)]; //Program data len = 8 let mut cairo_runner = cairo_runner!(program, "all_cairo", true); cairo_runner.program_base = Some(Relocatable::from((0, 0))); diff --git a/src/vm/security.rs b/src/vm/security.rs index d5c0c9107c..29b38371e6 100644 --- a/src/vm/security.rs +++ b/src/vm/security.rs @@ -48,7 +48,8 @@ pub fn verify_secure_runner( .program_base .and_then(|rel| rel.segment_index.to_usize()) .ok_or(RunnerError::NoProgBase)?; - let program_segment_size = program_segment_size.unwrap_or(runner.program.data.len()); + let program_segment_size = + program_segment_size.unwrap_or(runner.program.shared_program_data.data.len()); let program_length = vm .segments .memory