Skip to content

Commit

Permalink
fixes to get bigcurve working?
Browse files Browse the repository at this point in the history
  • Loading branch information
zac-williamson committed Jul 24, 2024
1 parent 2aa6a66 commit ef8c8af
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 13 deletions.
6 changes: 6 additions & 0 deletions src/bignum_test.nr
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ impl BigNumParamsTrait<18> for Test2048Params {
];
BigNumInstance::new(modulus, redc_param)
}
fn k() -> u64 {
2048
}
fn modulus_bits() -> u64 {
2048
}
}

type Fq = BigNum<3, BNParams>;
Expand Down
6 changes: 6 additions & 0 deletions src/fields/bls12381Fr.nr
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,10 @@ impl BigNumParamsTrait<3> for Bls12_381_Fr_Params {
let redc_param = [0x410fad2f92eb5c509cde80830358e4, 0x253b7fb78ddf0e2d772dc1f823b4d9, 0x008d54];
BigNumInstance::new(modulus, redc_param)
}
fn k() -> u64 {
255
}
fn modulus_bits() -> u64 {
255
}
}
14 changes: 14 additions & 0 deletions src/fields/bn254Fq.nr
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,18 @@ impl BigNumParamsTrait<3> for BNParams {
fn get_instance() -> BigNumInstance<3, Self> {
BN254INSTANCE
}
fn k() -> u64 {
255
}
fn modulus_bits() -> u64 {
254
}
}
impl BNParams {
fn k() -> u64 {
255
}
fn modulus_bits() -> u64 {
254
}
}
22 changes: 19 additions & 3 deletions src/lib.nr
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ trait BigNumParamsTrait<let N: u64> where Self: RuntimeBigNumParamsTrait<N> {
/**
* @brief k used for __barrett_reduction. Should be at least modulus_bits() + 1
**/
fn k() -> u64 { Self::k() }
fn k() -> u64;
/**
* @brief modulus_bits = log2(modulus) rounded up
**/
fn modulus_bits() -> u64 { Self::modulus_bits() }
fn modulus_bits() -> u64;
}

trait BigNumTrait where BigNumTrait: std::ops::Add + std::ops::Sub + std::ops::Mul + std::ops::Div + std::ops::Eq + RuntimeBigNumTrait {
Expand All @@ -44,6 +44,8 @@ trait BigNumTrait where BigNumTrait: std::ops::Add + std::ops::Sub + std::ops::M
fn new() -> Self { RuntimeBigNumTrait::new() }
fn one() -> Self { RuntimeBigNumTrait::one() }
fn modulus() -> Self;
fn modulus_bits(self) -> u64;
fn num_limbs(self) -> u64;
fn __derive_from_seed<let SeedBytes: u64>(seed: [u8; SeedBytes]) -> Self;
fn __powmod(self, exponent: Self) -> Self;
fn __negate(self) -> Self;
Expand All @@ -53,6 +55,7 @@ trait BigNumTrait where BigNumTrait: std::ops::Add + std::ops::Sub + std::ops::M
fn __divmod(self, other: Self) -> Self;
fn __invmod(self) -> Self;
fn __batch_invert<let M: u64>(to_invert: [Self; M]) -> [Self; M];
fn __batch_invert_slice(x: [Self]) -> [Self];
fn __is_zero(self) -> bool { RuntimeBigNumTrait::__is_zero(self) }
fn __eq(self, other: Self) -> bool { RuntimeBigNumTrait::__eq(self, other) }
fn __compute_quadratic_expression<let LHS_N: u64, let RHS_N: u64, let NUM_PRODUCTS: u64, let ADD_N: u64>(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);
Expand All @@ -76,6 +79,16 @@ trait BigNumTrait where BigNumTrait: std::ops::Add + std::ops::Sub + std::ops::M
impl<let N: u64, Params> BigNumTrait for BigNum<N, Params> where Params: BigNumParamsTrait<N> + RuntimeBigNumParamsTrait<N> {


// 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<N> 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) -> u64 {
let r: u64 = Params::modulus_bits();
r
}
fn num_limbs(_: Self) -> u64 { N }

fn modulus() -> Self {
Params::get_instance().modulus()
}
Expand Down Expand Up @@ -125,11 +138,14 @@ impl<let N: u64, Params> BigNumTrait for BigNum<N, Params> where Params: BigNumP
Params::get_instance().__divmod(self, rhs)
}

