Skip to main content

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