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

Add BN254 Curve for Groth16 #961

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
groth 16 for bn254. Tests working with all the constants
  • Loading branch information
Nicole authored and Nicole committed Jan 16, 2025
commit 030ef4d52a98ed499cde6313c99cbc93b4d6f2c6
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ use crate::{
field::{
element::FieldElement,
fields::montgomery_backed_prime_fields::{IsModulus, MontgomeryBackendPrimeField},
traits::IsFFTField,
},
unsigned_integer::element::U256,
unsigned_integer::element::{UnsignedInteger, U256},
};

#[derive(Clone, Debug)]
pub struct FrConfig;

/// Modulus of bn 254 subgroup r = 21888242871839275222246405745257275088548364400416034343698204186575808495617, aka order
/// We define Fr where r is the number of points that the eliptic curve BN254 has.
/// I.e. r is the order of the group BN254 Curve.
/// r = 21888242871839275222246405745257275088548364400416034343698204186575808495617.
impl IsModulus<U256> for FrConfig {
const MODULUS: U256 = U256::from_hex_unchecked(
"30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001",
Expand All @@ -20,3 +23,16 @@ impl IsModulus<U256> for FrConfig {
pub type FrField = MontgomeryBackendPrimeField<FrConfig, 4>;
/// FrElement using MontgomeryBackend for Bn254
pub type FrElement = FieldElement<FrField>;

/// TWO_ADICITY is 28 because there is a subgroup of Fr of order 2^28.
/// Note that 2^28 divides r - 1.
/// (r - 1) / 2^28 mod r = 81540058820840996586704275553141814055101440848469862132140264610111.
/// We calculated the TWO_ADIC_PRIMITVE_ROOT_OF_UNITY in the following way:
/// g = 5 is a primitive root of order r - 1, that is, g^{r-1} = 1 and g^i != 1 for i < r-1.
/// Then g^{(r-1) / 2^28} is a primitive root of order 2^28.
impl IsFFTField for FrField {
const TWO_ADICITY: u64 = 28;
const TWO_ADIC_PRIMITVE_ROOT_OF_UNITY: Self::BaseType = UnsignedInteger::from_hex_unchecked(
"2A3C09F0A58A7E8500E0A7EB8EF62ABC402D111E41112ED49BD61B6E725B19F0",
);
}
62 changes: 46 additions & 16 deletions provers/groth16/circom-adapter/src/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use lambdaworks_groth16::*;
const TEST_DIR: &str = "test_files";

// Proves & verifies a Poseidon circuit with 1 input and 2 outputs. The input is decimal 100.
// Converts the following circuit: https://github.com/iden3/circomlib/blob/master/circuits/poseidon.circom
// Poseidon constants: https://github.com/iden3/circomlib/blob/master/circuits/poseidon_constants.circom
#[test]
fn poseidon_parse_prove_verify() {
let test_dir = format!("{TEST_DIR}/poseidon");
Expand Down Expand Up @@ -64,30 +66,30 @@ fn vitalik_w_and_qap() {
// Same ordering difference exists for variable matrices, too. Circom adapter changes the
// order of the rows in the same way it rearranges the witness ordering.

const BLS12381_MINUS_ONE_STR: &str =
"0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000";
const BLS12381_ZERO_STR: &str = "0x0";
const BLS12381_ONE_STR: &str = "0x1";
const R_MINUS_ONE_STR: &str =
"30644E72E131A029B85045B68181585D2833E84879B9709143E1F593F0000000";
const ZERO_STR: &str = "0x0";
const ONE_STR: &str = "0x1";

let expected_num_of_public_inputs = 1;
let [temp_l, temp_r, temp_o] = [
[
[BLS12381_ZERO_STR, BLS12381_ZERO_STR], // 1
[BLS12381_MINUS_ONE_STR, BLS12381_ZERO_STR], // x
[BLS12381_ZERO_STR, BLS12381_ZERO_STR], // ~out
[BLS12381_ZERO_STR, BLS12381_MINUS_ONE_STR], // sym_1
[ZERO_STR, ZERO_STR], // 1
[R_MINUS_ONE_STR, ZERO_STR], // x
[ZERO_STR, ZERO_STR], // ~out
[ZERO_STR, R_MINUS_ONE_STR], // sym_1
],
[
[BLS12381_ZERO_STR, BLS12381_ZERO_STR], // 1
[BLS12381_ONE_STR, BLS12381_ONE_STR], // x
[BLS12381_ZERO_STR, BLS12381_ZERO_STR], // ~out
[BLS12381_ZERO_STR, BLS12381_ZERO_STR], // sym_1
[ZERO_STR, ZERO_STR], // 1
[ONE_STR, ONE_STR], // x
[ZERO_STR, ZERO_STR], // ~out
[ZERO_STR, ZERO_STR], // sym_1
],
[
[BLS12381_ZERO_STR, "5"], // 1
[BLS12381_ZERO_STR, BLS12381_ONE_STR], // x
[BLS12381_ZERO_STR, BLS12381_MINUS_ONE_STR], // ~out
[BLS12381_MINUS_ONE_STR, BLS12381_ZERO_STR], // sym_1
[ZERO_STR, "5"], // 1
[ZERO_STR, ONE_STR], // x
[ZERO_STR, R_MINUS_ONE_STR], // ~out
[R_MINUS_ONE_STR, ZERO_STR], // sym_1
],
]
.map(|matrix| matrix.map(|row| row.map(FrElement::from_hex_unchecked).to_vec()));
Expand All @@ -102,3 +104,31 @@ fn vitalik_w_and_qap() {
assert_eq!(qap.r, expected_r);
assert_eq!(qap.o, expected_o);
}

#[test]
fn fibonacci_verify() {
// Define the directory containing the R1CS and witness files
let test_dir = format!("{TEST_DIR}/fibonacci");

// Step 1: Parse R1CS and witness from JSON files
let (qap, w) = circom_to_lambda(
&fs::read_to_string(format!("{test_dir}/fibonacci.r1cs.json"))
.expect("Error reading the R1CS file"),
&fs::read_to_string(format!("{test_dir}/witness.json"))
.expect("Error reading the witness file"),
);

// Step 2: Generate the proving and verifying keys using the QAP
let (pk, vk) = setup(&qap);

// Step 3: Generate the proof using the proving key and witness
let proof = Prover::prove(&w, &qap, &pk);

// Step 4: Verify the proof using the verifying key and public inputs
let accept = verify(&vk, &proof, &w[..qap.num_of_public_inputs]);

// Step 5: Assert that the verification is successful
assert!(accept, "Proof verification failed.");

println!("Proof verification succeeded. All steps completed.");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
{
"n8": 32,
"prime": "21888242871839275222246405745257275088548364400416034343698204186575808495617",
"nVars": 12,
"nOutputs": 1,
"nPubInputs": 0,
"nPrvInputs": 2,
"nLabels": 15,
"nConstraints": 9,
"useCustomGates": false,
"constraints": [
[
{},
{},
{
"2": "1",
"3": "1",
"4": "21888242871839275222246405745257275088548364400416034343698204186575808495616"
}
],
[
{},
{},
{
"3": "1",
"4": "1",
"5": "21888242871839275222246405745257275088548364400416034343698204186575808495616"
}
],
[
{},
{},
{
"4": "1",
"5": "1",
"6": "21888242871839275222246405745257275088548364400416034343698204186575808495616"
}
],
[
{},
{},
{
"5": "1",
"6": "1",
"7": "21888242871839275222246405745257275088548364400416034343698204186575808495616"
}
],
[
{},
{},
{
"6": "1",
"7": "1",
"8": "21888242871839275222246405745257275088548364400416034343698204186575808495616"
}
],
[
{},
{},
{
"7": "1",
"8": "1",
"9": "21888242871839275222246405745257275088548364400416034343698204186575808495616"
}
],
[
{},
{},
{
"8": "1",
"9": "1",
"10": "21888242871839275222246405745257275088548364400416034343698204186575808495616"
}
],
[
{},
{},
{
"9": "1",
"10": "1",
"11": "21888242871839275222246405745257275088548364400416034343698204186575808495616"
}
],
[
{},
{},
{
"1": "21888242871839275222246405745257275088548364400416034343698204186575808495616",
"10": "1",
"11": "1"
}
]
],
"map": [
0,
1,
2,
3,
6,
7,
8,
9,
10,
11,
12,
13
],
"customGates": [],
"customGatesUses": []
}
14 changes: 14 additions & 0 deletions provers/groth16/circom-adapter/test_files/fibonacci/witness.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
"1",
"89",
"1",
"1",
"2",
"3",
"5",
"8",
"13",
"21",
"34",
"55"
]
Loading