// n.b. needs to be declared unconstrained because we take in a mutable slice
fn __batch_invert<let M: u64>(x: [Self; M]) -> [Self; M] {
Params::get_instance().__batch_invert(x)
}

// n.b. needs to be declared unconstrained because we return a slice from an unconstrained runtime
unconstrained fn __batch_invert_slice(x: [Self]) -> [Self] {
Params::get_instance().__batch_invert_slice(x)
}
fn __invmod(self) -> Self {
Params::get_instance().__invmod(self)
}
Expand Down
44 changes: 34 additions & 10 deletions src/runtime_bignum.nr
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ trait BigNumTrait {
fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self;
fn validate_in_range(self);
fn validate_quotient_in_range(self);
fn get_modulus_bits() -> u64;
fn num_limbs() -> u64;
fn __is_zero(self) -> bool;
fn __eq(self, rhs: Self) -> bool;
}
Expand All @@ -42,6 +40,8 @@ trait BigNumInstanceTrait<BN> where BN: BigNumTrait {
fn __mulmod(self, lhs: BN, rhs: BN) -> BN;
fn __divmod(self, lhs: BN, rhs: BN) -> BN;
fn __batch_invert<let M: u64>(self, x: [BN; M]) -> [BN; M];
fn __batch_invert_slice(self, x: [BN]) -> [BN];

fn __invmod(self, val: BN) -> BN;
fn __powmod(self, val: BN, exponent: BN) -> BN;
fn __compute_quadratic_expression<let LHS_N: u64, let RHS_N: u64, let NUM_PRODUCTS: u64, let ADD_N: u64>(
Expand Down Expand Up @@ -255,13 +255,6 @@ impl<let N: u64, Params> BigNumTrait for BigNum<N, Params> where Params: BigNumP
self.limbs[N - 1].assert_max_bit_size(final_limb_bits as u32);
}

fn get_modulus_bits() -> u64 {
Params::modulus_bits()
}
fn num_limbs() -> u64 {
N
}

fn __is_zero(self) -> bool {
self.__is_zero_impl()
}
Expand Down Expand Up @@ -323,11 +316,15 @@ impl<let N: u64, Params,> BigNumInstanceTrait<BigNum<N, Params>> for BigNumInsta
self.__divmod_impl(lhs, rhs)
}

// n.b. needs to be declared unconstrained because we take in a mutable slice
fn __batch_invert<let M: u64>(self, x: [BigNum<N, Params>; M]) -> [BigNum<N, Params>; M] {
self.batch_invert_impl(x)
}

// n.b. needs to be declared unconstrained because we return a slice from an unconstrained runtime
unconstrained fn __batch_invert_slice(self, x: [BigNum<N, Params>]) -> [BigNum<N, Params>] {
self.batch_invert_slice_impl(x)
}

fn __invmod(self, val: BigNum<N, Params>) -> BigNum<N, Params> {
self.__invmod_impl(val)
}
Expand Down Expand Up @@ -1049,6 +1046,33 @@ impl<let N: u64, Params> BigNumInstance<N, Params> where Params: BigNumParamsTra
result
}

unconstrained fn batch_invert_slice_impl(self, x: [BigNum<N, Params>]) -> [BigNum<N, Params>] {
// TODO: ugly! Will fail if input slice is empty
let mut accumulator: BigNum<N, Params> = BigNum::one();
let mut result: [BigNum<N, Params>] = [BigNum::new()];
let mut temporaries: [BigNum<N, Params>] = &[];
for i in 0..x.len() {
temporaries = temporaries.push_back(accumulator);
if (x[i].__is_zero() == false) {
accumulator = self.__mulmod(accumulator, x[i]);
}
result = result.push_back(BigNum::new());
}

accumulator = self.__invmod(accumulator);
let mut T0: BigNum<N, Params> = 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.__mulmod(accumulator, temporaries[idx]);
accumulator = self.__mulmod(accumulator, x[idx]);
result[idx] = T0;
}
}
result
}

unconstrained fn __divmod_impl(self, numerator: BigNum<N, Params>, divisor: BigNum<N, Params>) -> BigNum<N, Params> {
let t0 = self.__invmod(divisor);
self.__mulmod(numerator, t0)
Expand Down

0 comments on commit ef8c8af

Please sign in to comment.