diff --git a/CHANGELOG.md b/CHANGELOG.md index e776dfd3c5..d368d46ba5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ #### Upcoming Changes +* Fix bug affecting cairo1 programs with input and System builtin [#2207](https://github.com/lambdaclass/cairo-vm/pull/2207) + * fix: Added `cairo_1_test_contracts` and `cairo_2_test_contracts` as dependencies for `test-extensive_hints` target [#2201](https://github.com/lambdaclass/cairo-vm/pull/2201) * breaking: Store constants in Hint Data [#2191](https://github.com/lambdaclass/cairo-vm/pull/2191) diff --git a/cairo1-run/src/cairo_run.rs b/cairo1-run/src/cairo_run.rs index 51418afbc3..ae34f38771 100644 --- a/cairo1-run/src/cairo_run.rs +++ b/cairo1-run/src/cairo_run.rs @@ -54,6 +54,11 @@ use num_bigint::{BigInt, Sign}; use num_traits::{cast::ToPrimitive, Zero}; use std::{collections::HashMap, iter::Peekable}; +// Necessary memory gaps for the values created on the entry code of each implicit builtin +const SEGMENT_ARENA_GAPS: usize = 4; +const GAS_BUILTIN_GAPS: usize = 1; +const SYSTEM_BUILTIN_GAPS: usize = 1; + /// Representation of a cairo argument /// Can consist of a single Felt or an array of Felts #[derive(Debug, Clone)] @@ -469,20 +474,13 @@ fn load_arguments( cairo_run_config: &Cairo1RunConfig, main_func: &Function, ) -> Result<(), Error> { - let got_gas_builtin = main_func - .signature - .param_types - .iter() - .any(|ty| ty.debug_name.as_ref().is_some_and(|n| n == "GasBuiltin")); + let got_gas_builtin = got_implicit_builtin(&main_func.signature.param_types, "GasBuiltin"); if cairo_run_config.args.is_empty() && !got_gas_builtin { // Nothing to be done return Ok(()); } - let got_segment_arena = main_func - .signature - .param_types - .iter() - .any(|ty| ty.debug_name.as_ref().is_some_and(|n| n == "SegmentArena")); + let got_segment_arena = got_implicit_builtin(&main_func.signature.param_types, "SegmentArena"); + let got_system_builtin = got_implicit_builtin(&main_func.signature.param_types, "System"); // This AP correction represents the memory slots taken up by the values created by `create_entry_code`: // These include: // * The builtin bases (not including output) @@ -497,10 +495,13 @@ fn load_arguments( ap_offset += runner.get_program().builtins_len() - 1; } if got_segment_arena { - ap_offset += 4; + ap_offset += SEGMENT_ARENA_GAPS; } if got_gas_builtin { - ap_offset += 1; + ap_offset += GAS_BUILTIN_GAPS; + } + if got_system_builtin { + ap_offset += SYSTEM_BUILTIN_GAPS; } for arg in cairo_run_config.args { match arg { @@ -547,16 +548,9 @@ fn create_entry_code( ) -> Result<(CasmContext, Vec), Error> { let copy_to_output_builtin = config.copy_to_output(); let signature = &func.signature; - let got_segment_arena = signature.param_types.iter().any(|ty| { - get_info(sierra_program_registry, ty) - .map(|x| x.long_id.generic_id == SegmentArenaType::ID) - .unwrap_or_default() - }); - let got_gas_builtin = signature.param_types.iter().any(|ty| { - get_info(sierra_program_registry, ty) - .map(|x| x.long_id.generic_id == GasBuiltinType::ID) - .unwrap_or_default() - }); + let got_segment_arena = got_implicit_builtin(&signature.param_types, "SegmentArena"); + let got_gas_builtin = got_implicit_builtin(&signature.param_types, "GasBuiltin"); + let got_system_builtin = got_implicit_builtin(&signature.param_types, "System"); // The builtins in the formatting expected by the runner. let (builtins, builtin_offset) = get_function_builtins(&signature.param_types, copy_to_output_builtin); @@ -738,10 +732,12 @@ fn create_entry_code( // We lost the output_ptr var after re-scoping, so we need to create it again // The last instruction will write the last output ptr so we can find it in [ap - 1] let output_ptr = ctx.add_var(CellExpression::Deref(deref!([ap - 1]))); - // len(builtins - output) + len(builtins) + if segment_arena: segment_arena_ptr + info_ptr + 0 + (segment_arena_ptr + 3) + (gas_builtin) + // len(builtins - output) + len(builtins) + if segment_arena: segment_arena_ptr + + // info_ptr + 0 + (segment_arena_ptr + 3) + (gas_builtin) + (system_builtin) let offset = (2 * builtins.len() - 1 + 4 * got_segment_arena as usize - + got_gas_builtin as usize) as i16; + + got_gas_builtin as usize + + got_system_builtin as usize) as i16; let array_start_ptr = ctx.add_var(CellExpression::Deref(deref!([fp + offset]))); let array_end_ptr = ctx.add_var(CellExpression::Deref(deref!([fp + offset + 1]))); casm_build_extend! {ctx, @@ -1008,6 +1004,11 @@ fn check_only_array_felt_return_type( _ => false, } } +fn got_implicit_builtin(param_types: &[ConcreteTypeId], builtin_name: &str) -> bool { + param_types + .iter() + .any(|ty| ty.debug_name.as_ref().is_some_and(|n| n == builtin_name)) +} fn is_panic_result(return_type_id: Option<&ConcreteTypeId>) -> bool { return_type_id diff --git a/cairo1-run/src/main.rs b/cairo1-run/src/main.rs index 2116579d17..f068ef9d47 100644 --- a/cairo1-run/src/main.rs +++ b/cairo1-run/src/main.rs @@ -454,6 +454,27 @@ mod tests { None, None )] + #[case( + "with_input/implicit_system_builtin.cairo", + "[1 2]", + "[1 2]", + Some("[1 2]"), + Some("[1 2]") + )] + #[case( + "with_input/implicit_gas_builtin.cairo", + "[1 2]", + "[1 2]", + Some("[1 2]"), + Some("[1 2]") + )] + #[case( + "with_input/system_segment_gas.cairo", + "[1 2]", + "[1 2]", + Some("[1 2]"), + Some("[1 2]") + )] fn test_run_program( #[case] program: &str, #[case] expected_output: &str, diff --git a/cairo_programs/cairo-1-programs/serialized_output/with_input/implicit_gas_builtin.cairo b/cairo_programs/cairo-1-programs/serialized_output/with_input/implicit_gas_builtin.cairo new file mode 100644 index 0000000000..09d65660f6 --- /dev/null +++ b/cairo_programs/cairo-1-programs/serialized_output/with_input/implicit_gas_builtin.cairo @@ -0,0 +1,4 @@ +fn main(input: Array) -> Array { + core::internal::require_implicit::(); + input +} diff --git a/cairo_programs/cairo-1-programs/serialized_output/with_input/implicit_system_builtin.cairo b/cairo_programs/cairo-1-programs/serialized_output/with_input/implicit_system_builtin.cairo new file mode 100644 index 0000000000..baecc8b4ec --- /dev/null +++ b/cairo_programs/cairo-1-programs/serialized_output/with_input/implicit_system_builtin.cairo @@ -0,0 +1,4 @@ +fn main(input: Array) -> Array { + core::internal::require_implicit::(); + input +} diff --git a/cairo_programs/cairo-1-programs/serialized_output/with_input/system_segment_gas.cairo b/cairo_programs/cairo-1-programs/serialized_output/with_input/system_segment_gas.cairo new file mode 100644 index 0000000000..71e5d6e1cc --- /dev/null +++ b/cairo_programs/cairo-1-programs/serialized_output/with_input/system_segment_gas.cairo @@ -0,0 +1,5 @@ +fn main(input:Array) -> Array { + core::internal::require_implicit::(); + let _elements: Felt252Dict>> = Default::default(); + input +} diff --git a/cairo_programs/cairo-1-programs/with_input/implicit_gas_builtin.cairo b/cairo_programs/cairo-1-programs/with_input/implicit_gas_builtin.cairo new file mode 100644 index 0000000000..09d65660f6 --- /dev/null +++ b/cairo_programs/cairo-1-programs/with_input/implicit_gas_builtin.cairo @@ -0,0 +1,4 @@ +fn main(input: Array) -> Array { + core::internal::require_implicit::(); + input +} diff --git a/cairo_programs/cairo-1-programs/with_input/implicit_system_builtin.cairo b/cairo_programs/cairo-1-programs/with_input/implicit_system_builtin.cairo new file mode 100644 index 0000000000..baecc8b4ec --- /dev/null +++ b/cairo_programs/cairo-1-programs/with_input/implicit_system_builtin.cairo @@ -0,0 +1,4 @@ +fn main(input: Array) -> Array { + core::internal::require_implicit::(); + input +} diff --git a/cairo_programs/cairo-1-programs/with_input/system_segment_gas.cairo b/cairo_programs/cairo-1-programs/with_input/system_segment_gas.cairo new file mode 100644 index 0000000000..71e5d6e1cc --- /dev/null +++ b/cairo_programs/cairo-1-programs/with_input/system_segment_gas.cairo @@ -0,0 +1,5 @@ +fn main(input:Array) -> Array { + core::internal::require_implicit::(); + let _elements: Felt252Dict>> = Default::default(); + input +}