cairo_vm/hint_processor/builtin_hint_processor/
pow_utils.rs

1use crate::stdlib::{boxed::Box, collections::HashMap, prelude::*};
2
3use crate::Felt252;
4use crate::{
5    hint_processor::{
6        builtin_hint_processor::hint_utils::{
7            get_relocatable_from_var_name, insert_value_from_var_name,
8        },
9        hint_processor_definition::HintReference,
10    },
11    serde::deserialize_program::ApTracking,
12    vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
13};
14
15/*
16Implements hint:
17%{ ids.locs.bit = (ids.prev_locs.exp % PRIME) & 1 %}
18*/
19pub fn pow(
20    vm: &mut VirtualMachine,
21    ids_data: &HashMap<String, HintReference>,
22    ap_tracking: &ApTracking,
23) -> Result<(), HintError> {
24    let prev_locs_exp = vm
25        .get_integer(
26            (get_relocatable_from_var_name("prev_locs", vm, ids_data, ap_tracking)? + 4_i32)?,
27        )
28        .map_err(|_| {
29            HintError::IdentifierHasNoMember(Box::new(("prev_locs".to_string(), "exp".to_string())))
30        })?;
31    let locs_bit = prev_locs_exp.mod_floor(&Felt252::TWO.try_into().unwrap());
32    insert_value_from_var_name("locs", locs_bit, vm, ids_data, ap_tracking)?;
33    Ok(())
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39    use crate::types::relocatable::Relocatable;
40
41    use crate::{
42        any_box,
43        hint_processor::{
44            builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor,
45            builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData,
46            hint_processor_definition::HintProcessorLogic,
47        },
48        types::relocatable::MaybeRelocatable,
49        utils::test_utils::*,
50        vm::{errors::memory_errors::MemoryError, vm_core::VirtualMachine},
51    };
52    use assert_matches::assert_matches;
53
54    #[cfg(target_arch = "wasm32")]
55    use wasm_bindgen_test::*;
56
57    #[test]
58    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
59    fn run_pow_ok() {
60        let hint_code = "ids.locs.bit = (ids.prev_locs.exp % PRIME) & 1";
61        let mut vm = vm_with_range_check!();
62        //Initialize ap
63        vm.run_context.fp = 12;
64        vm.segments = segments![((1, 11), 3)];
65        let ids_data = non_continuous_ids_data![("prev_locs", -5), ("locs", 0)];
66        assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
67        //Check hint memory inserts
68        check_memory![vm.segments.memory, ((1, 12), 1)];
69    }
70
71    #[test]
72    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
73    fn run_pow_incorrect_ids() {
74        let hint_code = "ids.locs.bit = (ids.prev_locs.exp % PRIME) & 1";
75        let mut vm = vm_with_range_check!();
76        add_segments!(vm, 2);
77        //Initialize ap
78        vm.run_context.ap = 11;
79        //Create incorrect ids
80        let ids_data = ids_data!["locs"];
81        //Execute the hint
82        assert_matches!(
83            run_hint!(vm, ids_data, hint_code),
84            Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "prev_locs"
85        );
86    }
87
88    #[test]
89    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
90    fn run_pow_incorrect_references() {
91        let hint_code = "ids.locs.bit = (ids.prev_locs.exp % PRIME) & 1";
92        let mut vm = vm_with_range_check!();
93        add_segments!(vm, 2);
94        //Initialize fp
95        vm.run_context.fp = 11;
96        //Create hint_data
97        let ids_data = non_continuous_ids_data![("prev_locs", -5), ("locs", -12)];
98        //Execute the hint
99        assert_matches!(
100            run_hint!(vm, ids_data, hint_code),
101            Err(HintError::IdentifierHasNoMember(bx)) if *bx == ("prev_locs".to_string(), "exp".to_string())
102        );
103    }
104
105    #[test]
106    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
107    fn run_pow_prev_locs_exp_is_not_integer() {
108        let hint_code = "ids.locs.bit = (ids.prev_locs.exp % PRIME) & 1";
109        let mut vm = vm_with_range_check!();
110        //Initialize fp
111        vm.run_context.fp = 11;
112        //Create hint_data
113        let ids_data = non_continuous_ids_data![("prev_locs", -5), ("locs", -12)];
114        //Insert ids.prev_locs.exp into memory as a RelocatableValue
115        vm.segments = segments![((1, 10), (1, 11))];
116        add_segments!(vm, 1);
117        //Execute the hint
118        assert_matches!(
119            run_hint!(vm, ids_data, hint_code),
120            Err(HintError::IdentifierHasNoMember(bx)) if *bx == ("prev_locs".to_string(), "exp".to_string())
121        );
122    }
123
124    #[test]
125    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
126    fn run_pow_invalid_memory_insert() {
127        let hint_code = "ids.locs.bit = (ids.prev_locs.exp % PRIME) & 1";
128        let mut vm = vm_with_range_check!();
129        //Initialize ap
130        vm.run_context.fp = 11;
131        //Create hint_data
132        let ids_data = non_continuous_ids_data![("prev_locs", -5), ("locs", 0)];
133        //Insert ids into memory
134        vm.segments = segments![((1, 10), 3), ((1, 11), 3)];
135        //Execute the hint
136        assert_matches!(
137            run_hint!(vm, ids_data, hint_code),
138            Err(HintError::Memory(
139                MemoryError::InconsistentMemory(bx)
140            )) if *bx == (Relocatable::from((1, 11)),
141                    MaybeRelocatable::from(Felt252::from(3)),
142                    MaybeRelocatable::from(Felt252::ONE))
143        );
144    }
145}