cairo_vm/hint_processor/builtin_hint_processor/
segments.rs

1use crate::stdlib::{collections::HashMap, prelude::*};
2
3use crate::hint_processor::builtin_hint_processor::hint_utils::get_ptr_from_var_name;
4use crate::hint_processor::{
5    builtin_hint_processor::hint_utils::insert_value_from_var_name,
6    hint_processor_definition::HintReference,
7};
8use crate::serde::deserialize_program::ApTracking;
9use crate::vm::errors::hint_errors::HintError;
10use crate::vm::vm_core::VirtualMachine;
11
12/*
13Implements hint:
14%{ memory.add_relocation_rule(src_ptr=ids.src_ptr, dest_ptr=ids.dest_ptr) %}
15*/
16pub fn relocate_segment(
17    vm: &mut VirtualMachine,
18    ids_data: &HashMap<String, HintReference>,
19    ap_tracking: &ApTracking,
20) -> Result<(), HintError> {
21    let src_ptr = get_ptr_from_var_name("src_ptr", vm, ids_data, ap_tracking)?;
22    // Bugfix: this is a workaround for an issue in the vm related to the way it computes
23    // `dest_ptr` in `segment_arena.cairo`. For some reason it sets `dest_ptr` to 0 (felt) instead
24    // of a valid relocatable value.
25    // As this hint is used in other places, we need to determine if we are in `segments_arena`
26    // first. We check this by determining if the "infos" variable is declared.
27    // If it is the case, we simply recompute `dest_ptr` manually.
28    let dest_ptr = if let Ok(infos) = get_ptr_from_var_name("infos", vm, ids_data, ap_tracking) {
29        let infos_0_end = vm.get_relocatable((infos + 1)?)?;
30
31        #[cfg(not(feature = "extensive_hints"))]
32        {
33            (infos_0_end + 1u32)?
34        }
35
36        #[cfg(feature = "extensive_hints")]
37        {
38            crate::types::relocatable::MaybeRelocatable::RelocatableValue((infos_0_end + 1u32)?)
39        }
40    } else {
41        #[cfg(not(feature = "extensive_hints"))]
42        {
43            get_ptr_from_var_name("dest_ptr", vm, ids_data, ap_tracking)?
44        }
45
46        #[cfg(feature = "extensive_hints")]
47        {
48            crate::hint_processor::builtin_hint_processor::hint_utils::get_maybe_relocatable_from_var_name("dest_ptr", vm, ids_data, ap_tracking)?
49        }
50    };
51    vm.add_relocation_rule(src_ptr, dest_ptr)
52        .map_err(HintError::Memory)?;
53    Ok(())
54}
55
56/*
57This hint doesn't belong to the Cairo common library
58It's only added for testing proposes
59
60Implements hint:
61%{ ids.temporary_array = segments.add_temp_segment() %}
62*/
63pub fn temporary_array(
64    vm: &mut VirtualMachine,
65    ids_data: &HashMap<String, HintReference>,
66    ap_tracking: &ApTracking,
67) -> Result<(), HintError> {
68    let temp_segment = vm.add_temporary_segment();
69    insert_value_from_var_name("temporary_array", temp_segment, vm, ids_data, ap_tracking)?;
70
71    Ok(())
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    use crate::{
79        any_box,
80        hint_processor::{
81            builtin_hint_processor::{
82                builtin_hint_processor_definition::{BuiltinHintProcessor, HintProcessorData},
83                hint_code,
84            },
85            hint_processor_definition::HintProcessorLogic,
86        },
87        utils::test_utils::*,
88    };
89    use assert_matches::assert_matches;
90
91    #[cfg(target_arch = "wasm32")]
92    use wasm_bindgen_test::*;
93
94    #[test]
95    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
96    fn run_relocate_segment() {
97        let hint_code = hint_code::RELOCATE_SEGMENT;
98        //Initialize vm
99        let mut vm = vm!();
100        //Initialize fp
101        vm.run_context.fp = 2;
102        //Insert ids into memory
103        vm.segments = segments![((1, 0), (-2, 0)), ((1, 1), (3, 0)), ((3, 0), 42)];
104
105        //Create ids_data & hint_data
106        let ids_data = ids_data!["src_ptr", "dest_ptr"];
107
108        //Execute the hint
109        assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
110
111        vm.segments
112            .memory
113            .relocate_memory()
114            .expect("Couldn't relocate memory.");
115    }
116
117    #[test]
118    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
119    fn run_temporary_array() {
120        let hint_code = hint_code::TEMPORARY_ARRAY;
121        //Initialize vm
122        let mut vm = vm!();
123        vm.segments.add();
124        vm.segments.add();
125        //Initialize fp
126        vm.run_context.fp = 1;
127
128        //Create ids_data & hint_data
129        let ids_data = ids_data!["temporary_array"];
130
131        //Execute the hint
132        assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
133        check_memory!(vm.segments.memory, ((1, 0), (-1, 0)));
134    }
135}