From ac85d3dbf4d01df330aa12072c9f2b5b08c7fb59 Mon Sep 17 00:00:00 2001 From: Michael Connor Date: Thu, 3 Oct 2024 11:01:11 +0100 Subject: [PATCH 01/14] refactor --- src/bignum.nr | 340 +++++++ src/bignum_test.nr | 325 +++---- src/constrained_ops.nr | 308 +++++++ src/expressions.nr | 412 +++++++++ src/fields/U1024.nr | 59 +- src/fields/U2048.nr | 59 +- src/fields/U256.nr | 60 +- src/fields/U384.nr | 59 +- src/fields/U4096.nr | 59 +- src/fields/U512.nr | 41 +- src/fields/U768.nr | 59 +- src/fields/U8192.nr | 59 +- src/fields/bls12_377Fq.nr | 51 +- src/fields/bls12_377Fr.nr | 53 +- src/fields/bls12_381Fq.nr | 53 +- src/fields/bls12_381Fr.nr | 53 +- src/fields/bn254Fq.nr | 53 +- src/fields/ed25519Fq.nr | 53 +- src/fields/ed25519Fr.nr | 53 +- src/fields/mnt4_753Fq.nr | 53 +- src/fields/mnt4_753Fr.nr | 53 +- src/fields/mnt6_753Fq.nr | 53 +- src/fields/mnt6_753Fr.nr | 53 +- src/fields/mod.nr | 43 +- src/fields/pallasFq.nr | 53 +- src/fields/pallasFr.nr | 53 +- src/fields/secp256k1Fq.nr | 53 +- src/fields/secp256k1Fr.nr | 53 +- src/fields/secp256r1Fq.nr | 53 +- src/fields/secp256r1Fr.nr | 53 +- src/fields/secp384r1Fq.nr | 53 +- src/fields/secp384r1Fr.nr | 53 +- src/fields/vestaFq.nr | 53 +- src/fields/vestaFr.nr | 53 +- src/lib.nr | 325 +------ src/params.nr | 85 ++ src/runtime_bignum.nr | 1673 +++++----------------------------- src/runtime_bignum_test.nr | 453 ++++----- src/serialization.nr | 66 ++ src/unconstrained_helpers.nr | 223 +++++ src/unconstrained_ops.nr | 290 ++++++ src/utils/map.nr | 12 + src/utils/mod.nr | 9 +- 43 files changed, 3098 insertions(+), 3032 deletions(-) create mode 100644 src/bignum.nr create mode 100644 src/constrained_ops.nr create mode 100644 src/expressions.nr create mode 100644 src/params.nr create mode 100644 src/serialization.nr create mode 100644 src/unconstrained_helpers.nr create mode 100644 src/unconstrained_ops.nr create mode 100644 src/utils/map.nr diff --git a/src/bignum.nr b/src/bignum.nr new file mode 100644 index 00000000..d27905e4 --- /dev/null +++ b/src/bignum.nr @@ -0,0 +1,340 @@ +use crate::utils::map::map; + +use crate::params::BigNumParamsTrait; +use crate::constrained_ops::{ + conditional_select, assert_is_not_equal, eq, validate_in_field, validate_in_range, neg, add, sub, + mul, div, udiv_mod, udiv, umod +}; +use crate::unconstrained_ops::{ + __derive_from_seed, __eq, __is_zero, __neg, __add, __sub, __mul, __div, __udiv_mod, __invmod, __pow, + __batch_invert, __batch_invert_slice +}; +use crate::expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}; +use crate::serialization::{from_be_bytes, to_le_bytes}; + +pub struct BigNum { + limbs: [Field; N] +} + +pub(crate) trait BigNumTrait { + // TODO: this crashes the compiler? v0.32 + // fn default() -> Self { std::default::Default::default () } + fn new() -> Self; + fn one() -> Self; + unconstrained fn __derive_from_seed(seed: [u8; SeedBytes]) -> Self; + fn from_slice(limbs: [Field]) -> Self; + fn from_array(limbs: [Field; N]) -> Self; + fn from_be_bytes(x: [u8; NBytes]) -> Self; + fn to_le_bytes(self) -> [u8; NBytes]; + + fn modulus() -> Self; + fn modulus_bits() -> u32; + fn num_limbs() -> u32; + // fn get(self) -> [Field]; + fn get_limbs(self) -> [Field; N]; + fn get_limb(self, idx: u32) -> Field; + fn set_limb(&mut self, idx: u32, value: Field); + + unconstrained fn __eq(self, other: Self) -> bool; + unconstrained fn __is_zero(self) -> bool; + + unconstrained fn __neg(self) -> Self; + unconstrained fn __add(self, other: Self) -> Self; + unconstrained fn __sub(self, other: Self) -> Self; + unconstrained fn __mul(self, other: Self) -> Self; + unconstrained fn __div(self, other: Self) -> Self; + unconstrained fn __udiv_mod(self, divisor: Self) -> (Self, Self); + unconstrained fn __invmod(self) -> Self; + unconstrained fn __pow(self, exponent: Self) -> Self; + + unconstrained fn __batch_invert(to_invert: [Self; M]) -> [Self; M]; + unconstrained fn __batch_invert_slice(to_invert: [Self]) -> [Self]; + + unconstrained fn __compute_quadratic_expression( + lhs: [[Self; LHS_N]; NUM_PRODUCTS], + lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], + rhs: [[Self; RHS_N]; NUM_PRODUCTS], + rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], + add: [Self; ADD_N], + add_flags: [bool; ADD_N] + ) -> (Self, Self); + + fn evaluate_quadratic_expression( + lhs: [[Self; LHS_N]; NUM_PRODUCTS], + lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], + rhs: [[Self; RHS_N]; NUM_PRODUCTS], + rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], + add: [Self; ADD_N], + add_flags: [bool; ADD_N] + ); + + fn eq(self, other: Self) -> bool { self == other } + fn assert_is_not_equal(self, other: Self); + fn validate_in_range(self); + fn validate_in_field(self); + + fn neg(self) -> Self; + fn add(self, other: Self) -> Self { self + other } + fn sub(self, other: Self) -> Self { self - other } + fn mul(self, other: Self) -> Self { self * other } + fn div(self, other: Self) -> Self { self / other } + fn udiv_mod(self, divisor: Self) -> (Self, Self); + fn udiv(self, divisor: Self) -> Self; + fn umod(self, divisor: Self) -> Self; + + fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self; +} + +impl BigNumTrait for BigNum where Params: BigNumParamsTrait { + + fn new() -> Self { + Self { limbs: [0; N] } + } + + fn one() -> Self { + let mut result = BigNum::new(); + result.limbs[0] = 1; + result + } + + unconstrained fn __derive_from_seed(seed: [u8; SeedBytes]) -> Self { + let params = Params::get_params(); + Self { limbs: __derive_from_seed(params, seed) } + } + + fn from_slice(limbs: [Field]) -> Self { + Self { limbs: limbs.as_array() } + } + + fn from_array(limbs: [Field; N]) -> Self { + Self { limbs } + } + + fn from_be_bytes(x: [u8; NBytes]) -> Self { + let params = Params::get_params(); + Self { limbs: from_be_bytes(params, x) } + } + + fn to_le_bytes(self) -> [u8; NBytes] { + let params = Params::get_params(); + to_le_bytes(params, self.limbs) + } + + fn modulus() -> Self { + Self { limbs: Params::get_params().modulus } + } + + fn modulus_bits() -> u32 { + let modulus_bits_getter = Params::get_params().modulus_bits_getter; + modulus_bits_getter() + } + + fn num_limbs() -> u32 { + N + } + + // fn get(self) -> [Field] { + // self.get_limbs() + // } + + fn get_limbs(self) -> [Field; N] { + self.limbs + } + + fn get_limb(self, idx: u32) -> Field { + self.limbs[idx] + } + + fn set_limb(&mut self, idx: u32, value: Field) { + self.limbs[idx] = value; + } + + unconstrained fn __eq(self, other: Self) -> bool { + __eq(self.limbs, other.limbs) + } + + unconstrained fn __is_zero(self) -> bool { + __is_zero(self.limbs) + } + + unconstrained fn __neg(self) -> Self { + let params = Params::get_params(); + Self::from_array(__neg(params, self.limbs)) + } + + unconstrained fn __add(self, other: Self) -> Self { + let params = Params::get_params(); + Self::from_array(__add(params, self.limbs, other.limbs)) + } + + unconstrained fn __sub(self, other: Self) -> Self { + let params = Params::get_params(); + Self::from_array(__sub(params, self.limbs, other.limbs)) + } + + unconstrained fn __mul(self, other: Self) -> Self { + let params = Params::get_params(); + Self::from_array(__mul(params, self.limbs, other.limbs)) + } + + unconstrained fn __div(self, divisor: Self) -> Self { + let params = Params::get_params(); + Self::from_array(__div(params, self.limbs, divisor.limbs)) + } + + unconstrained fn __udiv_mod(self, divisor: Self) -> (Self, Self) { + let (q, r) = __udiv_mod(self.limbs, divisor.limbs); + (Self { limbs: q }, Self { limbs: r }) + } + + unconstrained fn __invmod(self) -> Self { + let params = Params::get_params(); + assert(params.has_multiplicative_inverse); + Self { limbs: __invmod(params, self.limbs) } + } + + unconstrained fn __pow(self, exponent: Self) -> Self { + let params = Params::get_params(); + Self { limbs: __pow(params, self.limbs, exponent.limbs) } + } + + unconstrained fn __batch_invert(x: [Self; M]) -> [Self; M] { + let params = Params::get_params(); + assert(params.has_multiplicative_inverse); + __batch_invert(params, x.map(|bn| Self::get_limbs(bn))).map(|limbs| Self {limbs}) + } + + unconstrained fn __batch_invert_slice(x: [Self]) -> [Self] { + let params = Params::get_params(); + assert(params.has_multiplicative_inverse); + __batch_invert_slice(params, x.map(|bn| Self::get_limbs(bn))).map(|limbs| Self { limbs }) + } + + unconstrained fn __compute_quadratic_expression( + lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS], + lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], + rhs_terms: [[Self; RHS_N]; NUM_PRODUCTS], + rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], + linear_terms: [Self; ADD_N], + linear_flags: [bool; ADD_N] + ) -> (Self, Self) { + let params = Params::get_params(); + let (q_limbs, r_limbs) = __compute_quadratic_expression( + params, + lhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + lhs_flags, + rhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + rhs_flags, + linear_terms.map(|bn| Self::get_limbs(bn)), + linear_flags + ); + (Self { limbs: q_limbs }, Self { limbs: r_limbs }) + } + + fn evaluate_quadratic_expression( + lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS], + lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], + rhs_terms: [[Self; RHS_N]; NUM_PRODUCTS], + rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], + linear_terms: [Self; ADD_N], + linear_flags: [bool; ADD_N] + ) { + let params = Params::get_params(); + evaluate_quadratic_expression( + params, + lhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + lhs_flags, + rhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + rhs_flags, + linear_terms.map(|bn| Self::get_limbs(bn)), + linear_flags + ) + } + + fn validate_in_field(self: Self) { + let params = Params::get_params(); + validate_in_field(params, self.limbs); + } + + fn validate_in_range(self) { + let params = Params::get_params(); + validate_in_range(params, self.limbs); + } + + fn assert_is_not_equal(self, other: Self) { + let params = Params::get_params(); + assert_is_not_equal(params, self.limbs, other.limbs); + } + + fn neg(self) -> Self { + let params = Params::get_params(); + Self { limbs: neg(params, self.limbs) } + } + + fn udiv_mod(self, divisor: Self) -> (Self, Self) { + let params = Params::get_params(); + let (q, r) = udiv_mod(params, self.limbs, divisor.limbs); + (Self { limbs: q }, Self { limbs: r }) + } + + fn udiv(self, divisor: Self) -> Self { + let params = Params::get_params(); + Self { limbs: udiv(params, self.limbs, divisor.limbs) } + } + + fn umod(self, divisor: Self) -> Self { + let params = Params::get_params(); + Self { limbs: umod(params, self.limbs, divisor.limbs) } + } + + fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self { + Self { limbs: conditional_select(lhs.limbs, rhs.limbs, predicate) } + } +} + +// impl BigNumTrait for BigNum where Params: BigNumParamsTrait {} + +impl std::ops::Add for BigNum where Params: BigNumParamsTrait { + // Note: this method is expensive! Try to craft quadratic relations and directly evaluate them + // via evaluate_quadratic_expression + fn add(self, other: Self) -> Self { + let params = Params::get_params(); + Self { limbs: add(params, self.limbs, other.limbs) } + } +} + +impl std::ops::Sub for BigNum where Params: BigNumParamsTrait { + // Note: this method is expensive! Try to craft quadratic relations and directly evaluate them + // via evaluate_quadratic_expression + fn sub(self, other: Self) -> Self { + let params = Params::get_params(); + Self { limbs: sub(params, self.limbs, other.limbs) } + } +} + +impl std::ops::Mul for BigNum where Params: BigNumParamsTrait { + // Note: this method is expensive! Try to craft quadratic relations and directly evaluate them + // via evaluate_quadratic_expression + // e.g. performing a sum of multiple multiplications and additions via `evaluate_quadratic_expression` + // will create much fewer constraints than calling `mul` and `add` directly + fn mul(self, other: Self) -> Self { + let params = Params::get_params(); + Self { limbs: mul(params, self.limbs, other.limbs) } + } +} + +impl std::ops::Div for BigNum where Params: BigNumParamsTrait { + // Note: this method is expensive! Witness computation is extremely expensive as it requires modular exponentiation + fn div(self, other: Self) -> Self { + let params = Params::get_params(); + Self { limbs: div(params, self.limbs, other.limbs) } + } +} + +impl std::cmp::Eq for BigNum where Params: BigNumParamsTrait { + fn eq(self, other: Self) -> bool { + let params = Params::get_params(); + eq(params, self.limbs, other.limbs) + } +} + diff --git a/src/bignum_test.nr b/src/bignum_test.nr index c74875b0..146afa0e 100644 --- a/src/bignum_test.nr +++ b/src/bignum_test.nr @@ -1,13 +1,13 @@ -use crate::BigNum; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; -use crate::BigNumParamsTrait as BigNumParamsTrait; - use crate::utils::u60_representation::U60Repr; -use crate::fields::bn254Fq::BNParams; -use crate::fields::U256::U256Params; -use crate::runtime_bignum::BigNumInstance; -use crate::BigNumTrait; +use crate::bignum::BigNum; +use crate::bignum::BigNumTrait; + +use crate::params::BigNumParams; +use crate::params::BigNumParamsTrait; + +use crate::fields::bn254Fq::BN254_Fq_Params; +use crate::fields::U256::U256Params; struct Test2048Params{} @@ -17,13 +17,11 @@ fn silence_warning() { let _ = Test2048Params {}; } -impl RuntimeBigNumParamsTrait<18> for Test2048Params { - fn modulus_bits() -> u32 { - 2048 - } -} impl BigNumParamsTrait<18> for Test2048Params { - fn get_instance() -> BigNumInstance<18, Self> { + fn get_params() -> BigNumParams<18> { + let has_multiplicative_inverse = false; + let modulus_bits_getter = || 2048; + // let modulus_bits = 2048; let modulus: [Field; 18] = [ 0x0000000000000000000000000000000000c0a197a5ae0fcdceb052c9732614fe, 0x0000000000000000000000000000000000656ae034423283422243918ab83be3, @@ -44,26 +42,6 @@ impl BigNumParamsTrait<18> for Test2048Params { 0x00000000000000000000000000000000009c1fdb18907711bfe3e3c1cf918395, 0x00000000000000000000000000000000000000000000000000000000000000b8 ]; - // fn double_modulus() -> [Field; 18] {[ - // 0x000000000000000000000000000000000181432f4b5c1f9b9d60a592e64c29fc, - // 0x0000000000000000000000000000000001cad5c06884650684448723157077c6, - // 0x0000000000000000000000000000000001d7eb21b4914f820e16fab557558cef, - // 0x0000000000000000000000000000000001199c73ea604716c0de49652dc57b51, - // 0x000000000000000000000000000000000103c3fdf37738387d5b31e44de37f3f, - // 0x00000000000000000000000000000000015b183902dc25c1da26f20abc6e757d, - // 0x00000000000000000000000000000000019d7d01c8e9eea7553a28c3886a247a, - // 0x00000000000000000000000000000000015dcb4319ddbdf11a22b5172782cf5a, - // 0x00000000000000000000000000000000014d17507894cb8860e84ff892bb3c88, - // 0x0000000000000000000000000000000001ba4eef24d090ccf6fbef3e684c73a7, - // 0x0000000000000000000000000000000001e8aa0e992d0ab9400d0cd1dfcfb47a, - // 0x0000000000000000000000000000000001bbb74d6617782d17f674244be4faca, - // 0x0000000000000000000000000000000001b23fd8909e6ce0ea4826779ade84af, - // 0x0000000000000000000000000000000001b2c836eacecd5dd7cccf03ba03a0c3, - // 0x0000000000000000000000000000000001b178bd5fe962cbc2857f3c4901dd75, - // 0x0000000000000000000000000000000001ccf472c9e11c0dbeee59cc964534e3, - // 0x0000000000000000000000000000000001383fb63120ee237fc7c7839f230729, - // 0x0000000000000000000000000000000000000000000000000000000000000170 - // ]} let redc_param: [Field; 18] = [ 0x000000000000000000000000000000000091697def7100cd5cf8d890b4ef2ec3, 0x00000000000000000000000000000000006765ba8304214dac764d3f4adc3185, @@ -84,24 +62,32 @@ impl BigNumParamsTrait<18> for Test2048Params { 0x0000000000000000000000000000000000ff4e42304e60fb3a54fca735499f2c, 0x0000000000000000000000000000000000000000000000000000000000000162 ]; - BigNumInstance::new(modulus, redc_param) - } - fn modulus_bits() -> u32 { - 2048 + BigNumParams::new( + has_multiplicative_inverse, + modulus_bits_getter, + modulus, + redc_param + ) } } -type Fq = BigNum<3, BNParams>; +type Fq = BigNum<3, BN254_Fq_Params>; -fn test_eq(_: BigNum, __: [Field; N]) where BigNum: BigNumTrait { - let a = BigNum::__derive_from_seed([1, 2, 3, 4]); - let b = BigNum::__derive_from_seed([1, 2, 3, 4]); - let c = BigNum::__derive_from_seed([2, 2, 3, 4]); +fn test_eq() where BN: BigNumTrait { + let a = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; + let b = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; + let c = unsafe { + BN::__derive_from_seed([2, 2, 3, 4]) + }; - let modulus = BigNum::modulus(); - let t0: U60Repr = (U60Repr::from(modulus.get().as_array())); - let t1: U60Repr = (U60Repr::from(b.get().as_array())); - let b_plus_modulus: BigNum = BigNum::from(U60Repr::into(t0 + t1).as_slice()); + let modulus = BN::modulus(); + let t0: U60Repr = (U60Repr::from(modulus.get_limbs())); + let t1: U60Repr = (U60Repr::from(b.get_limbs())); + let b_plus_modulus = BN::from_array(U60Repr::into(t0 + t1)); assert(a.eq(b) == true); assert(a.eq(b_plus_modulus) == true); assert(c.eq(b) == false); @@ -113,7 +99,7 @@ fn test_eq(_: BigNum, __: [Field; N]) where BigNum: BigNumTr // let b = BigNum::__derive_from_seed([1, 2, 3, 4]); // let c = BigNum::__derive_from_seed([2, 2, 3, 4]); -// let modulus: BigNum = Params::get_instance().modulus(); +// let modulus: BigNum = Params::get_params().modulus(); // let t0: U60Repr = (U60Repr::from(modulus.limbs)); // let t1: U60Repr = (U60Repr::from(b.limbs)); // let b_plus_modulus: BigNum = BigNum { limbs: U60Repr::into(t0 + t1) }; @@ -127,19 +113,27 @@ fn test_eq(_: BigNum, __: [Field; N]) where BigNum: BigNumTr // // // 98760 // // // 99689 // // // 929 gates for a 2048 bit mul -fn test_mul(_: BigNum) where BigNum: BigNumTrait + std::ops::Mul + std::ops::Add { - let a: BigNum = BigNum::__derive_from_seed([1, 2, 3, 4]); - let b: BigNum = BigNum::__derive_from_seed([4, 5, 6, 7]); +fn test_mul() where BN: BigNumTrait + std::ops::Mul + std::ops::Add { + let a: BN = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; + let b: BN = unsafe { + BN::__derive_from_seed([4, 5, 6, 7]) + }; let c = (a + b) * (a + b); let d = (a * a) + (b * b) + (a * b) + (a * b); assert(c.eq(d)); } -fn test_add(_: BigNum) where BigNum: BigNumTrait + std::ops::Add + std::ops::Mul + std::cmp::Eq { - let a = BigNum::__derive_from_seed([1, 2, 3, 4]); - let b: BigNum = BigNum::__derive_from_seed([4, 5, 6, 7]); - let one = BigNum::one(); +fn test_add() where BN: BigNumTrait + std::ops::Add + std::ops::Mul + std::cmp::Eq { + let a = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; + let b: BN = unsafe { + BN::__derive_from_seed([4, 5, 6, 7]) + }; + let one = BN::one(); a.validate_in_range(); a.validate_in_field(); b.validate_in_range(); @@ -149,7 +143,7 @@ fn test_add(_: BigNum) where BigNum: BigNumTrait + std::ops::Add + std:: let d = (a + b) * (one + one); assert(c == (d)); let e = one + one; - let limbs = e.get(); + let limbs = e.get_limbs(); let mut first: bool = true; for limb in limbs { if first { @@ -161,80 +155,110 @@ fn test_add(_: BigNum) where BigNum: BigNumTrait + std::ops::Add + std:: } } -fn test_div(_: BigNum) where BigNum: BigNumTrait + std::ops::Div + std::ops::Mul + std::ops::Add + std::cmp::Eq { - let a = BigNum::__derive_from_seed([1, 2, 3, 4]); - let b = BigNum::__derive_from_seed([4, 5, 6, 7]); +fn test_div() where BN: BigNumTrait + std::ops::Div + std::ops::Mul + std::ops::Add + std::cmp::Eq { + let a = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; + let b = unsafe { + BN::__derive_from_seed([4, 5, 6, 7]) + }; let c = a / b; assert((b * c) == (a)); } -fn test_invmod(_: BigNum) where BigNum: BigNumTrait + std::cmp::Eq { - let u = BigNum::__derive_from_seed([1, 2, 3, 4]); +fn test_invmod() where BN: BigNumTrait + std::cmp::Eq { + let u = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; for _ in 0..1 { - let v = u.__invmod(); - let result = u.__mul(v); - let expected = BigNum::one(); + let v = unsafe { + u.__invmod() + }; + let result = unsafe { + u.__mul(v) + }; + let expected = BN::one(); assert(result == expected); } } -fn assert_is_not_equal(_: BigNum) where BigNum: BigNumTrait { - let a = BigNum::__derive_from_seed([1, 2, 3, 4]); - let b = BigNum::__derive_from_seed([4, 5, 6, 7]); +fn assert_is_not_equal() where BN: BigNumTrait { + let a = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; + let b = unsafe { + BN::__derive_from_seed([4, 5, 6, 7]) + }; a.assert_is_not_equal(b); } -fn assert_is_not_equal_fail(_: BigNum) where BigNum: BigNumTrait { - let a = BigNum::__derive_from_seed([1, 2, 3, 4]); - let b = BigNum::__derive_from_seed([1, 2, 3, 4]); +fn assert_is_not_equal_fail() where BN: BigNumTrait { + let a = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; + let b = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; a.assert_is_not_equal(b); } -fn assert_is_not_equal_overloaded_lhs_fail(_: BigNum, __: [Field; N]) where BigNum: BigNumTrait { - let a = BigNum::__derive_from_seed([1, 2, 3, 4]); - let b = BigNum::__derive_from_seed([1, 2, 3, 4]); +fn assert_is_not_equal_overloaded_lhs_fail() where BN: BigNumTrait { + let a = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; + let b = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; - let modulus = BigNum::modulus(); + let modulus = BN::modulus(); - let t0: U60Repr = U60Repr::from(a.get().as_array()); - let t1: U60Repr = U60Repr::from(modulus.get().as_array()); - let a_plus_modulus: BigNum = BigNum::from(U60Repr::into(t0 + t1).as_slice()); + let t0: U60Repr = U60Repr::from(a.get_limbs()); + let t1: U60Repr = U60Repr::from(modulus.get_limbs()); + let a_plus_modulus = BN::from_array(U60Repr::into(t0 + t1)); a_plus_modulus.assert_is_not_equal(b); } -fn assert_is_not_equal_overloaded_rhs_fail(_: BigNum, __: [Field; N]) where BigNum: BigNumTrait { - let a = BigNum::__derive_from_seed([1, 2, 3, 4]); - let b = BigNum::__derive_from_seed([1, 2, 3, 4]); +fn assert_is_not_equal_overloaded_rhs_fail() where BN: BigNumTrait { + let a = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; + let b = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; - let modulus = BigNum::modulus(); + let modulus = BN::modulus(); - let t0: U60Repr = U60Repr::from(b.get().as_array()); - let t1: U60Repr = U60Repr::from(modulus.get().as_array()); - let b_plus_modulus: BigNum = BigNum::from(U60Repr::into(t0 + t1).as_slice()); + let t0: U60Repr = U60Repr::from(b.get_limbs()); + let t1: U60Repr = U60Repr::from(modulus.get_limbs()); + let b_plus_modulus = BN::from_array(U60Repr::into(t0 + t1)); a.assert_is_not_equal(b_plus_modulus); } -fn assert_is_not_equal_overloaded_fail(_: BigNum, __: [Field; N]) where BigNum: BigNumTrait { - let a = BigNum::__derive_from_seed([1, 2, 3, 4]); - let b = BigNum::__derive_from_seed([1, 2, 3, 4]); +fn assert_is_not_equal_overloaded_fail() where BN: BigNumTrait { + let a = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; + let b = unsafe { + BN::__derive_from_seed([1, 2, 3, 4]) + }; - let modulus = BigNum::modulus(); + let modulus = BN::modulus(); - let t0: U60Repr = U60Repr::from(a.get().as_array()); - let t1: U60Repr = U60Repr::from(b.get().as_array()); - let t2: U60Repr = U60Repr::from(modulus.get().as_array()); - let a_plus_modulus: BigNum = BigNum::from(U60Repr::into(t0 + t2).as_slice()); - let b_plus_modulus: BigNum = BigNum::from(U60Repr::into(t1 + t2).as_slice()); + let t0: U60Repr = U60Repr::from(a.get_limbs()); + let t1: U60Repr = U60Repr::from(b.get_limbs()); + let t2: U60Repr = U60Repr::from(modulus.get_limbs()); + let a_plus_modulus: BN = BN::from_array(U60Repr::into(t0 + t2)); + let b_plus_modulus: BN = BN::from_array(U60Repr::into(t1 + t2)); a_plus_modulus.assert_is_not_equal(b_plus_modulus); } #[test] fn test_eq_BN() { - let stub: BigNum<3, BNParams> = BigNum::new(); - test_eq(stub, [0; 3]); + // let stub: BigNum<3, BN254_Fq_Params> = BigNum::new(); + test_eq::<3, BigNum<3, BN254_Fq_Params>>(); } #[test] fn test_add_BN() { @@ -292,7 +316,7 @@ fn test_add_modulus_limit() { // p + 2^{254} - 1 should be the maximum allowed value fed into an add operation // when adding, if the result overflows the modulus, we conditionally subtract the modulus, producing 2^{254} - 1 // this is the largest value that will satisfy the range check applied when constructing a bignum - let p : U60Repr<3, 2> = U60Repr::from(BNParams::get_instance().modulus().get().as_array()); + let p : U60Repr<3, 2> = U60Repr::from(BN254_Fq_Params::get_params().modulus); let two_pow_254_minus_1: U60Repr<3, 2> = U60Repr::from([0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x3fff]); let a: Fq = BigNum { limbs: U60Repr::into(p) }; let b: Fq = BigNum { limbs: U60Repr::into(two_pow_254_minus_1) }; @@ -304,7 +328,7 @@ fn test_add_modulus_limit() { fn test_add_modulus_overflow() { //(2^{254} - 1) + (p - 1) = 2^{254} + p // after subtracting modulus, result is 2^{254} will does not satisfy the range check applied when constructing a BigNum - let p : U60Repr<3, 2> = U60Repr::from(BNParams::get_instance().modulus().get().as_array()); + let p : U60Repr<3, 2> = U60Repr::from(BN254_Fq_Params::get_params().modulus); let two_pow_254_minus_1: U60Repr<3, 2> = U60Repr::from([0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x3fff]); let one = U60Repr::from([1, 0, 0]); let a: Fq = BigNum { limbs: U60Repr::into(p + one) }; @@ -315,164 +339,143 @@ fn test_add_modulus_overflow() { #[test] fn test_mul_BN() { - let stub: BigNum<3, BNParams> = BigNum::new(); - test_mul(stub); + test_mul::<3, BigNum<3, BN254_Fq_Params>>(); } #[test] fn test_add_BN2() { - let stub: BigNum<3, BNParams> = BigNum::new(); - test_add(stub); + test_add::<3, BigNum<3, BN254_Fq_Params>>(); } #[test] fn test_div_BN() { - let stub: BigNum<3, BNParams> = BigNum::new(); - test_div(stub); + test_div::<3, BigNum<3, BN254_Fq_Params>>(); } #[test] fn test_invmod_BN() { - let stub: BigNum<3, BNParams> = BigNum::new(); - test_invmod(stub); + test_invmod::<3, BigNum<3, BN254_Fq_Params>>(); } #[test] fn test_assert_is_not_equal_BN() { - let stub: BigNum<3, BNParams> = BigNum::new(); - assert_is_not_equal(stub); + assert_is_not_equal::<3, BigNum<3, BN254_Fq_Params>>(); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_fail_BN() { - let stub: BigNum<3, BNParams> = BigNum::new(); - assert_is_not_equal_fail(stub); + assert_is_not_equal_fail::<3, BigNum<3, BN254_Fq_Params>>(); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_lhs_fail_BN() { - let stub: BigNum<3, BNParams> = BigNum::new(); - assert_is_not_equal_overloaded_lhs_fail(stub, [0; 3]); + assert_is_not_equal_overloaded_lhs_fail::<3, BigNum<3, BN254_Fq_Params>>(); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_rhs_fail_BN() { - let stub: BigNum<3, BNParams> = BigNum::new(); - assert_is_not_equal_overloaded_rhs_fail(stub, [0; 3]); + assert_is_not_equal_overloaded_rhs_fail::<3, BigNum<3, BN254_Fq_Params>>(); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_fail_BN() { - let stub: BigNum<3, BNParams> = BigNum::new(); - assert_is_not_equal_overloaded_fail(stub, [0; 3]); + assert_is_not_equal_overloaded_fail::<3, BigNum<3, BN254_Fq_Params>>(); } #[test] fn test_eq_2048() { - let stub: BigNum<18, Test2048Params> = BigNum::new(); - test_eq(stub, [0; 18]); + test_eq::<18, BigNum<18, Test2048Params>>(); } #[test] fn test_mul_2048() { - let stub: BigNum<18, Test2048Params> = BigNum::new(); - test_mul(stub); + test_mul::<18, BigNum<18, Test2048Params>>(); } #[test] fn test_add_2048() { - let stub: BigNum<18, Test2048Params> = BigNum::new(); - test_add(stub); + test_add::<18, BigNum<18, Test2048Params>>(); } #[test] fn test_assert_is_not_equal_2048() { - let stub: BigNum<18, Test2048Params> = BigNum::new(); - assert_is_not_equal(stub); + assert_is_not_equal::<18, BigNum<18, Test2048Params>>(); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_fail_2048() { - let stub: BigNum<18, Test2048Params> = BigNum::new(); - assert_is_not_equal_fail(stub); + assert_is_not_equal_fail::<18, BigNum<18, Test2048Params>>(); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_lhs_fail_2048() { - let stub: BigNum<18, Test2048Params> = BigNum::new(); - assert_is_not_equal_overloaded_lhs_fail(stub, [0; 18]); + assert_is_not_equal_overloaded_lhs_fail::<18, BigNum<18, Test2048Params>>(); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_rhs_fail_2048() { - let stub: BigNum<18, Test2048Params> = BigNum::new(); - assert_is_not_equal_overloaded_rhs_fail(stub, [0; 18]); + assert_is_not_equal_overloaded_rhs_fail::<18, BigNum<18, Test2048Params>>(); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_fail_2048() { - let stub: BigNum<18, Test2048Params> = BigNum::new(); - assert_is_not_equal_overloaded_fail(stub, [0; 18]); + assert_is_not_equal_overloaded_fail::<18, BigNum<18, Test2048Params>>(); } #[test] fn test_eq_U256() { - let stub: BigNum<3, U256Params> = BigNum::new(); - test_eq(stub, [0; 3]); + test_eq::<3, BigNum<3, U256Params>>(); } #[test] fn test_mul_U256() { - let stub: BigNum<3, U256Params> = BigNum::new(); - test_mul(stub); + test_mul::<3, BigNum<3, U256Params>>(); } #[test] fn test_add_U256() { - let stub: BigNum<3, U256Params> = BigNum::new(); - test_add(stub); + test_add::<3, BigNum<3, U256Params>>(); } #[test] fn test_assert_is_not_equal_U256() { - let stub: BigNum<3, U256Params> = BigNum::new(); - assert_is_not_equal(stub); + assert_is_not_equal::<3, BigNum<3, U256Params>>(); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_fail_U256() { - let stub: BigNum<3, U256Params> = BigNum::new(); - assert_is_not_equal_fail(stub); + assert_is_not_equal_fail::<3, BigNum<3, U256Params>>(); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_lhs_fail_U256() { - let stub: BigNum<3, U256Params> = BigNum::new(); - assert_is_not_equal_overloaded_lhs_fail(stub, [0; 3]); + assert_is_not_equal_overloaded_lhs_fail::<3, BigNum<3, U256Params>>(); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_rhs_fail_U256() { - let stub: BigNum<3, U256Params> = BigNum::new(); - assert_is_not_equal_overloaded_rhs_fail(stub, [0; 3]); + assert_is_not_equal_overloaded_rhs_fail::<3, BigNum<3, U256Params>>(); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_fail_U256() { - let stub: BigNum<18, Test2048Params> = BigNum::new(); - assert_is_not_equal_overloaded_fail(stub, [0; 18]); + assert_is_not_equal_overloaded_fail::<3, BigNum<3, U256Params>>(); } type U256 = BigNum<3, U256Params>; #[test] fn test_udiv_mod_U256() { - let a: U256 = BigNum::__derive_from_seed([1, 2, 3, 4]); + let a: U256 = unsafe { + BigNum::__derive_from_seed([1, 2, 3, 4]) + }; let b: U256 = BigNum::from_array([12, 0, 0]); let (q, r) = a.udiv_mod(b); // let qb = q.__mul(b); - let product = q.__mul(b).__add(r); + let product = unsafe { + q.__mul(b).__add(r) + }; assert(product.eq(a)); } @@ -555,7 +558,9 @@ fn test_2048_bit_quadratic_expression() { let a_bn: BigNum<18, Test2048Params> = BigNum { limbs: a }; let b_bn: BigNum<18, Test2048Params> = BigNum { limbs: b }; - let c_bn = a_bn.__mul(b_bn); + let c_bn = unsafe { + a_bn.__mul(b_bn) + }; assert(c_bn.limbs == c_expected); a_bn.validate_in_range(); @@ -584,7 +589,9 @@ fn test_expressions() { 0x0 ] }; - let yy = y.__add(y); + let yy = unsafe { + y.__add(y) + }; assert(yy.limbs == z.limbs); @@ -616,10 +623,18 @@ fn test_expressions() { 0x0000000000000000000000000000000000000000000000000000000000000f93 ] }; - let wx = w.__mul(x); - let uv = uu.__mul(vv); - let y = (uv.__add(wx)).__neg(); - let z = uv.__add(wx); + let wx = unsafe { + w.__mul(x) + }; + let uv = unsafe { + uu.__mul(vv) + }; + let y = unsafe { + (uv.__add(wx)).__neg() + }; + let z = unsafe { + uv.__add(wx) + }; BigNum::evaluate_quadratic_expression( [[uu], [w]], diff --git a/src/constrained_ops.nr b/src/constrained_ops.nr new file mode 100644 index 00000000..3021eb49 --- /dev/null +++ b/src/constrained_ops.nr @@ -0,0 +1,308 @@ +use crate::params::BigNumParams as P; + +use crate::unconstrained_helpers::{ + __validate_in_field_compute_borrow_flags, __validate_gt_remainder, __neg_with_flags, + __add_with_flags, __sub_with_flags +}; +use crate::unconstrained_ops::{__mul, __div, __udiv_mod}; +use crate::expressions::evaluate_quadratic_expression; + +/** +* @brief conditional_select given the value of `predicate` return either `self` (if 0) or `other` (if 1) +* @description should be cheaper than using an IF statement (TODO: check!) +**/ +pub(crate) fn conditional_select(lhs: [Field; N], rhs: [Field; N], predicate: bool) -> [Field; N] { + let mut result: [Field; N] = lhs; + for i in 0..N { + result[i] = (lhs[i] - rhs[i]) * predicate as Field + rhs[i]; + } + result +} + +/** + * @brief Validate self != other + * @details If A == B, then A == B mod N. + * We can efficiently evaluate A == B mod N where N = circuit modulus + * This method is *sound*, but not *complete* (i.e. A != B but A == B mod N) + * However the probability of an honest Prover being unable to satisfy this check is tiny! + * (todo: compute how tiny) + **/ +pub(crate) fn assert_is_not_equal(params: P, lhs: [Field; N], rhs: [Field; N]) { + let mut l: Field = 0; + let mut r: Field = 0; + let mut modulus_mod_n: Field = 0; + let two_pow_120: Field = 0x1000000000000000000000000000000; + let modulus = params.modulus; + for i in 0..N { + l *= two_pow_120; + r *= two_pow_120; + modulus_mod_n *= two_pow_120; + l += lhs[N - i - 1]; + r += rhs[N - i - 1] ; + modulus_mod_n += modulus[N - i - 1]; + } + + // lhs can be either X mod N or P + X mod N + // rhs can be either Y mod N or P + Y mod N + // If lhs - rhs = 0 mod P then lhs - rhs = 0, P or -P mod N + let mut diff = l - r; + let mut target = diff * (diff + modulus_mod_n) * (diff - modulus_mod_n); + assert(target != 0, "asssert_is_not_equal fail"); +} + +pub(crate) fn eq(params: P, lhs: [Field; N], rhs: [Field; N]) -> bool { + let diff = sub(params, lhs, rhs); + // if self == other, possible values of `diff` will be `p` or `0` + // (the subtract operator constrains diff to be < ceil(log(p))) + // TODO: can do this more efficiently via witngen in unconstrained functions? + let mut is_equal_modulus: bool = true; + let mut is_equal_zero: bool = true; + for i in 0..N { + is_equal_modulus = is_equal_modulus & (diff[i] == params.modulus[i]); + is_equal_zero = is_equal_zero & (diff[i] == 0); + } + is_equal_modulus | is_equal_zero +} + +pub(crate) fn validate_in_field(params: P, val: [Field; N]) { + // N.B. need to combine with validate_in_range if `self` limbs have not been range constrained + let mut p_minus_self: [Field; N] = [0; N]; + let modulus: [Field; N] = params.modulus; + for i in 0..N { + p_minus_self[i] = modulus[i] - val[i]; + } + let borrow_flags = unsafe { + __validate_in_field_compute_borrow_flags(params, val) + }; + let two_pow_120: Field = 0x1000000000000000000000000000000; + p_minus_self[0] += borrow_flags[0] as Field * two_pow_120; + for i in 1..N - 1 { + p_minus_self[i] += (borrow_flags[i] as Field * two_pow_120 - borrow_flags[i-1] as Field); + } + p_minus_self[N - 1] -= borrow_flags[N - 2] as Field; + let mut compare = val; + compare = p_minus_self; + validate_in_range(params, compare); +} + +/** +* @brief Validate a BigNum instance is correctly range constrained to contain no more than Params::modulus_bits() +**/ +pub(crate) fn validate_in_range(params: P, limbs: [Field; N]) { + for i in 0..(N - 1) { + limbs[i].assert_max_bit_size(120); + } + let modulus_bits_getter = params.modulus_bits_getter; + let final_limb_bits = modulus_bits_getter() - ((N - 1) * 120); + limbs[N - 1].assert_max_bit_size(final_limb_bits as u32); +} + +/** +* @brief validate quotient produced from `evaluate_quadratic_expression` is well-formed +* @description because the inputs into evaluate_quadratic_expression may cause the quotient to extend beyond `Params::modulus_bits`. +* We allow the quotient to extend 6 bits beyond Params::modulus_bits() +* Why is this? +* several factors: 1. quotient * modulus , limbs cannot overflow field boundary (254 bits) +* 2. in `evaluate_quadratic_expression`, we require that for `expression - quotient * modulus`, +* limbs cannot exceed 246 bits (246 magic number due to a higher number adding extra range check gates) +* because of factor 2 and the fact that modulus limbs are 120 bits, quotient limbs cannot be >126 bits +* +* Note: doesn't this mean that final_limb_bits should be constrained to be 126 bits, not modulus_bits() - ((N - 1) * 120) + 6? +* TODO: think about this more! we want the range constraint we apply to be as small as allowable as this is more efficient +**/ +pub(crate) fn validate_quotient_in_range(params: P, limbs: [Field; N]) { + for i in 0..(N) { + limbs[i].assert_max_bit_size(120); + } + // Note: replace magic number 6 with definition + let modulus_bits_getter = params.modulus_bits_getter; + let final_limb_bits = modulus_bits_getter() - ((N - 1) * 120) + 6; + limbs[N - 1].assert_max_bit_size(final_limb_bits as u32); +} + +// validate that lhs - rhs does not underflow i.e. lhs > rhs +pub(crate) fn validate_gt(params: P, lhs: [Field; N], rhs: [Field; N]) { + // so we do... p - x - r = 0 and there might be borrow flags + + // a - b = r + // p + a - b - r = 0 + let (result, carry_flags, borrow_flags) = unsafe { + __validate_gt_remainder(lhs, rhs) + }; + + validate_in_range(params, result); + + let borrow_shift = 0x1000000000000000000000000000000; + let carry_shift = 0x1000000000000000000000000000000; + + let mut addend: [Field; N] = [0; N]; + let result_limb = lhs[0] - rhs[0] + addend[0] - result[0] - 1 + (borrow_flags[0] as Field * borrow_shift) + - (carry_flags[0] as Field * carry_shift); + assert(result_limb == 0); + for i in 1..N - 1 { + let result_limb = lhs[i] - rhs[i] + addend[i] - result[i] - borrow_flags[i - 1] as Field + + carry_flags[i - 1] as Field + + ((borrow_flags[i] as Field - carry_flags[i] as Field) * borrow_shift); + assert(result_limb == 0); + } + let result_limb = lhs[N - 1] - rhs[N - 1] + addend[N - 1] - result[N - 1] - borrow_flags[N - 2] as Field + + carry_flags[N - 2] as Field; + assert(result_limb == 0); +} + +pub(crate) fn neg(params: P, val: [Field; N]) -> [Field; N] { + // so we do... p - x - r = 0 and there might be borrow flags + let (result, borrow_flags) = unsafe { + __neg_with_flags(params, val) + }; + validate_in_range(params, result); + let modulus = params.modulus; + let borrow_shift = 0x1000000000000000000000000000000; + let result_limb = modulus[0] - val[0] - result[0] + (borrow_flags[0] as Field * borrow_shift); + assert(result_limb == 0); + for i in 1..N - 1 { + let result_limb = modulus[i] - val[i] - result[i] - borrow_flags[i - 1] as Field + + (borrow_flags[i] as Field * borrow_shift); + assert(result_limb == 0); + } + let result_limb = modulus[N - 1] - val[N - 1] - result[N - 1] - borrow_flags[N - 2] as Field; + assert(result_limb == 0); + result +} + +pub(crate) fn add(params: P, lhs: [Field; N], rhs: [Field; N]) -> [Field; N] { + // so we do... p - x - r = 0 and there might be borrow flags + let (result, carry_flags, borrow_flags, overflow_modulus) = unsafe { + __add_with_flags(params, lhs, rhs) + }; + validate_in_range(params, result); + let modulus = params.modulus; + let borrow_shift = 0x1000000000000000000000000000000; + let carry_shift = 0x1000000000000000000000000000000; + + let mut subtrahend: [Field; N] = [0; N]; + if (overflow_modulus) { + subtrahend = modulus; + } + let result_limb = lhs[0] + rhs[0] - subtrahend[0] - result[0] + (borrow_flags[0] as Field * borrow_shift) + - (carry_flags[0] as Field * carry_shift); + assert(result_limb == 0); + for i in 1..N - 1 { + let result_limb = lhs[i] + rhs[i] - subtrahend[i] - result[i] - borrow_flags[i - 1] as Field + + carry_flags[i - 1] as Field + + ((borrow_flags[i] as Field - carry_flags[i] as Field) * borrow_shift); + assert(result_limb == 0); + } + let result_limb = lhs[N - 1] + rhs[N - 1] - subtrahend[N - 1] - result[N - 1] - borrow_flags[N - 2] as Field + + carry_flags[N - 2] as Field; + assert(result_limb == 0); + result +} + +pub(crate) fn sub(params: P, lhs: [Field; N], rhs: [Field; N]) -> [Field; N] { + // so we do... p - x - r = 0 and there might be borrow flags + + // a - b = r + // p + a - b - r = 0 + let (result, carry_flags, borrow_flags, underflow) = unsafe { + __sub_with_flags(params, lhs, rhs) + }; + validate_in_range(params, result); + let modulus = params.modulus; + let borrow_shift = 0x1000000000000000000000000000000; + let carry_shift = 0x1000000000000000000000000000000; + + let mut addend: [Field; N] = [0; N]; + if (underflow) { + addend = modulus; + } + let result_limb = lhs[0] - rhs[0] + addend[0] - result[0] + (borrow_flags[0] as Field * borrow_shift) + - (carry_flags[0] as Field * carry_shift); + assert(result_limb == 0); + for i in 1..N - 1 { + let result_limb = lhs[i] - rhs[i] + addend[i] - result[i] - borrow_flags[i - 1] as Field + + carry_flags[i - 1] as Field + + ((borrow_flags[i] as Field - carry_flags[i] as Field) * borrow_shift); + assert(result_limb == 0); + } + let result_limb = lhs[N - 1] - rhs[N - 1] + addend[N - 1] - result[N - 1] - borrow_flags[N - 2] as Field + + carry_flags[N - 2] as Field; + assert(result_limb == 0); + result +} + +// Note: this method is expensive! Try to craft quadratic relations and directly evaluate them +// via evaluate_quadratic_expression +// e.g. performing a sum of multiple multiplications and additions via `evaluate_quadratic_expression` +// will create much fewer constraints than calling `mul` and `add` directly +pub(crate) fn mul(params: P, lhs: [Field; N], rhs: [Field; N]) -> [Field; N] { + let result = unsafe { + __mul(params, lhs, rhs) + }; + evaluate_quadratic_expression(params, [[lhs]], [[false]], [[rhs]], [[false]], [result], [true]); + result +} + +// Note: this method is expensive! Witness computation is extremely expensive as it requires modular exponentiation +pub(crate) fn div(params: P, lhs: [Field; N], rhs: [Field; N]) -> [Field; N] { + assert( + params.has_multiplicative_inverse, "BigNum has no multiplicative inverse. Use udiv for unsigned integer division" + ); + let result = unsafe { + __div(params, lhs, rhs) + }; + evaluate_quadratic_expression(params, [[result]], [[false]], [[rhs]], [[false]], [lhs], [true]); + result +} + +/** +* @brief udiv_mod performs integer division between numerator, divisor +* +* i.e. 1. floor(numerator / divisor) = quotient +* 2. numerator % divisor = remainder +* 3. divisor * quotient + remainder = numerator +**/ +pub(crate) fn udiv_mod( + params: P, + numerator: [Field; N], + divisor: [Field; N] +) -> ([Field; N], [Field; N]) { + let (quotient, remainder) = unsafe { + __udiv_mod(numerator, divisor) + }; + + // self / divisor = quotient rounded + // quotient * divisor + remainder - self = 0 + evaluate_quadratic_expression( + params, + [[quotient]], + [[false]], + [[divisor]], + [[false]], + [numerator, remainder], + [true, false] + ); + // we need (remainder < divisor) + // implies (divisor - remainder > 0) + validate_gt(params, divisor, remainder); + (quotient, remainder) +} + +/** +* @brief udiv_mod performs integer division between numerator, divisor +* +* i.e. return param is floor(numerator / divisor) +**/ +pub(crate) fn udiv(params: P, numerator: [Field; N], divisor: [Field; N]) -> [Field; N] { + udiv_mod(params, numerator, divisor).0 +} + +/** +* @brief udiv_mod performs integer modular reduction +* +* i.e. 1. numerator % divisor = return value +**/ +pub(crate) fn umod(params: P, numerator: [Field; N], divisor: [Field; N]) -> [Field; N] { + udiv_mod(params, numerator, divisor).1 +} + diff --git a/src/expressions.nr b/src/expressions.nr new file mode 100644 index 00000000..a2ef3e03 --- /dev/null +++ b/src/expressions.nr @@ -0,0 +1,412 @@ +use crate::utils::split_bits; + +use crate::params::BigNumParams as P; +use crate::constrained_ops::validate_quotient_in_range; +use crate::unconstrained_helpers::__barrett_reduction; + +/** +* @brief Given a degree-2 BigNum expression that is equal to 0 mod p, compute the quotient and borrow flags +* @description The expression is of the form: +* +* \sum_{i=0}^{NUM_PRODUCTS - 1} ((\sum_{j=0}^{LHS_N-1}lhs[i][j]) * (\sum_{j=0}^{RHS_N-1}rhs[i][j])) + \sum_{i=0}^{ADD_N - 1}linear_terms[i] = quotient * modulus +* +* The intent is to capture an arbitrary degree-2 expression within the limitations of Noir (no efficient dynamically-sized vectors) +* +* When performing BigNum arithmetic, we want to represent desired BigNum operations in a way that minimizes the number of modular reductions that are required. +* This can be achieved by minimizing the number of degree-2 relations required. +* +* The borrow flags describe whether individual Field limbs will underflow when evaluating the above relation. +* For example, when computing the product a * b - q * p = 0, it is possible that: +* 1. a[0]*b[0] - p[0]*q[0] = -2^{120} +* 2. a[0]*b[1] + a[1]*b[0] - p[0]*q[1] - p[1]*q[0] = 1 +* In the above example, the value represented by these two limbs is zero despite each limb being nonzero. +* In this case, to correctly constrain the result, we must add (at least) 2^{120} from the first limb and subtract 1 from the second. +* +* @param lhs_terms a 2D array of BigNum +* @param lhs_flags a 2D array of sign flags +* @param rhs_terms a 2D array of BigNum +* @param rhs_flags a 2D array of sign flags +* @param linear_terms an array of BigNum +* @param linear_flags an array of sign flags +**/ +unconstrained fn __compute_quadratic_expression_with_borrow_flags< + let N: u32, + let LHS_N: u32, + let RHS_N: u32, + let NUM_PRODUCTS: u32, + let ADD_N: u32 +>( + params: P, + lhs_terms: [[[Field; N]; LHS_N]; NUM_PRODUCTS], + lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], + rhs_terms: [[[Field; N]; RHS_N]; NUM_PRODUCTS], + rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], + linear_terms: [[Field; N]; ADD_N], + linear_flags: [bool; ADD_N] +) -> ([Field; N], [Field; N], [Field; 2 * N]) { + // TODO, validate we do not overflow N2 when multiplying and N when adding + + let mut mulout_p = __compute_quadratic_expression_product( + params, + lhs_terms, + lhs_flags, + rhs_terms, + rhs_flags, + linear_terms, + linear_flags + ); + let mut mulout_n: [Field; 2 * N] = [0; 2 * N]; + let mut relation_result: [Field; 2 * N] = split_bits::__normalize_limbs(mulout_p, 2 * N); + + let modulus: [Field; N] = params.modulus; + let modulus_bits_getter = params.modulus_bits_getter; + let (quotient, remainder) = __barrett_reduction( + relation_result, + params.redc_param, + modulus_bits_getter(), + modulus, + params.modulus_u60_x4 + ); + assert(remainder == [0; N]); + + for i in 0..N { + for j in 0..N { + mulout_n[i + j] += quotient[i] * modulus[j]; + } + } + + // compute borrow flags from mulout_p and mulout_n + let mut borrow_flags: [Field; 2 * N] = [0; 2 * N]; + let borrow_shift: Field = 0x40000000000000000000000000000000000000000000000000000000000000; // 2^{246} + let borrow_carry: Field = 0x40000000000000000000000000000000; // 2^{246 - 120} = 2^{126} + let two_pow_120: Field = 0x1000000000000000000000000000000; + let downshift: Field = 1 / two_pow_120; + + // determine whether we need to borrow from more significant limbs. + // initial limb is "simple" comparison operation + // TODO: check how expensive `lt` operator is w.r.t. witness generation + borrow_flags[0] = mulout_p[0].lt(mulout_n[0]) as Field; + // we have 2N - 2 borrow flags. The number of limbs from our product computation is 2N - 1 + // and there is nothing to borrow against for the final limb. + let mut hi_bits = (mulout_p[0] - mulout_n[0] + (borrow_flags[0] * borrow_shift)) * downshift; + for i in 1..(N + N - 2) { + // compute the contribution from limb `i-1` that gets added into limb `i`, and add into limb `i` + // let hi_bits = (mulout_p.get(i - 1) - mulout_n.get(i - 1) + (borrow_flags.get(i - 1) * borrow_shift)) + // * downshift; + mulout_p[i] += hi_bits; + + // determine whether negative limb values are greater than positive limb values + let underflow: Field = mulout_p[i].lt(mulout_n[i] + (borrow_flags[i - 1] * borrow_carry)) as Field; + borrow_flags[i] = underflow; + + hi_bits = (mulout_p[i] - mulout_n[i] + (borrow_flags[i] * borrow_shift) + - (borrow_flags[i - 1] * borrow_carry)) * downshift; + } + + (quotient, remainder, borrow_flags) +} + +/** +* @brief Computes the result of a linear combination of (possibly negative) BigNum values (unconstrained) +**/ +// NOTE: modulus2 is structured such that all limbs will be greater than 0, even when subtracting. +// To do this, when computing `p - x`, we ensure that each limb in `p` is greater than each limb in `x`. +// We know that, for a valid bignum element, the limbs in `x` will be <2^{120} +// Therefore each of the limbs in `p` (except the most significant) will borrow 2^{120} from the more significant limb. +// Finally, to ensure we do not underflow in the most significant limb, we use `2p` instead of `p` +unconstrained fn __add_linear_expression( + params: P, + x: [[Field; N]; M], + flags: [bool; M] +) -> ([Field; N]) { + // TODO, validate we do not overflow N2 when multiplying and N when adding + let mut sum: [Field; N] = [0; N]; + // TODO: ugly! Will fail if input array is empty + let modulus2: [Field; N] = params.double_modulus; + for i in 0..M { + if (flags[i]) { + for j in 0..N { + sum[j] = sum[j] + modulus2[j] - x[i][j]; + assert(x[i][j].lt(modulus2[j])); + } + } else { + for j in 0..N { + sum[j] = sum[j] + x[i][j]; + } + } + } + // problem if we normalize when used in computing quotient + sum +} + +/** +* @brief computes the limb products of a quadratic expression +* @details see __compute_quadratic_expression_with_borrow_flags for full description +**/ +unconstrained fn __compute_quadratic_expression_product< + let N: u32, + let LHS_N: u32, + let RHS_N: u32, + let NUM_PRODUCTS: u32, + let ADD_N: u32 +>( + params: P, + lhs_terms: [[[Field; N]; LHS_N]; NUM_PRODUCTS], + lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], + rhs_terms: [[[Field; N]; RHS_N]; NUM_PRODUCTS], + rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], + linear_terms: [[Field; N]; ADD_N], + linear_flags: [bool; ADD_N] +) -> [Field; 2 * N] { + // TODO, validate we do not overflow N2 when multiplying and N when adding + let mut lhs: [[Field; N]; NUM_PRODUCTS] = [[0; N]; NUM_PRODUCTS]; + let mut rhs: [[Field; N]; NUM_PRODUCTS] = [[0; N]; NUM_PRODUCTS]; + let mut add: [Field; N] = [0; N]; + + for i in 0..NUM_PRODUCTS { + lhs[i] = __add_linear_expression(params, lhs_terms[i], lhs_flags[i]); + rhs[i] = __add_linear_expression(params, rhs_terms[i], rhs_flags[i]); + } + + let add: [Field; N] = __add_linear_expression(params, linear_terms, linear_flags); + + let mut mulout: [Field; 2 * N] = [0; 2 * N]; + + for i in 0..N { + for j in 0..N { + for k in 0..NUM_PRODUCTS { + mulout[i + j] += (lhs[k][i] * rhs[k][j]); + } + } + mulout[i] += add[i]; + } + mulout +} + +/** +* @brief computes the quotient/remainder of a quadratic expression +* @details see __compute_quadratic_expression_with_borrow_flags for full description +**/ +unconstrained pub(crate) fn __compute_quadratic_expression< + let N: u32, + let LHS_N: u32, + let RHS_N: u32, + let NUM_PRODUCTS: u32, + let ADD_N: u32 +>( + params: P, + lhs_terms: [[[Field; N]; LHS_N]; NUM_PRODUCTS], + lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], + rhs_terms: [[[Field; N]; RHS_N]; NUM_PRODUCTS], + rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], + linear_terms: [[Field; N]; ADD_N], + linear_flags: [bool; ADD_N] +) -> ([Field; N], [Field; N]) { + // TODO, validate we do not overflow N2 when multiplying and N when adding + let mulout = __compute_quadratic_expression_product( + params, + lhs_terms, + lhs_flags, + rhs_terms, + rhs_flags, + linear_terms, + linear_flags + ); + let mut relation_result: [Field; 2 * N] = split_bits::__normalize_limbs(mulout, 2 * N); + + // TODO: ugly! Will fail if input slice is empty + let modulus_bits_getter = params.modulus_bits_getter; + let k = modulus_bits_getter(); + + let (quotient, remainder) = __barrett_reduction( + relation_result, + params.redc_param, + k, + params.modulus, + params.modulus_u60_x4 + ); + + let mut q = quotient; + let mut r = remainder; + (q, r) +} + +/** +* @brief Constrain a degree-2 BigNum expression to be equal to 0 modulo self.modulus +* @description The expression is of the form (when evaluated as an integer relation): +* +* \sum_{i=0}^{NUM_PRODUCTS - 1} ((\sum_{j=0}^{LHS_N-1}lhs[i][j]) * (\sum_{j=0}^{RHS_N-1}rhs[i][j])) + \sum_{i=0}^{ADD_N - 1}linear_terms[i] - quotient * modulus = 0 +* +* The intent is to capture an arbitrary degree-2 expression within the limitations of Noir (no efficient dynamically-sized vectors) +* +* Note: this method requires the remainder term of the expression to be ZERO +* When performing BigNum arithmetic, we want to represent desired BigNum operations in a way that minimizes the number of modular reductions that are required. +* This can be achieved by minimizing the number of degree-2 relations required. +* +* The expensive parts of this algorithm are the following: +* 1. evaluating the limb products required to compute `lhs * rhs` +* 2. applying range constraints to validate the result is 0 +* +* Range constraints are needed for the following reason: +* When evaluating the above expression over N-limb BigNum objects, the result will consist of 2N - 1 limbs. +* Each limb will be in the range [0, ..., 2^{240 + twiddle_factor} - 1] (twiddle_factor needs to be less than 6). +* Because of the subtractions, the limbs may underflow and represent NEGATIVE values. +* To account for this, we allow the Prover to borrow values from more significant limbs and add them into less significant limbs +* (explicitly, we can borrow 2^{126} from limb `i + 1` to add `2^{246}` into `i`). +* To ensure this has been done correctly, we validate that the borrow-adjusted limbs are all-zero for the first 120 bits. +* We do *this* by multiplying the borrow-adjusted limbs by 1 / 2^{120} modulo CircutModulus, and we validate the result is in the range [0, ..., 2^{126} - 1]. +* TODO: explain why this check works. It's statistically sound but not perfectly sound. Chance of the check failing is ~1 in 2^{120} +* I believe this is the most efficient way of performing the zero-check for this relation as it only requires `2N - 2` 126-bit range checks. +* TODO: explain why we apply a 126-bit range check, this feels like a magic number +* (it is. we could go higher, up to the number of bits in the CircuitModulus - 121, but 126 *should be* sufficient and is much cheaper) +* TODO: apply checks in this method to validate twiddle_factor does not exceed 6 +* +* @param lhs_terms a 2D array of BigNum +* @param lhs_flags a 2D array of sign flags +* @param rhs_terms a 2D array of BigNum +* @param rhs_flags a 2D array of sign flags +* @param linear_terms an array of BigNum +* @param linear_flags an array of sign flags +**/ +pub(crate) fn evaluate_quadratic_expression< + let N: u32, + let LHS_N: u32, + let RHS_N: u32, + let NUM_PRODUCTS: u32, + let ADD_N: u32 +>( + params: P, + lhs_terms: [[[Field; N]; LHS_N]; NUM_PRODUCTS], + lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], + rhs_terms: [[[Field; N]; RHS_N]; NUM_PRODUCTS], + rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], + linear_terms: [[Field; N]; ADD_N], + linear_flags: [bool; ADD_N] +) { + // use an unconstrained function to compute the value of the quotient + let (quotient, _, borrow_flags): ([Field; N], [Field; N], [Field; 2 * N]) = unsafe { + __compute_quadratic_expression_with_borrow_flags( + params, + lhs_terms, + lhs_flags, + rhs_terms, + rhs_flags, + linear_terms, + linear_flags + ) + }; + // constrain the quotient to be in the range [0, ..., 2^{m} - 1], where `m` is log2(modulus) rounded up. + // Additionally, validate quotient limbs are also in the range [0, ..., 2^{120} - 1] + validate_quotient_in_range(params, quotient); + // TODO, validate we do not overflow N2 when multiplying and N when adding + // (should be a compile-time check...unconstrained function?) + + // Compute the linear sums that represent lhs_1, rhs_1, lhs_2, rhs_2, add + let mut t0: [[Field; N]; NUM_PRODUCTS] = [[0; N]; NUM_PRODUCTS]; + let mut t1: [[Field; N]; NUM_PRODUCTS] = [[0; N]; NUM_PRODUCTS]; + let mut t4: [Field; N] = [0; N]; + + // TODO: this is super nasty as it requires a multiplication + let double_modulus: [Field; N] = params.double_modulus; + for k in 0..NUM_PRODUCTS { + for i in 0..N { + for j in 0..LHS_N { + // note: if is_negative is not known at comptime this is very expensive + if (lhs_flags[k][j]) { + t0[k][i] -= lhs_terms[k][j][i]; + t0[k][i] += double_modulus[i]; + } else { + t0[k][i] += lhs_terms[k][j][i]; + } + } + for j in 0..RHS_N { + if (rhs_flags[k][j]) { + t1[k][i] -= rhs_terms[k][j][i]; + t1[k][i] += double_modulus[i]; + } else { + t1[k][i] += rhs_terms[k][j][i]; + } + } + } + } + for i in 0..N { + for j in 0..ADD_N { + if (linear_flags[j]) { + t4[i] -= linear_terms[j][i]; + t4[i] += double_modulus[i]; + } else { + t4[i] += linear_terms[j][i]; + } + } + } + + // We want to evaluate that t0 * t1 + t2 * t3 + t4 - Quotient * Modulus = 0, evaluated over the integers + // For this we need to be able to borrow values from more-significant limbs into less-significant limbs, + // so that we can ensure that no limbs will underflow for an honest Prover + let mut product_limbs: [Field; 2 * N] = [0; 2 * N]; + + // Compute the product t0 * t1 + t2 * t3 + t4 - Quotient * Modulus + // TODO: this is super nasty as it requires a multiplication + for i in 0..N { + for j in 0..N { + for k in 0..NUM_PRODUCTS { + if k == 0 { + let new_term = t0[k][i] * t1[k][j] - quotient[i] * params.modulus[j]; + std::as_witness(new_term); // width-4 optimization (n.b. might not be optimal if t2, t3 input arrays are nonzero) + product_limbs[i + j] += new_term; + } else { + product_limbs[i + j] += t0[k][i] * t1[k][j]; + } + } + if (NUM_PRODUCTS == 0) { + product_limbs[i + j] -= quotient[i] * params.modulus[j]; + } + } + product_limbs[i] += t4[i]; + } + + // each limb product represents the sum of 120-bit products. + // by setting the borrow value to 2^246 we are restricting this method's completeness to expressions + // where no more than 64 limb products are summed together. + // TODO: check in unconstrained function that this condition is satisfied + // TODO: define trade-offs regarding the value of borrow_shift + // (the larger the value, the greater the range check that is required on product_limbs) + // (126-bit range check is a sweet spot for the barretenberg backend as it decomposes into 9 14-bit range checks) + // (the barretenberg backend can evaluate these in 5.25 gates. 127 bits costs 6.5 gates) + let borrow_shift: Field = 0x40000000000000000000000000000000000000000000000000000000000000; // 2^{246} + let borrow_carry: Field = 0x40000000000000000000000000000000; // 2^{246 - 120} = 2^{126} + + // N.B. borrow_flags is `Field` type because making it `bool` would apply boolean constraints to all `N2` array entries. + // We only use `N2 - 2` borrow flags so applying 1-bit range checks on the array elements we use is more efficient. + // TODO: Once it is possible to perform arithmetic on generics we can use `borrow_flags: [bool;N+N-2]` to avoid this issue + borrow_flags[0].assert_max_bit_size(1); + product_limbs[0] += borrow_flags[0] * borrow_shift; + for i in 1..(N + N - 2) { + borrow_flags[i].assert_max_bit_size(1); + product_limbs[i] += + (borrow_flags[i] * borrow_shift - borrow_flags[i - 1] * borrow_carry); + } + product_limbs[N + N - 2] -= borrow_flags[N + N - 3] * borrow_carry; + + // Final step: Validate `product_limbs` represents the integer value `0` + // Each element `i` in `product_limbs` overlaps in bitrange with element `i+1`, EXCEPT for the low 120 bits + // i.e. we need to do the following for each limb `i`: + // 1. validate the limb's low-120 bits equals zero + // 2. compute the limb "carry" by right-shifting by 2^{120} + // 3. add the carry into limb `i+1` + // We can efficiently do all of the above by multiplying the limb by 2^{-120} and constraining the result to be <2^{126} + // (if the low 120 bits are nonzero the result will underflow and product a large value that cannot be range constrained) + // (the probability of an underflow value satisfying a 126-bit range constraint is approx. 2^{k - 126}, + // where k is the number of bits in the prime field) + // We then add the result into the next limb and repeat. + let hi_shift: Field = 0x1000000000000000000000000000000; + let hi_downshift: Field = 1 / hi_shift; + for i in 0..N + N - 2 { + product_limbs[i] *= hi_downshift; + std::as_witness(product_limbs[i]); + product_limbs[i].assert_max_bit_size(126); // N.B. is this sufficient? going beyond 126 costs us 1 gate per limb + product_limbs[i + 1] += product_limbs[i]; + } + // the most significant limb has no limb to "carry" values into - the entire limb must equal zero + assert(product_limbs[N + N - 2] == 0); +} diff --git a/src/fields/U1024.nr b/src/fields/U1024.nr index a024bbbe..aedfd269 100644 --- a/src/fields/U1024.nr +++ b/src/fields/U1024.nr @@ -1,41 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct U1024Params {} -impl RuntimeBigNumParamsTrait<9> for U1024Params { - fn modulus_bits() -> u32 { - 1025 - } - fn has_multiplicative_inverse() -> bool { - false - } -} +global U1024_PARAMS: BigNumParams<9> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 1025, + modulus: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000000000000000 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffffffffffffff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x040000000000000000 + ] +}; + +struct U1024Params {} + impl BigNumParamsTrait<9> for U1024Params { - fn get_instance() -> BigNumInstance<9, Self> { - U1024_Instance - } - fn modulus_bits() -> u32 { - 1025 - } - fn has_multiplicative_inverse() -> bool { - false + fn get_params() -> BigNumParams<9> { + U1024_PARAMS } } -global U1024_Instance: BigNumInstance<9, U1024Params> = BigNumInstance { - modulus: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000000000000000 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffffffffffffff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x040000000000000000 - ] -}; diff --git a/src/fields/U2048.nr b/src/fields/U2048.nr index 3394e44f..a677b974 100644 --- a/src/fields/U2048.nr +++ b/src/fields/U2048.nr @@ -1,41 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct U2048Params {} -impl RuntimeBigNumParamsTrait<18> for U2048Params { - fn modulus_bits() -> u32 { - 2049 - } - fn has_multiplicative_inverse() -> bool { - false - } -} +global U2048_PARAMS: BigNumParams<18> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 2049, + modulus: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0400 + ] +}; + +struct U2048Params {} + impl BigNumParamsTrait<18> for U2048Params { - fn get_instance() -> BigNumInstance<18, Self> { - U2048_Instance - } - fn modulus_bits() -> u32 { - 2049 - } - fn has_multiplicative_inverse() -> bool { - false + fn get_params() -> BigNumParams<18> { + U2048_PARAMS } } -global U2048_Instance: BigNumInstance<18, U2048Params> = BigNumInstance { - modulus: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0400 - ] -}; diff --git a/src/fields/U256.nr b/src/fields/U256.nr index 258ef2e5..10951b32 100644 --- a/src/fields/U256.nr +++ b/src/fields/U256.nr @@ -1,40 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct U256Params {} -impl RuntimeBigNumParamsTrait<3> for U256Params { - fn modulus_bits() -> u32 { - 257 - } - fn has_multiplicative_inverse() -> bool { - false - } -} +global U256_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 257, + modulus: [ + 0x00, 0x00, 0x010000 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0x01ffff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x040000 + ] +}; + +pub struct U256Params {} + impl BigNumParamsTrait<3> for U256Params { - fn get_instance() -> BigNumInstance<3, Self> { - U256_Instance - } - fn modulus_bits() -> u32 { - 257 - } - fn has_multiplicative_inverse() -> bool { - false + fn get_params() -> BigNumParams<3> { + U256_PARAMS } } -global U256_Instance: BigNumInstance<3, U256Params> = BigNumInstance { - modulus: [ - 0x00, 0x00, 0x010000 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0x01ffff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x040000 - ] -}; + diff --git a/src/fields/U384.nr b/src/fields/U384.nr index b827d680..59a47181 100644 --- a/src/fields/U384.nr +++ b/src/fields/U384.nr @@ -1,41 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct U384_Params {} -impl RuntimeBigNumParamsTrait<4> for U384_Params { - fn modulus_bits() -> u32 { - 385 - } - fn has_multiplicative_inverse() -> bool { - false - } -} +global U384_PARAMS: BigNumParams<4> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 385, + modulus: [ + 0x00, 0x00, 0x00, 0x01000000 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x00, 0x04000000 + ] +}; + +struct U384_Params {} + impl BigNumParamsTrait<4> for U384_Params { - fn get_instance() -> BigNumInstance<4, Self> { - U384_Instance - } - fn modulus_bits() -> u32 { - 385 - } - fn has_multiplicative_inverse() -> bool { - false + fn get_params() -> BigNumParams<4> { + U384_PARAMS } } -global U384_Instance: BigNumInstance<4, U384_Params> = BigNumInstance { - modulus: [ - 0x00, 0x00, 0x00, 0x01000000 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x00, 0x04000000 - ] -}; diff --git a/src/fields/U4096.nr b/src/fields/U4096.nr index 806e2a5d..88b84fc2 100644 --- a/src/fields/U4096.nr +++ b/src/fields/U4096.nr @@ -1,41 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct U4096Params {} -impl RuntimeBigNumParamsTrait<35> for U4096Params { - fn modulus_bits() -> u32 { - 4097 - } - fn has_multiplicative_inverse() -> bool { - false - } -} +global U4096_PARAMS: BigNumParams<35> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 4097, + modulus: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x040000 + ] +}; + +struct U4096Params {} + impl BigNumParamsTrait<35> for U4096Params { - fn get_instance() -> BigNumInstance<35, Self> { - U4096_Instance - } - fn modulus_bits() -> u32 { - 4097 - } - fn has_multiplicative_inverse() -> bool { - false + fn get_params() -> BigNumParams<35> { + U4096_PARAMS } } -global U4096_Instance: BigNumInstance<35, U4096Params> = BigNumInstance { - modulus: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x040000 - ] -}; diff --git a/src/fields/U512.nr b/src/fields/U512.nr index b49c20bc..4aa93f3c 100644 --- a/src/fields/U512.nr +++ b/src/fields/U512.nr @@ -1,32 +1,10 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -// a / b = c - -// b * c + (rem < modulus) = a -pub struct U512Params {} -impl RuntimeBigNumParamsTrait<5> for U512Params { - fn modulus_bits() -> u32 { - 513 - } - fn has_multiplicative_inverse() -> bool { - false - } -} -impl BigNumParamsTrait<5> for U512Params { - fn get_instance() -> BigNumInstance<5, Self> { - U512_Instance - } - fn modulus_bits() -> u32 { - 513 - } - fn has_multiplicative_inverse() -> bool { - false - } -} -global U512_Instance: BigNumInstance<5, U512Params> = BigNumInstance { +global U512_PARAMS: BigNumParams<5> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 513, modulus: [ 0x00, 0x00, 0x00, 0x00, 0x0100000000 ], @@ -41,3 +19,12 @@ global U512_Instance: BigNumInstance<5, U512Params> = BigNumInstance { 0x00, 0x00, 0x00, 0x00, 0x0400000000 ] }; + +struct U512Params {} + +impl BigNumParamsTrait<5> for U512Params { + fn get_params() -> BigNumParams<5> { + U512_PARAMS + } +} + diff --git a/src/fields/U768.nr b/src/fields/U768.nr index b5a41ec7..98223e1a 100644 --- a/src/fields/U768.nr +++ b/src/fields/U768.nr @@ -1,41 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct U768Params {} -impl RuntimeBigNumParamsTrait<13> for U768Params { - fn modulus_bits() -> u32 { - 1537 - } - fn has_multiplicative_inverse() -> bool { - false - } -} +global U768_PARAMS: BigNumParams<13> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 1537, + modulus: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000000000000000000000 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffffffffffffffffffffff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1000000000]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1000000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04000000000000000000000000 + ] +}; + +struct U768Params {} + impl BigNumParamsTrait<13> for U768Params { - fn get_instance() -> BigNumInstance<13, Self> { - U768_Instance - } - fn modulus_bits() -> u32 { - 1537 - } - fn has_multiplicative_inverse() -> bool { - false + fn get_params() -> BigNumParams<13> { + U768_PARAMS } } -global U768_Instance: BigNumInstance<13, U768Params> = BigNumInstance { - modulus: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000000000000000000000 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffffffffffffffffffffff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1000000000]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1000000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04000000000000000000000000 - ] -}; diff --git a/src/fields/U8192.nr b/src/fields/U8192.nr index 089e16bb..5c4951b2 100644 --- a/src/fields/U8192.nr +++ b/src/fields/U8192.nr @@ -1,41 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct U8192Params {} -impl RuntimeBigNumParamsTrait<69> for U8192Params { - fn modulus_bits() -> u32 { - 8193 - } - fn has_multiplicative_inverse() -> bool { - false - } -} +global U8192_PARAMS: BigNumParams<69> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 8193, + modulus: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100000000 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffffff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100000000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0400000000 + ] +}; + +struct U8192Params {} + impl BigNumParamsTrait<69> for U8192Params { - fn get_instance() -> BigNumInstance<69, Self> { - U8192_Instance - } - fn modulus_bits() -> u32 { - 8193 - } - fn has_multiplicative_inverse() -> bool { - false + fn get_params() -> BigNumParams<69> { + U8192_PARAMS } } -global U8192_Instance: BigNumInstance<69, U8192Params> = BigNumInstance { - modulus: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100000000 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffffff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100000000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0400000000 - ] -}; diff --git a/src/fields/bls12_377Fq.nr b/src/fields/bls12_377Fq.nr index 7c13ca1b..7d876a83 100644 --- a/src/fields/bls12_377Fq.nr +++ b/src/fields/bls12_377Fq.nr @@ -16,38 +16,33 @@ //! * G1 curve equation: y^2 = x^3 + 1 //! * G2 curve equation: y^2 = x^3 + B, where //! * B = Fq2(0, 155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906) -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; +global BLS12_377_Fq_PARAMS: BigNumParams<4> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 377, + modulus: [ + 0x0b5d44300000008508c00000000001, 0xd9f300f5138f1ef3622fba09480017, 0x4617c510eac63b05c06ca1493b1a22, 0x01ae3a + ], + double_modulus: [ + 0x0116ba88600000010a11800000000002, 0x01b3e601ea271e3de6c45f741290002d, 0x018c2f8a21d58c760b80d94292763444, 0x035c73 + ], + modulus_u60: U60Repr { limbs: [ + 0x0508c00000000001, 0xb5d44300000008, 0x03622fba09480017, 0x0d9f300f5138f1ef, 0x05c06ca1493b1a22, 0x04617c510eac63b0, 0x01ae3a, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0508c00000000001, 0xb5d44300000008, 0x03622fba09480017, 0x0d9f300f5138f1ef, 0x05c06ca1493b1a22, 0x04617c510eac63b0, 0x01ae3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0xed687789c42a591f9fd58c5e4daffc, 0xd0de6776b1a06af2d488d85a6d02d0, 0x8d0cc4060e976c3ca0582ef4f73bba, 0x026150 + ] +}; + pub struct BLS12_377_Fq_Params {} -impl RuntimeBigNumParamsTrait<4> for BLS12_377_Fq_Params { - fn modulus_bits() -> u32 { - 377 - } -} + impl BigNumParamsTrait<4> for BLS12_377_Fq_Params { - fn get_instance() -> BigNumInstance<4, Self> { - BLS12_377_Fq_Instance - } - fn modulus_bits() -> u32 { - 377 + fn get_params() -> BigNumParams<4> { + BLS12_377_Fq_PARAMS } } -global BLS12_377_Fq_Instance: BigNumInstance<4, BLS12_377_Fq_Params> = BigNumInstance { - modulus: [ - 0x0b5d44300000008508c00000000001, 0xd9f300f5138f1ef3622fba09480017, 0x4617c510eac63b05c06ca1493b1a22, 0x01ae3a - ], - double_modulus: [ - 0x0116ba88600000010a11800000000002, 0x01b3e601ea271e3de6c45f741290002d, 0x018c2f8a21d58c760b80d94292763444, 0x035c73 - ], - modulus_u60: U60Repr { limbs: [ - 0x0508c00000000001, 0xb5d44300000008, 0x03622fba09480017, 0x0d9f300f5138f1ef, 0x05c06ca1493b1a22, 0x04617c510eac63b0, 0x01ae3a, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0508c00000000001, 0xb5d44300000008, 0x03622fba09480017, 0x0d9f300f5138f1ef, 0x05c06ca1493b1a22, 0x04617c510eac63b0, 0x01ae3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xed687789c42a591f9fd58c5e4daffc, 0xd0de6776b1a06af2d488d85a6d02d0, 0x8d0cc4060e976c3ca0582ef4f73bba, 0x026150 - ] -}; diff --git a/src/fields/bls12_377Fr.nr b/src/fields/bls12_377Fr.nr index c44c18cf..572e9358 100644 --- a/src/fields/bls12_377Fr.nr +++ b/src/fields/bls12_377Fr.nr @@ -16,38 +16,33 @@ //! * G1 curve equation: y^2 = x^3 + 1 //! * G2 curve equation: y^2 = x^3 + B, where //! * B = Fq2(0, 155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906) -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct BLS12_377_Fr_Params {} -impl RuntimeBigNumParamsTrait<3> for BLS12_377_Fr_Params { - fn modulus_bits() -> u32 { - 253 - } -} +global BLS12_377_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 253, + modulus: [ + 0xaa76fed00000010a11800000000001, 0x655e9a2ca55660b44d1e5c37b00159, 0x12ab + ], + double_modulus: [ + 0x0154edfda00000021423000000000002, 0x01cabd34594aacc1689a3cb86f6002b2, 0x2555 + ], + modulus_u60: U60Repr { limbs: [ + 0x0a11800000000001, 0x0aa76fed00000010, 0x044d1e5c37b00159, 0x0655e9a2ca55660b, 0x12ab, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0a11800000000001, 0x0aa76fed00000010, 0x044d1e5c37b00159, 0x0655e9a2ca55660b, 0x12ab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x0a180b8d69e258f5204c21151e79ea, 0x491ec40b2c9ee4e51e49faa80548fd, 0x36d9 + ] +}; + +struct BLS12_377_Fr_Params {} + impl BigNumParamsTrait<3> for BLS12_377_Fr_Params { - fn get_instance() -> BigNumInstance<3, Self> { - BLS12_377_Fr_Instance - } - fn modulus_bits() -> u32 { - 253 + fn get_params() -> BigNumParams<3> { + BLS12_377_Fr_PARAMS } } -global BLS12_377_Fr_Instance: BigNumInstance<3, BLS12_377_Fr_Params> = BigNumInstance { - modulus: [ - 0xaa76fed00000010a11800000000001, 0x655e9a2ca55660b44d1e5c37b00159, 0x12ab - ], - double_modulus: [ - 0x0154edfda00000021423000000000002, 0x01cabd34594aacc1689a3cb86f6002b2, 0x2555 - ], - modulus_u60: U60Repr { limbs: [ - 0x0a11800000000001, 0x0aa76fed00000010, 0x044d1e5c37b00159, 0x0655e9a2ca55660b, 0x12ab, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0a11800000000001, 0x0aa76fed00000010, 0x044d1e5c37b00159, 0x0655e9a2ca55660b, 0x12ab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x0a180b8d69e258f5204c21151e79ea, 0x491ec40b2c9ee4e51e49faa80548fd, 0x36d9 - ] -}; diff --git a/src/fields/bls12_381Fq.nr b/src/fields/bls12_381Fq.nr index f788c44f..fea750f9 100644 --- a/src/fields/bls12_381Fq.nr +++ b/src/fields/bls12_381Fq.nr @@ -14,38 +14,33 @@ //! * valuation(r - 1, 2) = 32 //! * G1 curve equation: y^2 = x^3 + 4 //! * G2 curve equation: y^2 = x^3 + Fq2(4, 4) -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct BLS12_381_Fq_Params {} -impl RuntimeBigNumParamsTrait<4> for BLS12_381_Fq_Params { - fn modulus_bits() -> u32 { - 381 - } -} +global BLS12_381_Fq_PARAMS: BigNumParams<4> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 381, + modulus: [ + 0xabfffeb153ffffb9feffffffffaaab, 0x4b84f38512bf6730d2a0f6b0f6241e, 0xea397fe69a4b1ba7b6434bacd76477, 0x1a0111 + ], + double_modulus: [ + 0x0157fffd62a7ffff73fdffffffff5556, 0x019709e70a257ece61a541ed61ec483c, 0x01d472ffcd3496374f6c869759aec8ed, 0x340222 + ], + modulus_u60: U60Repr { limbs: [ + 0x09feffffffffaaab, 0x0abfffeb153ffffb, 0xd2a0f6b0f6241e, 0x04b84f38512bf673, 0x07b6434bacd76477, 0x0ea397fe69a4b1ba, 0x1a0111, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x09feffffffffaaab, 0x0abfffeb153ffffb, 0xd2a0f6b0f6241e, 0x04b84f38512bf673, 0x07b6434bacd76477, 0x0ea397fe69a4b1ba, 0x1a0111, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x65c59e8163c701ec4f881fd59646e8, 0x09d07fda82a52f7d1dc780a19de74e, 0x4bcf32791738a0406c331e9ae8a46e, 0x2760d7 + ] +}; + +struct BLS12_381_Fq_Params {} + impl BigNumParamsTrait<4> for BLS12_381_Fq_Params { - fn get_instance() -> BigNumInstance<4, Self> { - BLS12_381_Fq_Instance - } - fn modulus_bits() -> u32 { - 381 + fn get_params() -> BigNumParams<4> { + BLS12_381_Fq_PARAMS } } -global BLS12_381_Fq_Instance: BigNumInstance<4, BLS12_381_Fq_Params> = BigNumInstance { - modulus: [ - 0xabfffeb153ffffb9feffffffffaaab, 0x4b84f38512bf6730d2a0f6b0f6241e, 0xea397fe69a4b1ba7b6434bacd76477, 0x1a0111 - ], - double_modulus: [ - 0x0157fffd62a7ffff73fdffffffff5556, 0x019709e70a257ece61a541ed61ec483c, 0x01d472ffcd3496374f6c869759aec8ed, 0x340222 - ], - modulus_u60: U60Repr { limbs: [ - 0x09feffffffffaaab, 0x0abfffeb153ffffb, 0xd2a0f6b0f6241e, 0x04b84f38512bf673, 0x07b6434bacd76477, 0x0ea397fe69a4b1ba, 0x1a0111, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x09feffffffffaaab, 0x0abfffeb153ffffb, 0xd2a0f6b0f6241e, 0x04b84f38512bf673, 0x07b6434bacd76477, 0x0ea397fe69a4b1ba, 0x1a0111, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x65c59e8163c701ec4f881fd59646e8, 0x09d07fda82a52f7d1dc780a19de74e, 0x4bcf32791738a0406c331e9ae8a46e, 0x2760d7 - ] -}; diff --git a/src/fields/bls12_381Fr.nr b/src/fields/bls12_381Fr.nr index 89b4a1dd..6f968dd8 100644 --- a/src/fields/bls12_381Fr.nr +++ b/src/fields/bls12_381Fr.nr @@ -14,37 +14,32 @@ //! * valuation(r - 1, 2) = 32 //! * G1 curve equation: y^2 = x^3 + 4 //! * G2 curve equation: y^2 = x^3 + Fq2(4, 4) -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct BLS12_381_Fr_Params {} -impl RuntimeBigNumParamsTrait<3> for BLS12_381_Fr_Params { - fn modulus_bits() -> u32 { - 255 - } -} +global BLS12_381_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 255, + modulus: [ + 0xbda402fffe5bfeffffffff00000001, 0xa753299d7d483339d80809a1d80553, 0x73ed + ], + double_modulus: [ + 0x017b4805fffcb7fdfffffffe00000002, 0x014ea6533afa906673b0101343b00aa6, 0xe7da + ], + modulus_u60: U60Repr { limbs: [ + 0x0fffffff00000001, 0x0bda402fffe5bfef, 0x09d80809a1d80553, 0x0a753299d7d48333, 0x73ed, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0fffffff00000001, 0x0bda402fffe5bfef, 0x09d80809a1d80553, 0x0a753299d7d48333, 0x73ed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x410fad2f92eb5c509cde80830358e4, 0x253b7fb78ddf0e2d772dc1f823b4d9, 0x8d54 + ] +}; + +struct BLS12_381_Fr_Params {} impl BigNumParamsTrait<3> for BLS12_381_Fr_Params { - fn get_instance() -> BigNumInstance<3, Self> { - BLS12_381_Fr_Instance - } - fn modulus_bits() -> u32 { - 255 + fn get_params() -> BigNumParams<3> { + BLS12_381_Fr_PARAMS } } -global BLS12_381_Fr_Instance: BigNumInstance<3, BLS12_381_Fr_Params> = BigNumInstance { - modulus: [ - 0xbda402fffe5bfeffffffff00000001, 0xa753299d7d483339d80809a1d80553, 0x73ed - ], - double_modulus: [ - 0x017b4805fffcb7fdfffffffe00000002, 0x014ea6533afa906673b0101343b00aa6, 0xe7da - ], - modulus_u60: U60Repr { limbs: [ - 0x0fffffff00000001, 0x0bda402fffe5bfef, 0x09d80809a1d80553, 0x0a753299d7d48333, 0x73ed, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0fffffff00000001, 0x0bda402fffe5bfef, 0x09d80809a1d80553, 0x0a753299d7d48333, 0x73ed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x410fad2f92eb5c509cde80830358e4, 0x253b7fb78ddf0e2d772dc1f823b4d9, 0x8d54 - ] -}; + diff --git a/src/fields/bn254Fq.nr b/src/fields/bn254Fq.nr index 0d40eba2..61a4d7f9 100644 --- a/src/fields/bn254Fq.nr +++ b/src/fields/bn254Fq.nr @@ -1,36 +1,29 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct BNParams {} -impl RuntimeBigNumParamsTrait<3> for BNParams { - fn modulus_bits() -> u32 { - 254 - } -} - -global BN254INSTANCE: BigNumInstance<3, BNParams> = BigNumInstance { - modulus: [ - 0x816a916871ca8d3c208c16d87cfd47, 0x4e72e131a029b85045b68181585d97, 0x3064 - ], - double_modulus: [ - 0x0102d522d0e3951a7841182db0f9fa8e, 0x019ce5c263405370a08b6d0302b0bb2e, 0x60c7 - ], - modulus_u60: U60Repr { limbs: [ - 0x0c208c16d87cfd47, 0x0816a916871ca8d3, 0x45b68181585d97, 0x04e72e131a029b85, 0x3064, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0c208c16d87cfd47, 0x0816a916871ca8d3, 0x45b68181585d97, 0x04e72e131a029b85, 0x3064, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x965e1767cd4c086f3aed8a19bf90e5, 0x7462623a04a7ab074a5868073013ae, 0x54a4 - ] +global BN254_Fq_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 254, + modulus: [ + 0x816a916871ca8d3c208c16d87cfd47, 0x4e72e131a029b85045b68181585d97, 0x3064 + ], + double_modulus: [ + 0x0102d522d0e3951a7841182db0f9fa8e, 0x019ce5c263405370a08b6d0302b0bb2e, 0x60c7 + ], + modulus_u60: U60Repr { limbs: [ + 0x0c208c16d87cfd47, 0x0816a916871ca8d3, 0x45b68181585d97, 0x04e72e131a029b85, 0x3064, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0c208c16d87cfd47, 0x0816a916871ca8d3, 0x45b68181585d97, 0x04e72e131a029b85, 0x3064, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x965e1767cd4c086f3aed8a19bf90e5, 0x7462623a04a7ab074a5868073013ae, 0x54a4 + ] }; -impl BigNumParamsTrait<3> for BNParams { - fn get_instance() -> BigNumInstance<3, Self> { - BN254INSTANCE - } - fn modulus_bits() -> u32 { - 254 +pub struct BN254_Fq_Params {} + +impl BigNumParamsTrait<3> for BN254_Fq_Params { + fn get_params() -> BigNumParams<3> { + BN254_Fq_PARAMS } } diff --git a/src/fields/ed25519Fq.nr b/src/fields/ed25519Fq.nr index cf7cb667..e610153f 100644 --- a/src/fields/ed25519Fq.nr +++ b/src/fields/ed25519Fq.nr @@ -1,35 +1,30 @@ -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; -use crate::BigNumParamsTrait as BigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct ED25519_Fq_Params {} -impl RuntimeBigNumParamsTrait<3> for ED25519_Fq_Params { - fn modulus_bits() -> u32 { - 255 - } -} +global ED25519_Fq_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 255, + modulus: [ + 0xffffffffffffffffffffffffffffed, 0xffffffffffffffffffffffffffffff, 0x7fff + ], + double_modulus: [ + 0x01ffffffffffffffffffffffffffffda, 0x01fffffffffffffffffffffffffffffe, 0xfffe + ], + modulus_u60: U60Repr { limbs: [ + 0x0fffffffffffffed, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x7fff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0fffffffffffffed, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x7fff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x13, 0x00, 0x8000 + ] +}; + +struct ED25519_Fq_Params {} + impl BigNumParamsTrait<3> for ED25519_Fq_Params { - fn get_instance() -> BigNumInstance<3, Self> { - ED25519_Fq_Instance - } - fn modulus_bits() -> u32 { - 255 + fn get_params() -> BigNumParams<3> { + ED25519_Fq_PARAMS } } -global ED25519_Fq_Instance: BigNumInstance<3, ED25519_Fq_Params> = BigNumInstance { - modulus: [ - 0xffffffffffffffffffffffffffffed, 0xffffffffffffffffffffffffffffff, 0x7fff - ], - double_modulus: [ - 0x01ffffffffffffffffffffffffffffda, 0x01fffffffffffffffffffffffffffffe, 0xfffe - ], - modulus_u60: U60Repr { limbs: [ - 0x0fffffffffffffed, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x7fff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0fffffffffffffed, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x7fff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x13, 0x00, 0x8000 - ] -}; diff --git a/src/fields/ed25519Fr.nr b/src/fields/ed25519Fr.nr index 26734582..9df6e099 100644 --- a/src/fields/ed25519Fr.nr +++ b/src/fields/ed25519Fr.nr @@ -1,35 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct ED25519_Fr_Params {} -impl RuntimeBigNumParamsTrait<3> for ED25519_Fr_Params { - fn modulus_bits() -> u32 { - 253 - } -} +global ED25519_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 253, + modulus: [ + 0xdef9dea2f79cd65812631a5cf5d3ed, 0x14, 0x1000 + ], + double_modulus: [ + 0x01bdf3bd45ef39acb024c634b9eba7da, 0x01000000000000000000000000000028, 0x1fff + ], + modulus_u60: U60Repr { limbs: [ + 0x0812631a5cf5d3ed, 0x0def9dea2f79cd65, 0x14, 0x00, 0x1000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0812631a5cf5d3ed, 0x0def9dea2f79cd65, 0x14, 0x00, 0x1000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x84188574218ca69fb673968c28b04c, 0xffffffffffffffffffffffffffffac, 0x3fff + ] +}; + +struct ED25519_Fr_Params {} + impl BigNumParamsTrait<3> for ED25519_Fr_Params { - fn get_instance() -> BigNumInstance<3, Self> { - ED25519_Fr_Instance - } - fn modulus_bits() -> u32 { - 253 + fn get_params() -> BigNumParams<3> { + ED25519_Fr_PARAMS } } -global ED25519_Fr_Instance: BigNumInstance<3, ED25519_Fr_Params> = BigNumInstance { - modulus: [ - 0xdef9dea2f79cd65812631a5cf5d3ed, 0x14, 0x1000 - ], - double_modulus: [ - 0x01bdf3bd45ef39acb024c634b9eba7da, 0x01000000000000000000000000000028, 0x1fff - ], - modulus_u60: U60Repr { limbs: [ - 0x0812631a5cf5d3ed, 0x0def9dea2f79cd65, 0x14, 0x00, 0x1000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0812631a5cf5d3ed, 0x0def9dea2f79cd65, 0x14, 0x00, 0x1000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x84188574218ca69fb673968c28b04c, 0xffffffffffffffffffffffffffffac, 0x3fff - ] -}; diff --git a/src/fields/mnt4_753Fq.nr b/src/fields/mnt4_753Fq.nr index d2b4df2c..00c84564 100644 --- a/src/fields/mnt4_753Fq.nr +++ b/src/fields/mnt4_753Fq.nr @@ -19,38 +19,33 @@ //! * B = Fq2(0, b * NON_RESIDUE) //! * NON_RESIDUE = 13 is the quadratic non-residue used to conpub struct the //! extension field Fq2 -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct MNT4_753_Fq_Params {} -impl RuntimeBigNumParamsTrait<7> for MNT4_753_Fq_Params { - fn modulus_bits() -> u32 { - 753 - } -} +global MNT4_753_Fq_PARAMS: BigNumParams<7> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 753, + modulus: [ + 0x9d54522cdd119f5e9063de245e8001, 0xcce9767254a4638810719ac425f0e3, 0x76f218059db80f0da5cb537e38685a, 0xe8a0ed8d99d124d9a15af79db117e7, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 + ], + double_modulus: [ + 0x013aa8a459ba233ebd20c7bc48bd0002, 0x0199d2ece4a948c71020e335884be1c6, 0x01ede4300b3b701e1b4b96a6fc70d0b4, 0x01d141db1b33a249b342b5ef3b622fcd, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 + ], + modulus_u60: U60Repr { limbs: [ + 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x45dcc95da918349f4965a2aee8fd75, 0x282372b75580c27c4d1f1f57a96a11, 0xd58326e3c0552419849e3c7171d852, 0xa300e0ede1965cbf72f0aa9bf03479, 0x67fb932cae2aba9a5d17c1ff73538b, 0xa82727c6eaef38056aaa0aaedb0574, 0x0242f916cf + ] +}; + +struct MNT4_753_Fq_Params {} + impl BigNumParamsTrait<7> for MNT4_753_Fq_Params { - fn get_instance() -> BigNumInstance<7, Self> { - MNT4_753_Fq_Instance - } - fn modulus_bits() -> u32 { - 753 + fn get_params() -> BigNumParams<7> { + MNT4_753_Fq_PARAMS } } -global MNT4_753_Fq_Instance: BigNumInstance<7, MNT4_753_Fq_Params> = BigNumInstance { - modulus: [ - 0x9d54522cdd119f5e9063de245e8001, 0xcce9767254a4638810719ac425f0e3, 0x76f218059db80f0da5cb537e38685a, 0xe8a0ed8d99d124d9a15af79db117e7, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 - ], - double_modulus: [ - 0x013aa8a459ba233ebd20c7bc48bd0002, 0x0199d2ece4a948c71020e335884be1c6, 0x01ede4300b3b701e1b4b96a6fc70d0b4, 0x01d141db1b33a249b342b5ef3b622fcd, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 - ], - modulus_u60: U60Repr { limbs: [ - 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x45dcc95da918349f4965a2aee8fd75, 0x282372b75580c27c4d1f1f57a96a11, 0xd58326e3c0552419849e3c7171d852, 0xa300e0ede1965cbf72f0aa9bf03479, 0x67fb932cae2aba9a5d17c1ff73538b, 0xa82727c6eaef38056aaa0aaedb0574, 0x0242f916cf - ] -}; diff --git a/src/fields/mnt4_753Fr.nr b/src/fields/mnt4_753Fr.nr index 4142fe87..68a9d50a 100644 --- a/src/fields/mnt4_753Fr.nr +++ b/src/fields/mnt4_753Fr.nr @@ -19,38 +19,33 @@ //! * B = Fq2(0, b * NON_RESIDUE) //! * NON_RESIDUE = 13 is the quadratic non-residue used to conpub struct the //! extension field Fq2 -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct MNT4_753_Fr_Params {} -impl RuntimeBigNumParamsTrait<7> for MNT4_753_Fr_Params { - fn modulus_bits() -> u32 { - 753 - } -} +global MNT4_753_Fr_PARAMS: BigNumParams<7> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 753, + modulus: [ + 0xa099170fa13a4fd90776e240000001, 0xf97634993aa4d6c381bc3f0057974e, 0x28c859a99b3eebca9429212636b9df, 0xe8a0ed8d99d124d9a15af79db26c5c, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 + ], + double_modulus: [ + 0x0141322e1f42749fb20eedc480000002, 0x01f2ec69327549ad8703787e00af2e9c, 0x015190b353367dd7952852424c6d73be, 0x01d141db1b33a249b342b5ef3b64d8b7, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 + ], + modulus_u60: U60Repr { limbs: [ + 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0xa2dae11d15867718ec70f5ff059bba, 0x276d65fe7e00ba391da260f2623ff9, 0x8140a086edaa60c58eb476bdedcb35, 0xa300e0ede1965cbf72f0aa9bee8120, 0x67fb932cae2aba9a5d17c1ff73538b, 0xa82727c6eaef38056aaa0aaedb0574, 0x0242f916cf + ] +}; + +struct MNT4_753_Fr_Params {} + impl BigNumParamsTrait<7> for MNT4_753_Fr_Params { - fn get_instance() -> BigNumInstance<7, Self> { - MNT4_753_Fr_Instance - } - fn modulus_bits() -> u32 { - 753 + fn get_params() -> BigNumParams<7> { + MNT4_753_Fr_PARAMS } } -global MNT4_753_Fr_Instance: BigNumInstance<7, MNT4_753_Fr_Params> = BigNumInstance { - modulus: [ - 0xa099170fa13a4fd90776e240000001, 0xf97634993aa4d6c381bc3f0057974e, 0x28c859a99b3eebca9429212636b9df, 0xe8a0ed8d99d124d9a15af79db26c5c, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 - ], - double_modulus: [ - 0x0141322e1f42749fb20eedc480000002, 0x01f2ec69327549ad8703787e00af2e9c, 0x015190b353367dd7952852424c6d73be, 0x01d141db1b33a249b342b5ef3b64d8b7, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 - ], - modulus_u60: U60Repr { limbs: [ - 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xa2dae11d15867718ec70f5ff059bba, 0x276d65fe7e00ba391da260f2623ff9, 0x8140a086edaa60c58eb476bdedcb35, 0xa300e0ede1965cbf72f0aa9bee8120, 0x67fb932cae2aba9a5d17c1ff73538b, 0xa82727c6eaef38056aaa0aaedb0574, 0x0242f916cf - ] -}; diff --git a/src/fields/mnt6_753Fq.nr b/src/fields/mnt6_753Fq.nr index c581c569..2ed18388 100644 --- a/src/fields/mnt6_753Fq.nr +++ b/src/fields/mnt6_753Fq.nr @@ -19,38 +19,33 @@ //! * B = Fq3(b * NON_RESIDUE, 0, 0) //! * NON_RESIDUE = 11 is the cubic non-residue used to conpub struct the //! extension field Fq3 -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct MNT6_753_Fq_Params {} -impl RuntimeBigNumParamsTrait<7> for MNT6_753_Fq_Params { - fn modulus_bits() -> u32 { - 753 - } -} +global MNT6_753_Fq_PARAMS: BigNumParams<7> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 753, + modulus: [ + 0xa099170fa13a4fd90776e240000001, 0xf97634993aa4d6c381bc3f0057974e, 0x28c859a99b3eebca9429212636b9df, 0xe8a0ed8d99d124d9a15af79db26c5c, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 + ], + double_modulus: [ + 0x0141322e1f42749fb20eedc480000002, 0x01f2ec69327549ad8703787e00af2e9c, 0x015190b353367dd7952852424c6d73be, 0x01d141db1b33a249b342b5ef3b64d8b7, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 + ], + modulus_u60: U60Repr { limbs: [ + 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0xa2dae11d15867718ec70f5ff059bba, 0x276d65fe7e00ba391da260f2623ff9, 0x8140a086edaa60c58eb476bdedcb35, 0xa300e0ede1965cbf72f0aa9bee8120, 0x67fb932cae2aba9a5d17c1ff73538b, 0xa82727c6eaef38056aaa0aaedb0574, 0x0242f916cf + ] +}; + +struct MNT6_753_Fq_Params {} + impl BigNumParamsTrait<7> for MNT6_753_Fq_Params { - fn get_instance() -> BigNumInstance<7, Self> { - MNT6_753_Fq_Instance - } - fn modulus_bits() -> u32 { - 753 + fn get_params() -> BigNumParams<7> { + MNT6_753_Fq_PARAMS } } -global MNT6_753_Fq_Instance: BigNumInstance<7, MNT6_753_Fq_Params> = BigNumInstance { - modulus: [ - 0xa099170fa13a4fd90776e240000001, 0xf97634993aa4d6c381bc3f0057974e, 0x28c859a99b3eebca9429212636b9df, 0xe8a0ed8d99d124d9a15af79db26c5c, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 - ], - double_modulus: [ - 0x0141322e1f42749fb20eedc480000002, 0x01f2ec69327549ad8703787e00af2e9c, 0x015190b353367dd7952852424c6d73be, 0x01d141db1b33a249b342b5ef3b64d8b7, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 - ], - modulus_u60: U60Repr { limbs: [ - 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xa2dae11d15867718ec70f5ff059bba, 0x276d65fe7e00ba391da260f2623ff9, 0x8140a086edaa60c58eb476bdedcb35, 0xa300e0ede1965cbf72f0aa9bee8120, 0x67fb932cae2aba9a5d17c1ff73538b, 0xa82727c6eaef38056aaa0aaedb0574, 0x0242f916cf - ] -}; diff --git a/src/fields/mnt6_753Fr.nr b/src/fields/mnt6_753Fr.nr index cb83e360..7f88e572 100644 --- a/src/fields/mnt6_753Fr.nr +++ b/src/fields/mnt6_753Fr.nr @@ -19,38 +19,33 @@ //! * B = Fq3(b * NON_RESIDUE, 0, 0) //! * NON_RESIDUE = 11 is the cubic non-residue used to conpub struct the //! extension field Fq3 -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct MNT6_753_Fr_Params {} -impl RuntimeBigNumParamsTrait<7> for MNT6_753_Fr_Params { - fn modulus_bits() -> u32 { - 753 - } -} +global MNT6_753_Fr_PARAMS: BigNumParams<7> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 753, + modulus: [ + 0x9d54522cdd119f5e9063de245e8001, 0xcce9767254a4638810719ac425f0e3, 0x76f218059db80f0da5cb537e38685a, 0xe8a0ed8d99d124d9a15af79db117e7, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 + ], + double_modulus: [ + 0x013aa8a459ba233ebd20c7bc48bd0002, 0x0199d2ece4a948c71020e335884be1c6, 0x01ede4300b3b701e1b4b96a6fc70d0b4, 0x01d141db1b33a249b342b5ef3b622fcd, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 + ], + modulus_u60: U60Repr { limbs: [ + 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x45dcc95da918349f4965a2aee8fd75, 0x282372b75580c27c4d1f1f57a96a11, 0xd58326e3c0552419849e3c7171d852, 0xa300e0ede1965cbf72f0aa9bf03479, 0x67fb932cae2aba9a5d17c1ff73538b, 0xa82727c6eaef38056aaa0aaedb0574, 0x0242f916cf + ] +}; + +struct MNT6_753_Fr_Params {} + impl BigNumParamsTrait<7> for MNT6_753_Fr_Params { - fn get_instance() -> BigNumInstance<7, Self> { - MNT6_753_Fr_Instance - } - fn modulus_bits() -> u32 { - 753 + fn get_params() -> BigNumParams<7> { + MNT6_753_Fr_PARAMS } } -global MNT6_753_Fr_Instance: BigNumInstance<7, MNT6_753_Fr_Params> = BigNumInstance { - modulus: [ - 0x9d54522cdd119f5e9063de245e8001, 0xcce9767254a4638810719ac425f0e3, 0x76f218059db80f0da5cb537e38685a, 0xe8a0ed8d99d124d9a15af79db117e7, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 - ], - double_modulus: [ - 0x013aa8a459ba233ebd20c7bc48bd0002, 0x0199d2ece4a948c71020e335884be1c6, 0x01ede4300b3b701e1b4b96a6fc70d0b4, 0x01d141db1b33a249b342b5ef3b622fcd, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 - ], - modulus_u60: U60Repr { limbs: [ - 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x45dcc95da918349f4965a2aee8fd75, 0x282372b75580c27c4d1f1f57a96a11, 0xd58326e3c0552419849e3c7171d852, 0xa300e0ede1965cbf72f0aa9bf03479, 0x67fb932cae2aba9a5d17c1ff73538b, 0xa82727c6eaef38056aaa0aaedb0574, 0x0242f916cf - ] -}; diff --git a/src/fields/mod.nr b/src/fields/mod.nr index db44ec3d..b2b8802c 100644 --- a/src/fields/mod.nr +++ b/src/fields/mod.nr @@ -28,42 +28,9 @@ pub mod U2048; pub mod U4096; pub mod U8192; -pub use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::bignum::BigNum; +use bn254Fq::BN254_Fq_Params; + +// example typedef when using a defined bignum instance +type Fq = BigNum<3, BN254_Fq_Params>; -/** - * @brief Parameter definitions for generic fields of varying bit lengths - * (these can be used when defining modular fields where the - * modulus is a witness value and cannot be predefined - * e.g. 2048-bit RSA) - **/ -pub struct Params512 {} -impl RuntimeBigNumParamsTrait<5> for Params512 { - fn modulus_bits() -> u32 { - 512 - } -} -pub struct Params768 {} -impl RuntimeBigNumParamsTrait<7> for Params768 { - fn modulus_bits() -> u32 { - 768 - } -} -pub struct Params1024 {} -impl RuntimeBigNumParamsTrait<9> for Params1024 { - fn modulus_bits() -> u32 { - 1024 - } -} -pub struct Params2048 {} -impl RuntimeBigNumParamsTrait<18> for Params2048 { - fn modulus_bits() -> u32 { - 2048 - } -} -pub struct Params4096 {} -impl RuntimeBigNumParamsTrait<35> for Params4096 { - fn modulus_bits() -> u32 { - 4096 - } -} diff --git a/src/fields/pallasFq.nr b/src/fields/pallasFq.nr index af652727..06023e1a 100644 --- a/src/fields/pallasFq.nr +++ b/src/fields/pallasFq.nr @@ -13,38 +13,33 @@ //! * Curve equation: y^2 = x^3 + 5 //! * Valuation(q - 1, 2) = 32 //! * Valuation(r - 1, 2) = 32 -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct Pallas_Fq_Params {} -impl RuntimeBigNumParamsTrait<3> for Pallas_Fq_Params { - fn modulus_bits() -> u32 { - 255 - } -} +global Pallas_Fq_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 255, + modulus: [ + 0x4698fc094cf91b992d30ed00000001, 0x22, 0x4000 + ], + double_modulus: [ + 0x018d31f81299f237325a61da00000002, 0x01000000000000000000000000000043, 0x7fff + ], + modulus_u60: U60Repr { limbs: [ + 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0xe59c0fdacc1b919b4b3c4bfffffffc, 0xffffffffffffffffffffffffffff76, 0xffff + ] +}; + +struct Pallas_Fq_Params {} + impl BigNumParamsTrait<3> for Pallas_Fq_Params { - fn get_instance() -> BigNumInstance<3, Self> { - Pallas_Fq_Instance - } - fn modulus_bits() -> u32 { - 255 + fn get_params() -> BigNumParams<3> { + Pallas_Fq_PARAMS } } -global Pallas_Fq_Instance: BigNumInstance<3, Pallas_Fq_Params> = BigNumInstance { - modulus: [ - 0x4698fc094cf91b992d30ed00000001, 0x22, 0x4000 - ], - double_modulus: [ - 0x018d31f81299f237325a61da00000002, 0x01000000000000000000000000000043, 0x7fff - ], - modulus_u60: U60Repr { limbs: [ - 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xe59c0fdacc1b919b4b3c4bfffffffc, 0xffffffffffffffffffffffffffff76, 0xffff - ] -}; diff --git a/src/fields/pallasFr.nr b/src/fields/pallasFr.nr index e3960d94..19946f83 100644 --- a/src/fields/pallasFr.nr +++ b/src/fields/pallasFr.nr @@ -13,38 +13,33 @@ //! * Curve equation: y^2 = x^3 + 5 //! * Valuation(q - 1, 2) = 32 //! * Valuation(r - 1, 2) = 32 -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct Pallas_Fr_Params {} -impl RuntimeBigNumParamsTrait<3> for Pallas_Fr_Params { - fn modulus_bits() -> u32 { - 255 - } -} +global Pallas_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 255, + modulus: [ + 0x4698fc0994a8dd8c46eb2100000001, 0x22, 0x4000 + ], + double_modulus: [ + 0x018d31f8132951bb188dd64200000002, 0x01000000000000000000000000000043, 0x7fff + ], + modulus_u60: U60Repr { limbs: [ + 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0xe59c0fd9ad5c89cee4537bfffffffc, 0xffffffffffffffffffffffffffff76, 0xffff + ] +}; + +struct Pallas_Fr_Params {} + impl BigNumParamsTrait<3> for Pallas_Fr_Params { - fn get_instance() -> BigNumInstance<3, Self> { - Pallas_Fr_Instance - } - fn modulus_bits() -> u32 { - 255 + fn get_params() -> BigNumParams<3> { + Pallas_Fr_PARAMS } } -global Pallas_Fr_Instance: BigNumInstance<3, Pallas_Fr_Params> = BigNumInstance { - modulus: [ - 0x4698fc0994a8dd8c46eb2100000001, 0x22, 0x4000 - ], - double_modulus: [ - 0x018d31f8132951bb188dd64200000002, 0x01000000000000000000000000000043, 0x7fff - ], - modulus_u60: U60Repr { limbs: [ - 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xe59c0fd9ad5c89cee4537bfffffffc, 0xffffffffffffffffffffffffffff76, 0xffff - ] -}; diff --git a/src/fields/secp256k1Fq.nr b/src/fields/secp256k1Fq.nr index 1f3741e3..9f11555a 100644 --- a/src/fields/secp256k1Fq.nr +++ b/src/fields/secp256k1Fq.nr @@ -1,35 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct Secp256k1_Fq_Params {} -impl RuntimeBigNumParamsTrait<3> for Secp256k1_Fq_Params { - fn modulus_bits() -> u32 { - 256 - } -} +global Secp256k1_Fq_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 256, + modulus: [ + 0xfffffffffffffffffffffefffffc2f, 0xffffffffffffffffffffffffffffff, 0xffff + ], + double_modulus: [ + 0x01fffffffffffffffffffffdfffff85e, 0x01fffffffffffffffffffffffffffffe, 0x01fffe + ], + modulus_u60: U60Repr { limbs: [ + 0x0ffffffefffffc2f, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0ffffffefffffc2f, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x01000003d1, 0x00, 0x010000 + ] +}; + +struct Secp256k1_Fq_Params {} + impl BigNumParamsTrait<3> for Secp256k1_Fq_Params { - fn get_instance() -> BigNumInstance<3, Self> { - Secp256k1_Fq_Instance - } - fn modulus_bits() -> u32 { - 256 + fn get_params() -> BigNumParams<3> { + Secp256k1_Fq_PARAMS } } -global Secp256k1_Fq_Instance: BigNumInstance<3, Secp256k1_Fq_Params> = BigNumInstance { - modulus: [ - 0xfffffffffffffffffffffefffffc2f, 0xffffffffffffffffffffffffffffff, 0xffff - ], - double_modulus: [ - 0x01fffffffffffffffffffffdfffff85e, 0x01fffffffffffffffffffffffffffffe, 0x01fffe - ], - modulus_u60: U60Repr { limbs: [ - 0x0ffffffefffffc2f, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0ffffffefffffc2f, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x01000003d1, 0x00, 0x010000 - ] -}; diff --git a/src/fields/secp256k1Fr.nr b/src/fields/secp256k1Fr.nr index 6d604ead..0ce1a703 100644 --- a/src/fields/secp256k1Fr.nr +++ b/src/fields/secp256k1Fr.nr @@ -1,35 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct Secp256k1_Fr_Params {} -impl RuntimeBigNumParamsTrait<3> for Secp256k1_Fr_Params { - fn modulus_bits() -> u32 { - 256 - } -} +global Secp256k1_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 256, + modulus: [ + 0xaedce6af48a03bbfd25e8cd0364141, 0xfffffffffffffffffffffffffffeba, 0xffff + ], + double_modulus: [ + 0x015db9cd5e9140777fa4bd19a06c8282, 0x01fffffffffffffffffffffffffffd74, 0x01fffe + ], + modulus_u60: U60Repr { limbs: [ + 0x0fd25e8cd0364141, 0x0aedce6af48a03bb, 0x0ffffffffffffeba, 0x0fffffffffffffff, 0xffff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0fd25e8cd0364141, 0x0aedce6af48a03bb, 0x0ffffffffffffeba, 0x0fffffffffffffff, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x51231950b75fc4402da1732fc9bec0, 0x0145, 0x010000 + ] +}; + +struct Secp256k1_Fr_Params {} + impl BigNumParamsTrait<3> for Secp256k1_Fr_Params { - fn get_instance() -> BigNumInstance<3, Self> { - Secp256k1_Fr_Instance - } - fn modulus_bits() -> u32 { - 256 + fn get_params() -> BigNumParams<3> { + Secp256k1_Fr_PARAMS } } -global Secp256k1_Fr_Instance: BigNumInstance<3, Secp256k1_Fr_Params> = BigNumInstance { - modulus: [ - 0xaedce6af48a03bbfd25e8cd0364141, 0xfffffffffffffffffffffffffffeba, 0xffff - ], - double_modulus: [ - 0x015db9cd5e9140777fa4bd19a06c8282, 0x01fffffffffffffffffffffffffffd74, 0x01fffe - ], - modulus_u60: U60Repr { limbs: [ - 0x0fd25e8cd0364141, 0x0aedce6af48a03bb, 0x0ffffffffffffeba, 0x0fffffffffffffff, 0xffff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0fd25e8cd0364141, 0x0aedce6af48a03bb, 0x0ffffffffffffeba, 0x0fffffffffffffff, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x51231950b75fc4402da1732fc9bec0, 0x0145, 0x010000 - ] -}; diff --git a/src/fields/secp256r1Fq.nr b/src/fields/secp256r1Fq.nr index 2023f04a..56fb42d5 100644 --- a/src/fields/secp256r1Fq.nr +++ b/src/fields/secp256r1Fq.nr @@ -1,35 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct Secp256r1_Fq_Params {} -impl RuntimeBigNumParamsTrait<3> for Secp256r1_Fq_Params { - fn modulus_bits() -> u32 { - 256 - } -} +global Secp256r1_Fq_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 256, + modulus: [ + 0xffffffffffffffffffffffff, 0xffff00000001000000000000000000, 0xffff + ], + double_modulus: [ + 0x01000001fffffffffffffffffffffffe, 0x01fffe00000001ffffffffffffffffff, 0x01fffe + ], + modulus_u60: U60Repr { limbs: [ + 0x0fffffffffffffff, 0x0fffffffff, 0x00, 0x0ffff00000001000, 0xffff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0fffffffffffffff, 0x0fffffffff, 0x00, 0x0ffff00000001000, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0xfffffeffffffff0000000000000003, 0xfffffffffffffffefffffffeff, 0x010000 + ] +}; + +struct Secp256r1_Fq_Params {} + impl BigNumParamsTrait<3> for Secp256r1_Fq_Params { - fn get_instance() -> BigNumInstance<3, Self> { - Secp256r1_Fq_Instance - } - fn modulus_bits() -> u32 { - 256 + fn get_params() -> BigNumParams<3> { + Secp256r1_Fq_PARAMS } } -global Secp256r1_Fq_Instance: BigNumInstance<3, Secp256r1_Fq_Params> = BigNumInstance { - modulus: [ - 0xffffffffffffffffffffffff, 0xffff00000001000000000000000000, 0xffff - ], - double_modulus: [ - 0x01000001fffffffffffffffffffffffe, 0x01fffe00000001ffffffffffffffffff, 0x01fffe - ], - modulus_u60: U60Repr { limbs: [ - 0x0fffffffffffffff, 0x0fffffffff, 0x00, 0x0ffff00000001000, 0xffff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0fffffffffffffff, 0x0fffffffff, 0x00, 0x0ffff00000001000, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xfffffeffffffff0000000000000003, 0xfffffffffffffffefffffffeff, 0x010000 - ] -}; diff --git a/src/fields/secp256r1Fr.nr b/src/fields/secp256r1Fr.nr index e028721b..7b1cc7b9 100644 --- a/src/fields/secp256r1Fr.nr +++ b/src/fields/secp256r1Fr.nr @@ -1,35 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct Secp256r1_Fr_Params {} -impl RuntimeBigNumParamsTrait<3> for Secp256r1_Fr_Params { - fn modulus_bits() -> u32 { - 256 - } -} +global Secp256r1_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 256, + modulus: [ + 0xe6faada7179e84f3b9cac2fc632551, 0xffff00000000ffffffffffffffffbc, 0xffff + ], + double_modulus: [ + 0x01cdf55b4e2f3d09e7739585f8c64aa2, 0x01fffe00000001ffffffffffffffff78, 0x01fffe + ], + modulus_u60: U60Repr { limbs: [ + 0x03b9cac2fc632551, 0x0e6faada7179e84f, 0x0fffffffffffffbc, 0x0ffff00000000fff, 0xffff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x03b9cac2fc632551, 0x0e6faada7179e84f, 0x0fffffffffffffbc, 0x0ffff00000000fff, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x190552df1a6c21012ffd85eedf9bfe, 0xfffffffffffffffeffffffff43, 0x010000 + ] +}; + +struct Secp256r1_Fr_Params {} + impl BigNumParamsTrait<3> for Secp256r1_Fr_Params { - fn get_instance() -> BigNumInstance<3, Self> { - Secp256r1_Fr_Instance - } - fn modulus_bits() -> u32 { - 256 + fn get_params() -> BigNumParams<3> { + Secp256r1_Fr_PARAMS } } -global Secp256r1_Fr_Instance: BigNumInstance<3, Secp256r1_Fr_Params> = BigNumInstance { - modulus: [ - 0xe6faada7179e84f3b9cac2fc632551, 0xffff00000000ffffffffffffffffbc, 0xffff - ], - double_modulus: [ - 0x01cdf55b4e2f3d09e7739585f8c64aa2, 0x01fffe00000001ffffffffffffffff78, 0x01fffe - ], - modulus_u60: U60Repr { limbs: [ - 0x03b9cac2fc632551, 0x0e6faada7179e84f, 0x0fffffffffffffbc, 0x0ffff00000000fff, 0xffff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x03b9cac2fc632551, 0x0e6faada7179e84f, 0x0fffffffffffffbc, 0x0ffff00000000fff, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x190552df1a6c21012ffd85eedf9bfe, 0xfffffffffffffffeffffffff43, 0x010000 - ] -}; diff --git a/src/fields/secp384r1Fq.nr b/src/fields/secp384r1Fq.nr index ccb39ef5..22814829 100644 --- a/src/fields/secp384r1Fq.nr +++ b/src/fields/secp384r1Fq.nr @@ -1,35 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct Secp384r1_Fq_Params {} -impl RuntimeBigNumParamsTrait<4> for Secp384r1_Fq_Params { - fn modulus_bits() -> u32 { - 384 - } -} +global Secp384r1_Fq_PARAMS: BigNumParams<4> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 384, + modulus: [ + 0xffffff0000000000000000ffffffff, 0xfffffffffffffffffffffffffffeff, 0xffffffffffffffffffffffffffffff, 0xffffff + ], + double_modulus: [ + 0x01fffffe0000000000000001fffffffe, 0x01fffffffffffffffffffffffffffdfe, 0x01fffffffffffffffffffffffffffffe, 0x01fffffe + ], + modulus_u60: U60Repr { limbs: [ + 0xffffffff, 0x0ffffff000000000, 0x0ffffffffffffeff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0xffffffff, 0x0ffffff000000000, 0x0ffffffffffffeff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0xffffffffffffffff00000001, 0x0100, 0x00, 0x01000000 + ] +}; + +struct Secp384r1_Fq_Params {} + impl BigNumParamsTrait<4> for Secp384r1_Fq_Params { - fn get_instance() -> BigNumInstance<4, Self> { - Secp384r1_Fq_Instance - } - fn modulus_bits() -> u32 { - 384 + fn get_params() -> BigNumParams<4> { + Secp384r1_Fq_PARAMS } } -global Secp384r1_Fq_Instance: BigNumInstance<4, Secp384r1_Fq_Params> = BigNumInstance { - modulus: [ - 0xffffff0000000000000000ffffffff, 0xfffffffffffffffffffffffffffeff, 0xffffffffffffffffffffffffffffff, 0xffffff - ], - double_modulus: [ - 0x01fffffe0000000000000001fffffffe, 0x01fffffffffffffffffffffffffffdfe, 0x01fffffffffffffffffffffffffffffe, 0x01fffffe - ], - modulus_u60: U60Repr { limbs: [ - 0xffffffff, 0x0ffffff000000000, 0x0ffffffffffffeff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0xffffffff, 0x0ffffff000000000, 0x0ffffffffffffeff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xffffffffffffffff00000001, 0x0100, 0x00, 0x01000000 - ] -}; diff --git a/src/fields/secp384r1Fr.nr b/src/fields/secp384r1Fr.nr index 6ed9764d..76d95078 100644 --- a/src/fields/secp384r1Fr.nr +++ b/src/fields/secp384r1Fr.nr @@ -1,35 +1,30 @@ -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct Secp384r1_Fr_Params {} -impl RuntimeBigNumParamsTrait<4> for Secp384r1_Fr_Params { - fn modulus_bits() -> u32 { - 384 - } -} +global Secp384r1_Fr_PARAMS: BigNumParams<4> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 384, + modulus: [ + 0x1a0db248b0a77aecec196accc52973, 0xffffffffffffc7634d81f4372ddf58, 0xffffffffffffffffffffffffffffff, 0xffffff + ], + double_modulus: [ + 0x01341b6491614ef5d9d832d5998a52e6, 0x01ffffffffffff8ec69b03e86e5bbeaf, 0x01fffffffffffffffffffffffffffffe, 0x01fffffe + ], + modulus_u60: U60Repr { limbs: [ + 0x0cec196accc52973, 0x01a0db248b0a77ae, 0x034d81f4372ddf58, 0x0ffffffffffffc76, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0cec196accc52973, 0x01a0db248b0a77ae, 0x034d81f4372ddf58, 0x0ffffffffffffc76, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0xe5f24db74f58851313e695333ad68d, 0x389cb27e0bc8d220a7, 0x00, 0x01000000 + ] +}; + +struct Secp384r1_Fr_Params {} + impl BigNumParamsTrait<4> for Secp384r1_Fr_Params { - fn get_instance() -> BigNumInstance<4, Self> { - Secp384r1_Fr_Instance - } - fn modulus_bits() -> u32 { - 384 + fn get_params() -> BigNumParams<4> { + Secp384r1_Fr_PARAMS } } -global Secp384r1_Fr_Instance: BigNumInstance<4, Secp384r1_Fr_Params> = BigNumInstance { - modulus: [ - 0x1a0db248b0a77aecec196accc52973, 0xffffffffffffc7634d81f4372ddf58, 0xffffffffffffffffffffffffffffff, 0xffffff - ], - double_modulus: [ - 0x01341b6491614ef5d9d832d5998a52e6, 0x01ffffffffffff8ec69b03e86e5bbeaf, 0x01fffffffffffffffffffffffffffffe, 0x01fffffe - ], - modulus_u60: U60Repr { limbs: [ - 0x0cec196accc52973, 0x01a0db248b0a77ae, 0x034d81f4372ddf58, 0x0ffffffffffffc76, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0cec196accc52973, 0x01a0db248b0a77ae, 0x034d81f4372ddf58, 0x0ffffffffffffc76, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xe5f24db74f58851313e695333ad68d, 0x389cb27e0bc8d220a7, 0x00, 0x01000000 - ] -}; diff --git a/src/fields/vestaFq.nr b/src/fields/vestaFq.nr index fbbefe93..202eb2be 100644 --- a/src/fields/vestaFq.nr +++ b/src/fields/vestaFq.nr @@ -14,38 +14,33 @@ //! * Curve equation: y^2 = x^3 + 5 //! * Valuation(q - 1, 2) = 32 //! * Valuation(r - 1, 2) = 32 -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct Vesta_Fq_Params {} -impl RuntimeBigNumParamsTrait<3> for Vesta_Fq_Params { - fn modulus_bits() -> u32 { - 255 - } -} +global Vesta_Fq_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 255, + modulus: [ + 0x4698fc0994a8dd8c46eb2100000001, 0x22, 0x4000 + ], + double_modulus: [ + 0x018d31f8132951bb188dd64200000002, 0x01000000000000000000000000000043, 0x7fff + ], + modulus_u60: U60Repr { limbs: [ + 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0xe59c0fd9ad5c89cee4537bfffffffc, 0xffffffffffffffffffffffffffff76, 0xffff + ] +}; + +struct Vesta_Fq_Params {} + impl BigNumParamsTrait<3> for Vesta_Fq_Params { - fn get_instance() -> BigNumInstance<3, Self> { - Vesta_Fq_Instance - } - fn modulus_bits() -> u32 { - 255 + fn get_params() -> BigNumParams<3> { + Vesta_Fq_PARAMS } } -global Vesta_Fq_Instance: BigNumInstance<3, Vesta_Fq_Params> = BigNumInstance { - modulus: [ - 0x4698fc0994a8dd8c46eb2100000001, 0x22, 0x4000 - ], - double_modulus: [ - 0x018d31f8132951bb188dd64200000002, 0x01000000000000000000000000000043, 0x7fff - ], - modulus_u60: U60Repr { limbs: [ - 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xe59c0fd9ad5c89cee4537bfffffffc, 0xffffffffffffffffffffffffffff76, 0xffff - ] -}; diff --git a/src/fields/vestaFr.nr b/src/fields/vestaFr.nr index d5ef72b1..46e6560b 100644 --- a/src/fields/vestaFr.nr +++ b/src/fields/vestaFr.nr @@ -14,38 +14,33 @@ //! * Curve equation: y^2 = x^3 + 5 //! * Valuation(q - 1, 2) = 32 //! * Valuation(r - 1, 2) = 32 -use crate::BigNumParamsTrait; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; +use crate::params::BigNumParamsTrait; +use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -pub struct Vesta_Fr_Params {} -impl RuntimeBigNumParamsTrait<3> for Vesta_Fr_Params { - fn modulus_bits() -> u32 { - 255 - } -} +global Vesta_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 255, + modulus: [ + 0x4698fc094cf91b992d30ed00000001, 0x22, 0x4000 + ], + double_modulus: [ + 0x018d31f81299f237325a61da00000002, 0x01000000000000000000000000000043, 0x7fff + ], + modulus_u60: U60Repr { limbs: [ + 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0xe59c0fdacc1b919b4b3c4bfffffffc, 0xffffffffffffffffffffffffffff76, 0xffff + ] +}; + +struct Vesta_Fr_Params {} + impl BigNumParamsTrait<3> for Vesta_Fr_Params { - fn get_instance() -> BigNumInstance<3, Self> { - Vesta_Fr_Instance - } - fn modulus_bits() -> u32 { - 255 + fn get_params() -> BigNumParams<3> { + Vesta_Fr_PARAMS } } -global Vesta_Fr_Instance: BigNumInstance<3, Vesta_Fr_Params> = BigNumInstance { - modulus: [ - 0x4698fc094cf91b992d30ed00000001, 0x22, 0x4000 - ], - double_modulus: [ - 0x018d31f81299f237325a61da00000002, 0x01000000000000000000000000000043, 0x7fff - ], - modulus_u60: U60Repr { limbs: [ - 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xe59c0fdacc1b919b4b3c4bfffffffc, 0xffffffffffffffffffffffffffff76, 0xffff - ] -}; diff --git a/src/lib.nr b/src/lib.nr index de450e49..0a315506 100644 --- a/src/lib.nr +++ b/src/lib.nr @@ -1,311 +1,18 @@ -pub(crate) mod utils; +mod utils; +mod fields; + +// Structs +mod params; +mod bignum; +mod runtime_bignum; + +// Functions on structs +mod unconstrained_ops; +mod constrained_ops; +mod unconstrained_helpers; +mod expressions; +mod serialization; + +// Tests mod bignum_test; -pub mod fields; -pub(crate) mod runtime_bignum; mod runtime_bignum_test; - -pub use crate::utils::u60_representation::U60Repr; -pub use crate::runtime_bignum::BigNumInstance as RuntimeBigNumInstance; -pub use crate::runtime_bignum::BigNumInstanceTrait as RuntimeBigNumInstanceTrait; -pub use crate::runtime_bignum::BigNumParamsTrait as RuntimeBigNumParamsTrait; -pub use crate::runtime_bignum::BigNumTrait as RuntimeBigNumTrait; - -pub struct BigNum { - limbs: [Field; N] -} - -/** - * @brief BigNumParamsTrait defines a "field" with which to parametrise BigNum. - * @description The "field" does not need to be prime, any value *should* work (TODO: test!) -**/ -// -// trait BigNumParamsTrait where Params: RuntimeBigNumParamsTrait, RuntimeBigNumInstance: RuntimeBigNumInstanceTrait> { -trait BigNumParamsTrait where Self: RuntimeBigNumParamsTrait { - - fn get_instance() -> RuntimeBigNumInstance where Self: RuntimeBigNumParamsTrait;// ; - - /** - * @brief modulus_bits = log2(modulus) rounded up - **/ - fn modulus_bits() -> u32; - - fn has_multiplicative_inverse() -> bool { true } -} - -trait BigNumTrait where BigNumTrait: std::ops::Add + std::ops::Sub + std::ops::Mul + std::ops::Div + std::ops::Eq + RuntimeBigNumTrait { - // TODO: this crashes the compiler? v0.32 - // fn default() -> Self { std::default::Default::default () } - fn from(limbs: [Field]) -> Self { RuntimeBigNumTrait::from(limbs) } - fn new() -> Self { RuntimeBigNumTrait::new() } - fn one() -> Self { RuntimeBigNumTrait::one() } - fn modulus() -> Self; - fn modulus_bits(self) -> u32; - fn num_limbs(self) -> u32; - fn __derive_from_seed(seed: [u8; SeedBytes]) -> Self; - fn __pow(self, exponent: Self) -> Self; - fn __neg(self) -> Self; - fn __add(self, other: Self) -> Self; - fn __sub(self, other: Self) -> Self; - fn __mul(self, other: Self) -> Self; - fn __div(self, other: Self) -> Self; - fn __udiv_mod(self, divisor: Self) -> (Self, Self); - fn __invmod(self) -> Self; - fn __batch_invert(to_invert: [Self; M]) -> [Self; M]; - fn __is_zero(self) -> bool { RuntimeBigNumTrait::__is_zero(self) } - fn __eq(self, other: Self) -> bool { RuntimeBigNumTrait::__eq(self, other) } - fn __compute_quadratic_expression(lhs: [[Self; LHS_N]; NUM_PRODUCTS], lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], rhs: [[Self; RHS_N]; NUM_PRODUCTS], rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], add: [Self; ADD_N], add_flags: [bool; ADD_N]) -> (Self, Self); - fn evaluate_quadratic_expression(lhs: [[Self; LHS_N]; NUM_PRODUCTS], lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], rhs: [[Self; RHS_N]; NUM_PRODUCTS], rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], add: [Self; ADD_N], add_flags: [bool; ADD_N]); - fn validate_in_range(self){ RuntimeBigNumTrait::validate_in_range(self) } - fn validate_in_field(self); - fn assert_is_not_equal(self, other: Self); - fn neg(self) -> Self; - fn add(self, other: Self) -> Self { self + other } - fn sub(self, other: Self) -> Self { self - other } - fn mul(self, other: Self) -> Self { self * other } - fn div(self, other: Self) -> Self { self / other } - fn udiv_mod(self, divisor: Self) -> (Self, Self); - fn udiv(self, divisor: Self) -> Self; - fn umod(self, divisor: Self) -> Self; - fn eq(self, other: Self) -> bool { self == other } - fn get(self) -> [Field] { RuntimeBigNumTrait::get(self) } - fn get_limb(self, idx: u64) -> Field { RuntimeBigNumTrait::get_limb(self, idx) } - fn set_limb(&mut self, idx: u32, value: Field) { RuntimeBigNumTrait::set_limb(self, idx, value) } - fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self { RuntimeBigNumTrait::conditional_select(lhs, rhs, predicate) } - fn to_le_bytes(self) -> [u8; X] { RuntimeBigNumTrait::to_le_bytes(self) } -} - -impl BigNumTrait for BigNum where Params: BigNumParamsTrait + RuntimeBigNumParamsTrait { - - // Weird compiler issue where if we do not pass `Self` as a parameter to these methods, - // then a generic struct that conforms to BigNumTrait cannot access these methods? - // the Params: BigNumParamsTrait needs to be satisfied, but the BigNumTrait has no knowledge of BigNumParamsTrait? - // but...passing in a Self parameter seems to fix. really weird - fn modulus_bits(_: Self) -> u32 { - let r: u32 = Params::modulus_bits(); - r - } - fn num_limbs(_: Self) -> u32 { - N - } - - fn modulus() -> Self { - Params::get_instance().modulus() - } - - // #################################################################################################################### - // #################################################################################################################### - // ### C O N S T R U C T O R S - // #################################################################################################################### - // #################################################################################################################### - // fn new() -> Self { - // BigNum { limbs: [0; N] } - // } - - // fn one() -> Self { - // let mut result = BigNum::new(); - // result.limbs[0] = 1; - // result - // } - - // #################################################################################################################### - // #################################################################################################################### - // ### U N C O N S T R A I N E D F U N C T I O N S - // ### NOTE: these functions call unconstrained internal implementations because trait impl modifiers are not supported - // #################################################################################################################### - // #################################################################################################################### - fn __derive_from_seed(seed: [u8; SeedBytes]) -> Self { - Params::get_instance().__derive_from_seed(seed) - } - - fn __neg(self) -> Self { - Params::get_instance().__neg(self) - } - - fn __add(self, rhs: Self) -> Self { - Params::get_instance().__add(self, rhs) - } - - fn __sub(self, rhs: Self) -> Self { - Params::get_instance().__sub(self, rhs) - } - - fn __mul(self, rhs: Self) -> Self { - Params::get_instance().__mul(self, rhs) - } - - fn __div(self, rhs: Self) -> Self { - Params::get_instance().__div(self, rhs) - } - - fn __batch_invert(x: [Self; M]) -> [Self; M] { - assert(Params::has_multiplicative_inverse()); - Params::get_instance().__batch_invert(x) - } - - fn __invmod(self) -> Self { - assert(Params::has_multiplicative_inverse()); - Params::get_instance().__invmod(self) - } - - fn __pow(self, exponent: Self) -> Self { - Params::get_instance().__pow(self, exponent) - } - - fn __compute_quadratic_expression( - lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS], - lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], - rhs_terms: [[Self; RHS_N]; NUM_PRODUCTS], - rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], - linear_terms: [Self; ADD_N], - linear_flags: [bool; ADD_N] - ) -> (Self, Self) { - Params::get_instance().__compute_quadratic_expression( - lhs_terms, - lhs_flags, - rhs_terms, - rhs_flags, - linear_terms, - linear_flags - ) - } - - // #################################################################################################################### - // #################################################################################################################### - // ### C O N S T R A I N E D F U N C T I O N S - // #################################################################################################################### - // #################################################################################################################### - - /** - * @brief Constrain a degree-2 BigNum expression to be equal to 0 modulo Params::modulus() - * @description The expression is of the form (when evaluated as an integer relation): - * - * \sum_{i=0}^{NUM_PRODUCTS - 1} ((\sum_{j=0}^{LHS_N-1}lhs[i][j]) * (\sum_{j=0}^{RHS_N-1}rhs[i][j])) + \sum_{i=0}^{ADD_N - 1}linear_terms[i] - quotient * modulus = 0 - * - * The intent is to capture an arbitrary degree-2 expression within the limitations of Noir (no efficient dynamically-sized vectors) - * - * Note: this method requires the remainder term of the expression to be ZERO - * When performing BigNum arithmetic, we want to represent desired BigNum operations in a way that minimizes the number of modular reductions that are required. - * This can be achieved by minimizing the number of degree-2 relations required. - * - * The expensive parts of this algorithm are the following: - * 1. evaluating the limb products required to compute `lhs * rhs` - * 2. applying range constraints to validate the result is 0 - * - * Range constraints are needed for the following reason: - * When evaluating the above expression over N-limb BigNum objects, the result will consist of 2N - 1 limbs. - * Each limb will be in the range [0, ..., 2^{240 + twiddle_factor} - 1] (twiddle_factor needs to be less than 6). - * Because of the subtractions, the limbs may underflow and represent NEGATIVE values. - * To account for this, we allow the Prover to borrow values from more significant limbs and add them into less significant limbs - * (explicitly, we can borrow 2^{126} from limb `i + 1` to add `2^{246}` into `i`). - * To ensure this has been done correctly, we validate that the borrow-adjusted limbs are all-zero for the first 120 bits. - * We do *this* by multiplying the borrow-adjusted limbs by 1 / 2^{120} modulo CircutModulus, and we validate the result is in the range [0, ..., 2^{126} - 1]. - * TODO: explain why this check works. It's statistically sound but not perfectly sound. Chance of the check failing is ~1 in 2^{120} - * I believe this is the most efficient way of performing the zero-check for this relation as it only requires `2N - 2` 126-bit range checks. - * TODO: explain why we apply a 126-bit range check, this feels like a magic number - * (it is. we could go higher, up to the number of bits in the CircuitModulus - 121, but 126 *should be* sufficient and is much cheaper) - * TODO: apply checks in this method to validate twiddle_factor does not exceed 6 - * - * @param lhs_terms a 2D array of BigNum - * @param lhs_flags a 2D array of sign flags - * @param rhs_terms a 2D array of BigNum - * @param rhs_flags a 2D array of sign flags - * @param linear_terms an array of BigNum - * @param linear_flags an array of sign flags - **/ - fn evaluate_quadratic_expression( - lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS], - lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], - rhs_terms: [[Self; RHS_N]; NUM_PRODUCTS], - rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], - linear_terms: [Self; ADD_N], - linear_flags: [bool; ADD_N] - ) { - Params::get_instance().evaluate_quadratic_expression( - lhs_terms, - lhs_flags, - rhs_terms, - rhs_flags, - linear_terms, - linear_flags - ) - } - - fn validate_in_field(self: Self) { - Params::get_instance().validate_in_field(self); - } - - /** - * @brief Validate self != other - * @details If A == B, then A == B mod N. - * We can efficiently evaluate A == B mod N where N = circuit modulus - * This method is *sound*, but not *complete* (i.e. A != B but A == B mod N) - * However the probability of an honest Prover being unable to satisfy this check is tiny! - * (todo: compute how tiny) - **/ - fn assert_is_not_equal(self, other: Self) { - Params::get_instance().assert_is_not_equal(self, other); - } - - fn neg(self) -> Self { - Params::get_instance().neg(self) - } - - fn __udiv_mod(self, divisor: Self) -> (Self, Self) { - Params::get_instance().__udiv_mod(self, divisor) - } - - fn udiv_mod(self, divisor: Self) -> (Self, Self) { - Params::get_instance().udiv_mod(self, divisor) - } - - fn udiv(self, divisor: Self) -> Self { - Params::get_instance().udiv(self, divisor) - } - - fn umod(self, divisor: Self) -> Self { - Params::get_instance().umod(self, divisor) - } -} - -impl BigNum where Params: BigNumParamsTrait + RuntimeBigNumParamsTrait {} - -impl std::ops::Add for BigNum where Params: BigNumParamsTrait + RuntimeBigNumParamsTrait { - // Note: this method is expensive! Try to craft quadratic relations and directly evaluate them - // via evaluate_quadratic_expression - fn add(self, other: Self) -> Self { - Params::get_instance().add(self, other) - } -} - -impl std::ops::Sub for BigNum where Params: BigNumParamsTrait + RuntimeBigNumParamsTrait { - // Note: this method is expensive! Try to craft quadratic relations and directly evaluate them - // via evaluate_quadratic_expression - fn sub(self, other: Self) -> Self { - Params::get_instance().sub(self, other) - } -} - -impl std::ops::Mul for BigNum where Params: BigNumParamsTrait + RuntimeBigNumParamsTrait { - // Note: this method is expensive! Try to craft quadratic relations and directly evaluate them - // via evaluate_quadratic_expression - // e.g. performing a sum of multiple multiplications and additions via `evaluate_quadratic_expression` - // will create much fewer constraints than calling `mul` and `add` directly - fn mul(self, other: Self) -> Self { - Params::get_instance().mul(self, other) - } -} - -impl std::ops::Div for BigNum where Params: BigNumParamsTrait + RuntimeBigNumParamsTrait { - // Note: this method is expensive! Witness computation is extremely expensive as it requires modular exponentiation - fn div(self, other: Self) -> Self { - Params::get_instance().div(self, other) - } -} - -impl std::cmp::Eq for BigNum where Params: BigNumParamsTrait + RuntimeBigNumParamsTrait { - - fn eq(self, other: Self) -> bool { - let bn: RuntimeBigNumInstance = Params::get_instance(); - bn.eq(self, other) - } -} diff --git a/src/params.nr b/src/params.nr new file mode 100644 index 00000000..a9c6046b --- /dev/null +++ b/src/params.nr @@ -0,0 +1,85 @@ +use crate::utils::u60_representation::U60Repr; + +pub(crate) struct BigNumParams { + has_multiplicative_inverse: bool, + + // @brief modulus_bits = log2(modulus) rounded up + // This needs to be a comptime const, so that it can be used as an argument to std::field::assert_constant() + modulus_bits_getter: fn () -> u32, + + // @brief modulus: all BigNum operations are evaluated modulo this value + modulus: [Field; N], + + // @brief modulus but represented in a U60Repr form + modulus_u60: U60Repr, + modulus_u60_x4: U60Repr, + + // @brief double_modulus: used when performing negations and subtractions + double_modulus: [Field; N], + + // @brief redc_param used for __barrett_reduction. See https://en.wikipedia.org/wiki/Barrett_reduction + redc_param: [Field; N], +} + +// To be implemented by the user, or within the prebuilt options in the `fields/` dir. +pub(crate) trait BigNumParamsTrait { + fn get_params() -> BigNumParams; +} + +// To be implemented by the user, or within the prebuilt options in the `fields/` dir. +// pub(crate) trait HasGetModulusBits { +// fn get_modulus_bits() -> u32; // This needs to be a comptime const, so that it can be used as an argument to std::field::assert_constant() +// } + +// impl HasGetModulusBits for BigNumParams {} +// impl RuntimeBigNumParamsTrait for BigNumParams {} + +impl BigNumParams { + fn new( + has_multiplicative_inverse: bool, + modulus_bits_getter: fn() -> u32, + modulus: [Field; N], + redc_param: [Field; N] + ) -> Self { + Self { + has_multiplicative_inverse, + modulus_bits_getter, + modulus, + modulus_u60: U60Repr::from(modulus), + modulus_u60_x4: U60Repr::from(modulus), + double_modulus: get_double_modulus(modulus), + redc_param + } + } +} + +fn get_double_modulus(modulus: [Field; N]) -> [Field; N] { + let TWO_POW_120: Field = 0x1000000000000000000000000000000; + let m: U60Repr = U60Repr::from(modulus); + let mut result: [Field; N] = U60Repr::into(m + m); + + result[0] += TWO_POW_120; + for i in 1..N - 1 { + result[i] += (TWO_POW_120 - 1); + } + result[N - 1] -= 1; + result +} + +// /** +// * @brief BigNumParamsTrait defines a "field" with which to parametrise BigNum. +// * @description The "field" does not need to be prime, any value *should* work (TODO: test!) +// **/ +// trait BigNumParamsTrait { +// fn has_multiplicative_inverse() -> bool; +// // @brief modulus_bits = log2(modulus) rounded up +// fn modulus_bits() -> u32; +// fn modulus() -> [Field; N]; +// fn modulus_u60() -> U60Repr; +// fn modulus_u60_x4() -> U60Repr; +// // @brief double_modulus: used when performing negations and subtractions +// fn double_modulus() -> [Field; N]; +// // redc_param used for __barrett_reduction. See https://en.wikipedia.org/wiki/Barrett_reduction +// redc_param: [Field; N], +// } + diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index cd7e45e9..37280282 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -1,1551 +1,344 @@ -use crate::utils::u60_representation::U60Repr; -use crate::utils::split_bits; -use crate::BigNum; -/** - * @brief runtime_bignum::BigNumTrait defines methods available to BigNum *if* the modulus is not known at compile time. - * e.g. RSA where the modulus is a witness value as it changes for every RSA signature - * tee `lib.nr` for a trait definition where the modulus is known at compile time - **/ -pub trait BigNumTrait { - fn new() -> Self; - fn one() -> Self; - fn from(limbs: [Field]) -> Self; - fn from_be_bytes(x: [u8; NBytes]) -> Self; - fn to_le_bytes(val: Self) -> [u8; NBytes]; - fn get(self) -> [Field]; - fn get_limb(self, idx: u64) -> Field; - fn set_limb(&mut self, idx: u32, value: Field); - fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self; - fn validate_in_range(self); - fn validate_quotient_in_range(self); - fn __is_zero(self) -> bool; - fn __eq(self, rhs: Self) -> bool; -} - -/** - * @brief BigNumInstanceTrait defines methods available to a runtime BigNumInstance. - * BigNumInstance wraps the modulus parameter (as well as a Barret reduction parameter), - * which is required for the majority of BigNum operations - **/ -pub trait BigNumInstanceTrait where BN: BigNumTrait { - fn modulus(self) -> BN; - fn __derive_from_seed(self, seed: [u8; SeedBytes]) -> BN; - fn eq(self, lhs: BN, rhs: BN) -> bool; - fn __neg(self, val: BN) -> BN; - fn __add(self, lhs: BN, rhs: BN) -> BN; - fn __sub(self, lhs: BN, rhs: BN) -> BN; - fn __mul(self, lhs: BN, rhs: BN) -> BN; - fn __div(self, lhs: BN, rhs: BN) -> BN; - fn __batch_invert(self, x: [BN; M]) -> [BN; M]; - fn __udiv_mod(self, numerator: BN, divisor: BN) -> (BN, BN); - fn __invmod(self, val: BN) -> BN; - fn __pow(self, val: BN, exponent: BN) -> BN; - fn __compute_quadratic_expression( - self, - lhs_terms: [[BN; LHS_N]; NUM_PRODUCTS], - lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], - rhs_terms: [[BN; RHS_N]; NUM_PRODUCTS], - rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], - linear_terms: [BN; ADD_N], - linear_flags: [bool; ADD_N] - ) -> (BN, BN); - - fn evaluate_quadratic_expression( - self, - lhs_terms: [[BN; LHS_N]; NUM_PRODUCTS], - lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], - rhs_terms: [[BN; RHS_N]; NUM_PRODUCTS], - rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], - linear_terms: [BN; ADD_N], - linear_flags: [bool; ADD_N] - ); - - fn validate_in_field(self, val: BN); - fn validate_gt(self, lhs: BN, rhs: BN); - fn assert_is_not_equal(self, lhs: BN, rhs: BN); - fn neg(self, val: BN) -> BN; - fn add(self, lhs: BN, rhs: BN) -> BN; - fn sub(self, lhs: BN, rhs: BN) -> BN; - fn mul(self, lhs: BN, rhs: BN) -> BN; - fn div(self, lhs: BN, rhs: BN) -> BN; - fn udiv_mod(self, numerator: BN, divisor: BN) -> (BN, BN); - fn udiv(self, numerator: BN, divisor: BN) -> BN; - fn umod(self, numerator: BN, divisor: BN) -> BN; - -} - -/** - * @brief BigNumParamsTrait defines a "field" with which to parametrise BigNum. - * @description The "field" does not need to be prime, any value *should* work (TODO: test!) -**/ -pub trait BigNumParamsTrait { - /** - * @brief modulus_bits = log2(modulus) rounded up - **/ - fn modulus_bits() -> u32; - - fn has_multiplicative_inverse() -> bool { true } -} - -pub struct BigNumInstance { - - /** - * @brief modulus: all BigNum operations are evaluated modulo this value - **/ - modulus: [Field; N], - - /** - * @brief modulus but represented in a U60Repr form - **/ - modulus_u60: U60Repr, - modulus_u60_x4: U60Repr, - - // /** - // * @brief double_modulus: used when performing negations and subtractions - // **/ - double_modulus: [Field; N], - // /** - // * @brief redc_param used for __barrett_reduction. See https://en.wikipedia.org/wiki/Barrett_reduction - // **/ - redc_param: [Field; N], -} - -impl BigNum { - // some strange circular dependency problem means we need to define `new` as a member of BigNumTrait as well as a definition outside of the trait - // (delete this method to see. BigNumInstance methods that use BigNum::new() error out, and I can't find a way of declaring BigNum to satisfy BigNumTrait as part of the BigNumInstance definition because BigNumInstance has no contextual knowledge of the BigNum type...) - fn new() -> Self { - BigNum { limbs: [0; N] } - } - fn one() -> BigNum { - let mut result: Self = BigNum { limbs: [0; N] }; - result.limbs[0] = 1; - result - } -} - -impl BigNumTrait for BigNum where Params: BigNumParamsTrait { - - fn new() -> Self { - BigNum::new() - } - fn one() -> Self { - BigNum::one() - } - - fn from(limbs: [Field]) -> Self { - BigNum { limbs: limbs.as_array() } - } - - /** - * @brief construct a BigNum instance out of an array of bytes in BIG ENDIAN format - * @description: each 120-bit limb represents 15 bytes, we require that the size of the byte array - * is precisely large enough to cover Params::modulus_bits() - * @param x: input byte array - **/ - fn from_be_bytes(x: [u8; NBytes]) -> BigNum { - let num_bits = NBytes * 8; - let modulus_bits = Params::modulus_bits(); - assert(num_bits >= modulus_bits); - assert(num_bits - modulus_bits < 8); - let mut result = BigNum::new(); - - let excess_bytes = N * 15 - NBytes; - let final_limb_bytes = 15 - excess_bytes; - let mut limb: Field = 0; - let mut k = 0; - for _j in 0..final_limb_bytes { - limb *= 256; - limb += x[k] as Field; - k += 1; - } - result.limbs[N - 1] = limb; - - for i in 1..N { - let mut limb: Field = 0; - for _j in 0..15 { - limb *= 256; - limb += x[k] as Field; - k += 1; - } - result.limbs[N - i - 1] = limb; - } - - // max_bits_in_most_significant_byte should be known at comptime. if not...messy! - let mut max_bits_in_most_significant_byte = 8 - (num_bits - modulus_bits); - - let most_significant_byte: Field = x[0] as Field; - - most_significant_byte.assert_max_bit_size(max_bits_in_most_significant_byte as u32); - result - } - - fn to_le_bytes(val: BigNum) -> [u8; NBytes] { - let nbytes = (Params::modulus_bits() / 8) + (Params::modulus_bits() % 8 != 0) as u32; - assert(nbytes <= NBytes); - - let mut result: [u8; NBytes] = [0; NBytes]; - for i in 0..N - 1 { - let limb_bytes: [u8; 15] = val.limbs[i].to_le_bytes(); - for j in 0..15 { - result[i * 15 + j] = limb_bytes[j]; - } - } - let last_limb_bytes: [u8; 15] = val.limbs[N - 1].to_le_bytes(); - let num_last_bytes = (NBytes - (N - 1) * 15); - for i in 0..num_last_bytes { - result[(N-1) * 15 + i] = last_limb_bytes[i]; - } - result - } - - fn get(self) -> [Field] { - self.limbs - } - fn get_limb(self, idx: u64) -> Field { - self.limbs[idx] - } - fn set_limb(&mut self, idx: u32, value: Field) { - self.limbs[idx] = value; - } - - /** - * @brief conditional_select given the value of `predicate` return either `self` (if 0) or `other` (if 1) - * @description should be cheaper than using an IF statement (TODO: check!) - **/ - fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self { - let mut result: Self = lhs; - for i in 0..N { - result.limbs[i] = (lhs.limbs[i] - rhs.limbs[i]) * predicate as Field + rhs.limbs[i]; - } - result - } - - /** - * @brief Validate a BigNum instance is correctly range constrained to contain no more than Params::modulus_bits() - **/ - fn validate_in_range(self) { - for i in 0..(N - 1) { - self.limbs[i].assert_max_bit_size(120); - } - let final_limb_bits = Params::modulus_bits() - ((N - 1) * 120); - self.limbs[N - 1].assert_max_bit_size(final_limb_bits as u32); - } - - /** - * @brief validate quotient produced from `evaluate_quadratic_expression` is well-formed - * @description because the inputs into evaluate_quadratic_expression may cause the quotient to extend beyond `Params::modulus_bits`. - * We allow the quotient to extend 6 bits beyond Params::modulus_bits() - * Why is this? - * several factors: 1. quotient * modulus , limbs cannot overflow field boundary (254 bits) - * 2. in `evaluate_quadratic_expression`, we require that for `expression - quotient * modulus`, - * limbs cannot exceed 246 bits (246 magic number due to a higher number adding extra range check gates) - * because of factor 2 and the fact that modulus limbs are 120 bits, quotient limbs cannot be >126 bits - * - * Note: doesn't this mean that final_limb_bits should be constrained to be 126 bits, not modulus_bits() - ((N - 1) * 120) + 6? - * TODO: think about this more! we want the range constraint we apply to be as small as allowable as this is more efficient - **/ - fn validate_quotient_in_range(self) { - for i in 0..(N) { - self.limbs[i].assert_max_bit_size(120); - } - // Note: replace magic number 6 with definition - let final_limb_bits = Params::modulus_bits() - ((N - 1) * 120) + 6; - self.limbs[N - 1].assert_max_bit_size(final_limb_bits as u32); - } - - fn __is_zero(self) -> bool { - self.__is_zero_impl() - } - - fn __eq(self, rhs: Self) -> bool { - self.__eq_impl(rhs) - } -} - -impl BigNum where Params: BigNumParamsTrait { - - fn from_array(limbs: [Field; N]) -> BigNum { - BigNum { limbs } - } - - unconstrained fn __is_zero_impl(self) -> bool { - let mut result: bool = true; - for i in 0..N { - result = result & (self.limbs[i] == 0); - } - result - } - - unconstrained fn __eq_impl(lhs: Self, rhs: Self) -> bool { - lhs.limbs == rhs.limbs - } +use dep::std; +use crate::utils::map::map; + +use crate::params::BigNumParams; +use crate::constrained_ops::{ + conditional_select, assert_is_not_equal, eq, validate_in_field, validate_in_range, neg, add, sub, + mul, div, udiv_mod, udiv, umod +}; +use crate::unconstrained_ops::{ + __derive_from_seed, __eq, __is_zero, __neg, __add, __sub, __mul, __div, __udiv_mod, __invmod, __pow, + __batch_invert, __batch_invert_slice +}; +use crate::expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}; +use crate::serialization::{from_be_bytes, to_le_bytes}; + +pub struct RuntimeBigNum { + limbs: [Field; N], + params: BigNumParams, } -impl BigNumInstanceTrait> for BigNumInstance where Params: BigNumParamsTrait { +impl RuntimeBigNum {} - fn modulus(self) -> BigNum { - BigNum { limbs: self.modulus } - } - fn __derive_from_seed(self, seed: [u8; SeedBytes]) -> BigNum { - self.__derive_from_seed_impl(seed) - } - // #################################################################################################################### - // #################################################################################################################### - // ### U N C O N S T R A I N E D F U N C T I O N S - // ### NOTE: these functions call unconstrained internal implementations because trait impl modifiers are not supported - // #################################################################################################################### - // #################################################################################################################### +pub(crate) trait RuntimeBigNumTrait { + fn new(params: BigNumParams) -> Self; + fn one(params: BigNumParams) -> Self; + unconstrained fn __derive_from_seed(params: BigNumParams, seed: [u8; SeedBytes]) -> Self; + fn from_slice(params: BigNumParams, limbs: [Field]) -> Self; + fn from_array(params: BigNumParams, limbs: [Field; N]) -> Self; + fn from_be_bytes(params: BigNumParams, x: [u8; NBytes]) -> Self; - fn __neg(self, val: BigNum) -> BigNum { - self.__neg_impl(val) - } + fn to_le_bytes(self) -> [u8; NBytes]; - fn __add(self, lhs: BigNum, rhs: BigNum) -> BigNum { - self.__add_impl(lhs, rhs) - } + fn modulus(self) -> Self; + fn modulus_bits(self) -> u32; + fn num_limbs() -> u32; + // fn get(self) -> [Field]; + fn get_limbs(self) -> [Field; N]; + fn get_limb(self, idx: u32) -> Field; + fn set_limb(&mut self, idx: u32, value: Field); - fn __sub(self, lhs: BigNum, rhs: BigNum) -> BigNum { - self.__sub_impl(lhs, rhs) - } + unconstrained fn __eq(self, other: Self) -> bool; + unconstrained fn __is_zero(self) -> bool; - fn __mul(self, lhs: BigNum, rhs: BigNum) -> BigNum { - self.__mul_impl(lhs, rhs) - } + unconstrained fn __neg(self) -> Self; + unconstrained fn __add(self, other: Self) -> Self; + unconstrained fn __sub(self, other: Self) -> Self; + unconstrained fn __mul(self, other: Self) -> Self; + unconstrained fn __div(self, other: Self) -> Self; + unconstrained fn __udiv_mod(self, divisor: Self) -> (Self, Self); + unconstrained fn __invmod(self) -> Self; + unconstrained fn __pow(self, exponent: Self) -> Self; - fn __div(self, lhs: BigNum, rhs: BigNum) -> BigNum { - self.__div_impl(lhs, rhs) - } + unconstrained fn __batch_invert(x: [Self; M]) -> [Self; M]; + unconstrained fn __batch_invert_slice(to_invert: [Self]) -> [Self]; - fn __batch_invert(self, x: [BigNum; M]) -> [BigNum; M] { - self.batch_invert_impl(x) - } - - fn __invmod(self, val: BigNum) -> BigNum { - self.__invmod_impl(val) - } - - fn __pow(self, val: BigNum, exponent: BigNum) -> BigNum { - self.__pow_impl(val, exponent) - } - - fn __compute_quadratic_expression( - self, - lhs_terms: [[BigNum; LHS_N]; NUM_PRODUCTS], + unconstrained fn __compute_quadratic_expression( + params: BigNumParams, + lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS], lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], - rhs_terms: [[BigNum; RHS_N]; NUM_PRODUCTS], + rhs_terms: [[Self; RHS_N]; NUM_PRODUCTS], rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], - linear_terms: [BigNum; ADD_N], + linear_terms: [Self; ADD_N], linear_flags: [bool; ADD_N] - ) -> (BigNum, BigNum) { - self.__compute_quadratic_expression_impl( - lhs_terms, - lhs_flags, - rhs_terms, - rhs_flags, - linear_terms, - linear_flags - ) - } + ) -> (Self, Self); - // #################################################################################################################### - // #################################################################################################################### - // ### C O N S T R A I N E D F U N C T I O N S - // #################################################################################################################### - // #################################################################################################################### - - /** - * @brief Constrain a degree-2 BigNum expression to be equal to 0 modulo self.modulus - * @description The expression is of the form (when evaluated as an integer relation): - * - * \sum_{i=0}^{NUM_PRODUCTS - 1} ((\sum_{j=0}^{LHS_N-1}lhs[i][j]) * (\sum_{j=0}^{RHS_N-1}rhs[i][j])) + \sum_{i=0}^{ADD_N - 1}linear_terms[i] - quotient * modulus = 0 - * - * The intent is to capture an arbitrary degree-2 expression within the limitations of Noir (no efficient dynamically-sized vectors) - * - * Note: this method requires the remainder term of the expression to be ZERO - * When performing BigNum arithmetic, we want to represent desired BigNum operations in a way that minimizes the number of modular reductions that are required. - * This can be achieved by minimizing the number of degree-2 relations required. - * - * The expensive parts of this algorithm are the following: - * 1. evaluating the limb products required to compute `lhs * rhs` - * 2. applying range constraints to validate the result is 0 - * - * Range constraints are needed for the following reason: - * When evaluating the above expression over N-limb BigNum objects, the result will consist of 2N - 1 limbs. - * Each limb will be in the range [0, ..., 2^{240 + twiddle_factor} - 1] (twiddle_factor needs to be less than 6). - * Because of the subtractions, the limbs may underflow and represent NEGATIVE values. - * To account for this, we allow the Prover to borrow values from more significant limbs and add them into less significant limbs - * (explicitly, we can borrow 2^{126} from limb `i + 1` to add `2^{246}` into `i`). - * To ensure this has been done correctly, we validate that the borrow-adjusted limbs are all-zero for the first 120 bits. - * We do *this* by multiplying the borrow-adjusted limbs by 1 / 2^{120} modulo CircutModulus, and we validate the result is in the range [0, ..., 2^{126} - 1]. - * TODO: explain why this check works. It's statistically sound but not perfectly sound. Chance of the check failing is ~1 in 2^{120} - * I believe this is the most efficient way of performing the zero-check for this relation as it only requires `2N - 2` 126-bit range checks. - * TODO: explain why we apply a 126-bit range check, this feels like a magic number - * (it is. we could go higher, up to the number of bits in the CircuitModulus - 121, but 126 *should be* sufficient and is much cheaper) - * TODO: apply checks in this method to validate twiddle_factor does not exceed 6 - * - * @param lhs_terms a 2D array of BigNum - * @param lhs_flags a 2D array of sign flags - * @param rhs_terms a 2D array of BigNum - * @param rhs_flags a 2D array of sign flags - * @param linear_terms an array of BigNum - * @param linear_flags an array of sign flags - **/ fn evaluate_quadratic_expression( - self, - lhs_terms: [[BigNum; LHS_N]; NUM_PRODUCTS], + params: BigNumParams, + lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS], lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], - rhs_terms: [[BigNum; RHS_N]; NUM_PRODUCTS], + rhs_terms: [[Self; RHS_N]; NUM_PRODUCTS], rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], - linear_terms: [BigNum; ADD_N], + linear_terms: [Self; ADD_N], linear_flags: [bool; ADD_N] - ) { - // use an unconstrained function to compute the value of the quotient - let (quotient, _, borrow_flags): (BigNum, BigNum, [Field; 2 * N]) = unsafe { - self.__compute_quadratic_expression_with_borrow_flags( - lhs_terms, - lhs_flags, - rhs_terms, - rhs_flags, - linear_terms, - linear_flags - ) - }; - // constrain the quotient to be in the range [0, ..., 2^{m} - 1], where `m` is log2(modulus) rounded up. - // Additionally, validate quotient limbs are also in the range [0, ..., 2^{120} - 1] - quotient.validate_quotient_in_range(); - // TODO, validate we do not overflow N2 when multiplying and N when adding - // (should be a compile-time check...unconstrained function?) - - // Compute the linear sums that represent lhs_1, rhs_1, lhs_2, rhs_2, add - let mut t0: [[Field; N]; NUM_PRODUCTS] = [[0; N]; NUM_PRODUCTS]; - let mut t1: [[Field; N]; NUM_PRODUCTS] = [[0; N]; NUM_PRODUCTS]; - let mut t4: [Field; N] = [0; N]; - - // TODO: this is super nasty as it requires a multiplication - let double_modulus: [Field; N] = self.double_modulus; - for k in 0..NUM_PRODUCTS { - for i in 0..N { - for j in 0..LHS_N { - // note: if is_negative is not known at comptime this is very expensive - if (lhs_flags[k][j]) { - t0[k][i] -= lhs_terms[k][j].limbs[i]; - t0[k][i] += double_modulus[i]; - } else { - t0[k][i] += lhs_terms[k][j].limbs[i]; - } - } - for j in 0..RHS_N { - if (rhs_flags[k][j]) { - t1[k][i] -= rhs_terms[k][j].limbs[i]; - t1[k][i] += double_modulus[i]; - } else { - t1[k][i] += rhs_terms[k][j].limbs[i]; - } - } - } - } - for i in 0..N { - for j in 0..ADD_N { - if (linear_flags[j]) { - t4[i] -= linear_terms[j].limbs[i]; - t4[i] += double_modulus[i]; - } else { - t4[i] += linear_terms[j].limbs[i]; - } - } - } - - // We want to evaluate that t0 * t1 + t2 * t3 + t4 - Quotient * Modulus = 0, evaluated over the integers - // For this we need to be able to borrow values from more-significant limbs into less-significant limbs, - // so that we can ensure that no limbs will underflow for an honest Prover - let mut product_limbs: [Field; 2 * N] = [0; 2 * N]; - - // Compute the product t0 * t1 + t2 * t3 + t4 - Quotient * Modulus - // TODO: this is super nasty as it requires a multiplication - for i in 0..N { - for j in 0..N { - for k in 0..NUM_PRODUCTS { - if k == 0 { - let new_term = t0[k][i] * t1[k][j] - quotient.limbs[i] * self.modulus[j]; - std::as_witness(new_term); // width-4 optimization (n.b. might not be optimal if t2, t3 input arrays are nonzero) - product_limbs[i + j] += new_term; - } else { - product_limbs[i + j] += t0[k][i] * t1[k][j]; - } - } - if (NUM_PRODUCTS == 0) { - product_limbs[i + j] -= quotient.limbs[i] * self.modulus[j]; - } - } - product_limbs[i] += t4[i]; - } - - // each limb product represents the sum of 120-bit products. - // by setting the borrow value to 2^246 we are restricting this method's completeness to expressions - // where no more than 64 limb products are summed together. - // TODO: check in unconstrained function that this condition is satisfied - // TODO: define trade-offs regarding the value of borrow_shift - // (the larger the value, the greater the range check that is required on product_limbs) - // (126-bit range check is a sweet spot for the barretenberg backend as it decomposes into 9 14-bit range checks) - // (the barretenberg backend can evaluate these in 5.25 gates. 127 bits costs 6.5 gates) - let borrow_shift: Field = 0x40000000000000000000000000000000000000000000000000000000000000; // 2^{246} - let borrow_carry: Field = 0x40000000000000000000000000000000; // 2^{246 - 120} = 2^{126} - - // N.B. borrow_flags is `Field` type because making it `bool` would apply boolean constraints to all `N2` array entries. - // We only use `N2 - 2` borrow flags so applying 1-bit range checks on the array elements we use is more efficient. - // TODO: Once it is possible to perform arithmetic on generics we can use `borrow_flags: [bool;N+N-2]` to avoid this issue - borrow_flags[0].assert_max_bit_size(1); - product_limbs[0] += borrow_flags[0] * borrow_shift; - for i in 1..(N + N - 2) { - borrow_flags[i].assert_max_bit_size(1); - product_limbs[i] += - (borrow_flags[i] * borrow_shift - borrow_flags[i - 1] * borrow_carry); - } - product_limbs[N + N - 2] -= borrow_flags[N + N - 3] * borrow_carry; - - // Final step: Validate `product_limbs` represents the integer value `0` - // Each element `i` in `product_limbs` overlaps in bitrange with element `i+1`, EXCEPT for the low 120 bits - // i.e. we need to do the following for each limb `i`: - // 1. validate the limb's low-120 bits equals zero - // 2. compute the limb "carry" by right-shifting by 2^{120} - // 3. add the carry into limb `i+1` - // We can efficiently do all of the above by multiplying the limb by 2^{-120} and constraining the result to be <2^{126} - // (if the low 120 bits are nonzero the result will underflow and product a large value that cannot be range constrained) - // (the probability of an underflow value satisfying a 126-bit range constraint is approx. 2^{k - 126}, - // where k is the number of bits in the prime field) - // We then add the result into the next limb and repeat. - let hi_shift: Field = 0x1000000000000000000000000000000; - let hi_downshift: Field = 1 / hi_shift; - for i in 0..N + N - 2 { - product_limbs[i] *= hi_downshift; - std::as_witness(product_limbs[i]); - product_limbs[i].assert_max_bit_size(126); // N.B. is this sufficient? going beyond 126 costs us 1 gate per limb - product_limbs[i + 1] += product_limbs[i]; - } - // the most significant limb has no limb to "carry" values into - the entire limb must equal zero - assert(product_limbs[N + N - 2] == 0); - } - - fn validate_in_field(self, val: BigNum) { - // N.B. need to combine with validate_in_range if `self` limbs have not been range constrained - let mut p_minus_self: [Field; N] = [0; N]; - let modulus: [Field; N] = self.modulus; - for i in 0..N { - p_minus_self[i] = modulus[i] - val.limbs[i]; - } - let borrow_flags = unsafe { - self.__validate_in_field_compute_borrow_flags(val) - }; - let two_pow_120: Field = 0x1000000000000000000000000000000; - p_minus_self[0] += borrow_flags[0] as Field * two_pow_120; - for i in 1..N - 1 { - p_minus_self[i] += (borrow_flags[i] as Field * two_pow_120 - borrow_flags[i-1] as Field); - } - p_minus_self[N - 1] -= borrow_flags[N - 2] as Field; - let mut compare = val; - compare.limbs = p_minus_self; - compare.validate_in_range(); - } - - /** - * @brief Validate self != other - * @details If A == B, then A == B mod N. - * We can efficiently evaluate A == B mod N where N = circuit modulus - * This method is *sound*, but not *complete* (i.e. A != B but A == B mod N) - * However the probability of an honest Prover being unable to satisfy this check is tiny! - * (todo: compute how tiny) - **/ - fn assert_is_not_equal(self, lhs: BigNum, rhs: BigNum) { - let mut l: Field = 0; - let mut r: Field = 0; - let mut modulus_mod_n: Field = 0; - let mut two_pow_120: Field = 0x1000000000000000000000000000000; - let modulus = self.modulus; - for i in 0..N { - l *= two_pow_120; - r *= two_pow_120; - modulus_mod_n *= two_pow_120; - l += lhs.limbs[N - i - 1]; - r += rhs.limbs[N - i - 1] ; - modulus_mod_n += modulus[N - i - 1]; - } - - // lhs can be either X mod N or P + X mod N - // rhs can be either Y mod N or P + Y mod N - // If lhs - rhs = 0 mod P then lhs - rhs = 0, P or -P mod N - let mut diff = l - r; - let mut target = diff * (diff + modulus_mod_n) * (diff - modulus_mod_n); - assert(target != 0, "asssert_is_not_equal fail"); - } - - fn eq(self, lhs: BigNum, rhs: BigNum) -> bool { - let diff = self.sub(lhs, rhs); - // if self == other, possible values of `diff` will be `p` or `0` - // (the subtract operator constrains diff to be < ceil(log(p))) - // TODO: can do this more efficiently via witngen in unconstrained functions? - let mut is_equal_modulus: bool = true; - let mut is_equal_zero: bool = true; - for i in 0..N { - is_equal_modulus = is_equal_modulus & (diff.limbs[i] == self.modulus[i]); - is_equal_zero = is_equal_zero & (diff.limbs[i] == 0); - } - is_equal_modulus | is_equal_zero - } - - fn neg(self, val: BigNum) -> BigNum { - // so we do... p - x - r = 0 and there might be borrow flags - let (result, borrow_flags) = unsafe { - self.__neg_with_flags(val) - }; - result.validate_in_range(); - let modulus = self.modulus; - let borrow_shift = 0x1000000000000000000000000000000; - let result_limb = modulus[0] - val.limbs[0] - result.limbs[0] + (borrow_flags[0] as Field * borrow_shift); - assert(result_limb == 0); - for i in 1..N - 1 { - let result_limb = modulus[i] - val.limbs[i] - result.limbs[i] - borrow_flags[i - 1] as Field - + (borrow_flags[i] as Field * borrow_shift); - assert(result_limb == 0); - } - let result_limb = modulus[N - 1] - val.limbs[N - 1] - result.limbs[N - 1] - borrow_flags[N - 2] as Field; - assert(result_limb == 0); - result - } - - fn add(self, lhs: BigNum, rhs: BigNum) -> BigNum { - // so we do... p - x - r = 0 and there might be borrow flags - let (result, carry_flags, borrow_flags, overflow_modulus) = unsafe { - self.__add_with_flags(lhs, rhs) - }; - result.validate_in_range(); - let modulus = self.modulus; - let borrow_shift = 0x1000000000000000000000000000000; - let carry_shift = 0x1000000000000000000000000000000; - - let mut subtrahend: [Field; N] = [0; N]; - if (overflow_modulus) { - subtrahend = modulus; - } - let result_limb = lhs.limbs[0] + rhs.limbs[0] - subtrahend[0] - result.limbs[0] - + (borrow_flags[0] as Field * borrow_shift) - - (carry_flags[0] as Field * carry_shift); - assert(result_limb == 0); - for i in 1..N - 1 { - let result_limb = lhs.limbs[i] + rhs.limbs[i] - - subtrahend[i] - - result.limbs[i] - - borrow_flags[i - 1] as Field - + carry_flags[i - 1] as Field - + ((borrow_flags[i] as Field - carry_flags[i] as Field) * borrow_shift); - assert(result_limb == 0); - } - let result_limb = lhs.limbs[N - 1] + rhs.limbs[N - 1] - - subtrahend[N - 1] - - result.limbs[N - 1] - - borrow_flags[N - 2] as Field - + carry_flags[N - 2] as Field; - assert(result_limb == 0); - result - } + ); - // validate that lhs - rhs does not underflow i.e. lhs > rhs - fn validate_gt(self, lhs: BigNum, rhs: BigNum) { - // so we do... p - x - r = 0 and there might be borrow flags + fn eq(lhs: Self, rhs: Self) -> bool { lhs == rhs } + fn assert_is_not_equal(self, other: Self); + fn validate_in_field(self); + fn validate_in_range(self); + // fn validate_gt(self, lhs: Self, rhs: Self); - // a - b = r - // p + a - b - r = 0 - let (result, carry_flags, borrow_flags) = unsafe { - self.__validate_gt_remainder(lhs, rhs) - }; + fn neg(self) -> Self; + fn add(lhs: Self, rhs: Self) -> Self { lhs + rhs } + fn sub(lhs: Self, rhs: Self) -> Self { lhs - rhs } + fn mul(lhs: Self, rhs: Self) -> Self { lhs * rhs } + fn div(lhs: Self, rhs: Self) -> Self { lhs / rhs } + fn udiv_mod(numerator: Self, divisor: Self) -> (Self, Self); + fn udiv(numerator: Self, divisor: Self) -> Self; + fn umod(numerator: Self, divisor: Self) -> Self; - result.validate_in_range(); + fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self; +} - let borrow_shift = 0x1000000000000000000000000000000; - let carry_shift = 0x1000000000000000000000000000000; +impl RuntimeBigNumTrait for RuntimeBigNum { - let mut addend: [Field; N] = [0; N]; - let result_limb = lhs.limbs[0] - rhs.limbs[0] + addend[0] - result.limbs[0] - 1 - + (borrow_flags[0] as Field * borrow_shift) - - (carry_flags[0] as Field * carry_shift); - assert(result_limb == 0); - for i in 1..N - 1 { - let result_limb = lhs.limbs[i] - rhs.limbs[i] + addend[i] - result.limbs[i] - borrow_flags[i - 1] as Field - + carry_flags[i - 1] as Field - + ((borrow_flags[i] as Field - carry_flags[i] as Field) * borrow_shift); - assert(result_limb == 0); - } - let result_limb = lhs.limbs[N - 1] - rhs.limbs[N - 1] + addend[N - 1] - - result.limbs[N - 1] - - borrow_flags[N - 2] as Field - + carry_flags[N - 2] as Field; - assert(result_limb == 0); + fn new(params: BigNumParams) -> Self { + let limbs: [Field; N] = [0; N]; + Self { limbs, params } } - fn sub(self, lhs: BigNum, rhs: BigNum) -> BigNum { - // so we do... p - x - r = 0 and there might be borrow flags - - // a - b = r - // p + a - b - r = 0 - let (result, carry_flags, borrow_flags, underflow) = unsafe { - self.__sub_with_flags(lhs, rhs) - }; - result.validate_in_range(); - let modulus = self.modulus; - let borrow_shift = 0x1000000000000000000000000000000; - let carry_shift = 0x1000000000000000000000000000000; - - let mut addend: [Field; N] = [0; N]; - if (underflow) { - addend = modulus; - } - let result_limb = lhs.limbs[0] - rhs.limbs[0] + addend[0] - result.limbs[0] - + (borrow_flags[0] as Field * borrow_shift) - - (carry_flags[0] as Field * carry_shift); - assert(result_limb == 0); - for i in 1..N - 1 { - let result_limb = lhs.limbs[i] - rhs.limbs[i] + addend[i] - result.limbs[i] - borrow_flags[i - 1] as Field - + carry_flags[i - 1] as Field - + ((borrow_flags[i] as Field - carry_flags[i] as Field) * borrow_shift); - assert(result_limb == 0); - } - let result_limb = lhs.limbs[N - 1] - rhs.limbs[N - 1] + addend[N - 1] - - result.limbs[N - 1] - - borrow_flags[N - 2] as Field - + carry_flags[N - 2] as Field; - assert(result_limb == 0); - result - } - // Note: this method is expensive! Try to craft quadratic relations and directly evaluate them - // via evaluate_quadratic_expression - // e.g. performing a sum of multiple multiplications and additions via `evaluate_quadratic_expression` - // will create much fewer constraints than calling `mul` and `add` directly - fn mul(self, lhs: BigNum, rhs: BigNum) -> BigNum { - let result = self.__mul(lhs, rhs); - self.evaluate_quadratic_expression([[lhs]], [[false]], [[rhs]], [[false]], [result], [true]); - result - } - // Note: this method is expensive! Witness computation is extremely expensive as it requires modular exponentiation - fn div(self, lhs: BigNum, rhs: BigNum) -> BigNum { - assert( - Params::has_multiplicative_inverse(), "BigNum has no multiplicative inverse. Use udiv for unsigned integer division" - ); - let result = self.__div(lhs, rhs); - self.evaluate_quadratic_expression([[result]], [[false]], [[rhs]], [[false]], [lhs], [true]); + fn one(params: BigNumParams) -> Self { + let mut result = RuntimeBigNum::new(params); + result.limbs[0] = 1; result } - /** - * @brief __udiv_mod performs *unconstrained* integer division between numerator, divisor - * - * i.e. 1. floor(numerator / divisor) = quotient - * 2. numerator % divisor = remainder - * 3. divisor * quotient + remainder = numerator - **/ - fn __udiv_mod( - self, - numerator: BigNum, - divisor: BigNum - ) -> (BigNum, BigNum) { - self.__udiv_mod_impl(numerator, divisor) + unconstrained fn __derive_from_seed(params: BigNumParams, seed: [u8; SeedBytes]) -> Self { + Self { limbs: __derive_from_seed(params, seed), params } } - /** - * @brief udiv_mod performs integer division between numerator, divisor - * - * i.e. 1. floor(numerator / divisor) = quotient - * 2. numerator % divisor = remainder - * 3. divisor * quotient + remainder = numerator - **/ - fn udiv_mod( - self, - numerator: BigNum, - divisor: BigNum - ) -> (BigNum, BigNum) { - let (quotient, remainder) = BigNumInstance::__udiv_mod_impl(self, numerator, divisor); - // self / divisor = quotient rounded - // quotient * divisor + remainder - self = 0 - self.evaluate_quadratic_expression( - [[quotient]], - [[false]], - [[divisor]], - [[false]], - [numerator, remainder], - [true, false] - ); - // we need (remainder < divisor) - // implies (divisor - remainder > 0) - self.validate_gt(divisor, remainder); - (quotient, remainder) + fn from_slice(params: BigNumParams, limbs: [Field]) -> Self { + Self { limbs: limbs.as_array(), params } } - /** - * @brief udiv_mod performs integer division between numerator, divisor - * - * i.e. return param is floor(numerator / divisor) - **/ - fn udiv(self, numerator: BigNum, divisor: BigNum) -> BigNum { - self.udiv_mod(numerator, divisor).0 + fn from_array(params: BigNumParams, limbs: [Field; N]) -> Self { + Self { limbs, params } } - /** - * @brief udiv_mod performs integer modular reduction - * - * i.e. 1. numerator % divisor = return value - **/ - fn umod(self, numerator: BigNum, divisor: BigNum) -> BigNum { - self.udiv_mod(numerator, divisor).1 + fn from_be_bytes(params: BigNumParams, x: [u8; NBytes]) -> Self { + Self { limbs: from_be_bytes(params, x), params } } -} - -impl BigNumInstance where Params: BigNumParamsTrait { - // #################################################################################################################### - // #################################################################################################################### - // ### C O N S T R U C T O R S - // #################################################################################################################### - // #################################################################################################################### - - fn new(modulus: [Field; N], redc_param: [Field; N]) -> Self { - Self { - redc_param, - modulus, - modulus_u60: U60Repr::from(modulus), - modulus_u60_x4: U60Repr::from(modulus), - double_modulus: get_double_modulus(modulus) - } + fn to_le_bytes(self) -> [u8; NBytes] { + to_le_bytes(self.params, self.limbs) } - unconstrained fn __derive_from_seed_impl(self, seed: [u8; SeedBytes]) -> BigNum { - let mut rolling_seed = seed; - - let mut to_reduce: [Field; 2 * N] = [0; 2 * N]; - - let mut double_modulus_bits = Params::modulus_bits() * 2; - let mut double_modulus_bytes = (double_modulus_bits) / 8 + (double_modulus_bits % 8 != 0) as u32; - - let mut last_limb_bytes = double_modulus_bytes % 15; - if (last_limb_bytes == 0) { - last_limb_bytes = 15; - } - let mut last_limb_bits = double_modulus_bits % 8; - if (last_limb_bits == 0) { - last_limb_bits = 8; - } - - for i in 0..(N - 1) { - let hash: [u8; 32] = std::hash::sha256(rolling_seed); - let mut lo: Field = 0; - let mut hi: Field = 0; - for j in 0..15 { - hi *= 256; - lo *= 256; - - if (i < 2 * N - 2) { - lo += hash[j + 15] as Field; - hi += hash[j] as Field; - } - } - to_reduce[2 * i] = lo; - to_reduce[2 * i + 1] = hi; - rolling_seed[0] += 1; - } - - { - let hash: [u8; 32] = std::hash::sha256(rolling_seed); - let mut hi: Field = 0; - for j in 0..(last_limb_bytes - 1) { - hi *= 256; - hi += hash[j] as Field; - } - hi *= 256; - let last_byte = hash[last_limb_bytes - 1]; - let mask = (1 as u64 << (last_limb_bits) as u8) - 1; - let last_bits = last_byte as u64 & mask; - hi += last_bits as Field; - to_reduce[2 * N - 2] = hi; - } - - let (_, remainder) = __barrett_reduction( - to_reduce, - self.redc_param, - Params::modulus_bits(), - self.modulus, - self.modulus_u60_x4 - ); - let mut result = BigNum::new(); - result.limbs = remainder; - result + fn modulus(self) -> Self { + let params = self.params; + Self { limbs: params.modulus, params } } - // #################################################################################################################### - // #################################################################################################################### - // ### U N C O N S T R A I N E D F U N C T I O N S - // #################################################################################################################### - // #################################################################################################################### - - unconstrained fn __validate_in_field_compute_borrow_flags(self: Self, val: BigNum) -> [bool; N] { - let mut flags: [bool; N] = [false; N]; - let modulus: [Field; N] = self.modulus; - flags[0] = modulus[0].lt(val.limbs[0]); - for i in 1..N - 1 { - flags[i] = modulus[i].lt(val.limbs[i] + flags[i - 1] as Field); - } - flags + fn modulus_bits(self) -> u32 { + let getter = self.params.modulus_bits_getter; + getter() } - unconstrained fn __pow_impl( - self, - val: BigNum, - exponent: BigNum - ) -> BigNum { - let x: U60Repr = U60Repr::from(exponent.limbs); - - let num_bits = Params::modulus_bits() + 1; - - let mut accumulator: BigNum = BigNum::one(); - - for i in 0..num_bits { - accumulator = self.__mul(accumulator, accumulator); - if x.get_bit(num_bits - i - 1) { - accumulator = self.__mul(accumulator, val); - } - } - accumulator + fn num_limbs() -> u32 { + N } - unconstrained fn __mul_with_quotient( - self, - lhs: BigNum, - rhs: BigNum - ) -> (BigNum, BigNum) { - let mut mul: [Field; 2 * N] = [0; 2 * N]; - for i in 0..N { - for j in 0..N { - mul[i + j] += lhs.limbs[i] * rhs.limbs[j]; - } - } - let (q, r) = __barrett_reduction( - split_bits::__normalize_limbs(mul, 2 * N), - self.redc_param, - Params::modulus_bits(), - self.modulus, - self.modulus_u60_x4 - ); + // fn get(self) -> [Field] { + // self.get_limbs() + // } - let mut quotient = BigNum::from_array(q); - let mut remainder = BigNum::from_array(r); - (quotient, remainder) + fn get_limbs(self) -> [Field; N] { + self.limbs } - unconstrained fn __mul_impl( - self, - lhs: BigNum, - rhs: BigNum - ) -> BigNum { - let (_, b) = self.__mul_with_quotient(lhs, rhs); - b + fn get_limb(self, idx: u32) -> Field { + self.limbs[idx] } - unconstrained fn __add_impl( - self, - lhs: BigNum, - rhs: BigNum - ) -> BigNum { - let x_u60 : U60Repr = U60Repr::from(lhs.limbs); - let y_u60 : U60Repr = U60Repr::from(rhs.limbs); - - let mut z_u60 = x_u60 + y_u60; - - if z_u60.gte(self.modulus_u60) { - z_u60 = z_u60 - self.modulus_u60; - } - let mut result = BigNum::from_array(U60Repr::into(z_u60)); - result + fn set_limb(&mut self, idx: u32, value: Field) { + self.limbs[idx] = value; } - /** - * @brief given an input `x`, compute `2p - x` (unconstrained) - * - * @description we subtract the input from double the modulus, because all constrained BigNum operations - * only guarantee that the output is in the range [0, ceil(log2(p))]. - * I.E. the input may be larger than the modulus `p`. - * In order to ensure this operation does not underflow, we compute `2p - x` instead of `p - x`. - * N.B. constrained BigNum operations do not fully constrain outputs to be in the range [0, p-1] - * because such a check is expensive and usually unneccesary. - */ - unconstrained fn __neg_impl(self, val: BigNum) -> BigNum { - let f: [Field; N] = val.limbs; - let x_u60 : U60Repr = U60Repr::from(f); - let mut result = BigNum::from_array(U60Repr::into(self.modulus_u60 - x_u60)); - result + unconstrained fn __eq(self, other: Self) -> bool { + __eq(self.limbs, other.limbs) } - unconstrained fn __add_with_flags( - self, - lhs: BigNum, - rhs: BigNum - ) -> (BigNum, [bool; N], [bool; N], bool) { - let a_u60 : U60Repr = U60Repr::from(lhs.limbs); - let b_u60 : U60Repr = U60Repr::from(rhs.limbs); - let add_u60 = a_u60 + b_u60; - - let overflow = add_u60.gte(self.modulus_u60); - - let mut subtrahend_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; - let mut result_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; - - if overflow { - subtrahend_u60 = self.modulus_u60; - } - - let mut carry: u64 = 0; - let mut carry_in: u64 = 0; - let mut borrow: u64 = 0; - let mut borrow_in: u64 = 0; - let mut borrow_flags: [bool; N] = [false; N]; - let mut carry_flags: [bool; N] = [false; N]; - for i in 0..2 * N { - let mut add_term: u64 = a_u60.limbs[i] + b_u60.limbs[i] + carry_in; - carry = (add_term >= 0x1000000000000000) as u64; - add_term -= (carry as u64 * 0x1000000000000000); - result_u60.limbs[i] = add_term; - carry_in = carry as u64; - borrow = ((subtrahend_u60.limbs[i] + borrow_in) > result_u60.limbs[i]) as u64; - let sub = (borrow << 60) + result_u60.limbs[i] - subtrahend_u60.limbs[i] - borrow_in; - result_u60.limbs[i] = sub; - borrow_in = borrow; - - if ((i & 1) == 1) { - let idx = (i - 1) / 2; - if (carry & borrow == 1) { - carry = 0; - borrow = 0; - } - carry_flags[idx] = carry as bool; - borrow_flags[idx] = borrow as bool; - } - } - let mut result = BigNum::from_array(U60Repr::into(result_u60)); - - (result, carry_flags, borrow_flags, overflow) + unconstrained fn __is_zero(self) -> bool { + __is_zero(self.limbs) } - unconstrained fn __validate_gt_remainder( - _: Self, - lhs: BigNum, - rhs: BigNum - ) -> (BigNum, [bool; N], [bool; N]) { - let a_u60 : U60Repr = U60Repr::from(lhs.limbs); - let mut b_u60 : U60Repr = U60Repr::from(rhs.limbs); - - let underflow = b_u60.gte(a_u60); - b_u60 += U60Repr::one(); - assert(underflow == false, "BigNum::validate_gt check fails"); - let mut addend_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; - let mut result_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; - - let mut carry: u64 = 0; - let mut carry_in: u64 = 0; - let mut borrow: u64 = 0; - let mut borrow_in: u64 = 0; - let mut borrow_flags: [bool; N] = [false; N]; - let mut carry_flags: [bool; N] = [false; N]; - for i in 0..2 * N { - let mut add_term: u64 = a_u60.limbs[i] + addend_u60.limbs[i] + carry_in; - carry = (add_term >= 0x1000000000000000) as u64; - add_term -= (carry as u64 * 0x1000000000000000); - result_u60.limbs[i] = add_term; - carry_in = carry as u64; - borrow = ((b_u60.limbs[i] + borrow_in) > result_u60.limbs[i]) as u64; - let sub = (borrow << 60) + result_u60.limbs[i] - b_u60.limbs[i] - borrow_in; - result_u60.limbs[i] = sub; - borrow_in = borrow; - - if ((i & 1) == 1) { - if (carry & borrow == 1) { - carry = 0; - borrow = 0; - } - carry_flags[i/2] = carry as bool; - borrow_flags[i/2] = borrow as bool; - } - } - - let mut result = BigNum::from_array(U60Repr::into(result_u60)); - (result, carry_flags, borrow_flags) + unconstrained fn __neg(self) -> Self { + let params = self.params; + Self::from_array(params, __neg(params, self.limbs)) } - unconstrained fn __sub_with_flags( - self, - lhs: BigNum, - rhs: BigNum - ) -> (BigNum, [bool; N], [bool; N], bool) { - let a_u60 : U60Repr = U60Repr::from(lhs.limbs); - let b_u60 : U60Repr = U60Repr::from(rhs.limbs); - - let underflow = b_u60.gte(a_u60 + U60Repr::one()); - - let mut addend_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; - let mut result_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; - - if underflow { - addend_u60 = self.modulus_u60; - } - - let mut carry: u64 = 0; - let mut carry_in: u64 = 0; - let mut borrow: u64 = 0; - let mut borrow_in: u64 = 0; - let mut borrow_flags: [bool; N] = [false; N]; - let mut carry_flags: [bool; N] = [false; N]; - for i in 0..2 * N { - let mut add_term: u64 = a_u60.limbs[i] + addend_u60.limbs[i] + carry_in; - carry = (add_term >= 0x1000000000000000) as u64; - add_term -= (carry as u64 * 0x1000000000000000); - result_u60.limbs[i] = add_term; - carry_in = carry as u64; - borrow = ((b_u60.limbs[i] + borrow_in) > result_u60.limbs[i]) as u64; - let sub = (borrow << 60) + result_u60.limbs[i] - b_u60.limbs[i] - borrow_in; - result_u60.limbs[i] = sub; - borrow_in = borrow; - - if ((i & 1) == 1) { - if (carry & borrow == 1) { - carry = 0; - borrow = 0; - } - carry_flags[i/2] = carry as bool; - borrow_flags[i/2] = borrow as bool; - } - } - let mut result = BigNum::from_array(U60Repr::into(result_u60)); - (result, carry_flags, borrow_flags, underflow) + unconstrained fn __add(self, other: Self) -> Self { + let params = self.params; + Self::from_array(params, __add(params, self.limbs, other.limbs)) } - unconstrained fn __neg_with_flags( - self, - val: BigNum - ) -> (BigNum, [bool; N]) { - let f: [Field; N] = val.limbs; - let x_u60 : U60Repr = U60Repr::from(f); - let mut result_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; - - let mut borrow: u64 = 0; - let mut borrow_in: u64 = 0; - - let mut borrow_flags: [bool; N] = [false; N]; - for i in 0..2 * N { - borrow = ((x_u60.limbs[i] + borrow_in) > self.modulus_u60.limbs[i]) as u64; - let sub = (borrow << 60) + self.modulus_u60.limbs[i] - x_u60.limbs[i] - borrow_in; - result_u60.limbs[i] = sub; - borrow_in = borrow; - if ((i & 1) == 1) { - borrow_flags[i / 2] = borrow as bool; - } - } - let mut result = BigNum::from_array(U60Repr::into(result_u60)); - (result, borrow_flags) + unconstrained fn __sub(self, other: Self) -> Self { + let params = self.params; + Self::from_array(params, __sub(params, self.limbs, other.limbs)) } - /** - * @brief given inputs `x, y` compute 2p + x - y (unconstrained) - * @description see `__neg` for why we use 2p instead of p - **/ - unconstrained fn __sub_impl( - self, - lhs: BigNum, - rhs: BigNum - ) -> BigNum { - self.__add(lhs, self.__neg(rhs)) + unconstrained fn __mul(self, other: Self) -> Self { + let params = self.params; + Self::from_array(params, __mul(params, self.limbs, other.limbs)) } - unconstrained fn __invmod_impl(self, val: BigNum) -> BigNum { - let one: BigNum = BigNum::one(); - let one_u60: U60Repr = U60Repr::from(one.limbs); - let exponent = self.modulus_u60.sub(one_u60.add(one_u60)); - let mut result = BigNum::from_array(U60Repr::into(exponent)); - self.__pow(val, result) + unconstrained fn __div(self, divisor: Self) -> Self { + let params = self.params; + Self::from_array(params, __div(params, self.limbs, divisor.limbs)) } - unconstrained fn batch_invert_impl( - self, - x: [BigNum; M] - ) -> [BigNum; M] { - // TODO: ugly! Will fail if input slice is empty - let mut accumulator: BigNum = BigNum::one(); - let mut result: [BigNum; M] = [BigNum::new(); M]; - let mut temporaries: [BigNum] = &[]; - for i in 0..x.len() { - temporaries = temporaries.push_back(accumulator); - if (x[i].__is_zero() == false) { - accumulator = self.__mul(accumulator, x[i]); - } - } - - accumulator = self.__invmod(accumulator); - let mut T0: BigNum = BigNum::new(); - T0.limbs = [0; N]; - for i in 0..x.len() { - let idx = x.len() - 1 - i; - if (x[idx].__is_zero() == false) { - T0 = self.__mul(accumulator, temporaries[idx]); - accumulator = self.__mul(accumulator, x[idx]); - result[idx] = T0; - } - } - result + unconstrained fn __udiv_mod(self, divisor: Self) -> (Self, Self) { + let params = self.params; + let (q, r) = __udiv_mod(self.limbs, divisor.limbs); + (Self { limbs: q, params }, Self { limbs: r, params }) } - unconstrained fn batch_invert_slice_impl(self, x: [BigNum]) -> [BigNum] { - // TODO: ugly! Will fail if input slice is empty - let mut accumulator: BigNum = BigNum::one(); - let mut result: [BigNum] = [BigNum::new()]; - let mut temporaries: [BigNum] = &[]; - for i in 0..x.len() { - temporaries = temporaries.push_back(accumulator); - if (x[i].__is_zero() == false) { - accumulator = self.__mul(accumulator, x[i]); - } - result = result.push_back(BigNum::new()); - } - - accumulator = self.__invmod(accumulator); - let mut T0: BigNum = BigNum::new(); - T0.limbs = [0; N]; - for i in 0..x.len() { - let idx = x.len() - 1 - i; - if (x[idx].__is_zero() == false) { - T0 = self.__mul(accumulator, temporaries[idx]); - accumulator = self.__mul(accumulator, x[idx]); - result[idx] = T0; - } - } - result + unconstrained fn __invmod(self) -> Self { + let params = self.params; + assert(params.has_multiplicative_inverse); + Self { limbs: __invmod(params, self.limbs), params } } - unconstrained fn __div_impl( - self, - numerator: BigNum, - divisor: BigNum - ) -> BigNum { - let t0 = self.__invmod(divisor); - self.__mul(numerator, t0) + unconstrained fn __pow(self, exponent: Self) -> Self { + let params = self.params; + Self { limbs: __pow(params, self.limbs, exponent.limbs), params } } - /** - * @brief Computes the result of a linear combination of (possibly negative) BigNum values (unconstrained) - **/ - // NOTE: modulus2 is structured such that all limbs will be greater than 0, even when subtracting. - // To do this, when computing `p - x`, we ensure that each limb in `p` is greater than each limb in `x`. - // We know that, for a valid bignum element, the limbs in `x` will be <2^{120} - // Therefore each of the limbs in `p` (except the most significant) will borrow 2^{120} from the more significant limb. - // Finally, to ensure we do not underflow in the most significant limb, we use `2p` instead of `p` - unconstrained fn __add_linear_expression(self, x: [BigNum; M], flags: [bool; M]) -> ([Field; N]) { - // TODO, validate we do not overflow N2 when multiplying and N when adding - let mut sum: [Field; N] = [0; N]; - // TODO: ugly! Will fail if input array is empty - let modulus2: [Field;N] = self.double_modulus; - for i in 0..M { - if (flags[i]) { - for j in 0..N { - sum[j] = sum[j] + modulus2[j] - x[i].limbs[j]; - assert(x[i].limbs[j].lt(modulus2[j])); - } - } else { - for j in 0..N { - sum[j] = sum[j] + x[i].limbs[j]; - } - } - } - // problem if we normalize when used in computing quotient - sum + unconstrained fn __batch_invert(x: [Self; M]) -> [Self; M] { + let params = x[0].params; + assert(params.has_multiplicative_inverse); + __batch_invert(params, x.map(|bn| Self::get_limbs(bn))).map(|limbs| Self { limbs, params }) } - /** - * @brief computes the limb products of a quadratic expression - * @details see __compute_quadratic_expression_with_borrow_flags for full description - **/ - unconstrained fn __compute_quadratic_expression_product( - self, - lhs_terms: [[BigNum; LHS_N]; NUM_PRODUCTS], - lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], - rhs_terms: [[BigNum; RHS_N]; NUM_PRODUCTS], - rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], - linear_terms: [BigNum; ADD_N], - linear_flags: [bool; ADD_N] - ) -> [Field; 2 * N] { - // TODO, validate we do not overflow N2 when multiplying and N when adding - let mut lhs: [[Field; N]; NUM_PRODUCTS] = [[0; N]; NUM_PRODUCTS]; - let mut rhs: [[Field; N]; NUM_PRODUCTS] = [[0; N]; NUM_PRODUCTS]; - let mut add: [Field; N] = [0; N]; - - for i in 0..NUM_PRODUCTS { - lhs[i] = self.__add_linear_expression(lhs_terms[i], lhs_flags[i]); - rhs[i] = self.__add_linear_expression(rhs_terms[i], rhs_flags[i]); - } - - let add: [Field; N] = self.__add_linear_expression(linear_terms, linear_flags); - - let mut mulout: [Field; 2 * N] = [0; 2 * N]; - - for i in 0..N { - for j in 0..N { - for k in 0..NUM_PRODUCTS { - mulout[i + j] += (lhs[k][i] * rhs[k][j]); - } - } - mulout[i] += add[i]; - } - mulout + unconstrained fn __batch_invert_slice(x: [Self]) -> [Self] { + let params = x[0].params; + assert(params.has_multiplicative_inverse); + __batch_invert_slice(params, x.map(|bn| Self::get_limbs(bn))).map(|limbs| Self { limbs, params }) } - /** - * @brief computes the quotient/remainder of a quadratic expression - * @details see __compute_quadratic_expression_with_borrow_flags for full description - **/ - unconstrained fn __compute_quadratic_expression_impl( - self, - lhs_terms: [[BigNum; LHS_N]; NUM_PRODUCTS], + unconstrained fn __compute_quadratic_expression( + params: BigNumParams, + lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS], lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], - rhs_terms: [[BigNum; RHS_N]; NUM_PRODUCTS], + rhs_terms: [[Self; RHS_N]; NUM_PRODUCTS], rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], - linear_terms: [BigNum; ADD_N], + linear_terms: [Self; ADD_N], linear_flags: [bool; ADD_N] - ) -> (BigNum, BigNum) { - // TODO, validate we do not overflow N2 when multiplying and N when adding - let mulout = self.__compute_quadratic_expression_product( - lhs_terms, + ) -> (Self, Self) { + let (q_limbs, r_limbs) = __compute_quadratic_expression( + params, + lhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), lhs_flags, - rhs_terms, + rhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), rhs_flags, - linear_terms, + linear_terms.map(|bn| Self::get_limbs(bn)), linear_flags ); - let mut relation_result: [Field; 2 * N] = split_bits::__normalize_limbs(mulout, 2 * N); - - // TODO: ugly! Will fail if input slice is empty - let k = Params::modulus_bits(); - - let (quotient, remainder) = __barrett_reduction( - relation_result, - self.redc_param, - k, - self.modulus, - self.modulus_u60_x4 - ); - - let mut q = BigNum::from_array(quotient); - let mut r = BigNum::from_array(remainder); - (q, r) + (Self { limbs: q_limbs, params }, Self { limbs: r_limbs, params }) } - /** - * @brief Given a degree-2 BigNum expression that is equal to 0 mod p, compute the quotient and borrow flags - * @description The expression is of the form: - * - * \sum_{i=0}^{NUM_PRODUCTS - 1} ((\sum_{j=0}^{LHS_N-1}lhs[i][j]) * (\sum_{j=0}^{RHS_N-1}rhs[i][j])) + \sum_{i=0}^{ADD_N - 1}linear_terms[i] = quotient * modulus - * - * The intent is to capture an arbitrary degree-2 expression within the limitations of Noir (no efficient dynamically-sized vectors) - * - * When performing BigNum arithmetic, we want to represent desired BigNum operations in a way that minimizes the number of modular reductions that are required. - * This can be achieved by minimizing the number of degree-2 relations required. - * - * The borrow flags describe whether individual Field limbs will underflow when evaluating the above relation. - * For example, when computing the product a * b - q * p = 0, it is possible that: - * 1. a[0]*b[0] - p[0]*q[0] = -2^{120} - * 2. a[0]*b[1] + a[1]*b[0] - p[0]*q[1] - p[1]*q[0] = 1 - * In the above example, the value represented by these two limbs is zero despite each limb being nonzero. - * In this case, to correctly constrain the result, we must add (at least) 2^{120} from the first limb and subtract 1 from the second. - * - * @param lhs_terms a 2D array of BigNum - * @param lhs_flags a 2D array of sign flags - * @param rhs_terms a 2D array of BigNum - * @param rhs_flags a 2D array of sign flags - * @param linear_terms an array of BigNum - * @param linear_flags an array of sign flags - **/ - unconstrained fn __compute_quadratic_expression_with_borrow_flags( - self, - lhs_terms: [[BigNum; LHS_N]; NUM_PRODUCTS], + fn evaluate_quadratic_expression( + params: BigNumParams, + lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS], lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], - rhs_terms: [[BigNum; RHS_N]; NUM_PRODUCTS], + rhs_terms: [[Self; RHS_N]; NUM_PRODUCTS], rhs_flags: [[bool; RHS_N]; NUM_PRODUCTS], - linear_terms: [BigNum; ADD_N], + linear_terms: [Self; ADD_N], linear_flags: [bool; ADD_N] - ) -> (BigNum, BigNum, [Field; 2 * N]) { - // TODO, validate we do not overflow N2 when multiplying and N when adding - - let mut mulout_p = self.__compute_quadratic_expression_product( - lhs_terms, + ) { + evaluate_quadratic_expression( + params, + lhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), lhs_flags, - rhs_terms, + rhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), rhs_flags, - linear_terms, + linear_terms.map(|bn| Self::get_limbs(bn)), linear_flags - ); - let mut mulout_n: [Field; 2 * N] = [0; 2 * N]; - let mut relation_result: [Field; 2 * N] = split_bits::__normalize_limbs(mulout_p, 2 * N); - - let modulus: [Field; N] = self.modulus; - let (quotient, remainder) = __barrett_reduction( - relation_result, - self.redc_param, - Params::modulus_bits(), - modulus, - self.modulus_u60_x4 - ); - assert(remainder == [0; N]); - - for i in 0..N { - for j in 0..N { - mulout_n[i + j] += quotient[i] * modulus[j]; - } - } - - // compute borrow flags from mulout_p and mulout_n - let mut borrow_flags: [Field; 2 * N] = [0; 2 * N]; - let borrow_shift: Field = 0x40000000000000000000000000000000000000000000000000000000000000; // 2^{246} - let borrow_carry: Field = 0x40000000000000000000000000000000; // 2^{246 - 120} = 2^{126} - let two_pow_120: Field = 0x1000000000000000000000000000000; - let downshift: Field = 1 / two_pow_120; - - // determine whether we need to borrow from more significant limbs. - // initial limb is "simple" comparison operation - // TODO: check how expensive `lt` operator is w.r.t. witness generation - borrow_flags[0] = mulout_p[0].lt(mulout_n[0]) as Field; - // we have 2N - 2 borrow flags. The number of limbs from our product computation is 2N - 1 - // and there is nothing to borrow against for the final limb. - let mut hi_bits = (mulout_p[0] - mulout_n[0] + (borrow_flags[0] * borrow_shift)) * downshift; - for i in 1..(N + N - 2) { - // compute the contribution from limb `i-1` that gets added into limb `i`, and add into limb `i` - // let hi_bits = (mulout_p.get(i - 1) - mulout_n.get(i - 1) + (borrow_flags.get(i - 1) * borrow_shift)) - // * downshift; - mulout_p[i] += hi_bits; - - // determine whether negative limb values are greater than positive limb values - let underflow: Field = mulout_p[i].lt(mulout_n[i] + (borrow_flags[i - 1] * borrow_carry)) as Field; - borrow_flags[i] = underflow; - - hi_bits = (mulout_p[i] - mulout_n[i] + (borrow_flags[i] * borrow_shift) - - (borrow_flags[i - 1] * borrow_carry)) * downshift; - } + ) + } - let mut q = BigNum::from_array(quotient); - let mut r = BigNum::from_array(remainder); - (q, r, borrow_flags) + fn validate_in_field(self: Self) { + let params = self.params; + validate_in_field(params, self.limbs); } - unconstrained fn __udiv_mod_impl( - _: Self, - numerator: BigNum, - divisor: BigNum - ) -> (BigNum, BigNum) { - let mut quotient_u60: U60Repr = U60Repr::from([0; N]); - let mut remainder_u60: U60Repr = U60Repr::from(numerator.limbs); + fn validate_in_range(self) { + let params = self.params; + validate_in_range(params, self.limbs); + } - let mut divisor_u60: U60Repr = U60Repr::from(divisor.limbs); - let b = divisor_u60; + fn assert_is_not_equal(self, other: Self) { + let params = self.params; + assert_is_not_equal(params, self.limbs, other.limbs); + } - let mut bit_difference = remainder_u60.get_msb() - divisor_u60.get_msb(); + fn neg(self) -> Self { + let params = self.params; + Self { limbs: neg(params, self.limbs), params } + } - let mut accumulator_u60: U60Repr = U60Repr::one(); - divisor_u60 = divisor_u60.shl(bit_difference); - accumulator_u60 = accumulator_u60.shl(bit_difference); + fn udiv_mod(self, divisor: Self) -> (Self, Self) { + let params = self.params; + let (q, r) = udiv_mod(params, self.limbs, divisor.limbs); + (Self { limbs: q, params }, Self { limbs: r, params }) + } - if (divisor_u60.gte(remainder_u60 + U60Repr::one())) { - divisor_u60.shr1(); - accumulator_u60.shr1(); - } - for _ in 0..(N * 120) { - if (remainder_u60.gte(b) == false) { - break; - } + fn udiv(self, divisor: Self) -> Self { + let params = self.params; + Self { limbs: udiv(params, self.limbs, divisor.limbs), params } + } - // we've shunted 'divisor' up to have the same bit length as our remainder. - // If remainder >= divisor, then a is at least '1 << bit_difference' multiples of b - if (remainder_u60.gte(divisor_u60)) { - remainder_u60 -= divisor_u60; - // we can use OR here instead of +, as - // accumulator is always a nice power of two - quotient_u60 = quotient_u60 + accumulator_u60; - } - divisor_u60.shr1(); // >>= 1; - accumulator_u60.shr1(); // >>= 1; - } + fn umod(self, divisor: Self) -> Self { + let params = self.params; + Self { limbs: umod(params, self.limbs, divisor.limbs), params } + } - ( - BigNum::from_array(U60Repr::into(quotient_u60)), BigNum::from_array(U60Repr::into(remainder_u60)) - ) + fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self { + let params = lhs.params; + Self { limbs: conditional_select(lhs.limbs, rhs.limbs, predicate), params } } } -fn get_double_modulus(modulus: [Field; N]) -> [Field; N] { - let TWO_POW_120: Field = 0x1000000000000000000000000000000; - let m: U60Repr = U60Repr::from(modulus); - let mut result: [Field; N] = U60Repr::into(m + m); - - result[0] += TWO_POW_120; - for i in 1..N - 1 { - result[i] += (TWO_POW_120 - 1); +impl std::ops::Add for RuntimeBigNum { + // Note: this method is expensive! Try to craft quadratic relations and directly evaluate them + // via evaluate_quadratic_expression + fn add(self, other: Self) -> Self { + let params = self.params; + Self { limbs: add(params, self.limbs, other.limbs), params } } - result[N - 1] -= 1; - result } -unconstrained fn __barrett_reduction( - x: [Field; 2 * N], - redc_param: [Field; N], - k: u32, - modulus: [Field; N], - modulus_u60: U60Repr -) -> ([Field; N], [Field; N]) { - let mut mulout: [Field; 3 * N] = [0; 3 * N]; - for i in 0..(N + N) { - for j in 0..N { - mulout[i + j] += x[i] * redc_param[j]; - } +impl std::ops::Sub for RuntimeBigNum { + // Note: this method is expensive! Try to craft quadratic relations and directly evaluate them + // via evaluate_quadratic_expression + fn sub(self, other: Self) -> Self { + let params = self.params; + Self { limbs: sub(params, self.limbs, other.limbs), params } } - mulout = split_bits::__normalize_limbs(mulout, 3 * N - 1); - let mulout_u60: U60Repr = U60Repr::new(mulout); - let mut quotient_u60 = mulout_u60.shr((k + k)); +} - // N.B. we assume that the shifted quotient cannot exceed 2 times original bit size. - // (partial_quotient should be just slightly larger than the modulus, we could probably represent with a size N+1 array) - let partial_quotient_full: [Field; 3 * N] = quotient_u60.into_field_array(); - let mut partial_quotient: [Field; 2 * N] = [0; 2 * N]; - for i in 0..2 * N { - partial_quotient[i] = partial_quotient_full[i]; - } - // quotient_mul_modulus can never exceed input value `x` so can fit into size-2 array - let mut quotient_mul_modulus: [Field; 2 * N] = [0; 2 * N]; - let mut quotient_mul_modulus_normalized: [Field; 2 * N] = [0; 2 * N]; - for j in 0..N { - for i in 0..(N + N - j) { - quotient_mul_modulus[i + j] += partial_quotient[i] * modulus[j]; - } +impl std::ops::Mul for RuntimeBigNum { + // Note: this method is expensive! Try to craft quadratic relations and directly evaluate them + // via evaluate_quadratic_expression + // e.g. performing a sum of multiple multiplications and additions via `evaluate_quadratic_expression` + // will create much fewer constraints than calling `mul` and `add` directly + fn mul(self, other: Self) -> Self { + let params = self.params; + Self { limbs: mul(params, self.limbs, other.limbs), params } } +} - for i in 0..(N + N) { - let (lo, hi) = split_bits::split_120_bits(quotient_mul_modulus[i]); - quotient_mul_modulus_normalized[i] = lo; - // TODO: what is faster, leaving this if statement in or out? - // (array is size-1 too large so we can tolerate adding 0 into max element) - if (i + 1 < N + N) { - quotient_mul_modulus[i + 1] += hi; - } +impl std::ops::Div for RuntimeBigNum { + // Note: this method is expensive! Witness computation is extremely expensive as it requires modular exponentiation + fn div(self, divisor: Self) -> Self { + let params = self.params; + Self { limbs: div(params, self.limbs, divisor.limbs), params } } - let quotient_mul_modulus_u60: U60Repr = U60Repr::new(quotient_mul_modulus_normalized); - - let x_u60 : U60Repr = U60Repr::new(x); - let mut remainder_u60 = x_u60 - quotient_mul_modulus_u60; - - if (remainder_u60.gte(modulus_u60)) { - remainder_u60 = remainder_u60 - modulus_u60; - quotient_u60.increment(); - } else {} - - let q: [Field; N] = U60Repr::into(quotient_u60); - let r: [Field; N] = U60Repr::into(remainder_u60); +} - (q, r) +impl std::cmp::Eq for RuntimeBigNum { + fn eq(self, other: Self) -> bool { + let params = self.params; + eq(params, self.limbs, other.limbs) + } } diff --git a/src/runtime_bignum_test.nr b/src/runtime_bignum_test.nr index d60eacb5..51f9d60b 100644 --- a/src/runtime_bignum_test.nr +++ b/src/runtime_bignum_test.nr @@ -1,24 +1,14 @@ -use crate::BigNum; -use crate::runtime_bignum::BigNumInstance; -use crate::runtime_bignum::BigNumParamsTrait; use crate::utils::u60_representation::U60Repr; -use crate::fields::bn254Fq::BNParams as BNParams; -struct Test2048Params {} +use crate::runtime_bignum::RuntimeBigNum; -// See https://github.com/noir-lang/noir/issues/6172 -#[test] -fn silence_warning() { - let _ = Test2048Params {}; -} +use crate::params::BigNumParams; -impl BigNumParamsTrait<18> for Test2048Params { - fn modulus_bits() -> u32 { - 2048 - } -} +use crate::fields::bn254Fq::BN254_Fq_PARAMS; -fn get_2048_BN_instance() -> BigNumInstance<18, Test2048Params> { +fn get_2048_BN_params() -> BigNumParams<18> { + let has_multiplicative_inverse = false; + let modulus_bits_getter = || 2048; let modulus: [Field; 18] = [ 0x0000000000000000000000000000000000c0a197a5ae0fcdceb052c9732614fe, 0x0000000000000000000000000000000000656ae034423283422243918ab83be3, @@ -59,349 +49,385 @@ fn get_2048_BN_instance() -> BigNumInstance<18, Test2048Params> { 0x0000000000000000000000000000000000ff4e42304e60fb3a54fca735499f2c, 0x0000000000000000000000000000000000000000000000000000000000000162 ]; - BigNumInstance::new(modulus, redc_param) + BigNumParams::new( + has_multiplicative_inverse, + modulus_bits_getter, + modulus, + redc_param + ) } -type Fq = BigNum<3, BNParams>; -// type FqInstance = BigNumInstance<3, BNParams>; -// type Fqq = BigNum<18, Test2048Params>; -// type FqqInstance = BigNumInstance<18, Test2048Params>; - -fn test_eq(BNInstance: BigNumInstance) where Params: BigNumParamsTrait { - let a: BigNum = BNInstance.__derive_from_seed([1, 2, 3, 4]); - let b: BigNum = BNInstance.__derive_from_seed([1, 2, 3, 4]); - let c: BigNum = BNInstance.__derive_from_seed([2, 2, 3, 4]); +fn test_eq(params: BigNumParams) { + let a = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; + let b = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; + let c = unsafe { + RuntimeBigNum::__derive_from_seed(params, [2, 2, 3, 4]) + }; - let modulus: BigNum = BNInstance.modulus(); + let modulus = a.modulus(); let t0: U60Repr = (U60Repr::from(modulus.limbs)); let t1: U60Repr = (U60Repr::from(b.limbs)); - let b_plus_modulus: BigNum = BigNum { limbs: U60Repr::into(t0 + t1) }; + let b_plus_modulus = RuntimeBigNum { limbs: U60Repr::into(t0 + t1), params }; - assert(BNInstance.eq(a, b) == true); - assert(BNInstance.eq(a, b_plus_modulus) == true); - assert(BNInstance.eq(c, b) == false); - assert(BNInstance.eq(c, a) == false); + assert((a == b) == true); + assert((a == b_plus_modulus) == true); + assert((c == b) == false); + assert((c == a) == false); } // 98760 // 99689 // 929 gates for a 2048 bit mul -fn test_mul(BNInstance: BigNumInstance) where Params: BigNumParamsTrait { - let a: BigNum = BNInstance.__derive_from_seed([1, 2, 3, 4]); - let b: BigNum = BNInstance.__derive_from_seed([4, 5, 6, 7]); - - let c = BNInstance.mul(BNInstance.add(a, b), BNInstance.add(a, b)); - let d = BNInstance.add( - BNInstance.add( - BNInstance.add(BNInstance.mul(a, a), BNInstance.mul(b, b)), - BNInstance.mul(a, b) - ), - BNInstance.mul(a, b) - ); - assert(BNInstance.eq(c, d)); +fn test_mul(params: BigNumParams) { + let a = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; + let b = unsafe { + RuntimeBigNum::__derive_from_seed(params, [4, 5, 6, 7]) + }; + + let c = (a + b) * (a + b); + let d = (a * a) + (b * b) + (a * b) + (a * b); + assert(c == d); } -fn test_add(bn: BigNumInstance) where Params: BigNumParamsTrait { - let a: BigNum = bn.__derive_from_seed([1, 2, 3, 4]); - let b: BigNum = bn.__derive_from_seed([4, 5, 6, 7]); - let one: BigNum = BigNum::one(); +fn test_add(params: BigNumParams) { + let a = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; + let b = unsafe { + RuntimeBigNum::__derive_from_seed(params, [4, 5, 6, 7]) + }; + let one = RuntimeBigNum::one(params); a.validate_in_range(); - bn.validate_in_field(a); + a.validate_in_field(); b.validate_in_range(); - bn.validate_in_field(b); + b.validate_in_field(); - let mut c = bn.add(a, b); - c = bn.add(c, c); - let d = bn.mul(bn.add(a, b), bn.add(one, one)); - assert(bn.eq(c, d)); + let mut c = a + b; + c = c + c; + let d = (a + b) * (one + one); + assert(c == d); - let e = bn.add(one, one); + let e = one + one; for i in 1..N { assert(e.limbs[i] == 0); } assert(e.limbs[0] == 2); } -fn test_div(bn: BigNumInstance) where Params: BigNumParamsTrait { - let a: BigNum = bn.__derive_from_seed([1, 2, 3, 4]); - let b: BigNum = bn.__derive_from_seed([4, 5, 6, 7]); +fn test_div(params: BigNumParams) { + let a = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; + let b = unsafe { + RuntimeBigNum::__derive_from_seed(params, [4, 5, 6, 7]) + }; - let c = bn.div(a, b); - assert(bn.eq(bn.mul(b, c), a)); + let c = a / b; + assert((b * c) == a); } -fn test_invmod(bn: BigNumInstance) where Params: BigNumParamsTrait { - let u: BigNum = bn.__derive_from_seed([1, 2, 3, 4]); +unconstrained fn test_invmod(params: BigNumParams) { + let u = RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]); for _ in 0..1 { - let v = bn.__invmod(u); - let result = bn.__mul(u, v); - let expected: BigNum = BigNum::one(); + let v = u.__invmod(); + let result = u.__mul(v); + let expected = RuntimeBigNum::one(params); assert(result.limbs == expected.limbs); } } -fn assert_is_not_equal(bn: BigNumInstance) where Params: BigNumParamsTrait { - let a: BigNum = bn.__derive_from_seed([1, 2, 3, 4]); - let b: BigNum = bn.__derive_from_seed([4, 5, 6, 7]); +unconstrained fn assert_is_not_equal(params: BigNumParams) { + let a = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; + let b = unsafe { + RuntimeBigNum::__derive_from_seed(params, [4, 5, 6, 7]) + }; - bn.assert_is_not_equal(a, b); + a.assert_is_not_equal(b); } -fn assert_is_not_equal_fail(bn: BigNumInstance) where Params: BigNumParamsTrait { - let a: BigNum = bn.__derive_from_seed([1, 2, 3, 4]); - let b: BigNum = bn.__derive_from_seed([1, 2, 3, 4]); +unconstrained fn assert_is_not_equal_fail(params: BigNumParams) { + let a = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; + let b = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; - bn.assert_is_not_equal(a, b); + a.assert_is_not_equal(b); } -fn assert_is_not_equal_overloaded_lhs_fail(bn: BigNumInstance) where Params: BigNumParamsTrait { - let a: BigNum = bn.__derive_from_seed([1, 2, 3, 4]); - let b: BigNum = bn.__derive_from_seed([1, 2, 3, 4]); +fn assert_is_not_equal_overloaded_lhs_fail(params: BigNumParams) { + let a = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; + let b = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; - let modulus = bn.modulus(); + let modulus = params.modulus; let t0: U60Repr = U60Repr::from(a.limbs); - let t1: U60Repr = U60Repr::from(modulus.limbs); - let a_plus_modulus: BigNum = BigNum { limbs: U60Repr::into(t0 + t1) }; - bn.assert_is_not_equal(a_plus_modulus, b); + let t1: U60Repr = U60Repr::from(modulus); + let a_plus_modulus = RuntimeBigNum { limbs: U60Repr::into(t0 + t1), params }; + a_plus_modulus.assert_is_not_equal(b); } -fn assert_is_not_equal_overloaded_rhs_fail(bn: BigNumInstance) where Params: BigNumParamsTrait { - let a: BigNum = bn.__derive_from_seed([1, 2, 3, 4]); - let b: BigNum = bn.__derive_from_seed([1, 2, 3, 4]); +fn assert_is_not_equal_overloaded_rhs_fail(params: BigNumParams) { + let a = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; + let b = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; - let modulus = bn.modulus(); + let modulus = params.modulus; let t0: U60Repr = U60Repr::from(b.limbs); - let t1: U60Repr = U60Repr::from(modulus.limbs); - let b_plus_modulus: BigNum = BigNum { limbs: U60Repr::into(t0 + t1) }; - bn.assert_is_not_equal(a, b_plus_modulus); + let t1: U60Repr = U60Repr::from(modulus); + let b_plus_modulus = RuntimeBigNum { limbs: U60Repr::into(t0 + t1), params }; + a.assert_is_not_equal(b_plus_modulus); } -fn assert_is_not_equal_overloaded_fail(bn: BigNumInstance) where Params: BigNumParamsTrait { - let a: BigNum = bn.__derive_from_seed([1, 2, 3, 4]); - let b: BigNum = bn.__derive_from_seed([1, 2, 3, 4]); +fn assert_is_not_equal_overloaded_fail(params: BigNumParams) { + let a = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; + let b = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; - let modulus = bn.modulus(); + let modulus = params.modulus; let t0: U60Repr = U60Repr::from(a.limbs); let t1: U60Repr = U60Repr::from(b.limbs); - let t2: U60Repr = U60Repr::from(modulus.limbs); - let a_plus_modulus: BigNum = BigNum { limbs: U60Repr::into(t0 + t2) }; - let b_plus_modulus: BigNum = BigNum { limbs: U60Repr::into(t1 + t2) }; - bn.assert_is_not_equal(a_plus_modulus, b_plus_modulus); + let t2: U60Repr = U60Repr::from(modulus); + let a_plus_modulus = RuntimeBigNum { limbs: U60Repr::into(t0 + t2), params }; + let b_plus_modulus = RuntimeBigNum { limbs: U60Repr::into(t1 + t2), params }; + a_plus_modulus.assert_is_not_equal(b_plus_modulus); } #[test] fn test_eq_BN() { - let instance = BNParams::get_instance(); - test_eq(instance); + let params = BN254_Fq_PARAMS; + test_eq(params); } #[test] fn test_add_BN() { - let instance = BNParams::get_instance(); + let params = BN254_Fq_PARAMS; - let mut a: Fq = instance.modulus(); - let mut b: Fq = instance.modulus(); - let mut expected: Fq = instance.modulus(); + let mut a = RuntimeBigNum { limbs: params.modulus, params }; + let mut b = a; + let mut expected = a; a.limbs[0] -= 1; b.limbs[0] -= 1; expected.limbs[0] -= 2; - let result = instance.add(a, b); - assert(instance.eq(result, expected)); + let result = a + b; + assert(result == expected); } #[test] fn test_sub_test_BN() { - let instance = BNParams::get_instance(); + let params = BN254_Fq_PARAMS; + // 0 - 1 should equal p - 1 - let mut a: Fq = BigNum::new(); - let mut b: Fq = BigNum::one(); - let mut expected: Fq = instance.modulus(); + let mut a = RuntimeBigNum::new(params); + let mut b = RuntimeBigNum::one(params); + let mut expected = RuntimeBigNum { limbs: params.modulus, params }; expected.limbs[0] -= 1; // p - 1 - let result = instance.sub(a, b); - assert(instance.eq(result, expected)); + let result = a - b; + assert(result == expected); } #[test] fn test_sub_modulus_limit() { - let instance = BNParams::get_instance(); + let params = BN254_Fq_PARAMS; + // if we underflow, maximum result should be ... // 0 - 1 = o-1 // 0 - p = 0 - let mut a: Fq = BigNum::new(); - let mut b: Fq = instance.modulus(); - let mut expected: Fq = BigNum::new(); + let mut a= RuntimeBigNum::new(params); + let mut b= RuntimeBigNum { limbs: params.modulus, params }; + let mut expected= RuntimeBigNum::new(params); - let result = instance.sub(a, b); - assert(instance.eq(result, expected)); + let result = a - b; + assert(result == expected); } #[test(should_fail_with = "call to assert_max_bit_size")] fn test_sub_modulus_underflow() { - let instance = BNParams::get_instance(); + let params = BN254_Fq_PARAMS; // 0 - (p + 1) is smaller than p and should produce unsatisfiable constraints - let mut a: Fq = BigNum::new(); - let mut b: Fq = instance.modulus(); + let mut a = RuntimeBigNum::new(params); + let mut b = RuntimeBigNum { limbs: params.modulus, params }; b.limbs[0] += 1; - let mut expected: Fq = BigNum::one(); + let mut expected = RuntimeBigNum::one(params); - let result = instance.sub(a, b); + let result = a - b; - assert(instance.eq(result, expected)); + assert(result == expected); } #[test] fn test_add_modulus_limit() { - let instance = BNParams::get_instance(); + let params = BN254_Fq_PARAMS; + // p + 2^{254} - 1 should be the maximum allowed value fed into an add operation // when adding, if the result overflows the modulus, we conditionally subtract the modulus, producing 2^{254} - 1 // this is the largest value that will satisfy the range check applied when constructing a bignum - let p : U60Repr<3, 2> = U60Repr::from(instance.modulus().limbs); + let p : U60Repr<3, 2> = U60Repr::from(params.modulus); let two_pow_254_minus_1: U60Repr<3, 2> = U60Repr::from([0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x3fff]); - let a: Fq = BigNum { limbs: U60Repr::into(p) }; - let b: Fq = BigNum { limbs: U60Repr::into(two_pow_254_minus_1) }; - let result = instance.add(a, b); - assert(instance.eq(result, b)); + let a = RuntimeBigNum { limbs: U60Repr::into(p), params }; + let b = RuntimeBigNum { limbs: U60Repr::into(two_pow_254_minus_1), params }; + let result = a + b; + assert(result == b); } #[test(should_fail_with = "call to assert_max_bit_size")] fn test_add_modulus_overflow() { - let instance = BNParams::get_instance(); + let params = BN254_Fq_PARAMS; + //(2^{254} - 1) + (p - 1) = 2^{254} + p // after subtracting modulus, result is 2^{254} will does not satisfy the range check applied when constructing a BigNum - let p : U60Repr<3, 2> = U60Repr::from(instance.modulus().limbs); + let p : U60Repr<3, 2> = U60Repr::from(params.modulus); let two_pow_254_minus_1: U60Repr<3, 2> = U60Repr::from([0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x3fff]); let one = U60Repr::from([1, 0, 0]); - let a: Fq = BigNum { limbs: U60Repr::into(p + one) }; - let b: Fq = BigNum { limbs: U60Repr::into(two_pow_254_minus_1) }; - let result = instance.add(a, b); - assert(instance.eq(result, b)); + let a = RuntimeBigNum { limbs: U60Repr::into(p + one), params }; + let b = RuntimeBigNum { limbs: U60Repr::into(two_pow_254_minus_1), params }; + let result = a + b; + assert(result == b); } #[test] fn test_mul_BN() { - let instance = BNParams::get_instance(); - test_mul(instance); + let params = BN254_Fq_PARAMS; + test_mul(params); } #[test] fn test_add_BN2() { - let instance = BNParams::get_instance(); - test_add(instance); + let params = BN254_Fq_PARAMS; + test_add(params); } #[test] fn test_div_BN() { - let instance = BNParams::get_instance(); - test_div(instance); + let params = BN254_Fq_PARAMS; + test_div(params); } #[test] -fn test_invmod_BN() { - let instance = BNParams::get_instance(); - test_invmod(instance); +unconstrained fn test_invmod_BN() { + let params = BN254_Fq_PARAMS; + test_invmod(params); } #[test] -fn test_assert_is_not_equal_BN() { - let instance = BNParams::get_instance(); - assert_is_not_equal(instance); +unconstrained fn test_assert_is_not_equal_BN() { + let params = BN254_Fq_PARAMS; + assert_is_not_equal(params); } #[test(should_fail_with = "asssert_is_not_equal fail")] -fn test_assert_is_not_equal_fail_BN() { - let instance = BNParams::get_instance(); - assert_is_not_equal_fail(instance); +unconstrained fn test_assert_is_not_equal_fail_BN() { + let params = BN254_Fq_PARAMS; + assert_is_not_equal_fail(params); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_lhs_fail_BN() { - let instance = BNParams::get_instance(); - assert_is_not_equal_overloaded_lhs_fail(instance); + let params = BN254_Fq_PARAMS; + assert_is_not_equal_overloaded_lhs_fail(params); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_rhs_fail_BN() { - let instance = BNParams::get_instance(); - assert_is_not_equal_overloaded_rhs_fail(instance); + let params = BN254_Fq_PARAMS; + assert_is_not_equal_overloaded_rhs_fail(params); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_fail_BN() { - let instance = BNParams::get_instance(); - assert_is_not_equal_overloaded_fail(instance); + let params = BN254_Fq_PARAMS; + assert_is_not_equal_overloaded_fail(params); } #[test] fn test_eq_2048() { - let instance = get_2048_BN_instance(); - test_eq(instance); + let params = get_2048_BN_params(); + test_eq(params); } #[test] fn test_mul_2048() { - let instance = get_2048_BN_instance(); - test_mul(instance); + let params = get_2048_BN_params(); + test_mul(params); } #[test] fn test_add_2048() { - let instance = get_2048_BN_instance(); - test_add(instance); + let params = get_2048_BN_params(); + test_add(params); } #[test] -fn test_assert_is_not_equal_2048() { - let instance = get_2048_BN_instance(); - assert_is_not_equal(instance); +unconstrained fn test_assert_is_not_equal_2048() { + let params = get_2048_BN_params(); + assert_is_not_equal(params); } #[test(should_fail_with = "asssert_is_not_equal fail")] -fn test_assert_is_not_equal_fail_2048() { - let instance = get_2048_BN_instance(); - assert_is_not_equal_fail(instance); +unconstrained fn test_assert_is_not_equal_fail_2048() { + let params = get_2048_BN_params(); + assert_is_not_equal_fail(params); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_lhs_fail_2048() { - let instance = get_2048_BN_instance(); - assert_is_not_equal_overloaded_lhs_fail(instance); + let params = get_2048_BN_params(); + assert_is_not_equal_overloaded_lhs_fail(params); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_rhs_fail_2048() { - let instance = get_2048_BN_instance(); - assert_is_not_equal_overloaded_rhs_fail(instance); + let params = get_2048_BN_params(); + assert_is_not_equal_overloaded_rhs_fail(params); } #[test(should_fail_with = "asssert_is_not_equal fail")] fn test_assert_is_not_equal_overloaded_fail_2048() { - let instance = get_2048_BN_instance(); - assert_is_not_equal_overloaded_fail(instance); + let params = get_2048_BN_params(); + assert_is_not_equal_overloaded_fail(params); } // N.B. witness generation times make these tests take ~15 minutes each! Uncomment at your peril // #[test] // fn test_div_2048() { -// let instance = get_2048_BN_instance(); -// test_div(instance); +// let params = get_2048_BN_params(); +// test_div(params); // } // N.B. witness generation times make these tests take ~15 minutes each! Uncomment at your peril // #[test] // fn test_invmod_2048() { -// let instance = get_2048_BN_instance(); -// test_invmod(instance); +// let params = get_2048_BN_params(); +// test_invmod(params); // } #[test] fn test_2048_bit_quadratic_expression() { - let instance = get_2048_BN_instance(); + let params = get_2048_BN_params(); let a: [Field; 18] = [ 0x000000000000000000000000000000000083684820ff40795b8d9f1be2220cba, 0x0000000000000000000000000000000000d4924fbdc522b07b6cd0ef5508fd66, @@ -463,76 +489,92 @@ fn test_2048_bit_quadratic_expression() { 0x0000000000000000000000000000000000000000000000000000000000000058 ]; - let a_bn: BigNum<18, Test2048Params> = BigNum { limbs: a }; - let b_bn: BigNum<18, Test2048Params> = BigNum { limbs: b }; - let c_bn = instance.__mul(a_bn, b_bn); - assert(c_bn.limbs == c_expected); + let a= RuntimeBigNum { limbs: a, params }; + let b = RuntimeBigNum { limbs: b, params }; + let c = a * b; + assert(c.limbs == c_expected); - a_bn.validate_in_range(); + a.validate_in_range(); - instance.evaluate_quadratic_expression([[a_bn]], [[false]], [[b_bn]], [[false]], [c_bn], [true]); + RuntimeBigNum::evaluate_quadratic_expression(params, [[a]], [[false]], [[b]], [[false]], [c], [true]); } #[test] fn test_expressions() { - let instance = BNParams::get_instance(); + let params = BN254_Fq_PARAMS; + let x: [Field; 6] = [ 0x000000000000000000000000000000000083684820ff40795b8d9f1be2220cba, 0x0000000000000000000000000000000000d4924fbdc522b07b6cd0ef5508fd66, 0x0000000000000000000000000000000000d48f6c43c5930f3d70d6db09a48f4a, 0x0000000000000000000000000000000000e7f72b2c0756704bea85be38352b34, 0x00000000000000000000000000000000000000000000000000000000b05d5ac5, 0 ]; - let y: Fq = BigNum { + let y= RuntimeBigNum { limbs: [ 0x1, 0x1, 0x0 - ] + ], params }; - let z: Fq = BigNum { + let z= RuntimeBigNum { limbs: [ 0x2, 0x2, 0x0 - ] + ], params + }; + let yy = unsafe { + y.__add(y) }; - let yy = instance.__add(y, y); assert(yy.limbs == z.limbs); - let uu: Fq = BigNum { + let uu= RuntimeBigNum { limbs: [ 0x0000000000000000000000000000000000b4a832748da6ad742a1fd81b787643, 0x00000000000000000000000000000000009575f594e04080471712c1d7f18e89, 0x000000000000000000000000000000000000000000000000000000000000063 - ] + ], + params }; - let vv: Fq = BigNum { + let vv= RuntimeBigNum { limbs: [ 0x0000000000000000000000000000000000b4aec2748da6ad742a1fd81b787643, 0x00000000000000000000000000000000009575f594e0408047171a01d7f18e89, 0x0000000000000000000000000000000000000000000000000000000000000062 - ] + ], + params }; - let w: Fq = BigNum { + let w= RuntimeBigNum { limbs: [ 0x0000000000000000000000000000000000b4a832748da6ad742a1fd81b787643, 0x00000000000000000000000000000000009575f594e04080471712c1d7f18e89, 0x0000000000000000000000000000000000000000000000000000000000001f93 - ] + ], + params }; - let x: Fq = BigNum { + let x= RuntimeBigNum { limbs: [ 0x0000000000000000000000000000000000b4aec2748da6ad742a1fd81b787643, 0x00000000000000000000000000000000009575f594e0408047171a01d7f18e89, 0x0000000000000000000000000000000000000000000000000000000000000f93 - ] + ], + params + }; + let wx = unsafe { + w.__mul(x) + }; + let uv = unsafe { + uu.__mul(vv) + }; + let y = unsafe { + (uv.__add(wx)).__neg() + }; + let z = unsafe { + uv.__add(wx) }; - let wx = instance.__mul(w, x); - let uv = instance.__mul(uu, vv); - let y = instance.__neg(instance.__add(uv, wx)); - let z = instance.__add(uv, wx); - instance.evaluate_quadratic_expression( + RuntimeBigNum::evaluate_quadratic_expression( + params, [[uu], [w]], [[false], [false]], [[vv], [x]], @@ -540,7 +582,8 @@ fn test_expressions() { [z], [true] ); - instance.evaluate_quadratic_expression( + RuntimeBigNum::evaluate_quadratic_expression( + params, [[uu], [w]], [[false], [false]], [[vv], [x]], @@ -549,6 +592,6 @@ fn test_expressions() { [false] ); - let wx_constrained = instance.mul(w, x); + let wx_constrained = w * x; assert(wx_constrained.limbs == wx.limbs); } diff --git a/src/serialization.nr b/src/serialization.nr new file mode 100644 index 00000000..bba1672f --- /dev/null +++ b/src/serialization.nr @@ -0,0 +1,66 @@ +use crate::params::BigNumParams as P; + +/** +* @brief construct a BigNum instance out of an array of bytes in BIG ENDIAN format +* @description: each 120-bit limb represents 15 bytes, we require that the size of the byte array +* is precisely large enough to cover Params::modulus_bits() +* @param x: input byte array +**/ +pub(crate) fn from_be_bytes(params: P, x: [u8; NBytes]) -> [Field; N] { + let num_bits = NBytes * 8; + let modulus_bits_getter = params.modulus_bits_getter; + let modulus_bits = modulus_bits_getter(); + assert(num_bits >= modulus_bits); + assert(num_bits - modulus_bits < 8); + let mut result = [0; N]; + + let excess_bytes = N * 15 - NBytes; + let final_limb_bytes = 15 - excess_bytes; + let mut limb: Field = 0; + let mut k = 0; + for _j in 0..final_limb_bytes { + limb *= 256; + limb += x[k] as Field; + k += 1; + } + result[N - 1] = limb; + + for i in 1..N { + let mut limb: Field = 0; + for _j in 0..15 { + limb *= 256; + limb += x[k] as Field; + k += 1; + } + result[N - i - 1] = limb; + } + + // max_bits_in_most_significant_byte should be known at comptime. if not...messy! + let mut max_bits_in_most_significant_byte = 8 - (num_bits - modulus_bits); + + let most_significant_byte: Field = x[0] as Field; + + most_significant_byte.assert_max_bit_size(max_bits_in_most_significant_byte as u32); + result +} + +pub(crate) fn to_le_bytes(params: P, val: [Field; N]) -> [u8; NBytes] { + let modulus_bits_getter = params.modulus_bits_getter; + let modulus_bits = modulus_bits_getter(); + let nbytes = (modulus_bits / 8) + (modulus_bits % 8 != 0) as u32; + assert(nbytes <= NBytes); + + let mut result: [u8; NBytes] = [0; NBytes]; + for i in 0..N - 1 { + let limb_bytes: [u8; 15] = val[i].to_le_bytes(); + for j in 0..15 { + result[i * 15 + j] = limb_bytes[j]; + } + } + let last_limb_bytes: [u8; 15] = val[N - 1].to_le_bytes(); + let num_last_bytes = (NBytes - (N - 1) * 15); + for i in 0..num_last_bytes { + result[(N-1) * 15 + i] = last_limb_bytes[i]; + } + result +} diff --git a/src/unconstrained_helpers.nr b/src/unconstrained_helpers.nr new file mode 100644 index 00000000..0d9dd581 --- /dev/null +++ b/src/unconstrained_helpers.nr @@ -0,0 +1,223 @@ +use crate::utils::u60_representation::U60Repr; +use crate::utils::split_bits; + +use crate::params::BigNumParams as P; + +unconstrained pub(crate) fn __validate_in_field_compute_borrow_flags(params: P, val: [Field; N]) -> [bool; N] { + let mut flags: [bool; N] = [false; N]; + let modulus: [Field; N] = params.modulus; + flags[0] = modulus[0].lt(val[0]); + for i in 1..N - 1 { + flags[i] = modulus[i].lt(val[i] + flags[i - 1] as Field); + } + flags +} + +unconstrained pub(crate) fn __validate_gt_remainder(lhs: [Field; N], rhs: [Field; N]) -> ([Field; N], [bool; N], [bool; N]) { + let a_u60 : U60Repr = U60Repr::from(lhs); + let mut b_u60 : U60Repr = U60Repr::from(rhs); + + let underflow = b_u60.gte(a_u60); + b_u60 += U60Repr::one(); + assert(underflow == false, "BigNum::validate_gt check fails"); + let mut addend_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; + let mut result_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; + + let mut carry: u64 = 0; + let mut carry_in: u64 = 0; + let mut borrow: u64 = 0; + let mut borrow_in: u64 = 0; + let mut borrow_flags: [bool; N] = [false; N]; + let mut carry_flags: [bool; N] = [false; N]; + for i in 0..2 * N { + let mut add_term: u64 = a_u60.limbs[i] + addend_u60.limbs[i] + carry_in; + carry = (add_term >= 0x1000000000000000) as u64; + add_term -= (carry as u64 * 0x1000000000000000); + result_u60.limbs[i] = add_term; + carry_in = carry as u64; + borrow = ((b_u60.limbs[i] + borrow_in) > result_u60.limbs[i]) as u64; + let sub = (borrow << 60) + result_u60.limbs[i] - b_u60.limbs[i] - borrow_in; + result_u60.limbs[i] = sub; + borrow_in = borrow; + + if ((i & 1) == 1) { + if (carry & borrow == 1) { + carry = 0; + borrow = 0; + } + carry_flags[i/2] = carry as bool; + borrow_flags[i/2] = borrow as bool; + } + } + + let result = U60Repr::into(result_u60); + (result, carry_flags, borrow_flags) +} + +unconstrained pub(crate) fn __neg_with_flags(params: P, val: [Field; N]) -> ([Field; N], [bool; N]) { + let x_u60 : U60Repr = U60Repr::from(val); + let mut result_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; + + let mut borrow: u64 = 0; + let mut borrow_in: u64 = 0; + + let mut borrow_flags: [bool; N] = [false; N]; + for i in 0..2 * N { + borrow = ((x_u60.limbs[i] + borrow_in) > params.modulus_u60.limbs[i]) as u64; + let sub = (borrow << 60) + params.modulus_u60.limbs[i] - x_u60.limbs[i] - borrow_in; + result_u60.limbs[i] = sub; + borrow_in = borrow; + if ((i & 1) == 1) { + borrow_flags[i / 2] = borrow as bool; + } + } + let result = U60Repr::into(result_u60); + (result, borrow_flags) +} + +unconstrained pub(crate) fn __add_with_flags(params: P, lhs: [Field; N], rhs: [Field; N]) -> ([Field; N], [bool; N], [bool; N], bool) { + let a_u60 : U60Repr = U60Repr::from(lhs); + let b_u60 : U60Repr = U60Repr::from(rhs); + let add_u60 = a_u60 + b_u60; + + let overflow = add_u60.gte(params.modulus_u60); + + let mut subtrahend_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; + let mut result_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; + + if overflow { + subtrahend_u60 = params.modulus_u60; + } + + let mut carry: u64 = 0; + let mut carry_in: u64 = 0; + let mut borrow: u64 = 0; + let mut borrow_in: u64 = 0; + let mut borrow_flags: [bool; N] = [false; N]; + let mut carry_flags: [bool; N] = [false; N]; + for i in 0..2 * N { + let mut add_term: u64 = a_u60.limbs[i] + b_u60.limbs[i] + carry_in; + carry = (add_term >= 0x1000000000000000) as u64; + add_term -= (carry as u64 * 0x1000000000000000); + result_u60.limbs[i] = add_term; + carry_in = carry as u64; + borrow = ((subtrahend_u60.limbs[i] + borrow_in) > result_u60.limbs[i]) as u64; + let sub = (borrow << 60) + result_u60.limbs[i] - subtrahend_u60.limbs[i] - borrow_in; + result_u60.limbs[i] = sub; + borrow_in = borrow; + + if ((i & 1) == 1) { + let idx = (i - 1) / 2; + if (carry & borrow == 1) { + carry = 0; + borrow = 0; + } + carry_flags[idx] = carry as bool; + borrow_flags[idx] = borrow as bool; + } + } + let result = U60Repr::into(result_u60); + + (result, carry_flags, borrow_flags, overflow) +} + +unconstrained pub(crate) fn __sub_with_flags(params: P, lhs: [Field; N], rhs: [Field; N]) -> ([Field; N], [bool; N], [bool; N], bool) { + let a_u60 : U60Repr = U60Repr::from(lhs); + let b_u60 : U60Repr = U60Repr::from(rhs); + + let underflow = b_u60.gte(a_u60 + U60Repr::one()); + + let mut addend_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; + let mut result_u60 : U60Repr = U60Repr { limbs: [0; 2 * N] }; + + if underflow { + addend_u60 = params.modulus_u60; + } + + let mut carry: u64 = 0; + let mut carry_in: u64 = 0; + let mut borrow: u64 = 0; + let mut borrow_in: u64 = 0; + let mut borrow_flags: [bool; N] = [false; N]; + let mut carry_flags: [bool; N] = [false; N]; + for i in 0..2 * N { + let mut add_term: u64 = a_u60.limbs[i] + addend_u60.limbs[i] + carry_in; + carry = (add_term >= 0x1000000000000000) as u64; + add_term -= (carry as u64 * 0x1000000000000000); + result_u60.limbs[i] = add_term; + carry_in = carry as u64; + borrow = ((b_u60.limbs[i] + borrow_in) > result_u60.limbs[i]) as u64; + let sub = (borrow << 60) + result_u60.limbs[i] - b_u60.limbs[i] - borrow_in; + result_u60.limbs[i] = sub; + borrow_in = borrow; + + if ((i & 1) == 1) { + if (carry & borrow == 1) { + carry = 0; + borrow = 0; + } + carry_flags[i/2] = carry as bool; + borrow_flags[i/2] = borrow as bool; + } + } + let result = U60Repr::into(result_u60); + (result, carry_flags, borrow_flags, underflow) +} + +unconstrained pub(crate) fn __barrett_reduction( + x: [Field; 2 * N], + redc_param: [Field; N], + k: u32, + modulus: [Field; N], + modulus_u60: U60Repr +) -> ([Field; N], [Field; N]) { + let mut mulout: [Field; 3 * N] = [0; 3 * N]; + for i in 0..(N + N) { + for j in 0..N { + mulout[i + j] += x[i] * redc_param[j]; + } + } + mulout = split_bits::__normalize_limbs(mulout, 3 * N - 1); + let mulout_u60: U60Repr = U60Repr::new(mulout); + let mut quotient_u60 = mulout_u60.shr((k + k)); + + // N.B. we assume that the shifted quotient cannot exceed 2 times original bit size. + // (partial_quotient should be just slightly larger than the modulus, we could probably represent with a size N+1 array) + let partial_quotient_full: [Field; 3 * N] = quotient_u60.into_field_array(); + let mut partial_quotient: [Field; 2 * N] = [0; 2 * N]; + for i in 0..2 * N { + partial_quotient[i] = partial_quotient_full[i]; + } + // quotient_mul_modulus can never exceed input value `x` so can fit into size-2 array + let mut quotient_mul_modulus: [Field; 2 * N] = [0; 2 * N]; + let mut quotient_mul_modulus_normalized: [Field; 2 * N] = [0; 2 * N]; + for j in 0..N { + for i in 0..(N + N - j) { + quotient_mul_modulus[i + j] += partial_quotient[i] * modulus[j]; + } + } + + for i in 0..(N + N) { + let (lo, hi) = split_bits::split_120_bits(quotient_mul_modulus[i]); + quotient_mul_modulus_normalized[i] = lo; + // TODO: what is faster, leaving this if statement in or out? + // (array is size-1 too large so we can tolerate adding 0 into max element) + if (i + 1 < N + N) { + quotient_mul_modulus[i + 1] += hi; + } + } + let quotient_mul_modulus_u60: U60Repr = U60Repr::new(quotient_mul_modulus_normalized); + + let x_u60 : U60Repr = U60Repr::new(x); + let mut remainder_u60 = x_u60 - quotient_mul_modulus_u60; + + if (remainder_u60.gte(modulus_u60)) { + remainder_u60 = remainder_u60 - modulus_u60; + quotient_u60.increment(); + } else {} + + let q: [Field; N] = U60Repr::into(quotient_u60); + let r: [Field; N] = U60Repr::into(remainder_u60); + + (q, r) +} diff --git a/src/unconstrained_ops.nr b/src/unconstrained_ops.nr new file mode 100644 index 00000000..f2650abf --- /dev/null +++ b/src/unconstrained_ops.nr @@ -0,0 +1,290 @@ +use crate::utils::u60_representation::U60Repr; +use crate::utils::split_bits; + +use crate::params::BigNumParams as P; +use crate::unconstrained_helpers::__barrett_reduction; + +unconstrained pub(crate) fn __one() -> [Field; N] { + let mut limbs: [Field; N] = [0; N]; + limbs[0] = 1; + limbs +} + +unconstrained pub(crate) fn __derive_from_seed(params: P, seed: [u8; SeedBytes]) -> [Field; N] { + let mut rolling_seed = seed; + + let mut to_reduce: [Field; 2 * N] = [0; 2 * N]; + + let modulus_bits_getter = params.modulus_bits_getter; + let modulus_bits = modulus_bits_getter(); + let mut double_modulus_bits = modulus_bits * 2; + let mut double_modulus_bytes = (double_modulus_bits) / 8 + (double_modulus_bits % 8 != 0) as u32; + + let mut last_limb_bytes = double_modulus_bytes % 15; + if (last_limb_bytes == 0) { + last_limb_bytes = 15; + } + let mut last_limb_bits = double_modulus_bits % 8; + if (last_limb_bits == 0) { + last_limb_bits = 8; + } + + for i in 0..(N - 1) { + let hash: [u8; 32] = std::hash::sha256(rolling_seed); + let mut lo: Field = 0; + let mut hi: Field = 0; + for j in 0..15 { + hi *= 256; + lo *= 256; + + if (i < 2 * N - 2) { + lo += hash[j + 15] as Field; + hi += hash[j] as Field; + } + } + to_reduce[2 * i] = lo; + to_reduce[2 * i + 1] = hi; + rolling_seed[0] += 1; + } + + { + let hash: [u8; 32] = std::hash::sha256(rolling_seed); + let mut hi: Field = 0; + for j in 0..(last_limb_bytes - 1) { + hi *= 256; + hi += hash[j] as Field; + } + hi *= 256; + let last_byte = hash[last_limb_bytes - 1]; + let mask = (1 as u64 << (last_limb_bits) as u8) - 1; + let last_bits = last_byte as u64 & mask; + hi += last_bits as Field; + to_reduce[2 * N - 2] = hi; + } + let modulus_bits_getter = params.modulus_bits_getter; + let modulus_bits = modulus_bits_getter(); + let (_, remainder) = __barrett_reduction( + to_reduce, + params.redc_param, + modulus_bits, + params.modulus, + params.modulus_u60_x4 + ); + let result = remainder; + result +} + +unconstrained pub(crate) fn __eq(lhs: [Field; N], rhs: [Field; N]) -> bool { + lhs == rhs +} + +unconstrained pub(crate) fn __is_zero(limbs: [Field; N]) -> bool { + let mut result: bool = true; + for i in 0..N { + result = result & (limbs[i] == 0); + } + result +} + +/** +* @brief given an input `x`, compute `2p - x` (unconstrained) +* +* @description we subtract the input from double the modulus, because all constrained BigNum operations +* only guarantee that the output is in the range [0, ceil(log2(p))]. +* I.E. the input may be larger than the modulus `p`. +* In order to ensure this operation does not underflow, we compute `2p - x` instead of `p - x`. +* N.B. constrained BigNum operations do not fully constrain outputs to be in the range [0, p-1] +* because such a check is expensive and usually unneccesary. +*/ +unconstrained pub(crate) fn __neg(params: P, limbs: [Field; N]) -> [Field; N] { + let f: [Field; N] = limbs; + let x_u60 : U60Repr = U60Repr::from(f); + U60Repr::into(params.modulus_u60 - x_u60) +} + +unconstrained pub(crate) fn __add( + params: P, + lhs: [Field; N], + rhs: [Field; N] +) -> [Field; N] { + let x_u60 : U60Repr = U60Repr::from(lhs); + let y_u60 : U60Repr = U60Repr::from(rhs); + + let mut z_u60 = x_u60 + y_u60; + + if z_u60.gte(params.modulus_u60) { + z_u60 = z_u60 - params.modulus_u60; + } + U60Repr::into(z_u60) +} + +/** +* @brief given inputs `x, y` compute 2p + x - y (unconstrained) +* @description see `__neg` for why we use 2p instead of p +**/ +unconstrained pub(crate) fn __sub(params: P, lhs: [Field; N], rhs: [Field; N]) -> [Field; N] { + __add(params, lhs, __neg(params, rhs)) +} + +unconstrained pub(crate) fn __mul_with_quotient(params: P, lhs: [Field; N], rhs: [Field; N]) -> ([Field; N], [Field; N]) { + let mut mul: [Field; 2 * N] = [0; 2 * N]; + for i in 0..N { + for j in 0..N { + mul[i + j] += lhs[i] * rhs[j]; + } + } + let modulus_bits_getter = params.modulus_bits_getter; + let modulus_bits = modulus_bits_getter(); + let (q, r) = __barrett_reduction( + split_bits::__normalize_limbs(mul, 2 * N), + params.redc_param, + modulus_bits, + params.modulus, + params.modulus_u60_x4 + ); + + (q, r) +} + +unconstrained pub(crate) fn __mul( + params: P, + lhs: [Field; N], + rhs: [Field; N] +) -> [Field; N] { + let (_, b) = __mul_with_quotient(params, lhs, rhs); + b +} + +unconstrained pub(crate) fn __div( + params: P, + numerator: [Field; N], + divisor: [Field; N] +) -> [Field; N] { + let inv_divisor = __invmod(params, divisor); + __mul(params, numerator, inv_divisor) +} + +/** +* @brief __udiv_mod performs *unconstrained* integer division between numerator, divisor +* +* i.e. 1. floor(numerator / divisor) = quotient +* 2. numerator % divisor = remainder +* 3. divisor * quotient + remainder = numerator +**/ +unconstrained pub(crate) fn __udiv_mod(numerator: [Field; N], divisor: [Field; N]) -> ([Field; N], [Field; N]) { + let mut quotient_u60: U60Repr = U60Repr::from([0; N]); + let mut remainder_u60: U60Repr = U60Repr::from(numerator); + + let mut divisor_u60: U60Repr = U60Repr::from(divisor); + let b = divisor_u60; + + let mut bit_difference = remainder_u60.get_msb() - divisor_u60.get_msb(); + + let mut accumulator_u60: U60Repr = U60Repr::one(); + divisor_u60 = divisor_u60.shl(bit_difference); + accumulator_u60 = accumulator_u60.shl(bit_difference); + + if (divisor_u60.gte(remainder_u60 + U60Repr::one())) { + divisor_u60.shr1(); + accumulator_u60.shr1(); + } + for _ in 0..(N * 120) { + if (remainder_u60.gte(b) == false) { + break; + } + + // we've shunted 'divisor' up to have the same bit length as our remainder. + // If remainder >= divisor, then a is at least '1 << bit_difference' multiples of b + if (remainder_u60.gte(divisor_u60)) { + remainder_u60 -= divisor_u60; + // we can use OR here instead of +, as + // accumulator is always a nice power of two + quotient_u60 = quotient_u60 + accumulator_u60; + } + divisor_u60.shr1(); // >>= 1; + accumulator_u60.shr1(); // >>= 1; + } + + (U60Repr::into(quotient_u60), U60Repr::into(remainder_u60)) +} + +unconstrained pub(crate) fn __invmod(params: P, val: [Field; N]) -> [Field; N] { + let one: [Field; N] = __one::(); + let one_u60: U60Repr = U60Repr::from(one); + let exp_u60 = params.modulus_u60.sub(one_u60.add(one_u60)); + let exp = U60Repr::into(exp_u60); + __pow(params, val, exp) +} + +unconstrained pub(crate) fn __pow( + params: P, + val: [Field; N], + exponent: [Field; N] +) -> [Field; N] { + let x: U60Repr = U60Repr::from(exponent); + + let modulus_bits_getter = params.modulus_bits_getter; + let modulus_bits = modulus_bits_getter(); + let num_bits = modulus_bits + 1; + + let mut accumulator: [Field; N] = __one::(); + + for i in 0..num_bits { + accumulator = __mul(params, accumulator, accumulator); + if x.get_bit(num_bits - i - 1) { + accumulator = __mul(params, accumulator, val); + } + } + accumulator +} + +unconstrained pub(crate) fn __batch_invert(params: P, x: [[Field; N]; M]) -> [[Field; N]; M] { + // TODO: ugly! Will fail if input slice is empty + let mut accumulator: [Field; N] = __one::(); + let mut result: [[Field; N]; M] = [[0; N]; M]; + let mut temporaries: [[Field; N]] = &[]; + for i in 0..x.len() { + temporaries = temporaries.push_back(accumulator); + if (__is_zero(x[i]) == false) { + accumulator = __mul(params, accumulator, x[i]); + } + } + + accumulator = __invmod(params, accumulator); + let mut T0: [Field; N] = [0; N]; + for i in 0..x.len() { + let idx = x.len() - 1 - i; + if (__is_zero(x[idx]) == false) { + T0 = __mul(params, accumulator, temporaries[idx]); + accumulator = __mul(params, accumulator, x[idx]); + result[idx] = T0; + } + } + result +} + +unconstrained pub(crate) fn __batch_invert_slice(params: P, x: [[Field; N]]) -> [[Field; N]] { + // TODO: ugly! Will fail if input slice is empty + let mut accumulator: [Field; N] = __one::(); + let mut result: [[Field; N]] = [[0; N]]; + let mut temporaries: [[Field; N]] = &[]; + for i in 0..x.len() { + temporaries = temporaries.push_back(accumulator); + if (__is_zero(x[i]) == false) { + accumulator = __mul(params, accumulator, x[i]); + } + result = result.push_back([0; N]); + } + + accumulator = __invmod(params, accumulator); + let mut T0: [Field; N] = [0; N]; + for i in 0..x.len() { + let idx = x.len() - 1 - i; + if (__is_zero(x[idx]) == false) { + T0 = __mul(params, accumulator, temporaries[idx]); + accumulator = __mul(params, accumulator, x[idx]); + result[idx] = T0; + } + } + result +} diff --git a/src/utils/map.nr b/src/utils/map.nr new file mode 100644 index 00000000..50e3d13c --- /dev/null +++ b/src/utils/map.nr @@ -0,0 +1,12 @@ +// Copied from std::array, because I couldn't figure out how to import the `map` method of the weird trait for an array. +// And the reason I wanted direct access to it, is because I couldn't figure out how to implement a double map. +pub fn map(arr: [T; N], f: fn[Env](T) -> U) -> [U; N] { + let first_elem = f(arr[0]); + let mut ret = [first_elem; N]; + + for i in 1..arr.len() { + ret[i] = f(arr[i]); + } + + ret +} diff --git a/src/utils/mod.nr b/src/utils/mod.nr index ca761e47..3d75400e 100644 --- a/src/utils/mod.nr +++ b/src/utils/mod.nr @@ -1,4 +1,5 @@ -pub(crate) mod u60_representation; -pub(crate) mod split_bits; -pub(crate) mod u60_representation_test; -pub(crate) mod msb; +mod u60_representation; +mod split_bits; +mod u60_representation_test; +mod msb; +mod map; From b7de59442a703a8df738917a7b37d1eba93ca068 Mon Sep 17 00:00:00 2001 From: Michael Connor Date: Thu, 3 Oct 2024 11:54:04 +0100 Subject: [PATCH 02/14] silence warnings --- src/bignum.nr | 16 ++++++++-------- src/bignum_test.nr | 6 +++--- src/fields/U1024.nr | 6 +++--- src/fields/U2048.nr | 6 +++--- src/fields/U256.nr | 4 ++-- src/fields/U384.nr | 6 +++--- src/fields/U4096.nr | 6 +++--- src/fields/U512.nr | 6 +++--- src/fields/U768.nr | 6 +++--- src/fields/U8192.nr | 6 +++--- src/fields/bls12_377Fq.nr | 4 ++-- src/fields/bls12_377Fr.nr | 6 +++--- src/fields/bls12_381Fq.nr | 6 +++--- src/fields/bls12_381Fr.nr | 7 ++++--- src/fields/bn254Fq.nr | 4 ++-- src/fields/ed25519Fq.nr | 6 +++--- src/fields/ed25519Fr.nr | 6 +++--- src/fields/mnt4_753Fq.nr | 6 +++--- src/fields/mnt4_753Fr.nr | 6 +++--- src/fields/mnt6_753Fq.nr | 6 +++--- src/fields/mnt6_753Fr.nr | 6 +++--- src/fields/pallasFq.nr | 6 +++--- src/fields/pallasFr.nr | 6 +++--- src/fields/secp256k1Fq.nr | 6 +++--- src/fields/secp256k1Fr.nr | 6 +++--- src/fields/secp256r1Fq.nr | 6 +++--- src/fields/secp256r1Fr.nr | 6 +++--- src/fields/secp384r1Fq.nr | 6 +++--- src/fields/secp384r1Fr.nr | 6 +++--- src/fields/vestaFq.nr | 6 +++--- src/fields/vestaFr.nr | 6 +++--- src/params.nr | 6 +++--- src/runtime_bignum_test.nr | 5 ++--- src/utils/u60_representation_test.nr | 24 +++++++++++++++++------- 34 files changed, 118 insertions(+), 108 deletions(-) diff --git a/src/bignum.nr b/src/bignum.nr index d27905e4..7b2108b9 100644 --- a/src/bignum.nr +++ b/src/bignum.nr @@ -1,6 +1,6 @@ use crate::utils::map::map; -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::constrained_ops::{ conditional_select, assert_is_not_equal, eq, validate_in_field, validate_in_range, neg, add, sub, mul, div, udiv_mod, udiv, umod @@ -85,7 +85,7 @@ pub(crate) trait BigNumTrait { fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self; } -impl BigNumTrait for BigNum where Params: BigNumParamsTrait { +impl BigNumTrait for BigNum where Params: BigNumParamsGetter { fn new() -> Self { Self { limbs: [0; N] } @@ -292,9 +292,9 @@ impl BigNumTrait for BigNum where Params: BigN } } -// impl BigNumTrait for BigNum where Params: BigNumParamsTrait {} +// impl BigNumTrait for BigNum where Params: BigNumParamsGetter {} -impl std::ops::Add for BigNum where Params: BigNumParamsTrait { +impl std::ops::Add for BigNum where Params: BigNumParamsGetter { // Note: this method is expensive! Try to craft quadratic relations and directly evaluate them // via evaluate_quadratic_expression fn add(self, other: Self) -> Self { @@ -303,7 +303,7 @@ impl std::ops::Add for BigNum where Params: BigNu } } -impl std::ops::Sub for BigNum where Params: BigNumParamsTrait { +impl std::ops::Sub for BigNum where Params: BigNumParamsGetter { // Note: this method is expensive! Try to craft quadratic relations and directly evaluate them // via evaluate_quadratic_expression fn sub(self, other: Self) -> Self { @@ -312,7 +312,7 @@ impl std::ops::Sub for BigNum where Params: BigNu } } -impl std::ops::Mul for BigNum where Params: BigNumParamsTrait { +impl std::ops::Mul for BigNum where Params: BigNumParamsGetter { // Note: this method is expensive! Try to craft quadratic relations and directly evaluate them // via evaluate_quadratic_expression // e.g. performing a sum of multiple multiplications and additions via `evaluate_quadratic_expression` @@ -323,7 +323,7 @@ impl std::ops::Mul for BigNum where Params: BigNu } } -impl std::ops::Div for BigNum where Params: BigNumParamsTrait { +impl std::ops::Div for BigNum where Params: BigNumParamsGetter { // Note: this method is expensive! Witness computation is extremely expensive as it requires modular exponentiation fn div(self, other: Self) -> Self { let params = Params::get_params(); @@ -331,7 +331,7 @@ impl std::ops::Div for BigNum where Params: BigNu } } -impl std::cmp::Eq for BigNum where Params: BigNumParamsTrait { +impl std::cmp::Eq for BigNum where Params: BigNumParamsGetter { fn eq(self, other: Self) -> bool { let params = Params::get_params(); eq(params, self.limbs, other.limbs) diff --git a/src/bignum_test.nr b/src/bignum_test.nr index 146afa0e..1fbb9966 100644 --- a/src/bignum_test.nr +++ b/src/bignum_test.nr @@ -4,7 +4,7 @@ use crate::bignum::BigNum; use crate::bignum::BigNumTrait; use crate::params::BigNumParams; -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::fields::bn254Fq::BN254_Fq_Params; use crate::fields::U256::U256Params; @@ -17,7 +17,7 @@ fn silence_warning() { let _ = Test2048Params {}; } -impl BigNumParamsTrait<18> for Test2048Params { +impl BigNumParamsGetter<18> for Test2048Params { fn get_params() -> BigNumParams<18> { let has_multiplicative_inverse = false; let modulus_bits_getter = || 2048; @@ -94,7 +94,7 @@ fn test_eq() where BN: BigNumTrait { assert(c.eq(a) == false); } -// fn test_eq(_: BigNum) where Params: BigNumParamsTrait + RuntimeBigNumParamsTrait { +// fn test_eq(_: BigNum) where Params: BigNumParamsGetter + RuntimeBigNumParamsTrait { // let a = BigNum::__derive_from_seed([1, 2, 3, 4]); // let b = BigNum::__derive_from_seed([1, 2, 3, 4]); // let c = BigNum::__derive_from_seed([2, 2, 3, 4]); diff --git a/src/fields/U1024.nr b/src/fields/U1024.nr index aedfd269..6dc7ffcc 100644 --- a/src/fields/U1024.nr +++ b/src/fields/U1024.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global U1024_PARAMS: BigNumParams<9> = BigNumParams { ] }; -struct U1024Params {} +pub struct U1024Params {} -impl BigNumParamsTrait<9> for U1024Params { +impl BigNumParamsGetter<9> for U1024Params { fn get_params() -> BigNumParams<9> { U1024_PARAMS } diff --git a/src/fields/U2048.nr b/src/fields/U2048.nr index a677b974..99fc3bdf 100644 --- a/src/fields/U2048.nr +++ b/src/fields/U2048.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global U2048_PARAMS: BigNumParams<18> = BigNumParams { ] }; -struct U2048Params {} +pub struct U2048Params {} -impl BigNumParamsTrait<18> for U2048Params { +impl BigNumParamsGetter<18> for U2048Params { fn get_params() -> BigNumParams<18> { U2048_PARAMS } diff --git a/src/fields/U256.nr b/src/fields/U256.nr index 10951b32..19b40cad 100644 --- a/src/fields/U256.nr +++ b/src/fields/U256.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -22,7 +22,7 @@ global U256_PARAMS: BigNumParams<3> = BigNumParams { pub struct U256Params {} -impl BigNumParamsTrait<3> for U256Params { +impl BigNumParamsGetter<3> for U256Params { fn get_params() -> BigNumParams<3> { U256_PARAMS } diff --git a/src/fields/U384.nr b/src/fields/U384.nr index 59a47181..dba9054e 100644 --- a/src/fields/U384.nr +++ b/src/fields/U384.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global U384_PARAMS: BigNumParams<4> = BigNumParams { ] }; -struct U384_Params {} +pub struct U384_Params {} -impl BigNumParamsTrait<4> for U384_Params { +impl BigNumParamsGetter<4> for U384_Params { fn get_params() -> BigNumParams<4> { U384_PARAMS } diff --git a/src/fields/U4096.nr b/src/fields/U4096.nr index 88b84fc2..441c28e0 100644 --- a/src/fields/U4096.nr +++ b/src/fields/U4096.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global U4096_PARAMS: BigNumParams<35> = BigNumParams { ] }; -struct U4096Params {} +pub struct U4096Params {} -impl BigNumParamsTrait<35> for U4096Params { +impl BigNumParamsGetter<35> for U4096Params { fn get_params() -> BigNumParams<35> { U4096_PARAMS } diff --git a/src/fields/U512.nr b/src/fields/U512.nr index 4aa93f3c..66c3f30d 100644 --- a/src/fields/U512.nr +++ b/src/fields/U512.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global U512_PARAMS: BigNumParams<5> = BigNumParams { ] }; -struct U512Params {} +pub struct U512Params {} -impl BigNumParamsTrait<5> for U512Params { +impl BigNumParamsGetter<5> for U512Params { fn get_params() -> BigNumParams<5> { U512_PARAMS } diff --git a/src/fields/U768.nr b/src/fields/U768.nr index 98223e1a..cf41ce21 100644 --- a/src/fields/U768.nr +++ b/src/fields/U768.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global U768_PARAMS: BigNumParams<13> = BigNumParams { ] }; -struct U768Params {} +pub struct U768Params {} -impl BigNumParamsTrait<13> for U768Params { +impl BigNumParamsGetter<13> for U768Params { fn get_params() -> BigNumParams<13> { U768_PARAMS } diff --git a/src/fields/U8192.nr b/src/fields/U8192.nr index 5c4951b2..d4788d3a 100644 --- a/src/fields/U8192.nr +++ b/src/fields/U8192.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global U8192_PARAMS: BigNumParams<69> = BigNumParams { ] }; -struct U8192Params {} +pub struct U8192Params {} -impl BigNumParamsTrait<69> for U8192Params { +impl BigNumParamsGetter<69> for U8192Params { fn get_params() -> BigNumParams<69> { U8192_PARAMS } diff --git a/src/fields/bls12_377Fq.nr b/src/fields/bls12_377Fq.nr index 7d876a83..5cf050aa 100644 --- a/src/fields/bls12_377Fq.nr +++ b/src/fields/bls12_377Fq.nr @@ -16,7 +16,7 @@ //! * G1 curve equation: y^2 = x^3 + 1 //! * G2 curve equation: y^2 = x^3 + B, where //! * B = Fq2(0, 155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906) -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -40,7 +40,7 @@ global BLS12_377_Fq_PARAMS: BigNumParams<4> = BigNumParams { pub struct BLS12_377_Fq_Params {} -impl BigNumParamsTrait<4> for BLS12_377_Fq_Params { +impl BigNumParamsGetter<4> for BLS12_377_Fq_Params { fn get_params() -> BigNumParams<4> { BLS12_377_Fq_PARAMS } diff --git a/src/fields/bls12_377Fr.nr b/src/fields/bls12_377Fr.nr index 572e9358..6b9789f5 100644 --- a/src/fields/bls12_377Fr.nr +++ b/src/fields/bls12_377Fr.nr @@ -16,7 +16,7 @@ //! * G1 curve equation: y^2 = x^3 + 1 //! * G2 curve equation: y^2 = x^3 + B, where //! * B = Fq2(0, 155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906) -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -38,9 +38,9 @@ global BLS12_377_Fr_PARAMS: BigNumParams<3> = BigNumParams { ] }; -struct BLS12_377_Fr_Params {} +pub struct BLS12_377_Fr_Params {} -impl BigNumParamsTrait<3> for BLS12_377_Fr_Params { +impl BigNumParamsGetter<3> for BLS12_377_Fr_Params { fn get_params() -> BigNumParams<3> { BLS12_377_Fr_PARAMS } diff --git a/src/fields/bls12_381Fq.nr b/src/fields/bls12_381Fq.nr index fea750f9..93e1ccab 100644 --- a/src/fields/bls12_381Fq.nr +++ b/src/fields/bls12_381Fq.nr @@ -14,7 +14,7 @@ //! * valuation(r - 1, 2) = 32 //! * G1 curve equation: y^2 = x^3 + 4 //! * G2 curve equation: y^2 = x^3 + Fq2(4, 4) -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -36,9 +36,9 @@ global BLS12_381_Fq_PARAMS: BigNumParams<4> = BigNumParams { ] }; -struct BLS12_381_Fq_Params {} +pub struct BLS12_381_Fq_Params {} -impl BigNumParamsTrait<4> for BLS12_381_Fq_Params { +impl BigNumParamsGetter<4> for BLS12_381_Fq_Params { fn get_params() -> BigNumParams<4> { BLS12_381_Fq_PARAMS } diff --git a/src/fields/bls12_381Fr.nr b/src/fields/bls12_381Fr.nr index 6f968dd8..6ccf0667 100644 --- a/src/fields/bls12_381Fr.nr +++ b/src/fields/bls12_381Fr.nr @@ -14,7 +14,7 @@ //! * valuation(r - 1, 2) = 32 //! * G1 curve equation: y^2 = x^3 + 4 //! * G2 curve equation: y^2 = x^3 + Fq2(4, 4) -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -36,8 +36,9 @@ global BLS12_381_Fr_PARAMS: BigNumParams<3> = BigNumParams { ] }; -struct BLS12_381_Fr_Params {} -impl BigNumParamsTrait<3> for BLS12_381_Fr_Params { +pub struct BLS12_381_Fr_Params {} + +impl BigNumParamsGetter<3> for BLS12_381_Fr_Params { fn get_params() -> BigNumParams<3> { BLS12_381_Fr_PARAMS } diff --git a/src/fields/bn254Fq.nr b/src/fields/bn254Fq.nr index 61a4d7f9..eaacd7f1 100644 --- a/src/fields/bn254Fq.nr +++ b/src/fields/bn254Fq.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -22,7 +22,7 @@ global BN254_Fq_PARAMS: BigNumParams<3> = BigNumParams { pub struct BN254_Fq_Params {} -impl BigNumParamsTrait<3> for BN254_Fq_Params { +impl BigNumParamsGetter<3> for BN254_Fq_Params { fn get_params() -> BigNumParams<3> { BN254_Fq_PARAMS } diff --git a/src/fields/ed25519Fq.nr b/src/fields/ed25519Fq.nr index e610153f..d8af5af6 100644 --- a/src/fields/ed25519Fq.nr +++ b/src/fields/ed25519Fq.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global ED25519_Fq_PARAMS: BigNumParams<3> = BigNumParams { ] }; -struct ED25519_Fq_Params {} +pub struct ED25519_Fq_Params {} -impl BigNumParamsTrait<3> for ED25519_Fq_Params { +impl BigNumParamsGetter<3> for ED25519_Fq_Params { fn get_params() -> BigNumParams<3> { ED25519_Fq_PARAMS } diff --git a/src/fields/ed25519Fr.nr b/src/fields/ed25519Fr.nr index 9df6e099..72be347d 100644 --- a/src/fields/ed25519Fr.nr +++ b/src/fields/ed25519Fr.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global ED25519_Fr_PARAMS: BigNumParams<3> = BigNumParams { ] }; -struct ED25519_Fr_Params {} +pub struct ED25519_Fr_Params {} -impl BigNumParamsTrait<3> for ED25519_Fr_Params { +impl BigNumParamsGetter<3> for ED25519_Fr_Params { fn get_params() -> BigNumParams<3> { ED25519_Fr_PARAMS } diff --git a/src/fields/mnt4_753Fq.nr b/src/fields/mnt4_753Fq.nr index 00c84564..14c5d641 100644 --- a/src/fields/mnt4_753Fq.nr +++ b/src/fields/mnt4_753Fq.nr @@ -19,7 +19,7 @@ //! * B = Fq2(0, b * NON_RESIDUE) //! * NON_RESIDUE = 13 is the quadratic non-residue used to conpub struct the //! extension field Fq2 -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -41,9 +41,9 @@ global MNT4_753_Fq_PARAMS: BigNumParams<7> = BigNumParams { ] }; -struct MNT4_753_Fq_Params {} +pub struct MNT4_753_Fq_Params {} -impl BigNumParamsTrait<7> for MNT4_753_Fq_Params { +impl BigNumParamsGetter<7> for MNT4_753_Fq_Params { fn get_params() -> BigNumParams<7> { MNT4_753_Fq_PARAMS } diff --git a/src/fields/mnt4_753Fr.nr b/src/fields/mnt4_753Fr.nr index 68a9d50a..ba8ae9de 100644 --- a/src/fields/mnt4_753Fr.nr +++ b/src/fields/mnt4_753Fr.nr @@ -19,7 +19,7 @@ //! * B = Fq2(0, b * NON_RESIDUE) //! * NON_RESIDUE = 13 is the quadratic non-residue used to conpub struct the //! extension field Fq2 -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -41,9 +41,9 @@ global MNT4_753_Fr_PARAMS: BigNumParams<7> = BigNumParams { ] }; -struct MNT4_753_Fr_Params {} +pub struct MNT4_753_Fr_Params {} -impl BigNumParamsTrait<7> for MNT4_753_Fr_Params { +impl BigNumParamsGetter<7> for MNT4_753_Fr_Params { fn get_params() -> BigNumParams<7> { MNT4_753_Fr_PARAMS } diff --git a/src/fields/mnt6_753Fq.nr b/src/fields/mnt6_753Fq.nr index 2ed18388..d9f03a7a 100644 --- a/src/fields/mnt6_753Fq.nr +++ b/src/fields/mnt6_753Fq.nr @@ -19,7 +19,7 @@ //! * B = Fq3(b * NON_RESIDUE, 0, 0) //! * NON_RESIDUE = 11 is the cubic non-residue used to conpub struct the //! extension field Fq3 -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -41,9 +41,9 @@ global MNT6_753_Fq_PARAMS: BigNumParams<7> = BigNumParams { ] }; -struct MNT6_753_Fq_Params {} +pub struct MNT6_753_Fq_Params {} -impl BigNumParamsTrait<7> for MNT6_753_Fq_Params { +impl BigNumParamsGetter<7> for MNT6_753_Fq_Params { fn get_params() -> BigNumParams<7> { MNT6_753_Fq_PARAMS } diff --git a/src/fields/mnt6_753Fr.nr b/src/fields/mnt6_753Fr.nr index 7f88e572..b07cacdc 100644 --- a/src/fields/mnt6_753Fr.nr +++ b/src/fields/mnt6_753Fr.nr @@ -19,7 +19,7 @@ //! * B = Fq3(b * NON_RESIDUE, 0, 0) //! * NON_RESIDUE = 11 is the cubic non-residue used to conpub struct the //! extension field Fq3 -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -41,9 +41,9 @@ global MNT6_753_Fr_PARAMS: BigNumParams<7> = BigNumParams { ] }; -struct MNT6_753_Fr_Params {} +pub struct MNT6_753_Fr_Params {} -impl BigNumParamsTrait<7> for MNT6_753_Fr_Params { +impl BigNumParamsGetter<7> for MNT6_753_Fr_Params { fn get_params() -> BigNumParams<7> { MNT6_753_Fr_PARAMS } diff --git a/src/fields/pallasFq.nr b/src/fields/pallasFq.nr index 06023e1a..4265ae55 100644 --- a/src/fields/pallasFq.nr +++ b/src/fields/pallasFq.nr @@ -13,7 +13,7 @@ //! * Curve equation: y^2 = x^3 + 5 //! * Valuation(q - 1, 2) = 32 //! * Valuation(r - 1, 2) = 32 -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -35,9 +35,9 @@ global Pallas_Fq_PARAMS: BigNumParams<3> = BigNumParams { ] }; -struct Pallas_Fq_Params {} +pub struct Pallas_Fq_Params {} -impl BigNumParamsTrait<3> for Pallas_Fq_Params { +impl BigNumParamsGetter<3> for Pallas_Fq_Params { fn get_params() -> BigNumParams<3> { Pallas_Fq_PARAMS } diff --git a/src/fields/pallasFr.nr b/src/fields/pallasFr.nr index 19946f83..e696d38f 100644 --- a/src/fields/pallasFr.nr +++ b/src/fields/pallasFr.nr @@ -13,7 +13,7 @@ //! * Curve equation: y^2 = x^3 + 5 //! * Valuation(q - 1, 2) = 32 //! * Valuation(r - 1, 2) = 32 -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -35,9 +35,9 @@ global Pallas_Fr_PARAMS: BigNumParams<3> = BigNumParams { ] }; -struct Pallas_Fr_Params {} +pub struct Pallas_Fr_Params {} -impl BigNumParamsTrait<3> for Pallas_Fr_Params { +impl BigNumParamsGetter<3> for Pallas_Fr_Params { fn get_params() -> BigNumParams<3> { Pallas_Fr_PARAMS } diff --git a/src/fields/secp256k1Fq.nr b/src/fields/secp256k1Fq.nr index 9f11555a..8615e19e 100644 --- a/src/fields/secp256k1Fq.nr +++ b/src/fields/secp256k1Fq.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global Secp256k1_Fq_PARAMS: BigNumParams<3> = BigNumParams { ] }; -struct Secp256k1_Fq_Params {} +pub struct Secp256k1_Fq_Params {} -impl BigNumParamsTrait<3> for Secp256k1_Fq_Params { +impl BigNumParamsGetter<3> for Secp256k1_Fq_Params { fn get_params() -> BigNumParams<3> { Secp256k1_Fq_PARAMS } diff --git a/src/fields/secp256k1Fr.nr b/src/fields/secp256k1Fr.nr index 0ce1a703..65474658 100644 --- a/src/fields/secp256k1Fr.nr +++ b/src/fields/secp256k1Fr.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global Secp256k1_Fr_PARAMS: BigNumParams<3> = BigNumParams { ] }; -struct Secp256k1_Fr_Params {} +pub struct Secp256k1_Fr_Params {} -impl BigNumParamsTrait<3> for Secp256k1_Fr_Params { +impl BigNumParamsGetter<3> for Secp256k1_Fr_Params { fn get_params() -> BigNumParams<3> { Secp256k1_Fr_PARAMS } diff --git a/src/fields/secp256r1Fq.nr b/src/fields/secp256r1Fq.nr index 56fb42d5..acad7082 100644 --- a/src/fields/secp256r1Fq.nr +++ b/src/fields/secp256r1Fq.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global Secp256r1_Fq_PARAMS: BigNumParams<3> = BigNumParams { ] }; -struct Secp256r1_Fq_Params {} +pub struct Secp256r1_Fq_Params {} -impl BigNumParamsTrait<3> for Secp256r1_Fq_Params { +impl BigNumParamsGetter<3> for Secp256r1_Fq_Params { fn get_params() -> BigNumParams<3> { Secp256r1_Fq_PARAMS } diff --git a/src/fields/secp256r1Fr.nr b/src/fields/secp256r1Fr.nr index 7b1cc7b9..4ed0088b 100644 --- a/src/fields/secp256r1Fr.nr +++ b/src/fields/secp256r1Fr.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global Secp256r1_Fr_PARAMS: BigNumParams<3> = BigNumParams { ] }; -struct Secp256r1_Fr_Params {} +pub struct Secp256r1_Fr_Params {} -impl BigNumParamsTrait<3> for Secp256r1_Fr_Params { +impl BigNumParamsGetter<3> for Secp256r1_Fr_Params { fn get_params() -> BigNumParams<3> { Secp256r1_Fr_PARAMS } diff --git a/src/fields/secp384r1Fq.nr b/src/fields/secp384r1Fq.nr index 22814829..9149f604 100644 --- a/src/fields/secp384r1Fq.nr +++ b/src/fields/secp384r1Fq.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global Secp384r1_Fq_PARAMS: BigNumParams<4> = BigNumParams { ] }; -struct Secp384r1_Fq_Params {} +pub struct Secp384r1_Fq_Params {} -impl BigNumParamsTrait<4> for Secp384r1_Fq_Params { +impl BigNumParamsGetter<4> for Secp384r1_Fq_Params { fn get_params() -> BigNumParams<4> { Secp384r1_Fq_PARAMS } diff --git a/src/fields/secp384r1Fr.nr b/src/fields/secp384r1Fr.nr index 76d95078..75393219 100644 --- a/src/fields/secp384r1Fr.nr +++ b/src/fields/secp384r1Fr.nr @@ -1,4 +1,4 @@ -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -20,9 +20,9 @@ global Secp384r1_Fr_PARAMS: BigNumParams<4> = BigNumParams { ] }; -struct Secp384r1_Fr_Params {} +pub struct Secp384r1_Fr_Params {} -impl BigNumParamsTrait<4> for Secp384r1_Fr_Params { +impl BigNumParamsGetter<4> for Secp384r1_Fr_Params { fn get_params() -> BigNumParams<4> { Secp384r1_Fr_PARAMS } diff --git a/src/fields/vestaFq.nr b/src/fields/vestaFq.nr index 202eb2be..0fcecf4e 100644 --- a/src/fields/vestaFq.nr +++ b/src/fields/vestaFq.nr @@ -14,7 +14,7 @@ //! * Curve equation: y^2 = x^3 + 5 //! * Valuation(q - 1, 2) = 32 //! * Valuation(r - 1, 2) = 32 -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -36,9 +36,9 @@ global Vesta_Fq_PARAMS: BigNumParams<3> = BigNumParams { ] }; -struct Vesta_Fq_Params {} +pub struct Vesta_Fq_Params {} -impl BigNumParamsTrait<3> for Vesta_Fq_Params { +impl BigNumParamsGetter<3> for Vesta_Fq_Params { fn get_params() -> BigNumParams<3> { Vesta_Fq_PARAMS } diff --git a/src/fields/vestaFr.nr b/src/fields/vestaFr.nr index 46e6560b..c0367491 100644 --- a/src/fields/vestaFr.nr +++ b/src/fields/vestaFr.nr @@ -14,7 +14,7 @@ //! * Curve equation: y^2 = x^3 + 5 //! * Valuation(q - 1, 2) = 32 //! * Valuation(r - 1, 2) = 32 -use crate::params::BigNumParamsTrait; +use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; @@ -36,9 +36,9 @@ global Vesta_Fr_PARAMS: BigNumParams<3> = BigNumParams { ] }; -struct Vesta_Fr_Params {} +pub struct Vesta_Fr_Params {} -impl BigNumParamsTrait<3> for Vesta_Fr_Params { +impl BigNumParamsGetter<3> for Vesta_Fr_Params { fn get_params() -> BigNumParams<3> { Vesta_Fr_PARAMS } diff --git a/src/params.nr b/src/params.nr index a9c6046b..bde9c676 100644 --- a/src/params.nr +++ b/src/params.nr @@ -22,7 +22,7 @@ pub(crate) struct BigNumParams { } // To be implemented by the user, or within the prebuilt options in the `fields/` dir. -pub(crate) trait BigNumParamsTrait { +pub(crate) trait BigNumParamsGetter { fn get_params() -> BigNumParams; } @@ -67,10 +67,10 @@ fn get_double_modulus(modulus: [Field; N]) -> [Field; N] { } // /** -// * @brief BigNumParamsTrait defines a "field" with which to parametrise BigNum. +// * @brief BigNumParamsGetter defines a "field" with which to parametrise BigNum. // * @description The "field" does not need to be prime, any value *should* work (TODO: test!) // **/ -// trait BigNumParamsTrait { +// trait BigNumParamsGetter { // fn has_multiplicative_inverse() -> bool; // // @brief modulus_bits = log2(modulus) rounded up // fn modulus_bits() -> u32; diff --git a/src/runtime_bignum_test.nr b/src/runtime_bignum_test.nr index 51f9d60b..61e318d8 100644 --- a/src/runtime_bignum_test.nr +++ b/src/runtime_bignum_test.nr @@ -1,10 +1,9 @@ use crate::utils::u60_representation::U60Repr; - use crate::runtime_bignum::RuntimeBigNum; - use crate::params::BigNumParams; +use crate::fields::bn254Fq::BN254_Fq_Params; -use crate::fields::bn254Fq::BN254_Fq_PARAMS; +global BN254_Fq_PARAMS = BN254_Fq_Params::get_params(); fn get_2048_BN_params() -> BigNumParams<18> { let has_multiplicative_inverse = false; diff --git a/src/utils/u60_representation_test.nr b/src/utils/u60_representation_test.nr index f32c1133..3029fed1 100644 --- a/src/utils/u60_representation_test.nr +++ b/src/utils/u60_representation_test.nr @@ -1,7 +1,7 @@ use crate::utils::u60_representation::U60Repr; #[test] -fn test_conversion() { +unconstrained fn test_conversion() { let p = 0xffffffffffffffffffffffffffffff; // 2^120 - 1 let expected: [Field; 3 * 2] = [p, p - 1, p - 2, p - 3, p - 4, p - 5]; let u60repr: U60Repr<3, 4> = U60Repr::new(expected); @@ -19,10 +19,14 @@ fn test_shr() { // 120 bits of 01010101 (repeating) let Y = 0x555555555555555555555555555555; let input: [Field; 6] = [X, X, X, X, X, X]; - let u60repr: U60Repr<3, 6> = U60Repr::new(input); + let u60repr: U60Repr<3, 6> = unsafe { + U60Repr::new(input) + }; let result = u60repr.shr(121); - let expected: U60Repr<3, 6> = U60Repr::new([Y, Y, Y, Y, Y, 0]); + let expected: U60Repr<3, 6> = unsafe { + U60Repr::new([Y, Y, Y, Y, Y, 0]) + }; assert(result == expected); let noshift = u60repr.shr(0); @@ -36,10 +40,14 @@ fn test_shl() { // 120 bits of 01010101 (repeating) let Y = 0x555555555555555555555555555555; let input: [Field; 6] = [Y, Y, Y, Y, Y, Y]; - let u60repr: U60Repr<3, 6> = U60Repr::new(input); + let u60repr: U60Repr<3, 6> = unsafe { + U60Repr::new(input) + }; let result = u60repr.shl(121); - let expected: U60Repr<3, 6> = U60Repr::new([0, X, X, X, X, X, X, 0, 0]); + let expected: U60Repr<3, 6> = unsafe { + U60Repr::new([0, X, X, X, X, X, X, 0, 0]) + }; assert(result == expected); let noshift = u60repr.shr(0); @@ -51,7 +59,9 @@ fn test_get_bit() { // 0x8000 = b1000000000000000 (16th bit is high) // 256th bit of input should be high let input: [Field; 6] = [0, 0, 0x8000, 0, 0, 0]; - let u60repr: U60Repr<3, 6> = U60Repr::new(input); + let u60repr: U60Repr<3, 6> = unsafe { + U60Repr::new(input) + }; for i in 0..720 { if i == 255 { assert(u60repr.get_bit(i) == true); @@ -62,7 +72,7 @@ fn test_get_bit() { } #[test] -fn test_gte() { +unconstrained fn test_gte() { let p = 0xffffffffffffffffffffffffffffff; // 2^120 - 1 let input: [Field; 6] = [p, p - 1, p - 2, p - 3, p - 4, p - 5]; let lhs: U60Repr<3, 6> = U60Repr::new(input); From 1bdce7449e608b1f11c22453cc4658604e37a31b Mon Sep 17 00:00:00 2001 From: Michael Connor Date: Thu, 3 Oct 2024 12:03:57 +0100 Subject: [PATCH 03/14] silence more warnings --- src/lib.nr | 20 ++++++++++---------- src/utils/mod.nr | 10 +++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/lib.nr b/src/lib.nr index 0a315506..e55bdbbb 100644 --- a/src/lib.nr +++ b/src/lib.nr @@ -1,17 +1,17 @@ -mod utils; -mod fields; +pub(crate) mod utils; +pub mod fields; // Structs -mod params; -mod bignum; -mod runtime_bignum; +pub mod params; +pub mod bignum; +pub mod runtime_bignum; // Functions on structs -mod unconstrained_ops; -mod constrained_ops; -mod unconstrained_helpers; -mod expressions; -mod serialization; +pub(crate) mod unconstrained_ops; +pub(crate) mod constrained_ops; +pub(crate) mod unconstrained_helpers; +pub(crate) mod expressions; +pub(crate) mod serialization; // Tests mod bignum_test; diff --git a/src/utils/mod.nr b/src/utils/mod.nr index 3d75400e..e419cfce 100644 --- a/src/utils/mod.nr +++ b/src/utils/mod.nr @@ -1,5 +1,5 @@ -mod u60_representation; -mod split_bits; -mod u60_representation_test; -mod msb; -mod map; +pub(crate) mod u60_representation; +pub(crate) mod split_bits; +pub(crate) mod u60_representation_test; +pub(crate) mod msb; +pub(crate) mod map; From 523f2e652a7bf8a97656b9430c005e25716e9d05 Mon Sep 17 00:00:00 2001 From: Michael Connor Date: Thu, 3 Oct 2024 15:45:54 +0100 Subject: [PATCH 04/14] rebase & silence warnings --- src/fields/mod.nr | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/fields/mod.nr b/src/fields/mod.nr index b2b8802c..5031c4a6 100644 --- a/src/fields/mod.nr +++ b/src/fields/mod.nr @@ -28,9 +28,12 @@ pub mod U2048; pub mod U4096; pub mod U8192; -use crate::bignum::BigNum; -use bn254Fq::BN254_Fq_Params; -// example typedef when using a defined bignum instance -type Fq = BigNum<3, BN254_Fq_Params>; + +// example typedef when using a defined bignum instance: +// +// use crate::bignum::BigNum; +// use bn254Fq::BN254_Fq_Params; +// +// type Fq = BigNum<3, BN254_Fq_Params>; From 1ff683c18a24205937b3318fd2d8540959e98345 Mon Sep 17 00:00:00 2001 From: Michael Connor Date: Thu, 3 Oct 2024 15:47:12 +0100 Subject: [PATCH 05/14] fmt --- src/fields/mod.nr | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/fields/mod.nr b/src/fields/mod.nr index 5031c4a6..14c73f80 100644 --- a/src/fields/mod.nr +++ b/src/fields/mod.nr @@ -28,8 +28,6 @@ pub mod U2048; pub mod U4096; pub mod U8192; - - // example typedef when using a defined bignum instance: // // use crate::bignum::BigNum; From a2240641d0db271a4f0cab0a75df3f66a6b44094 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 4 Oct 2024 10:18:31 +0100 Subject: [PATCH 06/14] Update src/runtime_bignum.nr --- src/runtime_bignum.nr | 1 - 1 file changed, 1 deletion(-) diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index 37280282..4cf9fa6e 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -18,7 +18,6 @@ pub struct RuntimeBigNum { params: BigNumParams, } -impl RuntimeBigNum {} pub(crate) trait RuntimeBigNumTrait { fn new(params: BigNumParams) -> Self; From d8f794e5af37ea595b11107962365bb4b0bbe837 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 4 Oct 2024 10:18:37 +0100 Subject: [PATCH 07/14] Update src/utils/map.nr --- src/utils/map.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/map.nr b/src/utils/map.nr index 50e3d13c..9d95e2d1 100644 --- a/src/utils/map.nr +++ b/src/utils/map.nr @@ -1,6 +1,6 @@ // Copied from std::array, because I couldn't figure out how to import the `map` method of the weird trait for an array. // And the reason I wanted direct access to it, is because I couldn't figure out how to implement a double map. -pub fn map(arr: [T; N], f: fn[Env](T) -> U) -> [U; N] { +pub(crate) fn map(arr: [T; N], f: fn[Env](T) -> U) -> [U; N] { let first_elem = f(arr[0]); let mut ret = [first_elem; N]; From 8d246671e96bf51de72a95450bcdf793e4cf5353 Mon Sep 17 00:00:00 2001 From: Michael Connor Date: Mon, 21 Oct 2024 11:51:15 +0100 Subject: [PATCH 08/14] reduce constraint counts --- src/params.nr | 30 +------ src/runtime_bignum.nr | 134 ++++++++++++++++++++++---------- src/utils/u60_representation.nr | 4 +- 3 files changed, 95 insertions(+), 73 deletions(-) diff --git a/src/params.nr b/src/params.nr index bde9c676..61c198b5 100644 --- a/src/params.nr +++ b/src/params.nr @@ -21,21 +21,13 @@ pub(crate) struct BigNumParams { redc_param: [Field; N], } -// To be implemented by the user, or within the prebuilt options in the `fields/` dir. +// To be implemented by the user for any BigNum they define, or within the predefined BigNums in the `fields/` dir. pub(crate) trait BigNumParamsGetter { fn get_params() -> BigNumParams; } -// To be implemented by the user, or within the prebuilt options in the `fields/` dir. -// pub(crate) trait HasGetModulusBits { -// fn get_modulus_bits() -> u32; // This needs to be a comptime const, so that it can be used as an argument to std::field::assert_constant() -// } - -// impl HasGetModulusBits for BigNumParams {} -// impl RuntimeBigNumParamsTrait for BigNumParams {} - impl BigNumParams { - fn new( + pub fn new( has_multiplicative_inverse: bool, modulus_bits_getter: fn() -> u32, modulus: [Field; N], @@ -65,21 +57,3 @@ fn get_double_modulus(modulus: [Field; N]) -> [Field; N] { result[N - 1] -= 1; result } - -// /** -// * @brief BigNumParamsGetter defines a "field" with which to parametrise BigNum. -// * @description The "field" does not need to be prime, any value *should* work (TODO: test!) -// **/ -// trait BigNumParamsGetter { -// fn has_multiplicative_inverse() -> bool; -// // @brief modulus_bits = log2(modulus) rounded up -// fn modulus_bits() -> u32; -// fn modulus() -> [Field; N]; -// fn modulus_u60() -> U60Repr; -// fn modulus_u60_x4() -> U60Repr; -// // @brief double_modulus: used when performing negations and subtractions -// fn double_modulus() -> [Field; N]; -// // redc_param used for __barrett_reduction. See https://en.wikipedia.org/wiki/Barrett_reduction -// redc_param: [Field; N], -// } - diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index 4cf9fa6e..0387dcee 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -18,11 +18,12 @@ pub struct RuntimeBigNum { params: BigNumParams, } - +// All functions prefixed `__` are unconstrained! +// They're not actually decorated as `unconstrained` because to return the `params` (as part of Self) from an `unconstrained` fn would cause range constraints. Instead, each `__` fn wraps a call to an unconstrained fn, so that the already-range-constrained `params` can be inserted into Self after the unconstrained call. pub(crate) trait RuntimeBigNumTrait { fn new(params: BigNumParams) -> Self; fn one(params: BigNumParams) -> Self; - unconstrained fn __derive_from_seed(params: BigNumParams, seed: [u8; SeedBytes]) -> Self; + fn __derive_from_seed(params: BigNumParams, seed: [u8; SeedBytes]) -> Self; fn from_slice(params: BigNumParams, limbs: [Field]) -> Self; fn from_array(params: BigNumParams, limbs: [Field; N]) -> Self; fn from_be_bytes(params: BigNumParams, x: [u8; NBytes]) -> Self; @@ -40,19 +41,19 @@ pub(crate) trait RuntimeBigNumTrait { unconstrained fn __eq(self, other: Self) -> bool; unconstrained fn __is_zero(self) -> bool; - unconstrained fn __neg(self) -> Self; - unconstrained fn __add(self, other: Self) -> Self; - unconstrained fn __sub(self, other: Self) -> Self; - unconstrained fn __mul(self, other: Self) -> Self; - unconstrained fn __div(self, other: Self) -> Self; - unconstrained fn __udiv_mod(self, divisor: Self) -> (Self, Self); - unconstrained fn __invmod(self) -> Self; - unconstrained fn __pow(self, exponent: Self) -> Self; + fn __neg(self) -> Self; + fn __add(self, other: Self) -> Self; + fn __sub(self, other: Self) -> Self; + fn __mul(self, other: Self) -> Self; + fn __div(self, other: Self) -> Self; + fn __udiv_mod(self, divisor: Self) -> (Self, Self); + fn __invmod(self) -> Self; + fn __pow(self, exponent: Self) -> Self; - unconstrained fn __batch_invert(x: [Self; M]) -> [Self; M]; + fn __batch_invert(x: [Self; M]) -> [Self; M]; unconstrained fn __batch_invert_slice(to_invert: [Self]) -> [Self]; - unconstrained fn __compute_quadratic_expression( + fn __compute_quadratic_expression( params: BigNumParams, lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS], lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], @@ -103,8 +104,12 @@ impl RuntimeBigNumTrait for RuntimeBigNum { result } - unconstrained fn __derive_from_seed(params: BigNumParams, seed: [u8; SeedBytes]) -> Self { - Self { limbs: __derive_from_seed(params, seed), params } + // UNCONSTRAINED! (Hence `__` prefix). + fn __derive_from_seed(params: BigNumParams, seed: [u8; SeedBytes]) -> Self { + let limbs = unsafe { + __derive_from_seed(params, seed) + }; + Self { limbs, params } } fn from_slice(params: BigNumParams, limbs: [Field]) -> Self { @@ -161,61 +166,102 @@ impl RuntimeBigNumTrait for RuntimeBigNum { __is_zero(self.limbs) } - unconstrained fn __neg(self) -> Self { + // UNCONSTRAINED! (Hence `__` prefix). + fn __neg(self) -> Self { let params = self.params; - Self::from_array(params, __neg(params, self.limbs)) + let limbs = unsafe { + __neg(params, self.limbs) + }; + Self { params, limbs } } - unconstrained fn __add(self, other: Self) -> Self { + // UNCONSTRAINED! (Hence `__` prefix). + fn __add(self, other: Self) -> Self { let params = self.params; - Self::from_array(params, __add(params, self.limbs, other.limbs)) + let limbs = unsafe { + __add(params, self.limbs, other.limbs) + }; + Self { params, limbs } } - unconstrained fn __sub(self, other: Self) -> Self { + // UNCONSTRAINED! (Hence `__` prefix). + fn __sub(self, other: Self) -> Self { let params = self.params; - Self::from_array(params, __sub(params, self.limbs, other.limbs)) + let limbs = unsafe { + __sub(params, self.limbs, other.limbs) + }; + Self { params, limbs } } - unconstrained fn __mul(self, other: Self) -> Self { + // UNCONSTRAINED! (Hence `__` prefix). + fn __mul(self, other: Self) -> Self { let params = self.params; - Self::from_array(params, __mul(params, self.limbs, other.limbs)) + let limbs = unsafe { + __mul(params, self.limbs, other.limbs) + }; + Self { params, limbs } } - unconstrained fn __div(self, divisor: Self) -> Self { + // UNCONSTRAINED! (Hence `__` prefix). + fn __div(self, divisor: Self) -> Self { let params = self.params; - Self::from_array(params, __div(params, self.limbs, divisor.limbs)) + let limbs = unsafe { + __div(params, self.limbs, divisor.limbs) + }; + Self { params, limbs } } - unconstrained fn __udiv_mod(self, divisor: Self) -> (Self, Self) { + // UNCONSTRAINED! (Hence `__` prefix). + fn __udiv_mod(self, divisor: Self) -> (Self, Self) { let params = self.params; - let (q, r) = __udiv_mod(self.limbs, divisor.limbs); + let (q, r) = unsafe { + __udiv_mod(self.limbs, divisor.limbs) + }; (Self { limbs: q, params }, Self { limbs: r, params }) } - unconstrained fn __invmod(self) -> Self { + // UNCONSTRAINED! (Hence `__` prefix). + fn __invmod(self) -> Self { let params = self.params; assert(params.has_multiplicative_inverse); - Self { limbs: __invmod(params, self.limbs), params } + let limbs = unsafe { + __invmod(params, self.limbs) + }; + Self { limbs, params } } - unconstrained fn __pow(self, exponent: Self) -> Self { + // UNCONSTRAINED! (Hence `__` prefix). + fn __pow(self, exponent: Self) -> Self { let params = self.params; - Self { limbs: __pow(params, self.limbs, exponent.limbs), params } + let limbs = unsafe { + __pow(params, self.limbs, exponent.limbs) + }; + Self { limbs, params } } - unconstrained fn __batch_invert(x: [Self; M]) -> [Self; M] { + // UNCONSTRAINED! (Hence `__` prefix). + fn __batch_invert(x: [Self; M]) -> [Self; M] { let params = x[0].params; assert(params.has_multiplicative_inverse); - __batch_invert(params, x.map(|bn| Self::get_limbs(bn))).map(|limbs| Self { limbs, params }) + let all_limbs = unsafe { + __batch_invert(params, x.map(|bn| Self::get_limbs(bn))) + }; + all_limbs.map(|limbs| Self { limbs, params }) } + // Note: can't return a slice from this unconstrained to a constrained function. unconstrained fn __batch_invert_slice(x: [Self]) -> [Self] { let params = x[0].params; assert(params.has_multiplicative_inverse); - __batch_invert_slice(params, x.map(|bn| Self::get_limbs(bn))).map(|limbs| Self { limbs, params }) + let all_limbs = unsafe { + let inv_slice = __batch_invert_slice(params, x.map(|bn| Self::get_limbs(bn))); + inv_slice.as_array() + }; + all_limbs.map(|limbs| Self { limbs, params }) } - unconstrained fn __compute_quadratic_expression( + // UNCONSTRAINED! (Hence `__` prefix). + fn __compute_quadratic_expression( params: BigNumParams, lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS], lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], @@ -224,15 +270,17 @@ impl RuntimeBigNumTrait for RuntimeBigNum { linear_terms: [Self; ADD_N], linear_flags: [bool; ADD_N] ) -> (Self, Self) { - let (q_limbs, r_limbs) = __compute_quadratic_expression( - params, - lhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), - lhs_flags, - rhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), - rhs_flags, - linear_terms.map(|bn| Self::get_limbs(bn)), - linear_flags - ); + let (q_limbs, r_limbs) = unsafe { + __compute_quadratic_expression( + params, + lhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + lhs_flags, + rhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + rhs_flags, + linear_terms.map(|bn| Self::get_limbs(bn)), + linear_flags + ) + }; (Self { limbs: q_limbs, params }, Self { limbs: r_limbs, params }) } diff --git a/src/utils/u60_representation.nr b/src/utils/u60_representation.nr index 21d3b896..61a29b54 100644 --- a/src/utils/u60_representation.nr +++ b/src/utils/u60_representation.nr @@ -78,7 +78,7 @@ impl std::cmp::Eq for U60Repr impl U60Repr { - unconstrained fn new(x: [Field; N * NumFieldSegments]) -> Self { + unconstrained pub fn new(x: [Field; N * NumFieldSegments]) -> Self { let mut result: Self = U60Repr { limbs: [0; N * NumSegments] }; for i in 0..(N * NumFieldSegments) { let (lo, hi) = split_bits::split_60_bits(x[i]); @@ -88,7 +88,7 @@ impl U60Repr { result } - unconstrained fn one() -> Self { + unconstrained pub fn one() -> Self { let mut result: Self = U60Repr { limbs: [0; N * NumSegments] }; result.limbs[0] = 1; result From 8bb7304844336f9cb1875fe460cadd568970326d Mon Sep 17 00:00:00 2001 From: Michael Connor Date: Mon, 21 Oct 2024 17:22:14 +0100 Subject: [PATCH 09/14] update in line w/ Zac's changes, incl macro tests --- src/bignum.nr | 20 +- src/bignum_test.nr | 93 +++-- src/constrained_ops.nr | 132 ++++++- src/expressions.nr | 14 +- src/fields/U1024.nr | 35 +- src/fields/U2048.nr | 36 +- src/fields/U256.nr | 35 +- src/fields/U384.nr | 35 +- src/fields/U4096.nr | 35 +- src/fields/U512.nr | 22 +- src/fields/U768.nr | 40 +- src/fields/U8192.nr | 35 +- src/fields/bls12_377Fq.nr | 39 +- src/fields/bls12_377Fr.nr | 36 +- src/fields/bls12_381Fq.nr | 35 +- src/fields/bls12_381Fr.nr | 35 +- src/fields/bn254Fq.nr | 36 +- src/fields/ed25519Fq.nr | 35 +- src/fields/ed25519Fr.nr | 35 +- src/fields/mnt4_753Fq.nr | 39 +- src/fields/mnt4_753Fr.nr | 37 +- src/fields/mnt6_753Fq.nr | 37 +- src/fields/mnt6_753Fr.nr | 37 +- src/fields/pallasFq.nr | 37 +- src/fields/pallasFr.nr | 37 +- src/fields/secp256k1Fq.nr | 35 +- src/fields/secp256k1Fr.nr | 35 +- src/fields/secp256r1Fq.nr | 35 +- src/fields/secp256r1Fr.nr | 35 +- src/fields/secp384r1Fq.nr | 35 +- src/fields/secp384r1Fr.nr | 35 +- src/fields/vestaFq.nr | 36 +- src/fields/vestaFr.nr | 35 +- src/runtime_bignum.nr | 22 +- src/runtime_bignum_test.nr | 692 ++++++++++++++++------------------- src/unconstrained_helpers.nr | 188 +++++++++- src/unconstrained_ops.nr | 47 ++- src/utils/map.nr | 5 +- 38 files changed, 1260 insertions(+), 982 deletions(-) diff --git a/src/bignum.nr b/src/bignum.nr index 7b2108b9..b5a0fdbe 100644 --- a/src/bignum.nr +++ b/src/bignum.nr @@ -2,7 +2,7 @@ use crate::utils::map::map; use crate::params::BigNumParamsGetter; use crate::constrained_ops::{ - conditional_select, assert_is_not_equal, eq, validate_in_field, validate_in_range, neg, add, sub, + derive_from_seed, conditional_select, assert_is_not_equal, eq, validate_in_field, validate_in_range, neg, add, sub, mul, div, udiv_mod, udiv, umod }; use crate::unconstrained_ops::{ @@ -21,6 +21,7 @@ pub(crate) trait BigNumTrait { // fn default() -> Self { std::default::Default::default () } fn new() -> Self; fn one() -> Self; + fn derive_from_seed(seed: [u8; SeedBytes]) -> Self; unconstrained fn __derive_from_seed(seed: [u8; SeedBytes]) -> Self; fn from_slice(limbs: [Field]) -> Self; fn from_array(limbs: [Field; N]) -> Self; @@ -97,6 +98,11 @@ impl BigNumTrait for BigNum where Params: BigN result } + fn derive_from_seed(seed: [u8; SeedBytes]) -> Self { + let params = Params::get_params(); + Self { limbs: derive_from_seed(params, seed) } + } + unconstrained fn __derive_from_seed(seed: [u8; SeedBytes]) -> Self { let params = Params::get_params(); Self { limbs: __derive_from_seed(params, seed) } @@ -221,11 +227,11 @@ impl BigNumTrait for BigNum where Params: BigN let params = Params::get_params(); let (q_limbs, r_limbs) = __compute_quadratic_expression( params, - lhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + map(lhs_terms, |bns| map(bns, |bn| Self::get_limbs(bn))), lhs_flags, - rhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + map(rhs_terms, |bns| map(bns, |bn| Self::get_limbs(bn))), rhs_flags, - linear_terms.map(|bn| Self::get_limbs(bn)), + map(linear_terms, |bn| Self::get_limbs(bn)), linear_flags ); (Self { limbs: q_limbs }, Self { limbs: r_limbs }) @@ -242,11 +248,11 @@ impl BigNumTrait for BigNum where Params: BigN let params = Params::get_params(); evaluate_quadratic_expression( params, - lhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + map(lhs_terms, |bns| map(bns, |bn| Self::get_limbs(bn))), lhs_flags, - rhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + map(rhs_terms, |bns| map(bns, |bn| Self::get_limbs(bn))), rhs_flags, - linear_terms.map(|bn| Self::get_limbs(bn)), + map(linear_terms, |bn| Self::get_limbs(bn)), linear_flags ) } diff --git a/src/bignum_test.nr b/src/bignum_test.nr index 1fbb9966..15243613 100644 --- a/src/bignum_test.nr +++ b/src/bignum_test.nr @@ -8,6 +8,7 @@ use crate::params::BigNumParamsGetter; use crate::fields::bn254Fq::BN254_Fq_Params; use crate::fields::U256::U256Params; +use crate::fields::bls12_381Fq::BLS12_381_Fq_Params; struct Test2048Params{} @@ -17,62 +18,56 @@ fn silence_warning() { let _ = Test2048Params {}; } +global TEST_2048_PARAMS: BigNumParams<18> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 2048, + modulus: [ + 0xc0a197a5ae0fcdceb052c9732614fe, 0x656ae034423283422243918ab83be3, 0x6bf590da48a7c1070b7d5aabaac678, 0x0cce39f530238b606f24b296e2bda9, 0x01e1fef9bb9c1c3ead98f226f1bfa0, 0xad8c1c816e12e0ed1379055e373abf, 0xcebe80e474f753aa9d1461c435123d, 0xaee5a18ceedef88d115a8b93c167ad, 0x268ba83c4a65c4307427fc495d9e44, 0xdd2777926848667b7df79f342639d4, 0xf455074c96855ca0068668efe7da3d, 0x5ddba6b30bbc168bfb3a1225f27d65, 0x591fec484f36707524133bcd6f4258, 0x59641b756766aeebe66781dd01d062, 0x58bc5eaff4b165e142bf9e2480eebb, 0x667a3964f08e06df772ce64b229a72, 0x9c1fdb18907711bfe3e3c1cf918395, 0xb8 + ], + double_modulus: [ + 0x0181432f4b5c1f9b9d60a592e64c29fc, 0x01cad5c06884650684448723157077c6, 0x01d7eb21b4914f820e16fab557558cef, 0x01199c73ea604716c0de49652dc57b51, 0x0103c3fdf37738387d5b31e44de37f3f, 0x015b183902dc25c1da26f20abc6e757d, 0x019d7d01c8e9eea7553a28c3886a247a, 0x015dcb4319ddbdf11a22b5172782cf5a, 0x014d17507894cb8860e84ff892bb3c88, 0x01ba4eef24d090ccf6fbef3e684c73a7, 0x01e8aa0e992d0ab9400d0cd1dfcfb47a, 0x01bbb74d6617782d17f674244be4faca, 0x01b23fd8909e6ce0ea4826779ade84af, 0x01b2c836eacecd5dd7cccf03ba03a0c3, 0x01b178bd5fe962cbc2857f3c4901dd75, 0x01ccf472c9e11c0dbeee59cc964534e3, 0x01383fb63120ee237fc7c7839f230729, 0x0170 + ], + modulus_u60: U60Repr { limbs: [ + 0x0eb052c9732614fe, 0x0c0a197a5ae0fcdc, 0x022243918ab83be3, 0x0656ae0344232834, 0x070b7d5aabaac678, 0x06bf590da48a7c10, 0x6f24b296e2bda9, 0xcce39f530238b6, 0x0ead98f226f1bfa0, 0x1e1fef9bb9c1c3, 0x0d1379055e373abf, 0x0ad8c1c816e12e0e, 0x0a9d1461c435123d, 0x0cebe80e474f753a, 0x0d115a8b93c167ad, 0x0aee5a18ceedef88, 0x7427fc495d9e44, 0x0268ba83c4a65c43, 0x0b7df79f342639d4, 0x0dd2777926848667, 0x068668efe7da3d, 0x0f455074c96855ca, 0x0bfb3a1225f27d65, 0x05ddba6b30bbc168, 0x0524133bcd6f4258, 0x0591fec484f36707, 0x0be66781dd01d062, 0x059641b756766aee, 0x0142bf9e2480eebb, 0x058bc5eaff4b165e, 0x0f772ce64b229a72, 0x0667a3964f08e06d, 0x0fe3e3c1cf918395, 0x09c1fdb18907711b, 0xb8, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0eb052c9732614fe, 0x0c0a197a5ae0fcdc, 0x022243918ab83be3, 0x0656ae0344232834, 0x070b7d5aabaac678, 0x06bf590da48a7c10, 0x6f24b296e2bda9, 0xcce39f530238b6, 0x0ead98f226f1bfa0, 0x1e1fef9bb9c1c3, 0x0d1379055e373abf, 0x0ad8c1c816e12e0e, 0x0a9d1461c435123d, 0x0cebe80e474f753a, 0x0d115a8b93c167ad, 0x0aee5a18ceedef88, 0x7427fc495d9e44, 0x0268ba83c4a65c43, 0x0b7df79f342639d4, 0x0dd2777926848667, 0x068668efe7da3d, 0x0f455074c96855ca, 0x0bfb3a1225f27d65, 0x05ddba6b30bbc168, 0x0524133bcd6f4258, 0x0591fec484f36707, 0x0be66781dd01d062, 0x059641b756766aee, 0x0142bf9e2480eebb, 0x058bc5eaff4b165e, 0x0f772ce64b229a72, 0x0667a3964f08e06d, 0x0fe3e3c1cf918395, 0x09c1fdb18907711b, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x1697def7100cd5cf8d890b4ef2ec3f, 0x765ba8304214dac764d3f4adc31859, 0x8404bd14d927ea230e60d4bebf9406, 0xc4d53a23bacc251ecbfc4b7ba5a0b4, 0x3eaf3499474a6f5b2fff83f1259c87, 0xbff4c737b97281f1a5f2384a8c16d9, 0x1b4cf2f55358476b53237829990555, 0xe7a804e8eacfe3a2a5673bc3885b86, 0xabadeae4282906c817adf70eab4ae1, 0x66f7df257fe2bf27f0809aceed9b0e, 0xd90fb7428901b8bed11f6b81e36bf1, 0x36e6ba885c60b7024c563605df7e07, 0x2b7c58d2fb5d2c8478963ae6d4a44f, 0x6ee761de26635f114ccc3f7d74f855, 0x3fb726a10cf2220897513f05243de3, 0x43a26bbd732496eb4d828591b8056e, 0xf4e42304e60fb3a54fca735499f2cf, 0x162f + ] +}; + impl BigNumParamsGetter<18> for Test2048Params { fn get_params() -> BigNumParams<18> { - let has_multiplicative_inverse = false; - let modulus_bits_getter = || 2048; - // let modulus_bits = 2048; - let modulus: [Field; 18] = [ - 0x0000000000000000000000000000000000c0a197a5ae0fcdceb052c9732614fe, - 0x0000000000000000000000000000000000656ae034423283422243918ab83be3, - 0x00000000000000000000000000000000006bf590da48a7c1070b7d5aabaac678, - 0x00000000000000000000000000000000000cce39f530238b606f24b296e2bda9, - 0x000000000000000000000000000000000001e1fef9bb9c1c3ead98f226f1bfa0, - 0x0000000000000000000000000000000000ad8c1c816e12e0ed1379055e373abf, - 0x0000000000000000000000000000000000cebe80e474f753aa9d1461c435123d, - 0x0000000000000000000000000000000000aee5a18ceedef88d115a8b93c167ad, - 0x0000000000000000000000000000000000268ba83c4a65c4307427fc495d9e44, - 0x0000000000000000000000000000000000dd2777926848667b7df79f342639d4, - 0x0000000000000000000000000000000000f455074c96855ca0068668efe7da3d, - 0x00000000000000000000000000000000005ddba6b30bbc168bfb3a1225f27d65, - 0x0000000000000000000000000000000000591fec484f36707524133bcd6f4258, - 0x000000000000000000000000000000000059641b756766aeebe66781dd01d062, - 0x000000000000000000000000000000000058bc5eaff4b165e142bf9e2480eebb, - 0x0000000000000000000000000000000000667a3964f08e06df772ce64b229a72, - 0x00000000000000000000000000000000009c1fdb18907711bfe3e3c1cf918395, - 0x00000000000000000000000000000000000000000000000000000000000000b8 - ]; - let redc_param: [Field; 18] = [ - 0x000000000000000000000000000000000091697def7100cd5cf8d890b4ef2ec3, - 0x00000000000000000000000000000000006765ba8304214dac764d3f4adc3185, - 0x000000000000000000000000000000000048404bd14d927ea230e60d4bebf940, - 0x00000000000000000000000000000000007c4d53a23bacc251ecbfc4b7ba5a0b, - 0x000000000000000000000000000000000093eaf3499474a6f5b2fff83f1259c8, - 0x00000000000000000000000000000000005bff4c737b97281f1a5f2384a8c16d, - 0x000000000000000000000000000000000061b4cf2f55358476b5323782999055, - 0x00000000000000000000000000000000001e7a804e8eacfe3a2a5673bc3885b8, - 0x0000000000000000000000000000000000eabadeae4282906c817adf70eab4ae, - 0x0000000000000000000000000000000000166f7df257fe2bf27f0809aceed9b0, - 0x00000000000000000000000000000000007d90fb7428901b8bed11f6b81e36bf, - 0x0000000000000000000000000000000000f36e6ba885c60b7024c563605df7e0, - 0x000000000000000000000000000000000052b7c58d2fb5d2c8478963ae6d4a44, - 0x000000000000000000000000000000000036ee761de26635f114ccc3f7d74f85, - 0x0000000000000000000000000000000000e3fb726a10cf2220897513f05243de, - 0x0000000000000000000000000000000000f43a26bbd732496eb4d828591b8056, - 0x0000000000000000000000000000000000ff4e42304e60fb3a54fca735499f2c, - 0x0000000000000000000000000000000000000000000000000000000000000162 - ]; - BigNumParams::new( - has_multiplicative_inverse, - modulus_bits_getter, - modulus, - redc_param - ) + TEST_2048_PARAMS } } type Fq = BigNum<3, BN254_Fq_Params>; +/** + * @brief this example was failing - sanity test to validate it now works + **/ +#[test] +fn test_bls_reduction() { + let X1: BigNum<4, BLS12_381_Fq_Params> = BigNum { + limbs: [ + 0x55e83ff97a1aeffb3af00adb22c6bb, 0x8c4f9774b905a14e3a3f171bac586c, 0xa73197d7942695638c4fa9ac0fc368, 0x17f1d3 + ] + }; + X1.validate_in_field(); + let mut (_, XX_mul_3): (BigNum<4, BLS12_381_Fq_Params>, BigNum<4, BLS12_381_Fq_Params> ) = unsafe { + BigNum::__compute_quadratic_expression( + [[X1, X1, X1]], + [[false, false, false]], + [[X1]], + [[false]], + [], + [] + ) + }; + XX_mul_3.validate_in_field(); +} + fn test_eq() where BN: BigNumTrait { let a = unsafe { BN::__derive_from_seed([1, 2, 3, 4]) diff --git a/src/constrained_ops.nr b/src/constrained_ops.nr index 3021eb49..d2580413 100644 --- a/src/constrained_ops.nr +++ b/src/constrained_ops.nr @@ -7,6 +7,135 @@ use crate::unconstrained_helpers::{ use crate::unconstrained_ops::{__mul, __div, __udiv_mod}; use crate::expressions::evaluate_quadratic_expression; +/** + * In this file: + * + * conditional_select + * assert_is_not_equal + * eq + * validate_in_field + * validate_in_range + * validate_quotient_in_range + * validate_gt + * neg + * add + * sub + * mul + * div + * udiv_mod + * udiv + * umod + */ + +/** +* @brief given an input seed, generate a pseudorandom BigNum value +* @details we hash the input seed into `modulus_bits * 2` bits of entropy, +* which is then reduced into a BigNum value +* We use a hash function that can be modelled as a random oracle +* This function *should* produce an output that is a uniformly randomly distributed value modulo BigNum::modulus() +**/ +pub(crate) fn derive_from_seed(params: P, seed: [u8; SeedBytes]) -> [Field; N] { + let mut rolling_seed: [u8; SeedBytes + 1] = [0; SeedBytes + 1]; + for i in 0..SeedBytes { + rolling_seed[i] = seed[i]; + assert_eq(rolling_seed[i], seed[i]); + } + + let mut hash_buffer: [u8; N * 2 * 15] = [0; N * 2 * 15]; + + let mut rolling_hash_fields: [Field; (SeedBytes / 31) + 1] = [0; (SeedBytes / 31) + 1]; + let mut seed_ptr = 0; + for i in 0..(SeedBytes / 31) + 1 { + let mut packed: Field = 0; + for _ in 0..31 { + if (seed_ptr < SeedBytes) { + packed *= 256; + packed += seed[seed_ptr] as Field; + seed_ptr += 1; + } + } + rolling_hash_fields[i] = packed; + } + + let compressed = std::hash::poseidon2::Poseidon2::hash(rolling_hash_fields, (SeedBytes / 31) + 1); + let mut rolling_hash: [Field; 2] = [compressed, 0]; + let num_hashes = (30 * N) / 32 + (((30 * N) % 32) != 0) as u32; + for i in 0..num_hashes - 1 { + let hash: Field = std::hash::poseidon2::Poseidon2::hash(rolling_hash, 2); + let hash: [u8; 32] = hash.to_le_bytes(); + for j in 0..30 { + hash_buffer[i * 30 + j] = hash[j]; + } + rolling_hash[1] += 1; + } + { + let hash: Field = std::hash::poseidon2::Poseidon2::hash(rolling_hash, 2); + let hash: [u8; 32] = hash.to_le_bytes(); + let remaining_bytes = 30 * N - (num_hashes - 1) * 30; + for j in 0..remaining_bytes { + hash_buffer[(num_hashes - 1) * 30 + j] = hash[j]; + } + } + + let modulus_bits_getter = params.modulus_bits_getter; + let modulus_bits = modulus_bits_getter(); + let num_bits = modulus_bits * 2; + let num_bytes = num_bits / 8 + ((num_bits % 8) != 0) as u32; + + let bits_in_last_byte = num_bits as u8 % 8; + let last_byte_mask = (1 as u8 << bits_in_last_byte) - 1; + hash_buffer[num_bytes - 1] = hash_buffer[num_bytes - 1] & last_byte_mask; + + let num_bigfield_chunks = (2 * N) / (N - 1) + (((2 * N) % (N - 1)) != 0) as u32; + let mut byte_ptr = 0; + + // we want to convert our byte array into bigfield chunks + // each chunk has at most N-1 limbs + // to determine the exact number of chunks, we need the `!=` or `>` operator which is not avaiable when defining array sizes + // so we overestimate at 4 + // e.g. if N = 20, then we have 40 limbs we want to reduce, but each bigfield chunk is 19 limbs, so we need 3 + // if N = 2, we have 4 limbs we want to reduce but each bigfield chunk is only 1 limb, so we need 4 + // max possible number of chunks is therefore 4 + + let mut bigfield_chunks: [[Field; N]; 4] = [[0; N]; 4]; + for k in 0..num_bigfield_chunks { + let mut bigfield_limbs: [Field; N] = [0; N]; + let mut num_filled_bytes = (k * 30); + let mut num_remaining_bytes = num_bytes - num_filled_bytes; + let mut num_remaining_limbs = (num_remaining_bytes / 15) + (num_remaining_bytes % 15 > 0) as u32; + let mut more_than_N_minus_one_limbs = (num_remaining_limbs > (N - 1)) as u32; + let mut num_limbs_in_bigfield = more_than_N_minus_one_limbs * (N - 1) + + num_remaining_limbs * (1 - more_than_N_minus_one_limbs); + + for j in 0..num_limbs_in_bigfield { + let mut limb: Field = 0; + for _ in 0..15 { + let need_more_bytes = (byte_ptr < num_bytes); + let mut byte = hash_buffer[byte_ptr]; + limb *= (256 * need_more_bytes as Field + (1 - need_more_bytes as Field)); + limb += byte as Field * need_more_bytes as Field; + byte_ptr += need_more_bytes as u32; + } + bigfield_limbs[num_limbs_in_bigfield - 1 - j] = limb; + } + bigfield_chunks[num_bigfield_chunks - 1 - k] = bigfield_limbs; + } + + let mut bigfield_rhs_limbs: [Field; N] = [0; N]; + bigfield_rhs_limbs[N-1] = 1; + validate_in_range(params, bigfield_rhs_limbs); + + let mut result: [Field; N] = [0; N]; + + for i in 0..num_bigfield_chunks { + let bigfield_lhs_limbs = bigfield_chunks[i]; + + result = mul(params, result, bigfield_rhs_limbs); + result = add(params, result, bigfield_lhs_limbs); + } + result +} + /** * @brief conditional_select given the value of `predicate` return either `self` (if 0) or `other` (if 1) * @description should be cheaper than using an IF statement (TODO: check!) @@ -93,7 +222,8 @@ pub(crate) fn validate_in_range(params: P, limbs: [Field; N]) { limbs[i].assert_max_bit_size(120); } let modulus_bits_getter = params.modulus_bits_getter; - let final_limb_bits = modulus_bits_getter() - ((N - 1) * 120); + let modulus_bits = modulus_bits_getter(); + let final_limb_bits = modulus_bits - ((N - 1) * 120); limbs[N - 1].assert_max_bit_size(final_limb_bits as u32); } diff --git a/src/expressions.nr b/src/expressions.nr index a2ef3e03..e2821113 100644 --- a/src/expressions.nr +++ b/src/expressions.nr @@ -4,6 +4,16 @@ use crate::params::BigNumParams as P; use crate::constrained_ops::validate_quotient_in_range; use crate::unconstrained_helpers::__barrett_reduction; +/** + * In this file: + * + * __compute_quadratic_expression_with_borrow_flags + * __add_linear_expression + * __compute_quadratic_expression_product + * __compute_quadratic_expression + * evaluate_quadratic_expression + */ + /** * @brief Given a degree-2 BigNum expression that is equal to 0 mod p, compute the quotient and borrow flags * @description The expression is of the form: @@ -127,7 +137,7 @@ unconstrained fn __add_linear_expression( if (flags[i]) { for j in 0..N { sum[j] = sum[j] + modulus2[j] - x[i][j]; - assert(x[i][j].lt(modulus2[j])); + // assert(x[i][j].lt(modulus2[j])); } } else { for j in 0..N { @@ -214,6 +224,8 @@ unconstrained pub(crate) fn __compute_quadratic_expression< ); let mut relation_result: [Field; 2 * N] = split_bits::__normalize_limbs(mulout, 2 * N); + // size 4 + // a[3] * b[3] = a[6] = 7 // TODO: ugly! Will fail if input slice is empty let modulus_bits_getter = params.modulus_bits_getter; let k = modulus_bits_getter(); diff --git a/src/fields/U1024.nr b/src/fields/U1024.nr index 6dc7ffcc..c5aef12d 100644 --- a/src/fields/U1024.nr +++ b/src/fields/U1024.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global U1024_PARAMS: BigNumParams<9> = BigNumParams { - has_multiplicative_inverse: false, - modulus_bits_getter: || 1025, - modulus: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000000000000000 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffffffffffffff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x040000000000000000 - ] -}; - pub struct U1024Params {} impl BigNumParamsGetter<9> for U1024Params { @@ -28,3 +10,20 @@ impl BigNumParamsGetter<9> for U1024Params { } } +global U1024_PARAMS: BigNumParams<9> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 1025, + modulus: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000000000000000 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffffffffffffff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x400000000000000000 + ] +}; diff --git a/src/fields/U2048.nr b/src/fields/U2048.nr index 99fc3bdf..2fac1524 100644 --- a/src/fields/U2048.nr +++ b/src/fields/U2048.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global U2048_PARAMS: BigNumParams<18> = BigNumParams { - has_multiplicative_inverse: false, - modulus_bits_getter: || 2049, - modulus: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0400 - ] -}; - pub struct U2048Params {} impl BigNumParamsGetter<18> for U2048Params { @@ -28,3 +10,21 @@ impl BigNumParamsGetter<18> for U2048Params { } } +global U2048_PARAMS: BigNumParams<18> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 2049, + modulus: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4000 + ] +}; + diff --git a/src/fields/U256.nr b/src/fields/U256.nr index 19b40cad..65f71be3 100644 --- a/src/fields/U256.nr +++ b/src/fields/U256.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global U256_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: false, - modulus_bits_getter: || 257, - modulus: [ - 0x00, 0x00, 0x010000 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0x01ffff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x040000 - ] -}; - pub struct U256Params {} impl BigNumParamsGetter<3> for U256Params { @@ -28,3 +10,20 @@ impl BigNumParamsGetter<3> for U256Params { } } +global U256_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 257, + modulus: [ + 0x00, 0x00, 0x010000 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0x01ffff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x400000 + ] +}; diff --git a/src/fields/U384.nr b/src/fields/U384.nr index dba9054e..c076695c 100644 --- a/src/fields/U384.nr +++ b/src/fields/U384.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global U384_PARAMS: BigNumParams<4> = BigNumParams { - has_multiplicative_inverse: false, - modulus_bits_getter: || 385, - modulus: [ - 0x00, 0x00, 0x00, 0x01000000 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x00, 0x04000000 - ] -}; - pub struct U384_Params {} impl BigNumParamsGetter<4> for U384_Params { @@ -28,3 +10,20 @@ impl BigNumParamsGetter<4> for U384_Params { } } +global U384_PARAMS: BigNumParams<4> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 385, + modulus: [ + 0x00, 0x00, 0x00, 0x01000000 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x00, 0x40000000 + ] +}; diff --git a/src/fields/U4096.nr b/src/fields/U4096.nr index 441c28e0..06335a1d 100644 --- a/src/fields/U4096.nr +++ b/src/fields/U4096.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global U4096_PARAMS: BigNumParams<35> = BigNumParams { - has_multiplicative_inverse: false, - modulus_bits_getter: || 4097, - modulus: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x040000 - ] -}; - pub struct U4096Params {} impl BigNumParamsGetter<35> for U4096Params { @@ -28,3 +10,20 @@ impl BigNumParamsGetter<35> for U4096Params { } } +global U4096_PARAMS: BigNumParams<35> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 4097, + modulus: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x010000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x400000 + ] +}; diff --git a/src/fields/U512.nr b/src/fields/U512.nr index 66c3f30d..2b91b00b 100644 --- a/src/fields/U512.nr +++ b/src/fields/U512.nr @@ -2,9 +2,17 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; +pub struct U512Params {} + +impl BigNumParamsGetter<5> for U512Params { + fn get_params() -> BigNumParams<5> { + U512_PARAMS + } +} + global U512_PARAMS: BigNumParams<5> = BigNumParams { - has_multiplicative_inverse: false, - modulus_bits_getter: || 513, + has_multiplicative_inverse: false, + modulus_bits_getter: || 513, modulus: [ 0x00, 0x00, 0x00, 0x00, 0x0100000000 ], @@ -16,15 +24,7 @@ global U512_PARAMS: BigNumParams<5> = BigNumParams { modulus_u60_x4: U60Repr { limbs: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, redc_param: [ - 0x00, 0x00, 0x00, 0x00, 0x0400000000 + 0x00, 0x00, 0x00, 0x00, 0x4000000000 ] }; -pub struct U512Params {} - -impl BigNumParamsGetter<5> for U512Params { - fn get_params() -> BigNumParams<5> { - U512_PARAMS - } -} - diff --git a/src/fields/U768.nr b/src/fields/U768.nr index cf41ce21..087af311 100644 --- a/src/fields/U768.nr +++ b/src/fields/U768.nr @@ -2,29 +2,29 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global U768_PARAMS: BigNumParams<13> = BigNumParams { - has_multiplicative_inverse: false, - modulus_bits_getter: || 1537, - modulus: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000000000000000000000 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffffffffffffffffffffff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1000000000]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1000000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04000000000000000000000000 - ] -}; - pub struct U768Params {} -impl BigNumParamsGetter<13> for U768Params { - fn get_params() -> BigNumParams<13> { +impl BigNumParamsGetter<7> for U768Params { + fn get_params() -> BigNumParams<7> { U768_PARAMS } } +global U768_PARAMS: BigNumParams<7> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 769, + modulus: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000000000 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffffffffff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000000000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01000000000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40000000000000 + ] +}; + diff --git a/src/fields/U8192.nr b/src/fields/U8192.nr index d4788d3a..91702ec3 100644 --- a/src/fields/U8192.nr +++ b/src/fields/U8192.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global U8192_PARAMS: BigNumParams<69> = BigNumParams { - has_multiplicative_inverse: false, - modulus_bits_getter: || 8193, - modulus: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100000000 - ], - double_modulus: [ - 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffffff - ], - modulus_u60: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100000000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0400000000 - ] -}; - pub struct U8192Params {} impl BigNumParamsGetter<69> for U8192Params { @@ -28,3 +10,20 @@ impl BigNumParamsGetter<69> for U8192Params { } } +global U8192_PARAMS: BigNumParams<69> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 8193, + modulus: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100000000 + ], + double_modulus: [ + 0x01000000000000000000000000000000, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x01ffffffff + ], + modulus_u60: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100000000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0100000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4000000000 + ] +}; diff --git a/src/fields/bls12_377Fq.nr b/src/fields/bls12_377Fq.nr index 5cf050aa..4fb833ef 100644 --- a/src/fields/bls12_377Fq.nr +++ b/src/fields/bls12_377Fq.nr @@ -1,5 +1,5 @@ //! Blurb sourced from https://github.com/arkworks-rs -//! This library implements the base field of the BLS12_377 curve generated in [[BCGMMW20, "Zexe"]](https://eprint.iacr.org/2018/962). +//! This library implements the base field of the BLS12_377 curve generated in [[BCGMMW20, "Zexe"]]((https://eprint.iacr.org/2018/962). //! The name denotes that it is a Barreto--Lynn--Scott curve of embedding degree //! 12, defined over a 377-bit (prime) field. The main feature of this curve is //! that both the scalar field and the base field are highly 2-adic. @@ -20,25 +20,7 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global BLS12_377_Fq_PARAMS: BigNumParams<4> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 377, - modulus: [ - 0x0b5d44300000008508c00000000001, 0xd9f300f5138f1ef3622fba09480017, 0x4617c510eac63b05c06ca1493b1a22, 0x01ae3a - ], - double_modulus: [ - 0x0116ba88600000010a11800000000002, 0x01b3e601ea271e3de6c45f741290002d, 0x018c2f8a21d58c760b80d94292763444, 0x035c73 - ], - modulus_u60: U60Repr { limbs: [ - 0x0508c00000000001, 0xb5d44300000008, 0x03622fba09480017, 0x0d9f300f5138f1ef, 0x05c06ca1493b1a22, 0x04617c510eac63b0, 0x01ae3a, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0508c00000000001, 0xb5d44300000008, 0x03622fba09480017, 0x0d9f300f5138f1ef, 0x05c06ca1493b1a22, 0x04617c510eac63b0, 0x01ae3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xed687789c42a591f9fd58c5e4daffc, 0xd0de6776b1a06af2d488d85a6d02d0, 0x8d0cc4060e976c3ca0582ef4f73bba, 0x026150 - ] -}; - -pub struct BLS12_377_Fq_Params {} +pub struct BLS12_377_Fq_Params {} impl BigNumParamsGetter<4> for BLS12_377_Fq_Params { fn get_params() -> BigNumParams<4> { @@ -46,3 +28,20 @@ impl BigNumParamsGetter<4> for BLS12_377_Fq_Params { } } +pub global BLS12_377_Fq_PARAMS: BigNumParams<4> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 377, + modulus: [ + 0x0b5d44300000008508c00000000001, 0xd9f300f5138f1ef3622fba09480017, 0x4617c510eac63b05c06ca1493b1a22, 0x01ae3a + ], + double_modulus: [ + 0x0116ba88600000010a11800000000002, 0x01b3e601ea271e3de6c45f741290002d, 0x018c2f8a21d58c760b80d94292763444, 0x035c73 + ], + modulus_u60: U60Repr { limbs: [ + 0x0508c00000000001, 0xb5d44300000008, 0x03622fba09480017, 0x0d9f300f5138f1ef, 0x05c06ca1493b1a22, 0x04617c510eac63b0, 0x01ae3a, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0508c00000000001, 0xb5d44300000008, 0x03622fba09480017, 0x0d9f300f5138f1ef, 0x05c06ca1493b1a22, 0x04617c510eac63b0, 0x01ae3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0xd687789c42a591f9fd58c5e4daffcc, 0x0de6776b1a06af2d488d85a6d02d0e, 0xd0cc4060e976c3ca0582ef4f73bbad, 0x261508 + ] +}; diff --git a/src/fields/bls12_377Fr.nr b/src/fields/bls12_377Fr.nr index 6b9789f5..ac6bfd01 100644 --- a/src/fields/bls12_377Fr.nr +++ b/src/fields/bls12_377Fr.nr @@ -16,28 +16,11 @@ //! * G1 curve equation: y^2 = x^3 + 1 //! * G2 curve equation: y^2 = x^3 + B, where //! * B = Fq2(0, 155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906) + use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global BLS12_377_Fr_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 253, - modulus: [ - 0xaa76fed00000010a11800000000001, 0x655e9a2ca55660b44d1e5c37b00159, 0x12ab - ], - double_modulus: [ - 0x0154edfda00000021423000000000002, 0x01cabd34594aacc1689a3cb86f6002b2, 0x2555 - ], - modulus_u60: U60Repr { limbs: [ - 0x0a11800000000001, 0x0aa76fed00000010, 0x044d1e5c37b00159, 0x0655e9a2ca55660b, 0x12ab, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0a11800000000001, 0x0aa76fed00000010, 0x044d1e5c37b00159, 0x0655e9a2ca55660b, 0x12ab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x0a180b8d69e258f5204c21151e79ea, 0x491ec40b2c9ee4e51e49faa80548fd, 0x36d9 - ] -}; - pub struct BLS12_377_Fr_Params {} impl BigNumParamsGetter<3> for BLS12_377_Fr_Params { @@ -46,3 +29,20 @@ impl BigNumParamsGetter<3> for BLS12_377_Fr_Params { } } +global BLS12_377_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 253, + modulus: [ + 0xaa76fed00000010a11800000000001, 0x655e9a2ca55660b44d1e5c37b00159, 0x12ab + ], + double_modulus: [ + 0x0154edfda00000021423000000000002, 0x01cabd34594aacc1689a3cb86f6002b2, 0x2555 + ], + modulus_u60: U60Repr { limbs: [ + 0x0a11800000000001, 0x0aa76fed00000010, 0x044d1e5c37b00159, 0x0655e9a2ca55660b, 0x12ab, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0a11800000000001, 0x0aa76fed00000010, 0x044d1e5c37b00159, 0x0655e9a2ca55660b, 0x12ab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0xa180b8d69e258f5204c21151e79ea1, 0x91ec40b2c9ee4e51e49faa80548fd0, 0x036d94 + ] +}; diff --git a/src/fields/bls12_381Fq.nr b/src/fields/bls12_381Fq.nr index 93e1ccab..f4c0ef5a 100644 --- a/src/fields/bls12_381Fq.nr +++ b/src/fields/bls12_381Fq.nr @@ -18,24 +18,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global BLS12_381_Fq_PARAMS: BigNumParams<4> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 381, - modulus: [ - 0xabfffeb153ffffb9feffffffffaaab, 0x4b84f38512bf6730d2a0f6b0f6241e, 0xea397fe69a4b1ba7b6434bacd76477, 0x1a0111 - ], - double_modulus: [ - 0x0157fffd62a7ffff73fdffffffff5556, 0x019709e70a257ece61a541ed61ec483c, 0x01d472ffcd3496374f6c869759aec8ed, 0x340222 - ], - modulus_u60: U60Repr { limbs: [ - 0x09feffffffffaaab, 0x0abfffeb153ffffb, 0xd2a0f6b0f6241e, 0x04b84f38512bf673, 0x07b6434bacd76477, 0x0ea397fe69a4b1ba, 0x1a0111, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x09feffffffffaaab, 0x0abfffeb153ffffb, 0xd2a0f6b0f6241e, 0x04b84f38512bf673, 0x07b6434bacd76477, 0x0ea397fe69a4b1ba, 0x1a0111, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x65c59e8163c701ec4f881fd59646e8, 0x09d07fda82a52f7d1dc780a19de74e, 0x4bcf32791738a0406c331e9ae8a46e, 0x2760d7 - ] -}; - pub struct BLS12_381_Fq_Params {} impl BigNumParamsGetter<4> for BLS12_381_Fq_Params { @@ -44,3 +26,20 @@ impl BigNumParamsGetter<4> for BLS12_381_Fq_Params { } } +global BLS12_381_Fq_PARAMS: BigNumParams<4> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 381, + modulus: [ + 0xabfffeb153ffffb9feffffffffaaab, 0x4b84f38512bf6730d2a0f6b0f6241e, 0xea397fe69a4b1ba7b6434bacd76477, 0x1a0111 + ], + double_modulus: [ + 0x0157fffd62a7ffff73fdffffffff5556, 0x019709e70a257ece61a541ed61ec483c, 0x01d472ffcd3496374f6c869759aec8ed, 0x340222 + ], + modulus_u60: U60Repr { limbs: [ + 0x09feffffffffaaab, 0x0abfffeb153ffffb, 0xd2a0f6b0f6241e, 0x04b84f38512bf673, 0x07b6434bacd76477, 0x0ea397fe69a4b1ba, 0x1a0111, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x09feffffffffaaab, 0x0abfffeb153ffffb, 0xd2a0f6b0f6241e, 0x04b84f38512bf673, 0x07b6434bacd76477, 0x0ea397fe69a4b1ba, 0x1a0111, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x5c59e8163c701ec4f881fd59646e8b, 0x9d07fda82a52f7d1dc780a19de74e6, 0xbcf32791738a0406c331e9ae8a46e0, 0x02760d74 + ] +}; diff --git a/src/fields/bls12_381Fr.nr b/src/fields/bls12_381Fr.nr index 6ccf0667..fce8a52b 100644 --- a/src/fields/bls12_381Fr.nr +++ b/src/fields/bls12_381Fr.nr @@ -18,24 +18,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global BLS12_381_Fr_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 255, - modulus: [ - 0xbda402fffe5bfeffffffff00000001, 0xa753299d7d483339d80809a1d80553, 0x73ed - ], - double_modulus: [ - 0x017b4805fffcb7fdfffffffe00000002, 0x014ea6533afa906673b0101343b00aa6, 0xe7da - ], - modulus_u60: U60Repr { limbs: [ - 0x0fffffff00000001, 0x0bda402fffe5bfef, 0x09d80809a1d80553, 0x0a753299d7d48333, 0x73ed, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0fffffff00000001, 0x0bda402fffe5bfef, 0x09d80809a1d80553, 0x0a753299d7d48333, 0x73ed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x410fad2f92eb5c509cde80830358e4, 0x253b7fb78ddf0e2d772dc1f823b4d9, 0x8d54 - ] -}; - pub struct BLS12_381_Fr_Params {} impl BigNumParamsGetter<3> for BLS12_381_Fr_Params { @@ -44,3 +26,20 @@ impl BigNumParamsGetter<3> for BLS12_381_Fr_Params { } } +global BLS12_381_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 255, + modulus: [ + 0xbda402fffe5bfeffffffff00000001, 0xa753299d7d483339d80809a1d80553, 0x73ed + ], + double_modulus: [ + 0x017b4805fffcb7fdfffffffe00000002, 0x014ea6533afa906673b0101343b00aa6, 0xe7da + ], + modulus_u60: U60Repr { limbs: [ + 0x0fffffff00000001, 0x0bda402fffe5bfef, 0x09d80809a1d80553, 0x0a753299d7d48333, 0x73ed, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0fffffff00000001, 0x0bda402fffe5bfef, 0x09d80809a1d80553, 0x0a753299d7d48333, 0x73ed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x10fad2f92eb5c509cde80830358e4c, 0x53b7fb78ddf0e2d772dc1f823b4d94, 0x08d542 + ] +}; diff --git a/src/fields/bn254Fq.nr b/src/fields/bn254Fq.nr index eaacd7f1..fa54b0e2 100644 --- a/src/fields/bn254Fq.nr +++ b/src/fields/bn254Fq.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global BN254_Fq_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 254, - modulus: [ - 0x816a916871ca8d3c208c16d87cfd47, 0x4e72e131a029b85045b68181585d97, 0x3064 - ], - double_modulus: [ - 0x0102d522d0e3951a7841182db0f9fa8e, 0x019ce5c263405370a08b6d0302b0bb2e, 0x60c7 - ], - modulus_u60: U60Repr { limbs: [ - 0x0c208c16d87cfd47, 0x0816a916871ca8d3, 0x45b68181585d97, 0x04e72e131a029b85, 0x3064, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0c208c16d87cfd47, 0x0816a916871ca8d3, 0x45b68181585d97, 0x04e72e131a029b85, 0x3064, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x965e1767cd4c086f3aed8a19bf90e5, 0x7462623a04a7ab074a5868073013ae, 0x54a4 - ] -}; - pub struct BN254_Fq_Params {} impl BigNumParamsGetter<3> for BN254_Fq_Params { @@ -27,3 +9,21 @@ impl BigNumParamsGetter<3> for BN254_Fq_Params { BN254_Fq_PARAMS } } + +global BN254_Fq_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 254, + modulus: [ + 0x816a916871ca8d3c208c16d87cfd47, 0x4e72e131a029b85045b68181585d97, 0x3064 + ], + double_modulus: [ + 0x0102d522d0e3951a7841182db0f9fa8e, 0x019ce5c263405370a08b6d0302b0bb2e, 0x60c7 + ], + modulus_u60: U60Repr { limbs: [ + 0x0c208c16d87cfd47, 0x0816a916871ca8d3, 0x45b68181585d97, 0x04e72e131a029b85, 0x3064, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0c208c16d87cfd47, 0x0816a916871ca8d3, 0x45b68181585d97, 0x04e72e131a029b85, 0x3064, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x65e1767cd4c086f3aed8a19bf90e51, 0x462623a04a7ab074a5868073013ae9, 0x054a47 + ] +}; diff --git a/src/fields/ed25519Fq.nr b/src/fields/ed25519Fq.nr index d8af5af6..254e288e 100644 --- a/src/fields/ed25519Fq.nr +++ b/src/fields/ed25519Fq.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global ED25519_Fq_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 255, - modulus: [ - 0xffffffffffffffffffffffffffffed, 0xffffffffffffffffffffffffffffff, 0x7fff - ], - double_modulus: [ - 0x01ffffffffffffffffffffffffffffda, 0x01fffffffffffffffffffffffffffffe, 0xfffe - ], - modulus_u60: U60Repr { limbs: [ - 0x0fffffffffffffed, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x7fff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0fffffffffffffed, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x7fff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x13, 0x00, 0x8000 - ] -}; - pub struct ED25519_Fq_Params {} impl BigNumParamsGetter<3> for ED25519_Fq_Params { @@ -28,3 +10,20 @@ impl BigNumParamsGetter<3> for ED25519_Fq_Params { } } +global ED25519_Fq_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 255, + modulus: [ + 0xffffffffffffffffffffffffffffed, 0xffffffffffffffffffffffffffffff, 0x7fff + ], + double_modulus: [ + 0x01ffffffffffffffffffffffffffffda, 0x01fffffffffffffffffffffffffffffe, 0xfffe + ], + modulus_u60: U60Repr { limbs: [ + 0x0fffffffffffffed, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x7fff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0fffffffffffffed, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x7fff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x0130, 0x00, 0x080000 + ] +}; diff --git a/src/fields/ed25519Fr.nr b/src/fields/ed25519Fr.nr index 72be347d..595c95be 100644 --- a/src/fields/ed25519Fr.nr +++ b/src/fields/ed25519Fr.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global ED25519_Fr_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 253, - modulus: [ - 0xdef9dea2f79cd65812631a5cf5d3ed, 0x14, 0x1000 - ], - double_modulus: [ - 0x01bdf3bd45ef39acb024c634b9eba7da, 0x01000000000000000000000000000028, 0x1fff - ], - modulus_u60: U60Repr { limbs: [ - 0x0812631a5cf5d3ed, 0x0def9dea2f79cd65, 0x14, 0x00, 0x1000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0812631a5cf5d3ed, 0x0def9dea2f79cd65, 0x14, 0x00, 0x1000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x84188574218ca69fb673968c28b04c, 0xffffffffffffffffffffffffffffac, 0x3fff - ] -}; - pub struct ED25519_Fr_Params {} impl BigNumParamsGetter<3> for ED25519_Fr_Params { @@ -28,3 +10,20 @@ impl BigNumParamsGetter<3> for ED25519_Fr_Params { } } +global ED25519_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 253, + modulus: [ + 0xdef9dea2f79cd65812631a5cf5d3ed, 0x14, 0x1000 + ], + double_modulus: [ + 0x01bdf3bd45ef39acb024c634b9eba7da, 0x01000000000000000000000000000028, 0x1fff + ], + modulus_u60: U60Repr { limbs: [ + 0x0812631a5cf5d3ed, 0x0def9dea2f79cd65, 0x14, 0x00, 0x1000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0812631a5cf5d3ed, 0x0def9dea2f79cd65, 0x14, 0x00, 0x1000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x4188574218ca69fb673968c28b04c6, 0xfffffffffffffffffffffffffffac8, 0x03ffff + ] +}; diff --git a/src/fields/mnt4_753Fq.nr b/src/fields/mnt4_753Fq.nr index 14c5d641..076d0bc2 100644 --- a/src/fields/mnt4_753Fq.nr +++ b/src/fields/mnt4_753Fq.nr @@ -1,6 +1,6 @@ //! Blurb sourced from https://github.com/arkworks-rs //! This library implements the base field of the MNT4_753 curve generated in -//! [\[BCTV14\]](https://eprint.iacr.org/2014/595). The name denotes that it is a +//! [[BCTV14]](https://eprint.iacr.org/2014/595). The name denotes that it is a //! Miyaji--Nakabayashi--Takano curve of embedding degree 4, defined over a //! 753-bit (prime) field. The main feature of this curve is that its scalar //! field and base field respectively equal the base field and scalar field of @@ -23,25 +23,7 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global MNT4_753_Fq_PARAMS: BigNumParams<7> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 753, - modulus: [ - 0x9d54522cdd119f5e9063de245e8001, 0xcce9767254a4638810719ac425f0e3, 0x76f218059db80f0da5cb537e38685a, 0xe8a0ed8d99d124d9a15af79db117e7, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 - ], - double_modulus: [ - 0x013aa8a459ba233ebd20c7bc48bd0002, 0x0199d2ece4a948c71020e335884be1c6, 0x01ede4300b3b701e1b4b96a6fc70d0b4, 0x01d141db1b33a249b342b5ef3b622fcd, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 - ], - modulus_u60: U60Repr { limbs: [ - 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x45dcc95da918349f4965a2aee8fd75, 0x282372b75580c27c4d1f1f57a96a11, 0xd58326e3c0552419849e3c7171d852, 0xa300e0ede1965cbf72f0aa9bf03479, 0x67fb932cae2aba9a5d17c1ff73538b, 0xa82727c6eaef38056aaa0aaedb0574, 0x0242f916cf - ] -}; - -pub struct MNT4_753_Fq_Params {} +pub struct MNT4_753_Fq_Params {} impl BigNumParamsGetter<7> for MNT4_753_Fq_Params { fn get_params() -> BigNumParams<7> { @@ -49,3 +31,20 @@ impl BigNumParamsGetter<7> for MNT4_753_Fq_Params { } } +global MNT4_753_Fq_PARAMS: BigNumParams<7> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 753, + modulus: [ + 0x9d54522cdd119f5e9063de245e8001, 0xcce9767254a4638810719ac425f0e3, 0x76f218059db80f0da5cb537e38685a, 0xe8a0ed8d99d124d9a15af79db117e7, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 + ], + double_modulus: [ + 0x013aa8a459ba233ebd20c7bc48bd0002, 0x0199d2ece4a948c71020e335884be1c6, 0x01ede4300b3b701e1b4b96a6fc70d0b4, 0x01d141db1b33a249b342b5ef3b622fcd, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 + ], + modulus_u60: U60Repr { limbs: [ + 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x5dcc95da918349f4965a2aee8fd750, 0x82372b75580c27c4d1f1f57a96a114, 0x58326e3c0552419849e3c7171d8522, 0x300e0ede1965cbf72f0aa9bf03479d, 0x7fb932cae2aba9a5d17c1ff73538ba, 0x82727c6eaef38056aaa0aaedb05746, 0x242f916cfa + ] +}; diff --git a/src/fields/mnt4_753Fr.nr b/src/fields/mnt4_753Fr.nr index ba8ae9de..10a3dfc3 100644 --- a/src/fields/mnt4_753Fr.nr +++ b/src/fields/mnt4_753Fr.nr @@ -1,6 +1,6 @@ //! Blurb sourced from https://github.com/arkworks-rs //! This library implements the scalar field of the MNT4_753 curve generated in -//! [\[BCTV14\]](https://eprint.iacr.org/2014/595). The name denotes that it is a +//! [[BCTV14]](https://eprint.iacr.org/2014/595). The name denotes that it is a //! Miyaji--Nakabayashi--Takano curve of embedding degree 4, defined over a //! 753-bit (prime) field. The main feature of this curve is that its scalar //! field and base field respectively equal the base field and scalar field of @@ -23,24 +23,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global MNT4_753_Fr_PARAMS: BigNumParams<7> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 753, - modulus: [ - 0xa099170fa13a4fd90776e240000001, 0xf97634993aa4d6c381bc3f0057974e, 0x28c859a99b3eebca9429212636b9df, 0xe8a0ed8d99d124d9a15af79db26c5c, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 - ], - double_modulus: [ - 0x0141322e1f42749fb20eedc480000002, 0x01f2ec69327549ad8703787e00af2e9c, 0x015190b353367dd7952852424c6d73be, 0x01d141db1b33a249b342b5ef3b64d8b7, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 - ], - modulus_u60: U60Repr { limbs: [ - 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xa2dae11d15867718ec70f5ff059bba, 0x276d65fe7e00ba391da260f2623ff9, 0x8140a086edaa60c58eb476bdedcb35, 0xa300e0ede1965cbf72f0aa9bee8120, 0x67fb932cae2aba9a5d17c1ff73538b, 0xa82727c6eaef38056aaa0aaedb0574, 0x0242f916cf - ] -}; - pub struct MNT4_753_Fr_Params {} impl BigNumParamsGetter<7> for MNT4_753_Fr_Params { @@ -49,3 +31,20 @@ impl BigNumParamsGetter<7> for MNT4_753_Fr_Params { } } +global MNT4_753_Fr_PARAMS: BigNumParams<7> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 753, + modulus: [ + 0xa099170fa13a4fd90776e240000001, 0xf97634993aa4d6c381bc3f0057974e, 0x28c859a99b3eebca9429212636b9df, 0xe8a0ed8d99d124d9a15af79db26c5c, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 + ], + double_modulus: [ + 0x0141322e1f42749fb20eedc480000002, 0x01f2ec69327549ad8703787e00af2e9c, 0x015190b353367dd7952852424c6d73be, 0x01d141db1b33a249b342b5ef3b64d8b7, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 + ], + modulus_u60: U60Repr { limbs: [ + 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x2dae11d15867718ec70f5ff059bba2, 0x76d65fe7e00ba391da260f2623ff9a, 0x140a086edaa60c58eb476bdedcb352, 0x300e0ede1965cbf72f0aa9bee81208, 0x7fb932cae2aba9a5d17c1ff73538ba, 0x82727c6eaef38056aaa0aaedb05746, 0x242f916cfa + ] +}; diff --git a/src/fields/mnt6_753Fq.nr b/src/fields/mnt6_753Fq.nr index d9f03a7a..80b9745a 100644 --- a/src/fields/mnt6_753Fq.nr +++ b/src/fields/mnt6_753Fq.nr @@ -1,6 +1,6 @@ //! Blurb sourced from https://github.com/arkworks-rs //! This library implements the base field of the MNT6_753 curve generated in -//! [\[BCTV14\]](https://eprint.iacr.org/2014/595). The name denotes that it is a +//! [[BCTV14]](https://eprint.iacr.org/2014/595). The name denotes that it is a //! Miyaji--Nakabayashi--Takano curve of embedding degree 6, defined over a //! 753-bit (prime) field. The main feature of this curve is that its scalar //! field and base field respectively equal the base field and scalar field of @@ -23,24 +23,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global MNT6_753_Fq_PARAMS: BigNumParams<7> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 753, - modulus: [ - 0xa099170fa13a4fd90776e240000001, 0xf97634993aa4d6c381bc3f0057974e, 0x28c859a99b3eebca9429212636b9df, 0xe8a0ed8d99d124d9a15af79db26c5c, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 - ], - double_modulus: [ - 0x0141322e1f42749fb20eedc480000002, 0x01f2ec69327549ad8703787e00af2e9c, 0x015190b353367dd7952852424c6d73be, 0x01d141db1b33a249b342b5ef3b64d8b7, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 - ], - modulus_u60: U60Repr { limbs: [ - 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xa2dae11d15867718ec70f5ff059bba, 0x276d65fe7e00ba391da260f2623ff9, 0x8140a086edaa60c58eb476bdedcb35, 0xa300e0ede1965cbf72f0aa9bee8120, 0x67fb932cae2aba9a5d17c1ff73538b, 0xa82727c6eaef38056aaa0aaedb0574, 0x0242f916cf - ] -}; - pub struct MNT6_753_Fq_Params {} impl BigNumParamsGetter<7> for MNT6_753_Fq_Params { @@ -49,3 +31,20 @@ impl BigNumParamsGetter<7> for MNT6_753_Fq_Params { } } +global MNT6_753_Fq_PARAMS: BigNumParams<7> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 753, + modulus: [ + 0xa099170fa13a4fd90776e240000001, 0xf97634993aa4d6c381bc3f0057974e, 0x28c859a99b3eebca9429212636b9df, 0xe8a0ed8d99d124d9a15af79db26c5c, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 + ], + double_modulus: [ + 0x0141322e1f42749fb20eedc480000002, 0x01f2ec69327549ad8703787e00af2e9c, 0x015190b353367dd7952852424c6d73be, 0x01d141db1b33a249b342b5ef3b64d8b7, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 + ], + modulus_u60: U60Repr { limbs: [ + 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x090776e240000001, 0x0a099170fa13a4fd, 0x0381bc3f0057974e, 0x0f97634993aa4d6c, 0x0a9429212636b9df, 0x028c859a99b3eebc, 0x09a15af79db26c5c, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x2dae11d15867718ec70f5ff059bba2, 0x76d65fe7e00ba391da260f2623ff9a, 0x140a086edaa60c58eb476bdedcb352, 0x300e0ede1965cbf72f0aa9bee81208, 0x7fb932cae2aba9a5d17c1ff73538ba, 0x82727c6eaef38056aaa0aaedb05746, 0x242f916cfa + ] +}; diff --git a/src/fields/mnt6_753Fr.nr b/src/fields/mnt6_753Fr.nr index b07cacdc..82ebd40c 100644 --- a/src/fields/mnt6_753Fr.nr +++ b/src/fields/mnt6_753Fr.nr @@ -1,6 +1,6 @@ //! Blurb sourced from https://github.com/arkworks-rs //! This library implements the scalar field of the MNT6_753 curve generated in -//! [\[BCTV14\]](https://eprint.iacr.org/2014/595). The name denotes that it is a +//! [[BCTV14]](https://eprint.iacr.org/2014/595). The name denotes that it is a //! Miyaji--Nakabayashi--Takano curve of embedding degree 6, defined over a //! 753-bit (prime) field. The main feature of this curve is that its scalar //! field and base field respectively equal the base field and scalar field of @@ -23,24 +23,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global MNT6_753_Fr_PARAMS: BigNumParams<7> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 753, - modulus: [ - 0x9d54522cdd119f5e9063de245e8001, 0xcce9767254a4638810719ac425f0e3, 0x76f218059db80f0da5cb537e38685a, 0xe8a0ed8d99d124d9a15af79db117e7, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 - ], - double_modulus: [ - 0x013aa8a459ba233ebd20c7bc48bd0002, 0x0199d2ece4a948c71020e335884be1c6, 0x01ede4300b3b701e1b4b96a6fc70d0b4, 0x01d141db1b33a249b342b5ef3b622fcd, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 - ], - modulus_u60: U60Repr { limbs: [ - 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x45dcc95da918349f4965a2aee8fd75, 0x282372b75580c27c4d1f1f57a96a11, 0xd58326e3c0552419849e3c7171d852, 0xa300e0ede1965cbf72f0aa9bf03479, 0x67fb932cae2aba9a5d17c1ff73538b, 0xa82727c6eaef38056aaa0aaedb0574, 0x0242f916cf - ] -}; - pub struct MNT6_753_Fr_Params {} impl BigNumParamsGetter<7> for MNT6_753_Fr_Params { @@ -49,3 +31,20 @@ impl BigNumParamsGetter<7> for MNT6_753_Fr_Params { } } +global MNT6_753_Fr_PARAMS: BigNumParams<7> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 753, + modulus: [ + 0x9d54522cdd119f5e9063de245e8001, 0xcce9767254a4638810719ac425f0e3, 0x76f218059db80f0da5cb537e38685a, 0xe8a0ed8d99d124d9a15af79db117e7, 0x8fafed5eb7e8f96c97d87307fdb925, 0xc41110229022eee2cdadb7f997505b, 0x01c4c62d92 + ], + double_modulus: [ + 0x013aa8a459ba233ebd20c7bc48bd0002, 0x0199d2ece4a948c71020e335884be1c6, 0x01ede4300b3b701e1b4b96a6fc70d0b4, 0x01d141db1b33a249b342b5ef3b622fcd, 0x011f5fdabd6fd1f2d92fb0e60ffb724a, 0x01882220452045ddc59b5b6ff32ea0b6, 0x03898c5b24 + ], + modulus_u60: U60Repr { limbs: [ + 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0e9063de245e8001, 0x09d54522cdd119f5, 0x0810719ac425f0e3, 0x0cce9767254a4638, 0x0da5cb537e38685a, 0x076f218059db80f0, 0x09a15af79db117e7, 0x0e8a0ed8d99d124d, 0x0c97d87307fdb925, 0x08fafed5eb7e8f96, 0x02cdadb7f997505b, 0x0c41110229022eee, 0x01c4c62d92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x5dcc95da918349f4965a2aee8fd750, 0x82372b75580c27c4d1f1f57a96a114, 0x58326e3c0552419849e3c7171d8522, 0x300e0ede1965cbf72f0aa9bf03479d, 0x7fb932cae2aba9a5d17c1ff73538ba, 0x82727c6eaef38056aaa0aaedb05746, 0x242f916cfa + ] +}; diff --git a/src/fields/pallasFq.nr b/src/fields/pallasFq.nr index 4265ae55..e305c4fa 100644 --- a/src/fields/pallasFq.nr +++ b/src/fields/pallasFq.nr @@ -1,5 +1,5 @@ //! Blurb sourced from https://github.com/arkworks-rs -//! This library implements the scalar field of the prime-order curve Pallas, generated by +//! This library implements the base field of the prime-order curve Pallas, generated by //! [Daira Hopwood](https://github.com/zcash/pasta). The main feature of this //! curve is that it forms a cycle with Vesta, i.e. its scalar field and base //! field respectively are the base field and scalar field of Vesta. @@ -17,24 +17,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global Pallas_Fq_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 255, - modulus: [ - 0x4698fc094cf91b992d30ed00000001, 0x22, 0x4000 - ], - double_modulus: [ - 0x018d31f81299f237325a61da00000002, 0x01000000000000000000000000000043, 0x7fff - ], - modulus_u60: U60Repr { limbs: [ - 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xe59c0fdacc1b919b4b3c4bfffffffc, 0xffffffffffffffffffffffffffff76, 0xffff - ] -}; - pub struct Pallas_Fq_Params {} impl BigNumParamsGetter<3> for Pallas_Fq_Params { @@ -43,3 +25,20 @@ impl BigNumParamsGetter<3> for Pallas_Fq_Params { } } +global Pallas_Fq_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 255, + modulus: [ + 0x4698fc094cf91b992d30ed00000001, 0x22, 0x4000 + ], + double_modulus: [ + 0x018d31f81299f237325a61da00000002, 0x01000000000000000000000000000043, 0x7fff + ], + modulus_u60: U60Repr { limbs: [ + 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x59c0fdacc1b919b4b3c4bfffffffc4, 0xfffffffffffffffffffffffffff76e, 0x0fffff + ] +}; diff --git a/src/fields/pallasFr.nr b/src/fields/pallasFr.nr index e696d38f..a865f93e 100644 --- a/src/fields/pallasFr.nr +++ b/src/fields/pallasFr.nr @@ -1,5 +1,5 @@ //! Blurb sourced from https://github.com/arkworks-rs -//! This library implements the base field of the prime-order curve Pallas, generated by +//! This library implements the scalar field of the prime-order curve Pallas, generated by //! [Daira Hopwood](https://github.com/zcash/pasta). The main feature of this //! curve is that it forms a cycle with Vesta, i.e. its scalar field and base //! field respectively are the base field and scalar field of Vesta. @@ -17,24 +17,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global Pallas_Fr_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 255, - modulus: [ - 0x4698fc0994a8dd8c46eb2100000001, 0x22, 0x4000 - ], - double_modulus: [ - 0x018d31f8132951bb188dd64200000002, 0x01000000000000000000000000000043, 0x7fff - ], - modulus_u60: U60Repr { limbs: [ - 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xe59c0fd9ad5c89cee4537bfffffffc, 0xffffffffffffffffffffffffffff76, 0xffff - ] -}; - pub struct Pallas_Fr_Params {} impl BigNumParamsGetter<3> for Pallas_Fr_Params { @@ -43,3 +25,20 @@ impl BigNumParamsGetter<3> for Pallas_Fr_Params { } } +global Pallas_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 255, + modulus: [ + 0x4698fc0994a8dd8c46eb2100000001, 0x22, 0x4000 + ], + double_modulus: [ + 0x018d31f8132951bb188dd64200000002, 0x01000000000000000000000000000043, 0x7fff + ], + modulus_u60: U60Repr { limbs: [ + 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x59c0fd9ad5c89cee4537bfffffffc4, 0xfffffffffffffffffffffffffff76e, 0x0fffff + ] +}; diff --git a/src/fields/secp256k1Fq.nr b/src/fields/secp256k1Fq.nr index 8615e19e..84274f71 100644 --- a/src/fields/secp256k1Fq.nr +++ b/src/fields/secp256k1Fq.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global Secp256k1_Fq_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 256, - modulus: [ - 0xfffffffffffffffffffffefffffc2f, 0xffffffffffffffffffffffffffffff, 0xffff - ], - double_modulus: [ - 0x01fffffffffffffffffffffdfffff85e, 0x01fffffffffffffffffffffffffffffe, 0x01fffe - ], - modulus_u60: U60Repr { limbs: [ - 0x0ffffffefffffc2f, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0ffffffefffffc2f, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x01000003d1, 0x00, 0x010000 - ] -}; - pub struct Secp256k1_Fq_Params {} impl BigNumParamsGetter<3> for Secp256k1_Fq_Params { @@ -28,3 +10,20 @@ impl BigNumParamsGetter<3> for Secp256k1_Fq_Params { } } +global Secp256k1_Fq_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 256, + modulus: [ + 0xfffffffffffffffffffffefffffc2f, 0xffffffffffffffffffffffffffffff, 0xffff + ], + double_modulus: [ + 0x01fffffffffffffffffffffdfffff85e, 0x01fffffffffffffffffffffffffffffe, 0x01fffe + ], + modulus_u60: U60Repr { limbs: [ + 0x0ffffffefffffc2f, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0ffffffefffffc2f, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x1000003d10, 0x00, 0x100000 + ] +}; diff --git a/src/fields/secp256k1Fr.nr b/src/fields/secp256k1Fr.nr index 65474658..a8dcac44 100644 --- a/src/fields/secp256k1Fr.nr +++ b/src/fields/secp256k1Fr.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global Secp256k1_Fr_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 256, - modulus: [ - 0xaedce6af48a03bbfd25e8cd0364141, 0xfffffffffffffffffffffffffffeba, 0xffff - ], - double_modulus: [ - 0x015db9cd5e9140777fa4bd19a06c8282, 0x01fffffffffffffffffffffffffffd74, 0x01fffe - ], - modulus_u60: U60Repr { limbs: [ - 0x0fd25e8cd0364141, 0x0aedce6af48a03bb, 0x0ffffffffffffeba, 0x0fffffffffffffff, 0xffff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0fd25e8cd0364141, 0x0aedce6af48a03bb, 0x0ffffffffffffeba, 0x0fffffffffffffff, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x51231950b75fc4402da1732fc9bec0, 0x0145, 0x010000 - ] -}; - pub struct Secp256k1_Fr_Params {} impl BigNumParamsGetter<3> for Secp256k1_Fr_Params { @@ -28,3 +10,20 @@ impl BigNumParamsGetter<3> for Secp256k1_Fr_Params { } } +global Secp256k1_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 256, + modulus: [ + 0xaedce6af48a03bbfd25e8cd0364141, 0xfffffffffffffffffffffffffffeba, 0xffff + ], + double_modulus: [ + 0x015db9cd5e9140777fa4bd19a06c8282, 0x01fffffffffffffffffffffffffffd74, 0x01fffe + ], + modulus_u60: U60Repr { limbs: [ + 0x0fd25e8cd0364141, 0x0aedce6af48a03bb, 0x0ffffffffffffeba, 0x0fffffffffffffff, 0xffff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0fd25e8cd0364141, 0x0aedce6af48a03bb, 0x0ffffffffffffeba, 0x0fffffffffffffff, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x1231950b75fc4402da1732fc9bec09, 0x1455, 0x100000 + ] +}; diff --git a/src/fields/secp256r1Fq.nr b/src/fields/secp256r1Fq.nr index acad7082..77c6808e 100644 --- a/src/fields/secp256r1Fq.nr +++ b/src/fields/secp256r1Fq.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global Secp256r1_Fq_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 256, - modulus: [ - 0xffffffffffffffffffffffff, 0xffff00000001000000000000000000, 0xffff - ], - double_modulus: [ - 0x01000001fffffffffffffffffffffffe, 0x01fffe00000001ffffffffffffffffff, 0x01fffe - ], - modulus_u60: U60Repr { limbs: [ - 0x0fffffffffffffff, 0x0fffffffff, 0x00, 0x0ffff00000001000, 0xffff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0fffffffffffffff, 0x0fffffffff, 0x00, 0x0ffff00000001000, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xfffffeffffffff0000000000000003, 0xfffffffffffffffefffffffeff, 0x010000 - ] -}; - pub struct Secp256r1_Fq_Params {} impl BigNumParamsGetter<3> for Secp256r1_Fq_Params { @@ -28,3 +10,20 @@ impl BigNumParamsGetter<3> for Secp256r1_Fq_Params { } } +global Secp256r1_Fq_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 256, + modulus: [ + 0xffffffffffffffffffffffff, 0xffff00000001000000000000000000, 0xffff + ], + double_modulus: [ + 0x01000001fffffffffffffffffffffffe, 0x01fffe00000001ffffffffffffffffff, 0x01fffe + ], + modulus_u60: U60Repr { limbs: [ + 0x0fffffffffffffff, 0x0fffffffff, 0x00, 0x0ffff00000001000, 0xffff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0fffffffffffffff, 0x0fffffffff, 0x00, 0x0ffff00000001000, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0xffffeffffffff00000000000000030, 0x0fffffffffffffffefffffffefff, 0x100000 + ] +}; diff --git a/src/fields/secp256r1Fr.nr b/src/fields/secp256r1Fr.nr index 4ed0088b..29d6d92a 100644 --- a/src/fields/secp256r1Fr.nr +++ b/src/fields/secp256r1Fr.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global Secp256r1_Fr_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 256, - modulus: [ - 0xe6faada7179e84f3b9cac2fc632551, 0xffff00000000ffffffffffffffffbc, 0xffff - ], - double_modulus: [ - 0x01cdf55b4e2f3d09e7739585f8c64aa2, 0x01fffe00000001ffffffffffffffff78, 0x01fffe - ], - modulus_u60: U60Repr { limbs: [ - 0x03b9cac2fc632551, 0x0e6faada7179e84f, 0x0fffffffffffffbc, 0x0ffff00000000fff, 0xffff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x03b9cac2fc632551, 0x0e6faada7179e84f, 0x0fffffffffffffbc, 0x0ffff00000000fff, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0x190552df1a6c21012ffd85eedf9bfe, 0xfffffffffffffffeffffffff43, 0x010000 - ] -}; - pub struct Secp256r1_Fr_Params {} impl BigNumParamsGetter<3> for Secp256r1_Fr_Params { @@ -28,3 +10,20 @@ impl BigNumParamsGetter<3> for Secp256r1_Fr_Params { } } +global Secp256r1_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 256, + modulus: [ + 0xe6faada7179e84f3b9cac2fc632551, 0xffff00000000ffffffffffffffffbc, 0xffff + ], + double_modulus: [ + 0x01cdf55b4e2f3d09e7739585f8c64aa2, 0x01fffe00000001ffffffffffffffff78, 0x01fffe + ], + modulus_u60: U60Repr { limbs: [ + 0x03b9cac2fc632551, 0x0e6faada7179e84f, 0x0fffffffffffffbc, 0x0ffff00000000fff, 0xffff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x03b9cac2fc632551, 0x0e6faada7179e84f, 0x0fffffffffffffbc, 0x0ffff00000000fff, 0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x90552df1a6c21012ffd85eedf9bfe6, 0x0fffffffffffffffeffffffff431, 0x100000 + ] +}; diff --git a/src/fields/secp384r1Fq.nr b/src/fields/secp384r1Fq.nr index 9149f604..3035c0e2 100644 --- a/src/fields/secp384r1Fq.nr +++ b/src/fields/secp384r1Fq.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global Secp384r1_Fq_PARAMS: BigNumParams<4> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 384, - modulus: [ - 0xffffff0000000000000000ffffffff, 0xfffffffffffffffffffffffffffeff, 0xffffffffffffffffffffffffffffff, 0xffffff - ], - double_modulus: [ - 0x01fffffe0000000000000001fffffffe, 0x01fffffffffffffffffffffffffffdfe, 0x01fffffffffffffffffffffffffffffe, 0x01fffffe - ], - modulus_u60: U60Repr { limbs: [ - 0xffffffff, 0x0ffffff000000000, 0x0ffffffffffffeff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0xffffffff, 0x0ffffff000000000, 0x0ffffffffffffeff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xffffffffffffffff00000001, 0x0100, 0x00, 0x01000000 - ] -}; - pub struct Secp384r1_Fq_Params {} impl BigNumParamsGetter<4> for Secp384r1_Fq_Params { @@ -28,3 +10,20 @@ impl BigNumParamsGetter<4> for Secp384r1_Fq_Params { } } +global Secp384r1_Fq_PARAMS: BigNumParams<4> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 384, + modulus: [ + 0xffffff0000000000000000ffffffff, 0xfffffffffffffffffffffffffffeff, 0xffffffffffffffffffffffffffffff, 0xffffff + ], + double_modulus: [ + 0x01fffffe0000000000000001fffffffe, 0x01fffffffffffffffffffffffffffdfe, 0x01fffffffffffffffffffffffffffffe, 0x01fffffe + ], + modulus_u60: U60Repr { limbs: [ + 0xffffffff, 0x0ffffff000000000, 0x0ffffffffffffeff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0xffffffff, 0x0ffffff000000000, 0x0ffffffffffffeff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x0ffffffffffffffff000000010, 0x1000, 0x00, 0x10000000 + ] +}; diff --git a/src/fields/secp384r1Fr.nr b/src/fields/secp384r1Fr.nr index 75393219..0d819a83 100644 --- a/src/fields/secp384r1Fr.nr +++ b/src/fields/secp384r1Fr.nr @@ -2,24 +2,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global Secp384r1_Fr_PARAMS: BigNumParams<4> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 384, - modulus: [ - 0x1a0db248b0a77aecec196accc52973, 0xffffffffffffc7634d81f4372ddf58, 0xffffffffffffffffffffffffffffff, 0xffffff - ], - double_modulus: [ - 0x01341b6491614ef5d9d832d5998a52e6, 0x01ffffffffffff8ec69b03e86e5bbeaf, 0x01fffffffffffffffffffffffffffffe, 0x01fffffe - ], - modulus_u60: U60Repr { limbs: [ - 0x0cec196accc52973, 0x01a0db248b0a77ae, 0x034d81f4372ddf58, 0x0ffffffffffffc76, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0cec196accc52973, 0x01a0db248b0a77ae, 0x034d81f4372ddf58, 0x0ffffffffffffc76, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xe5f24db74f58851313e695333ad68d, 0x389cb27e0bc8d220a7, 0x00, 0x01000000 - ] -}; - pub struct Secp384r1_Fr_Params {} impl BigNumParamsGetter<4> for Secp384r1_Fr_Params { @@ -28,3 +10,20 @@ impl BigNumParamsGetter<4> for Secp384r1_Fr_Params { } } +global Secp384r1_Fr_PARAMS: BigNumParams<4> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 384, + modulus: [ + 0x1a0db248b0a77aecec196accc52973, 0xffffffffffffc7634d81f4372ddf58, 0xffffffffffffffffffffffffffffff, 0xffffff + ], + double_modulus: [ + 0x01341b6491614ef5d9d832d5998a52e6, 0x01ffffffffffff8ec69b03e86e5bbeaf, 0x01fffffffffffffffffffffffffffffe, 0x01fffffe + ], + modulus_u60: U60Repr { limbs: [ + 0x0cec196accc52973, 0x01a0db248b0a77ae, 0x034d81f4372ddf58, 0x0ffffffffffffc76, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0cec196accc52973, 0x01a0db248b0a77ae, 0x034d81f4372ddf58, 0x0ffffffffffffc76, 0x0fffffffffffffff, 0x0fffffffffffffff, 0xffffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x5f24db74f58851313e695333ad68d0, 0x0389cb27e0bc8d220a7e, 0x00, 0x10000000 + ] +}; diff --git a/src/fields/vestaFq.nr b/src/fields/vestaFq.nr index 0fcecf4e..59c0bfc4 100644 --- a/src/fields/vestaFq.nr +++ b/src/fields/vestaFq.nr @@ -18,24 +18,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global Vesta_Fq_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 255, - modulus: [ - 0x4698fc0994a8dd8c46eb2100000001, 0x22, 0x4000 - ], - double_modulus: [ - 0x018d31f8132951bb188dd64200000002, 0x01000000000000000000000000000043, 0x7fff - ], - modulus_u60: U60Repr { limbs: [ - 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xe59c0fd9ad5c89cee4537bfffffffc, 0xffffffffffffffffffffffffffff76, 0xffff - ] -}; - pub struct Vesta_Fq_Params {} impl BigNumParamsGetter<3> for Vesta_Fq_Params { @@ -44,3 +26,21 @@ impl BigNumParamsGetter<3> for Vesta_Fq_Params { } } +global Vesta_Fq_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 255, + modulus: [ + 0x4698fc0994a8dd8c46eb2100000001, 0x22, 0x4000 + ], + double_modulus: [ + 0x018d31f8132951bb188dd64200000002, 0x01000000000000000000000000000043, 0x7fff + ], + modulus_u60: U60Repr { limbs: [ + 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0c46eb2100000001, 0x04698fc0994a8dd8, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x59c0fd9ad5c89cee4537bfffffffc4, 0xfffffffffffffffffffffffffff76e, 0x0fffff + ] +}; + diff --git a/src/fields/vestaFr.nr b/src/fields/vestaFr.nr index c0367491..25c45332 100644 --- a/src/fields/vestaFr.nr +++ b/src/fields/vestaFr.nr @@ -18,24 +18,6 @@ use crate::params::BigNumParamsGetter; use crate::params::BigNumParams; use crate::utils::u60_representation::U60Repr; -global Vesta_Fr_PARAMS: BigNumParams<3> = BigNumParams { - has_multiplicative_inverse: true, - modulus_bits_getter: || 255, - modulus: [ - 0x4698fc094cf91b992d30ed00000001, 0x22, 0x4000 - ], - double_modulus: [ - 0x018d31f81299f237325a61da00000002, 0x01000000000000000000000000000043, 0x7fff - ], - modulus_u60: U60Repr { limbs: [ - 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00]}, - modulus_u60_x4: U60Repr { limbs: [ - 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, - redc_param: [ - 0xe59c0fdacc1b919b4b3c4bfffffffc, 0xffffffffffffffffffffffffffff76, 0xffff - ] -}; - pub struct Vesta_Fr_Params {} impl BigNumParamsGetter<3> for Vesta_Fr_Params { @@ -44,3 +26,20 @@ impl BigNumParamsGetter<3> for Vesta_Fr_Params { } } +global Vesta_Fr_PARAMS: BigNumParams<3> = BigNumParams { + has_multiplicative_inverse: true, + modulus_bits_getter: || 255, + modulus: [ + 0x4698fc094cf91b992d30ed00000001, 0x22, 0x4000 + ], + double_modulus: [ + 0x018d31f81299f237325a61da00000002, 0x01000000000000000000000000000043, 0x7fff + ], + modulus_u60: U60Repr { limbs: [ + 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x092d30ed00000001, 0x04698fc094cf91b9, 0x22, 0x00, 0x4000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x59c0fdacc1b919b4b3c4bfffffffc4, 0xfffffffffffffffffffffffffff76e, 0x0fffff + ] +}; diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index 0387dcee..f42931e8 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -3,7 +3,7 @@ use crate::utils::map::map; use crate::params::BigNumParams; use crate::constrained_ops::{ - conditional_select, assert_is_not_equal, eq, validate_in_field, validate_in_range, neg, add, sub, + derive_from_seed, conditional_select, assert_is_not_equal, eq, validate_in_field, validate_in_range, neg, add, sub, mul, div, udiv_mod, udiv, umod }; use crate::unconstrained_ops::{ @@ -23,6 +23,7 @@ pub struct RuntimeBigNum { pub(crate) trait RuntimeBigNumTrait { fn new(params: BigNumParams) -> Self; fn one(params: BigNumParams) -> Self; + fn derive_from_seed(params: BigNumParams, seed: [u8; SeedBytes]) -> Self; fn __derive_from_seed(params: BigNumParams, seed: [u8; SeedBytes]) -> Self; fn from_slice(params: BigNumParams, limbs: [Field]) -> Self; fn from_array(params: BigNumParams, limbs: [Field; N]) -> Self; @@ -104,6 +105,13 @@ impl RuntimeBigNumTrait for RuntimeBigNum { result } + fn derive_from_seed(params: BigNumParams, seed: [u8; SeedBytes]) -> Self { + let limbs = unsafe { + derive_from_seed(params, seed) + }; + Self { limbs, params } + } + // UNCONSTRAINED! (Hence `__` prefix). fn __derive_from_seed(params: BigNumParams, seed: [u8; SeedBytes]) -> Self { let limbs = unsafe { @@ -273,11 +281,11 @@ impl RuntimeBigNumTrait for RuntimeBigNum { let (q_limbs, r_limbs) = unsafe { __compute_quadratic_expression( params, - lhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + map(lhs_terms, |bns| map(bns, |bn| Self::get_limbs(bn))), lhs_flags, - rhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + map(rhs_terms, |bns| map(bns, |bn| Self::get_limbs(bn))), rhs_flags, - linear_terms.map(|bn| Self::get_limbs(bn)), + map(linear_terms, |bn| Self::get_limbs(bn)), linear_flags ) }; @@ -295,11 +303,11 @@ impl RuntimeBigNumTrait for RuntimeBigNum { ) { evaluate_quadratic_expression( params, - lhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + map(lhs_terms, |bns| map(bns, |bn| Self::get_limbs(bn))), lhs_flags, - rhs_terms.map(|bns| map(bns, |bn| Self::get_limbs(bn))), + map(rhs_terms, |bns| map(bns, |bn| Self::get_limbs(bn))), rhs_flags, - linear_terms.map(|bn| Self::get_limbs(bn)), + map(linear_terms, |bn| Self::get_limbs(bn)), linear_flags ) } diff --git a/src/runtime_bignum_test.nr b/src/runtime_bignum_test.nr index 61e318d8..d7503ac8 100644 --- a/src/runtime_bignum_test.nr +++ b/src/runtime_bignum_test.nr @@ -1,107 +1,88 @@ use crate::utils::u60_representation::U60Repr; use crate::runtime_bignum::RuntimeBigNum; -use crate::params::BigNumParams; +use crate::params::{ BigNumParams, BigNumParamsGetter }; + use crate::fields::bn254Fq::BN254_Fq_Params; +use crate::fields::secp256k1Fq::Secp256k1_Fq_Params; +use crate::fields::bls12_381Fq::BLS12_381_Fq_Params; +use crate::fields::bls12_381Fr::BLS12_381_Fr_Params; +use crate::fields::bls12_377Fq::BLS12_377_Fq_Params; +use crate::fields::bls12_377Fr::BLS12_377_Fr_Params; + +global TEST_2048_PARAMS: BigNumParams<18> = BigNumParams { + has_multiplicative_inverse: false, + modulus_bits_getter: || 2048, + modulus: [ + 0xc0a197a5ae0fcdceb052c9732614fe, 0x656ae034423283422243918ab83be3, 0x6bf590da48a7c1070b7d5aabaac678, 0x0cce39f530238b606f24b296e2bda9, 0x01e1fef9bb9c1c3ead98f226f1bfa0, 0xad8c1c816e12e0ed1379055e373abf, 0xcebe80e474f753aa9d1461c435123d, 0xaee5a18ceedef88d115a8b93c167ad, 0x268ba83c4a65c4307427fc495d9e44, 0xdd2777926848667b7df79f342639d4, 0xf455074c96855ca0068668efe7da3d, 0x5ddba6b30bbc168bfb3a1225f27d65, 0x591fec484f36707524133bcd6f4258, 0x59641b756766aeebe66781dd01d062, 0x58bc5eaff4b165e142bf9e2480eebb, 0x667a3964f08e06df772ce64b229a72, 0x9c1fdb18907711bfe3e3c1cf918395, 0xb8 + ], + double_modulus: [ + 0x0181432f4b5c1f9b9d60a592e64c29fc, 0x01cad5c06884650684448723157077c6, 0x01d7eb21b4914f820e16fab557558cef, 0x01199c73ea604716c0de49652dc57b51, 0x0103c3fdf37738387d5b31e44de37f3f, 0x015b183902dc25c1da26f20abc6e757d, 0x019d7d01c8e9eea7553a28c3886a247a, 0x015dcb4319ddbdf11a22b5172782cf5a, 0x014d17507894cb8860e84ff892bb3c88, 0x01ba4eef24d090ccf6fbef3e684c73a7, 0x01e8aa0e992d0ab9400d0cd1dfcfb47a, 0x01bbb74d6617782d17f674244be4faca, 0x01b23fd8909e6ce0ea4826779ade84af, 0x01b2c836eacecd5dd7cccf03ba03a0c3, 0x01b178bd5fe962cbc2857f3c4901dd75, 0x01ccf472c9e11c0dbeee59cc964534e3, 0x01383fb63120ee237fc7c7839f230729, 0x0170 + ], + modulus_u60: U60Repr { limbs: [ + 0x0eb052c9732614fe, 0x0c0a197a5ae0fcdc, 0x022243918ab83be3, 0x0656ae0344232834, 0x070b7d5aabaac678, 0x06bf590da48a7c10, 0x6f24b296e2bda9, 0xcce39f530238b6, 0x0ead98f226f1bfa0, 0x1e1fef9bb9c1c3, 0x0d1379055e373abf, 0x0ad8c1c816e12e0e, 0x0a9d1461c435123d, 0x0cebe80e474f753a, 0x0d115a8b93c167ad, 0x0aee5a18ceedef88, 0x7427fc495d9e44, 0x0268ba83c4a65c43, 0x0b7df79f342639d4, 0x0dd2777926848667, 0x068668efe7da3d, 0x0f455074c96855ca, 0x0bfb3a1225f27d65, 0x05ddba6b30bbc168, 0x0524133bcd6f4258, 0x0591fec484f36707, 0x0be66781dd01d062, 0x059641b756766aee, 0x0142bf9e2480eebb, 0x058bc5eaff4b165e, 0x0f772ce64b229a72, 0x0667a3964f08e06d, 0x0fe3e3c1cf918395, 0x09c1fdb18907711b, 0xb8, 0x00]}, + modulus_u60_x4: U60Repr { limbs: [ + 0x0eb052c9732614fe, 0x0c0a197a5ae0fcdc, 0x022243918ab83be3, 0x0656ae0344232834, 0x070b7d5aabaac678, 0x06bf590da48a7c10, 0x6f24b296e2bda9, 0xcce39f530238b6, 0x0ead98f226f1bfa0, 0x1e1fef9bb9c1c3, 0x0d1379055e373abf, 0x0ad8c1c816e12e0e, 0x0a9d1461c435123d, 0x0cebe80e474f753a, 0x0d115a8b93c167ad, 0x0aee5a18ceedef88, 0x7427fc495d9e44, 0x0268ba83c4a65c43, 0x0b7df79f342639d4, 0x0dd2777926848667, 0x068668efe7da3d, 0x0f455074c96855ca, 0x0bfb3a1225f27d65, 0x05ddba6b30bbc168, 0x0524133bcd6f4258, 0x0591fec484f36707, 0x0be66781dd01d062, 0x059641b756766aee, 0x0142bf9e2480eebb, 0x058bc5eaff4b165e, 0x0f772ce64b229a72, 0x0667a3964f08e06d, 0x0fe3e3c1cf918395, 0x09c1fdb18907711b, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] }, + redc_param: [ + 0x1697def7100cd5cf8d890b4ef2ec3f, 0x765ba8304214dac764d3f4adc31859, 0x8404bd14d927ea230e60d4bebf9406, 0xc4d53a23bacc251ecbfc4b7ba5a0b4, 0x3eaf3499474a6f5b2fff83f1259c87, 0xbff4c737b97281f1a5f2384a8c16d9, 0x1b4cf2f55358476b53237829990555, 0xe7a804e8eacfe3a2a5673bc3885b86, 0xabadeae4282906c817adf70eab4ae1, 0x66f7df257fe2bf27f0809aceed9b0e, 0xd90fb7428901b8bed11f6b81e36bf1, 0x36e6ba885c60b7024c563605df7e07, 0x2b7c58d2fb5d2c8478963ae6d4a44f, 0x6ee761de26635f114ccc3f7d74f855, 0x3fb726a10cf2220897513f05243de3, 0x43a26bbd732496eb4d828591b8056e, 0xf4e42304e60fb3a54fca735499f2cf, 0x162f + ] +}; + +struct Test2048Params {} + +// See https://github.com/noir-lang/noir/issues/6172 +#[test] +fn silence_warning() { + let _ = Test2048Params {}; +} -global BN254_Fq_PARAMS = BN254_Fq_Params::get_params(); - -fn get_2048_BN_params() -> BigNumParams<18> { - let has_multiplicative_inverse = false; - let modulus_bits_getter = || 2048; - let modulus: [Field; 18] = [ - 0x0000000000000000000000000000000000c0a197a5ae0fcdceb052c9732614fe, - 0x0000000000000000000000000000000000656ae034423283422243918ab83be3, - 0x00000000000000000000000000000000006bf590da48a7c1070b7d5aabaac678, - 0x00000000000000000000000000000000000cce39f530238b606f24b296e2bda9, - 0x000000000000000000000000000000000001e1fef9bb9c1c3ead98f226f1bfa0, - 0x0000000000000000000000000000000000ad8c1c816e12e0ed1379055e373abf, - 0x0000000000000000000000000000000000cebe80e474f753aa9d1461c435123d, - 0x0000000000000000000000000000000000aee5a18ceedef88d115a8b93c167ad, - 0x0000000000000000000000000000000000268ba83c4a65c4307427fc495d9e44, - 0x0000000000000000000000000000000000dd2777926848667b7df79f342639d4, - 0x0000000000000000000000000000000000f455074c96855ca0068668efe7da3d, - 0x00000000000000000000000000000000005ddba6b30bbc168bfb3a1225f27d65, - 0x0000000000000000000000000000000000591fec484f36707524133bcd6f4258, - 0x000000000000000000000000000000000059641b756766aeebe66781dd01d062, - 0x000000000000000000000000000000000058bc5eaff4b165e142bf9e2480eebb, - 0x0000000000000000000000000000000000667a3964f08e06df772ce64b229a72, - 0x00000000000000000000000000000000009c1fdb18907711bfe3e3c1cf918395, - 0x00000000000000000000000000000000000000000000000000000000000000b8 - ]; - let redc_param: [Field; 18] = [ - 0x000000000000000000000000000000000091697def7100cd5cf8d890b4ef2ec3, - 0x00000000000000000000000000000000006765ba8304214dac764d3f4adc3185, - 0x000000000000000000000000000000000048404bd14d927ea230e60d4bebf940, - 0x00000000000000000000000000000000007c4d53a23bacc251ecbfc4b7ba5a0b, - 0x000000000000000000000000000000000093eaf3499474a6f5b2fff83f1259c8, - 0x00000000000000000000000000000000005bff4c737b97281f1a5f2384a8c16d, - 0x000000000000000000000000000000000061b4cf2f55358476b5323782999055, - 0x00000000000000000000000000000000001e7a804e8eacfe3a2a5673bc3885b8, - 0x0000000000000000000000000000000000eabadeae4282906c817adf70eab4ae, - 0x0000000000000000000000000000000000166f7df257fe2bf27f0809aceed9b0, - 0x00000000000000000000000000000000007d90fb7428901b8bed11f6b81e36bf, - 0x0000000000000000000000000000000000f36e6ba885c60b7024c563605df7e0, - 0x000000000000000000000000000000000052b7c58d2fb5d2c8478963ae6d4a44, - 0x000000000000000000000000000000000036ee761de26635f114ccc3f7d74f85, - 0x0000000000000000000000000000000000e3fb726a10cf2220897513f05243de, - 0x0000000000000000000000000000000000f43a26bbd732496eb4d828591b8056, - 0x0000000000000000000000000000000000ff4e42304e60fb3a54fca735499f2c, - 0x0000000000000000000000000000000000000000000000000000000000000162 - ]; - BigNumParams::new( - has_multiplicative_inverse, - modulus_bits_getter, - modulus, - redc_param - ) +impl BigNumParamsGetter<18> for Test2048Params { + fn get_params() -> BigNumParams<18> { + TEST_2048_PARAMS + } } -fn test_eq(params: BigNumParams) { - let a = unsafe { - RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) - }; - let b = unsafe { - RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) - }; - let c = unsafe { - RuntimeBigNum::__derive_from_seed(params, [2, 2, 3, 4]) - }; +#[test] +fn test_add() { + let params = BN254_Fq_Params::get_params(); - let modulus = a.modulus(); - let t0: U60Repr = (U60Repr::from(modulus.limbs)); - let t1: U60Repr = (U60Repr::from(b.limbs)); - let b_plus_modulus = RuntimeBigNum { limbs: U60Repr::into(t0 + t1), params }; + let a = unsafe{ RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) }; + let b = unsafe{ RuntimeBigNum::__derive_from_seed(params, [4, 5, 6, 7]) }; - assert((a == b) == true); - assert((a == b_plus_modulus) == true); - assert((c == b) == false); - assert((c == a) == false); -} + let one = RuntimeBigNum::one(params); -// 98760 -// 99689 -// 929 gates for a 2048 bit mul -fn test_mul(params: BigNumParams) { - let a = unsafe { - RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) - }; - let b = unsafe { - RuntimeBigNum::__derive_from_seed(params, [4, 5, 6, 7]) - }; + a.validate_in_range(); + a.validate_in_field(); + b.validate_in_range(); + b.validate_in_field(); - let c = (a + b) * (a + b); - let d = (a * a) + (b * b) + (a * b) + (a * b); + let mut c = a + b; + c = c + c; + let d = (a + b) * (one + one); assert(c == d); + + let e = one + one; + for i in 1..3 { + assert(e.limbs[i] == 0); + } + assert(e.limbs[0] == 2); } -fn test_add(params: BigNumParams) { - let a = unsafe { - RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) - }; - let b = unsafe { - RuntimeBigNum::__derive_from_seed(params, [4, 5, 6, 7]) - }; - let one = RuntimeBigNum::one(params); +/** + * @brief experimenting with macro madness and code generation to make some tests that apply to multiple BigNum parametrisations! + **/ +comptime fn make_test(f: StructDefinition, N: Quoted, typ: Quoted) -> Quoted { + let k = f.name(); + quote{ +impl $k { +#[test] +fn test_add() { + let params = $typ ::get_params(); + + let a = unsafe{ RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) }; + let b = unsafe{ RuntimeBigNum::__derive_from_seed(params, [4, 5, 6, 7]) }; + + let one: RuntimeBigNum<$N> = RuntimeBigNum::one(params); + a.validate_in_range(); a.validate_in_field(); b.validate_in_range(); @@ -113,13 +94,96 @@ fn test_add(params: BigNumParams) { assert(c == d); let e = one + one; - for i in 1..N { + for i in 1..$N { assert(e.limbs[i] == 0); } assert(e.limbs[0] == 2); } -fn test_div(params: BigNumParams) { +#[test] +fn test_sub() { + let params = $typ ::get_params(); + + // 0 - 1 should equal p - 1 + let mut a: RuntimeBigNum<$N> = RuntimeBigNum::new(params); + let mut b: RuntimeBigNum<$N> = RuntimeBigNum::one(params); + let mut expected = RuntimeBigNum { limbs: params.modulus, params }; + expected.limbs[0] -= 1; // p - 1 + + let result = a - b; + assert(result == expected); +} + +#[test] +fn test_sub_modulus_limit() { + let params = $typ ::get_params(); + // if we underflow, maximum result should be ... + // 0 - 1 = o-1 + // 0 - p = 0 + let mut a: RuntimeBigNum<$N> = RuntimeBigNum::new(params); + let mut b = RuntimeBigNum { limbs: params.modulus, params }; + let mut expected: RuntimeBigNum<$N> = RuntimeBigNum::new(params); + + let result = a - b; + assert(result == expected); +} + +#[test(should_fail_with = "call to assert_max_bit_size")] +fn test_sub_modulus_underflow() { + let params = $typ ::get_params(); + + // 0 - (p + 1) is smaller than p and should produce unsatisfiable constraints + let mut a: RuntimeBigNum<$N> = RuntimeBigNum::new(params); + let mut b = RuntimeBigNum { limbs: params.modulus, params }; + b.limbs[0] += 1; + let mut expected: RuntimeBigNum<$N> = RuntimeBigNum::one(params); + + let result = a - b; + + assert(result == expected); +} + +#[test] +fn test_add_modulus_limit() { + let params = $typ ::get_params(); + + // p + 2^{modulus_bits()} - 1 should be the maximum allowed value fed into an add operation + // when adding, if the result overflows the modulus, we conditionally subtract the modulus, producing 2^{254} - 1 + // this is the largest value that will satisfy the range check applied when constructing a bignum + let p: U60Repr<$N, 2> = U60Repr::from(params.modulus); + let one = unsafe{ U60Repr::one() }; + + let a = RuntimeBigNum { limbs: U60Repr::into(p), params }; + + let two_pow_modulus_bits_minus_one: U60Repr<$N, 2> = unsafe{ one.shl(a.modulus_bits()) - one }; + + let b = RuntimeBigNum { limbs: U60Repr::into(two_pow_modulus_bits_minus_one), params }; + + let result = a + b; + assert(result == b); +} + +#[test(should_fail_with = "call to assert_max_bit_size")] +fn test_add_modulus_overflow() { + let params = $typ ::get_params(); + + let p : U60Repr<$N, 2> = U60Repr::from(params.modulus); + let one = unsafe{ U60Repr::one() }; + + let a = RuntimeBigNum { limbs: U60Repr::into(p + one), params }; + + let mut two_pow_modulus_bits_minus_one: U60Repr<$N, 2> = unsafe{ one.shl(a.modulus_bits()) - one }; + + let b = RuntimeBigNum { limbs: U60Repr::into(two_pow_modulus_bits_minus_one), params }; + + let result = a + b; + assert(result == b); +} + +#[test] +fn test_mul() { + let params = $typ ::get_params(); + let a = unsafe { RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) }; @@ -127,21 +191,63 @@ fn test_div(params: BigNumParams) { RuntimeBigNum::__derive_from_seed(params, [4, 5, 6, 7]) }; - let c = a / b; - assert((b * c) == a); + let c = (a + b) * (a + b); + let d = (a * a) + (b * b) + (a * b) + (a * b); + assert(c == d); } -unconstrained fn test_invmod(params: BigNumParams) { - let u = RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]); - for _ in 0..1 { - let v = u.__invmod(); - let result = u.__mul(v); - let expected = RuntimeBigNum::one(params); - assert(result.limbs == expected.limbs); +#[test] +fn test_quadratic_expression() { + let params = $typ ::get_params(); + + for i in 0..32 { + let X1 = unsafe{ RuntimeBigNum::__derive_from_seed(params, [i as u8, 2, 3, 4]) }; + let Y1 = unsafe{ RuntimeBigNum::__derive_from_seed(params, [i as u8, i as u8, 6, 7]) }; + let Z1: RuntimeBigNum<$N> = RuntimeBigNum::one(params); + + let (_, YY_mul_2) = unsafe{ RuntimeBigNum::__compute_quadratic_expression(params, [[Y1]], [[false]], [[Y1, Y1]], [[false, false]], [], []) }; + let mut (_, XX_mul_3) = unsafe{ RuntimeBigNum::__compute_quadratic_expression( + params, + [[X1]], + [[false]], + [[X1, X1, X1]], + [[false, false, false]], + [], + [] + ) }; + let (_, D) = unsafe{ RuntimeBigNum::__compute_quadratic_expression(params, [[X1, X1]], [[false, false]], [[YY_mul_2]], [[false]], [], []) }; + let mut (_, X3) = unsafe{ RuntimeBigNum::__compute_quadratic_expression( + params, + [[XX_mul_3]], + [[false]], + [[XX_mul_3]], + [[false]], + [D, D], + [true, true] + ) }; + let (_, Y3) = unsafe{ RuntimeBigNum::__compute_quadratic_expression( + params, + [[XX_mul_3], [YY_mul_2]], + [[false], [true]], + [[D, X3], [YY_mul_2, YY_mul_2]], + [[false, true], [false, false]], + [], + [] + ) }; + // 3XX * (D - X3) - 8YYYY + + let (_, Z3) = unsafe{ RuntimeBigNum::__compute_quadratic_expression(params, [[Y1]], [[false]], [[Z1, Z1]], [[false, false]], [], []) }; + + X3.validate_in_field(); + Y3.validate_in_field(); + Z3.validate_in_field(); } } -unconstrained fn assert_is_not_equal(params: BigNumParams) { +#[test] +fn assert_is_not_equal() { + let params = $typ ::get_params(); + let a = unsafe { RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) }; @@ -152,7 +258,10 @@ unconstrained fn assert_is_not_equal(params: BigNumParams) { a.assert_is_not_equal(b); } -unconstrained fn assert_is_not_equal_fail(params: BigNumParams) { +#[test(should_fail_with = "asssert_is_not_equal fail")] +fn assert_is_not_equal_fail() { + let params = $typ ::get_params(); + let a = unsafe { RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) }; @@ -163,7 +272,10 @@ unconstrained fn assert_is_not_equal_fail(params: BigNumParams) { a.assert_is_not_equal(b); } -fn assert_is_not_equal_overloaded_lhs_fail(params: BigNumParams) { +#[test(should_fail_with = "asssert_is_not_equal fail")] +fn assert_is_not_equal_overloaded_lhs_fail() { + let params = $typ ::get_params(); + let a = unsafe { RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) }; @@ -173,13 +285,17 @@ fn assert_is_not_equal_overloaded_lhs_fail(params: BigNumParams) let modulus = params.modulus; - let t0: U60Repr = U60Repr::from(a.limbs); - let t1: U60Repr = U60Repr::from(modulus); + let t0: U60Repr<$N, 2> = U60Repr::from(a.limbs); + let t1: U60Repr<$N, 2> = U60Repr::from(modulus); let a_plus_modulus = RuntimeBigNum { limbs: U60Repr::into(t0 + t1), params }; + a_plus_modulus.assert_is_not_equal(b); } -fn assert_is_not_equal_overloaded_rhs_fail(params: BigNumParams) { +#[test(should_fail_with = "asssert_is_not_equal fail")] +fn assert_is_not_equal_overloaded_rhs_fail() { + let params = $typ ::get_params(); + let a = unsafe { RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) }; @@ -189,13 +305,17 @@ fn assert_is_not_equal_overloaded_rhs_fail(params: BigNumParams) let modulus = params.modulus; - let t0: U60Repr = U60Repr::from(b.limbs); - let t1: U60Repr = U60Repr::from(modulus); + let t0: U60Repr<$N, 2> = U60Repr::from(b.limbs); + let t1: U60Repr<$N, 2> = U60Repr::from(modulus); let b_plus_modulus = RuntimeBigNum { limbs: U60Repr::into(t0 + t1), params }; + a.assert_is_not_equal(b_plus_modulus); } -fn assert_is_not_equal_overloaded_fail(params: BigNumParams) { +#[test(should_fail_with = "asssert_is_not_equal fail")] +fn assert_is_not_equal_overloaded_fail() { + let params = $typ ::get_params(); + let a = unsafe { RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) }; @@ -205,228 +325,135 @@ fn assert_is_not_equal_overloaded_fail(params: BigNumParams) { let modulus = params.modulus; - let t0: U60Repr = U60Repr::from(a.limbs); - let t1: U60Repr = U60Repr::from(b.limbs); - let t2: U60Repr = U60Repr::from(modulus); + let t0: U60Repr<$N, 2> = U60Repr::from(a.limbs); + let t1: U60Repr<$N, 2> = U60Repr::from(b.limbs); + let t2: U60Repr<$N, 2> = U60Repr::from(modulus); + let a_plus_modulus = RuntimeBigNum { limbs: U60Repr::into(t0 + t2), params }; let b_plus_modulus = RuntimeBigNum { limbs: U60Repr::into(t1 + t2), params }; + a_plus_modulus.assert_is_not_equal(b_plus_modulus); } #[test] -fn test_eq_BN() { - let params = BN254_Fq_PARAMS; - test_eq(params); -} -#[test] -fn test_add_BN() { - let params = BN254_Fq_PARAMS; +fn test_derive() +{ + let params = $typ ::get_params(); - let mut a = RuntimeBigNum { limbs: params.modulus, params }; - let mut b = a; - let mut expected = a; - - a.limbs[0] -= 1; - b.limbs[0] -= 1; - expected.limbs[0] -= 2; - - let result = a + b; - assert(result == expected); + let a = RuntimeBigNum::derive_from_seed(params, "hello".as_bytes()); + let b = unsafe { + RuntimeBigNum::__derive_from_seed(params, "hello".as_bytes()) + }; + assert(a == b); } #[test] -fn test_sub_test_BN() { - let params = BN254_Fq_PARAMS; +fn test_eq() { + let params = $typ ::get_params(); - // 0 - 1 should equal p - 1 - let mut a = RuntimeBigNum::new(params); - let mut b = RuntimeBigNum::one(params); - let mut expected = RuntimeBigNum { limbs: params.modulus, params }; - expected.limbs[0] -= 1; // p - 1 + let a = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; + let b = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; + let c = unsafe { + RuntimeBigNum::__derive_from_seed(params, [2, 2, 3, 4]) + }; - let result = a - b; - assert(result == expected); -} + let modulus = a.modulus(); -#[test] -fn test_sub_modulus_limit() { - let params = BN254_Fq_PARAMS; + let t0: U60Repr<$N, 2> = (U60Repr::from(modulus.limbs)); + let t1: U60Repr<$N, 2> = (U60Repr::from(b.limbs)); - // if we underflow, maximum result should be ... - // 0 - 1 = o-1 - // 0 - p = 0 - let mut a= RuntimeBigNum::new(params); - let mut b= RuntimeBigNum { limbs: params.modulus, params }; - let mut expected= RuntimeBigNum::new(params); + let b_plus_modulus = RuntimeBigNum { limbs: U60Repr::into(t0 + t1), params }; - let result = a - b; - assert(result == expected); + assert((a == b) == true); + assert((a == b_plus_modulus) == true); + assert((c == b) == false); + assert((c == a) == false); } -#[test(should_fail_with = "call to assert_max_bit_size")] -fn test_sub_modulus_underflow() { - let params = BN254_Fq_PARAMS; - - // 0 - (p + 1) is smaller than p and should produce unsatisfiable constraints - let mut a = RuntimeBigNum::new(params); - let mut b = RuntimeBigNum { limbs: params.modulus, params }; - b.limbs[0] += 1; - let mut expected = RuntimeBigNum::one(params); - - let result = a - b; - - assert(result == expected); } - -#[test] -fn test_add_modulus_limit() { - let params = BN254_Fq_PARAMS; - - // p + 2^{254} - 1 should be the maximum allowed value fed into an add operation - // when adding, if the result overflows the modulus, we conditionally subtract the modulus, producing 2^{254} - 1 - // this is the largest value that will satisfy the range check applied when constructing a bignum - let p : U60Repr<3, 2> = U60Repr::from(params.modulus); - let two_pow_254_minus_1: U60Repr<3, 2> = U60Repr::from([0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x3fff]); - let a = RuntimeBigNum { limbs: U60Repr::into(p), params }; - let b = RuntimeBigNum { limbs: U60Repr::into(two_pow_254_minus_1), params }; - let result = a + b; - assert(result == b); } - -#[test(should_fail_with = "call to assert_max_bit_size")] -fn test_add_modulus_overflow() { - let params = BN254_Fq_PARAMS; - - //(2^{254} - 1) + (p - 1) = 2^{254} + p - // after subtracting modulus, result is 2^{254} will does not satisfy the range check applied when constructing a BigNum - let p : U60Repr<3, 2> = U60Repr::from(params.modulus); - let two_pow_254_minus_1: U60Repr<3, 2> = U60Repr::from([0xffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffff, 0x3fff]); - let one = U60Repr::from([1, 0, 0]); - let a = RuntimeBigNum { limbs: U60Repr::into(p + one), params }; - let b = RuntimeBigNum { limbs: U60Repr::into(two_pow_254_minus_1), params }; - let result = a + b; - assert(result == b); } -#[test] -fn test_mul_BN() { - let params = BN254_Fq_PARAMS; - test_mul(params); -} +#[make_test(quote{3},quote{BN254_Fq_Params})] +pub struct BNTests{} -#[test] -fn test_add_BN2() { - let params = BN254_Fq_PARAMS; - test_add(params); -} +#[make_test(quote{3},quote{Secp256k1_Fq_Params})] +pub struct Secp256K1FqTests{} -#[test] -fn test_div_BN() { - let params = BN254_Fq_PARAMS; - test_div(params); -} +#[make_test(quote{4},quote{BLS12_381_Fq_Params})] +pub struct BLS12_381FqTests{} -#[test] -unconstrained fn test_invmod_BN() { - let params = BN254_Fq_PARAMS; - test_invmod(params); -} +#[make_test(quote{18},quote{Test2048Params})] +pub struct Test2048Tests{} -#[test] -unconstrained fn test_assert_is_not_equal_BN() { - let params = BN254_Fq_PARAMS; - assert_is_not_equal(params); -} +#[make_test(quote{3},quote{BLS12_381_Fr_Params})] +pub struct BLS12_381_Fr_ParamsTests{} -#[test(should_fail_with = "asssert_is_not_equal fail")] -unconstrained fn test_assert_is_not_equal_fail_BN() { - let params = BN254_Fq_PARAMS; - assert_is_not_equal_fail(params); -} +#[make_test(quote{4},quote{BLS12_377_Fq_Params})] +pub struct BLS12_377_Fq_ParamsTests{} -#[test(should_fail_with = "asssert_is_not_equal fail")] -fn test_assert_is_not_equal_overloaded_lhs_fail_BN() { - let params = BN254_Fq_PARAMS; - assert_is_not_equal_overloaded_lhs_fail(params); -} +#[make_test(quote{3},quote{BLS12_377_Fr_Params})] +pub struct BLS12_377_Fr_ParamsTests{} -#[test(should_fail_with = "asssert_is_not_equal fail")] -fn test_assert_is_not_equal_overloaded_rhs_fail_BN() { - let params = BN254_Fq_PARAMS; - assert_is_not_equal_overloaded_rhs_fail(params); -} +// 98760 +// 99689 +// 929 gates for a 2048 bit mul -#[test(should_fail_with = "asssert_is_not_equal fail")] -fn test_assert_is_not_equal_overloaded_fail_BN() { - let params = BN254_Fq_PARAMS; - assert_is_not_equal_overloaded_fail(params); -} +fn test_div(params: BigNumParams) { + let a = unsafe { + RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) + }; + let b = unsafe { + RuntimeBigNum::__derive_from_seed(params, [4, 5, 6, 7]) + }; -#[test] -fn test_eq_2048() { - let params = get_2048_BN_params(); - test_eq(params); + let c = a / b; + assert((b * c) == a); } -#[test] -fn test_mul_2048() { - let params = get_2048_BN_params(); - test_mul(params); +unconstrained fn test_invmod(params: BigNumParams) { + let u = RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]); + for _ in 0..1 { + let v = u.__invmod(); + let result = u.__mul(v); + let expected = RuntimeBigNum::one(params); + assert(result.limbs == expected.limbs); + } } #[test] -fn test_add_2048() { - let params = get_2048_BN_params(); - test_add(params); +fn test_div_BN() { + let params = BN254_Fq_Params::get_params(); + test_div(params); } #[test] -unconstrained fn test_assert_is_not_equal_2048() { - let params = get_2048_BN_params(); - assert_is_not_equal(params); -} - -#[test(should_fail_with = "asssert_is_not_equal fail")] -unconstrained fn test_assert_is_not_equal_fail_2048() { - let params = get_2048_BN_params(); - assert_is_not_equal_fail(params); -} - -#[test(should_fail_with = "asssert_is_not_equal fail")] -fn test_assert_is_not_equal_overloaded_lhs_fail_2048() { - let params = get_2048_BN_params(); - assert_is_not_equal_overloaded_lhs_fail(params); -} - -#[test(should_fail_with = "asssert_is_not_equal fail")] -fn test_assert_is_not_equal_overloaded_rhs_fail_2048() { - let params = get_2048_BN_params(); - assert_is_not_equal_overloaded_rhs_fail(params); -} - -#[test(should_fail_with = "asssert_is_not_equal fail")] -fn test_assert_is_not_equal_overloaded_fail_2048() { - let params = get_2048_BN_params(); - assert_is_not_equal_overloaded_fail(params); +fn test_invmod_BN() { + let params = BN254_Fq_Params::get_params(); + unsafe { test_invmod(params) }; } // N.B. witness generation times make these tests take ~15 minutes each! Uncomment at your peril // #[test] // fn test_div_2048() { -// let params = get_2048_BN_params(); +// let params = get_2048_params(); // test_div(params); // } // N.B. witness generation times make these tests take ~15 minutes each! Uncomment at your peril // #[test] // fn test_invmod_2048() { -// let params = get_2048_BN_params(); +// let params = get_2048_params(); // test_invmod(params); // } #[test] fn test_2048_bit_quadratic_expression() { - let params = get_2048_BN_params(); + let params = TEST_2048_PARAMS; let a: [Field; 18] = [ 0x000000000000000000000000000000000083684820ff40795b8d9f1be2220cba, 0x0000000000000000000000000000000000d4924fbdc522b07b6cd0ef5508fd66, @@ -488,109 +515,12 @@ fn test_2048_bit_quadratic_expression() { 0x0000000000000000000000000000000000000000000000000000000000000058 ]; - let a= RuntimeBigNum { limbs: a, params }; - let b = RuntimeBigNum { limbs: b, params }; - let c = a * b; + let a_bn = RuntimeBigNum { limbs: a, params }; + let b_bn = RuntimeBigNum { limbs: b, params }; + let c = a_bn * b_bn; assert(c.limbs == c_expected); - a.validate_in_range(); - - RuntimeBigNum::evaluate_quadratic_expression(params, [[a]], [[false]], [[b]], [[false]], [c], [true]); -} - -#[test] -fn test_expressions() { - let params = BN254_Fq_PARAMS; - - let x: [Field; 6] = [ - 0x000000000000000000000000000000000083684820ff40795b8d9f1be2220cba, 0x0000000000000000000000000000000000d4924fbdc522b07b6cd0ef5508fd66, 0x0000000000000000000000000000000000d48f6c43c5930f3d70d6db09a48f4a, - 0x0000000000000000000000000000000000e7f72b2c0756704bea85be38352b34, 0x00000000000000000000000000000000000000000000000000000000b05d5ac5, 0 - ]; - - let y= RuntimeBigNum { - limbs: [ - 0x1, - 0x1, - 0x0 - ], params - }; - let z= RuntimeBigNum { - limbs: [ - 0x2, - 0x2, - 0x0 - ], params - }; - let yy = unsafe { - y.__add(y) - }; - - assert(yy.limbs == z.limbs); - - let uu= RuntimeBigNum { - limbs: [ - 0x0000000000000000000000000000000000b4a832748da6ad742a1fd81b787643, - 0x00000000000000000000000000000000009575f594e04080471712c1d7f18e89, - 0x000000000000000000000000000000000000000000000000000000000000063 - ], - params - }; - let vv= RuntimeBigNum { - limbs: [ - 0x0000000000000000000000000000000000b4aec2748da6ad742a1fd81b787643, - 0x00000000000000000000000000000000009575f594e0408047171a01d7f18e89, - 0x0000000000000000000000000000000000000000000000000000000000000062 - ], - params - }; - let w= RuntimeBigNum { - limbs: [ - 0x0000000000000000000000000000000000b4a832748da6ad742a1fd81b787643, - 0x00000000000000000000000000000000009575f594e04080471712c1d7f18e89, - 0x0000000000000000000000000000000000000000000000000000000000001f93 - ], - params - }; - let x= RuntimeBigNum { - limbs: [ - 0x0000000000000000000000000000000000b4aec2748da6ad742a1fd81b787643, - 0x00000000000000000000000000000000009575f594e0408047171a01d7f18e89, - 0x0000000000000000000000000000000000000000000000000000000000000f93 - ], - params - }; - let wx = unsafe { - w.__mul(x) - }; - let uv = unsafe { - uu.__mul(vv) - }; - let y = unsafe { - (uv.__add(wx)).__neg() - }; - let z = unsafe { - uv.__add(wx) - }; + a_bn.validate_in_range(); - RuntimeBigNum::evaluate_quadratic_expression( - params, - [[uu], [w]], - [[false], [false]], - [[vv], [x]], - [[false], [false]], - [z], - [true] - ); - RuntimeBigNum::evaluate_quadratic_expression( - params, - [[uu], [w]], - [[false], [false]], - [[vv], [x]], - [[false], [false]], - [y], - [false] - ); - - let wx_constrained = w * x; - assert(wx_constrained.limbs == wx.limbs); + RuntimeBigNum::evaluate_quadratic_expression(params, [[a_bn]], [[false]], [[b_bn]], [[false]], [c], [true]); } diff --git a/src/unconstrained_helpers.nr b/src/unconstrained_helpers.nr index 0d9dd581..fb9f29db 100644 --- a/src/unconstrained_helpers.nr +++ b/src/unconstrained_helpers.nr @@ -3,6 +3,18 @@ use crate::utils::split_bits; use crate::params::BigNumParams as P; +/** + * In this file: + * + * __validate_in_field_compute_borrow_flags + * __validate_gt_remainder + * __neg_with_flags + * __add_with_flags + * __sub_with_flags + * __barrett_reduction + * __tonelli_shanks_sqrt + */ + unconstrained pub(crate) fn __validate_in_field_compute_borrow_flags(params: P, val: [Field; N]) -> [bool; N] { let mut flags: [bool; N] = [false; N]; let modulus: [Field; N] = params.modulus; @@ -164,6 +176,13 @@ unconstrained pub(crate) fn __sub_with_flags(params: P, lhs: [Fie (result, carry_flags, borrow_flags, underflow) } +/** + * @brief BARRETT_REDUCTION_OVERFLOW_BITS defines how large an input to barrett reduction can be + * @details maximum value = modulus^2 <( x: [Field; 2 * N], redc_param: [Field; N], @@ -177,9 +196,23 @@ unconstrained pub(crate) fn __barrett_reduction( mulout[i + j] += x[i] * redc_param[j]; } } - mulout = split_bits::__normalize_limbs(mulout, 3 * N - 1); + mulout = split_bits::__normalize_limbs(mulout, 3 * N - 2); let mulout_u60: U60Repr = U60Repr::new(mulout); - let mut quotient_u60 = mulout_u60.shr((k + k)); + + // When we apply the barrett reduction, the maximum value of the output will be + // <= p * (1 + x/2^{2k}) + // where p = modulus, + // x = reduction input + // if x > p * p, we need k to be larger than modulus_bits() + // we hardcode k = 4, which means that the maximum value of x is approx. 16 * p * p + // this should be larger than most values put into `evaluate_quadratic_expression` + // TODO: try and detect cases where x might be too large at comptime + // N.B. BARRETT_REDUCTION_OVERFLOW_BITS affects how `redc_param` is generated. + // `redc_param` = 2^{modulus_bits() * 2 + BARRETT_REDUCTION_OVERFLOW_BITS} / modulus + // NOTE: very niche edge case error that we need to be aware of: + // N must be large enough to cover the modulus *plus* BARRETT_REDUCTION_OVERFLOW_BITS + // i.e. a 359-bit prime needs (I think) 4 limbs to represent or we may overflow when calling __barrett_reduction + let mut quotient_u60 = mulout_u60.shr((k + k + BARRETT_REDUCTION_OVERFLOW_BITS)); // N.B. we assume that the shifted quotient cannot exceed 2 times original bit size. // (partial_quotient should be just slightly larger than the modulus, we could probably represent with a size N+1 array) @@ -221,3 +254,154 @@ unconstrained pub(crate) fn __barrett_reduction( (q, r) } + + +// /** +// * @brief compute the log of the size of the primitive root +// * @details find the maximum value k where x^k = 1, where x = primitive root +// * This is needed for our Tonelli-Shanks sqrt algorithm +// **/ +// unconstrained fn primitive_root_log_size(self) -> u32 { +// let mut target: U60Repr = self.modulus_u60 - U60Repr::one(); +// let mut result: u32 = 0; +// for _ in 0..Params::modulus_bits() { +// let lsb_is_one = (target.limbs[0] & 1) == 1; +// if (!lsb_is_one) { +// result += 1; +// target.shr1(); +// } else { +// break; +// } +// } +// result +// } +// /** +// * @brief inner loop fn for `find_multiplive_generator` +// * @details recursive function to get around the lack of a `while` keyword +// **/ +// unconstrained fn recursively_find_multiplicative_generator( +// self, +// target: BigNum, +// p_minus_one_over_two: BigNum +// ) -> (bool, BigNum) { +// let exped = (self.__pow(target, p_minus_one_over_two)); +// let found = exped.__eq(self.__neg(BigNum::one())); +// let mut result: (bool, BigNum) = (found, target); +// if (!found) { +// let _target = unsafe { +// self.__add(target, BigNum::one()) +// }; +// result = self.recursively_find_multiplicative_generator(_target, p_minus_one_over_two); +// } +// result +// } +// /** +// * @brief find multiplicative generator `g` where `g` is the smallest value that is not a quadratic residue +// * i.e. smallest g where g^2 = -1 +// * @note WARNING if multiplicative generator does not exist, this function will enter an infinite loop! +// **/ +// unconstrained fn multiplicative_generator(self) -> BigNum { +// let mut target = BigNum::one(); +// let p_minus_one_over_two: U60Repr = (self.modulus_u60 - U60Repr::one()).shr(1); +// let p_minus_one_over_two: BigNum = BigNum::from_array(U60Repr::into(p_minus_one_over_two)); +// let (_, target) = self.recursively_find_multiplicative_generator(target, p_minus_one_over_two); +// target +// } +// unconstrained fn __tonelli_shanks_sqrt_inner_loop_check(self, t2m: BigNum, i: u32) -> u32 { +// let is_one = t2m.__eq(BigNum::one()); +// let mut result = i; +// if (!is_one) { +// let t2m = self.__mul(t2m, t2m); +// let i = i + 1; +// result = self.__tonelli_shanks_sqrt_inner_loop_check(t2m, i); +// } +// result +// } + +// /** +// * @brief compute a modular square root using the Tonelli-Shanks algorithm +// * @details only use for prime fields! Function may infinite loop if used for non-prime fields +// * @note this is unconstrained fn. To constrain a square root, validate that output^2 = self +// * TODO: create fn that constrains nonexistence of square root (i.e. find x where x^2 = -self) +// **/ +// unconstrained fn __tonelli_shanks_sqrt( +// self, +// input: BigNum +// ) -> std::option::Option> { +// // Tonelli-shanks algorithm begins by finding a field element Q and integer S, +// // such that (p - 1) = Q.2^{s} +// // We can compute the square root of a, by considering a^{(Q + 1) / 2} = R +// // Once we have found such an R, we have +// // R^{2} = a^{Q + 1} = a^{Q}a +// // If a^{Q} = 1, we have found our square root. +// // Otherwise, we have a^{Q} = t, where t is a 2^{s-1}'th root of unity. +// // This is because t^{2^{s-1}} = a^{Q.2^{s-1}}. +// // We know that (p - 1) = Q.w^{s}, therefore t^{2^{s-1}} = a^{(p - 1) / 2} +// // From Euler's criterion, if a is a quadratic residue, a^{(p - 1) / 2} = 1 +// // i.e. t^{2^{s-1}} = 1 +// // To proceed with computing our square root, we want to transform t into a smaller subgroup, +// // specifically, the (s-2)'th roots of unity. +// // We do this by finding some value b,such that +// // (t.b^2)^{2^{s-2}} = 1 and R' = R.b +// // Finding such a b is trivial, because from Euler's criterion, we know that, +// // for any quadratic non-residue z, z^{(p - 1) / 2} = -1 +// // i.e. z^{Q.2^{s-1}} = -1 +// // => z^Q is a 2^{s-1}'th root of -1 +// // => z^{Q^2} is a 2^{s-2}'th root of -1 +// // Since t^{2^{s-1}} = 1, we know that t^{2^{s - 2}} = -1 +// // => t.z^{Q^2} is a 2^{s - 2}'th root of unity. +// // We can iteratively transform t into ever smaller subgroups, until t = 1. +// // At each iteration, we need to find a new value for b, which we can obtain +// // by repeatedly squaring z^{Q} +// let one: U60Repr = unsafe { +// U60Repr::one() +// }; +// let primitive_root_log_size = self.primitive_root_log_size(); +// let mut Q = (self.modulus_u60 - one).shr(primitive_root_log_size - 1); +// let mut Q_minus_one_over_two = (Q - one).shr(2); +// let mut Q_minus_one_over_two = BigNum::from_array(U60Repr::into(Q_minus_one_over_two)); +// let mut z = self.multiplicative_generator(); // the generator is a non-residue +// let mut b = self.__pow(input, Q_minus_one_over_two); +// let mut r = self.__mul(input, b); +// let mut t = self.__mul(r, b); +// let mut check: BigNum = t; +// for _ in 0..primitive_root_log_size - 1 { +// check = self.__mul(check, check); +// } +// let mut found_root = false; +// if (check.__eq(BigNum::one()) == false) {} else { +// let mut t1 = self.__pow(z, Q_minus_one_over_two); +// let mut t2 = self.__mul(t1, z); +// let mut c = self.__mul(t2, t1); +// let mut m: u32 = primitive_root_log_size; +// // tonelli shanks inner 1 +// // (if t2m == 1) then skip +// // else increase i and square t2m and go again +// // algorithm runtime should only be max the number of bits in modulus +// let num_bits: u32 = Params::modulus_bits(); +// for _ in 0..num_bits { +// if (t.__eq(BigNum::one())) { +// found_root = true; +// break; +// } +// let mut t2m = t; +// // while loop time +// let i = self.__tonelli_shanks_sqrt_inner_loop_check(t2m, 0); +// let mut j = m - i - 1; +// b = c; +// for _ in 0..j { // how big +// if (j == 0) { +// break; +// } +// b = self.__mul(b, b); +// //j -= 1; +// } +// c = self.__mul(b, b); +// t = self.__mul(t, c); +// r = self.__mul(r, b); +// m = i; +// } +// } +// let mut result = std::option::Option { _value: r, _is_some: found_root }; +// result +// } diff --git a/src/unconstrained_ops.nr b/src/unconstrained_ops.nr index f2650abf..580d7399 100644 --- a/src/unconstrained_ops.nr +++ b/src/unconstrained_ops.nr @@ -4,6 +4,26 @@ use crate::utils::split_bits; use crate::params::BigNumParams as P; use crate::unconstrained_helpers::__barrett_reduction; +/** + * In this file: + * + * __one + * __derive_from_seed + * __eq + * __is_zero + * __neg + * __add + * __sub + * __mul_with_quotient + * __mul + * __div + * __udiv_mod + * __invmod + * __pow + * __batch_invert + * __batch_invert_slice + */ + unconstrained pub(crate) fn __one() -> [Field; N] { let mut limbs: [Field; N] = [0; N]; limbs[0] = 1; @@ -11,7 +31,21 @@ unconstrained pub(crate) fn __one() -> [Field; N] { } unconstrained pub(crate) fn __derive_from_seed(params: P, seed: [u8; SeedBytes]) -> [Field; N] { - let mut rolling_seed = seed; + let mut rolling_hash_fields: [Field; (SeedBytes / 31) + 1] = [0; (SeedBytes / 31) + 1]; + let mut seed_ptr = 0; + for i in 0..(SeedBytes / 31) + 1 { + let mut packed: Field = 0; + for _ in 0..31 { + if (seed_ptr < SeedBytes) { + packed *= 256; + packed += seed[seed_ptr] as Field; + seed_ptr += 1; + } + } + rolling_hash_fields[i] = packed; + } + let compressed = std::hash::poseidon2::Poseidon2::hash(rolling_hash_fields, (SeedBytes / 31) + 1); + let mut rolling_hash: [Field; 2] = [compressed, 0]; let mut to_reduce: [Field; 2 * N] = [0; 2 * N]; @@ -30,7 +64,8 @@ unconstrained pub(crate) fn __derive_from_seed(p } for i in 0..(N - 1) { - let hash: [u8; 32] = std::hash::sha256(rolling_seed); + let hash = std::hash::poseidon2::Poseidon2::hash(rolling_hash, 2); + let hash : [u8; 30] = hash.to_le_bytes(); let mut lo: Field = 0; let mut hi: Field = 0; for j in 0..15 { @@ -44,11 +79,12 @@ unconstrained pub(crate) fn __derive_from_seed(p } to_reduce[2 * i] = lo; to_reduce[2 * i + 1] = hi; - rolling_seed[0] += 1; + rolling_hash[1] += 1; } { - let hash: [u8; 32] = std::hash::sha256(rolling_seed); + let hash = std::hash::poseidon2::Poseidon2::hash(rolling_hash, 2); + let hash : [u8; 30] = hash.to_le_bytes(); let mut hi: Field = 0; for j in 0..(last_limb_bytes - 1) { hi *= 256; @@ -133,10 +169,11 @@ unconstrained pub(crate) fn __mul_with_quotient(params: P, lhs: [ mul[i + j] += lhs[i] * rhs[j]; } } + let to_reduce = split_bits::__normalize_limbs(mul, 2 * N); let modulus_bits_getter = params.modulus_bits_getter; let modulus_bits = modulus_bits_getter(); let (q, r) = __barrett_reduction( - split_bits::__normalize_limbs(mul, 2 * N), + to_reduce, params.redc_param, modulus_bits, params.modulus, diff --git a/src/utils/map.nr b/src/utils/map.nr index 9d95e2d1..698e5f46 100644 --- a/src/utils/map.nr +++ b/src/utils/map.nr @@ -1,10 +1,9 @@ // Copied from std::array, because I couldn't figure out how to import the `map` method of the weird trait for an array. // And the reason I wanted direct access to it, is because I couldn't figure out how to implement a double map. pub(crate) fn map(arr: [T; N], f: fn[Env](T) -> U) -> [U; N] { - let first_elem = f(arr[0]); - let mut ret = [first_elem; N]; + let mut ret: [U; N] = std::mem::zeroed(); - for i in 1..arr.len() { + for i in 0..arr.len() { ret[i] = f(arr[i]); } From 9e73b245cc3f6d28a738200cd914cd537d8b941f Mon Sep 17 00:00:00 2001 From: Michael Connor Date: Mon, 21 Oct 2024 17:42:06 +0100 Subject: [PATCH 10/14] fix merge mistake --- src/runtime_bignum_test.nr | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/runtime_bignum_test.nr b/src/runtime_bignum_test.nr index b2de3a34..f88c3ded 100644 --- a/src/runtime_bignum_test.nr +++ b/src/runtime_bignum_test.nr @@ -40,11 +40,6 @@ impl BigNumParamsGetter<18> for Test2048Params { TEST_2048_PARAMS } } -impl NotRuntimeBigNumParamsTrait<18> for Test2048Params { - fn modulus_bits() -> u32 { - 2048 - } -} /** * @brief experimenting with macro madness and code generation to make some tests that apply to multiple BigNum parametrisations! From c0dcaf7d56e5e1788d5644edb8b272cbc8792a3a Mon Sep 17 00:00:00 2001 From: Michael Connor Date: Mon, 21 Oct 2024 21:08:52 +0100 Subject: [PATCH 11/14] add sqrt code from zac --- src/bignum.nr | 21 +++- src/runtime_bignum.nr | 21 +++- src/runtime_bignum_test.nr | 28 ++++- src/unconstrained_helpers.nr | 219 +++++++++++------------------------ src/unconstrained_ops.nr | 93 ++++++++++++++- 5 files changed, 224 insertions(+), 158 deletions(-) diff --git a/src/bignum.nr b/src/bignum.nr index b5a0fdbe..be4d59bd 100644 --- a/src/bignum.nr +++ b/src/bignum.nr @@ -2,12 +2,12 @@ use crate::utils::map::map; use crate::params::BigNumParamsGetter; use crate::constrained_ops::{ - derive_from_seed, conditional_select, assert_is_not_equal, eq, validate_in_field, validate_in_range, neg, add, sub, - mul, div, udiv_mod, udiv, umod + derive_from_seed, conditional_select, assert_is_not_equal, eq, validate_in_field, validate_in_range, + neg, add, sub, mul, div, udiv_mod, udiv, umod }; use crate::unconstrained_ops::{ __derive_from_seed, __eq, __is_zero, __neg, __add, __sub, __mul, __div, __udiv_mod, __invmod, __pow, - __batch_invert, __batch_invert_slice + __batch_invert, __batch_invert_slice, __tonelli_shanks_sqrt }; use crate::expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}; use crate::serialization::{from_be_bytes, to_le_bytes}; @@ -51,6 +51,8 @@ pub(crate) trait BigNumTrait { unconstrained fn __batch_invert(to_invert: [Self; M]) -> [Self; M]; unconstrained fn __batch_invert_slice(to_invert: [Self]) -> [Self]; + unconstrained fn __tonelli_shanks_sqrt(self) -> std::option::Option; + unconstrained fn __compute_quadratic_expression( lhs: [[Self; LHS_N]; NUM_PRODUCTS], lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], @@ -216,6 +218,19 @@ impl BigNumTrait for BigNum where Params: BigN __batch_invert_slice(params, x.map(|bn| Self::get_limbs(bn))).map(|limbs| Self { limbs }) } + unconstrained fn __tonelli_shanks_sqrt(self) -> std::option::Option { + let params = Params::get_params(); + let maybe_limbs = unsafe { + __tonelli_shanks_sqrt(params, self.limbs) + }; + let result: std::option::Option = if maybe_limbs.is_some() { + std::option::Option::some(Self { limbs: maybe_limbs.unwrap_unchecked() }) + } else { + std::option::Option::none() + }; + result + } + unconstrained fn __compute_quadratic_expression( lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS], lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS], diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index f42931e8..b3d4499e 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -3,12 +3,12 @@ use crate::utils::map::map; use crate::params::BigNumParams; use crate::constrained_ops::{ - derive_from_seed, conditional_select, assert_is_not_equal, eq, validate_in_field, validate_in_range, neg, add, sub, - mul, div, udiv_mod, udiv, umod + derive_from_seed, conditional_select, assert_is_not_equal, eq, validate_in_field, validate_in_range, + neg, add, sub, mul, div, udiv_mod, udiv, umod }; use crate::unconstrained_ops::{ __derive_from_seed, __eq, __is_zero, __neg, __add, __sub, __mul, __div, __udiv_mod, __invmod, __pow, - __batch_invert, __batch_invert_slice + __batch_invert, __batch_invert_slice, __tonelli_shanks_sqrt }; use crate::expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}; use crate::serialization::{from_be_bytes, to_le_bytes}; @@ -54,6 +54,8 @@ pub(crate) trait RuntimeBigNumTrait { fn __batch_invert(x: [Self; M]) -> [Self; M]; unconstrained fn __batch_invert_slice(to_invert: [Self]) -> [Self]; + unconstrained fn __tonelli_shanks_sqrt(self) -> std::option::Option; + fn __compute_quadratic_expression( params: BigNumParams, lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS], @@ -268,6 +270,19 @@ impl RuntimeBigNumTrait for RuntimeBigNum { all_limbs.map(|limbs| Self { limbs, params }) } + unconstrained fn __tonelli_shanks_sqrt(self) -> std::option::Option { + let params = self.params; + let maybe_limbs = unsafe { + __tonelli_shanks_sqrt(params, self.limbs) + }; + let result: std::option::Option = if maybe_limbs.is_some() { + std::option::Option::some(Self { limbs: maybe_limbs.unwrap_unchecked(), params }) + } else { + std::option::Option::none() + }; + result + } + // UNCONSTRAINED! (Hence `__` prefix). fn __compute_quadratic_expression( params: BigNumParams, diff --git a/src/runtime_bignum_test.nr b/src/runtime_bignum_test.nr index f88c3ded..9f3bee0f 100644 --- a/src/runtime_bignum_test.nr +++ b/src/runtime_bignum_test.nr @@ -1,6 +1,6 @@ use crate::utils::u60_representation::U60Repr; use crate::runtime_bignum::RuntimeBigNum; -use crate::params::{ BigNumParams, BigNumParamsGetter }; +use crate::params::{BigNumParams, BigNumParamsGetter}; use crate::fields::bn254Fq::BN254_Fq_Params; use crate::fields::secp256k1Fq::Secp256k1_Fq_Params; @@ -410,7 +410,9 @@ fn test_div_BN() { #[test] fn test_invmod_BN() { let params = BN254_Fq_Params::get_params(); - unsafe { test_invmod(params) }; + unsafe { + test_invmod(params) + }; } // N.B. witness generation times make these tests take ~15 minutes each! Uncomment at your peril @@ -500,3 +502,25 @@ fn test_2048_bit_quadratic_expression() { RuntimeBigNum::evaluate_quadratic_expression(params, [[a_bn]], [[false]], [[b_bn]], [[false]], [c], [true]); } + +#[test] +fn test_sqrt_BN() { + let params = BN254_Fq_Params::get_params(); + + let x = RuntimeBigNum { limbs: [144, 0, 0], params }; + // let y = RuntimeBigNum { limbs: [143, 0, 0], params }; + + let maybe_sqrt_x = unsafe { x.__tonelli_shanks_sqrt() }; + // let maybe_sqrt_y = unsafe { y.__tonelli_shanks_sqrt() }; + + // println(f"maybe_sqrt_x: {maybe_sqrt_x}"); + // println(f"maybe_sqrt_y: {maybe_sqrt_y}"); + + // let sqrt_x = maybe_sqrt_x.unwrap(); + // println(f"sqrt_x: {sqrt_x}"); + + assert(x == x); + + // assert(maybe_sqrt_x.unwrap() == RuntimeBigNum { limbs: [12, 0, 0], params }); + // assert(maybe_sqrt_y.is_none()); +} \ No newline at end of file diff --git a/src/unconstrained_helpers.nr b/src/unconstrained_helpers.nr index fb9f29db..55d7c772 100644 --- a/src/unconstrained_helpers.nr +++ b/src/unconstrained_helpers.nr @@ -2,6 +2,8 @@ use crate::utils::u60_representation::U60Repr; use crate::utils::split_bits; use crate::params::BigNumParams as P; +use crate::unconstrained_ops::{ __one, __eq, __neg, __add, __mul, __pow }; + /** * In this file: @@ -255,153 +257,72 @@ unconstrained pub(crate) fn __barrett_reduction( (q, r) } +/** +* @brief compute the log of the size of the primitive root +* @details find the maximum value k where x^k = 1, where x = primitive root +* This is needed for our Tonelli-Shanks sqrt algorithm +**/ +unconstrained pub(crate) fn __primitive_root_log_size(params: P) -> u32 { + let mut target: U60Repr = params.modulus_u60 - U60Repr::one(); + let mut result: u32 = 0; + let modulus_bits_getter = params.modulus_bits_getter; + let modulus_bits = modulus_bits_getter(); + for _ in 0..modulus_bits { + let lsb_is_one = (target.limbs[0] & 1) == 1; + if (!lsb_is_one) { + result += 1; + target.shr1(); + } else { + break; + } + } + result +} + +/** +* @brief inner loop fn for `find_multiplive_generator` +* @details recursive function to get around the lack of a `while` keyword +**/ +unconstrained fn __recursively_find_multiplicative_generator( + params: P, + target: [Field; N], + p_minus_one_over_two: [Field; N] +) -> (bool, [Field; N]) { + let exped = __pow(params, target, p_minus_one_over_two); + let one: [Field; N] = __one(); + let neg_one = __neg(params, one); + let found = __eq(exped, neg_one); + let mut result: (bool, [Field; N]) = (found, target); + if (!found) { + let _target = unsafe { + __add(params, target, one) + }; + result = __recursively_find_multiplicative_generator(params, _target, p_minus_one_over_two); + } + result +} + +/** +* @brief find multiplicative generator `g` where `g` is the smallest value that is not a quadratic residue +* i.e. smallest g where g^2 = -1 +* @note WARNING if multiplicative generator does not exist, this function will enter an infinite loop! +**/ +unconstrained pub(crate) fn __multiplicative_generator(params: P) -> [Field; N] { + let mut target: [Field; N] = __one(); + let p_minus_one_over_two: U60Repr = (params.modulus_u60 - U60Repr::one()).shr(1); + let p_minus_one_over_two: [Field; N] = U60Repr::into(p_minus_one_over_two); + let (_, target) = __recursively_find_multiplicative_generator(params, target, p_minus_one_over_two); + target +} -// /** -// * @brief compute the log of the size of the primitive root -// * @details find the maximum value k where x^k = 1, where x = primitive root -// * This is needed for our Tonelli-Shanks sqrt algorithm -// **/ -// unconstrained fn primitive_root_log_size(self) -> u32 { -// let mut target: U60Repr = self.modulus_u60 - U60Repr::one(); -// let mut result: u32 = 0; -// for _ in 0..Params::modulus_bits() { -// let lsb_is_one = (target.limbs[0] & 1) == 1; -// if (!lsb_is_one) { -// result += 1; -// target.shr1(); -// } else { -// break; -// } -// } -// result -// } -// /** -// * @brief inner loop fn for `find_multiplive_generator` -// * @details recursive function to get around the lack of a `while` keyword -// **/ -// unconstrained fn recursively_find_multiplicative_generator( -// self, -// target: BigNum, -// p_minus_one_over_two: BigNum -// ) -> (bool, BigNum) { -// let exped = (self.__pow(target, p_minus_one_over_two)); -// let found = exped.__eq(self.__neg(BigNum::one())); -// let mut result: (bool, BigNum) = (found, target); -// if (!found) { -// let _target = unsafe { -// self.__add(target, BigNum::one()) -// }; -// result = self.recursively_find_multiplicative_generator(_target, p_minus_one_over_two); -// } -// result -// } -// /** -// * @brief find multiplicative generator `g` where `g` is the smallest value that is not a quadratic residue -// * i.e. smallest g where g^2 = -1 -// * @note WARNING if multiplicative generator does not exist, this function will enter an infinite loop! -// **/ -// unconstrained fn multiplicative_generator(self) -> BigNum { -// let mut target = BigNum::one(); -// let p_minus_one_over_two: U60Repr = (self.modulus_u60 - U60Repr::one()).shr(1); -// let p_minus_one_over_two: BigNum = BigNum::from_array(U60Repr::into(p_minus_one_over_two)); -// let (_, target) = self.recursively_find_multiplicative_generator(target, p_minus_one_over_two); -// target -// } -// unconstrained fn __tonelli_shanks_sqrt_inner_loop_check(self, t2m: BigNum, i: u32) -> u32 { -// let is_one = t2m.__eq(BigNum::one()); -// let mut result = i; -// if (!is_one) { -// let t2m = self.__mul(t2m, t2m); -// let i = i + 1; -// result = self.__tonelli_shanks_sqrt_inner_loop_check(t2m, i); -// } -// result -// } - -// /** -// * @brief compute a modular square root using the Tonelli-Shanks algorithm -// * @details only use for prime fields! Function may infinite loop if used for non-prime fields -// * @note this is unconstrained fn. To constrain a square root, validate that output^2 = self -// * TODO: create fn that constrains nonexistence of square root (i.e. find x where x^2 = -self) -// **/ -// unconstrained fn __tonelli_shanks_sqrt( -// self, -// input: BigNum -// ) -> std::option::Option> { -// // Tonelli-shanks algorithm begins by finding a field element Q and integer S, -// // such that (p - 1) = Q.2^{s} -// // We can compute the square root of a, by considering a^{(Q + 1) / 2} = R -// // Once we have found such an R, we have -// // R^{2} = a^{Q + 1} = a^{Q}a -// // If a^{Q} = 1, we have found our square root. -// // Otherwise, we have a^{Q} = t, where t is a 2^{s-1}'th root of unity. -// // This is because t^{2^{s-1}} = a^{Q.2^{s-1}}. -// // We know that (p - 1) = Q.w^{s}, therefore t^{2^{s-1}} = a^{(p - 1) / 2} -// // From Euler's criterion, if a is a quadratic residue, a^{(p - 1) / 2} = 1 -// // i.e. t^{2^{s-1}} = 1 -// // To proceed with computing our square root, we want to transform t into a smaller subgroup, -// // specifically, the (s-2)'th roots of unity. -// // We do this by finding some value b,such that -// // (t.b^2)^{2^{s-2}} = 1 and R' = R.b -// // Finding such a b is trivial, because from Euler's criterion, we know that, -// // for any quadratic non-residue z, z^{(p - 1) / 2} = -1 -// // i.e. z^{Q.2^{s-1}} = -1 -// // => z^Q is a 2^{s-1}'th root of -1 -// // => z^{Q^2} is a 2^{s-2}'th root of -1 -// // Since t^{2^{s-1}} = 1, we know that t^{2^{s - 2}} = -1 -// // => t.z^{Q^2} is a 2^{s - 2}'th root of unity. -// // We can iteratively transform t into ever smaller subgroups, until t = 1. -// // At each iteration, we need to find a new value for b, which we can obtain -// // by repeatedly squaring z^{Q} -// let one: U60Repr = unsafe { -// U60Repr::one() -// }; -// let primitive_root_log_size = self.primitive_root_log_size(); -// let mut Q = (self.modulus_u60 - one).shr(primitive_root_log_size - 1); -// let mut Q_minus_one_over_two = (Q - one).shr(2); -// let mut Q_minus_one_over_two = BigNum::from_array(U60Repr::into(Q_minus_one_over_two)); -// let mut z = self.multiplicative_generator(); // the generator is a non-residue -// let mut b = self.__pow(input, Q_minus_one_over_two); -// let mut r = self.__mul(input, b); -// let mut t = self.__mul(r, b); -// let mut check: BigNum = t; -// for _ in 0..primitive_root_log_size - 1 { -// check = self.__mul(check, check); -// } -// let mut found_root = false; -// if (check.__eq(BigNum::one()) == false) {} else { -// let mut t1 = self.__pow(z, Q_minus_one_over_two); -// let mut t2 = self.__mul(t1, z); -// let mut c = self.__mul(t2, t1); -// let mut m: u32 = primitive_root_log_size; -// // tonelli shanks inner 1 -// // (if t2m == 1) then skip -// // else increase i and square t2m and go again -// // algorithm runtime should only be max the number of bits in modulus -// let num_bits: u32 = Params::modulus_bits(); -// for _ in 0..num_bits { -// if (t.__eq(BigNum::one())) { -// found_root = true; -// break; -// } -// let mut t2m = t; -// // while loop time -// let i = self.__tonelli_shanks_sqrt_inner_loop_check(t2m, 0); -// let mut j = m - i - 1; -// b = c; -// for _ in 0..j { // how big -// if (j == 0) { -// break; -// } -// b = self.__mul(b, b); -// //j -= 1; -// } -// c = self.__mul(b, b); -// t = self.__mul(t, c); -// r = self.__mul(r, b); -// m = i; -// } -// } -// let mut result = std::option::Option { _value: r, _is_some: found_root }; -// result -// } +unconstrained pub(crate) fn __tonelli_shanks_sqrt_inner_loop_check(params: P, t2m: [Field; N], i: u32) -> u32 { + let one: [Field; N] = __one(); + let is_one = __eq(t2m, one); + let mut result = i; + if (!is_one) { + let t2m = __mul(params, t2m, t2m); + let i = i + 1; + result = __tonelli_shanks_sqrt_inner_loop_check(params, t2m, i); + } + result +} diff --git a/src/unconstrained_ops.nr b/src/unconstrained_ops.nr index 580d7399..7dafac61 100644 --- a/src/unconstrained_ops.nr +++ b/src/unconstrained_ops.nr @@ -2,7 +2,7 @@ use crate::utils::u60_representation::U60Repr; use crate::utils::split_bits; use crate::params::BigNumParams as P; -use crate::unconstrained_helpers::__barrett_reduction; +use crate::unconstrained_helpers::{__barrett_reduction, __primitive_root_log_size, __multiplicative_generator, __tonelli_shanks_sqrt_inner_loop_check}; /** * In this file: @@ -325,3 +325,94 @@ unconstrained pub(crate) fn __batch_invert_slice(params: P, x: [[ } result } + +/** +* @brief compute a modular square root using the Tonelli-Shanks algorithm +* @details only use for prime fields! Function may infinite loop if used for non-prime fields +* @note this is unconstrained fn. To constrain a square root, validate that output^2 = self +* TODO: create fn that constrains nonexistence of square root (i.e. find x where x^2 = -self) +**/ +unconstrained pub(crate) fn __tonelli_shanks_sqrt( + params: P, + input: [Field; N] +) -> std::option::Option<[Field; N]> { + // Tonelli-shanks algorithm begins by finding a field element Q and integer S, + // such that (p - 1) = Q.2^{s} + // We can compute the square root of a, by considering a^{(Q + 1) / 2} = R + // Once we have found such an R, we have + // R^{2} = a^{Q + 1} = a^{Q}a + // If a^{Q} = 1, we have found our square root. + // Otherwise, we have a^{Q} = t, where t is a 2^{s-1}'th root of unity. + // This is because t^{2^{s-1}} = a^{Q.2^{s-1}}. + // We know that (p - 1) = Q.w^{s}, therefore t^{2^{s-1}} = a^{(p - 1) / 2} + // From Euler's criterion, if a is a quadratic residue, a^{(p - 1) / 2} = 1 + // i.e. t^{2^{s-1}} = 1 + // To proceed with computing our square root, we want to transform t into a smaller subgroup, + // specifically, the (s-2)'th roots of unity. + // We do this by finding some value b,such that + // (t.b^2)^{2^{s-2}} = 1 and R' = R.b + // Finding such a b is trivial, because from Euler's criterion, we know that, + // for any quadratic non-residue z, z^{(p - 1) / 2} = -1 + // i.e. z^{Q.2^{s-1}} = -1 + // => z^Q is a 2^{s-1}'th root of -1 + // => z^{Q^2} is a 2^{s-2}'th root of -1 + // Since t^{2^{s-1}} = 1, we know that t^{2^{s - 2}} = -1 + // => t.z^{Q^2} is a 2^{s - 2}'th root of unity. + // We can iteratively transform t into ever smaller subgroups, until t = 1. + // At each iteration, we need to find a new value for b, which we can obtain + // by repeatedly squaring z^{Q} + let one_u60: U60Repr = unsafe { + U60Repr::one() + }; + let primitive_root_log_size = __primitive_root_log_size(params); + let mut Q = (params.modulus_u60 - one_u60).shr(primitive_root_log_size - 1); + let Q_minus_one_over_two_u60 = (Q - one_u60).shr(2); + let Q_minus_one_over_two: [Field; N] = U60Repr::into(Q_minus_one_over_two_u60); + let mut z = __multiplicative_generator(params); // the generator is a non-residue + let mut b = __pow(params, input, Q_minus_one_over_two); + let mut r = __mul(params, input, b); + let mut t = __mul(params, r, b); + let mut check: [Field; N] = t; + for _ in 0..primitive_root_log_size - 1 { + check = __mul(params, check, check); + } + let mut found_root = false; + let one: [Field; N] = __one::(); + if (__eq(check, one) == false) {} else { + let mut t1 = __pow(params, z, Q_minus_one_over_two); + let mut t2 = __mul(params, t1, z); + let mut c = __mul(params, t2, t1); + let mut m: u32 = primitive_root_log_size; + // tonelli shanks inner 1 + // (if t2m == 1) then skip + // else increase i and square t2m and go again + // algorithm runtime should only be max the number of bits in modulus + let modulus_bits_getter = params.modulus_bits_getter; + let modulus_bits = modulus_bits_getter(); + let num_bits: u32 = modulus_bits; + for _ in 0..num_bits { + if (__eq(t, one)) { + found_root = true; + break; + } + let mut t2m = t; + // while loop time + let i = __tonelli_shanks_sqrt_inner_loop_check(params, t2m, 0); + let mut j = m - i - 1; + b = c; + for _ in 0..j { // how big + if (j == 0) { + break; + } + b = __mul(params, b, b); + //j -= 1; + } + c = __mul(params, b, b); + t = __mul(params, t, c); + r = __mul(params, r, b); + m = i; + } + } + let mut result = std::option::Option { _value: r, _is_some: found_root }; + result +} From 33611026357627f3e11005120e14b3f271c1b8e2 Mon Sep 17 00:00:00 2001 From: Michael Connor Date: Mon, 21 Oct 2024 21:54:47 +0100 Subject: [PATCH 12/14] fix sqrt test --- src/bignum.nr | 7 +------ src/runtime_bignum.nr | 11 ++++++----- src/runtime_bignum_test.nr | 17 ++++------------- 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/src/bignum.nr b/src/bignum.nr index be4d59bd..f3d45d49 100644 --- a/src/bignum.nr +++ b/src/bignum.nr @@ -223,12 +223,7 @@ impl BigNumTrait for BigNum where Params: BigN let maybe_limbs = unsafe { __tonelli_shanks_sqrt(params, self.limbs) }; - let result: std::option::Option = if maybe_limbs.is_some() { - std::option::Option::some(Self { limbs: maybe_limbs.unwrap_unchecked() }) - } else { - std::option::Option::none() - }; - result + maybe_limbs.map(|limbs| Self { limbs }) } unconstrained fn __compute_quadratic_expression( diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index b3d4499e..cf0d283a 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -54,7 +54,7 @@ pub(crate) trait RuntimeBigNumTrait { fn __batch_invert(x: [Self; M]) -> [Self; M]; unconstrained fn __batch_invert_slice(to_invert: [Self]) -> [Self]; - unconstrained fn __tonelli_shanks_sqrt(self) -> std::option::Option; + unconstrained fn __tonelli_shanks_sqrt(self) -> (bool, Self); fn __compute_quadratic_expression( params: BigNumParams, @@ -270,15 +270,16 @@ impl RuntimeBigNumTrait for RuntimeBigNum { all_limbs.map(|limbs| Self { limbs, params }) } - unconstrained fn __tonelli_shanks_sqrt(self) -> std::option::Option { + // @dev We intentionally don't use std::option::Option, because the Option::none() case doesn't propagate the `params`, so the code breaks. Specifically, the code stops evaluating modulus_bits = self.params.modulus_bits_getter() as constant, which then breaks calls to `validate_in_range()` (e.g. via calls to `==` on `self`), because `validate_in_range` calls `assert_max_bit_size` on a value derived from `modulus_bits`. I'm not sure why it stops evaluating the getter's return value as constant if we return a std::Option, really. + unconstrained fn __tonelli_shanks_sqrt(self) -> (bool, Self) { let params = self.params; let maybe_limbs = unsafe { __tonelli_shanks_sqrt(params, self.limbs) }; - let result: std::option::Option = if maybe_limbs.is_some() { - std::option::Option::some(Self { limbs: maybe_limbs.unwrap_unchecked(), params }) + let result: (bool, Self) = if maybe_limbs.is_some() { + (true, Self { limbs: maybe_limbs.unwrap_unchecked(), params }) } else { - std::option::Option::none() + (false, Self::new(params)) }; result } diff --git a/src/runtime_bignum_test.nr b/src/runtime_bignum_test.nr index 9f3bee0f..2ba36137 100644 --- a/src/runtime_bignum_test.nr +++ b/src/runtime_bignum_test.nr @@ -507,20 +507,11 @@ fn test_2048_bit_quadratic_expression() { fn test_sqrt_BN() { let params = BN254_Fq_Params::get_params(); - let x = RuntimeBigNum { limbs: [144, 0, 0], params }; - // let y = RuntimeBigNum { limbs: [143, 0, 0], params }; + let x = RuntimeBigNum { limbs: [9, 0, 0], params }; - let maybe_sqrt_x = unsafe { x.__tonelli_shanks_sqrt() }; - // let maybe_sqrt_y = unsafe { y.__tonelli_shanks_sqrt() }; + let (_, maybe_sqrt_x) = unsafe { x.__tonelli_shanks_sqrt() }; - // println(f"maybe_sqrt_x: {maybe_sqrt_x}"); - // println(f"maybe_sqrt_y: {maybe_sqrt_y}"); + assert(maybe_sqrt_x * maybe_sqrt_x == x); - // let sqrt_x = maybe_sqrt_x.unwrap(); - // println(f"sqrt_x: {sqrt_x}"); - - assert(x == x); - - // assert(maybe_sqrt_x.unwrap() == RuntimeBigNum { limbs: [12, 0, 0], params }); - // assert(maybe_sqrt_y.is_none()); + assert(x == x); // This was breaking for a while, because a previous version of RuntimeBigNum::__tonelli_shanks_sqrt() was returning an Option. My theory is that this meant Option:none() wasn't propagating the params anymore, which for some reason was causing the params of x to no-longer be evaluated as constant, which is strange. } \ No newline at end of file From d66161caca5591e89423a593b0b589b24694ebee Mon Sep 17 00:00:00 2001 From: Michael Connor Date: Mon, 21 Oct 2024 22:03:48 +0100 Subject: [PATCH 13/14] fmt --- src/runtime_bignum_test.nr | 6 ++++-- src/unconstrained_helpers.nr | 3 +-- src/unconstrained_ops.nr | 16 ++++++++++------ 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/runtime_bignum_test.nr b/src/runtime_bignum_test.nr index 2ba36137..2fe95757 100644 --- a/src/runtime_bignum_test.nr +++ b/src/runtime_bignum_test.nr @@ -509,9 +509,11 @@ fn test_sqrt_BN() { let x = RuntimeBigNum { limbs: [9, 0, 0], params }; - let (_, maybe_sqrt_x) = unsafe { x.__tonelli_shanks_sqrt() }; + let (_, maybe_sqrt_x) = unsafe { + x.__tonelli_shanks_sqrt() + }; assert(maybe_sqrt_x * maybe_sqrt_x == x); assert(x == x); // This was breaking for a while, because a previous version of RuntimeBigNum::__tonelli_shanks_sqrt() was returning an Option. My theory is that this meant Option:none() wasn't propagating the params anymore, which for some reason was causing the params of x to no-longer be evaluated as constant, which is strange. -} \ No newline at end of file +} diff --git a/src/unconstrained_helpers.nr b/src/unconstrained_helpers.nr index 55d7c772..4141c305 100644 --- a/src/unconstrained_helpers.nr +++ b/src/unconstrained_helpers.nr @@ -2,8 +2,7 @@ use crate::utils::u60_representation::U60Repr; use crate::utils::split_bits; use crate::params::BigNumParams as P; -use crate::unconstrained_ops::{ __one, __eq, __neg, __add, __mul, __pow }; - +use crate::unconstrained_ops::{__one, __eq, __neg, __add, __mul, __pow}; /** * In this file: diff --git a/src/unconstrained_ops.nr b/src/unconstrained_ops.nr index 7dafac61..3e1547c4 100644 --- a/src/unconstrained_ops.nr +++ b/src/unconstrained_ops.nr @@ -2,7 +2,10 @@ use crate::utils::u60_representation::U60Repr; use crate::utils::split_bits; use crate::params::BigNumParams as P; -use crate::unconstrained_helpers::{__barrett_reduction, __primitive_root_log_size, __multiplicative_generator, __tonelli_shanks_sqrt_inner_loop_check}; +use crate::unconstrained_helpers::{ + __barrett_reduction, __primitive_root_log_size, __multiplicative_generator, + __tonelli_shanks_sqrt_inner_loop_check +}; /** * In this file: @@ -158,7 +161,11 @@ unconstrained pub(crate) fn __add( * @brief given inputs `x, y` compute 2p + x - y (unconstrained) * @description see `__neg` for why we use 2p instead of p **/ -unconstrained pub(crate) fn __sub(params: P, lhs: [Field; N], rhs: [Field; N]) -> [Field; N] { +unconstrained pub(crate) fn __sub( + params: P, + lhs: [Field; N], + rhs: [Field; N] +) -> [Field; N] { __add(params, lhs, __neg(params, rhs)) } @@ -332,10 +339,7 @@ unconstrained pub(crate) fn __batch_invert_slice(params: P, x: [[ * @note this is unconstrained fn. To constrain a square root, validate that output^2 = self * TODO: create fn that constrains nonexistence of square root (i.e. find x where x^2 = -self) **/ -unconstrained pub(crate) fn __tonelli_shanks_sqrt( - params: P, - input: [Field; N] -) -> std::option::Option<[Field; N]> { +unconstrained pub(crate) fn __tonelli_shanks_sqrt(params: P, input: [Field; N]) -> std::option::Option<[Field; N]> { // Tonelli-shanks algorithm begins by finding a field element Q and integer S, // such that (p - 1) = Q.2^{s} // We can compute the square root of a, by considering a^{(Q + 1) / 2} = R From e5dbed07830affac0d3a78a2cd19b6469934e131 Mon Sep 17 00:00:00 2001 From: Michael Connor Date: Mon, 21 Oct 2024 22:06:57 +0100 Subject: [PATCH 14/14] fmt --- src/unconstrained_ops.nr | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/unconstrained_ops.nr b/src/unconstrained_ops.nr index 3e1547c4..85ad548c 100644 --- a/src/unconstrained_ops.nr +++ b/src/unconstrained_ops.nr @@ -161,11 +161,7 @@ unconstrained pub(crate) fn __add( * @brief given inputs `x, y` compute 2p + x - y (unconstrained) * @description see `__neg` for why we use 2p instead of p **/ -unconstrained pub(crate) fn __sub( - params: P, - lhs: [Field; N], - rhs: [Field; N] -) -> [Field; N] { +unconstrained pub(crate) fn __sub(params: P, lhs: [Field; N], rhs: [Field; N]) -> [Field; N] { __add(params, lhs, __neg(params, rhs)) }