mirror of
https://github.com/arnaucube/nova-study.git
synced 2026-01-11 00:21:29 +01:00
add initial IVC proof generation impl
This commit is contained in:
@@ -125,17 +125,18 @@ pub struct AugmentedFCircuit<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>>
|
||||
where
|
||||
<<C as CurveGroup>::BaseField as Field>::BasePrimeField: Absorb,
|
||||
{
|
||||
_c: PhantomData<C>,
|
||||
_gc: PhantomData<GC>,
|
||||
pub _c: PhantomData<C>,
|
||||
pub _gc: PhantomData<GC>,
|
||||
|
||||
pub poseidon_native: PoseidonSponge<ConstraintF<C>>,
|
||||
// pub poseidon_native: PoseidonSponge<ConstraintF<C>>,
|
||||
pub poseidon_config: PoseidonConfig<ConstraintF<C>>,
|
||||
pub i: Option<C::BaseField>,
|
||||
pub z_0: Option<C::BaseField>,
|
||||
pub z_i: Option<C::BaseField>,
|
||||
pub phi: Option<Phi<C>>, // phi in the paper sometimes appears as phi (φ) and others as 𝗎
|
||||
pub phiBig: Option<Phi<C>>,
|
||||
pub phiOut: Option<Phi<C>>,
|
||||
pub z_i1: Option<C::BaseField>, // z_{i+1}
|
||||
pub phi: Option<Phi<C>>, // phi_i in the paper sometimes appears as phi (φ) and others as 𝗎
|
||||
pub phiBig: Option<Phi<C>>, // ϕ_i
|
||||
pub phiOut: Option<Phi<C>>, // ϕ_{i+1}
|
||||
pub cmT: Option<C>,
|
||||
pub r: Option<C::ScalarField>, // This will not be an input and derived from a hash internally in the circuit (poseidon transcript)
|
||||
}
|
||||
@@ -156,6 +157,7 @@ where
|
||||
let i = FpVar::<ConstraintF<C>>::new_witness(cs.clone(), || Ok(self.i.unwrap()))?;
|
||||
let z_0 = FpVar::<ConstraintF<C>>::new_witness(cs.clone(), || Ok(self.z_0.unwrap()))?;
|
||||
let z_i = FpVar::<ConstraintF<C>>::new_witness(cs.clone(), || Ok(self.z_i.unwrap()))?;
|
||||
let z_i1 = FpVar::<ConstraintF<C>>::new_witness(cs.clone(), || Ok(self.z_i1.unwrap()))?;
|
||||
|
||||
let phi = PhiVar::<C, GC>::new_witness(cs.clone(), || Ok(self.phi.unwrap()))?;
|
||||
let phiBig = PhiVar::<C, GC>::new_witness(cs.clone(), || Ok(self.phiBig.unwrap()))?;
|
||||
@@ -168,8 +170,9 @@ where
|
||||
})?; // r will come from transcript
|
||||
|
||||
// 1. phi.x == H(vk_nifs, i, z_0, z_i, phiBig)
|
||||
let mut sponge = PoseidonSpongeVar::<ConstraintF<C>>::new(cs, &self.poseidon_config);
|
||||
let input = vec![i, z_0, z_i];
|
||||
let mut sponge =
|
||||
PoseidonSpongeVar::<ConstraintF<C>>::new(cs.clone(), &self.poseidon_config);
|
||||
let input = vec![i.clone(), z_0.clone(), z_i.clone()];
|
||||
sponge.absorb(&input)?;
|
||||
let input = vec![
|
||||
phiBig.u.to_constraint_field()?,
|
||||
@@ -182,15 +185,24 @@ where
|
||||
let x_CF = phi.x.to_constraint_field()?; // phi.x on the ConstraintF<C>
|
||||
x_CF[0].enforce_equal(&h[0])?; // review
|
||||
|
||||
// // 2. phi.cmE==0, phi.u==1
|
||||
// <GC as CurveVar<C, ConstraintF<C>>>::is_zero(&phi.cmE)?;
|
||||
// 2. phi.cmE==0, phi.u==1
|
||||
(phi.cmE.is_zero()?).enforce_equal(&Boolean::TRUE)?;
|
||||
(phi.u.is_one()?).enforce_equal(&Boolean::TRUE)?;
|
||||
|
||||
// 3. nifs.verify
|
||||
NIFSGadget::<C, GC>::verify(r, cmT, phi, phiBig, phiOut)?;
|
||||
// 3. nifs.verify, checks that folding phi & phiBig obtains phiOut
|
||||
NIFSGadget::<C, GC>::verify(r, cmT, phi, phiBig, phiOut.clone())?;
|
||||
|
||||
// 4. zksnark.V(vk_snark, phi_new, proof_phi)
|
||||
// 5. phiOut.x == H(i+1, z_0, z_i+1, phiOut)
|
||||
// WIP
|
||||
let mut sponge = PoseidonSpongeVar::<ConstraintF<C>>::new(cs, &self.poseidon_config);
|
||||
let input = vec![i + FpVar::<ConstraintF<C>>::one(), z_0, z_i1];
|
||||
sponge.absorb(&input)?;
|
||||
let input = vec![phiOut.cmE.to_bytes()?, phiOut.cmW.to_bytes()?];
|
||||
sponge.absorb(&input)?;
|
||||
let h = sponge.squeeze_field_elements(1).unwrap();
|
||||
let x_CF = phiOut.x.to_constraint_field()?; // phi.x on the ConstraintF<C>
|
||||
x_CF[0].enforce_equal(&h[0])?; // review
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
134
src/ivc.rs
Normal file
134
src/ivc.rs
Normal file
@@ -0,0 +1,134 @@
|
||||
use ark_crypto_primitives::sponge::Absorb;
|
||||
use ark_ec::{CurveGroup, Group};
|
||||
use ark_ff::{Field, PrimeField};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use ark_crypto_primitives::sponge::poseidon::{PoseidonConfig, PoseidonSponge};
|
||||
use ark_r1cs_std::{groups::GroupOpsBounds, prelude::CurveVar};
|
||||
use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError};
|
||||
|
||||
use crate::circuits::{AugmentedFCircuit, ConstraintF};
|
||||
use crate::nifs::{FWit, Phi, NIFS, R1CS};
|
||||
use crate::pedersen::{Commitment, Params as PedersenParams, Pedersen, Proof as PedersenProof};
|
||||
use crate::transcript::Transcript;
|
||||
|
||||
use ark_std::{One, Zero};
|
||||
use core::ops::Deref;
|
||||
|
||||
pub struct IVCProof<C1: CurveGroup, C2: CurveGroup> {
|
||||
phi: Phi<C1>,
|
||||
// w: FWit<C1>,
|
||||
w: Vec<C1::ScalarField>,
|
||||
phiBig: Phi<C2>,
|
||||
// W: FWit<C2>,
|
||||
W: Vec<C2::ScalarField>,
|
||||
}
|
||||
|
||||
pub struct IVC<
|
||||
C1: CurveGroup,
|
||||
GC1: CurveVar<C1, ConstraintF<C1>>,
|
||||
C2: CurveGroup,
|
||||
GC2: CurveVar<C2, ConstraintF<C2>>,
|
||||
> where
|
||||
C1: CurveGroup<BaseField = <C2 as Group>::ScalarField>,
|
||||
C2: CurveGroup<BaseField = <C1 as Group>::ScalarField>,
|
||||
{
|
||||
_c1: PhantomData<C1>,
|
||||
_gc1: PhantomData<GC1>,
|
||||
_c2: PhantomData<C2>,
|
||||
_gc2: PhantomData<GC2>,
|
||||
|
||||
pub poseidon_config: PoseidonConfig<ConstraintF<C2>>,
|
||||
pub pedersen_params_C1: PedersenParams<C1>,
|
||||
pub pedersen_params_C2: PedersenParams<C2>,
|
||||
}
|
||||
|
||||
impl<
|
||||
C1: CurveGroup,
|
||||
GC1: CurveVar<C1, ConstraintF<C1>>,
|
||||
C2: CurveGroup,
|
||||
GC2: CurveVar<C2, ConstraintF<C2>>,
|
||||
> IVC<C1, GC1, C2, GC2>
|
||||
where
|
||||
for<'a> &'a GC1: GroupOpsBounds<'a, C1, GC1>,
|
||||
for<'a> &'a GC2: GroupOpsBounds<'a, C2, GC2>,
|
||||
C1: CurveGroup<BaseField = <C2 as Group>::ScalarField>,
|
||||
C2: CurveGroup<BaseField = <C1 as Group>::ScalarField>,
|
||||
|
||||
<C1 as Group>::ScalarField: Absorb,
|
||||
<C1 as CurveGroup>::BaseField: Absorb,
|
||||
<<C1 as CurveGroup>::BaseField as Field>::BasePrimeField: Absorb,
|
||||
<C1 as CurveGroup>::BaseField: PrimeField,
|
||||
// 2
|
||||
<C2 as Group>::ScalarField: Absorb,
|
||||
<C2 as CurveGroup>::BaseField: Absorb,
|
||||
<<C2 as CurveGroup>::BaseField as Field>::BasePrimeField: Absorb,
|
||||
<C2 as CurveGroup>::BaseField: PrimeField,
|
||||
{
|
||||
pub fn prove(
|
||||
&self,
|
||||
cs: ConstraintSystemRef<ConstraintF<C2>>,
|
||||
tr1: &mut Transcript<C1::ScalarField, C1>,
|
||||
tr2: &mut Transcript<C2::ScalarField, C2>,
|
||||
r1cs: &R1CS<C2::ScalarField>,
|
||||
i: C1::ScalarField,
|
||||
z_0: C1::ScalarField,
|
||||
z_i: C1::ScalarField,
|
||||
// phi1: &Phi<C>,
|
||||
// phi2: &Phi<C>,
|
||||
fw1: FWit<C2>,
|
||||
fw2: FWit<C2>,
|
||||
) -> Result<IVCProof<C1, C2>, SynthesisError> {
|
||||
tr1.get_challenge();
|
||||
let r = tr2.get_challenge(); // TODO transcript usage is still WIP, will update with expected adds & gets
|
||||
|
||||
// fold phi_i and phiBig_i
|
||||
let (fw3, phi1, phi2, _T, cmT) =
|
||||
NIFS::<C2>::P(tr2, &self.pedersen_params_C2, r, r1cs, fw1, fw2);
|
||||
let phi3 = NIFS::<C2>::V(r, &phi1, &phi2, &cmT);
|
||||
|
||||
// TODO compute z_{i+1}
|
||||
let z_i1 = z_i.clone(); // WIP this will be the actual computed z_{i+1}
|
||||
|
||||
let c = AugmentedFCircuit::<C2, GC2> {
|
||||
_c: PhantomData,
|
||||
_gc: PhantomData,
|
||||
poseidon_config: self.poseidon_config.clone(),
|
||||
i: Some(i),
|
||||
z_0: Some(z_0),
|
||||
z_i: Some(z_i),
|
||||
z_i1: Some(z_i1),
|
||||
phi: Some(phi1),
|
||||
phiBig: Some(phi2),
|
||||
phiOut: Some(phi3.clone()),
|
||||
cmT: Some(cmT.0),
|
||||
r: Some(r),
|
||||
};
|
||||
|
||||
c.generate_constraints(cs.clone())?;
|
||||
|
||||
// get w_{i+1}
|
||||
let cs1 = cs.borrow().unwrap();
|
||||
let cs2 = cs1.deref();
|
||||
let w_i1 = cs2.witness_assignment.clone();
|
||||
let x_i1 = cs2.instance_assignment.clone();
|
||||
|
||||
let rW = tr1.get_challenge();
|
||||
let _ = tr2.get_challenge();
|
||||
|
||||
// phi_{i+1} small
|
||||
let phi = Phi::<C1> {
|
||||
cmE: Commitment::<C1>(C1::zero()),
|
||||
u: C1::ScalarField::one(),
|
||||
cmW: Pedersen::commit(&self.pedersen_params_C1, &w_i1, &rW),
|
||||
x: x_i1[0], // check if pos 0 is 1
|
||||
};
|
||||
|
||||
Ok(IVCProof {
|
||||
phiBig: phi3,
|
||||
W: fw3.W,
|
||||
phi, // phi_{i+1}
|
||||
w: w_i1, // w_{i+1}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
#![allow(dead_code)] // TMP
|
||||
|
||||
mod circuits;
|
||||
mod ivc;
|
||||
mod nifs;
|
||||
mod pedersen;
|
||||
mod sumcheck;
|
||||
|
||||
@@ -26,10 +26,10 @@ pub struct Phi<C: CurveGroup> {
|
||||
|
||||
// FWit: Folded Witness
|
||||
pub struct FWit<C: CurveGroup> {
|
||||
E: Vec<C::ScalarField>,
|
||||
rE: C::ScalarField,
|
||||
W: Vec<C::ScalarField>,
|
||||
rW: C::ScalarField,
|
||||
pub E: Vec<C::ScalarField>,
|
||||
pub rE: C::ScalarField,
|
||||
pub W: Vec<C::ScalarField>,
|
||||
pub rW: C::ScalarField,
|
||||
}
|
||||
|
||||
impl<C: CurveGroup> FWit<C>
|
||||
|
||||
Reference in New Issue
Block a user