Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: remove redefinition of arithmetic methods on BigNumTrait #84

Merged
merged 6 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:

env:
CARGO_TERM_COLOR: always
MINIMUM_NOIR_VERSION: v0.36.0
MINIMUM_NOIR_VERSION: v1.0.0-beta.0

jobs:
noir-version-list:
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 = ">=0.36.0"
asterite marked this conversation as resolved.
Show resolved Hide resolved
compiler_version = ">=1.0.0"

[dependencies]
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ TODO

## Noir Version Compatibility

This library is tested with all stable releases since 0.36.0 as well as nightly.
This library is tested with all stable releases since 1.0.0-beta.0 as well as nightly.

## Dependencies

- Noir ≥v0.36.0
- Noir ≥v1.0.0-beta.0
- Barretenberg ≥v0.56.1

Refer to [Noir's docs](https://noir-lang.org/docs/getting_started/installation/) and [Barretenberg's docs](https://github.com/AztecProtocol/aztec-packages/blob/master/barretenberg/cpp/src/barretenberg/bb/readme.md#installation) for installation steps.
Expand Down
34 changes: 14 additions & 20 deletions src/bignum.nr
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@ use crate::fns::{
constrained_ops::{
add, assert_is_not_equal, conditional_select, derive_from_seed, div, eq, mul, neg, sub,
udiv, udiv_mod, umod, validate_in_field, validate_in_range,
}, expressions::{__compute_quadratic_expression, evaluate_quadratic_expression},
},
expressions::{__compute_quadratic_expression, evaluate_quadratic_expression},
serialization::{from_be_bytes, to_le_bytes},
unconstrained_ops::{
__add, __batch_invert, __batch_invert_slice, __derive_from_seed, __div, __eq, __invmod,
__is_zero, __mul, __neg, __pow, __sub, __tonelli_shanks_sqrt, __udiv_mod,
},
};
use std::ops::{Add, Div, Mul, Neg, Sub};

