From bcee2c1ee724c5ab90e025eb53c6cc8f19b55fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Wed, 15 Oct 2025 15:50:40 -0300 Subject: [PATCH 01/21] Use CairoRunnerBuilder for cairo_run, but as a placeholder --- cairo1-run/src/cairo_run.rs | 10 ++++++---- vm/src/vm/runners/cairo_runner.rs | 6 ++++++ vm/src/vm/vm_core.rs | 9 ++++++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/cairo1-run/src/cairo_run.rs b/cairo1-run/src/cairo_run.rs index fbe0760d94..063cf2e01b 100644 --- a/cairo1-run/src/cairo_run.rs +++ b/cairo1-run/src/cairo_run.rs @@ -44,7 +44,7 @@ use cairo_vm::{ }, vm::{ errors::{runner_errors::RunnerError, vm_errors::VirtualMachineError}, - runners::cairo_runner::{CairoRunner, RunResources, RunnerMode}, + runners::cairo_runner::{CairoRunner, CairoRunnerBuilder, RunResources, RunnerMode}, vm_core::VirtualMachine, }, Felt252, @@ -250,14 +250,16 @@ pub fn cairo_run_program( RunnerMode::ExecutionMode }; - let mut runner = CairoRunner::new_v2( + let mut runner_builder = CairoRunnerBuilder::new( &program, cairo_run_config.layout, cairo_run_config.dynamic_layout_params.clone(), runner_mode, - cairo_run_config.trace_enabled, - false, )?; + runner_builder.enable_trace(cairo_run_config.trace_enabled); + + let mut runner = runner_builder.build()?; + let end = runner.initialize(cairo_run_config.proof_mode)?; load_arguments(&mut runner, &cairo_run_config, main_func)?; diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 248f354289..3ca7a757df 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -524,6 +524,12 @@ impl CairoRunnerBuilder { .builtin_runners(self.builtin_runners) .segments(self.memory) .instruction_cache(self.instructions) + .disable_trace_padding(self.disable_trace_padding) + .trace(if self.enable_trace { + Some(Vec::::new()) + } else { + None + }) .build(); Ok(CairoRunner { diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index cee428153a..1a165978e3 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -1363,6 +1363,7 @@ pub struct VirtualMachineBuilder { instruction_cache: Vec>, skip_instruction_execution: bool, run_finished: bool, + disable_trace_padding: bool, #[cfg(feature = "test_utils")] pub(crate) hooks: crate::vm::hooks::Hooks, } @@ -1386,6 +1387,7 @@ impl Default for VirtualMachineBuilder { #[cfg(feature = "test_utils")] hooks: Default::default(), instruction_cache: Vec::new(), + disable_trace_padding: false, } } } @@ -1411,6 +1413,11 @@ impl VirtualMachineBuilder { self } + pub fn disable_trace_padding(mut self, value: bool) -> VirtualMachineBuilder { + self.disable_trace_padding = value; + self + } + pub fn current_step(mut self, current_step: usize) -> VirtualMachineBuilder { self.current_step = current_step; self @@ -1458,7 +1465,7 @@ impl VirtualMachineBuilder { #[cfg(feature = "test_utils")] hooks: self.hooks, relocation_table: None, - disable_trace_padding: false, + disable_trace_padding: self.disable_trace_padding, } } } From 9558d3d39521316045a3f1c6497b1474a01b6cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Wed, 15 Oct 2025 16:23:13 -0300 Subject: [PATCH 02/21] Initialize full runner in builder --- cairo1-run/src/cairo_run.rs | 9 +- vm/src/vm/runners/cairo_runner.rs | 200 ++++++++++++++++++++++++++++-- 2 files changed, 197 insertions(+), 12 deletions(-) diff --git a/cairo1-run/src/cairo_run.rs b/cairo1-run/src/cairo_run.rs index 063cf2e01b..262d0762f5 100644 --- a/cairo1-run/src/cairo_run.rs +++ b/cairo1-run/src/cairo_run.rs @@ -257,10 +257,17 @@ pub fn cairo_run_program( runner_mode, )?; runner_builder.enable_trace(cairo_run_config.trace_enabled); + runner_builder.allow_missing_builtins(cairo_run_config.proof_mode); + runner_builder.initialize_builtin_runners_for_layout()?; + runner_builder.initialize_base_segments(); + runner_builder.load_program()?; + runner_builder.initialize_builtin_segments(); + runner_builder.initialize_builtin_zero_segments(); + let end = runner_builder.initialize_main_entrypoint()?; + runner_builder.initialize_validation_rules()?; let mut runner = runner_builder.build()?; - let end = runner.initialize(cairo_run_config.proof_mode)?; load_arguments(&mut runner, &cairo_run_config, main_func)?; // Run it until the end / infinite loop in proof_mode diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 3ca7a757df..5a88354ebc 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -170,6 +170,12 @@ pub struct CairoRunnerBuilder { program_base: Option, execution_base: Option, memory: MemorySegmentManager, + // Set after initializing entrypoint. + initial_pc: Option, + initial_fp: Option, + initial_ap: Option, + final_pc: Option, + execution_public_memory: Option>, // Set after loading program. loaded_program: bool, // Set after compiling hints. @@ -215,7 +221,7 @@ impl CairoRunnerBuilder { enable_trace: false, disable_trace_padding: false, allow_missing_builtins: false, - runner_mode, + runner_mode: runner_mode.clone(), builtin_runners: Vec::new(), program_base: None, execution_base: None, @@ -223,6 +229,15 @@ impl CairoRunnerBuilder { loaded_program: false, hints: None, instructions: Vec::new(), + initial_pc: None, + initial_fp: None, + initial_ap: None, + final_pc: None, + execution_public_memory: if runner_mode != RunnerMode::ExecutionMode { + Some(Vec::new()) + } else { + None + }, }) } @@ -427,12 +442,164 @@ impl CairoRunnerBuilder { /// Depends on: /// - [initialize_base_segments](Self::initialize_base_segments) /// - [initialize_builtin_runners_for_layout](Self::initialize_builtin_runners_for_layout) + /// or [initialize_builtin_runners](Self::initialize_builtin_runners) pub fn initialize_builtin_segments(&mut self) { for builtin_runner in self.builtin_runners.iter_mut() { builtin_runner.initialize_segments(&mut self.memory); } } + /// Initializing the builtin segments. + /// + /// Depends on: + /// - [initialize_builtin_segments](Self::initialize_builtin_segments) + pub fn initialize_builtin_zero_segments(&mut self) { + for builtin_runner in self.builtin_runners.iter_mut() { + if let BuiltinRunner::Mod(runner) = builtin_runner { + runner.initialize_zero_segment(&mut self.memory); + } + } + } + + pub fn initialize_validation_rules(&mut self) -> Result<(), RunnerError> { + for builtin in self.builtin_runners.iter() { + builtin.add_validation_rule(&mut self.memory.memory); + } + + self.memory + .memory + .validate_existing_memory() + .map_err(RunnerError::MemoryValidationError) + } + + pub fn initialize_main_entrypoint(&mut self) -> Result { + let mut stack = Vec::new(); + { + let builtin_runners = self + .builtin_runners + .iter() + .map(|b| (b.name(), b)) + .collect::>(); + for builtin_name in &self.program.builtins { + if let Some(builtin_runner) = builtin_runners.get(builtin_name) { + stack.append(&mut builtin_runner.initial_stack()); + } else { + stack.push(Felt252::ZERO.into()) + } + } + } + + if self.is_proof_mode() { + // In canonical proof mode, add the dummy last fp and pc to the public memory, so that the verifier can enforce + + // canonical offset should be 2 for Cairo 0 + let mut target_offset = 2; + + // Cairo1 is not adding data to check [fp - 2] = fp, and has a different initialization of the stack. This should be updated. + // Cairo0 remains canonical + + if matches!(self.runner_mode, RunnerMode::ProofModeCairo1) { + target_offset = stack.len() + 2; + + // This values shouldn't be needed with a canonical proof mode + let return_fp = self.add_memory_segment(); + let end = self.add_memory_segment(); + stack.append(&mut vec![ + MaybeRelocatable::RelocatableValue(return_fp), + MaybeRelocatable::RelocatableValue(end), + ]); + + self.initialize_state( + self.program + .shared_program_data + .start + .ok_or(RunnerError::NoProgramStart)?, + stack, + )?; + } else { + let mut stack_prefix = vec![ + Into::::into( + (self.execution_base.ok_or(RunnerError::NoExecBase)? + target_offset)?, + ), + MaybeRelocatable::from(Felt252::zero()), + ]; + stack_prefix.extend(stack.clone()); + + self.execution_public_memory = Some(Vec::from_iter(0..stack_prefix.len())); + + self.initialize_state( + self.program + .shared_program_data + .start + .ok_or(RunnerError::NoProgramStart)?, + stack_prefix.clone(), + )?; + } + + self.initial_fp = + Some((self.execution_base.ok_or(RunnerError::NoExecBase)? + target_offset)?); + + self.initial_ap = self.initial_fp; + return Ok((self.program_base.ok_or(RunnerError::NoProgBase)? + + self + .program + .shared_program_data + .end + .ok_or(RunnerError::NoProgramEnd)?)?); + } + + let return_fp = self.add_memory_segment(); + if let Some(main) = self.program.shared_program_data.main { + let main_clone = main; + Ok(self.initialize_function_entrypoint( + main_clone, + stack, + MaybeRelocatable::RelocatableValue(return_fp), + )?) + } else { + Err(RunnerError::MissingMain) + } + } + + fn initialize_function_entrypoint( + &mut self, + entrypoint: usize, + mut stack: Vec, + return_fp: MaybeRelocatable, + ) -> Result { + let end = self.add_memory_segment(); + stack.append(&mut vec![ + return_fp, + MaybeRelocatable::RelocatableValue(end), + ]); + if let Some(base) = &self.execution_base { + self.initial_fp = Some(Relocatable { + segment_index: base.segment_index, + offset: base.offset + stack.len(), + }); + self.initial_ap = self.initial_fp; + } else { + return Err(RunnerError::NoExecBase); + } + self.initialize_state(entrypoint, stack)?; + self.final_pc = Some(end); + Ok(end) + } + + fn initialize_state( + &mut self, + entrypoint: usize, + stack: Vec, + ) -> Result<(), RunnerError> { + let prog_base = self.program_base.ok_or(RunnerError::NoProgBase)?; + let exec_base = self.execution_base.ok_or(RunnerError::NoExecBase)?; + self.initial_pc = Some((prog_base + entrypoint)?); + self.memory + .load_data(exec_base, &stack) + .map_err(RunnerError::MemoryInitializationError)?; + Ok(()) + } + /// Loads the program into the program segment. /// /// If this function is not called, the program will be loaded @@ -520,7 +687,7 @@ impl CairoRunnerBuilder { } pub fn build(self) -> Result { - let vm = VirtualMachineBuilder::default() + let mut vm = VirtualMachineBuilder::default() .builtin_runners(self.builtin_runners) .segments(self.memory) .instruction_cache(self.instructions) @@ -532,23 +699,29 @@ impl CairoRunnerBuilder { }) .build(); + if let Some(initial_pc) = self.initial_pc { + vm.run_context.pc = initial_pc; + } + if let Some(initial_fp) = self.initial_fp { + vm.run_context.fp = initial_fp.offset; + } + if let Some(initial_ap) = self.initial_ap { + vm.run_context.ap = initial_ap.offset; + } + Ok(CairoRunner { vm, layout: self.layout, program_base: self.program_base, execution_base: self.execution_base, entrypoint: self.program.shared_program_data.main, - initial_ap: None, - initial_fp: None, - initial_pc: None, - final_pc: None, + initial_ap: self.initial_ap, + initial_fp: self.initial_fp, + initial_pc: self.initial_pc, + final_pc: self.final_pc, run_ended: false, segments_finalized: false, - execution_public_memory: if self.runner_mode != RunnerMode::ExecutionMode { - Some(Vec::new()) - } else { - None - }, + execution_public_memory: self.execution_public_memory, runner_mode: self.runner_mode, relocated_memory: Vec::new(), exec_scopes: ExecutionScopes::new(), @@ -597,6 +770,11 @@ impl Clone for CairoRunnerBuilder { loaded_program: self.loaded_program, hints: self.hints.clone(), instructions: self.instructions.clone(), + initial_pc: self.initial_pc, + initial_fp: self.initial_fp, + initial_ap: self.initial_ap, + final_pc: self.final_pc, + execution_public_memory: self.execution_public_memory.clone(), } } } From c56cb7135f1f6490b8497d403074a8985a9d2fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Wed, 15 Oct 2025 17:29:07 -0300 Subject: [PATCH 03/21] Use builder in vm::cairo_run program tests --- vm/src/cairo_run.rs | 28 ++++++++++++++++++++++------ vm/src/lib.rs | 2 +- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/vm/src/cairo_run.rs b/vm/src/cairo_run.rs index eb63334e4c..7ea5bf1151 100644 --- a/vm/src/cairo_run.rs +++ b/vm/src/cairo_run.rs @@ -8,7 +8,10 @@ use crate::{ errors::{ cairo_run_errors::CairoRunError, runner_errors::RunnerError, vm_exception::VmException, }, - runners::{cairo_pie::CairoPie, cairo_runner::CairoRunner}, + runners::{ + cairo_pie::CairoPie, + cairo_runner::{CairoRunner, CairoRunnerBuilder, RunnerMode}, + }, security::verify_secure_runner, }, }; @@ -77,18 +80,31 @@ pub fn cairo_run_program_with_initial_scope( .allow_missing_builtins .unwrap_or(cairo_run_config.proof_mode); - let mut cairo_runner = CairoRunner::new( + let mut runner_builder = CairoRunnerBuilder::new( program, cairo_run_config.layout, cairo_run_config.dynamic_layout_params.clone(), - cairo_run_config.proof_mode, - cairo_run_config.trace_enabled, - cairo_run_config.disable_trace_padding, + if cairo_run_config.proof_mode { + RunnerMode::ProofModeCanonical + } else { + RunnerMode::ExecutionMode + }, )?; + runner_builder.enable_trace(cairo_run_config.trace_enabled); + runner_builder.disable_trace_padding(cairo_run_config.disable_trace_padding); + runner_builder.allow_missing_builtins(allow_missing_builtins); + runner_builder.initialize_builtin_runners_for_layout()?; + runner_builder.initialize_base_segments(); + runner_builder.load_program()?; + runner_builder.initialize_builtin_segments(); + runner_builder.initialize_builtin_zero_segments(); + let end = runner_builder.initialize_main_entrypoint()?; + runner_builder.initialize_validation_rules()?; + + let mut cairo_runner = runner_builder.build()?; cairo_runner.exec_scopes = exec_scopes; - let end = cairo_runner.initialize(allow_missing_builtins)?; // check step calculation cairo_runner diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 425a5796fd..d907b101ad 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -12,7 +12,7 @@ //! - `cairo-0-data-availability-hints`: Enable data availability hints that were introduced in Cairo 0. Not enabled by default. #![cfg_attr(docsrs, feature(doc_cfg))] -#![deny(warnings)] +// #![deny(warnings)] #![forbid(unsafe_code)] #![cfg_attr(any(target_arch = "wasm32", not(feature = "std")), no_std)] From fef6e8a5a52929d7a2ac82b2a171d50d88a7c214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Wed, 15 Oct 2025 17:56:09 -0300 Subject: [PATCH 04/21] Use builder for custom mod builtin params test --- vm/src/tests/cairo_run_test.rs | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/vm/src/tests/cairo_run_test.rs b/vm/src/tests/cairo_run_test.rs index 03758cc285..03e6b4fb7e 100644 --- a/vm/src/tests/cairo_run_test.rs +++ b/vm/src/tests/cairo_run_test.rs @@ -4,7 +4,10 @@ use crate::{tests::*, types::layout_name::LayoutName}; use crate::{ utils::test_utils::Program, vm::{ - runners::{builtin_runner::BuiltinRunner, cairo_runner::CairoRunner}, + runners::{ + builtin_runner::BuiltinRunner, + cairo_runner::{CairoRunnerBuilder, RunnerMode}, + }, security::verify_secure_runner, }, }; @@ -1213,17 +1216,31 @@ fn run_program_with_custom_mod_builtin_params( }; let mut hint_processor = BuiltinHintProcessor::new_empty(); let program = Program::from_bytes(data, Some(cairo_run_config.entrypoint)).unwrap(); - let mut cairo_runner = CairoRunner::new( + let mut runner_builder = CairoRunnerBuilder::new( &program, cairo_run_config.layout, - cairo_run_config.dynamic_layout_params, - cairo_run_config.proof_mode, - cairo_run_config.trace_enabled, - cairo_run_config.disable_trace_padding, + cairo_run_config.dynamic_layout_params.clone(), + if cairo_run_config.proof_mode { + RunnerMode::ProofModeCanonical + } else { + RunnerMode::ExecutionMode + }, ) .unwrap(); + runner_builder.enable_trace(cairo_run_config.trace_enabled); + runner_builder.allow_missing_builtins(false); + runner_builder + .initialize_builtin_runners_for_layout() + .unwrap(); + runner_builder.initialize_base_segments(); + runner_builder.load_program().unwrap(); + runner_builder.initialize_builtin_segments(); + runner_builder.initialize_builtin_zero_segments(); + let end = runner_builder.initialize_main_entrypoint().unwrap(); + runner_builder.initialize_validation_rules().unwrap(); + + let mut cairo_runner = runner_builder.build().unwrap(); - let end = cairo_runner.initialize(false).unwrap(); // Modify add_mod & mul_mod params for runner in cairo_runner.vm.get_builtin_runners_as_mut() { if let BuiltinRunner::Mod(runner) = runner { From fbc21fa6d1cfea43a65f784738d2f82d0b9f57b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Wed, 15 Oct 2025 18:20:14 -0300 Subject: [PATCH 05/21] Use builder for air private input with mod builtin test --- vm/src/vm/runners/builtin_runner/modulo.rs | 23 +++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/vm/src/vm/runners/builtin_runner/modulo.rs b/vm/src/vm/runners/builtin_runner/modulo.rs index 85a8fe8070..ac82c629c1 100644 --- a/vm/src/vm/runners/builtin_runner/modulo.rs +++ b/vm/src/vm/runners/builtin_runner/modulo.rs @@ -811,7 +811,7 @@ mod tests { hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor, types::layout_name::LayoutName, utils::test_utils::Program, - vm::runners::cairo_runner::CairoRunner, + vm::runners::cairo_runner::{CairoRunnerBuilder, RunnerMode}, Felt252, }; @@ -821,11 +821,24 @@ mod tests { let mut hint_processor = BuiltinHintProcessor::new_empty(); let program = Program::from_bytes(program_data, Some("main")).unwrap(); - let mut runner = - CairoRunner::new(&program, LayoutName::all_cairo, None, true, false, false).unwrap(); - let end = runner.initialize(false).unwrap(); - // Modify add_mod & mul_mod params + let mut runner_builder = CairoRunnerBuilder::new( + &program, + LayoutName::all_cairo, + None, + RunnerMode::ProofModeCanonical, + ) + .unwrap(); + runner_builder + .initialize_builtin_runners_for_layout() + .unwrap(); + runner_builder.initialize_base_segments(); + runner_builder.load_program().unwrap(); + runner_builder.initialize_builtin_segments(); + runner_builder.initialize_builtin_zero_segments(); + let end = runner_builder.initialize_main_entrypoint().unwrap(); + runner_builder.initialize_validation_rules().unwrap(); + let mut runner = runner_builder.build().unwrap(); runner.run_until_pc(end, &mut hint_processor).unwrap(); runner.run_for_steps(1, &mut hint_processor).unwrap(); From b3f104c18a28f0183e2da90fa4fd623a6387effe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Wed, 15 Oct 2025 18:28:21 -0300 Subject: [PATCH 06/21] Use builder in cairo pie test --- vm/src/cairo_run.rs | 20 +++++++++++++++----- vm/src/vm/runners/cairo_runner.rs | 2 ++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/vm/src/cairo_run.rs b/vm/src/cairo_run.rs index 7ea5bf1151..48f7009eca 100644 --- a/vm/src/cairo_run.rs +++ b/vm/src/cairo_run.rs @@ -187,16 +187,26 @@ pub fn cairo_run_pie( let allow_missing_builtins = cairo_run_config.allow_missing_builtins.unwrap_or_default(); let program = Program::from_stripped_program(&pie.metadata.program); - let mut cairo_runner = CairoRunner::new( + + let mut runner_builder = CairoRunnerBuilder::new( &program, cairo_run_config.layout, cairo_run_config.dynamic_layout_params.clone(), - false, - cairo_run_config.trace_enabled, - cairo_run_config.disable_trace_padding, + RunnerMode::ExecutionMode, )?; + runner_builder.enable_trace(cairo_run_config.trace_enabled); + runner_builder.disable_trace_padding(cairo_run_config.disable_trace_padding); + runner_builder.allow_missing_builtins(allow_missing_builtins); + runner_builder.initialize_builtin_runners_for_layout()?; + runner_builder.initialize_base_segments(); + runner_builder.load_program()?; + runner_builder.initialize_builtin_segments(); + runner_builder.initialize_builtin_zero_segments(); + let end = runner_builder.initialize_main_entrypoint()?; + runner_builder.initialize_validation_rules()?; + + let mut cairo_runner = runner_builder.build()?; - let end = cairo_runner.initialize(allow_missing_builtins)?; cairo_runner.vm.finalize_segments_by_cairo_pie(pie); // Load builtin additional data for (name, data) in pie.additional_data.0.iter() { diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 5a88354ebc..356ef3733a 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -156,6 +156,8 @@ impl ResourceTracker for RunResources { /// - Compiled hints /// - Decoded instructions /// - Loaded program segment +/// +/// TODO: Add support for Cairo PIE pub struct CairoRunnerBuilder { program: Program, layout: CairoLayout, From 7bb23f6100aae28d23a7dba41137f2210ea15484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Wed, 15 Oct 2025 18:32:59 -0300 Subject: [PATCH 07/21] Use builder in fuzzed program test --- vm/src/cairo_run.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/vm/src/cairo_run.rs b/vm/src/cairo_run.rs index 48f7009eca..6a64739670 100644 --- a/vm/src/cairo_run.rs +++ b/vm/src/cairo_run.rs @@ -272,16 +272,27 @@ pub fn cairo_run_fuzzed_program( .allow_missing_builtins .unwrap_or(cairo_run_config.proof_mode); - let mut cairo_runner = CairoRunner::new( + let mut runner_builder = CairoRunnerBuilder::new( &program, cairo_run_config.layout, cairo_run_config.dynamic_layout_params.clone(), - cairo_run_config.proof_mode, - cairo_run_config.trace_enabled, - cairo_run_config.disable_trace_padding, + if cairo_run_config.proof_mode { + RunnerMode::ProofModeCanonical + } else { + RunnerMode::ExecutionMode + }, )?; - - let _end = cairo_runner.initialize(allow_missing_builtins)?; + runner_builder.enable_trace(cairo_run_config.trace_enabled); + runner_builder.allow_missing_builtins(allow_missing_builtins); + runner_builder.disable_trace_padding(cairo_run_config.disable_trace_padding); + runner_builder.initialize_builtin_runners_for_layout()?; + runner_builder.initialize_base_segments(); + runner_builder.load_program()?; + runner_builder.initialize_builtin_segments(); + runner_builder.initialize_builtin_zero_segments(); + let _end = runner_builder.initialize_main_entrypoint()?; + runner_builder.initialize_validation_rules()?; + let mut cairo_runner = runner_builder.build()?; let res = match cairo_runner.run_until_steps(steps_limit, hint_processor) { Err(VirtualMachineError::EndOfProgram(_remaining)) => Ok(()), // program ran OK but ended before steps limit From 68188d09022c0db4a9cad40379852d1cca0ed063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Thu, 16 Oct 2025 12:02:30 -0300 Subject: [PATCH 08/21] Add builder in run from entrypoint tests --- vm/src/tests/mod.rs | 43 ++++++++++++++----------------- vm/src/vm/runners/cairo_runner.rs | 2 ++ 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/vm/src/tests/mod.rs b/vm/src/tests/mod.rs index 49358c29e1..694aa00407 100644 --- a/vm/src/tests/mod.rs +++ b/vm/src/tests/mod.rs @@ -10,7 +10,7 @@ use crate::Felt252; use crate::{ hint_processor::cairo_1_hint_processor::hint_processor::Cairo1HintProcessor, types::{builtin_name::BuiltinName, relocatable::MaybeRelocatable}, - vm::runners::cairo_runner::{CairoArg, CairoRunner}, + vm::runners::cairo_runner::{CairoArg, CairoRunner, CairoRunnerBuilder, RunnerMode}, }; #[cfg(feature = "cairo-1-hints")] use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; @@ -110,32 +110,30 @@ fn run_cairo_1_entrypoint( let contract_class: CasmContractClass = serde_json::from_slice(program_content).unwrap(); let mut hint_processor = Cairo1HintProcessor::new(&contract_class.hints, RunResources::default(), false); + let program_builtins = get_casm_contract_builtins(&contract_class, entrypoint_offset); - let mut runner = CairoRunner::new( + let mut runner_builder = CairoRunnerBuilder::new( &(contract_class.clone().try_into().unwrap()), LayoutName::all_cairo, None, - false, - false, - false, + RunnerMode::ExecutionMode, ) .unwrap(); - - let program_builtins = get_casm_contract_builtins(&contract_class, entrypoint_offset); - runner - .initialize_function_runner_cairo_1(&program_builtins) + runner_builder.initialize_base_segments(); + runner_builder + .initialize_builtin_runners(&program_builtins) .unwrap(); + runner_builder.initialize_builtin_segments(); + let mut runner = runner_builder.build().unwrap(); // Implicit Args let syscall_segment = MaybeRelocatable::from(runner.vm.add_memory_segment()); - let builtins = runner.get_program_builtins(); - let builtin_segment: Vec = runner .vm .get_builtin_runners() .iter() - .filter(|b| builtins.contains(&b.name())) + .filter(|b| program_builtins.contains(&b.name())) .flat_map(|b| b.initial_stack()) .collect(); @@ -218,31 +216,30 @@ fn run_cairo_1_entrypoint_with_run_resources( hint_processor: &mut Cairo1HintProcessor, args: &[MaybeRelocatable], ) -> Result, CairoRunError> { - let mut runner = CairoRunner::new( + let program_builtins = get_casm_contract_builtins(&contract_class, entrypoint_offset); + + let mut runner_builder = CairoRunnerBuilder::new( &(contract_class.clone().try_into().unwrap()), LayoutName::all_cairo, None, - false, - false, - false, + RunnerMode::ExecutionMode, ) .unwrap(); - - let program_builtins = get_casm_contract_builtins(&contract_class, entrypoint_offset); - runner - .initialize_function_runner_cairo_1(&program_builtins) + runner_builder.initialize_base_segments(); + runner_builder + .initialize_builtin_runners(&program_builtins) .unwrap(); + runner_builder.initialize_builtin_segments(); + let mut runner = runner_builder.build().unwrap(); // Implicit Args let syscall_segment = MaybeRelocatable::from(runner.vm.add_memory_segment()); - let builtins = runner.get_program_builtins(); - let builtin_segment: Vec = runner .vm .get_builtin_runners() .iter() - .filter(|b| builtins.contains(&b.name())) + .filter(|b| program_builtins.contains(&b.name())) .flat_map(|b| b.initial_stack()) .collect(); diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 356ef3733a..a2f60b49ca 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -158,6 +158,8 @@ impl ResourceTracker for RunResources { /// - Loaded program segment /// /// TODO: Add support for Cairo PIE +/// +/// TODO: Add support for initialization of run_from_entrypoint pub struct CairoRunnerBuilder { program: Program, layout: CairoLayout, From f02f26744e6b637fba6cf4e0507d9bd8b0a20417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Fri, 17 Oct 2025 12:16:33 -0300 Subject: [PATCH 09/21] Use builder for initializing contract entrypoint --- vm/src/tests/mod.rs | 126 ++++++++++++++++-------------- vm/src/vm/runners/cairo_runner.rs | 28 ++++++- 2 files changed, 94 insertions(+), 60 deletions(-) diff --git a/vm/src/tests/mod.rs b/vm/src/tests/mod.rs index 694aa00407..6b804a19fc 100644 --- a/vm/src/tests/mod.rs +++ b/vm/src/tests/mod.rs @@ -10,7 +10,11 @@ use crate::Felt252; use crate::{ hint_processor::cairo_1_hint_processor::hint_processor::Cairo1HintProcessor, types::{builtin_name::BuiltinName, relocatable::MaybeRelocatable}, - vm::runners::cairo_runner::{CairoArg, CairoRunner, CairoRunnerBuilder, RunnerMode}, + vm::{ + errors::vm_exception::VmException, + runners::cairo_runner::{CairoArg, CairoRunnerBuilder, RunnerMode}, + security::verify_secure_runner, + }, }; #[cfg(feature = "cairo-1-hints")] use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; @@ -112,8 +116,10 @@ fn run_cairo_1_entrypoint( Cairo1HintProcessor::new(&contract_class.hints, RunResources::default(), false); let program_builtins = get_casm_contract_builtins(&contract_class, entrypoint_offset); + let program = contract_class.clone().try_into().unwrap(); + let mut runner_builder = CairoRunnerBuilder::new( - &(contract_class.clone().try_into().unwrap()), + &program, LayoutName::all_cairo, None, RunnerMode::ExecutionMode, @@ -124,13 +130,12 @@ fn run_cairo_1_entrypoint( .initialize_builtin_runners(&program_builtins) .unwrap(); runner_builder.initialize_builtin_segments(); - let mut runner = runner_builder.build().unwrap(); + runner_builder.load_program().unwrap(); // Implicit Args - let syscall_segment = MaybeRelocatable::from(runner.vm.add_memory_segment()); + let syscall_segment = MaybeRelocatable::from(runner_builder.add_memory_segment()); - let builtin_segment: Vec = runner - .vm + let builtin_segment: Vec = runner_builder .get_builtin_runners() .iter() .filter(|b| program_builtins.contains(&b.name())) @@ -148,28 +153,26 @@ fn run_cairo_1_entrypoint( // Load builtin costs let builtin_costs: Vec = vec![0.into(), 0.into(), 0.into(), 0.into(), 0.into()]; - let builtin_costs_ptr = runner.vm.add_memory_segment(); - runner - .vm - .load_data(builtin_costs_ptr, &builtin_costs) + let builtin_costs_ptr = runner_builder.add_memory_segment(); + runner_builder + .load_memory(builtin_costs_ptr, &builtin_costs) .unwrap(); // Load extra data - let core_program_end_ptr = - (runner.program_base.unwrap() + runner.program.shared_program_data.data.len()).unwrap(); + let core_program_end_ptr = (runner_builder.get_program_base().unwrap() + + program.shared_program_data.data.len()) + .unwrap(); let program_extra_data: Vec = vec![0x208B7FFF7FFF7FFE.into(), builtin_costs_ptr.into()]; - runner - .vm - .load_data(core_program_end_ptr, &program_extra_data) + runner_builder + .load_memory(core_program_end_ptr, &program_extra_data) .unwrap(); // Load calldata - let calldata_start = runner.vm.add_memory_segment(); - let calldata_end = runner.vm.load_data(calldata_start, args).unwrap(); + let calldata_start = runner_builder.add_memory_segment(); + let calldata_end = runner_builder.load_memory(calldata_start, args).unwrap(); // Create entrypoint_args - let mut entrypoint_args: Vec = implicit_args .iter() .map(|m| CairoArg::from(m.clone())) @@ -180,17 +183,26 @@ fn run_cairo_1_entrypoint( ]); let entrypoint_args: Vec<&CairoArg> = entrypoint_args.iter().collect(); - // Run contract entrypoint + // Initialize entrypoint + let end = runner_builder + .initialize_function_entrypoint_with_args(entrypoint_offset, &entrypoint_args) + .unwrap(); + runner_builder.initialize_validation_rules().unwrap(); + + let mut runner = runner_builder.build().unwrap(); + // Run contract entrypoint runner - .run_from_entrypoint( - entrypoint_offset, - &entrypoint_args, - true, - Some(runner.program.shared_program_data.data.len() + program_extra_data.len()), - &mut hint_processor, - ) + .run_until_pc(end, &mut hint_processor) + .map_err(|err| VmException::from_vm_error(&runner, err)) .unwrap(); + runner.end_run(true, false, &mut hint_processor).unwrap(); + verify_secure_runner( + &runner, + false, + Some(program.shared_program_data.data.len() + program_extra_data.len()), + ) + .unwrap(); // Check return values let return_values = runner.vm.get_return_values(5).unwrap(); @@ -218,25 +230,22 @@ fn run_cairo_1_entrypoint_with_run_resources( ) -> Result, CairoRunError> { let program_builtins = get_casm_contract_builtins(&contract_class, entrypoint_offset); + let program = contract_class.clone().try_into()?; let mut runner_builder = CairoRunnerBuilder::new( - &(contract_class.clone().try_into().unwrap()), + &program, LayoutName::all_cairo, None, RunnerMode::ExecutionMode, - ) - .unwrap(); + )?; runner_builder.initialize_base_segments(); - runner_builder - .initialize_builtin_runners(&program_builtins) - .unwrap(); + runner_builder.initialize_builtin_runners(&program_builtins)?; runner_builder.initialize_builtin_segments(); - let mut runner = runner_builder.build().unwrap(); + runner_builder.load_program()?; // Implicit Args - let syscall_segment = MaybeRelocatable::from(runner.vm.add_memory_segment()); + let syscall_segment = MaybeRelocatable::from(runner_builder.add_memory_segment()); - let builtin_segment: Vec = runner - .vm + let builtin_segment: Vec = runner_builder .get_builtin_runners() .iter() .filter(|b| program_builtins.contains(&b.name())) @@ -254,28 +263,21 @@ fn run_cairo_1_entrypoint_with_run_resources( // Load builtin costs let builtin_costs: Vec = vec![0.into(), 0.into(), 0.into(), 0.into(), 0.into()]; - let builtin_costs_ptr = runner.vm.add_memory_segment(); - runner - .vm - .load_data(builtin_costs_ptr, &builtin_costs) - .unwrap(); + let builtin_costs_ptr = runner_builder.add_memory_segment(); + runner_builder.load_memory(builtin_costs_ptr, &builtin_costs)?; // Load extra data - let core_program_end_ptr = - (runner.program_base.unwrap() + runner.program.shared_program_data.data.len()).unwrap(); + let core_program_end_ptr = (runner_builder.get_program_base().unwrap() + + program.shared_program_data.data.len()) + .unwrap(); let program_extra_data: Vec = vec![0x208B7FFF7FFF7FFE.into(), builtin_costs_ptr.into()]; - runner - .vm - .load_data(core_program_end_ptr, &program_extra_data) - .unwrap(); + runner_builder.load_memory(core_program_end_ptr, &program_extra_data)?; // Load calldata - let calldata_start = runner.vm.add_memory_segment(); - let calldata_end = runner.vm.load_data(calldata_start, args).unwrap(); - + let calldata_start = runner_builder.add_memory_segment(); + let calldata_end = runner_builder.load_memory(calldata_start, args)?; // Create entrypoint_args - let mut entrypoint_args: Vec = implicit_args .iter() .map(|m| CairoArg::from(m.clone())) @@ -286,14 +288,22 @@ fn run_cairo_1_entrypoint_with_run_resources( ]); let entrypoint_args: Vec<&CairoArg> = entrypoint_args.iter().collect(); - // Run contract entrypoint + // Initialize entrypoint + let end = runner_builder + .initialize_function_entrypoint_with_args(entrypoint_offset, &entrypoint_args)?; + runner_builder.initialize_validation_rules()?; + + let mut runner = runner_builder.build()?; - runner.run_from_entrypoint( - entrypoint_offset, - &entrypoint_args, - true, - Some(runner.program.shared_program_data.data.len() + program_extra_data.len()), - hint_processor, + // Run contract entrypoint + runner + .run_until_pc(end, hint_processor) + .map_err(|err| VmException::from_vm_error(&runner, err))?; + runner.end_run(true, false, hint_processor)?; + verify_secure_runner( + &runner, + false, + Some(program.shared_program_data.data.len() + program_extra_data.len()), )?; // Check return values diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index a2f60b49ca..d2631fe57c 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -158,8 +158,6 @@ impl ResourceTracker for RunResources { /// - Loaded program segment /// /// TODO: Add support for Cairo PIE -/// -/// TODO: Add support for initialization of run_from_entrypoint pub struct CairoRunnerBuilder { program: Program, layout: CairoLayout, @@ -268,6 +266,14 @@ impl CairoRunnerBuilder { self.memory.add() } + pub fn load_memory( + &mut self, + ptr: Relocatable, + data: &[MaybeRelocatable], + ) -> Result { + self.memory.load_data(ptr, data) + } + /// *Initializes* all the builtin supported by the current layout, but only /// *includes* the builtins required by the program. /// @@ -436,6 +442,10 @@ impl CairoRunnerBuilder { Ok(()) } + pub fn get_builtin_runners(&self) -> &[BuiltinRunner] { + &self.builtin_runners + } + pub fn initialize_base_segments(&mut self) { self.program_base = Some(self.add_memory_segment()); self.execution_base = Some(self.add_memory_segment()); @@ -565,6 +575,20 @@ impl CairoRunnerBuilder { } } + pub fn initialize_function_entrypoint_with_args( + &mut self, + entrypoint: usize, + args: &[&CairoArg], + ) -> Result { + let stack = args + .iter() + .map(|arg| self.memory.gen_cairo_arg(arg)) + .collect::, VirtualMachineError>>()?; + let return_fp = MaybeRelocatable::from(0); + let end = self.initialize_function_entrypoint(entrypoint, stack, return_fp)?; + Ok(end) + } + fn initialize_function_entrypoint( &mut self, entrypoint: usize, From 57085b0eed1963f19a4590c20743ff5f126eadf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Fri, 17 Oct 2025 19:33:59 -0300 Subject: [PATCH 10/21] Improve entrypoint initialization (better readability) --- vm/src/cairo_run.rs | 2 +- vm/src/vm/runners/cairo_runner.rs | 216 ++++++++++++++++-------------- 2 files changed, 117 insertions(+), 101 deletions(-) diff --git a/vm/src/cairo_run.rs b/vm/src/cairo_run.rs index 6a64739670..886435e2a4 100644 --- a/vm/src/cairo_run.rs +++ b/vm/src/cairo_run.rs @@ -290,7 +290,7 @@ pub fn cairo_run_fuzzed_program( runner_builder.load_program()?; runner_builder.initialize_builtin_segments(); runner_builder.initialize_builtin_zero_segments(); - let _end = runner_builder.initialize_main_entrypoint()?; + runner_builder.initialize_main_entrypoint()?; runner_builder.initialize_validation_rules()?; let mut cairo_runner = runner_builder.build()?; diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index d2631fe57c..a5b7168dba 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -488,90 +488,109 @@ impl CairoRunnerBuilder { pub fn initialize_main_entrypoint(&mut self) -> Result { let mut stack = Vec::new(); - { - let builtin_runners = self - .builtin_runners - .iter() - .map(|b| (b.name(), b)) - .collect::>(); - for builtin_name in &self.program.builtins { - if let Some(builtin_runner) = builtin_runners.get(builtin_name) { - stack.append(&mut builtin_runner.initial_stack()); - } else { - stack.push(Felt252::ZERO.into()) - } + + // Initialize stack for builtin runners + let builtin_runner_map = self + .builtin_runners + .iter() + .map(|b| (b.name(), b)) + .collect::>(); + for builtin_name in &self.program.builtins { + if let Some(builtin_runner) = builtin_runner_map.get(builtin_name) { + stack.append(&mut builtin_runner.initial_stack()); + } else { + stack.push(Felt252::ZERO.into()) } } - if self.is_proof_mode() { - // In canonical proof mode, add the dummy last fp and pc to the public memory, so that the verifier can enforce + match self.runner_mode { + RunnerMode::ExecutionMode => { + // On ExecutionMode, we execute until control flow is returned. + // The stack is arranged as if we are at the start of a function call. + // Input arguments are set as input arguments to the the function. + // + // <-------- ARGUMENTS ---- + // ┌────┬────┬────┬────┬────────┬────────┬ ─ ─ ─ ─ ┐ + // ... │ │ │ │ │ RET FP │ RET PC │ + // └────┴────┴────┴────┴────────┴────────┴ ─ ─ ─ ─ ┘ + // INIT FP + // + // The initial fp points to the cell after the return pc. + + let entrypoint = self + .program + .shared_program_data + .main + .ok_or(RunnerError::MissingMain)?; + let end_pc = self.initialize_function_entrypoint_with_stack(entrypoint, stack)?; + Ok(end_pc) + } + RunnerMode::ProofModeCairo1 => { + // On ProofModeCairo1, initialization is similar to + // ExecutionMode, but we execute until a fixed address, instead + // of until control is returned. - // canonical offset should be 2 for Cairo 0 - let mut target_offset = 2; + let entrypoint = self + .program + .shared_program_data + .start + .ok_or(RunnerError::NoProgramStart)?; - // Cairo1 is not adding data to check [fp - 2] = fp, and has a different initialization of the stack. This should be updated. - // Cairo0 remains canonical + self.initialize_function_entrypoint_with_stack(entrypoint, stack)?; - if matches!(self.runner_mode, RunnerMode::ProofModeCairo1) { - target_offset = stack.len() + 2; + // We override the final PC, as we are not executing until + // control flow is returned, but rather until a fixed address. + let program_base = self.program_base.ok_or(RunnerError::NoProgBase)?; + let program_end_offset = self + .program + .shared_program_data + .end + .ok_or(RunnerError::NoProgramEnd)?; + Ok((program_base + program_end_offset)?) + } + RunnerMode::ProofModeCanonical => { + // On standalone, we execute until a fixed address. + // Input arguments are set as local variables to the current frame. + // + // ---- ARGUMENTS ------------------> + // ┌─────────┬─────────┬─────────┬────┬────┬────┬────┬────┐ + // │ INIT FP │ ZERO │ │ │ │ │ │ │ ... + // └─────────┴─────────┴─────────┴────┴────┴────┴────┴────┘ + // INIT FP + // + // The initial fp variable points to the third cell. We write + // INIT FP in the first cell, so that the verifier can enforce + // [fp - 2] = fp. + + let execution_base = self.execution_base.ok_or(RunnerError::NoExecBase)?; + let program_base = self.program_base.ok_or(RunnerError::NoProgBase)?; + let program_end_offset = self + .program + .shared_program_data + .end + .ok_or(RunnerError::NoProgramEnd)?; - // This values shouldn't be needed with a canonical proof mode - let return_fp = self.add_memory_segment(); - let end = self.add_memory_segment(); - stack.append(&mut vec![ - MaybeRelocatable::RelocatableValue(return_fp), - MaybeRelocatable::RelocatableValue(end), - ]); + let target_offset: u32 = 2; - self.initialize_state( - self.program - .shared_program_data - .start - .ok_or(RunnerError::NoProgramStart)?, - stack, - )?; - } else { - let mut stack_prefix = vec![ - Into::::into( - (self.execution_base.ok_or(RunnerError::NoExecBase)? + target_offset)?, - ), - MaybeRelocatable::from(Felt252::zero()), + let stack_prefix = [ + (execution_base + target_offset)?.into(), + Felt252::ZERO.into(), ]; - stack_prefix.extend(stack.clone()); - - self.execution_public_memory = Some(Vec::from_iter(0..stack_prefix.len())); - - self.initialize_state( - self.program - .shared_program_data - .start - .ok_or(RunnerError::NoProgramStart)?, - stack_prefix.clone(), - )?; - } + stack.splice(0..0, stack_prefix); - self.initial_fp = - Some((self.execution_base.ok_or(RunnerError::NoExecBase)? + target_offset)?); + self.execution_public_memory = Some(Vec::from_iter(0..stack.len())); - self.initial_ap = self.initial_fp; - return Ok((self.program_base.ok_or(RunnerError::NoProgBase)? - + self + let entrypoint = self .program .shared_program_data - .end - .ok_or(RunnerError::NoProgramEnd)?)?); - } - - let return_fp = self.add_memory_segment(); - if let Some(main) = self.program.shared_program_data.main { - let main_clone = main; - Ok(self.initialize_function_entrypoint( - main_clone, - stack, - MaybeRelocatable::RelocatableValue(return_fp), - )?) - } else { - Err(RunnerError::MissingMain) + .start + .ok_or(RunnerError::NoProgramStart)?; + self.initialize_pc(entrypoint)?; + self.initialize_stack(&stack)?; + self.initial_fp = Some((execution_base + target_offset)?); + self.initial_ap = self.initial_fp; + Ok((program_base + program_end_offset)?) + } } } @@ -584,46 +603,43 @@ impl CairoRunnerBuilder { .iter() .map(|arg| self.memory.gen_cairo_arg(arg)) .collect::, VirtualMachineError>>()?; - let return_fp = MaybeRelocatable::from(0); - let end = self.initialize_function_entrypoint(entrypoint, stack, return_fp)?; - Ok(end) + let end_pc = self.initialize_function_entrypoint_with_stack(entrypoint, stack)?; + Ok(end_pc) } - fn initialize_function_entrypoint( + fn initialize_function_entrypoint_with_stack( &mut self, entrypoint: usize, mut stack: Vec, - return_fp: MaybeRelocatable, ) -> Result { - let end = self.add_memory_segment(); + let return_fp = self.add_memory_segment(); + let final_pc = self.add_memory_segment(); + stack.append(&mut vec![ - return_fp, - MaybeRelocatable::RelocatableValue(end), + MaybeRelocatable::RelocatableValue(return_fp), + MaybeRelocatable::RelocatableValue(final_pc), ]); - if let Some(base) = &self.execution_base { - self.initial_fp = Some(Relocatable { - segment_index: base.segment_index, - offset: base.offset + stack.len(), - }); - self.initial_ap = self.initial_fp; - } else { - return Err(RunnerError::NoExecBase); - } - self.initialize_state(entrypoint, stack)?; - self.final_pc = Some(end); - Ok(end) + + self.initialize_pc(entrypoint)?; + self.initialize_stack(&stack)?; + + let execution_base = self.execution_base.ok_or(RunnerError::NoExecBase)?; + self.initial_fp = Some((execution_base + stack.len())?); + self.initial_ap = self.initial_fp; + self.final_pc = Some(final_pc); + Ok(final_pc) } - fn initialize_state( - &mut self, - entrypoint: usize, - stack: Vec, - ) -> Result<(), RunnerError> { - let prog_base = self.program_base.ok_or(RunnerError::NoProgBase)?; - let exec_base = self.execution_base.ok_or(RunnerError::NoExecBase)?; - self.initial_pc = Some((prog_base + entrypoint)?); + fn initialize_pc(&mut self, entrypoint: usize) -> Result<(), RunnerError> { + let program_base = self.program_base.ok_or(RunnerError::NoProgBase)?; + self.initial_pc = Some((program_base + entrypoint)?); + Ok(()) + } + + fn initialize_stack(&mut self, stack: &[MaybeRelocatable]) -> Result<(), RunnerError> { + let execution_base = self.execution_base.ok_or(RunnerError::NoExecBase)?; self.memory - .load_data(exec_base, &stack) + .load_data(execution_base, stack) .map_err(RunnerError::MemoryInitializationError)?; Ok(()) } From 5e8ab19e941c6a91019588eccbe8bbe0ddf47981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Tue, 21 Oct 2025 13:39:56 -0300 Subject: [PATCH 11/21] Update comment --- vm/src/vm/runners/cairo_runner.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index a5b7168dba..a56b010ba9 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -538,7 +538,7 @@ impl CairoRunnerBuilder { self.initialize_function_entrypoint_with_stack(entrypoint, stack)?; - // We override the final PC, as we are not executing until + // We don't return final_pc, as we are not executing until // control flow is returned, but rather until a fixed address. let program_base = self.program_base.ok_or(RunnerError::NoProgBase)?; let program_end_offset = self From 09524a93c706861264557690e604eb917e375b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Tue, 21 Oct 2025 13:43:15 -0300 Subject: [PATCH 12/21] Improve docs --- vm/src/vm/runners/cairo_runner.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index a56b010ba9..937a8c7f00 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -646,8 +646,11 @@ impl CairoRunnerBuilder { /// Loads the program into the program segment. /// - /// If this function is not called, the program will be loaded - /// automatically when initializing the entrypoint. + /// If the entrypoint is initialized from this builder, then this + /// function must be called in other to load the program. + /// + /// If the entrypoint is initialized from the runner instead, and this + /// functions is not called, the program would be loaded by the runner. pub fn load_program(&mut self) -> Result<(), RunnerError> { let program_base = self.program_base.ok_or(RunnerError::NoProgBase)?; let program_data = &self.program.shared_program_data.data; From 6aadd9951c3fa1f0425119cec5f9e38bc122a81f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Tue, 21 Oct 2025 15:37:58 -0300 Subject: [PATCH 13/21] Improve docs --- vm/src/vm/runners/cairo_runner.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 937a8c7f00..71b8f49a8e 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -507,9 +507,9 @@ impl CairoRunnerBuilder { RunnerMode::ExecutionMode => { // On ExecutionMode, we execute until control flow is returned. // The stack is arranged as if we are at the start of a function call. - // Input arguments are set as input arguments to the the function. + // Builtin bases are set as input arguments to the the function. // - // <-------- ARGUMENTS ---- + // <----- BUILTIN BASES ---- // ┌────┬────┬────┬────┬────────┬────────┬ ─ ─ ─ ─ ┐ // ... │ │ │ │ │ RET FP │ RET PC │ // └────┴────┴────┴────┴────────┴────────┴ ─ ─ ─ ─ ┘ @@ -550,9 +550,9 @@ impl CairoRunnerBuilder { } RunnerMode::ProofModeCanonical => { // On standalone, we execute until a fixed address. - // Input arguments are set as local variables to the current frame. + // Builtin bases are set as local variables to the current frame. // - // ---- ARGUMENTS ------------------> + // ---- BUILTIN BASES -------------------> // ┌─────────┬─────────┬─────────┬────┬────┬────┬────┬────┐ // │ INIT FP │ ZERO │ │ │ │ │ │ │ ... // └─────────┴─────────┴─────────┴────┴────┴────┴────┴────┘ From f0d0b7f8953a33c22c806bef12b94972c983f08b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Tue, 21 Oct 2025 16:06:27 -0300 Subject: [PATCH 14/21] Add missing config --- vm/src/tests/cairo_run_test.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/vm/src/tests/cairo_run_test.rs b/vm/src/tests/cairo_run_test.rs index 03e6b4fb7e..2f548d9e5c 100644 --- a/vm/src/tests/cairo_run_test.rs +++ b/vm/src/tests/cairo_run_test.rs @@ -1229,6 +1229,7 @@ fn run_program_with_custom_mod_builtin_params( .unwrap(); runner_builder.enable_trace(cairo_run_config.trace_enabled); runner_builder.allow_missing_builtins(false); + runner_builder.disable_trace_padding(cairo_run_config.disable_trace_padding); runner_builder .initialize_builtin_runners_for_layout() .unwrap(); From 0bbae7db0331c31e0c5c066eb134471419116dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Tue, 21 Oct 2025 16:06:31 -0300 Subject: [PATCH 15/21] Add comment --- vm/src/vm/runners/cairo_runner.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 71b8f49a8e..4a80cfbc34 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -157,7 +157,8 @@ impl ResourceTracker for RunResources { /// - Decoded instructions /// - Loaded program segment /// -/// TODO: Add support for Cairo PIE +/// TODO: Add support for Cairo PIE? +/// TODO: Add support for cairo1 load_arguments? pub struct CairoRunnerBuilder { program: Program, layout: CairoLayout, From b8abe634bda551b5f60f68ac2810d61a3b018ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Tue, 21 Oct 2025 16:06:44 -0300 Subject: [PATCH 16/21] Uncomment deny[warnings] --- vm/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/src/lib.rs b/vm/src/lib.rs index d907b101ad..425a5796fd 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -12,7 +12,7 @@ //! - `cairo-0-data-availability-hints`: Enable data availability hints that were introduced in Cairo 0. Not enabled by default. #![cfg_attr(docsrs, feature(doc_cfg))] -// #![deny(warnings)] +#![deny(warnings)] #![forbid(unsafe_code)] #![cfg_attr(any(target_arch = "wasm32", not(feature = "std")), no_std)] From f18073cca7cfd8384fd53dface66264ef5e3fa81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Tue, 21 Oct 2025 16:31:57 -0300 Subject: [PATCH 17/21] Use builder for loading arguments --- cairo1-run/src/cairo_run.rs | 25 ++++++++++++++----------- vm/src/tests/mod.rs | 12 ++++++------ vm/src/vm/runners/cairo_runner.rs | 27 +++++++++++++++++++++------ 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/cairo1-run/src/cairo_run.rs b/cairo1-run/src/cairo_run.rs index 262d0762f5..7a87a30dc4 100644 --- a/cairo1-run/src/cairo_run.rs +++ b/cairo1-run/src/cairo_run.rs @@ -266,9 +266,9 @@ pub fn cairo_run_program( let end = runner_builder.initialize_main_entrypoint()?; runner_builder.initialize_validation_rules()?; - let mut runner = runner_builder.build()?; + load_arguments(&mut runner_builder, &cairo_run_config, main_func)?; - load_arguments(&mut runner, &cairo_run_config, main_func)?; + let mut runner = runner_builder.build()?; // Run it until the end / infinite loop in proof_mode runner.run_until_pc(end, &mut hint_processor)?; @@ -469,7 +469,7 @@ After the entry_code (up until calling main) has been ran by the VM: (*4) if gas builtin is present */ fn load_arguments( - runner: &mut CairoRunner, + runner: &mut CairoRunnerBuilder, cairo_run_config: &Cairo1RunConfig, main_func: &Function, ) -> Result<(), Error> { @@ -509,25 +509,28 @@ fn load_arguments( for arg in cairo_run_config.args { match arg { FuncArg::Array(args) => { - let array_start = runner.vm.add_memory_segment(); - let array_end = runner.vm.load_data( + let array_start = runner.add_memory_segment(); + let array_end = runner.load_memory_array( array_start, &args.iter().map(|f| f.into()).collect::>(), )?; - runner.vm.insert_value( - (runner.vm.get_ap() + ap_offset).map_err(VirtualMachineError::Math)?, + runner.load_memory_value( + (runner.get_initial_ap().unwrap() + ap_offset) + .map_err(VirtualMachineError::Math)?, array_start, )?; ap_offset += 1; - runner.vm.insert_value( - (runner.vm.get_ap() + ap_offset).map_err(VirtualMachineError::Math)?, + runner.load_memory_value( + (runner.get_initial_ap().unwrap() + ap_offset) + .map_err(VirtualMachineError::Math)?, array_end, )?; ap_offset += 1; } FuncArg::Single(arg) => { - runner.vm.insert_value( - (runner.vm.get_ap() + ap_offset).map_err(VirtualMachineError::Math)?, + runner.load_memory_value( + (runner.get_initial_ap().unwrap() + ap_offset) + .map_err(VirtualMachineError::Math)?, arg, )?; ap_offset += 1; diff --git a/vm/src/tests/mod.rs b/vm/src/tests/mod.rs index 6b804a19fc..711dbe1d2b 100644 --- a/vm/src/tests/mod.rs +++ b/vm/src/tests/mod.rs @@ -155,7 +155,7 @@ fn run_cairo_1_entrypoint( vec![0.into(), 0.into(), 0.into(), 0.into(), 0.into()]; let builtin_costs_ptr = runner_builder.add_memory_segment(); runner_builder - .load_memory(builtin_costs_ptr, &builtin_costs) + .load_memory_array(builtin_costs_ptr, &builtin_costs) .unwrap(); // Load extra data @@ -165,12 +165,12 @@ fn run_cairo_1_entrypoint( let program_extra_data: Vec = vec![0x208B7FFF7FFF7FFE.into(), builtin_costs_ptr.into()]; runner_builder - .load_memory(core_program_end_ptr, &program_extra_data) + .load_memory_array(core_program_end_ptr, &program_extra_data) .unwrap(); // Load calldata let calldata_start = runner_builder.add_memory_segment(); - let calldata_end = runner_builder.load_memory(calldata_start, args).unwrap(); + let calldata_end = runner_builder.load_memory_array(calldata_start, args).unwrap(); // Create entrypoint_args let mut entrypoint_args: Vec = implicit_args @@ -264,7 +264,7 @@ fn run_cairo_1_entrypoint_with_run_resources( let builtin_costs: Vec = vec![0.into(), 0.into(), 0.into(), 0.into(), 0.into()]; let builtin_costs_ptr = runner_builder.add_memory_segment(); - runner_builder.load_memory(builtin_costs_ptr, &builtin_costs)?; + runner_builder.load_memory_array(builtin_costs_ptr, &builtin_costs)?; // Load extra data let core_program_end_ptr = (runner_builder.get_program_base().unwrap() @@ -272,11 +272,11 @@ fn run_cairo_1_entrypoint_with_run_resources( .unwrap(); let program_extra_data: Vec = vec![0x208B7FFF7FFF7FFE.into(), builtin_costs_ptr.into()]; - runner_builder.load_memory(core_program_end_ptr, &program_extra_data)?; + runner_builder.load_memory_array(core_program_end_ptr, &program_extra_data)?; // Load calldata let calldata_start = runner_builder.add_memory_segment(); - let calldata_end = runner_builder.load_memory(calldata_start, args)?; + let calldata_end = runner_builder.load_memory_array(calldata_start, args)?; // Create entrypoint_args let mut entrypoint_args: Vec = implicit_args .iter() diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 4a80cfbc34..fc0499297b 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -158,7 +158,6 @@ impl ResourceTracker for RunResources { /// - Loaded program segment /// /// TODO: Add support for Cairo PIE? -/// TODO: Add support for cairo1 load_arguments? pub struct CairoRunnerBuilder { program: Program, layout: CairoLayout, @@ -259,15 +258,27 @@ impl CairoRunnerBuilder { || self.runner_mode == RunnerMode::ProofModeCairo1 } + pub fn get_program(&self) -> &Program { + &self.program + } + pub fn get_program_base(&self) -> Option { self.program_base } + pub fn get_initial_ap(&self) -> Option { + self.initial_ap + } + + pub fn get_builtin_runners(&self) -> &[BuiltinRunner] { + &self.builtin_runners + } + pub fn add_memory_segment(&mut self) -> Relocatable { self.memory.add() } - pub fn load_memory( + pub fn load_memory_array( &mut self, ptr: Relocatable, data: &[MaybeRelocatable], @@ -275,6 +286,14 @@ impl CairoRunnerBuilder { self.memory.load_data(ptr, data) } + pub fn load_memory_value( + &mut self, + ptr: Relocatable, + data: impl Into, + ) -> Result<(), MemoryError> { + self.memory.memory.insert_value(ptr, data) + } + /// *Initializes* all the builtin supported by the current layout, but only /// *includes* the builtins required by the program. /// @@ -443,10 +462,6 @@ impl CairoRunnerBuilder { Ok(()) } - pub fn get_builtin_runners(&self) -> &[BuiltinRunner] { - &self.builtin_runners - } - pub fn initialize_base_segments(&mut self) { self.program_base = Some(self.add_memory_segment()); self.execution_base = Some(self.add_memory_segment()); From f53adb666de1c1b90ae9da7383828cd160938fd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Tue, 21 Oct 2025 17:19:15 -0300 Subject: [PATCH 18/21] Remove unwrap --- cairo1-run/src/cairo_run.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cairo1-run/src/cairo_run.rs b/cairo1-run/src/cairo_run.rs index 7a87a30dc4..debc9980b8 100644 --- a/cairo1-run/src/cairo_run.rs +++ b/cairo1-run/src/cairo_run.rs @@ -515,13 +515,13 @@ fn load_arguments( &args.iter().map(|f| f.into()).collect::>(), )?; runner.load_memory_value( - (runner.get_initial_ap().unwrap() + ap_offset) + (runner.get_initial_ap().ok_or(RunnerError::NoAP)? + ap_offset) .map_err(VirtualMachineError::Math)?, array_start, )?; ap_offset += 1; runner.load_memory_value( - (runner.get_initial_ap().unwrap() + ap_offset) + (runner.get_initial_ap().ok_or(RunnerError::NoAP)? + ap_offset) .map_err(VirtualMachineError::Math)?, array_end, )?; @@ -529,7 +529,7 @@ fn load_arguments( } FuncArg::Single(arg) => { runner.load_memory_value( - (runner.get_initial_ap().unwrap() + ap_offset) + (runner.get_initial_ap().ok_or(RunnerError::NoAP)? + ap_offset) .map_err(VirtualMachineError::Math)?, arg, )?; From ce22aabf9119a79f0c76b4dc8216c0be8915fde2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Tue, 21 Oct 2025 17:31:48 -0300 Subject: [PATCH 19/21] Improve documentation --- vm/src/vm/runners/cairo_runner.rs | 32 +++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index fc0499297b..9419d4bc49 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -152,7 +152,20 @@ impl ResourceTracker for RunResources { /// Handles the creation of a CairoRunner /// /// This structure can be cloned. This allows to compute the initial state once, -/// and execute it many times. The following elements can be cached: +/// and execute it many times. +/// +/// The following elements must be initialized in order: +/// - Base segments (program & execution segment) +/// - Builtin runners +/// - Builtin segments +/// - Entrypoint +/// +/// The following elements must be initialized in no particular order: +/// - Validation rules +/// - Program +/// +/// The following elements don't need to be initialized, but can be cached to +/// improve performance: /// - Compiled hints /// - Decoded instructions /// - Loaded program segment @@ -470,9 +483,8 @@ impl CairoRunnerBuilder { /// Initializing the builtin segments. /// /// Depends on: - /// - [initialize_base_segments](Self::initialize_base_segments) - /// - [initialize_builtin_runners_for_layout](Self::initialize_builtin_runners_for_layout) - /// or [initialize_builtin_runners](Self::initialize_builtin_runners) + /// - Base segments initialization + /// - Builtin runners initialization pub fn initialize_builtin_segments(&mut self) { for builtin_runner in self.builtin_runners.iter_mut() { builtin_runner.initialize_segments(&mut self.memory); @@ -482,7 +494,7 @@ impl CairoRunnerBuilder { /// Initializing the builtin segments. /// /// Depends on: - /// - [initialize_builtin_segments](Self::initialize_builtin_segments) + /// - Builtin segment initialization pub fn initialize_builtin_zero_segments(&mut self) { for builtin_runner in self.builtin_runners.iter_mut() { if let BuiltinRunner::Mod(runner) = builtin_runner { @@ -502,6 +514,12 @@ impl CairoRunnerBuilder { .map_err(RunnerError::MemoryValidationError) } + /// Initializes the stack for executing the main entrypoint. + /// + /// How the stack and registers are initialized depend on the execution mode. + /// + /// Depends on: + /// - Segment initialization pub fn initialize_main_entrypoint(&mut self) -> Result { let mut stack = Vec::new(); @@ -610,6 +628,8 @@ impl CairoRunnerBuilder { } } + /// Depends on: + /// - Segment initialization pub fn initialize_function_entrypoint_with_args( &mut self, entrypoint: usize, @@ -666,7 +686,7 @@ impl CairoRunnerBuilder { /// function must be called in other to load the program. /// /// If the entrypoint is initialized from the runner instead, and this - /// functions is not called, the program would be loaded by the runner. + /// functions is not called, the program will be loaded by the runner. pub fn load_program(&mut self) -> Result<(), RunnerError> { let program_base = self.program_base.ok_or(RunnerError::NoProgBase)?; let program_data = &self.program.shared_program_data.data; From 2c7f7bba5f209a8d08df406d3069a97d2f1a571b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Tue, 21 Oct 2025 18:25:53 -0300 Subject: [PATCH 20/21] Fix lifetime for wasm test --- vm/src/vm/runners/cairo_runner.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index ad21c99eec..7c28ddf81a 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -529,16 +529,18 @@ impl CairoRunnerBuilder { let mut stack = Vec::new(); // Initialize stack for builtin runners - let builtin_runner_map = self - .builtin_runners - .iter() - .map(|b| (b.name(), b)) - .collect::>(); - for builtin_name in &self.program.builtins { - if let Some(builtin_runner) = builtin_runner_map.get(builtin_name) { - stack.append(&mut builtin_runner.initial_stack()); - } else { - stack.push(Felt252::ZERO.into()) + { + let builtin_runner_map = self + .builtin_runners + .iter() + .map(|b| (b.name(), b)) + .collect::>(); + for builtin_name in &self.program.builtins { + if let Some(builtin_runner) = builtin_runner_map.get(builtin_name) { + stack.append(&mut builtin_runner.initial_stack()); + } else { + stack.push(Felt252::ZERO.into()) + } } } From b12f3b15e95156515583ed4eddfa53a21dc3b4b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Tue, 21 Oct 2025 18:30:52 -0300 Subject: [PATCH 21/21] Format --- vm/src/tests/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vm/src/tests/mod.rs b/vm/src/tests/mod.rs index 711dbe1d2b..676beeab15 100644 --- a/vm/src/tests/mod.rs +++ b/vm/src/tests/mod.rs @@ -170,7 +170,9 @@ fn run_cairo_1_entrypoint( // Load calldata let calldata_start = runner_builder.add_memory_segment(); - let calldata_end = runner_builder.load_memory_array(calldata_start, args).unwrap(); + let calldata_end = runner_builder + .load_memory_array(calldata_start, args) + .unwrap(); // Create entrypoint_args let mut entrypoint_args: Vec = implicit_args