cairo_vm/hint_processor/builtin_hint_processor/
pow_utils.rs1use 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
15pub 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 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_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 vm.run_context.ap = 11;
79 let ids_data = ids_data!["locs"];
81 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 vm.run_context.fp = 11;
96 let ids_data = non_continuous_ids_data![("prev_locs", -5), ("locs", -12)];
98 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 vm.run_context.fp = 11;
112 let ids_data = non_continuous_ids_data![("prev_locs", -5), ("locs", -12)];
114 vm.segments = segments![((1, 10), (1, 11))];
116 add_segments!(vm, 1);
117 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 vm.run_context.fp = 11;
131 let ids_data = non_continuous_ids_data![("prev_locs", -5), ("locs", 0)];
133 vm.segments = segments![((1, 10), 3), ((1, 11), 3)];
135 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}