Skip to content

Commit

Permalink
chore: add struct for each bigint modulus (#4422)
Browse files Browse the repository at this point in the history
Resolves Noir issue noir-lang/noir#4257

The PR simply adds one struct per modulus, so that the user cannot mix
them.
  • Loading branch information
guipublic committed Feb 15, 2024
1 parent c3a784f commit a2942b7
Show file tree
Hide file tree
Showing 3 changed files with 308 additions and 37 deletions.
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;
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;
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);

}

0 comments on commit a2942b7

Please sign in to comment.