cairo_vm/hint_processor/builtin_hint_processor/vrf/
pack.rs

1use num_bigint::BigInt;
2use num_integer::Integer;
3use num_traits::One;
4
5use crate::hint_processor::builtin_hint_processor::secp::bigint_utils::BigInt3;
6use crate::hint_processor::builtin_hint_processor::secp::secp_utils::SECP_P_V2;
7use crate::hint_processor::hint_processor_definition::HintReference;
8use crate::math_utils::div_mod;
9use crate::serde::deserialize_program::ApTracking;
10use crate::stdlib::collections::HashMap;
11use crate::stdlib::prelude::String;
12use crate::types::exec_scope::ExecutionScopes;
13use crate::vm::errors::hint_errors::HintError;
14use crate::vm::vm_core::VirtualMachine;
15
16/// Implements hint:
17/// ```python
18/// from starkware.cairo.common.cairo_secp.secp_utils import pack
19/// SECP_P=2**255-19
20///
21/// x = pack(ids.x, PRIME) % SECP_P
22/// ```
23pub fn ed25519_is_zero_pack(
24    vm: &mut VirtualMachine,
25    exec_scopes: &mut ExecutionScopes,
26    ids_data: &HashMap<String, HintReference>,
27    ap_tracking: &ApTracking,
28) -> Result<(), HintError> {
29    let x = BigInt3::from_var_name("x", vm, ids_data, ap_tracking)?.pack86();
30    exec_scopes.insert_value("x", x.mod_floor(&SECP_P_V2));
31    exec_scopes.insert_value("SECP_P", SECP_P_V2.clone());
32
33    Ok(())
34}
35
36/// Implements hint:
37/// ```python
38/// from starkware.cairo.common.cairo_secp.secp_utils import pack
39/// SECP_P=2**255-19
40///
41/// value = pack(ids.x, PRIME) % SECP_P
42/// ```
43pub fn ed25519_reduce(
44    vm: &mut VirtualMachine,
45    exec_scopes: &mut ExecutionScopes,
46    ids_data: &HashMap<String, HintReference>,
47    ap_tracking: &ApTracking,
48) -> Result<(), HintError> {
49    let x = BigInt3::from_var_name("x", vm, ids_data, ap_tracking)?.pack86();
50    exec_scopes.insert_value("value", x.mod_floor(&SECP_P_V2));
51    exec_scopes.insert_value("SECP_P", SECP_P_V2.clone());
52
53    Ok(())
54}
55
56/// Implements hint:
57/// ```python
58/// SECP_P=2**255-19
59/// from starkware.python.math_utils import div_mod
60///
61/// value = x_inv = div_mod(1, x, SECP_P)
62/// ```
63pub fn ed25519_is_zero_assign_scope_vars(
64    exec_scopes: &mut ExecutionScopes,
65) -> Result<(), HintError> {
66    let x = exec_scopes.get::<BigInt>("x")?;
67    let x_inv = div_mod(&BigInt::one(), &x, &SECP_P_V2)?;
68    exec_scopes.insert_value("x_inv", x_inv.clone());
69    exec_scopes.insert_value("value", x_inv);
70    exec_scopes.insert_value("SECP_P", SECP_P_V2.clone());
71
72    Ok(())
73}
74
75#[cfg(test)]
76mod test {
77    use crate::any_box;
78    use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor;
79    use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData;
80    use crate::hint_processor::builtin_hint_processor::hint_code;
81    use crate::hint_processor::builtin_hint_processor::secp::secp_utils::SECP_P_V2;
82    use crate::hint_processor::hint_processor_definition::HintProcessorLogic;
83    use crate::hint_processor::hint_processor_definition::HintReference;
84    use crate::stdlib::collections::HashMap;
85    use crate::types::exec_scope::ExecutionScopes;
86    use crate::utils::test_utils::*;
87    use num_bigint::BigInt;
88    use num_traits::One;
89    use num_traits::Zero;
90
91    static SECP_P_D0: i128 = 77371252455336267181195245_i128;
92    static SECP_P_D1: i128 = 77371252455336267181195263_i128;
93    static SECP_P_D2: i128 = 9671406556917033397649407_i128;
94
95    fn assert_is_zero_pack_ed25519_equals(x_d0: i128, x_d1: i128, x_d2: i128, expected: BigInt) {
96        let ids_data = non_continuous_ids_data![("x", 0)];
97
98        let mut vm = vm!();
99        vm.run_context.fp = 0;
100
101        vm.segments = segments![((1, 0), x_d0), ((1, 1), x_d1), ((1, 2), x_d2)];
102
103        let mut exec_scopes = scope![];
104        assert!(run_hint!(
105            vm,
106            ids_data,
107            hint_code::IS_ZERO_PACK_ED25519,
108            &mut exec_scopes
109        )
110        .is_ok());
111
112        check_scope!(
113            &exec_scopes,
114            [("x", expected), ("SECP_P", SECP_P_V2.clone())]
115        );
116    }
117
118    fn assert_reduce_ed25519_equals(x_d0: i128, x_d1: i128, x_d2: i128, expected: BigInt) {
119        let ids_data = non_continuous_ids_data![("x", 0)];
120
121        let mut vm = vm!();
122        vm.run_context.fp = 0;
123
124        vm.segments = segments![((1, 0), x_d0), ((1, 1), x_d1), ((1, 2), x_d2)];
125
126        let mut exec_scopes = scope![];
127
128        assert!(run_hint!(vm, ids_data, hint_code::REDUCE_ED25519, &mut exec_scopes).is_ok());
129
130        check_scope!(
131            &exec_scopes,
132            [("value", expected), ("SECP_P", SECP_P_V2.clone())]
133        );
134    }
135
136    #[test]
137    fn test_is_zero_pack_ed25519_with_zero() {
138        assert_is_zero_pack_ed25519_equals(0, 0, 0, BigInt::zero());
139    }
140
141    #[test]
142    fn test_is_zero_pack_ed25519_with_secp_prime_minus_one() {
143        assert_is_zero_pack_ed25519_equals(
144            SECP_P_D0 - 1,
145            SECP_P_D1,
146            SECP_P_D2,
147            SECP_P_V2.clone() - 1,
148        );
149    }
150
151    #[test]
152    fn test_is_zero_pack_ed25519_with_secp_prime() {
153        assert_is_zero_pack_ed25519_equals(SECP_P_D0, SECP_P_D1, SECP_P_D2, BigInt::zero());
154    }
155
156    #[test]
157    fn test_reduce_ed25519_with_zero() {
158        assert_reduce_ed25519_equals(0, 0, 0, BigInt::zero());
159    }
160
161    #[test]
162    fn test_reduce_ed25519_with_prime_minus_one() {
163        assert_reduce_ed25519_equals(SECP_P_D0 - 1, SECP_P_D1, SECP_P_D2, SECP_P_V2.clone() - 1);
164    }
165
166    #[test]
167    fn test_reduce_ed25519_with_prime() {
168        assert_reduce_ed25519_equals(SECP_P_D0, SECP_P_D1, SECP_P_D2, BigInt::zero());
169    }
170
171    #[test]
172    fn test_is_zero_assign_scope_vars_ed25519_with_one() {
173        let mut vm = vm!();
174        vm.run_context.fp = 0;
175
176        let mut exec_scopes = scope![("x", BigInt::one())];
177
178        assert!(run_hint!(
179            vm,
180            HashMap::default(),
181            hint_code::IS_ZERO_ASSIGN_SCOPE_VARS_ED25519,
182            &mut exec_scopes
183        )
184        .is_ok());
185
186        check_scope!(
187            &exec_scopes,
188            [
189                ("x_inv", BigInt::one()),
190                ("value", BigInt::one()),
191                ("SECP_P", SECP_P_V2.clone())
192            ]
193        );
194    }
195}