diff --git a/CHANGELOG.md b/CHANGELOG.md index ba5904a56f..f294e67f6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ Both branches support Stwo prover opcodes (Blake2s, QM31) since v2.0.0. #### Upcoming Changes +* feat: configurable limit to number of traceback entries [#2358](https://github.com/klaus993/cairo-vm/pull/2358) + * Add Stwo cairo runner API [#2351](https://github.com/lambdaclass/cairo-vm/pull/2351) * Add union merge strategy for CHANGELOG.md [#2345](https://github.com/lambdaclass/cairo-vm/pull/2345) diff --git a/bench/criterion_benchmark.rs b/bench/criterion_benchmark.rs index 86a032df56..0a657adfa5 100644 --- a/bench/criterion_benchmark.rs +++ b/bench/criterion_benchmark.rs @@ -1,6 +1,6 @@ use cairo_vm::{ types::{layout_name::LayoutName, program::Program}, - vm::runners::cairo_runner::CairoRunner, + vm::runners::cairo_runner::{CairoRunner, DEFAULT_MAX_TRACEBACK_ENTRIES}, }; use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion}; @@ -34,6 +34,7 @@ fn build_many_runners(c: &mut Criterion) { black_box(false), black_box(false), black_box(false), + black_box(DEFAULT_MAX_TRACEBACK_ENTRIES), ) .unwrap(), ); @@ -55,6 +56,7 @@ fn load_program_data(c: &mut Criterion) { false, false, false, + DEFAULT_MAX_TRACEBACK_ENTRIES, ) .unwrap() }, diff --git a/bench/iai_benchmark.rs b/bench/iai_benchmark.rs index 4d0922a789..07d81006e2 100644 --- a/bench/iai_benchmark.rs +++ b/bench/iai_benchmark.rs @@ -1,3 +1,4 @@ +use cairo_vm::vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES; use core::hint::black_box; use iai_callgrind::library_benchmark; use iai_callgrind::library_benchmark_group; @@ -41,6 +42,7 @@ fn build_runner() { false, false, false, + DEFAULT_MAX_TRACEBACK_ENTRIES, ) .unwrap(); core::mem::drop(black_box(runner)); @@ -59,6 +61,7 @@ fn build_runner_helper() -> CairoRunner { false, false, false, + DEFAULT_MAX_TRACEBACK_ENTRIES, ) .unwrap() } diff --git a/cairo-vm-cli/src/main.rs b/cairo-vm-cli/src/main.rs index bbc0eee9f3..521329f51b 100644 --- a/cairo-vm-cli/src/main.rs +++ b/cairo-vm-cli/src/main.rs @@ -14,7 +14,7 @@ use cairo_vm::vm::errors::vm_errors::VirtualMachineError; use cairo_vm::vm::runners::cairo_pie::CairoPie; #[cfg(feature = "with_tracer")] use cairo_vm::vm::runners::cairo_runner::CairoRunner; -use cairo_vm::vm::runners::cairo_runner::RunResources; +use cairo_vm::vm::runners::cairo_runner::{RunResources, DEFAULT_MAX_TRACEBACK_ENTRIES}; #[cfg(feature = "with_tracer")] use cairo_vm_tracer::error::trace_data_errors::TraceDataError; #[cfg(feature = "with_tracer")] @@ -157,6 +157,7 @@ fn run(args: impl Iterator) -> Result<(), Error> { allow_missing_builtins: args.allow_missing_builtins, dynamic_layout_params: cairo_layout_params, disable_trace_padding: false, + max_traceback_entries: DEFAULT_MAX_TRACEBACK_ENTRIES, }; let mut cairo_runner = match if args.run_from_cairo_pie { @@ -269,8 +270,9 @@ mod tests { use super::*; use assert_matches::assert_matches; use cairo_vm::{ - hint_processor::hint_processor_definition::HintProcessor, types::program::Program, - vm::runners::cairo_runner::CairoRunner, + hint_processor::hint_processor_definition::HintProcessor, + types::program::Program, + vm::runners::cairo_runner::{CairoRunner, DEFAULT_MAX_TRACEBACK_ENTRIES}, }; use rstest::rstest; @@ -280,8 +282,16 @@ mod tests { hint_processor: &mut dyn HintProcessor, ) -> Result { let program = Program::from_bytes(program_content, Some("main")).unwrap(); - let mut cairo_runner = - CairoRunner::new(&program, LayoutName::all_cairo, None, false, true, false).unwrap(); + let mut cairo_runner = CairoRunner::new( + &program, + LayoutName::all_cairo, + None, + false, + true, + false, + DEFAULT_MAX_TRACEBACK_ENTRIES, + ) + .unwrap(); let end = cairo_runner .initialize(false) .map_err(CairoRunError::Runner)?; diff --git a/cairo1-run/src/cairo_run.rs b/cairo1-run/src/cairo_run.rs index ae01d735a7..d71a41e6e0 100644 --- a/cairo1-run/src/cairo_run.rs +++ b/cairo1-run/src/cairo_run.rs @@ -46,7 +46,9 @@ use cairo_vm::{ }, vm::{ errors::{runner_errors::RunnerError, vm_errors::VirtualMachineError}, - runners::cairo_runner::{CairoRunner, RunResources, RunnerMode}, + runners::cairo_runner::{ + CairoRunner, RunResources, RunnerMode, DEFAULT_MAX_TRACEBACK_ENTRIES, + }, vm_core::VirtualMachine, }, Felt252, @@ -101,6 +103,8 @@ pub struct Cairo1RunConfig<'a> { pub finalize_builtins: bool, /// Appends the return and input values to the output segment. This is performed by default when running in proof_mode pub append_return_values: bool, + /// The maximum number of traceback entries to store. + pub max_traceback_entries: u32, } impl Default for Cairo1RunConfig<'_> { @@ -115,6 +119,7 @@ impl Default for Cairo1RunConfig<'_> { finalize_builtins: false, append_return_values: false, dynamic_layout_params: None, + max_traceback_entries: DEFAULT_MAX_TRACEBACK_ENTRIES, } } } @@ -263,6 +268,7 @@ pub fn cairo_run_program( runner_mode, cairo_run_config.trace_enabled, false, + cairo_run_config.max_traceback_entries, )?; let end = runner.initialize(cairo_run_config.proof_mode)?; load_arguments(&mut runner, &cairo_run_config, main_func)?; diff --git a/cairo1-run/src/main.rs b/cairo1-run/src/main.rs index 28a296004e..990480e248 100644 --- a/cairo1-run/src/main.rs +++ b/cairo1-run/src/main.rs @@ -5,6 +5,7 @@ use cairo_lang_compiler::{ }; use cairo_vm::cairo_run::{write_encoded_memory, write_encoded_trace}; use cairo_vm::types::layout::CairoLayoutParams; +use cairo_vm::vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES; use cairo_vm::{ air_public_input::PublicInputError, types::layout_name::LayoutName, vm::errors::trace_errors::TraceError, Felt252, @@ -143,6 +144,7 @@ fn run(args: impl Iterator) -> Result, Error> { finalize_builtins: args.air_public_input.is_some() || args.cairo_pie_output.is_some(), append_return_values: args.append_return_values, dynamic_layout_params: cairo_layout_params, + max_traceback_entries: DEFAULT_MAX_TRACEBACK_ENTRIES, }; // Try to parse the file as a sierra program diff --git a/hint_accountant/src/main.rs b/hint_accountant/src/main.rs index 5dcce47d2c..19f4c3cdc7 100644 --- a/hint_accountant/src/main.rs +++ b/hint_accountant/src/main.rs @@ -3,6 +3,7 @@ use std::fs::{self, File}; use std::io::BufReader; +use cairo_vm::vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES; use cairo_vm::{ hint_processor::{ builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor, @@ -49,7 +50,7 @@ fn run() { whitelists.push(whitelist_file.allowed_hint_expressions); } } - let mut vm = VirtualMachine::new(false, false); + let mut vm = VirtualMachine::new(false, false, DEFAULT_MAX_TRACEBACK_ENTRIES); let mut hint_executor = BuiltinHintProcessor::new_empty(); let (ap_tracking_data, reference_ids, references, mut exec_scopes, accessible_scopes) = ( ApTracking::default(), diff --git a/vm/src/cairo_run.rs b/vm/src/cairo_run.rs index 3f206d5d2c..ee6c42c8a3 100644 --- a/vm/src/cairo_run.rs +++ b/vm/src/cairo_run.rs @@ -10,7 +10,7 @@ use crate::{ }, runners::{ cairo_pie::CairoPie, - cairo_runner::{CairoRunner, RunnerMode}, + cairo_runner::{CairoRunner, RunnerMode, DEFAULT_MAX_TRACEBACK_ENTRIES}, }, security::verify_secure_runner, trace::trace_entry::RelocatedTraceEntry, @@ -49,6 +49,8 @@ pub struct CairoRunConfig<'a> { /// instances of the builtin) compared to their sizes at the end of the execution. pub disable_trace_padding: bool, pub allow_missing_builtins: Option, + /// The maximum number of traceback entries to store. + pub max_traceback_entries: u32, } impl Default for CairoRunConfig<'_> { @@ -66,6 +68,7 @@ impl Default for CairoRunConfig<'_> { disable_trace_padding: false, allow_missing_builtins: None, dynamic_layout_params: None, + max_traceback_entries: DEFAULT_MAX_TRACEBACK_ENTRIES, } } } @@ -77,6 +80,8 @@ pub struct StwoCairoRunConfig { pub fill_holes: bool, pub secure_run: bool, pub disable_trace_padding: bool, + /// The maximum number of traceback entries to store. + pub max_traceback_entries: u32, } impl Default for StwoCairoRunConfig { @@ -88,6 +93,7 @@ impl Default for StwoCairoRunConfig { fill_holes: false, secure_run: true, disable_trace_padding: true, + max_traceback_entries: DEFAULT_MAX_TRACEBACK_ENTRIES, } } } @@ -109,6 +115,7 @@ pub fn cairo_run_stwo( runner_mode, cairo_run_config.trace_enabled, cairo_run_config.disable_trace_padding, + cairo_run_config.max_traceback_entries, )?; cairo_runner.exec_scopes = exec_scopes; @@ -170,6 +177,7 @@ pub fn cairo_run_program_with_initial_scope( cairo_run_config.proof_mode, cairo_run_config.trace_enabled, cairo_run_config.disable_trace_padding, + cairo_run_config.max_traceback_entries, )?; cairo_runner.exec_scopes = exec_scopes; @@ -277,6 +285,7 @@ pub fn cairo_run_pie( false, cairo_run_config.trace_enabled, cairo_run_config.disable_trace_padding, + cairo_run_config.max_traceback_entries, )?; let end = cairo_runner.initialize(allow_missing_builtins)?; @@ -357,6 +366,7 @@ pub fn cairo_run_pie_stwo( RunnerMode::ExecutionMode, cairo_run_config.trace_enabled, cairo_run_config.disable_trace_padding, + cairo_run_config.max_traceback_entries, )?; let end = cairo_runner.initialize_stwo(allowed_builtins)?; @@ -435,6 +445,7 @@ pub fn cairo_run_fuzzed_program( cairo_run_config.proof_mode, cairo_run_config.trace_enabled, cairo_run_config.disable_trace_padding, + cairo_run_config.max_traceback_entries, )?; let _end = cairo_runner.initialize(allow_missing_builtins)?; diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/cairo0_hints.rs b/vm/src/hint_processor/builtin_hint_processor/secp/cairo0_hints.rs index 05c612224f..cf91421987 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/cairo0_hints.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/cairo0_hints.rs @@ -392,12 +392,13 @@ mod tests { use assert_matches::assert_matches; use crate::utils::test_utils::*; + use crate::vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES; use super::*; #[test] fn test_is_on_curve_2() { - let mut vm = VirtualMachine::new(false, false); + let mut vm = VirtualMachine::new(false, false, DEFAULT_MAX_TRACEBACK_ENTRIES); vm.set_fp(1); let ids_data = non_continuous_ids_data![("is_on_curve", -1)]; vm.segments = segments![((1, 0), 1)]; @@ -428,7 +429,7 @@ mod tests { #[test] fn test_compute_q_mod_prime() { - let mut vm = VirtualMachine::new(false, false); + let mut vm = VirtualMachine::new(false, false, DEFAULT_MAX_TRACEBACK_ENTRIES); let ap_tracking = ApTracking::default(); @@ -454,7 +455,7 @@ mod tests { #[test] fn test_compute_ids_high_low() { - let mut vm = VirtualMachine::new(false, false); + let mut vm = VirtualMachine::new(false, false, DEFAULT_MAX_TRACEBACK_ENTRIES); let value = BigInt::from(25); let shift = BigInt::from(12); @@ -523,7 +524,7 @@ mod tests { #[test] fn test_r1_get_point_from_x() { - let mut vm = VirtualMachine::new(false, false); + let mut vm = VirtualMachine::new(false, false, DEFAULT_MAX_TRACEBACK_ENTRIES); vm.set_fp(10); let ids_data = non_continuous_ids_data![("x", -10), ("v", -7)]; @@ -582,7 +583,7 @@ mod tests { #[test] fn test_reduce_value() { - let mut vm = VirtualMachine::new(false, false); + let mut vm = VirtualMachine::new(false, false, DEFAULT_MAX_TRACEBACK_ENTRIES); //Initialize fp vm.run_context.fp = 10; @@ -637,7 +638,7 @@ mod tests { #[test] fn test_reduce_x() { - let mut vm = VirtualMachine::new(false, false); + let mut vm = VirtualMachine::new(false, false, DEFAULT_MAX_TRACEBACK_ENTRIES); //Initialize fp vm.run_context.fp = 10; diff --git a/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs b/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs index c68d7bc490..21e660a1cc 100644 --- a/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs +++ b/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs @@ -243,13 +243,14 @@ impl DictSquashExecScope { mod tests { use super::*; use crate::types::relocatable::Relocatable; + use crate::vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES; use crate::vm::vm_core::VirtualMachine; use std::collections::HashMap; /// Test for relocate_all_dictionaries error cases #[test] fn test_relocate_all_dictionaries_errors() { - let mut vm = VirtualMachine::new(false, false); + let mut vm = VirtualMachine::new(false, false, DEFAULT_MAX_TRACEBACK_ENTRIES); // Test 1: First segment is a temporary segment (should error) { @@ -297,7 +298,7 @@ mod tests { /// Test for relocate_all_dictionaries when no temporary segments #[test] fn test_relocate_all_dictionaries_no_temporary_segments() { - let mut vm = VirtualMachine::new(false, false); + let mut vm = VirtualMachine::new(false, false, DEFAULT_MAX_TRACEBACK_ENTRIES); let mut dict_manager = DictManagerExecScope::new(false); // Adding some trackers should not cause any errors diff --git a/vm/src/tests/cairo_run_test.rs b/vm/src/tests/cairo_run_test.rs index d1539d8612..3d45025eeb 100644 --- a/vm/src/tests/cairo_run_test.rs +++ b/vm/src/tests/cairo_run_test.rs @@ -1076,6 +1076,7 @@ fn run_program_with_custom_mod_builtin_params( cairo_run_config.proof_mode, cairo_run_config.trace_enabled, cairo_run_config.disable_trace_padding, + cairo_run_config.max_traceback_entries, ) .unwrap(); diff --git a/vm/src/tests/mod.rs b/vm/src/tests/mod.rs index 2746df2252..3d7f2f7cc4 100644 --- a/vm/src/tests/mod.rs +++ b/vm/src/tests/mod.rs @@ -2,7 +2,7 @@ use crate::types::layout_name::LayoutName; #[cfg(feature = "cairo-1-hints")] use crate::vm::errors::cairo_run_errors::CairoRunError; #[cfg(feature = "cairo-1-hints")] -use crate::vm::runners::cairo_runner::RunResources; +use crate::vm::runners::cairo_runner::{RunResources, DEFAULT_MAX_TRACEBACK_ENTRIES}; use crate::vm::trace::trace_entry::RelocatedTraceEntry; #[cfg(feature = "cairo-1-hints")] use crate::Felt252; @@ -111,6 +111,7 @@ fn run_cairo_1_entrypoint( false, false, false, + DEFAULT_MAX_TRACEBACK_ENTRIES, ) .unwrap(); @@ -218,6 +219,7 @@ fn run_cairo_1_entrypoint_with_run_resources( false, false, false, + DEFAULT_MAX_TRACEBACK_ENTRIES, ) .unwrap(); diff --git a/vm/src/utils.rs b/vm/src/utils.rs index 247443ac31..6deb71e685 100644 --- a/vm/src/utils.rs +++ b/vm/src/utils.rs @@ -233,7 +233,11 @@ pub mod test_utils { macro_rules! vm_with_range_check { () => {{ - let mut vm = VirtualMachine::new(false, false); + let mut vm = VirtualMachine::new( + false, + false, + crate::vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES, + ); vm.builtin_runners = vec![ $crate::vm::runners::builtin_runner::RangeCheckBuiltinRunner::<8>::new( Some(8), @@ -255,12 +259,19 @@ pub mod test_utils { false, false, false, + crate::vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES, ) .unwrap() }; ($program:expr, $layout:expr) => { crate::vm::runners::cairo_runner::CairoRunner::new( - &$program, $layout, None, false, false, false, + &$program, + $layout, + None, + false, + false, + false, + crate::vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES, ) .unwrap() }; @@ -272,6 +283,7 @@ pub mod test_utils { $proof_mode, false, false, + crate::vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES, ) .unwrap() }; @@ -283,6 +295,7 @@ pub mod test_utils { $proof_mode, $trace_enabled, false, + crate::vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES, ) .unwrap() }; @@ -401,11 +414,19 @@ pub mod test_utils { macro_rules! vm { () => {{ - crate::vm::vm_core::VirtualMachine::new(false, false) + crate::vm::vm_core::VirtualMachine::new( + false, + false, + crate::vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES, + ) }}; ($use_trace:expr) => {{ - crate::vm::vm_core::VirtualMachine::new($use_trace, false) + crate::vm::vm_core::VirtualMachine::new( + $use_trace, + false, + crate::vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES, + ) }}; } pub(crate) use vm; diff --git a/vm/src/vm/runners/builtin_runner/modulo.rs b/vm/src/vm/runners/builtin_runner/modulo.rs index 2a0c42726e..1051dc4549 100644 --- a/vm/src/vm/runners/builtin_runner/modulo.rs +++ b/vm/src/vm/runners/builtin_runner/modulo.rs @@ -814,6 +814,7 @@ mod tests { types::layout_name::LayoutName, utils::test_utils::Program, vm::runners::cairo_runner::CairoRunner, + vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES, Felt252, }; @@ -831,6 +832,7 @@ mod tests { proof_mode, false, false, + DEFAULT_MAX_TRACEBACK_ENTRIES, ) .unwrap(); diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 82f620292b..d0948d45b8 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -62,6 +62,8 @@ use super::{ use crate::types::instance_definitions::mod_instance_def::ModInstanceDef; use tracing::info; +pub const DEFAULT_MAX_TRACEBACK_ENTRIES: u32 = 20; + pub const ORDERED_BUILTIN_LIST: &[BuiltinName] = &[ BuiltinName::output, BuiltinName::pedersen, @@ -195,6 +197,7 @@ impl CairoRunner { mode: RunnerMode, trace_enabled: bool, disable_trace_padding: bool, + max_traceback_entries: u32, ) -> Result { let cairo_layout = match layout { LayoutName::plain => CairoLayout::plain_instance(), @@ -220,7 +223,7 @@ impl CairoRunner { }; Ok(CairoRunner { program: program.clone(), - vm: VirtualMachine::new(trace_enabled, disable_trace_padding), + vm: VirtualMachine::new(trace_enabled, disable_trace_padding, max_traceback_entries), layout: cairo_layout, final_pc: None, program_base: None, @@ -252,13 +255,14 @@ impl CairoRunner { mode: RunnerMode, trace_enabled: bool, disable_trace_padding: bool, + max_traceback_entries: u32, ) -> Result { if disable_trace_padding && mode == RunnerMode::ExecutionMode { return Err(RunnerError::DisableTracePaddingWithoutProofMode); } Ok(CairoRunner { program: program.clone(), - vm: VirtualMachine::new(trace_enabled, disable_trace_padding), + vm: VirtualMachine::new(trace_enabled, disable_trace_padding, max_traceback_entries), layout: CairoLayout::all_cairo_stwo_instance(), final_pc: None, program_base: None, @@ -306,6 +310,7 @@ impl CairoRunner { proof_mode: bool, trace_enabled: bool, disable_trace_padding: bool, + max_traceback_entries: u32, ) -> Result { // `disable_trace_padding` can only be used in `proof_mode`, so we enforce this here to // avoid unintended behavior. @@ -320,6 +325,7 @@ impl CairoRunner { RunnerMode::ProofModeCanonical, trace_enabled, disable_trace_padding, + max_traceback_entries, ) } else { Self::new_v2( @@ -329,6 +335,7 @@ impl CairoRunner { RunnerMode::ExecutionMode, trace_enabled, disable_trace_padding, + max_traceback_entries, ) } } @@ -5605,7 +5612,15 @@ mod tests { fn test_disable_trace_padding_without_proof_mode() { let program = program!(); // Attempt to create a runner in non-proof mode with trace padding disabled. - let result = CairoRunner::new(&program, LayoutName::plain, None, false, true, true); + let result = CairoRunner::new( + &program, + LayoutName::plain, + None, + false, + true, + true, + DEFAULT_MAX_TRACEBACK_ENTRIES, + ); match result { Err(RunnerError::DisableTracePaddingWithoutProofMode) => { /* test passed */ } _ => panic!("Expected DisableTracePaddingWithoutProofMode error"), @@ -5806,9 +5821,16 @@ mod tests { Program::from_bytes(program_bytes, Some("main")).expect("failed to read program"); let program: &Program = &program; - let mut cairo_runner = - CairoRunner::new(program, LayoutName::plain, None, false, false, false) - .expect("failed to create runner"); + let mut cairo_runner = CairoRunner::new( + program, + LayoutName::plain, + None, + false, + false, + false, + DEFAULT_MAX_TRACEBACK_ENTRIES, + ) + .expect("failed to create runner"); // We allow missing builtins, as we will simulate them later. let end = cairo_runner @@ -5836,8 +5858,14 @@ mod tests { Some("main"), ) .unwrap(); - let runner = - CairoRunner::new_stwo(&program, RunnerMode::ProofModeCanonical, true, true).unwrap(); + let runner = CairoRunner::new_stwo( + &program, + RunnerMode::ProofModeCanonical, + true, + true, + DEFAULT_MAX_TRACEBACK_ENTRIES, + ) + .unwrap(); assert_eq!(runner.runner_mode, RunnerMode::ProofModeCanonical); assert!(runner.execution_public_memory.is_some()); } @@ -5849,8 +5877,14 @@ mod tests { Some("main"), ) .unwrap(); - let runner = - CairoRunner::new_stwo(&program, RunnerMode::ExecutionMode, true, false).unwrap(); + let runner = CairoRunner::new_stwo( + &program, + RunnerMode::ExecutionMode, + true, + false, + DEFAULT_MAX_TRACEBACK_ENTRIES, + ) + .unwrap(); assert_eq!(runner.runner_mode, RunnerMode::ExecutionMode); assert!(runner.execution_public_memory.is_none()); } @@ -5858,7 +5892,13 @@ mod tests { #[test] fn new_stwo_disable_trace_padding_without_proof_mode() { let program = Program::default(); - match CairoRunner::new_stwo(&program, RunnerMode::ExecutionMode, true, true) { + match CairoRunner::new_stwo( + &program, + RunnerMode::ExecutionMode, + true, + true, + DEFAULT_MAX_TRACEBACK_ENTRIES, + ) { Err(RunnerError::DisableTracePaddingWithoutProofMode) => {} _ => panic!("Expected DisableTracePaddingWithoutProofMode error"), } @@ -5871,8 +5911,14 @@ mod tests { Some("main"), ) .unwrap(); - let mut runner = - CairoRunner::new_stwo(&program, RunnerMode::ProofModeCanonical, true, true).unwrap(); + let mut runner = CairoRunner::new_stwo( + &program, + RunnerMode::ProofModeCanonical, + true, + true, + DEFAULT_MAX_TRACEBACK_ENTRIES, + ) + .unwrap(); let allowed = vec![ BuiltinName::output, BuiltinName::pedersen, @@ -5895,8 +5941,14 @@ mod tests { #[test] fn initialize_builtins_stwo_rejects_ecdsa() { let program = Program::default(); - let mut runner = - CairoRunner::new_stwo(&program, RunnerMode::ProofModeCanonical, true, true).unwrap(); + let mut runner = CairoRunner::new_stwo( + &program, + RunnerMode::ProofModeCanonical, + true, + true, + DEFAULT_MAX_TRACEBACK_ENTRIES, + ) + .unwrap(); match runner.initialize_builtins_stwo(&[BuiltinName::ecdsa]) { Err(RunnerError::UnsupportedStwoBuiltin(BuiltinName::ecdsa)) => {} _ => panic!("Expected UnsupportedStwoBuiltin(ecdsa) error"), @@ -5906,8 +5958,14 @@ mod tests { #[test] fn initialize_builtins_stwo_rejects_keccak() { let program = Program::default(); - let mut runner = - CairoRunner::new_stwo(&program, RunnerMode::ProofModeCanonical, true, true).unwrap(); + let mut runner = CairoRunner::new_stwo( + &program, + RunnerMode::ProofModeCanonical, + true, + true, + DEFAULT_MAX_TRACEBACK_ENTRIES, + ) + .unwrap(); match runner.initialize_builtins_stwo(&[BuiltinName::keccak]) { Err(RunnerError::UnsupportedStwoBuiltin(BuiltinName::keccak)) => {} _ => panic!("Expected UnsupportedStwoBuiltin(keccak) error"), @@ -5921,8 +5979,14 @@ mod tests { Some("main"), ) .unwrap(); - let mut runner = - CairoRunner::new_stwo(&program, RunnerMode::ProofModeCanonical, true, true).unwrap(); + let mut runner = CairoRunner::new_stwo( + &program, + RunnerMode::ProofModeCanonical, + true, + true, + DEFAULT_MAX_TRACEBACK_ENTRIES, + ) + .unwrap(); // bitwise_builtin_test requires bitwise, but we only allow output match runner.initialize_builtins_stwo(&[BuiltinName::output]) { Err(RunnerError::UnsupportedStwoBuiltin(BuiltinName::bitwise)) => {} @@ -6040,6 +6104,7 @@ mod tests { fill_holes: false, secure_run: true, disable_trace_padding: true, + max_traceback_entries: DEFAULT_MAX_TRACEBACK_ENTRIES, }, ) .unwrap(); diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index 8611d49a8b..8c887c7607 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -2,6 +2,7 @@ use crate::math_utils::signed_felt; use crate::types::builtin_name::BuiltinName; #[cfg(feature = "extensive_hints")] use crate::types::program::HintRange; +use crate::vm::runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES; use crate::vm::vm_memory::memory::MemoryCell; use crate::{ hint_processor::{ @@ -44,8 +45,6 @@ use super::errors::runner_errors::RunnerError; use super::runners::builtin_runner::{ModBuiltinRunner, RC_N_PARTS_STANDARD}; use super::runners::cairo_pie::CairoPie; -const MAX_TRACEBACK_ENTRIES: u32 = 20; - #[derive(PartialEq, Eq, Debug)] pub struct Operands { dst: MaybeRelocatable, @@ -133,10 +132,15 @@ pub struct VirtualMachine { #[cfg(feature = "test_utils")] pub(crate) hooks: Option>, pub(crate) relocation_table: Option>, + pub(crate) max_traceback_entries: u32, } impl VirtualMachine { - pub fn new(trace_enabled: bool, disable_trace_padding: bool) -> VirtualMachine { + pub fn new( + trace_enabled: bool, + disable_trace_padding: bool, + max_traceback_entries: u32, + ) -> VirtualMachine { let run_context = RunContext { pc: Relocatable::from((0, 0)), ap: 0, @@ -165,6 +169,7 @@ impl VirtualMachine { #[cfg(feature = "test_utils")] hooks: None, relocation_table: None, + max_traceback_entries, } } @@ -935,7 +940,7 @@ impl VirtualMachine { let mut entries = Vec::<(Relocatable, Relocatable)>::new(); let mut fp = Relocatable::from((1, self.run_context.fp)); // Fetch the fp and pc traceback entries - for _ in 0..MAX_TRACEBACK_ENTRIES { + for _ in 0..self.max_traceback_entries { // Get return pc let ret_pc = match (fp - 1) .ok() @@ -1382,6 +1387,7 @@ pub struct VirtualMachineBuilder { pub(crate) current_step: usize, skip_instruction_execution: bool, run_finished: bool, + max_traceback_entries: u32, #[cfg(feature = "test_utils")] pub(crate) hooks: Option>, } @@ -1402,6 +1408,7 @@ impl Default for VirtualMachineBuilder { skip_instruction_execution: false, segments: MemorySegmentManager::new(), run_finished: false, + max_traceback_entries: DEFAULT_MAX_TRACEBACK_ENTRIES, #[cfg(feature = "test_utils")] hooks: None, } @@ -1470,6 +1477,7 @@ impl VirtualMachineBuilder { hooks: self.hooks, relocation_table: None, disable_trace_padding: false, + max_traceback_entries: self.max_traceback_entries, } } } @@ -1496,6 +1504,7 @@ mod tests { vm::{ errors::memory_errors::MemoryError, runners::builtin_runner::{BitwiseBuiltinRunner, EcOpBuiltinRunner, HashBuiltinRunner}, + runners::cairo_runner::DEFAULT_MAX_TRACEBACK_ENTRIES, }, }; use assert_matches::assert_matches; @@ -1660,7 +1669,7 @@ mod tests { op1: MaybeRelocatable::Int(Felt252::from(10)), }; - let mut vm = VirtualMachine::new(false, false); + let mut vm = VirtualMachine::new(false, false, DEFAULT_MAX_TRACEBACK_ENTRIES); vm.run_context.pc = Relocatable::from((0, 4)); vm.run_context.ap = 5; vm.run_context.fp = 6;