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 11 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
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,19 @@
* 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 hints `NewHint#35` and `NewHint#36` [#975](https://github.com/lambdaclass/cairo-rs/issues/975)

`BuiltinHintProcessor` now supports the following hint:
Expand Down Expand Up @@ -879,4 +892,4 @@
* `pub fn from_vm_error(runner: &CairoRunner, error: VirtualMachineError, pc: usize) -> Self` is now `pub fn from_vm_error(runner: &CairoRunner, vm: &VirtualMachine, error: VirtualMachineError) -> Self`
* `pub fn get_location(pc: &usize, runner: &CairoRunner) -> Option<Location>` is now `pub fn get_location(pc: usize, runner: &CairoRunner) -> Option<Location>`
* `pub fn decode_instruction(encoded_instr: i64, mut imm: Option<BigInt>) -> Result<instruction::Instruction, VirtualMachineError>` is now `pub fn decode_instruction(encoded_instr: i64, mut imm: Option<&BigInt>) -> Result<instruction::Instruction, VirtualMachineError>`
* `VmExcepion` field's string format now mirror their cairo-lang conterparts.
* `VmExcepion` field's string format now mirror their cairo-lang conterparts.
Oppen marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -43,8 +43,8 @@ use crate::{
ec_utils::{
compute_doubling_slope, compute_slope, compute_slope_secp_p, di_bit,
ec_double_assign_new_x, ec_double_assign_new_y, ec_mul_inner, ec_negate,
fast_ec_add_assign_new_x, fast_ec_add_assign_new_y, import_secp256r1_p,
quad_bit,
fast_ec_add_assign_new_x, 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 @@ -586,6 +586,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 @@ -894,6 +894,12 @@ ids.remainder.d1 = remainder_split[1]
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(crate) const GET_SQUARE_ROOT: &str =
"from starkware.python.math_utils import is_quad_residue, sqrt

Expand Down
24 changes: 23 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 @@ -296,6 +300,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
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,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
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::<BigInt>("N")?;

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

exec_scopes.insert_value("value", value);
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 @@ -779,6 +779,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