Giter Club home page Giter Club logo

noir-bn254's Introduction

noir-bn254

BN254 Elliptic Curve Pairing Library

How to test the library

  1. Use following commands to use two libraries in your local

git clone https://github.com/onurinanc/noir-bn254

  1. To add the noir-bigint dependency, use a forked version of https://github.com/shuklaayush/noir-bigint,

git clone https://github.com/onurinanc/noir-bigint

  1. Test the files using the following commands inside the noir-bn254. nargo test

Documentation

Curve Description and Usage

BN254 is a pairing-friendly elliptic curve construction. This includes two elliptic curve constructions which are G1: E(Fp) and G2: E(Fp^2).

G1 curve is y^2 = x^3 + 3 Field modulus is 21888242871839275222246405745257275088696311157297823662689037894645226208583 The order of the elliptic curves is 21888242871839275222246405745257275088548364400416034343698204186575808495617 The generator of the G1 is the (1, 2)

The method and parameters for constructing the G1 curve is in the src/bn254.nr

// Construct G1 curve for BN254
fn bn254() -> BN254 {
    BN254 {
        curve: Curve::new(
            Fp::zero(),
            Fp::from_u56(3),
            Point::from_affine( 
                Fp::from_u56(1),
                Fp::from_u56(2),
            ),
        ),
    }
}

G2 is constructed using the Fp^2 extension field. The method and the parameters for constructing the G2 curve is in the src/bn254.nr

// Construct G2 curve for BN254
fn bn254_g2() -> BN254G2 {
    // Construct a, b, and gen for G2 Curve
    // G2_A, G2_B_ G2_GENERATOR_X, and G2_GENERATOR_Y

    let G2_A = Fp2::zero();
    let G2_B: Fp2 = Fp2::new(
        Fp::from_bytes(
                    [
                        0xe5, 0x38, 0xa1, 0x24, 0xdc, 0xe6, 0x67, 0x32, 
                        0xa3, 0xef, 0xdb, 0x59, 0xe5, 0xc5, 0xb4, 0xb5, 
                        0xc3, 0x6a, 0xe0, 0x1b, 0x99, 0x18, 0xbe, 0x81, 
                        0xae, 0xaa, 0xb8, 0xce, 0x40, 0x9d, 0x14, 0x2b
                    ]
                ),
        Fp::from_bytes(
                    [
                        0xd2, 0x15, 0xc3, 0x85, 0x06, 0xbd, 0xa2, 0xe4, 
                        0x52, 0x18, 0x2d, 0xe5, 0x84, 0xa0, 0x4f, 0xa7, 
                        0xf4, 0xfd, 0xd8, 0xee, 0xad, 0xaf, 0x2c, 0xcd, 
                        0xd4, 0xfe, 0xf0, 0x3a, 0xb0, 0x13, 0x97, 0x00
                    ]
                )
    );
    let G2_GENERATOR_X: Fp2 = Fp2::new(
        Fp::from_bytes(
                    [
                        0xed, 0xf6, 0x92, 0xd9, 0x5c, 0xbd, 0xde, 0x46, 
                        0xdd, 0xda, 0x5e, 0xf7, 0xd4, 0x22, 0x43, 0x67, 
                        0x79, 0x44, 0x5c, 0x5e, 0x66, 0x00, 0x6a, 0x42, 
                        0x76, 0x1e, 0x1f, 0x12, 0xef, 0xde, 0x00, 0x18
                    ]
                ),
        Fp::from_bytes(
                    [
                        0xc2, 0x12, 0xf3, 0xae, 0xb7, 0x85, 0xe4, 0x97, 
                        0x12, 0xe7, 0xa9, 0x35, 0x33, 0x49, 0xaa, 0xf1, 
                        0x25, 0x5d, 0xfb, 0x31, 0xb7, 0xbf, 0x60, 0x72, 
                        0x3a, 0x48, 0x0d, 0x92, 0x93, 0x93, 0x8e, 0x19
                    ]
                )
    );

    let G2_GENERATOR_Y: Fp2 = Fp2::new(
        Fp::from_bytes(
                    [
                        0xaa, 0x7d, 0xfa, 0x66, 0x01, 0xcc, 0xe6, 0x4c, 
                        0x7b, 0xd3, 0x43, 0x0c, 0x69, 0xe7, 0xd1, 0xe3, 
                        0x8f, 0x40, 0xcb, 0x8d, 0x80, 0x71, 0xab, 0x4a, 
                        0xeb, 0x6d, 0x8c, 0xdb, 0xa5, 0x5e, 0xc8, 0x12
                    ]
                ),
        Fp::from_bytes(
                    [
                        0x5b, 0x97, 0x22, 0xd1, 0xdc, 0xda, 0xac, 0x55, 
                        0xf3, 0x8e, 0xb3, 0x70, 0x33, 0x31, 0x4b, 0xbc, 
                        0x95, 0x33, 0x0c, 0x69, 0xad, 0x99, 0x9e, 0xec, 
                        0x75, 0xf0, 0x5f, 0x58, 0xd0, 0x89, 0x06, 0x09
                    ]
                )
    );

    BN254G2 {
        curve: G2Curve::new(
            Fp2::zero(),
            G2_B,
            G2Point::from_affine(
                G2_GENERATOR_X,
                G2_GENERATOR_Y,
            )
        )
    }
}

