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

chore: document big integers #4487

Merged
merged 12 commits into from
Mar 11, 2024
2 changes: 2 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@
"sdiv",
"secp256k1",
"secp256r1",
"Secpk",
"Secpr",
"signedness",
"signorecello",
"smol",
Expand Down
3 changes: 3 additions & 0 deletions docs/.markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"no-missing-space-atx": false
}
102 changes: 102 additions & 0 deletions docs/docs/noir/standard_library/bigint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
title: Big Integers
description: How to use big integers from Noir standard library
keywords:
[
Big Integer,
Noir programming language,
Noir libraries,
]
---

The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number.

:::note

The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers.

:::

Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely:

- BN254 Fq: Bn254Fq
- BN254 Fr: Bn254Fr
- Secp256k1 Fq: Secpk1Fq
- Secp256k1 Fr: Secpk1Fr
- Secp256r1 Fr: Secpr1Fr
- Secp256r1 Fq: Secpr1Fq
Savio-Sou marked this conversation as resolved.
Show resolved Hide resolved
guipublic marked this conversation as resolved.
Show resolved Hide resolved

Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX.
For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$.

Feel free to explore the source code for the other primes:

#include_code curve_order_base noir_stdlib/src/bigint.nr rust

## Example usage

A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it:

#include_code big_int_example test_programs/execution_success/bigint/src/main.nr rust

## Methods

The available operations for each big integer are:

### from_le_bytes

Construct a big integer from its little-endian bytes representation. Example:

```rust
let a = Secpk1Fq::from_le_bytes([x, y, 0, 45, 2]);
```

Sure, here's the formatted version of the remaining methods:

### to_le_bytes

Return the little-endian bytes representation of a big integer. Example:

```rust
let bytes = a.to_le_bytes();
```

### add

Add two big integers. Example:

```rust
let sum = a + b;
```

### sub

Subtract two big integers. Example:

```rust
let difference = a - b;
```

### mul

Multiply two big integers. Example:

```rust
let product = a * b;
```

### div

Divide two big integers. Note that division is field division and not euclidean division. Example:

```rust
let quotient = a / b;
```

### eq

Compare two big integers. Example:

```rust
let are_equal = a == b;
```
2 changes: 2 additions & 0 deletions noir_stdlib/src/bigint.nr
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::ops::{Add, Sub, Mul, Div};
use crate::cmp::Eq;

// docs:start:curve_order_base
global bn254_fq = [0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, 0x97,
0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30];
global bn254_fr = [0x01, 0x00, 0x00, 0x00, 0x3F, 0x59, 0x1F, 0x43, 0x09, 0x97, 0xB9, 0x79, 0x48, 0xE8, 0x33, 0x28,
Expand All @@ -13,6 +14,7 @@ global secpr1_fq = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF];
global secpr1_fr = [0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3, 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,0xFF, 0xFF, 0xFF, 0xFF];
// docs:end:curve_order_base

struct BigInt {
pointer: u32,
Expand Down
12 changes: 12 additions & 0 deletions test_programs/execution_success/bigint/src/main.nr
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use dep::std::bigint;
use dep::std::{bigint::Secpk1Fq, println};

fn main(mut x: [u8; 5], y: [u8; 5]) {
let a = bigint::Secpk1Fq::from_le_bytes([x[0], x[1], x[2], x[3], x[4]]);
Expand All @@ -13,4 +14,15 @@ fn main(mut x: [u8; 5], y: [u8; 5]) {
let d = a * b - b;
let d1 = bigint::Secpk1Fq::from_le_bytes(597243850900842442924.to_le_bytes(10));
assert(d1 == d);
// big_int_example(x[0], x[1]);
}

// docs:start:big_int_example
fn big_int_example(x: u8, y: u8) {
let a = Secpk1Fq::from_le_bytes([x, y, 0, 45, 2]);
let b = Secpk1Fq::from_le_bytes([y, x, 9]);
let c = (a + b) * b / a;
let d = c.to_le_bytes();
println(d[0]);
}
// docs:end:big_int_example
Loading