Skip to content

Commit 47e7b34

Browse files
mfachalOppen
andauthored
Newhint#17 & Newhint#18 imports of SECP256R1_ALPHA and SECP256R1_N (#1026)
* WIP newhint#17 and newhint#18 * WIP cairo program * add secp256r1 testing programs and newhint#17 and #18 * update changelog * remove program using unimplemented hint * add correct constants to test program * fix broken test when executing hint #25 with different context * Update CHANGELOG.md Co-authored-by: Mario Rugiero <[email protected]> * merge * add unit test for import alpha --------- Co-authored-by: Mario Rugiero <[email protected]>
1 parent 327ee7d commit 47e7b34

File tree

8 files changed

+159
-6
lines changed

8 files changed

+159
-6
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,19 @@ Add missing hint on vrf.json lib [#1053](https://github.com/lambdaclass/cairo-rs
354354
* Remove duplicated tests in cairo_run_test
355355
* BREAKING CHANGE: `MemorySegmentManager.get_memory_holes` now also receives the amount of builtins in the vm. Signature is now `pub fn get_memory_holes(&self, builtin_count: usize) -> Result<usize, MemoryError>`
356356

357+
* Add missing hints on cairo_secp lib [#1026](https://github.com/lambdaclass/cairo-rs/pull/1026):
358+
359+
`BuiltinHintProcessor` now supports the following hints:
360+
361+
```python
362+
from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA
363+
```
364+
and:
365+
366+
```python
367+
from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_N as N
368+
```
369+
357370
* Add missing hint on vrf.json lib [#1043](https://github.com/lambdaclass/cairo-rs/pull/1043):
358371

359372
`BuiltinHintProcessor` now supports the following hint:
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
%builtins range_check
2+
3+
// Sources: https://github.com/myBraavos/efficient-secp256r1/blob/main/src/secp256r1/signature.cairo#L48
4+
// Sources: https://github.com/myBraavos/efficient-secp256r1/blob/main/src/secp256r1/ec.cairo#L32
5+
6+
from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, BASE, bigint_mul
7+
8+
// N = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
9+
const N0 = 0x179e84f3b9cac2fc632551;
10+
const N1 = 0x3ffffffffffef39beab69c;
11+
const N2 = 0xffffffff00000000fffff;
12+
13+
func div_mod_n{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) {
14+
%{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_N as N %}
15+
// Hint 24
16+
%{
17+
from starkware.cairo.common.cairo_secp.secp_utils import pack
18+
from starkware.python.math_utils import div_mod, safe_div
19+
20+
a = pack(ids.a, PRIME)
21+
b = pack(ids.b, PRIME)
22+
value = res = div_mod(a, b, N)
23+
%}
24+
let (res) = nondet_bigint3();
25+
// Hint 25
26+
%{
27+
value = k_plus_one = safe_div(res * b - a, N) + 1
28+
%}
29+
let (k_plus_one) = nondet_bigint3();
30+
let k = BigInt3(d0=k_plus_one.d0 - 1, d1=k_plus_one.d1, d2=k_plus_one.d2);
31+
32+
let (res_b) = bigint_mul(res, b);
33+
let n = BigInt3(N0, N1, N2);
34+
let (k_n) = bigint_mul(k, n);
35+
36+
// We should now have res_b = k_n + a. Since the numbers are in unreduced form,
37+
// we should handle the carry.
38+
39+
tempvar carry1 = (res_b.d0 - k_n.d0 - a.d0) / BASE;
40+
assert [range_check_ptr + 0] = carry1 + 2 ** 127;
41+
42+
tempvar carry2 = (res_b.d1 - k_n.d1 - a.d1 + carry1) / BASE;
43+
assert [range_check_ptr + 1] = carry2 + 2 ** 127;
44+
45+
tempvar carry3 = (res_b.d2 - k_n.d2 - a.d2 + carry2) / BASE;
46+
assert [range_check_ptr + 2] = carry3 + 2 ** 127;
47+
48+
tempvar carry4 = (res_b.d3 - k_n.d3 + carry3) / BASE;
49+
assert [range_check_ptr + 3] = carry4 + 2 ** 127;
50+
51+
assert res_b.d4 - k_n.d4 + carry4 = 0;
52+
53+
let range_check_ptr = range_check_ptr + 4;
54+
55+
return (res=res);
56+
}
57+
58+
func test_div_mod_n{range_check_ptr: felt}() {
59+
let a: BigInt3 = BigInt3(100, 99, 98);
60+
let b: BigInt3 = BigInt3(10, 9, 8);
61+
62+
let (res) = div_mod_n(a, b);
63+
64+
assert res = BigInt3(
65+
17710125265123803206911742, 47938808641831879622633720, 16714845192957993827873659
66+
);
67+
68+
return ();
69+
}
70+
71+
func main{range_check_ptr: felt}() {
72+
test_div_mod_n();
73+
74+
return ();
75+
}

src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ use crate::{
5252
bigint_utils::{bigint_to_uint256, hi_max_bitlen, nondet_bigint3},
5353
ec_utils::{
5454
compute_doubling_slope, compute_slope, di_bit, fast_ec_add_assign_new_x,
55-
fast_ec_add_assign_new_y, import_secp256r1_p, quad_bit,
55+
fast_ec_add_assign_new_y, import_secp256r1_alpha, import_secp256r1_n,
56+
import_secp256r1_p, quad_bit,
5657
},
5758
field_utils::{
5859
is_zero_assign_scope_variables, is_zero_assign_scope_variables_external_const,
@@ -673,6 +674,8 @@ impl HintProcessor for BuiltinHintProcessor {
673674
hint_code::UINT256_MUL_DIV_MOD => {
674675
uint256_mul_div_mod(vm, &hint_data.ids_data, &hint_data.ap_tracking)
675676
}
677+
hint_code::IMPORT_SECP256R1_ALPHA => import_secp256r1_alpha(exec_scopes),
678+
hint_code::IMPORT_SECP256R1_N => import_secp256r1_n(exec_scopes),
676679
hint_code::UINT512_UNSIGNED_DIV_REM => {
677680
uint512_unsigned_div_rem(vm, &hint_data.ids_data, &hint_data.ap_tracking)
678681
}

src/hint_processor/builtin_hint_processor/hint_code.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,12 @@ ids.remainder.d2 = remainder_split[2]"#;
10491049

10501050
pub const UINT384_SIGNED_NN: &str = "memory[ap] = 1 if 0 <= (ids.a.d2 % PRIME) < 2 ** 127 else 0";
10511051

1052+
pub const IMPORT_SECP256R1_ALPHA: &str =
1053+
"from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA";
1054+
1055+
pub const IMPORT_SECP256R1_N: &str =
1056+
"from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_N as N";
1057+
10521058
pub const UINT384_GET_SQUARE_ROOT: &str =
10531059
"from starkware.python.math_utils import is_quad_residue, sqrt
10541060

src/hint_processor/builtin_hint_processor/secp/ec_utils.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ use crate::{
55
get_integer_from_var_name, get_relocatable_from_var_name,
66
insert_value_from_var_name, insert_value_into_ap,
77
},
8-
secp::{bigint_utils::BigInt3, secp_utils::SECP_P},
8+
secp::{
9+
bigint_utils::BigInt3,
10+
secp_utils::{SECP256R1_ALPHA, SECP256R1_N, SECP_P},
11+
},
912
},
1013
hint_processor_definition::HintReference,
1114
},
@@ -18,6 +21,7 @@ use crate::{
1821
use felt::Felt252;
1922
use num_bigint::BigInt;
2023
use num_integer::Integer;
24+
2125
use num_traits::{One, ToPrimitive, Zero};
2226

2327
use super::secp_utils::SECP256R1_P;
@@ -333,6 +337,24 @@ pub fn ec_mul_inner(
333337
insert_value_into_ap(vm, scalar)
334338
}
335339

340+
/*
341+
Implements hint:
342+
%{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA %}
343+
*/
344+
pub fn import_secp256r1_alpha(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> {
345+
exec_scopes.insert_value("ALPHA", SECP256R1_ALPHA.clone());
346+
Ok(())
347+
}
348+
349+
/*
350+
Implements hint:
351+
%{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_N as N %}
352+
*/
353+
pub fn import_secp256r1_n(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> {
354+
exec_scopes.insert_value("N", SECP256R1_N.clone());
355+
Ok(())
356+
}
357+
336358
/*
337359
Implements hint:
338360
%{
@@ -435,6 +457,7 @@ mod tests {
435457
};
436458
use assert_matches::assert_matches;
437459

460+
use num_bigint::BigUint;
438461
#[cfg(target_arch = "wasm32")]
439462
use wasm_bindgen_test::*;
440463

@@ -1142,4 +1165,26 @@ mod tests {
11421165
// Check hint memory inserts
11431166
check_memory![vm.segments.memory, ((1, 3), 2)];
11441167
}
1168+
1169+
#[test]
1170+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1171+
fn run_import_secp256r1_alpha() {
1172+
let hint_code = "from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA";
1173+
let mut vm = vm_with_range_check!();
1174+
1175+
//Initialize fp
1176+
vm.run_context.fp = 1;
1177+
//Create hint_data
1178+
let ids_data = ids_data!["point"];
1179+
let mut exec_scopes = ExecutionScopes::new();
1180+
//Execute the hint
1181+
assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(()));
1182+
//Check 'ALPHA' is defined in the vm scope
1183+
assert_matches!(
1184+
exec_scopes.get::<BigUint>("ALPHA"),
1185+
Ok(x) if x == biguint_str!(
1186+
"115792089210356248762697446949407573530086143415290314195533631308867097853948"
1187+
)
1188+
);
1189+
}
11451190
}

src/hint_processor/builtin_hint_processor/secp/secp_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ lazy_static! {
6161
"115792089210356248762697446949407573530086143415290314195533631308867097853951"
6262
).unwrap();
6363
//SECP256R1_N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
64-
pub(crate) static ref SECP256R1_N: BigUint = BigUint::from_str(
64+
pub(crate) static ref SECP256R1_N: BigInt = BigInt::from_str(
6565
"115792089210356248762697446949407573529996955224135760342422259061068512044369"
6666
).unwrap();
6767
//SECP256R1_ALPHA = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC

src/hint_processor/builtin_hint_processor/secp/signature.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ pub fn div_mod_n_safe_div(
8181
let b = exec_scopes.get_ref::<BigInt>(b_alias)?;
8282
let res = exec_scopes.get_ref::<BigInt>("res")?;
8383

84-
let value = safe_div_bigint(&(res * b - a), &N)?.add(to_add);
84+
let n = exec_scopes.get("N")?;
85+
86+
let value = safe_div_bigint(&(res * b - a), &n)?.add(to_add);
8587

8688
exec_scopes.insert_value("value", value);
8789
Ok(())
@@ -151,6 +153,7 @@ pub fn pack_modn_div_modn(
151153
let value = div_mod(&x, &s, &N);
152154
exec_scopes.insert_value("x", x);
153155
exec_scopes.insert_value("s", s);
156+
exec_scopes.insert_value("N", N.clone());
154157
exec_scopes.insert_value("value", value.clone());
155158
exec_scopes.insert_value("res", value);
156159
Ok(())
@@ -218,7 +221,8 @@ mod tests {
218221
let mut exec_scopes = scope![
219222
("a", BigInt::zero()),
220223
("b", BigInt::one()),
221-
("res", BigInt::one())
224+
("res", BigInt::one()),
225+
("N", N.clone())
222226
];
223227
assert_matches!(
224228
div_mod_n_safe_div(
@@ -308,6 +312,7 @@ mod tests {
308312
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
309313
fn pack_modn_div_modn_ok() {
310314
let hint_code = hint_code::PACK_MODN_DIV_MODN;
315+
let mut exec_scopes = scope![("N", N.clone())];
311316
let mut vm = vm!();
312317

313318
vm.segments = segments![
@@ -320,7 +325,6 @@ mod tests {
320325
];
321326
vm.run_context.fp = 3;
322327
let ids_data = non_continuous_ids_data![("x", -3), ("s", 0)];
323-
let mut exec_scopes = ExecutionScopes::new();
324328
assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(()));
325329
assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "x", "s", 0), Ok(()));
326330
}

src/tests/cairo_run_test.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,13 @@ fn is_zero() {
793793
run_program_simple(program_data.as_slice());
794794
}
795795

796+
#[test]
797+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
798+
fn cairo_run_secp256r1_div_mod_n() {
799+
let program_data = include_bytes!("../../cairo_programs/secp256r1_div_mod_n.json");
800+
run_program_simple(program_data.as_slice());
801+
}
802+
796803
#[test]
797804
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
798805
fn is_zero_pack() {

0 commit comments

Comments
 (0)