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: add struct for each bigint modulus #4422

Merged
merged 6 commits into from
Feb 15, 2024
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
329 changes: 302 additions & 27 deletions noir/noir_stdlib/src/bigint.nr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::ops::{Add, Sub, Mul, Div, Rem,};

use crate::ops::{Add, Sub, Mul, Div};
use crate::cmp::Eq;

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];
Expand Down Expand Up @@ -36,46 +36,321 @@ impl BigInt {
#[builtin(bigint_from_le_bytes)]
fn from_le_bytes(bytes: [u8], modulus: [u8]) -> BigInt {}
#[builtin(bigint_to_le_bytes)]
pub fn to_le_bytes(self) -> [u8] {}
fn to_le_bytes(self) -> [u8] {}

pub fn bn254_fr_from_le_bytes(bytes: [u8]) -> BigInt {
BigInt::from_le_bytes(bytes, bn254_fr)
fn check_32_bytes(self: Self, other: BigInt) -> bool {
let bytes = self.to_le_bytes();
let o_bytes = other.to_le_bytes();
let mut result = true;
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
for i in 0..32{
result = result & (bytes[i] == o_bytes[i]);
}
result
}
pub fn bn254_fq_from_le_bytes(bytes: [u8]) -> BigInt {
BigInt::from_le_bytes(bytes, bn254_fq)
}


trait BigField {
fn from_le_bytes(bytes: [u8]) -> Self;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want this to also have Bounds for Add, Sub, Mul and Div?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you clarify what do you mean with 'Bounds'?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can create an issue to have BigField inheriting from the Add, Sub, Mul trait Bounds

fn to_le_bytes(self) -> [u8];
}

struct Secpk1Fq {
inner: BigInt,
}

impl BigField for Secpk1Fq {
fn from_le_bytes(bytes: [u8]) -> Secpk1Fq {
Secpk1Fq {
inner: BigInt::from_le_bytes(bytes, secpk1_fq)
}
}
fn to_le_bytes(self) -> [u8] {
self.inner.to_le_bytes()
}
pub fn secpk1_fq_from_le_bytes(bytes: [u8]) -> BigInt {
BigInt::from_le_bytes(bytes, secpk1_fq)
}

impl Add for Secpk1Fq {
fn add(self: Self, other: Secpk1Fq) -> Secpk1Fq {
Secpk1Fq {
inner: self.inner.bigint_add(other.inner)
}
}
pub fn secpk1_fr_from_le_bytes(bytes: [u8]) -> BigInt {
BigInt::from_le_bytes(bytes, secpk1_fr)
}
impl Sub for Secpk1Fq {
fn sub(self: Self, other: Secpk1Fq) -> Secpk1Fq {
Secpk1Fq {
inner: self.inner.bigint_sub(other.inner)
}
}
}
impl Mul for Secpk1Fq {
fn mul(self: Self, other: Secpk1Fq) -> Secpk1Fq {
Secpk1Fq {
inner: self.inner.bigint_mul(other.inner)
}

impl Add for BigInt {
fn add(self: Self, other: BigInt) -> BigInt {
self.bigint_add(other)
}
}
impl Sub for BigInt {
fn sub(self: Self, other: BigInt) -> BigInt {
self.bigint_sub(other)
impl Div for Secpk1Fq {
fn div(self: Self, other: Secpk1Fq) -> Secpk1Fq {
Secpk1Fq {
inner: self.inner.bigint_div(other.inner)
}
}
}
impl Mul for BigInt {
fn mul(self: Self, other: BigInt) -> BigInt {
self.bigint_mul(other)
impl Eq for Secpk1Fq {
fn eq(self: Self, other: Secpk1Fq) -> bool {
self.inner.check_32_bytes(other.inner)
}
}
impl Div for BigInt {
fn div(self: Self, other: BigInt) -> BigInt {
self.bigint_div(other)

struct Secpk1Fr {
inner: BigInt,
}

impl BigField for Secpk1Fr {
fn from_le_bytes(bytes: [u8]) -> Secpk1Fr {
Secpk1Fr {
inner: BigInt::from_le_bytes(bytes, secpk1_fr)
}
}
fn to_le_bytes(self) -> [u8] {
self.inner.to_le_bytes()
}
}

impl Add for Secpk1Fr {
fn add(self: Self, other: Secpk1Fr) -> Secpk1Fr {
Secpk1Fr {
inner: self.inner.bigint_add(other.inner)
}
}
}
impl Rem for BigInt {
fn rem(self: Self, other: BigInt) -> BigInt {
let quotient = self.bigint_div(other);
self.bigint_sub(quotient.bigint_mul(other))
impl Sub for Secpk1Fr {
fn sub(self: Self, other: Secpk1Fr) -> Secpk1Fr {
Secpk1Fr {
inner: self.inner.bigint_sub(other.inner)
}
}
}
impl Mul for Secpk1Fr {
fn mul(self: Self, other: Secpk1Fr) -> Secpk1Fr {
Secpk1Fr {
inner: self.inner.bigint_mul(other.inner)
}

}
}
impl Div for Secpk1Fr {
fn div(self: Self, other: Secpk1Fr) -> Secpk1Fr {
Secpk1Fr {
inner: self.inner.bigint_div(other.inner)
}
}
}
impl Eq for Secpk1Fr {
fn eq(self: Self, other: Secpk1Fr) -> bool {
self.inner.check_32_bytes(other.inner)
}
}

struct Bn254Fr {
inner: BigInt,
}

impl BigField for Bn254Fr {
fn from_le_bytes(bytes: [u8]) -> Bn254Fr {
Bn254Fr {
inner: BigInt::from_le_bytes(bytes, bn254_fr)
}
}
fn to_le_bytes(self) -> [u8] {
self.inner.to_le_bytes()
}
}

impl Add for Bn254Fr {
fn add(self: Self, other: Bn254Fr) -> Bn254Fr {
Bn254Fr {
inner: self.inner.bigint_add(other.inner)
}
}
}
impl Sub for Bn254Fr {
fn sub(self: Self, other: Bn254Fr) -> Bn254Fr {
Bn254Fr {
inner: self.inner.bigint_sub(other.inner)
}
}
}
impl Mul for Bn254Fr {
fn mul(self: Self, other: Bn254Fr) -> Bn254Fr {
Bn254Fr {
inner: self.inner.bigint_mul(other.inner)
}

}
}
impl Div for Bn254Fr {
fn div(self: Self, other: Bn254Fr) -> Bn254Fr {
Bn254Fr {
inner: self.inner.bigint_div(other.inner)
}
}
}
impl Eq for Bn254Fr {
fn eq(self: Self, other: Bn254Fr) -> bool {
self.inner.check_32_bytes(other.inner)
}
}

struct Bn254Fq {
inner: BigInt,
}

impl BigField for Bn254Fq {
fn from_le_bytes(bytes: [u8]) -> Bn254Fq {
Bn254Fq {
inner: BigInt::from_le_bytes(bytes, bn254_fq)
}
}
fn to_le_bytes(self) -> [u8] {
self.inner.to_le_bytes()
}
}

impl Add for Bn254Fq {
fn add(self: Self, other: Bn254Fq) -> Bn254Fq {
Bn254Fq {
inner: self.inner.bigint_add(other.inner)
}
}
}
impl Sub for Bn254Fq {
fn sub(self: Self, other: Bn254Fq) -> Bn254Fq {
Bn254Fq {
inner: self.inner.bigint_sub(other.inner)
}
}
}
impl Mul for Bn254Fq {
fn mul(self: Self, other: Bn254Fq) -> Bn254Fq {
Bn254Fq {
inner: self.inner.bigint_mul(other.inner)
}

}
}
impl Div for Bn254Fq {
fn div(self: Self, other: Bn254Fq) -> Bn254Fq {
Bn254Fq {
inner: self.inner.bigint_div(other.inner)
}
}
}
impl Eq for Bn254Fq {
fn eq(self: Self, other: Bn254Fq) -> bool {
self.inner.check_32_bytes(other.inner)
}
}

struct Secpr1Fq {
inner: BigInt,
}

impl BigField for Secpr1Fq {
fn from_le_bytes(bytes: [u8]) -> Secpr1Fq {
Secpr1Fq {
inner: BigInt::from_le_bytes(bytes, secpr1_fq)
}
}
fn to_le_bytes(self) -> [u8] {
self.inner.to_le_bytes()
}
}

impl Add for Secpr1Fq {
fn add(self: Self, other: Secpr1Fq) -> Secpr1Fq {
Secpr1Fq {
inner: self.inner.bigint_add(other.inner)
}
}
}
impl Sub for Secpr1Fq {
fn sub(self: Self, other: Secpr1Fq) -> Secpr1Fq {
Secpr1Fq {
inner: self.inner.bigint_sub(other.inner)
}
}
}
impl Mul for Secpr1Fq {
fn mul(self: Self, other: Secpr1Fq) -> Secpr1Fq {
Secpr1Fq {
inner: self.inner.bigint_mul(other.inner)
}

}
}
impl Div for Secpr1Fq {
fn div(self: Self, other: Secpr1Fq) -> Secpr1Fq {
Secpr1Fq {
inner: self.inner.bigint_div(other.inner)
}
}
}
impl Eq for Secpr1Fq {
fn eq(self: Self, other: Secpr1Fq) -> bool {
self.inner.check_32_bytes(other.inner)
}
}

struct Secpr1Fr {
inner: BigInt,
}

impl BigField for Secpr1Fr {
fn from_le_bytes(bytes: [u8]) -> Secpr1Fr {
Secpr1Fr {
inner: BigInt::from_le_bytes(bytes, secpr1_fr)
}
}
fn to_le_bytes(self) -> [u8] {
self.inner.to_le_bytes()
}
}

impl Add for Secpr1Fr {
fn add(self: Self, other: Secpr1Fr) -> Secpr1Fr {
Secpr1Fr {
inner: self.inner.bigint_add(other.inner)
}
}
}
impl Sub for Secpr1Fr {
fn sub(self: Self, other: Secpr1Fr) -> Secpr1Fr {
Secpr1Fr {
inner: self.inner.bigint_sub(other.inner)
}
}
}
impl Mul for Secpr1Fr {
fn mul(self: Self, other: Secpr1Fr) -> Secpr1Fr {
Secpr1Fr {
inner: self.inner.bigint_mul(other.inner)
}

}
}
impl Div for Secpr1Fr {
fn div(self: Self, other: Secpr1Fr) -> Secpr1Fr {
Secpr1Fr {
inner: self.inner.bigint_div(other.inner)
}
}
}
impl Eq for Secpr1Fr {
fn eq(self: Self, other: Secpr1Fr) -> bool {
self.inner.check_32_bytes(other.inner)
}
}
2 changes: 1 addition & 1 deletion noir/test_programs/execution_success/3_add/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ fn main(mut x: u32, y: u32, z: u32) {

x *= 8;
assert(x > 9);
}
}
14 changes: 5 additions & 9 deletions noir/test_programs/execution_success/bigint/src/main.nr
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use dep::std::bigint;

fn main(mut x: [u8;5], y: [u8;5]) {
let a = bigint::BigInt::secpk1_fq_from_le_bytes([x[0],x[1],x[2],x[3],x[4]]);
let b = bigint::BigInt::secpk1_fq_from_le_bytes([y[0],y[1],y[2],y[3],y[4]]);

let a = bigint::Secpk1Fq::from_le_bytes([x[0],x[1],x[2],x[3],x[4]]);
let b = bigint::Secpk1Fq::from_le_bytes([y[0],y[1],y[2],y[3],y[4]]);
let a_bytes = a.to_le_bytes();
let b_bytes = b.to_le_bytes();
for i in 0..5 {
Expand All @@ -12,10 +11,7 @@ fn main(mut x: [u8;5], y: [u8;5]) {
}

let d = a*b - b;
let d_bytes = d.to_le_bytes();
let d1 = bigint::BigInt::secpk1_fq_from_le_bytes(597243850900842442924.to_le_bytes(10));
let d1_bytes = d1.to_le_bytes();
for i in 0..32 {
assert(d_bytes[i] == d1_bytes[i]);
}
let d1 = bigint::Secpk1Fq::from_le_bytes(597243850900842442924.to_le_bytes(10));
assert(d1 == d);

}
Loading