From 2a3314eae7ba034c522ec19ca46988c78bf28304 Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Wed, 19 Apr 2023 17:28:45 -0300 Subject: [PATCH 01/10] WIP newhint#17 and newhint#18 --- .../builtin_hint_processor_definition.rs | 8 +++++++- .../builtin_hint_processor/hint_code.rs | 6 ++++++ .../builtin_hint_processor/secp/ec_utils.rs | 16 +++++++++++++++- .../builtin_hint_processor/secp/secp_utils.rs | 18 ++++++++++++++++-- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs index 76db67251d..c0a808c4cd 100644 --- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs +++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs @@ -79,7 +79,10 @@ use felt::Felt252; #[cfg(feature = "skip_next_instruction_hint")] use crate::hint_processor::builtin_hint_processor::skip_next_instruction::skip_next_instruction; -use super::uint384_extension::unsigned_div_rem_uint768_by_uint384; +use super::{ + secp::ec_utils::{import_secp256r1_alpha, import_secp256r1_n}, + uint384_extension::unsigned_div_rem_uint768_by_uint384, +}; pub struct HintProcessorData { pub code: String, @@ -531,6 +534,9 @@ 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), + #[cfg(feature = "skip_next_instruction_hint")] hint_code::SKIP_NEXT_INSTRUCTION => skip_next_instruction(vm), code => Err(HintError::UnknownHint(code.to_string())), diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index 2e14f1ca65..598c09b061 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -815,5 +815,11 @@ 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"; + #[cfg(feature = "skip_next_instruction_hint")] pub const SKIP_NEXT_INSTRUCTION: &str = "skip_next_instruction()"; diff --git a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs index dc5822d28f..f4a86589fa 100644 --- a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs @@ -20,7 +20,10 @@ use num_bigint::BigInt; use num_integer::Integer; use num_traits::{One, Zero}; -use super::{bigint_utils::BigInt3, secp_utils::SECP_P}; +use super::{ + bigint_utils::BigInt3, + secp_utils::{SECP256R1_ALPHA, SECP256R1_N, SECP_P}, +}; #[derive(Debug, PartialEq)] struct EcPoint<'a> { @@ -272,6 +275,17 @@ pub fn ec_mul_inner( insert_value_into_ap(vm, scalar) } +pub fn import_secp256r1_alpha(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> { + exec_scopes.insert_value("ALPHA", SECP256R1_ALPHA.clone()); + + Ok(()) +} + +pub fn import_secp256r1_n(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> { + exec_scopes.insert_value("N", SECP256R1_N.clone()); + Ok(()) +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs b/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs index fc0411bc13..32d72e9c2c 100644 --- a/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs @@ -39,8 +39,22 @@ lazy_static! { // N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 pub(crate) static ref N: BigInt = BigInt::from_str( "115792089237316195423570985008687907852837564279074904382605163141518161494337" - ) -.unwrap(); + ).unwrap(); +} +// Constants in package "starkware.cairo.common.cairo_secp.secp256r1_utils" +lazy_static! { + //SECP256R1_P = 2**256 - 2**224 + 2**192 + 2**96 - 1 + pub(crate) static ref SECP256R1_P: BigInt = BigInt::from_str( + "115792089210356248762697446949407573530086143415290314195533631308867097853951" + ).unwrap(); + //SECP256R1_N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 + pub(crate) static ref SECP256R1_N: BigUint = BigUint::from_str( + "115792089210356248762697446949407573529996955224135760342422259061068512044369" + ).unwrap(); + //SECP256R1_ALPHA = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC + pub(crate) static ref SECP256R1_ALPHA: BigUint = BigUint::from_str( + "115792089210356248762697446949407573530086143415290314195533631308867097853948" + ).unwrap(); } /* From af18fc9b1e1d1f5ac5ddbbf753c461bc4ca1288f Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Wed, 19 Apr 2023 18:07:53 -0300 Subject: [PATCH 02/10] WIP cairo program --- .../doubling_slope_and_div_mod_n.cairo | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 cairo_programs/doubling_slope_and_div_mod_n.cairo diff --git a/cairo_programs/doubling_slope_and_div_mod_n.cairo b/cairo_programs/doubling_slope_and_div_mod_n.cairo new file mode 100644 index 0000000000..98d9560c8d --- /dev/null +++ b/cairo_programs/doubling_slope_and_div_mod_n.cairo @@ -0,0 +1,78 @@ +%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 + +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 %} + %{ + 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(); + + %{ + 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 compute_doubling_slope{range_check_ptr}(point: EcPoint) -> (slope: BigInt3) { + // Note that y cannot be zero: assume that it is, then point = -point, so 2 * point = 0, which + // contradicts the fact that the size of the curve is odd. + %{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P %} + %{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA %} + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + from starkware.python.math_utils import ec_double_slope + + # Compute the slope. + x = pack(ids.point.x, PRIME) + y = pack(ids.point.y, PRIME) + value = slope = ec_double_slope(point=(x, y), alpha=ALPHA, p=SECP_P) + %} + let (slope: BigInt3) = nondet_bigint3(); + + let (x_sqr: UnreducedBigInt3) = unreduced_sqr(point.x); + let (slope_y: UnreducedBigInt3) = unreduced_mul(slope, point.y); + verify_zero( + UnreducedBigInt3( + d0=3 * x_sqr.d0 + A0 - 2 * slope_y.d0, + d1=3 * x_sqr.d1 + A1 - 2 * slope_y.d1, + d2=3 * x_sqr.d2 + A2 - 2 * slope_y.d2, + ), + ); + + return (slope=slope); +} From 6f52d05f0221280963901445d53114b4fe55285d Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Thu, 20 Apr 2023 16:37:11 -0300 Subject: [PATCH 03/10] add secp256r1 testing programs and newhint#17 and #18 --- .../doubling_slope_and_div_mod_n.cairo | 78 ------------------- .../secp256r1_compute_doubling_slope.cairo | 33 ++++++++ cairo_programs/secp256r1_div_mod_n.cairo | 44 +++++++++++ .../builtin_hint_processor/secp/secp_utils.rs | 2 +- src/tests/cairo_run_test.rs | 7 ++ 5 files changed, 85 insertions(+), 79 deletions(-) delete mode 100644 cairo_programs/doubling_slope_and_div_mod_n.cairo create mode 100644 cairo_programs/secp256r1_compute_doubling_slope.cairo create mode 100644 cairo_programs/secp256r1_div_mod_n.cairo diff --git a/cairo_programs/doubling_slope_and_div_mod_n.cairo b/cairo_programs/doubling_slope_and_div_mod_n.cairo deleted file mode 100644 index 98d9560c8d..0000000000 --- a/cairo_programs/doubling_slope_and_div_mod_n.cairo +++ /dev/null @@ -1,78 +0,0 @@ -%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 - -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 %} - %{ - 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(); - - %{ - 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 compute_doubling_slope{range_check_ptr}(point: EcPoint) -> (slope: BigInt3) { - // Note that y cannot be zero: assume that it is, then point = -point, so 2 * point = 0, which - // contradicts the fact that the size of the curve is odd. - %{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P %} - %{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA %} - %{ - from starkware.cairo.common.cairo_secp.secp_utils import pack - from starkware.python.math_utils import ec_double_slope - - # Compute the slope. - x = pack(ids.point.x, PRIME) - y = pack(ids.point.y, PRIME) - value = slope = ec_double_slope(point=(x, y), alpha=ALPHA, p=SECP_P) - %} - let (slope: BigInt3) = nondet_bigint3(); - - let (x_sqr: UnreducedBigInt3) = unreduced_sqr(point.x); - let (slope_y: UnreducedBigInt3) = unreduced_mul(slope, point.y); - verify_zero( - UnreducedBigInt3( - d0=3 * x_sqr.d0 + A0 - 2 * slope_y.d0, - d1=3 * x_sqr.d1 + A1 - 2 * slope_y.d1, - d2=3 * x_sqr.d2 + A2 - 2 * slope_y.d2, - ), - ); - - return (slope=slope); -} diff --git a/cairo_programs/secp256r1_compute_doubling_slope.cairo b/cairo_programs/secp256r1_compute_doubling_slope.cairo new file mode 100644 index 0000000000..80721367a3 --- /dev/null +++ b/cairo_programs/secp256r1_compute_doubling_slope.cairo @@ -0,0 +1,33 @@ +%builtins range_check + +// Source: https://github.com/myBraavos/efficient-secp256r1/blob/main/src/secp256r1/ec.cairo#L32 + +func compute_doubling_slope{range_check_ptr}(point: EcPoint) -> (slope: BigInt3) { + // Note that y cannot be zero: assume that it is, then point = -point, so 2 * point = 0, which + // contradicts the fact that the size of the curve is odd. + %{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P %} + %{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA %} + // Hint #19 + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + from starkware.python.math_utils import ec_double_slope + + # Compute the slope. + x = pack(ids.point.x, PRIME) + y = pack(ids.point.y, PRIME) + value = slope = ec_double_slope(point=(x, y), alpha=ALPHA, p=SECP_P) + %} + let (slope: BigInt3) = nondet_bigint3(); + + let (x_sqr: UnreducedBigInt3) = unreduced_sqr(point.x); + let (slope_y: UnreducedBigInt3) = unreduced_mul(slope, point.y); + verify_zero( + UnreducedBigInt3( + d0=3 * x_sqr.d0 + A0 - 2 * slope_y.d0, + d1=3 * x_sqr.d1 + A1 - 2 * slope_y.d1, + d2=3 * x_sqr.d2 + A2 - 2 * slope_y.d2, + ), + ); + + return (slope=slope); +} diff --git a/cairo_programs/secp256r1_div_mod_n.cairo b/cairo_programs/secp256r1_div_mod_n.cairo new file mode 100644 index 0000000000..077ff849d1 --- /dev/null +++ b/cairo_programs/secp256r1_div_mod_n.cairo @@ -0,0 +1,44 @@ +%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.alloc import alloc +from starkware.cairo.common.bitwise import bitwise_and +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.cairo_secp.bigint import ( + BASE, + BigInt3, + UnreducedBigInt3, + bigint_mul, + nondet_bigint3, +) +from starkware.cairo.common.cairo_secp.ec import EcPoint +from starkware.cairo.common.math import assert_nn, assert_nn_le, assert_not_zero, unsigned_div_rem +from starkware.cairo.common.math_cmp import RC_BOUND +from starkware.cairo.common.uint256 import Uint256 + +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 %} + %{ + 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(); + + return (res=res); +} + +func main{range_check_ptr}(){ + let x = BigInt3(235, 522, 111); + let y = BigInt3(1323, 15124, 796759); + + let a = div_mod_n(x, y); + assert a = a; + return (); + +} diff --git a/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs b/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs index 32d72e9c2c..99beefbe4b 100644 --- a/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs @@ -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( "115792089210356248762697446949407573529996955224135760342422259061068512044369" ).unwrap(); //SECP256R1_ALPHA = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs index 4e42fe4b4b..65e7e5b30a 100644 --- a/src/tests/cairo_run_test.rs +++ b/src/tests/cairo_run_test.rs @@ -1343,3 +1343,10 @@ fn cairo_run_is_zero() { let program_data = include_bytes!("../../cairo_programs/is_zero.json"); 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()); +} From 591fde73041e4091ebb7559f964079f7cbbcffeb Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Fri, 21 Apr 2023 16:31:31 -0300 Subject: [PATCH 04/10] update changelog --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23858c7600..36c7357689 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,20 @@ * 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` +* 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 uint256_improvements lib [#1025](https://github.com/lambdaclass/cairo-rs/pull/1025): `BuiltinHintProcessor` now supports the following hint: From 25fd1df948c307c4440f524b8006ed0bb18b34db Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Fri, 21 Apr 2023 16:37:02 -0300 Subject: [PATCH 05/10] remove program using unimplemented hint --- .../secp256r1_compute_doubling_slope.cairo | 33 ------------------- 1 file changed, 33 deletions(-) delete mode 100644 cairo_programs/secp256r1_compute_doubling_slope.cairo diff --git a/cairo_programs/secp256r1_compute_doubling_slope.cairo b/cairo_programs/secp256r1_compute_doubling_slope.cairo deleted file mode 100644 index 80721367a3..0000000000 --- a/cairo_programs/secp256r1_compute_doubling_slope.cairo +++ /dev/null @@ -1,33 +0,0 @@ -%builtins range_check - -// Source: https://github.com/myBraavos/efficient-secp256r1/blob/main/src/secp256r1/ec.cairo#L32 - -func compute_doubling_slope{range_check_ptr}(point: EcPoint) -> (slope: BigInt3) { - // Note that y cannot be zero: assume that it is, then point = -point, so 2 * point = 0, which - // contradicts the fact that the size of the curve is odd. - %{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P %} - %{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_ALPHA as ALPHA %} - // Hint #19 - %{ - from starkware.cairo.common.cairo_secp.secp_utils import pack - from starkware.python.math_utils import ec_double_slope - - # Compute the slope. - x = pack(ids.point.x, PRIME) - y = pack(ids.point.y, PRIME) - value = slope = ec_double_slope(point=(x, y), alpha=ALPHA, p=SECP_P) - %} - let (slope: BigInt3) = nondet_bigint3(); - - let (x_sqr: UnreducedBigInt3) = unreduced_sqr(point.x); - let (slope_y: UnreducedBigInt3) = unreduced_mul(slope, point.y); - verify_zero( - UnreducedBigInt3( - d0=3 * x_sqr.d0 + A0 - 2 * slope_y.d0, - d1=3 * x_sqr.d1 + A1 - 2 * slope_y.d1, - d2=3 * x_sqr.d2 + A2 - 2 * slope_y.d2, - ), - ); - - return (slope=slope); -} From 16fd07e754cf73d0e26e28563c04737c79fa4e46 Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Tue, 25 Apr 2023 16:46:39 -0300 Subject: [PATCH 06/10] add correct constants to test program --- cairo_programs/secp256r1_div_mod_n.cairo | 69 ++++++++++++++----- .../builtin_hint_processor/secp/signature.rs | 4 +- 2 files changed, 53 insertions(+), 20 deletions(-) diff --git a/cairo_programs/secp256r1_div_mod_n.cairo b/cairo_programs/secp256r1_div_mod_n.cairo index 077ff849d1..ab77e03570 100644 --- a/cairo_programs/secp256r1_div_mod_n.cairo +++ b/cairo_programs/secp256r1_div_mod_n.cairo @@ -3,23 +3,16 @@ // 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.alloc import alloc -from starkware.cairo.common.bitwise import bitwise_and -from starkware.cairo.common.cairo_builtins import BitwiseBuiltin -from starkware.cairo.common.cairo_secp.bigint import ( - BASE, - BigInt3, - UnreducedBigInt3, - bigint_mul, - nondet_bigint3, -) -from starkware.cairo.common.cairo_secp.ec import EcPoint -from starkware.cairo.common.math import assert_nn, assert_nn_le, assert_not_zero, unsigned_div_rem -from starkware.cairo.common.math_cmp import RC_BOUND -from starkware.cairo.common.uint256 import Uint256 +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 @@ -29,16 +22,54 @@ func div_mod_n{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) { 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 main{range_check_ptr}(){ - let x = BigInt3(235, 522, 111); - let y = BigInt3(1323, 15124, 796759); +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 + ); - let a = div_mod_n(x, y); - assert a = a; return (); +} +func main{range_check_ptr: felt}() { + test_div_mod_n(); + + return (); } diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs index c4086fc99e..b259b1d1ae 100644 --- a/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -81,7 +81,9 @@ pub fn div_mod_n_safe_div( let b = exec_scopes.get_ref::(b_alias)?; let res = exec_scopes.get_ref::("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(()) From 51af1c3025d1edbbff084c9c0d58d5bd5010806a Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Tue, 25 Apr 2023 17:59:06 -0300 Subject: [PATCH 07/10] fix broken test when executing hint #25 with different context --- .../builtin_hint_processor/secp/signature.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs index 537b1a448d..d4a2d3b0a4 100644 --- a/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -81,7 +81,7 @@ pub fn div_mod_n_safe_div( let b = exec_scopes.get_ref::(b_alias)?; let res = exec_scopes.get_ref::("res")?; - let n = exec_scopes.get::("N")?; + let n = exec_scopes.get("N")?; let value = safe_div_bigint(&(res * b - a), &n)?.add(to_add); @@ -153,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(()) @@ -220,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( @@ -310,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![ @@ -322,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(())); } From 03926eb255b06a0159c37b309e2b91f453e54b99 Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Wed, 26 Apr 2023 10:55:47 -0300 Subject: [PATCH 08/10] Update CHANGELOG.md Co-authored-by: Mario Rugiero --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6264a24091..69c04c4a89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -329,7 +329,7 @@ ```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): From 927b9da906c2cdb3640cc0c7be4ddbf04b83b74b Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Wed, 26 Apr 2023 14:25:46 -0300 Subject: [PATCH 09/10] merge --- .../builtin_hint_processor_definition.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs index e04d66ee00..40e537bd27 100644 --- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs +++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs @@ -52,8 +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_n, import_secp256r1_p, - import_secp256r1_alpha, 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, From 4cf17572e29ec704ac1dda3f688afb726503e986 Mon Sep 17 00:00:00 2001 From: mfachal <647731+mfachal@users.noreply.github.com> Date: Wed, 26 Apr 2023 15:45:49 -0300 Subject: [PATCH 10/10] add unit test for import alpha --- .../builtin_hint_processor/secp/ec_utils.rs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs index d0205a5343..f80fe6caf1 100644 --- a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs +++ b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs @@ -457,6 +457,7 @@ mod tests { }; use assert_matches::assert_matches; + use num_bigint::BigUint; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -1164,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::("ALPHA"), + Ok(x) if x == biguint_str!( + "115792089210356248762697446949407573530086143415290314195533631308867097853948" + ) + ); + } }