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!: refactor library architecture #36

Merged
merged 30 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ac85d3d
refactor
iAmMichaelConnor Oct 3, 2024
b7de594
silence warnings
iAmMichaelConnor Oct 3, 2024
1bdce74
silence more warnings
iAmMichaelConnor Oct 3, 2024
523f2e6
rebase & silence warnings
iAmMichaelConnor Oct 3, 2024
1ff683c
fmt
iAmMichaelConnor Oct 3, 2024
a224064
Update src/runtime_bignum.nr
TomAFrench Oct 4, 2024
d8f794e
Update src/utils/map.nr
TomAFrench Oct 4, 2024
8d24667
reduce constraint counts
iAmMichaelConnor Oct 21, 2024
8bb7304
update in line w/ Zac's changes, incl macro tests
iAmMichaelConnor Oct 21, 2024
bc7fa23
merge main
iAmMichaelConnor Oct 21, 2024
9e73b24
fix merge mistake
iAmMichaelConnor Oct 21, 2024
c0dcaf7
add sqrt code from zac
iAmMichaelConnor Oct 21, 2024
3361102
fix sqrt test
iAmMichaelConnor Oct 21, 2024
d66161c
fmt
iAmMichaelConnor Oct 21, 2024
e5dbed0
fmt
iAmMichaelConnor Oct 21, 2024
2730997
riddle with MOD_BITS
iAmMichaelConnor Oct 22, 2024
b2ce9a4
tonelli
iAmMichaelConnor Oct 22, 2024
c42a40b
option
iAmMichaelConnor Oct 22, 2024
d7558da
tidy
iAmMichaelConnor Oct 22, 2024
e7996a8
warnings
iAmMichaelConnor Oct 22, 2024
4311278
warnings
iAmMichaelConnor Oct 22, 2024
dd0a7a3
fmt
iAmMichaelConnor Oct 22, 2024
70c4885
latest nightly
iAmMichaelConnor Oct 22, 2024
59ceb91
fix to work with latest aztec-packages version of nargo
iAmMichaelConnor Oct 22, 2024
709f7ff
README
iAmMichaelConnor Oct 22, 2024
042ffa9
tidy filing
iAmMichaelConnor Oct 22, 2024
13195a0
version bump
iAmMichaelConnor Oct 25, 2024
5afa312
fmt
iAmMichaelConnor Oct 25, 2024
54a2a34
use nargo 0.36 for ci
sirasistant Oct 25, 2024
39ef97d
Update test.yml
kashbrti Oct 25, 2024
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
28 changes: 26 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
strategy:
fail-fast: false
matrix:
toolchain: [nightly, 0.35.0]
toolchain: [nightly, 0.36.0]
steps:
- name: Checkout sources
uses: actions/checkout@v4
Expand All @@ -38,7 +38,31 @@ jobs:
- name: Install Nargo
uses: noir-lang/[email protected]
with:
toolchain: 0.35.0
toolchain: 0.36.0

- name: Run formatter
run: nargo fmt --check


# This is a job which depends on all test jobs and reports the overall status.
# This allows us to add/remove test jobs without having to update the required workflows.
tests-end:
name: Noir End
runs-on: ubuntu-latest
# We want this job to always run (even if the dependant jobs fail) as we want this job to fail rather than skipping.
if: ${{ always() }}
needs:
- test
- format

steps:
- name: Report overall success
run: |
if [[ $FAIL == true ]]; then
exit 1
else
exit 0
fi
env:
# We treat any cancelled, skipped or failing jobs as a failure for the workflow as a whole.
FAIL: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
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.35.0"
compiler_version = ">=0.36.0"

[dependencies]
90 changes: 47 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ TODO

## Dependencies

- Noir ≥v0.32.0
- Barretenberg ≥v0.46.1
- Noir ≥v0.36.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 Expand Up @@ -50,12 +50,13 @@ If your field moduli is _also_ known at compile-time, use the `BigNumTrait` defi
Big numbers are instantiated with the BigNum struct:

```rust
struct BigNum<let N: u64, Params> {
struct BigNum<let N: u32, let MOD_BITS: u32, Params> {
limbs: [Field; N]
}
```

- `N` is the number of `Field` limbs together holding the value of the big number
- `MOD_BITS` is the bit-length of the modulus of the big number.
- `Params` is the parameters associated with the big number; refer to sections below for presets and customizations

