arnaucube
arnaucube/nova-studyPublic Self-hosted repository
update vec commitment, add check of comm E, W in NIFS test
arnaucube root@arnaucube.com
Wed, 19 Apr 2023 22:25:29 +0200
commit

ba567dffde3a9335fc7f336c79422c64c3d6b471

parent

ab2b04740225eb1e11cdf69632527bf993c558d9

3 files changed, 61 insertions(+), 85 deletions(-)

jump to
M src/nifs.rs → src/nifs.rs

@@ -3,7 +3,7 @@ use ark_std::ops::Add;

use ark_std::One; use std::marker::PhantomData; -use crate::pedersen::{Commitment, CommitmentVec, Params as PedersenParams, Pedersen}; +use crate::pedersen::{Commitment, Params as PedersenParams, Pedersen}; use crate::r1cs::*; use crate::transcript::Transcript; use crate::utils::*;

@@ -14,37 +14,28 @@ };

// Phi: φ in the paper (later 𝖴), a folded instance pub struct Phi<C: AffineRepr> { - // cmE: CommitmentVec<C>, // TODO not Commitment but directly C (without rE) - cmE: C, + cmE: Commitment<C>, u: C::ScalarField, - // cmW: CommitmentVec<C>, // TODO not Commitment but directly C (without rW) - cmW: C, + cmW: Commitment<C>, x: Vec<C::ScalarField>, } // FWit: Folded Witness pub struct FWit<C: AffineRepr> { E: Vec<C::ScalarField>, - rE: C::ScalarField, W: Vec<C::ScalarField>, - rW: C::ScalarField, } impl<C: AffineRepr> FWit<C> { - pub fn commit<R: Rng>( - &self, - rng: &mut R, - params: &PedersenParams<C>, - x: Vec<C::ScalarField>, - ) -> Phi<C> { - // TODO instead of rand r, use self.rE and self.rW for the commit_vec - let cmE = Pedersen::commit_vec(rng, &params, &self.E); - let cmW = Pedersen::commit_vec(rng, &params, &self.W); + pub fn commit(self, params: &PedersenParams<C>, x: &Vec<C::ScalarField>) -> Phi<C> { + // TODO instead of r_vec, use self.rE and self.rW for the commit + let cmE = Pedersen::commit(&params.r_vec, &self.E); + let cmW = Pedersen::commit(&params.r_vec, &self.W); Phi { - cmE: cmE.cm, + cmE, u: C::ScalarField::one(), - cmW: cmW.cm, - x, + cmW, + x: x.clone(), } } }

@@ -91,19 +82,15 @@ let r2 = r * r;

