check openings of folded instance comms cmE, cmW

This commit is contained in:
2023-04-20 09:47:45 +02:00
parent 402fb41458
commit 71d8150a60
4 changed files with 746 additions and 44 deletions

View File

@@ -3,7 +3,7 @@
#![allow(non_upper_case_globals)]
#![allow(unused)] // TMP
// mod nifs;
mod nifs;
mod pedersen;
mod r1cs;
mod transcript;

View File

@@ -1,6 +1,5 @@
use ark_ec::AffineRepr;
use ark_std::ops::Add;
use ark_std::One;
use ark_std::{One, Zero};
use std::marker::PhantomData;
use crate::pedersen::{Commitment, Params as PedersenParams, Pedersen};
@@ -14,23 +13,24 @@ use ark_std::{
// Phi: φ in the paper (later 𝖴), a folded instance
pub struct Phi<C: AffineRepr> {
cmE: Commitment<C>,
cmE: Commitment<C>, // TODO do not contain Commitment, only Commitment.cm (without the randomness)
u: C::ScalarField,
cmW: Commitment<C>,
cmW: Commitment<C>, // TODO same as in cmE
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(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);
pub fn commit(&self, params: &PedersenParams<C>, x: &Vec<C::ScalarField>) -> Phi<C> {
let cmE = Pedersen::commit(&params, &self.E, &self.rE);
let cmW = Pedersen::commit(&params, &self.W, &self.rW);
Phi {
cmE,
u: C::ScalarField::one(),
@@ -77,20 +77,23 @@ impl<C: AffineRepr> NIFS<C> {
fw1: &FWit<C>,
fw2: &FWit<C>,
T: Vec<C::ScalarField>,
rT: C::ScalarField,
) -> FWit<C> {
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, &vector_elem_product(&T, &r)),
// rlin(fw1.E.clone(), T, r),
&vector_elem_product(&fw2.E, &r2),
);
let rE = fw1.rE + r * rT + r2 * fw2.rE;
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,
}
}
@@ -174,26 +177,32 @@ mod tests {
let T = NIFS::<G1Affine>::comp_T(relaxed_r1cs_1, relaxed_r1cs_2, &z1, &z2);
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 rT: Fr = Fr::rand(&mut rng);
let cmT = Pedersen::commit(&pedersen_params, &T, &rT);
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::one(),
W: z1,
rW: Fr::one(),
};
let fw2 = FWit::<G1Affine> {
E: vec![Fr::zero(); T.len()],
rE: Fr::one(),
W: z2,
rW: Fr::one(),
};
// fold witness
let fw3 = NIFS::<G1Affine>::fold_witness(r, &fw1, &fw2, T);
let fw3 = NIFS::<G1Affine>::fold_witness(r, &fw1, &fw2, T, rT);
// let pedersen_params = Pedersen::<G1Affine>::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec
// get committed instances
let phi1 = fw1.commit(&pedersen_params, &x1); // wip
let phi2 = fw2.commit(&pedersen_params, &x2);
// fold instance
let phi3 = NIFS::<G1Affine>::fold_instance(r, phi1, phi2, cmT);
@@ -209,8 +218,43 @@ mod tests {
// 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));
// use folded rE, rW to commit fw3
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);
// init Prover's transcript
let mut transcript_p: Transcript<Fr> = Transcript::<Fr>::new();
// init Verifier's transcript
let mut transcript_v: Transcript<Fr> = Transcript::<Fr>::new();
// check openings of phi3.cmE and phi3.cmW
let phi3_cmE_proof = Pedersen::prove(
&pedersen_params,
&mut transcript_p,
&phi3.cmE,
fw3.E,
fw3.rE,
);
let v = Pedersen::verify(
&pedersen_params,
&mut transcript_v,
phi3.cmE,
phi3_cmE_proof,
);
let phi3_cmW_proof = Pedersen::prove(
&pedersen_params,
&mut transcript_p,
&phi3.cmW,
fw3.W,
fw3.rW,
);
let v = Pedersen::verify(
&pedersen_params,
&mut transcript_v,
phi3.cmW,
phi3_cmW_proof,
);
}
}