You can create instances of the elliptic curves using

let g2: BN254G2 = bn254_g2();
let g1: BN254 = bn254();

You can test additions for G1 and G2 seperately using the following command in Noir

nargo test test_bn254_add1
nargo test test_bn254g2_add1

Features

  • fn pair(Q: G2Point, P: Point) -> Fp12

It's the pairing function. Q is an element of G2, and P is an element of G1.

  • The pair calculates the pairing in Fp12

  • Point is a point on the G1 curve

  • G2Point is a point on the G2 curve

You can create Point and G2Point as the following function signatures

  • Point::from_affine(x: Fp, y: Fp)
  • G2Point::from_affine(x: Fp2, y:Fp2)

You can create Fp, Fp2, Fp6, Fp12 elements using the following examples

let fp_1 = Fp::from_bytes([
            0x61, 0x22, 0xfe, 0xd9,
            0x3d, 0xff,	0xf1, 0xcd,
            0x57, 0x5b,	0x9c, 0x0b,
            0xb4, 0x63,	0x9e, 0x31,
            0x75, 0x64,	0x08, 0x8d,
            0x7c, 0xdb,	0x4f, 0x55,
            0x29, 0x94,	0x48, 0xe0,
            0xbe, 0x99,	0xb7, 0x2a,
        ]);

let fp_2 = Fp::from_u56(8);

let a: Fp2 = Fp2::new(Fp::from_u56(1), Fp::from_u56(2));
let b: Fp2 = Fp2::new(Fp::from_u56(3), Fp::from_u56(5));
let c: Fp2 = Fp2::new(Fp::from_u56(8), Fp::from_u56(11));

let a1: Fp6 = Fp6::new(a, b, c);
let a2: Fp6 = Fp6::new(a, a, b);
let a3: Fp6 = Fp6::new(b, c, c);
let a4: Fp6 = Fp6::new(c, b, a);

let x1: Fp12 = Fp12::new(a1, a4);
let x2: Fp12 = Fp12::new(a3, a2);
let x3: Fp12 = Fp12::new(a4, a2);

Benchmark

Compilation time for one pairing function takes ~0.5 h for 16 GB RAM, Intel Core i5-12450H

Contributing

Contributions are welcome! Please adhere to the following guidelines:

  • Open a pull request with a clear description of your changes.
  • Changes should aim to improve code efficiency or readability.
  • Add appropriate tests, ensuring all pass before submission.

Disclaimer

This is an experimental software and is provided on an "as is" and "as available" basis. We do not give any warranties and will not be liable for any losses incurred through any use of this code base.

noir-bn254's People

Contributors

onurinanc avatar

Stargazers

 avatar Vu Vo avatar Sriram avatar 0xYYY avatar nullity avatar Sandalots avatar Georgios Konstantopoulos avatar Rodrigo Ferreira avatar Harvey Specter avatar Mamy Ratsimbazafy avatar Erhan avatar lichu acuña avatar  avatar Ivan Litteri avatar  avatar Tao Xu avatar Maddiaa avatar Maxim Vezenov avatar  avatar

Watchers

 avatar

noir-bn254's Issues

OOM while trying to compile on Noir versions past 0.9.0

I've been trying to compile this codebase with newer versions of Noir, mainly trying with 0.11.1-aztec.0 (to try and deploy a contract using it in the sandbox) and 0.14.1, and I'm running into an out-of-memory issue, and just giving it more memory does not seem to be enough for it to compile.

Trying to narrow things down, it looks like one of the main culprits is Fp12 exponentiation, since I observe the OOM in tests test_fp12_final_exp and test_final_exponentiation, and not just when compiling the pairing function. I've commented out chunks of the final_exponentiate code to try and identify which specific calls make the compiler use so much memory, and landed in the Fp12::exponentiation function, which in my tests makes noir use over 900GiB of RAM during compilation before eventually running into a stack overflow if you give it enough RAM/swap space to keep running without OOMing.

I've also quickly tried other noir versions, and it seems like any version beyond 0.9.0 has issues compiling this code, so I'm guessing it's probably related to the SSA backend that was refactored and replaced in 0.10.0? I'm not sure if the code in this repo is just naturally leading to a large circuit that can't be compiled with the refactored codebase, or if there is something in how the code is written/organized that is making Fp12::exponentiation trigger some bug in the compiler.

Have you made any attempts at compiling with newer versions of Noir, or do you have any insight on the root cause of this memory regression?

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.