Skip to content

Commit

Permalink
Newhint#17 & Newhint#18 imports of SECP256R1_ALPHA and SECP256R1_N (#…
Browse files Browse the repository at this point in the history
…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 <mario.rugiero@lambdaclass.com>

* merge

* add unit test for import alpha

---------

Co-authored-by: Mario Rugiero <mario.rugiero@lambdaclass.com>
  • Loading branch information
mfachal and Oppen committed Apr 26, 2023
1 parent 327ee7d commit 47e7b34
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 6 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,19 @@ Add missing hint on vrf.json lib [#1053](https://github.com/lambdaclass/cairo-rs
* Remove duplicated tests in cairo_run_test
* 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>`

* Add missing hints on cairo_secp lib [#1026](https://github.com/lambdaclass/cairo-rs/pull/1026):

`BuiltinHintProcessor` now supports the following hints:

```python
from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA
```
and:

```python
from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_N as N
```

* Add missing hint on vrf.json lib [#1043](https://github.com/lambdaclass/cairo-rs/pull/1043):

`BuiltinHintProcessor` now supports the following hint:
Expand Down
75 changes: 75 additions & 0 deletions cairo_programs/secp256r1_div_mod_n.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
%builtins range_check

// Sources: https://github.com/myBraavos/efficient-secp256r1/blob/main/src/secp256r1/signature.cairo#L48
// Sources: https://github.com/myBraavos/efficient-secp256r1/blob/main/src/secp256r1/ec.cairo#L32

from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, BASE, bigint_mul

// N = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
const N0 = 0x179e84f3b9cac2fc632551;
const N1 = 0x3ffffffffffef39beab69c;
const N2 = 0xffffffff00000000fffff;

func div_mod_n{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) {
%{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_N as N %}
// Hint 24
%{
from starkware.cairo.common.cairo_secp.secp_utils import pack
from starkware.python.math_utils import div_mod, safe_div

a = pack(ids.a, PRIME)
b = pack(ids.b, PRIME)
value = res = div_mod(a, b, N)
%}
let (res) = nondet_bigint3();
// Hint 25
%{
value = k_plus_one = safe_div(res * b - a, N) + 1
%}
let (k_plus_one) = nondet_bigint3();
let k = BigInt3(d0=k_plus_one.d0 - 1, d1=k_plus_one.d1, d2=k_plus_one.d2);

let (res_b) = bigint_mul(res, b);
let n = BigInt3(N0, N1, N2);
let (k_n) = bigint_mul(k, n);

// We should now have res_b = k_n + a. Since the numbers are in unreduced form,
// we should handle the carry.

tempvar carry1 = (res_b.d0 - k_n.d0 - a.d0) / BASE;
assert [range_check_ptr + 0] = carry1 + 2 ** 127;

tempvar carry2 = (res_b.d1 - k_n.d1 - a.d1 + carry1) / BASE;
assert [range_check_ptr + 1] = carry2 + 2 ** 127;

tempvar carry3 = (res_b.d2 - k_n.d2 - a.d2 + carry2) / BASE;
assert [range_check_ptr + 2] = carry3 + 2 ** 127;

tempvar carry4 = (res_b.d3 - k_n.d3 + carry3) / BASE;
assert [range_check_ptr + 3] = carry4 + 2 ** 127;

assert res_b.d4 - k_n.d4 + carry4 = 0;

let range_check_ptr = range_check_ptr + 4;

return (res=res);
}

func test_div_mod_n{range_check_ptr: felt}() {
let a: BigInt3 = BigInt3(100, 99, 98);
let b: BigInt3 = BigInt3(10, 9, 8);

let (res) = div_mod_n(a, b);

assert res = BigInt3(
17710125265123803206911742, 47938808641831879622633720, 16714845192957993827873659
);

return ();
}

func main{range_check_ptr: felt}() {
test_div_mod_n();

return ();
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ use crate::{
bigint_utils::{bigint_to_uint256, hi_max_bitlen, nondet_bigint3},
ec_utils::{
compute_doubling_slope, compute_slope, di_bit, fast_ec_add_assign_new_x,
fast_ec_add_assign_new_y, import_secp256r1_p, quad_bit,
fast_ec_add_assign_new_y, import_secp256r1_alpha, import_secp256r1_n,
import_secp256r1_p, quad_bit,
},
field_utils::{
is_zero_assign_scope_variables, is_zero_assign_scope_variables_external_const,
Expand Down Expand Up @@ -673,6 +674,8 @@ impl HintProcessor for BuiltinHintProcessor {
hint_code::UINT256_MUL_DIV_MOD => {
uint256_mul_div_mod(vm, &hint_data.ids_data, &hint_data.ap_tracking)
}
hint_code::IMPORT_SECP256R1_ALPHA => import_secp256r1_alpha(exec_scopes),
hint_code::IMPORT_SECP256R1_N => import_secp256r1_n(exec_scopes),
hint_code::UINT512_UNSIGNED_DIV_REM => {
uint512_unsigned_div_rem(vm, &hint_data.ids_data, &hint_data.ap_tracking)
}
Expand Down
6 changes: 6 additions & 0 deletions src/hint_processor/builtin_hint_processor/hint_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,12 @@ ids.remainder.d2 = remainder_split[2]"#;

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

pub const IMPORT_SECP256R1_ALPHA: &str =
"from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA";

pub const IMPORT_SECP256R1_N: &str =
"from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_N as N";

pub const UINT384_GET_SQUARE_ROOT: &str =
"from starkware.python.math_utils import is_quad_residue, sqrt
Expand Down
47 changes: 46 additions & 1 deletion src/hint_processor/builtin_hint_processor/secp/ec_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use crate::{
get_integer_from_var_name, get_relocatable_from_var_name,
insert_value_from_var_name, insert_value_into_ap,
},
secp::{bigint_utils::BigInt3, secp_utils::SECP_P},
secp::{
bigint_utils::BigInt3,
secp_utils::{SECP256R1_ALPHA, SECP256R1_N, SECP_P},
},
},
hint_processor_definition::HintReference,
},
Expand All @@ -18,6 +21,7 @@ use crate::{
use felt::Felt252;
use num_bigint::BigInt;
use num_integer::Integer;

use num_traits::{One, ToPrimitive, Zero};

use super::secp_utils::SECP256R1_P;
Expand Down Expand Up @@ -333,6 +337,24 @@ pub fn ec_mul_inner(
insert_value_into_ap(vm, scalar)
}

/*
Implements hint:
%{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA %}
*/
pub fn import_secp256r1_alpha(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> {
exec_scopes.insert_value("ALPHA", SECP256R1_ALPHA.clone());
Ok(())
}

/*
Implements hint:
%{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_N as N %}
*/
pub fn import_secp256r1_n(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> {
exec_scopes.insert_value("N", SECP256R1_N.clone());
Ok(())
}

/*
Implements hint:
%{
Expand Down Expand Up @@ -435,6 +457,7 @@ mod tests {
};
use assert_matches::assert_matches;

use num_bigint::BigUint;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::*;

Expand Down Expand Up @@ -1142,4 +1165,26 @@ mod tests {
// Check hint memory inserts
check_memory![vm.segments.memory, ((1, 3), 2)];
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn run_import_secp256r1_alpha() {
let hint_code = "from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA";
let mut vm = vm_with_range_check!();

//Initialize fp
vm.run_context.fp = 1;
//Create hint_data
let ids_data = ids_data!["point"];
let mut exec_scopes = ExecutionScopes::new();
//Execute the hint
assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(()));
//Check 'ALPHA' is defined in the vm scope
assert_matches!(
exec_scopes.get::<BigUint>("ALPHA"),
Ok(x) if x == biguint_str!(
"115792089210356248762697446949407573530086143415290314195533631308867097853948"
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ lazy_static! {
"115792089210356248762697446949407573530086143415290314195533631308867097853951"
).unwrap();
//SECP256R1_N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
pub(crate) static ref SECP256R1_N: BigUint = BigUint::from_str(
pub(crate) static ref SECP256R1_N: BigInt = BigInt::from_str(
"115792089210356248762697446949407573529996955224135760342422259061068512044369"
).unwrap();
//SECP256R1_ALPHA = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC
Expand Down
10 changes: 7 additions & 3 deletions src/hint_processor/builtin_hint_processor/secp/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ pub fn div_mod_n_safe_div(
let b = exec_scopes.get_ref::<BigInt>(b_alias)?;
let res = exec_scopes.get_ref::<BigInt>("res")?;

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

let value = safe_div_bigint(&(res * b - a), &n)?.add(to_add);

exec_scopes.insert_value("value", value);
Ok(())
Expand Down Expand Up @@ -151,6 +153,7 @@ pub fn pack_modn_div_modn(
let value = div_mod(&x, &s, &N);
exec_scopes.insert_value("x", x);
exec_scopes.insert_value("s", s);
exec_scopes.insert_value("N", N.clone());
exec_scopes.insert_value("value", value.clone());
exec_scopes.insert_value("res", value);
Ok(())
Expand Down Expand Up @@ -218,7 +221,8 @@ mod tests {
let mut exec_scopes = scope![
("a", BigInt::zero()),
("b", BigInt::one()),
("res", BigInt::one())
("res", BigInt::one()),
("N", N.clone())
];
assert_matches!(
div_mod_n_safe_div(
Expand Down Expand Up @@ -308,6 +312,7 @@ mod tests {
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn pack_modn_div_modn_ok() {
let hint_code = hint_code::PACK_MODN_DIV_MODN;
let mut exec_scopes = scope![("N", N.clone())];
let mut vm = vm!();

vm.segments = segments![
Expand All @@ -320,7 +325,6 @@ mod tests {
];
vm.run_context.fp = 3;
let ids_data = non_continuous_ids_data![("x", -3), ("s", 0)];
let mut exec_scopes = ExecutionScopes::new();
assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(()));
assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "x", "s", 0), Ok(()));
}
Expand Down
7 changes: 7 additions & 0 deletions src/tests/cairo_run_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,13 @@ fn is_zero() {
run_program_simple(program_data.as_slice());
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn cairo_run_secp256r1_div_mod_n() {
let program_data = include_bytes!("../../cairo_programs/secp256r1_div_mod_n.json");
run_program_simple(program_data.as_slice());
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn is_zero_pack() {
Expand Down

0 comments on commit 47e7b34

Please sign in to comment.