Skip to content

Commit

Permalink
Merge b25b21b into d231a45
Browse files Browse the repository at this point in the history
  • Loading branch information
kashbrti authored Jan 21, 2025
2 parents d231a45 + b25b21b commit b9d34df
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 85 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ jobs:
run: |
npm install -g bbup
bbup -nv 1.0.0-beta.0
sudo apt install libc++-dev
- name: Build Noir benchmark programs
run: nargo export

Expand All @@ -47,3 +49,4 @@ jobs:
# delete the comment in case changes no longer impact circuit sizes
delete: ${{ !steps.gates_diff.outputs.markdown }}
message: ${{ steps.gates_diff.outputs.markdown }}

1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ jobs:
run: nargo test

format:
needs: [noir-version-list]
runs-on: ubuntu-latest
steps:
- name: Checkout sources
Expand Down
2 changes: 1 addition & 1 deletion Nargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
name = "bignum"
type = "lib"
authors = [""]
compiler_version = ">=1.0.0"
compiler_version = ">=0.36.0"

[dependencies]
82 changes: 41 additions & 41 deletions src/bignum.nr
Original file line number Diff line number Diff line change
Expand Up @@ -24,39 +24,39 @@ pub struct BigNum<let N: u32, let MOD_BITS: u32, Params> {
pub trait BigNumTrait: Neg + Add + Sub + Mul + Div + Eq {
// TODO: this crashes the compiler? v0.32
// fn default() -> Self { std::default::Default::default () }
pub fn new() -> Self;
pub fn one() -> Self;
pub fn derive_from_seed<let SeedBytes: u32>(seed: [u8; SeedBytes]) -> Self;
pub unconstrained fn __derive_from_seed<let SeedBytes: u32>(seed: [u8; SeedBytes]) -> Self;
pub fn from_slice(limbs: [Field]) -> Self;
pub fn from_be_bytes<let NBytes: u32>(x: [u8; NBytes]) -> Self;
pub fn to_le_bytes<let NBytes: u32>(self) -> [u8; NBytes];

pub fn modulus() -> Self;
pub fn modulus_bits(self) -> u32;
pub fn num_limbs(self) -> u32;
pub fn get_limbs_slice(self) -> [Field];
pub fn get_limb(self, idx: u32) -> Field;
pub fn set_limb(&mut self, idx: u32, value: Field);

pub unconstrained fn __eq(self, other: Self) -> bool;
pub unconstrained fn __is_zero(self) -> bool;

pub unconstrained fn __neg(self) -> Self;
pub unconstrained fn __add(self, other: Self) -> Self;
pub unconstrained fn __sub(self, other: Self) -> Self;
pub unconstrained fn __mul(self, other: Self) -> Self;
pub unconstrained fn __div(self, other: Self) -> Self;
pub unconstrained fn __udiv_mod(self, divisor: Self) -> (Self, Self);
pub unconstrained fn __invmod(self) -> Self;
pub unconstrained fn __pow(self, exponent: Self) -> Self;

pub unconstrained fn __batch_invert<let M: u32>(to_invert: [Self; M]) -> [Self; M];
pub unconstrained fn __batch_invert_slice<let M: u32>(to_invert: [Self]) -> [Self];

pub unconstrained fn __tonelli_shanks_sqrt(self) -> std::option::Option<Self>;

pub unconstrained fn __compute_quadratic_expression<let LHS_N: u32, let RHS_N: u32, let NUM_PRODUCTS: u32, let ADD_N: u32>(
fn new() -> Self;
fn one() -> Self;
fn derive_from_seed<let SeedBytes: u32>(seed: [u8; SeedBytes]) -> Self;
unconstrained fn __derive_from_seed<let SeedBytes: u32>(seed: [u8; SeedBytes]) -> Self;
fn from_slice(limbs: [Field]) -> Self;
fn from_be_bytes<let NBytes: u32>(x: [u8; NBytes]) -> Self;
fn to_le_bytes<let NBytes: u32>(self) -> [u8; NBytes];

fn modulus() -> Self;
fn modulus_bits(self) -> u32;
fn num_limbs(self) -> u32;
fn get_limbs_slice(self) -> [Field];
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<let M: u32>(to_invert: [Self; M]) -> [Self; M];
unconstrained fn __batch_invert_slice<let M: u32>(to_invert: [Self]) -> [Self];

unconstrained fn __tonelli_shanks_sqrt(self) -> std::option::Option<Self>;

unconstrained fn __compute_quadratic_expression<let LHS_N: u32, let RHS_N: u32, let NUM_PRODUCTS: u32, let ADD_N: u32>(
lhs: [[Self; LHS_N]; NUM_PRODUCTS],
lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS],
rhs: [[Self; RHS_N]; NUM_PRODUCTS],
Expand All @@ -65,7 +65,7 @@ pub trait BigNumTrait: Neg + Add + Sub + Mul + Div + Eq {
add_flags: [bool; ADD_N],
) -> (Self, Self);

pub fn evaluate_quadratic_expression<let LHS_N: u32, let RHS_N: u32, let NUM_PRODUCTS: u32, let ADD_N: u32>(
fn evaluate_quadratic_expression<let LHS_N: u32, let RHS_N: u32, let NUM_PRODUCTS: u32, let ADD_N: u32>(
lhs: [[Self; LHS_N]; NUM_PRODUCTS],
lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS],
rhs: [[Self; RHS_N]; NUM_PRODUCTS],
Expand All @@ -74,15 +74,15 @@ pub trait BigNumTrait: Neg + Add + Sub + Mul + Div + Eq {
add_flags: [bool; ADD_N],
);

pub fn assert_is_not_equal(self, other: Self);
pub fn validate_in_range(self);
pub fn validate_in_field(self);
fn assert_is_not_equal(self, other: Self);
fn validate_in_range(self);
fn validate_in_field(self);

pub fn udiv_mod(self, divisor: Self) -> (Self, Self);
pub fn udiv(self, divisor: Self) -> Self;
pub fn umod(self, divisor: Self) -> Self;
fn udiv_mod(self, divisor: Self) -> (Self, Self);
fn udiv(self, divisor: Self) -> Self;
fn umod(self, divisor: Self) -> Self;

pub fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self;
fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self;
}

impl<let N: u32, let MOD_BITS: u32, Params> std::convert::From<Field> for BigNum<N, MOD_BITS, Params>
Expand Down
34 changes: 29 additions & 5 deletions src/fns/constrained_ops.nr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::fns::{
expressions::evaluate_quadratic_expression,
unconstrained_helpers::{
__add_with_flags, __from_field, __neg_with_flags, __sub_with_flags, __validate_gt_remainder,
__validate_in_field_compute_borrow_flags,
__validate_in_field_compute_borrow_flags, __validate_in_grumpkin_compute_borrow_flags,
},
unconstrained_ops::{__div, __mul, __udiv_mod},
};
Expand Down Expand Up @@ -45,18 +45,18 @@ pub(crate) fn from_field<let N: u32, let MOD_BITS: u32>(
grumpkin_modulus[0] = 0x33e84879b9709143e1f593f0000001;
grumpkin_modulus[1] = 0x4e72e131a029b85045b68181585d28;
grumpkin_modulus[2] = 0x3064;
validate_gt::<N, 254>(grumpkin_modulus, result);
validate_gt::<N, MOD_BITS>(grumpkin_modulus, result);
// validate that the limbs are in range
validate_in_range::<N, 254>(result);
validate_in_range::<N, MOD_BITS>(result);
}
// validate the limbs sum up to the field value
let field_val = if N < 2 {
result[0]
} else if N == 2 {
validate_in_range::<N, 254>(result);
validate_in_range::<N, MOD_BITS>(result);
result[0] + result[1] * TWO_POW_120
} else {
validate_in_range::<N, 254>(result);
validate_in_range::<N, MOD_BITS>(result);
result[0] + result[1] * TWO_POW_120 + result[2] * TWO_POW_120 * TWO_POW_120
};
assert(field_val == field);
Expand Down Expand Up @@ -267,6 +267,30 @@ pub(crate) fn validate_in_field<let N: u32, let MOD_BITS: u32>(
validate_in_range::<_, MOD_BITS>(compare);
}

pub(crate) fn validate_in_grumpkin<let N: u32, let MOD_BITS: u32>(limbs: [Field; N]) {
// N.B. need to combine with validate_in_range if `self` limbs have not been range constrained
let mut grumpkin_modulus = [0; N];
grumpkin_modulus[0] = 0x33e84879b9709143e1f593f0000001;
grumpkin_modulus[1] = 0x4e72e131a029b85045b68181585d28;
grumpkin_modulus[2] = 0x3064;

let mut p_grumpkin_minus_self: [Field; N] = [0; N];
for i in 0..N {
p_grumpkin_minus_self[i] = grumpkin_modulus[i] - limbs[i];
}
let borrow_flags = unsafe { __validate_in_grumpkin_compute_borrow_flags(limbs) };
let two_pow_120: Field = 0x1000000000000000000000000000000;
p_grumpkin_minus_self[0] += borrow_flags[0] as Field * two_pow_120;
for i in 1..N - 1 {
p_grumpkin_minus_self[i] +=
(borrow_flags[i] as Field * two_pow_120 - borrow_flags[i - 1] as Field);
}
p_grumpkin_minus_self[N - 1] -= borrow_flags[N - 2] as Field;
let mut compare = limbs;
compare = p_grumpkin_minus_self;
validate_in_range::<_, MOD_BITS>(compare);
}

/**
* @brief Validate a BigNum instance is correctly range constrained to contain no more than Params::modulus_bits()
**/
Expand Down
15 changes: 15 additions & 0 deletions src/fns/unconstrained_helpers.nr
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@ pub(crate) unconstrained fn __validate_in_field_compute_borrow_flags<let N: u32,
flags
}

pub(crate) unconstrained fn __validate_in_grumpkin_compute_borrow_flags<let N: u32, let MOD_BITS: u32>(
val: [Field; N],
) -> [bool; N] {
let mut flags: [bool; N] = [false; N];
let mut grumpkin_modulus = [0; N];
grumpkin_modulus[0] = 0x33e84879b9709143e1f593f0000001;
grumpkin_modulus[1] = 0x4e72e131a029b85045b68181585d28;
grumpkin_modulus[2] = 0x3064;
flags[0] = grumpkin_modulus[0].lt(val[0]);
for i in 1..N - 1 {
flags[i] = grumpkin_modulus[i].lt(val[i] + flags[i - 1] as Field);
}
flags
}

pub(crate) unconstrained fn __validate_gt_remainder<let N: u32>(
lhs: [Field; N],
rhs: [Field; N],
Expand Down
2 changes: 1 addition & 1 deletion src/params.nr
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct BigNumParams<let N: u32, let MOD_BITS: u32> {

// To be implemented by the user for any BigNum they define, or within the predefined BigNums in the `fields/` dir.
pub trait BigNumParamsGetter<let N: u32, let MOD_BITS: u32> {
pub fn get_params() -> BigNumParams<N, MOD_BITS>;
fn get_params() -> BigNumParams<N, MOD_BITS>;
}

impl<let N: u32, let MOD_BITS: u32> BigNumParams<N, MOD_BITS> {
Expand Down
71 changes: 34 additions & 37 deletions src/runtime_bignum.nr
Original file line number Diff line number Diff line change
Expand Up @@ -25,61 +25,58 @@ impl<let N: u32, let MOD_BITS: u32> RuntimeBigNum<N, MOD_BITS> {}
// 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<let N: u32, let MOD_BITS: u32>: Neg + Add + Sub + Mul + Div + Eq {
pub fn new(params: BigNumParams<N, MOD_BITS>) -> Self;
pub fn one(params: BigNumParams<N, MOD_BITS>) -> Self;
pub fn derive_from_seed<let SeedBytes: u32>(
fn new(params: BigNumParams<N, MOD_BITS>) -> Self;
fn one(params: BigNumParams<N, MOD_BITS>) -> Self;
fn derive_from_seed<let SeedBytes: u32>(
params: BigNumParams<N, MOD_BITS>,
seed: [u8; SeedBytes],
) -> Self;
pub unconstrained fn __derive_from_seed<let SeedBytes: u32>(
unconstrained fn __derive_from_seed<let SeedBytes: u32>(
params: BigNumParams<N, MOD_BITS>,
seed: [u8; SeedBytes],
) -> Self;
pub fn from_slice(params: BigNumParams<N, MOD_BITS>, limbs: [Field]) -> Self;
pub fn from_array(params: BigNumParams<N, MOD_BITS>, limbs: [Field; N]) -> Self;
pub fn from_be_bytes<let NBytes: u32>(
params: BigNumParams<N, MOD_BITS>,
x: [u8; NBytes],
) -> Self;
fn from_slice(params: BigNumParams<N, MOD_BITS>, limbs: [Field]) -> Self;
fn from_array(params: BigNumParams<N, MOD_BITS>, limbs: [Field; N]) -> Self;
fn from_be_bytes<let NBytes: u32>(params: BigNumParams<N, MOD_BITS>, x: [u8; NBytes]) -> Self;

pub fn to_le_bytes<let NBytes: u32>(self) -> [u8; NBytes];
fn to_le_bytes<let NBytes: u32>(self) -> [u8; NBytes];

pub fn modulus(self) -> Self;
pub fn modulus_bits() -> u32;
pub fn num_limbs() -> u32;
fn modulus(self) -> Self;
fn modulus_bits() -> u32;
fn num_limbs() -> u32;
// pub fn get(self) -> [Field];
pub fn get_limbs(self) -> [Field; N];
pub fn get_limb(self, idx: u32) -> Field;
pub fn set_limb(&mut self, idx: u32, value: 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
pub fn __neg(self) -> Self;
fn __neg(self) -> Self;
// unconstrained
pub fn __add(self, other: Self) -> Self;
fn __add(self, other: Self) -> Self;
// unconstrained
pub fn __sub(self, other: Self) -> Self;
fn __sub(self, other: Self) -> Self;
// unconstrained
pub fn __mul(self, other: Self) -> Self;
fn __mul(self, other: Self) -> Self;
// unconstrained
pub fn __div(self, other: Self) -> Self;
fn __div(self, other: Self) -> Self;
// unconstrained
pub fn __udiv_mod(self, divisor: Self) -> (Self, Self);
fn __udiv_mod(self, divisor: Self) -> (Self, Self);
// unconstrained
pub fn __invmod(self) -> Self;
fn __invmod(self) -> Self;
// unconstrained
pub fn __pow(self, exponent: Self) -> Self;
fn __pow(self, exponent: Self) -> Self;

// unconstrained
pub fn __batch_invert<let M: u32>(x: [Self; M]) -> [Self; M];
fn __batch_invert<let M: u32>(x: [Self; M]) -> [Self; M];
unconstrained fn __batch_invert_slice<let M: u32>(to_invert: [Self]) -> [Self];

pub fn __tonelli_shanks_sqrt(self) -> std::option::Option<Self>;
fn __tonelli_shanks_sqrt(self) -> std::option::Option<Self>;

// unconstrained
pub fn __compute_quadratic_expression<let LHS_N: u32, let RHS_N: u32, let NUM_PRODUCTS: u32, let ADD_N: u32>(
fn __compute_quadratic_expression<let LHS_N: u32, let RHS_N: u32, let NUM_PRODUCTS: u32, let ADD_N: u32>(
params: BigNumParams<N, MOD_BITS>,
lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS],
lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS],
Expand All @@ -89,7 +86,7 @@ pub(crate) trait RuntimeBigNumTrait<let N: u32, let MOD_BITS: u32>: Neg + Add +
linear_flags: [bool; ADD_N],
) -> (Self, Self);

pub fn evaluate_quadratic_expression<let LHS_N: u32, let RHS_N: u32, let NUM_PRODUCTS: u32, let ADD_N: u32>(
fn evaluate_quadratic_expression<let LHS_N: u32, let RHS_N: u32, let NUM_PRODUCTS: u32, let ADD_N: u32>(
params: BigNumParams<N, MOD_BITS>,
lhs_terms: [[Self; LHS_N]; NUM_PRODUCTS],
lhs_flags: [[bool; LHS_N]; NUM_PRODUCTS],
Expand All @@ -99,19 +96,19 @@ pub(crate) trait RuntimeBigNumTrait<let N: u32, let MOD_BITS: u32>: Neg + Add +
linear_flags: [bool; ADD_N],
);

pub fn eq(lhs: Self, rhs: Self) -> bool {
fn eq(lhs: Self, rhs: Self) -> bool {
lhs == rhs
}
pub fn assert_is_not_equal(self, other: Self);
pub fn validate_in_field(self);
pub fn validate_in_range(self);
fn assert_is_not_equal(self, other: Self);
fn validate_in_field(self);
fn validate_in_range(self);
// pub fn validate_gt(self, lhs: Self, rhs: Self);

pub fn udiv_mod(numerator: Self, divisor: Self) -> (Self, Self);
pub fn udiv(numerator: Self, divisor: Self) -> Self;
pub fn umod(numerator: Self, divisor: Self) -> Self;
fn udiv_mod(numerator: Self, divisor: Self) -> (Self, Self);
fn udiv(numerator: Self, divisor: Self) -> Self;
fn umod(numerator: Self, divisor: Self) -> Self;

pub fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self;
fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self;
}

impl<let N: u32, let MOD_BITS: u32> Neg for RuntimeBigNum<N, MOD_BITS> {
Expand Down
1 change: 1 addition & 0 deletions src/tests/bignum_test.nr
Original file line number Diff line number Diff line change
Expand Up @@ -815,3 +815,4 @@ fn test_from_field_3_digits() {
};
assert(result == expected);
}

0 comments on commit b9d34df

Please sign in to comment.