let E: Vec<C::ScalarField> = vec_add( // this syntax will be simplified with future operators impl (or at least a method // for r-lin) - vec_add(fw1.E.clone(), vector_elem_product(&T, &r)), + &vec_add(&fw1.E, &vector_elem_product(&T, &r)), // rlin(fw1.E.clone(), T, r), - vector_elem_product(&fw2.E, &r2), + &vector_elem_product(&fw2.E, &r2), ); - let rE = fw1.rE + r2 * fw2.rE; // TODO rT - let W = vec_add(fw1.W.clone(), vector_elem_product(&fw2.W, &r)); + let W = vec_add(&fw1.W, &vector_elem_product(&fw2.W, &r)); // let W = rlin(fw1.W.clone(), fw2.W.clone(), r); - let rW = fw1.rW + r * fw2.rW; FWit::<C> { E: E.into(), - rE, W: W.into(), - rW, } }

@@ -111,28 +98,20 @@ pub fn fold_instance(

r: C::ScalarField, phi1: Phi<C>, phi2: Phi<C>, - cmT: CommitmentVec<C>, + cmT: Commitment<C>, ) -> Phi<C> { let r2 = r * r; - let cmE = phi1.cmE + cmT.cm.mul(r) + phi2.cmE.mul(r2); + 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 + phi2.cmW.mul(r); - let x = vec_add(phi1.x, vector_elem_product(&phi2.x, &r)); + 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); Phi::<C> { - // cmE: Commitment::<C> { - // cm: cmE.into(), - // r: phi1.cmE.r, - // }, - cmE: cmE.into(), + cmE: Commitment(cmE.into()), u, - // cmW: Commitment::<C> { - // cm: cmW.into(), - // r: phi1.cmW.r, - // }, - cmW: cmW.into(), + cmW: Commitment(cmW.into()), x, } }

@@ -194,44 +173,44 @@ }

.relax(); let T = NIFS::<G1Affine>::comp_T(relaxed_r1cs_1, relaxed_r1cs_2, &z1, &z2); - let params = Pedersen::<G1Affine>::new_params(&mut rng); - let cmT = Pedersen::commit_vec(&mut rng, &params, &T); + let pedersen_params = Pedersen::<G1Affine>::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec + let cmT = Pedersen::commit(&pedersen_params.r_vec, &T); let r = Fr::rand(&mut rng); // this would come from the transcript // WIP TMP let fw1 = FWit::<G1Affine> { E: vec![Fr::zero(); T.len()], - rE: Fr::zero(), W: z1, - rW: Fr::zero(), }; let fw2 = FWit::<G1Affine> { E: vec![Fr::zero(); T.len()], - rE: Fr::zero(), W: z2, - rW: Fr::zero(), }; // fold witness - let folded_witness = NIFS::<G1Affine>::fold_witness(r, &fw1, &fw2, T); + let fw3 = NIFS::<G1Affine>::fold_witness(r, &fw1, &fw2, T); - let pedersen_params = Pedersen::<G1Affine>::new_params(&mut rng); - let phi1 = fw1.commit(&mut rng, &pedersen_params, x1); // wip - let phi2 = fw2.commit(&mut rng, &pedersen_params, x2); + // let pedersen_params = Pedersen::<G1Affine>::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec + let phi1 = fw1.commit(&pedersen_params, &x1); // wip + let phi2 = fw2.commit(&pedersen_params, &x2); // fold instance - let folded_instance = NIFS::<G1Affine>::fold_instance(r, phi1, phi2, cmT); + let phi3 = NIFS::<G1Affine>::fold_instance(r, phi1, phi2, cmT); // naive check that the folded witness satisfies the relaxed r1cs - let Az = matrix_vector_product(&A, &folded_witness.W); - let Bz = matrix_vector_product(&B, &folded_witness.W); - let Cz = matrix_vector_product(&C, &folded_witness.W); + let Az = matrix_vector_product(&A, &fw3.W); + let Bz = matrix_vector_product(&B, &fw3.W); + let Cz = matrix_vector_product(&C, &fw3.W); assert_eq!( hadamard_product(Az, Bz), - vec_add( - vector_elem_product(&Cz, &folded_instance.u), - folded_witness.E - ) + vec_add(&vector_elem_product(&Cz, &phi3.u), &fw3.E) ); + + // check that folded commitments from folded instance (phi) are equal to folding the + // witnesses and committing into it + let x3 = vec_add(&x1, &vector_elem_product(&x2, &r)); + let phi3_expected = fw3.commit(&pedersen_params, &x3); + assert_eq!(phi3_expected.cmE.0, phi3.cmE.0); + assert_eq!(phi3_expected.cmW.0, phi3.cmW.0); } }
M src/pedersen.rs → src/pedersen.rs

@@ -17,6 +17,7 @@

pub struct Params<C: AffineRepr> { g: C, h: C, + pub r_vec: Vec<C>, } pub struct Pedersen<C: AffineRepr> {

@@ -24,12 +25,14 @@ _phantom: PhantomData<C>,

} impl<C: AffineRepr> Pedersen<C> { - pub fn new_params<R: Rng>(rng: &mut R) -> Params<C> { + pub fn new_params<R: Rng>(rng: &mut R, max: usize) -> Params<C> { let h_scalar = C::ScalarField::rand(rng); let g: C = C::generator(); + let r_vec: Vec<C> = vec![C::rand(rng); max]; let params: Params<C> = Params::<C> { g, h: g.mul(h_scalar).into(), + r_vec, // will need 2 r: rE, rW }; params }

@@ -38,22 +41,17 @@ pub fn commit_elem<R: RngCore>(

rng: &mut R, params: &Params<C>, v: &C::ScalarField, - ) -> Commitment<C> { + ) -> CommitmentElem<C> { let r = C::ScalarField::rand(rng); let cm: C = (params.g.mul(v) + params.h.mul(r)).into(); - Commitment::<C> { cm, r } + CommitmentElem::<C> { cm, r } } - pub fn commit_vec<R: RngCore>( - rng: &mut R, - params: &Params<C>, - v: &Vec<C::ScalarField>, - ) -> CommitmentVec<C> { - let r: Vec<C> = vec![C::rand(rng); v.len()]; // wip - let cm = naive_msm(v, &r); - CommitmentVec::<C> { cm, r } + pub fn commit(rs: &Vec<C>, v: &Vec<C::ScalarField>) -> Commitment<C> { + let cm = naive_msm(v, &rs); + Commitment::<C>(cm) } - pub fn prove( + pub fn prove_elem( params: &Params<C>, transcript: &mut Transcript<C::ScalarField>, cm: C,

@@ -75,7 +73,7 @@

Proof::<C> { R, t1, t2 } } - pub fn verify( + pub fn verify_elem( params: &Params<C>, transcript: &mut Transcript<C::ScalarField>, cm: C,

@@ -97,23 +95,20 @@ true

} } -pub struct CommitmentVec<C: AffineRepr> { - // WIP - pub cm: C, - pub r: Vec<C>, -} -pub struct Commitment<C: AffineRepr> { +pub struct Commitment<C: AffineRepr>(pub C); + +pub struct CommitmentElem<C: AffineRepr> { pub cm: C, pub r: C::ScalarField, } -impl<C: AffineRepr> Commitment<C> { +impl<C: AffineRepr> CommitmentElem<C> { pub fn prove( &self, params: &Params<C>, transcript: &mut Transcript<C::ScalarField>, v: C::ScalarField, ) -> Proof<C> { - Pedersen::<C>::prove(params, transcript, self.cm, v, self.r) + Pedersen::<C>::prove_elem(params, transcript, self.cm, v, self.r) } }

@@ -129,7 +124,9 @@ fn test_pedersen() {

let mut rng = ark_std::test_rng(); // setup params - let params = Pedersen::<G1Affine>::new_params(&mut rng); + let params = Pedersen::<G1Affine>::new_params( + &mut rng, 0, /* 0, as here we don't use commit_vec */ + ); // init Prover's transcript let mut transcript_p: Transcript<Fr> = Transcript::<Fr>::new();

@@ -141,8 +138,8 @@

let cm = Pedersen::commit_elem(&mut rng, &params, &v); let proof = cm.prove(&params, &mut transcript_p, v); // also can use: - // let proof = Pedersen::prove(&params, &mut transcript_p, cm.cm, v, cm.r); - let v = Pedersen::verify(&params, &mut transcript_v, cm.cm, proof); + // let proof = Pedersen::prove_elem(&params, &mut transcript_p, cm.cm, v, cm.r); + let v = Pedersen::verify_elem(&params, &mut transcript_v, cm.cm, proof); assert!(v); } }
M src/utils.rs → src/utils.rs

@@ -37,7 +37,7 @@ // vec_add(a, vector_elem_product(&b, &r)) // WIP probably group loops

// } pub fn naive_msm<C: AffineRepr>(s: &Vec<C::ScalarField>, p: &Vec<C>) -> C { - // check lengths + // 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() {

@@ -46,7 +46,7 @@ }

r.into() } -pub fn vec_add<F: PrimeField>(a: Vec<F>, b: Vec<F>) -> Vec<F> { +pub fn vec_add<F: PrimeField>(a: &Vec<F>, b: &Vec<F>) -> Vec<F> { let mut r: Vec<F> = vec![F::zero(); a.len()]; for i in 0..a.len() { r[i] = a[i] + b[i];

@@ -155,7 +155,7 @@ #[test]

fn test_vec_add() { let a: Vec<Fr> = to_F_vec::<Fr>(vec![1, 2, 3, 4, 5, 6]); let b: Vec<Fr> = to_F_vec(vec![7, 8, 9, 10, 11, 12]); - assert_eq!(vec_add(a.clone(), b.clone()), (Ve(a) + Ve(b)).0); + assert_eq!(vec_add(&a, &b), (Ve(a) + Ve(b)).0); } #[test]