From 051714b20a0a20b7c9dbd5aab5a5565ceb1264e5 Mon Sep 17 00:00:00 2001 From: Whichqua <170323628+whichqua@users.noreply.github.com> Date: Mon, 3 Jun 2024 18:40:37 +0300 Subject: [PATCH] fix: get tests compiling and running --- examples/run_program.rs | 100 -------------- src/hints/bootloader_hints.rs | 78 +++++------ src/hints/execute_task_hints.rs | 79 ++++++----- src/hints/inner_select_builtins.rs | 23 ++-- src/hints/program_loader.rs | 4 +- src/hints/select_builtins.rs | 14 +- src/hints/simple_bootloader_hints.rs | 36 ++--- src/lib.rs | 197 +++++++++++++++++++++++++++ 8 files changed, 308 insertions(+), 223 deletions(-) diff --git a/examples/run_program.rs b/examples/run_program.rs index ded0078..f451c0a 100644 --- a/examples/run_program.rs +++ b/examples/run_program.rs @@ -1,23 +1,10 @@ -<<<<<<< HEAD use std::error::Error; use cairo_vm::cairo_run::{cairo_run_program_with_initial_scope, CairoRunConfig}; -======= -use std::any::Any; -use std::collections::HashMap; -use std::error::Error; - -use cairo_vm::cairo_run::{cairo_run_program, CairoRunConfig}; -use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::{ - BuiltinHintProcessor, HintProcessorData, -}; -use cairo_vm::hint_processor::hint_processor_definition::{HintExtension, HintProcessorLogic}; ->>>>>>> fb2312f0f9bda782d4d08e8c6bb0bdf77f904ed8 use cairo_vm::types::exec_scope::ExecutionScopes; use cairo_vm::types::layout_name::LayoutName; use cairo_vm::types::program::Program; use cairo_vm::vm::errors::cairo_run_errors::CairoRunError; -<<<<<<< HEAD use cairo_vm::vm::runners::cairo_runner::CairoRunner; use cairo_vm::Felt252; @@ -28,86 +15,11 @@ use cairo_bootloader::{ PackedOutput, SimpleBootloaderInput, TaskSpec, }; -======= -use cairo_vm::vm::errors::hint_errors::HintError; -use cairo_vm::vm::runners::cairo_runner::{CairoRunner, ResourceTracker}; -use cairo_vm::vm::vm_core::VirtualMachine; -use cairo_vm::Felt252; -use starknet_types_core::felt::Felt; - -use cairo_bootloader::tasks::make_bootloader_tasks; -use cairo_bootloader::{ - insert_bootloader_input, load_bootloader, BootloaderConfig, BootloaderHintProcessor, - BootloaderInput, PackedOutput, SimpleBootloaderInput, TaskSpec, -}; - -struct ExampleHintProcessor { - bootloader_hint_processor: BootloaderHintProcessor, - builtin_hint_processor: BuiltinHintProcessor, -} - -impl ExampleHintProcessor { - fn new() -> Self { - Self { - bootloader_hint_processor: BootloaderHintProcessor {}, - builtin_hint_processor: BuiltinHintProcessor::new_empty(), - } - } -} - -impl HintProcessorLogic for ExampleHintProcessor { - fn execute_hint( - &mut self, - _vm: &mut VirtualMachine, - _exec_scopes: &mut ExecutionScopes, - hint_data: &Box, - _constants: &HashMap, - ) -> Result<(), HintError> { - // This method will never be called, but must be defined according to `HintProcessorLogic`. - - let hint_data = hint_data.downcast_ref::().unwrap(); - let hint_code = &hint_data.code; - Err(HintError::UnknownHint(hint_code.clone().into_boxed_str())) - } - - fn execute_hint_extensive( - &mut self, - vm: &mut VirtualMachine, - exec_scopes: &mut ExecutionScopes, - hint_data: &Box, - constants: &HashMap, - ) -> Result { - // Cascade through the internal hint processors until we find the hint implementation. - - match self.bootloader_hint_processor.execute_hint_extensive( - vm, - exec_scopes, - hint_data, - constants, - ) { - Err(HintError::UnknownHint(_)) => {} - result => { - return result; - } - } - - self.builtin_hint_processor - .execute_hint_extensive(vm, exec_scopes, hint_data, constants) - } -} - -impl ResourceTracker for ExampleHintProcessor {} - ->>>>>>> fb2312f0f9bda782d4d08e8c6bb0bdf77f904ed8 fn cairo_run_bootloader_in_proof_mode( bootloader_program: &Program, tasks: Vec, ) -> Result { -<<<<<<< HEAD let mut hint_processor = BootloaderHintProcessor::new(); -======= - let mut hint_processor = ExampleHintProcessor::new(); ->>>>>>> fb2312f0f9bda782d4d08e8c6bb0bdf77f904ed8 let cairo_run_config = CairoRunConfig { entrypoint: "main", @@ -141,19 +53,11 @@ fn cairo_run_bootloader_in_proof_mode( insert_bootloader_input(&mut exec_scopes, bootloader_input); // Run the bootloader -<<<<<<< HEAD cairo_run_program_with_initial_scope( &bootloader_program, &cairo_run_config, &mut hint_processor, exec_scopes, -======= - cairo_run_program( - &bootloader_program, - &cairo_run_config, - &mut hint_processor, - Some(exec_scopes), ->>>>>>> fb2312f0f9bda782d4d08e8c6bb0bdf77f904ed8 ) } @@ -163,15 +67,11 @@ fn main() -> Result<(), Box> { let tasks = make_bootloader_tasks(&[fibonacci_program], &[])?; -<<<<<<< HEAD let mut runner = cairo_run_bootloader_in_proof_mode(&bootloader_program, tasks)?; let mut output_buffer = "Program Output:\n".to_string(); runner.vm.write_output(&mut output_buffer)?; print!("{output_buffer}"); -======= - let _runner = cairo_run_bootloader_in_proof_mode(&bootloader_program, tasks)?; ->>>>>>> fb2312f0f9bda782d4d08e8c6bb0bdf77f904ed8 Ok(()) } diff --git a/src/hints/bootloader_hints.rs b/src/hints/bootloader_hints.rs index be5fb11..091ba2a 100644 --- a/src/hints/bootloader_hints.rs +++ b/src/hints/bootloader_hints.rs @@ -433,7 +433,11 @@ pub fn assert_program_address( mod tests { use num_traits::ToPrimitive; + use crate::hints::codes::{ + BOOTLOADER_GUESS_PRE_IMAGE_OF_SUBTASKS_OUTPUT_HASH, BOOTLOADER_SAVE_OUTPUT_POINTER, BOOTLOADER_SAVE_PACKED_OUTPUTS, BOOTLOADER_SET_PACKED_OUTPUT_TO_SUBTASKS, EXECUTE_TASK_ASSERT_PROGRAM_ADDRESS + }; use crate::hints::types::{BootloaderConfig, SimpleBootloaderInput}; + use crate::{add_segments, define_segments, ids_data, run_hint, segments, vm, MinimalBootloaderHintProcessor}; use assert_matches::assert_matches; use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::{ BuiltinHintProcessor, HintProcessorData, @@ -498,7 +502,7 @@ mod tests { .expect("Hint failed unexpectedly"); let current_output_builtin = vm - .get_output_builtin() + .get_output_builtin_mut() .expect("The VM should have an output builtin") .clone(); let stored_output_builtin: OutputBuiltinState = exec_scopes @@ -506,8 +510,8 @@ mod tests { .expect("The output builtin is not stored in the execution scope as expected"); // Check the content of the stored output builtin - assert_ne!(current_output_builtin.base(), stored_output_builtin.base()); - assert_eq!(stored_output_builtin.base(), output_builtin.base()); + assert_ne!(current_output_builtin.base(), stored_output_builtin.base); + assert_eq!(stored_output_builtin.base, output_builtin.base()); let simple_bootloader_output_start = get_maybe_relocatable_from_var_name( "simple_bootloader_output_start", @@ -561,12 +565,12 @@ mod tests { let mut vm: VirtualMachine = vm!(); // The VM must have an existing output segment let output_segment = vm.add_memory_segment(); - vm.builtin_runners = vec![OutputBuiltinRunner::from_segment(&output_segment, true).into()]; + vm.builtin_runners = vec![OutputBuiltinRunner::new(true).into()]; let mut exec_scopes = ExecutionScopes::new(); let new_segment = vm.add_memory_segment(); let output_builtin_state = OutputBuiltinState { - base: new_segment.segment_index, + base: new_segment.segment_index.try_into().unwrap(), pages: Default::default(), attributes: Default::default(), }; @@ -577,7 +581,7 @@ mod tests { assert_eq!(vm.builtin_runners.len(), 1); match &vm.builtin_runners[0] { BuiltinRunner::Output(output_builtin) => { - assert_eq!(output_builtin.base(), output_builtin_state.base()); + assert_eq!(output_builtin.base(), output_builtin_state.base); } other => panic!("Expected an output builtin, found {:?}", other), } @@ -589,7 +593,7 @@ mod tests { let mut vm = vm!(); add_segments!(vm, 2); - vm.run_context.fp = 2; + vm.set_fp(2); let mut exec_scopes = ExecutionScopes::new(); let ids_data = ids_data!["bootloader_config"]; @@ -602,10 +606,7 @@ mod tests { let bootloader_config_segment = get_ptr_from_var_name("bootloader_config", &mut vm, &ids_data, &ap_tracking).unwrap(); - let config_segment = vm - .segments - .memory .get_continuous_range(bootloader_config_segment, 3) .unwrap(); @@ -626,8 +627,6 @@ mod tests { match programs_segment { MaybeRelocatable::RelocatableValue(relocatable) => { let program_hashes: Vec = vm - .segments - .memory .get_integer_range(relocatable.clone(), expected_nb_programs) .unwrap() .iter() @@ -647,6 +646,7 @@ mod tests { #[rstest] fn test_gen_arg() { + use std::ops::Add; let mut vm = vm!(); let mut nested_args = Vec::>::new(); @@ -661,8 +661,6 @@ mod tests { let args_base: Relocatable = gen_arg(&mut vm, &args).expect("gen_args failed unexpectedly"); let values = vm - .segments - .memory .get_integer_range(args_base, 2) .expect("Loading values failed"); @@ -671,14 +669,10 @@ mod tests { let nested_args_address: Relocatable = args_base.add(2i32).unwrap(); let nested_args_base = vm - .segments - .memory .get_relocatable(nested_args_address) .expect("Nested vector should be here"); let nested_values = vm - .segments - .memory .get_integer_range(nested_args_base, 2) .expect("Loading nested values failed"); @@ -690,8 +684,8 @@ mod tests { fn test_enter_packed_output_scope() { let mut vm = vm!(); // Set n_subtasks to 2 - vm.run_context.fp = 1; - vm.segments = segments![((1, 0), 2)]; + vm.set_fp(1); + define_segments!(vm, 2, [((1, 0), 2)]); let ids_data = ids_data!["n_subtasks"]; let ap_tracking = ApTracking::default(); @@ -733,11 +727,7 @@ mod tests { ) -> bool { exec_scopes.insert_value(vars::PACKED_OUTPUT, packed_output); is_plain_packed_output(vm, exec_scopes).expect("Hint failed unexpectedly"); - let result = vm - .segments - .memory - .get_integer(vm.run_context.get_ap()) - .unwrap(); + let result = vm.get_integer(vm.get_ap()).unwrap(); result.into_owned() != Felt252::from(0) } @@ -748,7 +738,8 @@ mod tests { assert!(is_plain(&mut vm, &mut exec_scopes, plain_packed_output)); // Increment AP to avoid an inconsistent memory error writing in the same slot - vm.run_context.ap += 1; + let new_ap = (*&vm.get_ap() + 1usize).unwrap(); + vm.set_ap(new_ap.offset); assert!(!is_plain( &mut vm, &mut exec_scopes, @@ -759,18 +750,16 @@ mod tests { #[test] fn test_save_output_pointer() { let mut vm = vm!(); - vm.segments = segments![((1, 0), (0, 0))]; + define_segments!(vm, 2, [((1, 0), (0, 0))]); let mut hint_ref = HintReference::new(0, 0, true, false); hint_ref.offset2 = OffsetValue::Value(2); let ids_data = HashMap::from([("output_ptr".to_string(), hint_ref)]); let mut exec_scopes = ExecutionScopes::new(); - let hint_data = HintProcessorData::new_default( - String::from(hint_code::BOOTLOADER_SAVE_OUTPUT_POINTER), - ids_data, - ); - let mut hint_processor = BuiltinHintProcessor::new_empty(); + let hint_data = + HintProcessorData::new_default(String::from(BOOTLOADER_SAVE_OUTPUT_POINTER), ids_data); + let mut hint_processor = MinimalBootloaderHintProcessor::new(); assert_matches!( hint_processor.execute_hint( &mut vm, @@ -815,10 +804,10 @@ mod tests { exec_scopes.insert_box("bootloader_input", Box::new(bootloader_input.clone())); let hint_data = HintProcessorData::new_default( - String::from(hint_code::BOOTLOADER_SAVE_PACKED_OUTPUTS), + String::from(BOOTLOADER_SAVE_PACKED_OUTPUTS), HashMap::new(), ); - let mut hint_processor = BuiltinHintProcessor::new_empty(); + let mut hint_processor = MinimalBootloaderHintProcessor::new(); assert_matches!( hint_processor.execute_hint( &mut vm, @@ -881,8 +870,13 @@ mod tests { offset: 18 } ); + let pages = match vm.get_output_builtin_mut().unwrap().get_additional_data() { + cairo_vm::vm::runners::cairo_pie::BuiltinAdditionalData::Output(o) => o.pages, + _ => unreachable!("Type should be Output"), + }; + assert_eq!( - vm.get_output_builtin().unwrap().pages, + pages, HashMap::from([ (1, PublicMemoryPage { start: 2, size: 3 }), (2, PublicMemoryPage { start: 5, size: 1 }), @@ -909,10 +903,10 @@ mod tests { ); let hint_data = HintProcessorData::new_default( - String::from(hint_code::BOOTLOADER_SET_PACKED_OUTPUT_TO_SUBTASKS), + String::from(BOOTLOADER_SET_PACKED_OUTPUT_TO_SUBTASKS), HashMap::new(), ); - let mut hint_processor = BuiltinHintProcessor::new_empty(); + let mut hint_processor = MinimalBootloaderHintProcessor::new(); assert_matches!( hint_processor.execute_hint( &mut vm, @@ -931,7 +925,7 @@ mod tests { fn test_guess_pre_image_of_subtasks_output_hash() { let mut vm = vm!(); add_segments!(vm, 2); - vm.run_context.fp = 2; + vm.set_fp(2); let ids_data = ids_data!["nested_subtasks_output_len", "nested_subtasks_output"]; @@ -951,7 +945,7 @@ mod tests { run_hint!( vm, ids_data.clone(), - hint_code::BOOTLOADER_GUESS_PRE_IMAGE_OF_SUBTASKS_OUTPUT_HASH, + BOOTLOADER_GUESS_PRE_IMAGE_OF_SUBTASKS_OUTPUT_HASH, &mut exec_scopes ), Ok(()) @@ -959,7 +953,7 @@ mod tests { let nested_subtasks_output_len = get_integer_from_var_name("nested_subtasks_output_len", &vm, &ids_data, &ap_tracking) .expect("nested_subtasks_output_len should be set") - .into_owned(); + .to_owned(); assert_eq!(nested_subtasks_output_len, 1.into()); let nested_subtasks_output = @@ -992,7 +986,7 @@ mod tests { let mut vm = vm!(); add_segments!(vm, 2); - vm.run_context.fp = 2; + vm.set_fp(2); let ids_data = ids_data!(vars::PROGRAM_ADDRESS); let ap_tracking = ApTracking::new(); @@ -1023,7 +1017,7 @@ mod tests { let result = run_hint!( vm, ids_data.clone(), - hint_code::EXECUTE_TASK_ASSERT_PROGRAM_ADDRESS, + EXECUTE_TASK_ASSERT_PROGRAM_ADDRESS, &mut exec_scopes ); diff --git a/src/hints/execute_task_hints.rs b/src/hints/execute_task_hints.rs index 63423a2..73321be 100644 --- a/src/hints/execute_task_hints.rs +++ b/src/hints/execute_task_hints.rs @@ -493,14 +493,19 @@ mod tests { }; use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::get_maybe_relocatable_from_var_name; use cairo_vm::hint_processor::hint_processor_definition::HintProcessorLogic; - use cairo_vm::serde::deserialize_program::OffsetValue; + use cairo_vm::serde::deserialize_program::{OffsetValue, ReferenceManager}; + use cairo_vm::types::errors::math_errors::MathError; + use cairo_vm::types::program::Program; + use cairo_vm::types::relocatable::MaybeRelocatable; use cairo_vm::vm::runners::builtin_runner::BuiltinRunner; - use cairo_vm::vm::runners::cairo_pie::PublicMemoryPage; + use cairo_vm::vm::runners::cairo_pie::{BuiltinAdditionalData, OutputBuiltinAdditionalData, PublicMemoryPage}; use cairo_vm::{any_box, relocatable, Felt252}; use num_traits::ToPrimitive; use rstest::{fixture, rstest}; + use crate::hints::codes::EXECUTE_TASK_CALL_TASK; use crate::hints::types::{BootloaderConfig, SimpleBootloaderInput}; + use crate::{add_segments, define_segments, ids_data, non_continuous_ids_data, run_hint, segments, vm}; use super::*; @@ -508,7 +513,7 @@ mod tests { fn test_allocate_program_data_segment() { let mut vm = vm!(); // Allocate space for program_data_ptr - vm.run_context.fp = 1; + vm.set_fp(1); add_segments!(vm, 2); let ids_data = ids_data!["program_data_ptr"]; let expected_program_data_segment_index = vm.segments.num_segments(); @@ -545,7 +550,7 @@ mod tests { #[fixture] fn fibonacci() -> Program { let program_content = - include_bytes!("../../../../../cairo_programs/fibonacci.json").to_vec(); + include_bytes!("../cairo-programs/fibonacci.json").to_vec(); Program::from_bytes(&program_content, Some("main")) .expect("Loading example program failed unexpectedly") @@ -554,14 +559,14 @@ mod tests { #[fixture] fn fibonacci_pie() -> CairoPie { let pie_file = - Path::new("../cairo_programs/manually_compiled/fibonacci_cairo_pie/fibonacci_pie.zip"); - CairoPie::from_file(pie_file).expect("Failed to load the program PIE") + Path::new("../cairo-programs/pie.zip"); + CairoPie::read_zip_file(pie_file).expect("Failed to load the program PIE") } #[fixture] fn field_arithmetic_program() -> Program { let program_content = - include_bytes!("../../../../../cairo_programs/field_arithmetic.json").to_vec(); + include_bytes!("../cairo-programs/fibonacci.json").to_vec(); Program::from_bytes(&program_content, Some("main")) .expect("Loading example program failed unexpectedly") @@ -572,9 +577,9 @@ mod tests { let task = Task::Program(fibonacci.clone()); let mut vm = vm!(); - vm.run_context.fp = 1; + vm.set_fp(1); // Set program_header_ptr to (2, 0) - vm.segments = segments![((1, 0), (2, 0))]; + define_segments!(vm, 2, [((1, 0), (2, 0))]); let program_header_ptr = Relocatable::from((2, 0)); add_segments!(vm, 1); @@ -593,13 +598,14 @@ mod tests { // The Fibonacci program has no builtins -> the header size is 4 let header_size = 4; - let expected_code_address = &program_header_ptr + header_size; + let code_address: Result = *&program_header_ptr + header_size; + let expected_code_address: Relocatable = code_address.unwrap(); let program_address: Relocatable = exec_scopes.get(vars::PROGRAM_ADDRESS).unwrap(); assert_eq!(program_address, expected_code_address); // Check that the segment was finalized - let expected_program_size = header_size + fibonacci.shared_program_data.data.len(); + let expected_program_size = header_size + fibonacci.data_len(); assert_eq!( vm.segments.segment_sizes[&(program_address.segment_index as usize)], expected_program_size @@ -612,8 +618,8 @@ mod tests { // Allocate space for pre-execution (8 felts), which mimics the `BuiltinData` struct in the // Bootloader's Cairo code. Our code only uses the first felt (`output` field in the struct) - vm.segments = segments![((1, 0), (2, 0))]; - vm.run_context.fp = 8; + define_segments!(vm, 2, [((1, 0), (2, 0))]); + vm.set_fp(8); add_segments!(vm, 1); let ids_data = non_continuous_ids_data![(vars::PRE_EXECUTION_BUILTIN_PTRS, -8)]; @@ -632,7 +638,7 @@ mod tests { run_hint!( vm, ids_data.clone(), - hint_code::EXECUTE_TASK_CALL_TASK, + EXECUTE_TASK_CALL_TASK, &mut exec_scopes ), Ok(()) @@ -662,15 +668,16 @@ mod tests { }) .collect(); - let shared_program_data = SharedProgramData { + let program = Program::new( + vec![], + Default::default(), + Default::default(), + Default::default(), + ReferenceManager::default(), identifiers, - ..Default::default() - }; - let program = Program { - shared_program_data: Arc::new(shared_program_data), - constants: Default::default(), - builtins: vec![], - }; + Default::default(), + Default::default(), + ).unwrap(); program } @@ -684,9 +691,9 @@ mod tests { // the Bootloader Cairo code. Our code only uses the first felt (`output` field in the // struct). Finally, we put the mocked output of `select_input_builtins` in the next // memory address and increase the AP register accordingly. - vm.segments = segments![((1, 0), (2, 0)), ((1, 1), (4, 0)), ((1, 9), (4, 42))]; - vm.run_context.ap = 10; - vm.run_context.fp = 9; + define_segments!(vm, 3, [((1, 0), (2, 0)), ((1, 1), (4, 0)), ((1, 9), (4, 42))]); + vm.set_ap(10); + vm.set_fp(9); add_segments!(vm, 3); let program_header_ptr = Relocatable::from((2, 0)); @@ -734,18 +741,18 @@ mod tests { // The pre-execution struct starts at (1, 0) and the return struct at (1, 8). // We only set the output values to (2, 0) and (2, 10), respectively, to get an output size // of 10. - vm.segments = segments![((1, 0), (2, 0)), ((1, 8), (2, 10)),]; - vm.run_context.fp = 16; + define_segments!(vm, 2, [((1, 0), (2, 0)), ((1, 8), (2, 10)),]); + vm.set_fp(16); add_segments!(vm, 1); let tree_structure = vec![1, 2, 3, 4]; - let program_output_data = OutputBuiltinAdditionalData { - base: 0, + let program_output_data = OutputBuiltinState { pages: HashMap::from([ (1, PublicMemoryPage { start: 0, size: 7 }), (2, PublicMemoryPage { start: 7, size: 3 }), ]), attributes: HashMap::from([("gps_fact_topology".to_string(), tree_structure.clone())]), + base: 0 }; let mut output_builtin = OutputBuiltinRunner::new(true); output_builtin.set_state(program_output_data.clone()); @@ -763,7 +770,6 @@ mod tests { let mut exec_scopes = ExecutionScopes::new(); let output_runner_data = OutputBuiltinAdditionalData { - base: 0, pages: HashMap::new(), attributes: HashMap::new(), }; @@ -783,7 +789,8 @@ mod tests { assert_eq!(fact_topology.tree_structure, tree_structure); // Check that the output builtin was updated - let output_builtin_additional_data = vm.get_output_builtin().unwrap().get_additional_data(); + let output_builtin_additional_data = + vm.get_output_builtin_mut().unwrap().get_additional_data(); assert!(matches!( output_builtin_additional_data, BuiltinAdditionalData::Output(data) if data == output_runner_data, @@ -802,7 +809,7 @@ mod tests { // Initialize the used builtins to {range_check: 30, bitwise: 50} as these two // are used by the field arithmetic program. Note that the used builtins list // does not contain empty elements (i.e. offsets are 8 and 9 instead of 10 and 12). - vm.segments = segments![ + define_segments!(vm, 2, [ ((1, 0), (2, 1)), ((1, 1), (2, 2)), ((1, 2), (2, 3)), @@ -814,8 +821,8 @@ mod tests { ((1, 8), (2, 30)), ((1, 9), (2, 50)), ((1, 24), (1, 8)), - ]; - vm.run_context.fp = 25; + ]); + vm.set_fp(25); add_segments!(vm, 1); // Note that used_builtins_addr is a pointer to the used builtins list at (1, 8) @@ -827,7 +834,7 @@ mod tests { let ap_tracking = ApTracking::new(); let mut exec_scopes = ExecutionScopes::new(); - let n_builtins = field_arithmetic_program.builtins.len(); + let n_builtins = field_arithmetic_program.builtins_len(); exec_scopes.insert_value(vars::N_BUILTINS, n_builtins); exec_scopes.insert_value(vars::TASK, task); @@ -836,8 +843,6 @@ mod tests { // Check that the return builtins were written correctly let return_builtins = vm - .segments - .memory .get_continuous_range(Relocatable::from((1, 16)), 8) .expect("Return builtin was not properly written to memory."); diff --git a/src/hints/inner_select_builtins.rs b/src/hints/inner_select_builtins.rs index e6936fa..50397bf 100644 --- a/src/hints/inner_select_builtins.rs +++ b/src/hints/inner_select_builtins.rs @@ -65,6 +65,8 @@ mod tests { use cairo_vm::Felt252; use rstest::rstest; + use crate::{add_segments, define_segments, ids_data, segments, vm}; + use super::*; #[rstest] @@ -81,16 +83,21 @@ mod tests { builtin_value + 1 }; - vm.segments = segments![ - ((1, 0), (2, 0)), - ((1, 1), (2, 1)), - ((2, 0), builtin_value), - ((2, 1), expected_value) - ]; + define_segments!( + vm, + 3, + [ + ((1, 0), (2, 0)), + ((1, 1), (2, 1)), + ((2, 0), builtin_value), + ((2, 1), expected_value) + ] + ); // Allocate space for program_data_ptr - vm.run_context.fp = 3; + vm.set_fp(3); add_segments!(vm, 2); let ids_data = ids_data!["selected_encodings", "all_encodings", "select_builtin"]; + // dbg!(&ids_data); let ap_tracking = ApTracking::new(); let mut exec_scopes = ExecutionScopes::new(); @@ -102,7 +109,7 @@ mod tests { let select_builtin = get_integer_from_var_name("select_builtin", &vm, &ids_data, &ap_tracking) .unwrap() - .into_owned(); + .to_owned(); let n_selected_builtins: usize = exec_scopes.get(vars::N_SELECTED_BUILTINS).unwrap(); if (n_builtins != 0) && should_select_builtin { diff --git a/src/hints/program_loader.rs b/src/hints/program_loader.rs index e36e178..c53328b 100644 --- a/src/hints/program_loader.rs +++ b/src/hints/program_loader.rs @@ -242,7 +242,7 @@ mod tests { #[fixture] fn fibonacci() -> Program { let program_content = - include_bytes!("../../../../../cairo_programs/fibonacci.json").to_vec(); + include_bytes!("../cairo-programs/fibonacci.json").to_vec(); Program::from_bytes(&program_content, Some("main")) .expect("Loading example program failed unexpectedly") @@ -295,7 +295,7 @@ mod tests { check_loaded_header(&vm, base_address.clone(), &program, bootloader_version); - let builtin_list_ptr = (base_address + builtins_offset)?; + let builtin_list_ptr = (base_address + builtins_offset).unwrap(); check_loaded_builtins(&vm, &vec![], builtin_list_ptr); } diff --git a/src/hints/select_builtins.rs b/src/hints/select_builtins.rs index dcb2666..1f74203 100644 --- a/src/hints/select_builtins.rs +++ b/src/hints/select_builtins.rs @@ -39,17 +39,13 @@ pub fn select_builtins_enter_scope( #[cfg(test)] mod tests { - use std::any::Any; - use std::collections::HashMap; - use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::get_integer_from_var_name; - use cairo_vm::hint_processor::hint_processor_definition::HintReference; use cairo_vm::serde::deserialize_program::ApTracking; use cairo_vm::types::exec_scope::ExecutionScopes; - use cairo_vm::vm::errors::hint_errors::HintError; use cairo_vm::vm::vm_core::VirtualMachine; - use num_traits::ToPrimitive; - use serde::Serialize; + use std::collections::HashMap; + + use crate::{define_segments, ids_data, segments, vm}; use super::*; @@ -57,8 +53,8 @@ mod tests { fn test_select_builtins_enter_scope() { let mut vm = vm!(); // Set n_selected_builtins to 7 - vm.run_context.fp = 1; - vm.segments = segments![((1, 0), 7)]; + vm.set_fp(1); + define_segments!(vm, 2, [((1, 0), 7)]); let ids_data = ids_data![vars::N_SELECTED_BUILTINS]; let n_selected_builtins = 7usize; diff --git a/src/hints/simple_bootloader_hints.rs b/src/hints/simple_bootloader_hints.rs index c473226..acdee27 100644 --- a/src/hints/simple_bootloader_hints.rs +++ b/src/hints/simple_bootloader_hints.rs @@ -131,15 +131,12 @@ pub fn set_current_task( #[cfg(test)] mod tests { - use std::any::Any; - use std::collections::HashMap; use std::collections::HashMap; use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::{ get_ptr_from_var_name, get_relocatable_from_var_name, insert_value_from_var_name, }; - use cairo_vm::hint_processor::hint_processor_definition::HintReference; - use cairo_vm::serde::deserialize_program::{ApTracking, BuiltinName, Identifier}; + use cairo_vm::serde::deserialize_program::ApTracking; use cairo_vm::types::exec_scope::ExecutionScopes; use cairo_vm::types::program::Program; use cairo_vm::types::relocatable::{MaybeRelocatable, Relocatable}; @@ -153,7 +150,6 @@ mod tests { use cairo_vm::vm::vm_memory::memory::Memory; use cairo_vm::{any_box, Felt252}; use num_traits::ToPrimitive; - use num_traits::ToPrimitive; use rstest::{fixture, rstest}; use starknet_crypto::FieldElement; @@ -163,13 +159,14 @@ mod tests { use crate::hints::program_loader::ProgramLoader; use crate::hints::types::{BootloaderVersion, Task, TaskSpec}; use crate::hints::vars; + use crate::{add_segments, define_segments, ids_data, vm}; use super::*; #[fixture] fn fibonacci() -> Program { let program_content = - include_bytes!("../../../../../cairo_programs/fibonacci.json").to_vec(); + include_bytes!("../cairo-programs/fibonacci.json").to_vec(); Program::from_bytes(&program_content, Some("main")) .expect("Loading example program failed unexpectedly") @@ -194,8 +191,8 @@ mod tests { #[rstest] fn test_prepare_task_range_checks(simple_bootloader_input: SimpleBootloaderInput) { let mut vm = vm!(); - vm.run_context.fp = 3; - vm.segments = segments![((1, 0), (2, 0)), ((1, 1), (2, 2))]; + vm.set_fp(3); + define_segments!(vm, 2, [((1, 0), (2, 0)), ((1, 1), (2, 2))]); let ids_data = ids_data!["output_ptr", "range_check_ptr", "task_range_check_ptr"]; vm.add_memory_segment(); @@ -216,8 +213,6 @@ mod tests { // Assert *output_ptr == n_tasks let output = vm - .segments - .memory .get_integer(Relocatable { segment_index: 2, offset: 0, @@ -266,8 +261,8 @@ mod tests { let mut vm = vm!(); add_segments!(vm, 2); - vm.run_context.ap = 1; - vm.run_context.fp = 1; + vm.set_ap(1); + vm.set_fp(1); let ids_data = ids_data!["num"]; let ap_tracking = ApTracking::new(); @@ -276,11 +271,7 @@ mod tests { divide_num_by_2(&mut vm, &ids_data, &ap_tracking).expect("Hint failed unexpectedly"); - let divided_num = vm - .segments - .memory - .get_integer(vm.run_context.get_ap()) - .unwrap(); + let divided_num = vm.get_integer(vm.get_ap()).unwrap(); assert_eq!(divided_num.into_owned(), expected_num_felt); } @@ -291,12 +282,7 @@ mod tests { set_ap_to_zero(&mut vm).expect("Hint failed unexpectedly"); - let ap_value = vm - .segments - .memory - .get_integer(vm.run_context.get_ap()) - .unwrap() - .into_owned(); + let ap_value = vm.get_integer(vm.get_ap()).unwrap().into_owned(); assert_eq!(ap_value, Felt252::from(0)); } @@ -305,8 +291,8 @@ mod tests { fn test_set_current_task(simple_bootloader_input: SimpleBootloaderInput) { // Set n_tasks to 1 let mut vm = vm!(); - vm.run_context.fp = 2; - vm.segments = segments![((1, 0), 1)]; + vm.set_fp(2); + define_segments!(vm, 2, [((1, 0), 1)]); let mut exec_scopes = ExecutionScopes::new(); exec_scopes.insert_value(vars::SIMPLE_BOOTLOADER_INPUT, simple_bootloader_input); diff --git a/src/lib.rs b/src/lib.rs index 964a021..0f5725f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,3 +12,200 @@ pub fn insert_bootloader_input( ) { exec_scopes.insert_value(BOOTLOADER_INPUT, bootloader_input); } + +#[macro_export] +macro_rules! vm { + () => { + VirtualMachine::new(false) // Default to false if no argument is provided + }; + ($trace_enabled:expr) => { + VirtualMachine::new($trace_enabled) + }; +} + +#[macro_export] +macro_rules! add_segments { + ($vm:expr, $n:expr) => { + for _ in 0..$n { + $vm.add_memory_segment(); + } + }; +} +#[macro_export] +macro_rules! ids_data { + ( $( $name: expr ),* ) => { + { + #[allow(clippy::useless_vec)] + let ids_names = vec![$( $name ),*]; + let references = $crate::references!(ids_names.len() as i32); + let mut ids_data = HashMap::::new(); + for (i, name) in ids_names.iter().enumerate() { + ids_data.insert(name.to_string(), references.get(&i).unwrap().clone()); + } + ids_data + } + }; +} +#[macro_export] +macro_rules! references { + ($num: expr) => {{ + let mut references = HashMap::< + usize, + cairo_vm::hint_processor::hint_processor_definition::HintReference, + >::new(); + for i in 0..$num { + references.insert( + i as usize, + cairo_vm::hint_processor::hint_processor_definition::HintReference::new_simple( + (i as i32), + ), + ); + } + references + }}; +} + +#[macro_export] +macro_rules! non_continuous_ids_data { + ( $( ($name: expr, $offset:expr) ),* $(,)? ) => { + { + let mut ids_data = cairo_vm::stdlib::collections::HashMap::::new(); + $( + ids_data.insert(cairo_vm::stdlib::string::String::from($name), HintReference::new_simple($offset)); + )* + ids_data + } + }; +} + +#[macro_export] +macro_rules! segments { + ($( (($si:expr, $off:expr), $val:tt) ),* $(,)? ) => { + { + let mut segments = cairo_vm::vm::vm_memory::memory_segments::MemorySegmentManager::new(); + segments.memory = $crate::memory!($( (($si, $off), $val) ),*); + segments + } + + }; +} + +#[macro_export] +macro_rules! memory { + ( $( (($si:expr, $off:expr), $val:tt) ),* ) => { + { + let mut memory = cairo_vm::vm::vm_memory::memory::Memory::new(); + $crate::memory_from_memory!(memory, ( $( (($si, $off), $val) ),* )); + memory + } + }; +} + +#[macro_export] +macro_rules! memory_from_memory { + ($mem: expr, ( $( (($si:expr, $off:expr), $val:tt) ),* )) => { + { + $( + $crate::memory_inner!($mem, ($si, $off), $val); + )* + } + }; +} + +#[macro_export] +macro_rules! insert_value_inner { + ($vm:expr, ($si:expr, $off:expr), ($sival:expr, $offval: expr)) => { + let (k, v) = ( + ($si, $off).into(), + &$crate::mayberelocatable!($sival, $offval), + ); + let mut res = $vm.insert_value(k, v); + while matches!( + res, + Err(cairo_vm::vm::errors::memory_errors::MemoryError::UnallocatedSegment(_)) + ) { + dbg!(&res); + if $si < 0 { + // $vm.temp_data.push(cairo_vm::stdlib::vec::Vec::new()) + } else { + // $vm.data.push(cairo_vm::stdlib::vec::Vec::new()); + } + res = $vm.insert_value(k, v); + } + }; + ($vm:expr, ($si:expr, $off:expr), $val:expr) => { + let (k, v) = (($si, $off).into(), &$crate::mayberelocatable!($val)); + let mut res = $vm.insert_value(k, v); + while matches!( + res, + Err(cairo_vm::vm::errors::memory_errors::MemoryError::UnallocatedSegment(_)) + ) { + dbg!(&res); + if $si < 0 { + // $mem.temp_data.push($crate::stdlib::vec::Vec::new()) + } else { + // $mem.data.push($crate::stdlib::vec::Vec::new()); + } + res = $vm.insert_value(k, v); + } + }; +} + +#[macro_export] +macro_rules! mayberelocatable { + ($val1 : expr, $val2 : expr) => { + cairo_vm::types::relocatable::MaybeRelocatable::from(($val1, $val2)) + }; + ($val1 : expr) => { + cairo_vm::types::relocatable::MaybeRelocatable::from(cairo_vm::Felt252::from($val1 as i128)) + }; +} + +#[macro_export] +macro_rules! define_segments { + ($vm:ident, $count:expr, [$( (($seg1:expr, $off1:expr), $val:tt) ),* $(,)?]) => { + for _ in 0..$count { + $vm.add_memory_segment(); + } + $( + $crate::insert_value_inner!($vm, ($seg1, $off1), $val); + )* + }; +} + + +macro_rules! run_hint { + ($vm:expr, $ids_data:expr, $hint_code:expr, $exec_scopes:expr, $constants:expr) => {{ + let hint_data = HintProcessorData::new_default($hint_code.to_string(), $ids_data); + let mut hint_processor = $crate::MinimalBootloaderHintProcessor::new(); + hint_processor.execute_hint(&mut $vm, $exec_scopes, &any_box!(hint_data), $constants) + }}; + ($vm:expr, $ids_data:expr, $hint_code:expr, $exec_scopes:expr) => {{ + let hint_data = HintProcessorData::new_default( + cairo_vm::stdlib::string::ToString::to_string($hint_code), + $ids_data, + ); + let mut hint_processor = $crate::MinimalBootloaderHintProcessor::new(); + hint_processor.execute_hint( + &mut $vm, + $exec_scopes, + &any_box!(hint_data), + &cairo_vm::stdlib::collections::HashMap::new(), + ) + }}; + ($vm:expr, $ids_data:expr, $hint_code:expr) => {{ + let hint_data = HintProcessorData::new_default( + crate::stdlib::string::ToString::to_string($hint_code), + $ids_data, + ); + let mut hint_processor = $crate::MinimalBootloaderHintProcessor::new(); + hint_processor.execute_hint( + &mut $vm, + exec_scopes_ref!(), + &any_box!(hint_data), + &crate::stdlib::collections::HashMap::new(), + ) + }}; +} +pub(crate) use run_hint; +