Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Newhint#17 & Newhint#18 imports of SECP256R1_ALPHA and SECP256R1_N #1026

Merged
merged 19 commits into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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(
fmoletta marked this conversation as resolved.
Show resolved Hide resolved
"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