### Usage
Expand All @@ -68,7 +69,7 @@ A simple 1 + 2 = 3 check in 256-bit unsigned integers:
use dep::bignum::fields::U256::U256Params;
use dep::bignum::BigNum;

type U256 = BigNum<3, U256Params>;
type U256 = BigNum<3, 257, U256Params>;

fn main() {
let one: U256 = BigNum::from_array([1, 0, 0]);
Expand Down Expand Up @@ -96,7 +97,7 @@ e.g.
use dep::bignum::fields::U256::U256Params;
use dep::bignum::BigNum;

type U256 = BigNum<3, U256Params>;
type U256 = BigNum<3, 257, U256Params>;

fn foo(x: U256, y: U256) -> U256 {
x.udiv(y)
Expand All @@ -105,70 +106,74 @@ fn foo(x: U256, y: U256) -> U256 {

##### Fields

`BigNum::fields` contains `BigNumInstance` constructors for common fields.
`BigNum::fields` contains `BigNumParams` for common fields.

Feature requests and/or pull requests welcome for missing fields you need.

TODO: Document existing field presets (e.g. bls, ed25519, secp256k1)

## `runtime_bignum`
## `RuntimeBigNum`

If your field moduli is _not_ known at compile-time (e.g. RSA verification), use the traits and structs defined in `runtime_bignum`: `runtime_bignum::BigNumTrait` and `runtime_bignum::BigNumInstanceTrait`
If your field moduli is _not_ known at compile-time (e.g. RSA verification), use the `RuntimeBigNum` struct defined in `runtime_bignum.nr`: `runtime_bignum::RuntimeBigNum`.

A `runtime_bignum::BigNumInstance` wraps the bignum modulus (as well as a derived parameter used internally to perform Barret reductions). A `BigNumInstance` object is required to evaluate most bignum operations.
```rust
use dep::bignum::fields::bn254Fq::BN254_Fq_Params;

### Types
// Notice how we don't provide the params here, because we're pretending they're
// not known at compile-time, for illustration purposes.
type My_RBN = RuntimeBigNum<3, 254>;

bignum operations are evaluated using two structs and a trait: `ParamsTrait`, `BigNum<N, Params>`, `BigNumInstance<N, Params>`
fn main() {
let params = BN254_Fq_Params::get_params(); // or some other params known at runtime.

`ParamsTrait` defines the compile-time properties of a BigNum instance: the number of modulus bits and the Barret reduction parameter `k` (TODO: these two values should be the same?!)
// Notice how we feed the params in, because we're pretending they're not
// known at compile-time.
let one: My_RBN = RuntimeBigNum::from_array(params, [1, 0, 0]);
let two: My_RBN = RuntimeBigNum::from_array(params, [2, 0, 0]);
let three: My_RBN = RuntimeBigNum::from_array(params, [3, 0, 0]);

`BigNumInstance` is a generator type that is used to create `BigNum` objects and evaluate operations on `BigNum` objects. It wraps BigNum parameters that may not be known at compile time (the `modulus` and a reduction parameter required for Barret reductions (`redc_param`))
assert((one + two) == three);
}
```

The `BigNum` struct represents individual big numbers.
### Types

BigNumInstance parameters (`modulus`, `redc_param`) can be provided at runtime via witnesses (e.g. RSA verification). The `redc_param` is only used in unconstrained functions and does not need to be derived from `modulus` in-circuit.
User-facing structs:

### Usage
`BigNum`: big numbers whose parameters are all known at compile-time.

#### Example
`RuntimeBigNum`: big numbers whose parameters are only known at runtime. (Note: the number of bits of the modulus of the bignum must be known at compile-time).

```rust
use crate::bignum::fields::bn254Fq{BNParams, BN254INSTANCE};
use crate::bignum::runtime_bignum::BigNumInstance;
use crate::bignum::BigNum;
If creating custom bignum params:

type Fq = BigNum<3, BNParams>;
type FqInst = BigNumInstance<3, BNParams>;
`BigNumParams` is needed, to declare your params. These parameters (`modulus`, `redc_param`) can be provided at runtime via witnesses (e.g. RSA verification). The `redc_param` is only used in unconstrained functions and does not need to be derived from `modulus` in-circuit.

fn example(Fq a, Fq b) -> Fq {
let instance: FqInst = BN254INSTANCE;
instance.mul(a, b)
}
```
`BigNumParamsGetter` is a convenient wrapper around params, which is needed if declaring a new type of `BigNum`.

#### Methods

##### Arithmetics

Basic expressions can be evaluated using `BigNumInstance::add, BigNumInstance::sub, BigNumInstance::mul`. However, when evaluating relations (up to degree 2) that are more complex than single operations, the function `BigNumInstance::evaluate_quadratic_expression` is more efficient (due to needing only a single modular reduction).
Basic expressions can be evaluated using the `BigNum` and `RuntimeBigNum` operators `+`,`-`,`*`,`/`. However, when evaluating relations (up to degree 2) that are more complex than single operations, the static methods `BigNum::evaluate_quadratic_expression` or `RuntimeBigNum::evaluate_quadratic_expression` are much more efficient (due to needing only a single modular reduction).

##### Unconstrained arithmetics

Unconstrained functions `__mul, __add, __sub, __div, __pow` can be used to compute witnesses that can then be fed into `BigNumInstance::evaluate_quadratic_expression`.
Unconstrained functions `__mul, __add, __sub, __div, __pow` etc. can be used to compute witnesses that can then be fed into `BigNumInstance::evaluate_quadratic_expression`.

> **Note:** `__div`, `__pow` and `div` are expensive due to requiring modular exponentiations during witness computation. It is worth modifying witness generation algorithms to minimize the number of modular exponentiations required. (for example, using batch inverses)
> **Note:** `__div`, `__pow` and `div` are expensive due to requiring modular exponentiations during witness computation. It is worth modifying witness generation algorithms to minimize the number of modular exponentiations required. (for example, using batch inverses).

e.g. if we wanted to compute `(a + b) * c + (d - e) * f = g` by evaluating the above example, `g` can be derived via:

```rust
let bn: BigNumInstance<3, BNParams> = BNInstance();
let t0 = bn.__mul(bn.__add(a, b), c);
let t1 = bn.__mul(bn.__add(d, bn.__neg(e)), f);
let a: BigNumInstance<3, 254, BN254_Fq_Params> = BigNum::new();
let t0 = c.__mul(a.__add(b));
let t1 = f.__mul(d.__sub(e));
let g = bn.__add(t0, t1);
```

See `bignum_test.nr` for more examples.
then the values can be arranged and fed-into `evaluate_quadratic_expression`.

See `bignum_test.nr` and `runtime_bignum_test.nr` for more examples.

##### `evaluate_quadratic_expression`

Expand Down Expand Up @@ -206,9 +211,9 @@ BigNum::evaluate_quadratic_expresson(lhs_terms, lhs_flags, rhs_terms, rhs_flags,

##### TODO: Document other available methods

#### Deriving BigNumInstance parameters: `modulus`, `redc_param`
#### Deriving BigNumParams parameters: `modulus`, `redc_param`

For common fields, BigNumInstance parameters can be pulled from the presets in `BigNum::fields`.
For common fields, BigNumParams parameters can be pulled from the presets in `bignum/fields/`.

For other moduli (e.g. those used in RSA verification), both `modulus` and `redc_param` must be computed and formatted according to the following speficiations:

Expand All @@ -218,17 +223,16 @@ For other moduli (e.g. those used in RSA verification), both `modulus` and `redc

`double_modulus` is derived via the method `compute_double_modulus` in `runtime_bignum.nr`. If you want to provide this value as a compile-time constant (see `fields/bn254Fq.nr` for an example), follow the algorithm `compute_double_modulus` as this parameter is _not_ structly 2 \* modulus. Each limb except the most significant limb borrows 2^120 from the next most significant limb. This ensure that when performing limb subtractions `double_modulus.limbs[i] - x.limbs[i]`, we know that the result will not underflow.

BigNumInstance parameters can be derived from a known modulus using the rust crate `noir-bignum-paramgen` (https://crates.io/crates/noir-bignum-paramgen)
BigNumParams parameters can be derived from a known modulus using the rust crate `noir-bignum-paramgen` (https://crates.io/crates/noir-bignum-paramgen)

## Additional usage examples

```rust
use crate::bignum::fields::bn254Fq::BNParams;
use crate::bignum::fields::BN254Instance;
use crate::bignum::BigNum;
use crate::bignum::runtime_bignum::BigNumInstance;
use dep::bignum::fields::bn254Fq::BN254_Fq_Params;

use dep::bignum::BigNum;

type Fq = BigNum<3, BNParams>;
type Fq = BigNum<3, 254, BN254_Fq_Params>;

fn example_mul(Fq a, Fq b) -> Fq {
a * b
Expand Down
Loading
Loading