mirror of
https://github.com/arnaucube/sonobe.git
synced 2026-01-08 15:01:30 +01:00
Adapt Nova usage of commitment to the generic trait (#63)
This commit is contained in:
@@ -1 +1 @@
|
||||
1.73.0
|
||||
1.75.0
|
||||
|
||||
@@ -237,7 +237,7 @@ mod tests {
|
||||
// Initialize cs
|
||||
let cs = ConstraintSystem::<Fr>::new_ref();
|
||||
let vec_thetas = sigmas_thetas.1;
|
||||
for (_, thetas) in vec_thetas.iter().enumerate() {
|
||||
for thetas in vec_thetas.iter() {
|
||||
// sum c_i * prod theta_j
|
||||
let expected = sum_ci_mul_prod_thetaj(&ccs, thetas); // from `compute_c_from_sigmas_and_thetas`
|
||||
let mut prepared_thetas = Vec::new();
|
||||
|
||||
@@ -503,7 +503,7 @@ pub mod tests {
|
||||
fn test_nifs_gadget() {
|
||||
let (_, _, _, _, ci1, _, ci2, _, ci3, _, cmT, _, r_Fr) = prepare_simple_fold_inputs();
|
||||
|
||||
let ci3_verifier = NIFS::<Projective>::verify(r_Fr, &ci1, &ci2, &cmT);
|
||||
let ci3_verifier = NIFS::<Projective, Pedersen<Projective>>::verify(r_Fr, &ci1, &ci2, &cmT);
|
||||
assert_eq!(ci3_verifier, ci3);
|
||||
|
||||
let cs = ConstraintSystem::<Fr>::new_ref();
|
||||
@@ -721,7 +721,7 @@ pub mod tests {
|
||||
|
||||
// U_{i+1}
|
||||
let T: Vec<Fr>;
|
||||
(T, cmT) = NIFS::<Projective>::compute_cmT(
|
||||
(T, cmT) = NIFS::<Projective, Pedersen<Projective>>::compute_cmT(
|
||||
&pedersen_params,
|
||||
&r1cs,
|
||||
&w_i,
|
||||
@@ -741,9 +741,10 @@ pub mod tests {
|
||||
.unwrap();
|
||||
let r_Fr = Fr::from_bigint(BigInteger::from_bits_le(&r_bits)).unwrap();
|
||||
|
||||
(W_i1, U_i1) =
|
||||
NIFS::<Projective>::fold_instances(r_Fr, &w_i, &u_i, &W_i, &U_i, &T, cmT)
|
||||
.unwrap();
|
||||
(W_i1, U_i1) = NIFS::<Projective, Pedersen<Projective>>::fold_instances(
|
||||
r_Fr, &w_i, &u_i, &W_i, &U_i, &T, cmT,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
r1cs.check_relaxed_instance_relation(&W_i1, &U_i1).unwrap();
|
||||
|
||||
@@ -782,7 +783,7 @@ pub mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
let cf_r_Fq = Fq::from_bigint(BigInteger::from_bits_le(&cf_r_bits)).unwrap();
|
||||
let (_, cf_U_i1) = NIFS::<Projective2>::fold_instances(
|
||||
let (_, cf_U_i1) = NIFS::<Projective2, Pedersen<Projective2>>::fold_instances(
|
||||
cf_r_Fq, &cf_W_i, &cf_U_i, &cf_w_i, &cf_u_i, &cf_T, cf_cmT,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -828,7 +829,9 @@ pub mod tests {
|
||||
// compute committed instances, w_{i+1}, u_{i+1}, which will be used as w_i, u_i, so we
|
||||
// assign them directly to w_i, u_i.
|
||||
w_i = Witness::<Projective>::new(w_i1.clone(), r1cs.A.n_rows);
|
||||
u_i = w_i.commit(&pedersen_params, vec![u_i1_x]).unwrap();
|
||||
u_i = w_i
|
||||
.commit::<Pedersen<Projective>>(&pedersen_params, vec![u_i1_x])
|
||||
.unwrap();
|
||||
|
||||
r1cs.check_relaxed_instance_relation(&w_i, &u_i).unwrap();
|
||||
r1cs.check_relaxed_instance_relation(&W_i1, &U_i1).unwrap();
|
||||
|
||||
@@ -18,7 +18,7 @@ use ark_std::{One, Zero};
|
||||
use core::{borrow::Borrow, marker::PhantomData};
|
||||
|
||||
use crate::ccs::r1cs::R1CS;
|
||||
use crate::commitment::pedersen::Params as PedersenParams;
|
||||
use crate::commitment::{pedersen::Params as PedersenParams, CommitmentProver};
|
||||
use crate::folding::nova::{
|
||||
circuits::{CommittedInstanceVar, CF1, CF2},
|
||||
ivc::IVC,
|
||||
@@ -179,17 +179,21 @@ where
|
||||
|
||||
/// Circuit that implements the in-circuit checks needed for the onchain (Ethereum's EVM)
|
||||
/// verification.
|
||||
pub struct DeciderCircuit<C1, GC1, C2, GC2>
|
||||
pub struct DeciderCircuit<C1, GC1, C2, GC2, CP1, CP2>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
GC1: CurveVar<C1, CF2<C1>>,
|
||||
C2: CurveGroup,
|
||||
GC2: CurveVar<C2, CF2<C2>>,
|
||||
CP1: CommitmentProver<C1>,
|
||||
CP2: CommitmentProver<C2>,
|
||||
{
|
||||
_c1: PhantomData<C1>,
|
||||
_gc1: PhantomData<GC1>,
|
||||
_c2: PhantomData<C2>,
|
||||
_gc2: PhantomData<GC2>,
|
||||
_cp1: PhantomData<CP1>,
|
||||
_cp2: PhantomData<CP2>,
|
||||
|
||||
/// E vector's length of the Nova instance witness
|
||||
pub E_len: usize,
|
||||
@@ -199,7 +203,7 @@ where
|
||||
pub r1cs: R1CS<C1::ScalarField>,
|
||||
/// R1CS of the CycleFold circuit
|
||||
pub cf_r1cs: R1CS<C2::ScalarField>,
|
||||
/// CycleFold PedersenParams, over C2
|
||||
/// CycleFold PedersenParams over C2
|
||||
pub cf_pedersen_params: PedersenParams<C2>,
|
||||
pub poseidon_config: PoseidonConfig<CF1<C1>>,
|
||||
pub i: Option<CF1<C1>>,
|
||||
@@ -216,25 +220,32 @@ where
|
||||
pub cf_U_i: Option<CommittedInstance<C2>>,
|
||||
pub cf_W_i: Option<Witness<C2>>,
|
||||
}
|
||||
impl<C1, GC1, C2, GC2> DeciderCircuit<C1, GC1, C2, GC2>
|
||||
impl<C1, GC1, C2, GC2, CP1, CP2> DeciderCircuit<C1, GC1, C2, GC2, CP1, CP2>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
C2: CurveGroup,
|
||||
GC1: CurveVar<C1, CF2<C1>>,
|
||||
GC2: CurveVar<C2, CF2<C2>>,
|
||||
CP1: CommitmentProver<C1>,
|
||||
// enforce that the CP2 is Pedersen commitment, since we're at Ethereum's EVM decider
|
||||
CP2: CommitmentProver<C2, Params = PedersenParams<C2>>,
|
||||
{
|
||||
pub fn from_ivc<FC: FCircuit<C1::ScalarField>>(ivc: IVC<C1, GC1, C2, GC2, FC>) -> Self {
|
||||
pub fn from_ivc<FC: FCircuit<C1::ScalarField>>(
|
||||
ivc: IVC<C1, GC1, C2, GC2, FC, CP1, CP2>,
|
||||
) -> Self {
|
||||
Self {
|
||||
_c1: PhantomData,
|
||||
_gc1: PhantomData,
|
||||
_c2: PhantomData,
|
||||
_gc2: PhantomData,
|
||||
_cp1: PhantomData,
|
||||
_cp2: PhantomData,
|
||||
|
||||
E_len: ivc.W_i.E.len(),
|
||||
cf_E_len: ivc.cf_W_i.E.len(),
|
||||
r1cs: ivc.r1cs,
|
||||
cf_r1cs: ivc.cf_r1cs,
|
||||
cf_pedersen_params: ivc.cf_pedersen_params,
|
||||
cf_pedersen_params: ivc.cf_cm_params,
|
||||
poseidon_config: ivc.poseidon_config,
|
||||
i: Some(ivc.i),
|
||||
z_0: Some(ivc.z_0),
|
||||
@@ -249,18 +260,21 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C1, GC1, C2, GC2> ConstraintSynthesizer<CF1<C1>> for DeciderCircuit<C1, GC1, C2, GC2>
|
||||
impl<C1, GC1, C2, GC2, CP1, CP2> ConstraintSynthesizer<CF1<C1>>
|
||||
for DeciderCircuit<C1, GC1, C2, GC2, CP1, CP2>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
C2: CurveGroup,
|
||||
GC1: CurveVar<C1, CF2<C1>>,
|
||||
GC2: CurveVar<C2, CF2<C2>>,
|
||||
CP1: CommitmentProver<C1>,
|
||||
CP2: CommitmentProver<C2>,
|
||||
<C1 as CurveGroup>::BaseField: PrimeField,
|
||||
<C2 as CurveGroup>::BaseField: PrimeField,
|
||||
<C1 as Group>::ScalarField: Absorb,
|
||||
<C2 as Group>::ScalarField: Absorb,
|
||||
C1: CurveGroup<BaseField = C2::ScalarField, ScalarField = C2::BaseField>,
|
||||
for<'a> &'a GC2: GroupOpsBounds<'a, C2, GC2>,
|
||||
for<'b> &'b GC2: GroupOpsBounds<'b, C2, GC2>,
|
||||
{
|
||||
fn generate_constraints(self, cs: ConstraintSystemRef<CF1<C1>>) -> Result<(), SynthesisError> {
|
||||
let r1cs =
|
||||
@@ -437,7 +451,8 @@ pub mod tests {
|
||||
use ark_relations::r1cs::ConstraintSystem;
|
||||
use ark_vesta::{constraints::GVar as GVar2, Projective as Projective2};
|
||||
|
||||
use crate::folding::nova::ivc::IVC;
|
||||
use crate::commitment::pedersen::Pedersen;
|
||||
use crate::folding::nova::ivc::tests::get_pedersen_params_len;
|
||||
use crate::frontend::tests::{CubicFCircuit, CustomFCircuit, WrapperCircuit};
|
||||
use crate::transcript::poseidon::tests::poseidon_test_config;
|
||||
|
||||
@@ -604,10 +619,25 @@ pub mod tests {
|
||||
let F_circuit = CubicFCircuit::<Fr>::new(());
|
||||
let z_0 = vec![Fr::from(3_u32)];
|
||||
|
||||
let (pedersen_len, cf_pedersen_len) =
|
||||
get_pedersen_params_len::<CubicFCircuit<Fr>>(&poseidon_config, F_circuit).unwrap();
|
||||
// generate the Pedersen params
|
||||
let pedersen_params = Pedersen::<Projective>::new_params(&mut rng, pedersen_len);
|
||||
let cf_pedersen_params = Pedersen::<Projective2>::new_params(&mut rng, cf_pedersen_len);
|
||||
|
||||
// generate an IVC and do a step of it
|
||||
let mut ivc = IVC::<Projective, GVar, Projective2, GVar2, CubicFCircuit<Fr>>::new(
|
||||
&mut rng,
|
||||
let mut ivc = IVC::<
|
||||
Projective,
|
||||
GVar,
|
||||
Projective2,
|
||||
GVar2,
|
||||
CubicFCircuit<Fr>,
|
||||
Pedersen<Projective>,
|
||||
Pedersen<Projective2>,
|
||||
>::new(
|
||||
poseidon_config,
|
||||
pedersen_params,
|
||||
cf_pedersen_params,
|
||||
F_circuit,
|
||||
z_0.clone(),
|
||||
)
|
||||
@@ -616,7 +646,14 @@ pub mod tests {
|
||||
ivc.verify(z_0, 1).unwrap();
|
||||
|
||||
// load the DeciderCircuit from the generated IVC
|
||||
let decider_circuit = DeciderCircuit::<Projective, GVar, Projective2, GVar2>::from_ivc(ivc);
|
||||
let decider_circuit = DeciderCircuit::<
|
||||
Projective,
|
||||
GVar,
|
||||
Projective2,
|
||||
GVar2,
|
||||
Pedersen<Projective>,
|
||||
Pedersen<Projective2>,
|
||||
>::from_ivc(ivc);
|
||||
|
||||
let cs = ConstraintSystem::<Fr>::new_ref();
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ use ark_ec::{AffineRepr, CurveGroup, Group};
|
||||
use ark_ff::{BigInteger, PrimeField};
|
||||
use ark_r1cs_std::{groups::GroupOpsBounds, prelude::CurveVar};
|
||||
use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystem};
|
||||
use ark_std::rand::Rng;
|
||||
use ark_std::{One, Zero};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
@@ -12,9 +11,8 @@ use super::{
|
||||
cyclefold::{CycleFoldChallengeGadget, CycleFoldCircuit},
|
||||
};
|
||||
use super::{nifs::NIFS, traits::NovaR1CS, CommittedInstance, Witness};
|
||||
use crate::ccs::r1cs::R1CS;
|
||||
use crate::ccs::r1cs::{extract_r1cs, extract_w_x};
|
||||
use crate::commitment::pedersen::{Params as PedersenParams, Pedersen};
|
||||
use crate::ccs::r1cs::{extract_r1cs, extract_w_x, R1CS};
|
||||
use crate::commitment::CommitmentProver;
|
||||
use crate::frontend::FCircuit;
|
||||
use crate::Error;
|
||||
|
||||
@@ -23,13 +21,15 @@ use super::cyclefold::CF_IO_LEN;
|
||||
|
||||
/// Implements the Incremental Verifiable Computation described in sections 1.2 and 5 of
|
||||
/// [Nova](https://eprint.iacr.org/2021/370.pdf)
|
||||
pub struct IVC<C1, GC1, C2, GC2, FC>
|
||||
pub struct IVC<C1, GC1, C2, GC2, FC, CP1, CP2>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
GC1: CurveVar<C1, CF2<C1>>,
|
||||
C2: CurveGroup,
|
||||
GC2: CurveVar<C2, CF2<C2>>,
|
||||
FC: FCircuit<C1::ScalarField>,
|
||||
CP1: CommitmentProver<C1>,
|
||||
CP2: CommitmentProver<C2>,
|
||||
{
|
||||
_gc1: PhantomData<GC1>,
|
||||
_c2: PhantomData<C2>,
|
||||
@@ -39,10 +39,10 @@ where
|
||||
/// R1CS of the CycleFold circuit
|
||||
pub cf_r1cs: R1CS<C2::ScalarField>,
|
||||
pub poseidon_config: PoseidonConfig<C1::ScalarField>,
|
||||
/// PedersenParams over C1
|
||||
pub pedersen_params: PedersenParams<C1>,
|
||||
/// CycleFold PedersenParams, over C2
|
||||
pub cf_pedersen_params: PedersenParams<C2>,
|
||||
/// CommitmentProver::Params over C1
|
||||
pub cm_params: CP1::Params,
|
||||
/// CycleFold CommitmentProver::Params, over C2
|
||||
pub cf_cm_params: CP2::Params,
|
||||
/// F circuit, the circuit that is being folded
|
||||
pub F: FC,
|
||||
pub i: C1::ScalarField,
|
||||
@@ -61,13 +61,15 @@ where
|
||||
pub cf_U_i: CommittedInstance<C2>,
|
||||
}
|
||||
|
||||
impl<C1, GC1, C2, GC2, FC> IVC<C1, GC1, C2, GC2, FC>
|
||||
impl<C1, GC1, C2, GC2, FC, CP1, CP2> IVC<C1, GC1, C2, GC2, FC, CP1, CP2>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
GC1: CurveVar<C1, CF2<C1>>,
|
||||
C2: CurveGroup,
|
||||
GC2: CurveVar<C2, CF2<C2>>,
|
||||
FC: FCircuit<C1::ScalarField>,
|
||||
CP1: CommitmentProver<C1>,
|
||||
CP2: CommitmentProver<C2>,
|
||||
<C1 as CurveGroup>::BaseField: PrimeField,
|
||||
<C2 as CurveGroup>::BaseField: PrimeField,
|
||||
<C1 as Group>::ScalarField: Absorb,
|
||||
@@ -77,9 +79,10 @@ where
|
||||
for<'a> &'a GC2: GroupOpsBounds<'a, C2, GC2>,
|
||||
{
|
||||
/// Initializes the IVC for the given parameters and initial state `z_0`.
|
||||
pub fn new<R: Rng>(
|
||||
rng: &mut R,
|
||||
pub fn new(
|
||||
poseidon_config: PoseidonConfig<C1::ScalarField>,
|
||||
cm_params: CP1::Params,
|
||||
cf_cm_params: CP2::Params,
|
||||
F: FC,
|
||||
z_0: Vec<C1::ScalarField>,
|
||||
) -> Result<Self, Error> {
|
||||
@@ -100,11 +103,6 @@ where
|
||||
let cs2 = cs2.into_inner().ok_or(Error::NoInnerConstraintSystem)?;
|
||||
let cf_r1cs = extract_r1cs::<C1::BaseField>(&cs2);
|
||||
|
||||
// this will not be randomly generated in this method, and will come from above levels, so
|
||||
// the same params can be loaded on multiple instances
|
||||
let pedersen_params = Pedersen::<C1>::new_params(rng, r1cs.A.n_rows);
|
||||
let cf_pedersen_params = Pedersen::<C2>::new_params(rng, cf_r1cs.A.n_rows);
|
||||
|
||||
// setup the dummy instances
|
||||
let (w_dummy, u_dummy) = r1cs.dummy_instance();
|
||||
let (cf_w_dummy, cf_u_dummy) = cf_r1cs.dummy_instance();
|
||||
@@ -118,8 +116,8 @@ where
|
||||
r1cs,
|
||||
cf_r1cs,
|
||||
poseidon_config,
|
||||
pedersen_params,
|
||||
cf_pedersen_params,
|
||||
cm_params,
|
||||
cf_cm_params,
|
||||
F,
|
||||
i: C1::ScalarField::zero(),
|
||||
z_0: z_0.clone(),
|
||||
@@ -154,8 +152,9 @@ where
|
||||
.ok_or(Error::OutOfBounds)?;
|
||||
|
||||
// fold Nova instances
|
||||
let (W_i1, U_i1): (Witness<C1>, CommittedInstance<C1>) =
|
||||
NIFS::<C1>::fold_instances(r_Fr, &self.w_i, &self.u_i, &self.W_i, &self.U_i, &T, cmT)?;
|
||||
let (W_i1, U_i1): (Witness<C1>, CommittedInstance<C1>) = NIFS::<C1, CP1>::fold_instances(
|
||||
r_Fr, &self.w_i, &self.u_i, &self.W_i, &self.U_i, &T, cmT,
|
||||
)?;
|
||||
|
||||
// folded instance output (public input, x)
|
||||
// u_{i+1}.x = H(i+1, z_0, z_{i+1}, U_{i+1})
|
||||
@@ -188,7 +187,7 @@ where
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
NIFS::verify_folded_instance(r_Fr, &self.u_i, &self.U_i, &U_i1, &cmT)?;
|
||||
NIFS::<C1, CP1>::verify_folded_instance(r_Fr, &self.u_i, &self.U_i, &U_i1, &cmT)?;
|
||||
} else {
|
||||
// CycleFold part:
|
||||
// get the vector used as public inputs 'x' in the CycleFold circuit
|
||||
@@ -226,7 +225,7 @@ where
|
||||
// fold cyclefold instances
|
||||
let cf_w_i = Witness::<C2>::new(cf_w_i.clone(), self.cf_r1cs.A.n_rows);
|
||||
let cf_u_i: CommittedInstance<C2> =
|
||||
cf_w_i.commit(&self.cf_pedersen_params, cf_x_i.clone())?;
|
||||
cf_w_i.commit::<CP2>(&self.cf_cm_params, cf_x_i.clone())?;
|
||||
|
||||
// compute T* and cmT* for CycleFoldCircuit
|
||||
let (cf_T, cf_cmT) = self.compute_cf_cmT(&cf_w_i, &cf_u_i)?;
|
||||
@@ -240,7 +239,7 @@ where
|
||||
let cf_r_Fq = C1::BaseField::from_bigint(BigInteger::from_bits_le(&cf_r_bits))
|
||||
.ok_or(Error::OutOfBounds)?;
|
||||
|
||||
let (cf_W_i1, cf_U_i1) = NIFS::<C2>::fold_instances(
|
||||
let (cf_W_i1, cf_U_i1) = NIFS::<C2, CP2>::fold_instances(
|
||||
cf_r_Fq,
|
||||
&self.cf_W_i,
|
||||
&self.cf_U_i,
|
||||
@@ -300,7 +299,7 @@ where
|
||||
self.i += C1::ScalarField::one();
|
||||
self.z_i = z_i1.clone();
|
||||
self.w_i = Witness::<C1>::new(w_i1, self.r1cs.A.n_rows);
|
||||
self.u_i = self.w_i.commit(&self.pedersen_params, vec![u_i1_x])?;
|
||||
self.u_i = self.w_i.commit::<CP1>(&self.cm_params, vec![u_i1_x])?;
|
||||
self.W_i = W_i1.clone();
|
||||
self.U_i = U_i1.clone();
|
||||
|
||||
@@ -353,8 +352,8 @@ where
|
||||
|
||||
// computes T and cmT for the AugmentedFCircuit
|
||||
fn compute_cmT(&self) -> Result<(Vec<C1::ScalarField>, C1), Error> {
|
||||
NIFS::<C1>::compute_cmT(
|
||||
&self.pedersen_params,
|
||||
NIFS::<C1, CP1>::compute_cmT(
|
||||
&self.cm_params,
|
||||
&self.r1cs,
|
||||
&self.w_i,
|
||||
&self.u_i,
|
||||
@@ -368,8 +367,8 @@ where
|
||||
cf_w_i: &Witness<C2>,
|
||||
cf_u_i: &CommittedInstance<C2>,
|
||||
) -> Result<(Vec<C2::ScalarField>, C2), Error> {
|
||||
NIFS::<C2>::compute_cyclefold_cmT(
|
||||
&self.cf_pedersen_params,
|
||||
NIFS::<C2, CP2>::compute_cyclefold_cmT(
|
||||
&self.cf_cm_params,
|
||||
&self.cf_r1cs,
|
||||
cf_w_i,
|
||||
cf_u_i,
|
||||
@@ -393,14 +392,43 @@ pub(crate) fn get_committed_instance_coordinates<C: CurveGroup>(
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use ark_pallas::{constraints::GVar, Fr, Projective};
|
||||
use ark_vesta::{constraints::GVar as GVar2, Projective as Projective2};
|
||||
|
||||
use crate::commitment::pedersen::Pedersen;
|
||||
use crate::frontend::tests::CubicFCircuit;
|
||||
use crate::transcript::poseidon::tests::poseidon_test_config;
|
||||
|
||||
/// helper method to get the r1cs from the circuit
|
||||
pub fn get_r1cs<F: PrimeField>(
|
||||
circuit: impl ConstraintSynthesizer<F>,
|
||||
) -> Result<R1CS<F>, Error> {
|
||||
let cs = ConstraintSystem::<F>::new_ref();
|
||||
circuit.generate_constraints(cs.clone())?;
|
||||
cs.finalize();
|
||||
let cs = cs.into_inner().ok_or(Error::NoInnerConstraintSystem)?;
|
||||
let r1cs = extract_r1cs::<F>(&cs);
|
||||
Ok(r1cs)
|
||||
}
|
||||
|
||||
/// helper method to get the pedersen params length for both the AugmentedFCircuit and the
|
||||
/// CycleFold circuit
|
||||
pub fn get_pedersen_params_len<FC: FCircuit<Fr>>(
|
||||
poseidon_config: &PoseidonConfig<Fr>,
|
||||
F_circuit: FC,
|
||||
) -> Result<(usize, usize), Error> {
|
||||
let augmented_F_circuit = AugmentedFCircuit::<Projective, Projective2, GVar2, FC>::empty(
|
||||
poseidon_config,
|
||||
F_circuit,
|
||||
);
|
||||
let cf_circuit = CycleFoldCircuit::<Projective, GVar>::empty();
|
||||
let r1cs = get_r1cs(augmented_F_circuit)?;
|
||||
let cf_r1cs = get_r1cs(cf_circuit)?;
|
||||
Ok((r1cs.A.n_rows, cf_r1cs.A.n_rows))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ivc() {
|
||||
let mut rng = ark_std::test_rng();
|
||||
@@ -409,9 +437,24 @@ mod tests {
|
||||
let F_circuit = CubicFCircuit::<Fr>::new(());
|
||||
let z_0 = vec![Fr::from(3_u32)];
|
||||
|
||||
let mut ivc = IVC::<Projective, GVar, Projective2, GVar2, CubicFCircuit<Fr>>::new(
|
||||
&mut rng,
|
||||
let (pedersen_len, cf_pedersen_len) =
|
||||
get_pedersen_params_len::<CubicFCircuit<Fr>>(&poseidon_config, F_circuit).unwrap();
|
||||
// generate the Pedersen params
|
||||
let pedersen_params = Pedersen::<Projective>::new_params(&mut rng, pedersen_len);
|
||||
let cf_pedersen_params = Pedersen::<Projective2>::new_params(&mut rng, cf_pedersen_len);
|
||||
|
||||
let mut ivc = IVC::<
|
||||
Projective,
|
||||
GVar,
|
||||
Projective2,
|
||||
GVar2,
|
||||
CubicFCircuit<Fr>,
|
||||
Pedersen<Projective>,
|
||||
Pedersen<Projective2>,
|
||||
>::new(
|
||||
poseidon_config,
|
||||
pedersen_params,
|
||||
cf_pedersen_params,
|
||||
F_circuit,
|
||||
z_0.clone(),
|
||||
)
|
||||
|
||||
@@ -7,10 +7,7 @@ use ark_ec::{CurveGroup, Group};
|
||||
use ark_std::fmt::Debug;
|
||||
use ark_std::{One, Zero};
|
||||
|
||||
use crate::commitment::{
|
||||
pedersen::{Params as PedersenParams, Pedersen},
|
||||
CommitmentProver,
|
||||
};
|
||||
use crate::commitment::CommitmentProver;
|
||||
use crate::folding::circuits::nonnative::point_to_nonnative_limbs;
|
||||
use crate::utils::vec::is_zero_vec;
|
||||
use crate::Error;
|
||||
@@ -101,16 +98,16 @@ where
|
||||
rW: C::ScalarField::zero(),
|
||||
}
|
||||
}
|
||||
pub fn commit(
|
||||
pub fn commit<CP: CommitmentProver<C>>(
|
||||
&self,
|
||||
params: &PedersenParams<C>,
|
||||
params: &CP::Params,
|
||||
x: Vec<C::ScalarField>,
|
||||
) -> Result<CommittedInstance<C>, Error> {
|
||||
let mut cmE = C::zero();
|
||||
if !is_zero_vec::<C::ScalarField>(&self.E) {
|
||||
cmE = Pedersen::commit(params, &self.E, &self.rE)?;
|
||||
cmE = CP::commit(params, &self.E, &self.rE)?;
|
||||
}
|
||||
let cmW = Pedersen::commit(params, &self.W, &self.rW)?;
|
||||
let cmW = CP::commit(params, &self.W, &self.rW)?;
|
||||
Ok(CommittedInstance {
|
||||
cmE,
|
||||
u: C::ScalarField::one(),
|
||||
|
||||
@@ -5,21 +5,19 @@ use std::marker::PhantomData;
|
||||
|
||||
use super::{CommittedInstance, Witness};
|
||||
use crate::ccs::r1cs::R1CS;
|
||||
use crate::commitment::{
|
||||
pedersen::{Params as PedersenParams, Pedersen, Proof as PedersenProof},
|
||||
CommitmentProver,
|
||||
};
|
||||
use crate::commitment::CommitmentProver;
|
||||
use crate::transcript::Transcript;
|
||||
use crate::utils::vec::*;
|
||||
use crate::Error;
|
||||
|
||||
/// Implements the Non-Interactive Folding Scheme described in section 4 of
|
||||
/// [Nova](https://eprint.iacr.org/2021/370.pdf)
|
||||
pub struct NIFS<C: CurveGroup> {
|
||||
_phantom: PhantomData<C>,
|
||||
pub struct NIFS<C: CurveGroup, CP: CommitmentProver<C>> {
|
||||
_c: PhantomData<C>,
|
||||
_cp: PhantomData<CP>,
|
||||
}
|
||||
|
||||
impl<C: CurveGroup> NIFS<C>
|
||||
impl<C: CurveGroup, CP: CommitmentProver<C>> NIFS<C, CP>
|
||||
where
|
||||
<C as Group>::ScalarField: Absorb,
|
||||
{
|
||||
@@ -92,7 +90,7 @@ where
|
||||
|
||||
/// compute_cmT is part of the NIFS.P logic
|
||||
pub fn compute_cmT(
|
||||
pedersen_params: &PedersenParams<C>,
|
||||
cm_prover_params: &CP::Params,
|
||||
r1cs: &R1CS<C::ScalarField>,
|
||||
w1: &Witness<C>,
|
||||
ci1: &CommittedInstance<C>,
|
||||
@@ -105,11 +103,11 @@ where
|
||||
// compute cross terms
|
||||
let T = Self::compute_T(r1cs, ci1.u, ci2.u, &z1, &z2)?;
|
||||
// use r_T=1 since we don't need hiding property for cm(T)
|
||||
let cmT = Pedersen::commit(pedersen_params, &T, &C::ScalarField::one())?;
|
||||
let cmT = CP::commit(cm_prover_params, &T, &C::ScalarField::one())?;
|
||||
Ok((T, cmT))
|
||||
}
|
||||
pub fn compute_cyclefold_cmT(
|
||||
pedersen_params: &PedersenParams<C>,
|
||||
cm_prover_params: &CP::Params,
|
||||
r1cs: &R1CS<C::ScalarField>, // R1CS over C2.Fr=C1.Fq (here C=C2)
|
||||
w1: &Witness<C>,
|
||||
ci1: &CommittedInstance<C>,
|
||||
@@ -125,7 +123,7 @@ where
|
||||
// compute cross terms
|
||||
let T = Self::compute_T(r1cs, ci1.u, ci2.u, &z1, &z2)?;
|
||||
// use r_T=1 since we don't need hiding property for cm(T)
|
||||
let cmT = Pedersen::commit(pedersen_params, &T, &C::ScalarField::one())?;
|
||||
let cmT = CP::commit(cm_prover_params, &T, &C::ScalarField::one())?;
|
||||
Ok((T, cmT))
|
||||
}
|
||||
|
||||
@@ -143,10 +141,10 @@ where
|
||||
) -> Result<(Witness<C>, CommittedInstance<C>), Error> {
|
||||
// fold witness
|
||||
// use r_T=1 since we don't need hiding property for cm(T)
|
||||
let w3 = NIFS::<C>::fold_witness(r, w1, w2, T, C::ScalarField::one())?;
|
||||
let w3 = NIFS::<C, CP>::fold_witness(r, w1, w2, T, C::ScalarField::one())?;
|
||||
|
||||
// fold committed instancs
|
||||
let ci3 = NIFS::<C>::fold_committed_instance(r, ci1, ci2, &cmT);
|
||||
let ci3 = NIFS::<C, CP>::fold_committed_instance(r, ci1, ci2, &cmT);
|
||||
|
||||
Ok((w3, ci3))
|
||||
}
|
||||
@@ -160,7 +158,7 @@ where
|
||||
ci2: &CommittedInstance<C>,
|
||||
cmT: &C,
|
||||
) -> CommittedInstance<C> {
|
||||
NIFS::<C>::fold_committed_instance(r, ci1, ci2, cmT)
|
||||
NIFS::<C, CP>::fold_committed_instance(r, ci1, ci2, cmT)
|
||||
}
|
||||
|
||||
/// Verify commited folded instance (ci) relations. Notice that this method does not open the
|
||||
@@ -184,50 +182,35 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn open_commitments(
|
||||
pub fn prove_commitments(
|
||||
tr: &mut impl Transcript<C>,
|
||||
pedersen_params: &PedersenParams<C>,
|
||||
cm_prover_params: &CP::Params,
|
||||
w: &Witness<C>,
|
||||
ci: &CommittedInstance<C>,
|
||||
T: Vec<C::ScalarField>,
|
||||
cmT: &C,
|
||||
) -> Result<[PedersenProof<C>; 3], Error> {
|
||||
let cmE_proof = Pedersen::prove(pedersen_params, tr, &ci.cmE, &w.E, &w.rE)?;
|
||||
let cmW_proof = Pedersen::prove(pedersen_params, tr, &ci.cmW, &w.W, &w.rW)?;
|
||||
let cmT_proof = Pedersen::prove(pedersen_params, tr, cmT, &T, &C::ScalarField::one())?; // cm(T) is committed with rT=1
|
||||
) -> Result<[CP::Proof; 3], Error> {
|
||||
let cmE_proof = CP::prove(cm_prover_params, tr, &ci.cmE, &w.E, &w.rE)?;
|
||||
let cmW_proof = CP::prove(cm_prover_params, tr, &ci.cmW, &w.W, &w.rW)?;
|
||||
let cmT_proof = CP::prove(cm_prover_params, tr, cmT, &T, &C::ScalarField::one())?; // cm(T) is committed with rT=1
|
||||
Ok([cmE_proof, cmW_proof, cmT_proof])
|
||||
}
|
||||
pub fn verify_commitments(
|
||||
tr: &mut impl Transcript<C>,
|
||||
pedersen_params: &PedersenParams<C>,
|
||||
ci: CommittedInstance<C>,
|
||||
cmT: C,
|
||||
cm_proofs: [PedersenProof<C>; 3],
|
||||
) -> Result<(), Error> {
|
||||
if cm_proofs.len() != 3 {
|
||||
// cm_proofs should have length 3: [cmE_proof, cmW_proof, cmT_proof]
|
||||
return Err(Error::NotExpectedLength(cm_proofs.len(), 3));
|
||||
}
|
||||
Pedersen::verify(pedersen_params, tr, ci.cmE, cm_proofs[0].clone())?;
|
||||
Pedersen::verify(pedersen_params, tr, ci.cmW, cm_proofs[1].clone())?;
|
||||
Pedersen::verify(pedersen_params, tr, cmT, cm_proofs[2].clone())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use ark_crypto_primitives::sponge::poseidon::PoseidonConfig;
|
||||
use ark_ff::{BigInteger, PrimeField};
|
||||
use ark_pallas::{Fr, Projective};
|
||||
use ark_std::{ops::Mul, UniformRand, Zero};
|
||||
|
||||
use crate::ccs::r1cs::tests::{get_test_r1cs, get_test_z};
|
||||
use crate::commitment::pedersen::{Params as PedersenParams, Pedersen};
|
||||
use crate::folding::nova::circuits::ChallengeGadget;
|
||||
use crate::folding::nova::traits::NovaR1CS;
|
||||
use crate::transcript::poseidon::{tests::poseidon_test_config, PoseidonTranscript};
|
||||
use crate::utils::vec::vec_scalar_mul;
|
||||
use ark_crypto_primitives::sponge::poseidon::PoseidonConfig;
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub(crate) fn prepare_simple_fold_inputs() -> (
|
||||
@@ -258,12 +241,23 @@ pub mod tests {
|
||||
let pedersen_params = Pedersen::<Projective>::new_params(&mut rng, r1cs.A.n_cols);
|
||||
|
||||
// compute committed instances
|
||||
let ci1 = w1.commit(&pedersen_params, x1.clone()).unwrap();
|
||||
let ci2 = w2.commit(&pedersen_params, x2.clone()).unwrap();
|
||||
let ci1 = w1
|
||||
.commit::<Pedersen<Projective>>(&pedersen_params, x1.clone())
|
||||
.unwrap();
|
||||
let ci2 = w2
|
||||
.commit::<Pedersen<Projective>>(&pedersen_params, x2.clone())
|
||||
.unwrap();
|
||||
|
||||
// NIFS.P
|
||||
let (T, cmT) =
|
||||
NIFS::<Projective>::compute_cmT(&pedersen_params, &r1cs, &w1, &ci1, &w2, &ci2).unwrap();
|
||||
let (T, cmT) = NIFS::<Projective, Pedersen<Projective>>::compute_cmT(
|
||||
&pedersen_params,
|
||||
&r1cs,
|
||||
&w1,
|
||||
&ci1,
|
||||
&w2,
|
||||
&ci2,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let poseidon_config = poseidon_test_config::<Fr>();
|
||||
|
||||
@@ -276,8 +270,10 @@ pub mod tests {
|
||||
.unwrap();
|
||||
let r_Fr = Fr::from_bigint(BigInteger::from_bits_le(&r_bits)).unwrap();
|
||||
|
||||
let (w3, ci3) =
|
||||
NIFS::<Projective>::fold_instances(r_Fr, &w1, &ci1, &w2, &ci2, &T, cmT).unwrap();
|
||||
let (w3, ci3) = NIFS::<Projective, Pedersen<Projective>>::fold_instances(
|
||||
r_Fr, &w1, &ci1, &w2, &ci2, &T, cmT,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
(
|
||||
pedersen_params,
|
||||
@@ -309,7 +305,7 @@ pub mod tests {
|
||||
// dummy instance, witness and public inputs zeroes
|
||||
let w_dummy = Witness::<Projective>::new(vec![Fr::zero(); w1.len()], r1cs.A.n_rows);
|
||||
let mut u_dummy = w_dummy
|
||||
.commit(&pedersen_params, vec![Fr::zero(); x1.len()])
|
||||
.commit::<Pedersen<Projective>>(&pedersen_params, vec![Fr::zero(); x1.len()])
|
||||
.unwrap();
|
||||
u_dummy.u = Fr::zero();
|
||||
|
||||
@@ -322,11 +318,19 @@ pub mod tests {
|
||||
|
||||
let r_Fr = Fr::from(3_u32);
|
||||
|
||||
let (T, cmT) =
|
||||
NIFS::<Projective>::compute_cmT(&pedersen_params, &r1cs, &w_i, &u_i, &W_i, &U_i)
|
||||
.unwrap();
|
||||
let (W_i1, U_i1) =
|
||||
NIFS::<Projective>::fold_instances(r_Fr, &w_i, &u_i, &W_i, &U_i, &T, cmT).unwrap();
|
||||
let (T, cmT) = NIFS::<Projective, Pedersen<Projective>>::compute_cmT(
|
||||
&pedersen_params,
|
||||
&r1cs,
|
||||
&w_i,
|
||||
&u_i,
|
||||
&W_i,
|
||||
&U_i,
|
||||
)
|
||||
.unwrap();
|
||||
let (W_i1, U_i1) = NIFS::<Projective, Pedersen<Projective>>::fold_instances(
|
||||
r_Fr, &w_i, &u_i, &W_i, &U_i, &T, cmT,
|
||||
)
|
||||
.unwrap();
|
||||
r1cs.check_relaxed_instance_relation(&W_i1, &U_i1).unwrap();
|
||||
}
|
||||
|
||||
@@ -337,7 +341,7 @@ pub mod tests {
|
||||
prepare_simple_fold_inputs();
|
||||
|
||||
// NIFS.V
|
||||
let ci3_v = NIFS::<Projective>::verify(r, &ci1, &ci2, &cmT);
|
||||
let ci3_v = NIFS::<Projective, Pedersen<Projective>>::verify(r, &ci1, &ci2, &cmT);
|
||||
assert_eq!(ci3_v, ci3);
|
||||
|
||||
// check that relations hold for the 2 inputted instances and the folded one
|
||||
@@ -347,7 +351,9 @@ pub mod tests {
|
||||
|
||||
// check that folded commitments from folded instance (ci) are equal to folding the
|
||||
// use folded rE, rW to commit w3
|
||||
let ci3_expected = w3.commit(&pedersen_params, ci3.x.clone()).unwrap();
|
||||
let ci3_expected = w3
|
||||
.commit::<Pedersen<Projective>>(&pedersen_params, ci3.x.clone())
|
||||
.unwrap();
|
||||
assert_eq!(ci3_expected.cmE, ci3.cmE);
|
||||
assert_eq!(ci3_expected.cmW, ci3.cmW);
|
||||
|
||||
@@ -356,15 +362,16 @@ pub mod tests {
|
||||
assert_eq!(w3.E, vec_scalar_mul(&T, &r));
|
||||
|
||||
// NIFS.Verify_Folded_Instance:
|
||||
NIFS::<Projective>::verify_folded_instance(r, &ci1, &ci2, &ci3, &cmT).unwrap();
|
||||
NIFS::<Projective, Pedersen<Projective>>::verify_folded_instance(r, &ci1, &ci2, &ci3, &cmT)
|
||||
.unwrap();
|
||||
|
||||
// init Prover's transcript
|
||||
let mut transcript_p = PoseidonTranscript::<Projective>::new(&poseidon_config);
|
||||
// init Verifier's transcript
|
||||
let mut transcript_v = PoseidonTranscript::<Projective>::new(&poseidon_config);
|
||||
|
||||
// check openings of ci3.cmE, ci3.cmW and cmT
|
||||
let cm_proofs = NIFS::<Projective>::open_commitments(
|
||||
// prove the ci3.cmE, ci3.cmW, cmT commitments
|
||||
let cm_proofs = NIFS::<Projective, Pedersen<Projective>>::prove_commitments(
|
||||
&mut transcript_p,
|
||||
&pedersen_params,
|
||||
&w3,
|
||||
@@ -374,12 +381,27 @@ pub mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
NIFS::<Projective>::verify_commitments(
|
||||
&mut transcript_v,
|
||||
// verify the ci3.cmE, ci3.cmW, cmT commitments
|
||||
assert_eq!(cm_proofs.len(), 3);
|
||||
Pedersen::<Projective>::verify(
|
||||
&pedersen_params,
|
||||
ci3,
|
||||
&mut transcript_v,
|
||||
ci3.cmE,
|
||||
cm_proofs[0].clone(),
|
||||
)
|
||||
.unwrap();
|
||||
Pedersen::<Projective>::verify(
|
||||
&pedersen_params,
|
||||
&mut transcript_v,
|
||||
ci3.cmW,
|
||||
cm_proofs[1].clone(),
|
||||
)
|
||||
.unwrap();
|
||||
Pedersen::<Projective>::verify(
|
||||
&pedersen_params,
|
||||
&mut transcript_v,
|
||||
cmT,
|
||||
cm_proofs,
|
||||
cm_proofs[2].clone(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
@@ -395,8 +417,9 @@ pub mod tests {
|
||||
|
||||
// prepare the running instance
|
||||
let mut running_instance_w = Witness::<Projective>::new(w.clone(), r1cs.A.n_rows);
|
||||
let mut running_committed_instance =
|
||||
running_instance_w.commit(&pedersen_params, x).unwrap();
|
||||
let mut running_committed_instance = running_instance_w
|
||||
.commit::<Pedersen<Projective>>(&pedersen_params, x)
|
||||
.unwrap();
|
||||
|
||||
r1cs.check_relaxed_instance_relation(&running_instance_w, &running_committed_instance)
|
||||
.unwrap();
|
||||
@@ -407,8 +430,9 @@ pub mod tests {
|
||||
let incomming_instance_z = get_test_z(i + 4);
|
||||
let (w, x) = r1cs.split_z(&incomming_instance_z);
|
||||
let incomming_instance_w = Witness::<Projective>::new(w.clone(), r1cs.A.n_rows);
|
||||
let incomming_committed_instance =
|
||||
incomming_instance_w.commit(&pedersen_params, x).unwrap();
|
||||
let incomming_committed_instance = incomming_instance_w
|
||||
.commit::<Pedersen<Projective>>(&pedersen_params, x)
|
||||
.unwrap();
|
||||
r1cs.check_relaxed_instance_relation(
|
||||
&incomming_instance_w,
|
||||
&incomming_committed_instance,
|
||||
@@ -418,7 +442,7 @@ pub mod tests {
|
||||
let r = Fr::rand(&mut rng); // folding challenge would come from the RO
|
||||
|
||||
// NIFS.P
|
||||
let (T, cmT) = NIFS::<Projective>::compute_cmT(
|
||||
let (T, cmT) = NIFS::<Projective, Pedersen<Projective>>::compute_cmT(
|
||||
&pedersen_params,
|
||||
&r1cs,
|
||||
&running_instance_w,
|
||||
@@ -427,7 +451,7 @@ pub mod tests {
|
||||
&incomming_committed_instance,
|
||||
)
|
||||
.unwrap();
|
||||
let (folded_w, _) = NIFS::<Projective>::fold_instances(
|
||||
let (folded_w, _) = NIFS::<Projective, Pedersen<Projective>>::fold_instances(
|
||||
r,
|
||||
&running_instance_w,
|
||||
&running_committed_instance,
|
||||
@@ -439,7 +463,7 @@ pub mod tests {
|
||||
.unwrap();
|
||||
|
||||
// NIFS.V
|
||||
let folded_committed_instance = NIFS::<Projective>::verify(
|
||||
let folded_committed_instance = NIFS::<Projective, Pedersen<Projective>>::verify(
|
||||
r,
|
||||
&running_committed_instance,
|
||||
&incomming_committed_instance,
|
||||
|
||||
Reference in New Issue
Block a user