View File

@@ -51,14 +51,13 @@ impl<C: AffineRepr> Pedersen<C> {
let cm: C = (params.g.mul(v) + params.h.mul(r)).into();
CommitmentElem::<C> { cm, r }
}
pub fn commit<R: RngCore>(
rng: &mut R,
pub fn commit(
params: &Params<C>,
v: &Vec<C::ScalarField>,
r: &C::ScalarField, // random value is provided, in order to be choosen by other parts of the protocol
) -> Commitment<C> {
let r = C::ScalarField::rand(rng);
let cm = params.h.mul(r) + naive_msm(v, &params.r_vec);
Commitment::<C> { cm: cm.into(), r }
Commitment::<C>(cm.into())
}
pub fn prove_elem(
@@ -85,7 +84,7 @@ impl<C: AffineRepr> Pedersen<C> {
pub fn prove(
params: &Params<C>,
transcript: &mut Transcript<C::ScalarField>,
cm: C,
cm: &Commitment<C>, // TODO maybe it makes sense to not have a type wrapper and use directly C
v: Vec<C::ScalarField>,
r: C::ScalarField,
) -> Proof<C> {
@@ -94,7 +93,7 @@ impl<C: AffineRepr> Pedersen<C> {
let R: C = (params.h.mul(r1) + naive_msm(&d, &params.r_vec)).into();
transcript.add(b"cm", &cm);
transcript.add(b"cm", &cm.0);
transcript.add(b"R", &R);
let e = transcript.get_challenge(b"e");
@@ -106,17 +105,17 @@ impl<C: AffineRepr> Pedersen<C> {
pub fn verify(
params: &Params<C>,
transcript: &mut Transcript<C::ScalarField>,
cm: C,
cm: Commitment<C>,
proof: Proof<C>,
) -> bool {
// r1, d just to match Prover's transcript
transcript.get_challenge(b"r_1");
transcript.get_challenge_vec(b"d", proof.u_.len());
transcript.add(b"cm", &cm);
transcript.add(b"cm", &cm.0);
transcript.add(b"R", &proof.R);
let e = transcript.get_challenge(b"e");
let lhs = proof.R + cm.mul(e);
let lhs = proof.R + cm.0.mul(e);
let rhs = params.h.mul(proof.ru_) + naive_msm(&proof.u_, &params.r_vec);
if lhs != rhs {
return false;
@@ -146,20 +145,7 @@ impl<C: AffineRepr> Pedersen<C> {
}
}
pub struct Commitment<C: AffineRepr> {
pub cm: C,
pub r: C::ScalarField,
}
impl<C: AffineRepr> Commitment<C> {
pub fn prove(
&self,
params: &Params<C>,
transcript: &mut Transcript<C::ScalarField>,
v: Vec<C::ScalarField>,
) -> Proof<C> {
Pedersen::<C>::prove(params, transcript, self.cm, v, self.r)
}
}
pub struct Commitment<C: AffineRepr>(pub C);
pub struct CommitmentElem<C: AffineRepr> {
pub cm: C,
@@ -219,13 +205,11 @@ mod tests {
// init Verifier's transcript
let mut transcript_v: Transcript<Fr> = Transcript::<Fr>::new();
let mut v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
let cm = Pedersen::commit(&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 v: Vec<Fr> = vec![Fr::rand(&mut rng); n];
let r: Fr = Fr::rand(&mut rng);
let cm = Pedersen::commit(&params, &v, &r);
let proof = Pedersen::prove(&params, &mut transcript_p, &cm, v, r);
let v = Pedersen::verify(&params, &mut transcript_v, cm, proof);
assert!(v);
}
}