From 5aef5239f43430b12d423e0c70ec3ca3d07db571 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sat, 29 Apr 2023 01:03:38 +0200 Subject: [PATCH] change C from AffineRepr to CurveGroup, use MNT4,6 for tests, other minor changes --- Cargo.toml | 6 +- src/nifs.rs | 190 ++++++++++++++++++++++++------------------------ src/pedersen.rs | 34 +++++---- src/utils.rs | 7 +- 4 files changed, 120 insertions(+), 117 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8d961df..3bfc782 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ ark-serialize = { version = "0.4.0", default-features = false, features = [ "der rand = { version = "0.8", features = [ "std", "std_rng" ] } merlin = { version = "3.0.0" } -ark-crypto-primitives = { version = "^0.4.0", default-features = true, features = [ "r1cs", "snark" ] } +ark-crypto-primitives = { version = "^0.4.0", default-features = false, features = [ "r1cs", "snark"] } ark-r1cs-std = { version = "^0.4.0", default-features = false } ark-relations = { version = "^0.4.0", default-features = false } ark-snark = { version = "^0.4.0", default-features = false } @@ -24,4 +24,6 @@ tracing-subscriber = { version = "0.2" } derivative = { version = "2.0", features = ["use_core"] } [dev-dependencies] -ark-bn254 = { version = "0.4.0", default-features = false, features=["curve"] } +ark-mnt4-298 = { version = "0.4.0", default-features = false, features=["curve", "r1cs"] } +ark-mnt6-298 = { version = "0.4.0", default-features = false, features=["r1cs"] } +ark-ed-on-mnt4-298 = { version = "0.4.0", default-features = false, features=["r1cs"] } diff --git a/src/nifs.rs b/src/nifs.rs index d086f44..774190c 100644 --- a/src/nifs.rs +++ b/src/nifs.rs @@ -1,4 +1,5 @@ -use ark_ec::AffineRepr; +// use ark_ec::AffineRepr; +use ark_ec::CurveGroup; use ark_ff::fields::PrimeField; use ark_std::{ rand::{Rng, RngCore}, @@ -18,22 +19,23 @@ pub struct R1CS { } // Phi: φ in the paper (later 𝖴), a folded instance -pub struct Phi { - cmE: Commitment, - u: C::ScalarField, - cmW: Commitment, - x: Vec, +#[derive(Clone, Debug)] +pub struct Phi { + pub cmE: Commitment, + pub u: C::ScalarField, + pub cmW: Commitment, + pub x: C::ScalarField, } // FWit: Folded Witness -pub struct FWit { +pub struct FWit { E: Vec, rE: C::ScalarField, W: Vec, rW: C::ScalarField, } -impl FWit { +impl FWit { pub fn new(z: Vec, e_len: usize) -> Self { FWit:: { E: vec![C::ScalarField::zero(); e_len], @@ -49,16 +51,16 @@ impl FWit { cmE, u: C::ScalarField::one(), cmW, - x: self.W.clone(), + x: self.W[0].clone(), // TODO WIP review } } } -pub struct NIFS { +pub struct NIFS { _phantom: PhantomData, } -impl NIFS { +impl NIFS { // comp_T: compute cross-terms T pub fn comp_T( r1cs: &R1CS, @@ -123,13 +125,13 @@ impl NIFS { let cmE = phi1.cmE.0 + cmT.0.mul(r) + phi2.cmE.0.mul(r2); let u = phi1.u + r * phi2.u; let cmW = phi1.cmW.0 + phi2.cmW.0.mul(r); - let x = vec_add(&phi1.x, &vector_elem_product(&phi2.x, &r)); - // let x = rlin(phi1.x, phi2.x, r); + // let x = vec_add(&phi1.x, &vector_elem_product(&phi2.x, &r)); + let x = phi1.x + r * phi2.x; Phi:: { - cmE: Commitment(cmE.into()), + cmE: Commitment(cmE), u, - cmW: Commitment(cmW.into()), + cmW: Commitment(cmW), x, } } @@ -174,16 +176,17 @@ impl NIFS { cmT: &Commitment, ) -> bool { let r2 = r * r; - if phi3.cmE.0 != (phi1.cmE.0 + cmT.0.mul(r) + phi2.cmE.0.mul(r2)).into() { + if phi3.cmE.0 != (phi1.cmE.0 + cmT.0.mul(r) + phi2.cmE.0.mul(r2)) { return false; } if phi3.u != phi1.u + r * phi2.u { return false; } - if phi3.cmW.0 != (phi1.cmW.0 + phi2.cmW.0.mul(r)).into() { + if phi3.cmW.0 != (phi1.cmW.0 + phi2.cmW.0.mul(r)) { return false; } - if phi3.x != vec_add(&phi1.x, &vector_elem_product(&phi2.x, &r)) { + // if phi3.x != vec_add(&phi1.x, &vector_elem_product(&phi2.x, &r)) { + if phi3.x != phi1.x + r * phi2.x { return false; } true @@ -225,12 +228,53 @@ impl NIFS { } } +// only for tests across different files +pub fn gen_test_values( + rng: &mut R, +) -> (R1CS, Vec, Vec, Vec, Vec, Vec, Vec) { + // R1CS for: x^3 + x + 5 = y (example from article + // https://www.vitalik.ca/general/2016/12/10/qap.html ) + let A = to_F_matrix::(vec![ + vec![0, 1, 0, 0, 0, 0], + vec![0, 0, 0, 1, 0, 0], + vec![0, 1, 0, 0, 1, 0], + vec![5, 0, 0, 0, 0, 1], + ]); + let B = to_F_matrix::(vec![ + vec![0, 1, 0, 0, 0, 0], + vec![0, 1, 0, 0, 0, 0], + vec![1, 0, 0, 0, 0, 0], + vec![1, 0, 0, 0, 0, 0], + ]); + let C = to_F_matrix::(vec![ + vec![0, 0, 0, 1, 0, 0], + vec![0, 0, 0, 0, 1, 0], + vec![0, 0, 0, 0, 0, 1], + vec![0, 0, 1, 0, 0, 0], + ]); + // TODO in the future update this method to generate witness, and generate n witnesses + // instances, x: pub + let w1 = to_F_vec::(vec![1, 3, 35, 9, 27, 30]); + let x1 = to_F_vec::(vec![35]); + let w2 = to_F_vec::(vec![1, 4, 73, 16, 64, 68]); + let x2 = to_F_vec::(vec![73]); + let w3 = to_F_vec::(vec![1, 5, 135, 25, 125, 130]); + let x3 = to_F_vec::(vec![135]); + + let r1cs = R1CS:: { + A: A.clone(), + B: B.clone(), + C: C.clone(), + }; + (r1cs, w1, w2, w3, x1, x2, x3) +} + #[cfg(test)] mod tests { use super::*; use crate::pedersen::Pedersen; - use ark_bn254::{g1::G1Affine, Fr}; use ark_ec::CurveGroup; + use ark_mnt4_298::{Fr, G1Projective}; use ark_std::{ rand::{Rng, RngCore}, UniformRand, @@ -238,81 +282,33 @@ mod tests { use ark_std::{One, Zero}; use std::ops::Mul; - fn gen_test_values( - rng: &mut R, - ) -> ( - R1CS, - Vec, - Vec, - Vec, - Vec, - Vec, - Vec, - ) { - // R1CS for: x^3 + x + 5 = y (example from article - // https://www.vitalik.ca/general/2016/12/10/qap.html ) - let A = to_F_matrix::(vec![ - vec![0, 1, 0, 0, 0, 0], - vec![0, 0, 0, 1, 0, 0], - vec![0, 1, 0, 0, 1, 0], - vec![5, 0, 0, 0, 0, 1], - ]); - let B = to_F_matrix::(vec![ - vec![0, 1, 0, 0, 0, 0], - vec![0, 1, 0, 0, 0, 0], - vec![1, 0, 0, 0, 0, 0], - vec![1, 0, 0, 0, 0, 0], - ]); - let C = to_F_matrix::(vec![ - vec![0, 0, 0, 1, 0, 0], - vec![0, 0, 0, 0, 1, 0], - vec![0, 0, 0, 0, 0, 1], - vec![0, 0, 1, 0, 0, 0], - ]); - // TODO in the future update this method to generate witness, and generate n witnesses - // instances, x: pub - let w1 = to_F_vec::(vec![1, 3, 35, 9, 27, 30]); - let x1 = to_F_vec::(vec![35]); - let w2 = to_F_vec::(vec![1, 4, 73, 16, 64, 68]); - let x2 = to_F_vec::(vec![73]); - let w3 = to_F_vec::(vec![1, 5, 135, 25, 125, 130]); - let x3 = to_F_vec::(vec![135]); - - let r1cs = R1CS:: { - A: A.clone(), - B: B.clone(), - C: C.clone(), - }; - (r1cs, w1, w2, w3, x1, x2, x3) - } - // fold 2 instances into one #[test] fn test_one_fold() { let mut rng = ark_std::test_rng(); - let pedersen_params = Pedersen::::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec + let pedersen_params = Pedersen::::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec let (r1cs, w1, w2, _, x1, x2, _) = gen_test_values(&mut rng); let (A, B, C) = (r1cs.A.clone(), r1cs.B.clone(), r1cs.C.clone()); let r = Fr::rand(&mut rng); // this would come from the transcript - let fw1 = FWit::::new(w1.clone(), A.len()); - let fw2 = FWit::::new(w2.clone(), A.len()); + let fw1 = FWit::::new(w1.clone(), A.len()); + let fw2 = FWit::::new(w2.clone(), A.len()); // get committed instances let phi1 = fw1.commit(&pedersen_params); // wip let phi2 = fw2.commit(&pedersen_params); - let T = NIFS::::comp_T(&r1cs, phi1.u, phi2.u, &w1, &w2); + let T = NIFS::::comp_T(&r1cs, phi1.u, phi2.u, &w1, &w2); let rT: Fr = Fr::rand(&mut rng); let cmT = Pedersen::commit(&pedersen_params, &T, &rT); // fold witness - let fw3 = NIFS::::fold_witness(r, &fw1, &fw2, &T, rT); + let fw3 = NIFS::::fold_witness(r, &fw1, &fw2, &T, rT); // fold instance - let phi3 = NIFS::::fold_instance(r, &phi1, &phi2, &cmT); + let phi3 = NIFS::::fold_instance(r, &phi1, &phi2, &cmT); // naive check that the folded witness satisfies the relaxed r1cs let Az = matrix_vector_product(&A, &fw3.W); @@ -330,7 +326,7 @@ mod tests { assert_eq!(phi3_expected.cmW.0, phi3.cmW.0); // NIFS.Verify: - assert!(NIFS::::verify(r, &phi1, &phi2, &phi3, &cmT)); + assert!(NIFS::::verify(r, &phi1, &phi2, &phi3, &cmT)); // init Prover's transcript let mut transcript_p: Transcript = Transcript::::new(); @@ -338,7 +334,7 @@ mod tests { let mut transcript_v: Transcript = Transcript::::new(); // check openings of phi3.cmE, phi3.cmW and cmT - let (cmE_proof, cmW_proof, cmT_proof) = NIFS::::open_commitments( + let (cmE_proof, cmW_proof, cmT_proof) = NIFS::::open_commitments( &mut transcript_p, &pedersen_params, &fw3, @@ -347,7 +343,7 @@ mod tests { rT, &cmT, ); - let v = NIFS::::verify_commitments( + let v = NIFS::::verify_commitments( &mut transcript_v, &pedersen_params, phi3, @@ -362,41 +358,43 @@ mod tests { #[test] fn test_two_fold() { let mut rng = ark_std::test_rng(); - let pedersen_params = Pedersen::::new_params(&mut rng, 6); + let pedersen_params = Pedersen::::new_params(&mut rng, 6); let (r1cs, w1, w2, w3, x1, x2, x3) = gen_test_values(&mut rng); let u1: Fr = Fr::one(); let u2: Fr = Fr::one(); - let T_12 = NIFS::::comp_T(&r1cs, u1, u2, &w1, &w2); + let T_12 = NIFS::::comp_T(&r1cs, u1, u2, &w1, &w2); let rT_12: Fr = Fr::rand(&mut rng); let cmT_12 = Pedersen::commit(&pedersen_params, &T_12, &rT_12); let r = Fr::rand(&mut rng); // this would come from the transcript - let fw1 = FWit::::new(w1, T_12.len()); - let fw2 = FWit::::new(w2, T_12.len()); + let fw1 = FWit::::new(w1, T_12.len()); + let fw2 = FWit::::new(w2, T_12.len()); // fold witness - let fw_12 = NIFS::::fold_witness(r, &fw1, &fw2, &T_12, rT_12); + let fw_12 = NIFS::::fold_witness(r, &fw1, &fw2, &T_12, rT_12); // get committed instances let phi1 = fw1.commit(&pedersen_params); // wip let phi2 = fw2.commit(&pedersen_params); // fold instance - let phi_12 = NIFS::::fold_instance(r, &phi1, &phi2, &cmT_12); + let phi_12 = NIFS::::fold_instance(r, &phi1, &phi2, &cmT_12); // NIFS.Verify: - assert!(NIFS::::verify(r, &phi1, &phi2, &phi_12, &cmT_12)); + assert!(NIFS::::verify( + r, &phi1, &phi2, &phi_12, &cmT_12 + )); //---- // 2nd fold - let fw3 = FWit::::new(w3, r1cs.A.len()); + let fw3 = FWit::::new(w3, r1cs.A.len()); // compute cross terms - let T_123 = NIFS::::comp_T(&r1cs, phi_12.u, Fr::one(), &fw_12.W, &fw3.W); + let T_123 = NIFS::::comp_T(&r1cs, phi_12.u, Fr::one(), &fw_12.W, &fw3.W); let rT_123: Fr = Fr::rand(&mut rng); let cmT_123 = Pedersen::commit(&pedersen_params, &T_123, &rT_123); @@ -404,7 +402,7 @@ mod tests { let r = Fr::rand(&mut rng); // this would come from the transcript // fold witness - let fw_123 = NIFS::::fold_witness(r, &fw_12, &fw3, &T_123, rT_123); + let fw_123 = NIFS::::fold_witness(r, &fw_12, &fw3, &T_123, rT_123); // get committed instances // phi_12 is already known for Verifier from folding phi1, phi2 @@ -412,10 +410,10 @@ mod tests { let phi3 = fw3.commit(&pedersen_params); // fold instance - let phi_123 = NIFS::::fold_instance(r, &phi_12, &phi3, &cmT_123); + let phi_123 = NIFS::::fold_instance(r, &phi_12, &phi3, &cmT_123); // NIFS.Verify: - assert!(NIFS::::verify( + assert!(NIFS::::verify( r, &phi_12, &phi3, &phi_123, &cmT_123 )); @@ -440,7 +438,7 @@ mod tests { let mut transcript_v: Transcript = Transcript::::new(); // check openings of phi_123.cmE, phi_123.cmW and cmT_123 - let (cmE_proof, cmW_proof, cmT_proof) = NIFS::::open_commitments( + let (cmE_proof, cmW_proof, cmT_proof) = NIFS::::open_commitments( &mut transcript_p, &pedersen_params, &fw_123, @@ -449,7 +447,7 @@ mod tests { rT_123, &cmT_123, ); - let v = NIFS::::verify_commitments( + let v = NIFS::::verify_commitments( &mut transcript_v, &pedersen_params, phi_123, @@ -464,29 +462,29 @@ mod tests { #[test] fn test_nifs_interface() { let mut rng = ark_std::test_rng(); - let pedersen_params = Pedersen::::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec + let pedersen_params = Pedersen::::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec let (r1cs, w1, w2, _, x1, x2, _) = gen_test_values(&mut rng); let (A, B, C) = (r1cs.A.clone(), r1cs.B.clone(), r1cs.C.clone()); let r = Fr::rand(&mut rng); // this would come from the transcript - let fw1 = FWit::::new(w1.clone(), A.len()); - let fw2 = FWit::::new(w2.clone(), A.len()); + let fw1 = FWit::::new(w1.clone(), A.len()); + let fw2 = FWit::::new(w2.clone(), A.len()); // init Prover's transcript let mut transcript_p: Transcript = Transcript::::new(); // NIFS.P let (fw3, phi1, phi2, T, cmT) = - NIFS::::P(&mut transcript_p, &pedersen_params, r, &r1cs, fw1, fw2); + NIFS::::P(&mut transcript_p, &pedersen_params, r, &r1cs, fw1, fw2); // init Verifier's transcript let mut transcript_v: Transcript = Transcript::::new(); // NIFS.V - let phi3 = NIFS::::V(r, &phi1, &phi2, &cmT); + let phi3 = NIFS::::V(r, &phi1, &phi2, &cmT); - assert!(NIFS::::verify(r, &phi1, &phi2, &phi3, &cmT)); + assert!(NIFS::::verify(r, &phi1, &phi2, &phi3, &cmT)); } } diff --git a/src/pedersen.rs b/src/pedersen.rs index 0228001..f48a1c1 100644 --- a/src/pedersen.rs +++ b/src/pedersen.rs @@ -1,4 +1,5 @@ use ark_ec::AffineRepr; +use ark_ec::CurveGroup; use ark_std::{ rand::{Rng, RngCore}, UniformRand, @@ -8,35 +9,35 @@ use std::marker::PhantomData; use crate::transcript::Transcript; use crate::utils::{naive_msm, vec_add, vector_elem_product}; -pub struct Proof_elem { +pub struct Proof_elem { R: C, t1: C::ScalarField, t2: C::ScalarField, } -pub struct Proof { +pub struct Proof { R: C, u_: Vec, ru_: C::ScalarField, } -pub struct Params { +pub struct Params { g: C, h: C, pub generators: Vec, } -pub struct Pedersen { +pub struct Pedersen { _phantom: PhantomData, } -impl Pedersen { +impl Pedersen { pub fn new_params(rng: &mut R, max: usize) -> Params { let h_scalar = C::ScalarField::rand(rng); let g: C = C::generator(); let generators: Vec = vec![C::rand(rng); max]; let params: Params = Params:: { g, - h: g.mul(h_scalar).into(), + h: g.mul(h_scalar), generators, }; params @@ -48,7 +49,7 @@ impl Pedersen { v: &C::ScalarField, ) -> CommitmentElem { let r = C::ScalarField::rand(rng); - let cm: C = (params.g.mul(v) + params.h.mul(r)).into(); + let cm: C = (params.g.mul(v) + params.h.mul(r)); CommitmentElem:: { cm, r } } pub fn commit( @@ -57,7 +58,7 @@ impl Pedersen { r: &C::ScalarField, // random value is provided, in order to be choosen by other parts of the protocol ) -> Commitment { let cm = params.h.mul(r) + naive_msm(v, ¶ms.generators); - Commitment::(cm.into()) + Commitment::(cm) } pub fn prove_elem( @@ -70,7 +71,7 @@ impl Pedersen { let r1 = transcript.get_challenge(b"r_1"); let r2 = transcript.get_challenge(b"r_2"); - let R: C = (params.g.mul(r1) + params.h.mul(r2)).into(); + let R: C = (params.g.mul(r1) + params.h.mul(r2)); transcript.add(b"cm", &cm); transcript.add(b"R", &R); @@ -91,7 +92,7 @@ impl Pedersen { let r1 = transcript.get_challenge(b"r_1"); let d = transcript.get_challenge_vec(b"d", v.len()); - let R: C = (params.h.mul(r1) + naive_msm(&d, ¶ms.generators)).into(); + let R: C = params.h.mul(r1) + naive_msm(&d, ¶ms.generators); transcript.add(b"cm", &cm.0); transcript.add(b"R", &R); @@ -145,13 +146,14 @@ impl Pedersen { } } -pub struct Commitment(pub C); +#[derive(Clone, Debug)] +pub struct Commitment(pub C); -pub struct CommitmentElem { +pub struct CommitmentElem { pub cm: C, pub r: C::ScalarField, } -impl CommitmentElem { +impl CommitmentElem { pub fn prove( &self, params: &Params, @@ -165,8 +167,8 @@ impl CommitmentElem { #[cfg(test)] mod tests { use super::*; - use ark_bn254::{g1::G1Affine, Fr}; use ark_ec::CurveGroup; + use ark_mnt4_298::{Fr, G1Projective}; use std::ops::Mul; #[test] @@ -174,7 +176,7 @@ mod tests { let mut rng = ark_std::test_rng(); // setup params - let params = Pedersen::::new_params( + let params = Pedersen::::new_params( &mut rng, 0, /* 0, as here we don't use commit_vec */ ); @@ -198,7 +200,7 @@ mod tests { const n: usize = 10; // setup params - let params = Pedersen::::new_params(&mut rng, n); + let params = Pedersen::::new_params(&mut rng, n); // init Prover's transcript let mut transcript_p: Transcript = Transcript::::new(); diff --git a/src/utils.rs b/src/utils.rs index 0af04d8..04f3ca7 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,5 @@ use ark_ec::AffineRepr; +use ark_ec::CurveGroup; use ark_ff::fields::PrimeField; use core::ops::{Add, Sub}; use std::fmt; @@ -36,14 +37,14 @@ pub fn hadamard_product(a: Vec, b: Vec) -> Vec { // vec_add(a, vector_elem_product(&b, &r)) // WIP probably group loops // } -pub fn naive_msm(s: &Vec, p: &Vec) -> C { +pub fn naive_msm(s: &Vec, p: &Vec) -> C { // TODO check lengths, or at least check s.len()>= p.len() let mut r = p[0].mul(s[0]); for i in 1..s.len() { r = p[i].mul(s[i]); } - r.into() + r } pub fn vec_add(a: &Vec, b: &Vec) -> Vec { @@ -124,8 +125,8 @@ pub fn to_F_vec(z: Vec) -> Vec { #[cfg(test)] mod tests { use super::*; - use ark_bn254::{g1::G1Affine, Fr}; use ark_ec::CurveGroup; + use ark_mnt4_298::{g1::G1Affine, Fr}; use ark_std::{One, Zero}; use std::ops::Mul;