pub struct BigNum<let N: u32, let MOD_BITS: u32, Params> {
pub limbs: [Field; N],
}
// We aim to avoid needing to add a generic parameter to this trait, for this reason we do not allow
// accessing the limbs of the bignum except through slices.
pub trait BigNumTrait {
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;
Expand Down Expand Up @@ -79,26 +81,23 @@ pub trait BigNumTrait {
pub fn validate_in_range(self);
pub fn validate_in_field(self);

pub fn neg(self) -> Self;
pub fn add(self, other: Self) -> Self {
self + other
}
pub fn sub(self, other: Self) -> Self {
self - other
}
pub fn mul(self, other: Self) -> Self {
self * other
}
pub fn div(self, other: Self) -> Self {
self / other
}
pub fn udiv_mod(self, divisor: Self) -> (Self, Self);
pub fn udiv(self, divisor: Self) -> Self;
pub fn umod(self, divisor: Self) -> Self;

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

impl<let N: u32, let MOD_BITS: u32, Params> Neg for BigNum<N, MOD_BITS, Params>
where
Params: BigNumParamsGetter<N, MOD_BITS>,
{
fn neg(self) -> Self {
let params = Params::get_params();
Self { limbs: neg::<_, MOD_BITS>(params, self.limbs) }
}
}

impl<let N: u32, let MOD_BITS: u32, Params> BigNumTrait for BigNum<N, MOD_BITS, Params>
where
Params: BigNumParamsGetter<N, MOD_BITS>,
Expand Down Expand Up @@ -286,11 +285,6 @@ where
assert_is_not_equal(params, self.limbs, other.limbs);
}

fn neg(self) -> Self {
let params = Params::get_params();
Self { limbs: neg::<_, MOD_BITS>(params, self.limbs) }
}

fn udiv_mod(self, divisor: Self) -> (Self, Self) {
let params = Params::get_params();
let (q, r) = udiv_mod::<_, MOD_BITS>(params, self.limbs, divisor.limbs);
Expand Down
3 changes: 2 additions & 1 deletion src/fns/constrained_ops.nr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use crate::fns::{
unconstrained_helpers::{
__add_with_flags, __neg_with_flags, __sub_with_flags, __validate_gt_remainder,
__validate_in_field_compute_borrow_flags,
}, unconstrained_ops::{__div, __mul, __udiv_mod},
},
unconstrained_ops::{__div, __mul, __udiv_mod},
};

/**
Expand Down
2 changes: 1 addition & 1 deletion src/fns/unconstrained_ops.nr
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ pub(crate) unconstrained fn __invmod<let N: u32, let MOD_BITS: u32>(
) -> [Field; N] {
let one: [Field; N] = __one::<N>();
let one_u60: U60Repr<N, 2> = U60Repr::from(one);
let exp_u60 = params.modulus_u60.sub(one_u60.add(one_u60));
let exp_u60 = params.modulus_u60 - (one_u60 + one_u60);
let exp = U60Repr::into(exp_u60);
__pow::<_, MOD_BITS>(params, val, exp)
}
Expand Down
31 changes: 11 additions & 20 deletions src/runtime_bignum.nr
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ use crate::fns::{
constrained_ops::{
add, assert_is_not_equal, conditional_select, derive_from_seed, div, eq, mul, neg, sub,
udiv, udiv_mod, umod, validate_in_field, validate_in_range,
}, expressions::{__compute_quadratic_expression, evaluate_quadratic_expression},
},
expressions::{__compute_quadratic_expression, evaluate_quadratic_expression},
serialization::{from_be_bytes, to_le_bytes},
unconstrained_ops::{
__add, __batch_invert, __batch_invert_slice, __derive_from_seed, __div, __eq, __invmod,
__is_zero, __mul, __neg, __pow, __sub, __tonelli_shanks_sqrt, __udiv_mod,
},
};
use std::ops::{Add, Div, Mul, Neg, Sub};

pub struct RuntimeBigNum<let N: u32, let MOD_BITS: u32> {
pub limbs: [Field; N],
Expand All @@ -22,7 +24,7 @@ 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> {
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>(
Expand Down Expand Up @@ -105,26 +107,20 @@ pub(crate) trait RuntimeBigNumTrait<let N: u32, let MOD_BITS: u32> {
pub fn validate_in_range(self);
// pub fn validate_gt(self, lhs: Self, rhs: Self);

pub fn neg(self) -> Self;
pub fn add(lhs: Self, rhs: Self) -> Self {
lhs + rhs
}
pub fn sub(lhs: Self, rhs: Self) -> Self {
lhs - rhs
}
pub fn mul(lhs: Self, rhs: Self) -> Self {
lhs * rhs
}
pub fn div(lhs: Self, rhs: Self) -> Self {
lhs / rhs
}
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;

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

impl<let N: u32, let MOD_BITS: u32> Neg for RuntimeBigNum<N, MOD_BITS> {
fn neg(self) -> Self {
let params = self.params;
Self { limbs: neg::<_, MOD_BITS>(params, self.limbs), params }
}
}

impl<let N: u32, let MOD_BITS: u32> RuntimeBigNumTrait<N, MOD_BITS> for RuntimeBigNum<N, MOD_BITS> {

fn new(params: BigNumParams<N, MOD_BITS>) -> Self {
Expand Down Expand Up @@ -359,11 +355,6 @@ impl<let N: u32, let MOD_BITS: u32> RuntimeBigNumTrait<N, MOD_BITS> for RuntimeB
assert_is_not_equal(params, self.limbs, other.limbs);
}

fn neg(self) -> Self {
let params = self.params;
Self { limbs: neg::<_, MOD_BITS>(params, self.limbs), params }
}

fn udiv_mod(self, divisor: Self) -> (Self, Self) {
let params = self.params;
assert(params == divisor.params);
Expand Down
8 changes: 4 additions & 4 deletions src/tests/bignum_test.nr
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ where
// // // 929 gates for a 2048 bit mul
fn test_mul<let N: u32, BN>()
where
BN: BigNumTrait + std::ops::Mul + std::ops::Add,
BN: BigNumTrait,
{
let a: BN = unsafe { BN::__derive_from_seed([1, 2, 3, 4]) };
let b: BN = unsafe { BN::__derive_from_seed([4, 5, 6, 7]) };
Expand All @@ -287,7 +287,7 @@ where

fn test_add<let N: u32, BN>()
where
BN: BigNumTrait + std::ops::Add + std::ops::Mul + std::cmp::Eq,
BN: BigNumTrait,
{
let a = unsafe { BN::__derive_from_seed([1, 2, 3, 4]) };
let b: BN = unsafe { BN::__derive_from_seed([4, 5, 6, 7]) };
Expand Down Expand Up @@ -315,7 +315,7 @@ where

fn test_div<let N: u32, BN>()
where
BN: BigNumTrait + std::ops::Div + std::ops::Mul + std::ops::Add + std::cmp::Eq,
BN: BigNumTrait,
{
let a = unsafe { BN::__derive_from_seed([1, 2, 3, 4]) };
let b = unsafe { BN::__derive_from_seed([4, 5, 6, 7]) };
Expand All @@ -326,7 +326,7 @@ where

fn test_invmod<let N: u32, BN>()
where
BN: BigNumTrait + std::cmp::Eq,
BN: BigNumTrait,
{
let u = unsafe { BN::__derive_from_seed([1, 2, 3, 4]) };
for _ in 0..1 {
Expand Down
Loading