arnaucube
arnaucube/nova-studyPublic Self-hosted repository
nova-study/src/ivc.rs
src/ivc.rsRaw
  1use ark_crypto_primitives::sponge::Absorb;
  2use ark_ec::{CurveGroup, Group};
  3use ark_ff::{Field, PrimeField};
  4use std::marker::PhantomData;
  5
  6use ark_crypto_primitives::sponge::poseidon::{PoseidonConfig, PoseidonSponge};
  7use ark_r1cs_std::{groups::GroupOpsBounds, prelude::CurveVar};
  8use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError};
  9
 10use crate::circuits::{AugmentedFCircuit, ConstraintF};
 11use crate::nifs::{FWit, Phi, NIFS, R1CS};
 12use crate::pedersen::{Commitment, Params as PedersenParams, Pedersen, Proof as PedersenProof};
 13use crate::transcript::Transcript;
 14
 15use ark_std::{One, Zero};
 16use core::ops::Deref;
 17
 18pub struct IVCProof<C1: CurveGroup, C2: CurveGroup> {
 19    phi: Phi<C1>,
 20    // w: FWit<C1>,
 21    w: Vec<C1::ScalarField>,
 22    phiBig: Phi<C2>,
 23    // W: FWit<C2>,
 24    W: Vec<C2::ScalarField>,
 25}
 26
 27pub struct IVC<
 28    C1: CurveGroup,
 29    GC1: CurveVar<C1, ConstraintF<C1>>,
 30    C2: CurveGroup,
 31    GC2: CurveVar<C2, ConstraintF<C2>>,
 32> where
 33    C1: CurveGroup<BaseField = <C2 as Group>::ScalarField>,
 34    C2: CurveGroup<BaseField = <C1 as Group>::ScalarField>,
 35{
 36    _c1: PhantomData<C1>,
 37    _gc1: PhantomData<GC1>,
 38    _c2: PhantomData<C2>,
 39    _gc2: PhantomData<GC2>,
 40
 41    pub poseidon_config: PoseidonConfig<ConstraintF<C2>>,
 42    pub pedersen_params_C1: PedersenParams<C1>,
 43    pub pedersen_params_C2: PedersenParams<C2>,
 44}
 45
 46impl<
 47        C1: CurveGroup,
 48        GC1: CurveVar<C1, ConstraintF<C1>>,
 49        C2: CurveGroup,
 50        GC2: CurveVar<C2, ConstraintF<C2>>,
 51    > IVC<C1, GC1, C2, GC2>
 52where
 53    for<'a> &'a GC1: GroupOpsBounds<'a, C1, GC1>,
 54    for<'a> &'a GC2: GroupOpsBounds<'a, C2, GC2>,
 55    C1: CurveGroup<BaseField = <C2 as Group>::ScalarField>,
 56    C2: CurveGroup<BaseField = <C1 as Group>::ScalarField>,
 57
 58    <C1 as Group>::ScalarField: Absorb,
 59    <C1 as CurveGroup>::BaseField: Absorb,
 60    <<C1 as CurveGroup>::BaseField as Field>::BasePrimeField: Absorb,
 61    <C1 as CurveGroup>::BaseField: PrimeField,
 62    // 2
 63    <C2 as Group>::ScalarField: Absorb,
 64    <C2 as CurveGroup>::BaseField: Absorb,
 65    <<C2 as CurveGroup>::BaseField as Field>::BasePrimeField: Absorb,
 66    <C2 as CurveGroup>::BaseField: PrimeField,
 67{
 68    pub fn prove(
 69        &self,
 70        cs: ConstraintSystemRef<ConstraintF<C2>>,
 71        tr1: &mut Transcript<C1::ScalarField, C1>,
 72        tr2: &mut Transcript<C2::ScalarField, C2>,
 73        r1cs: &R1CS<C2::ScalarField>,
 74        i: C1::ScalarField,
 75        z_0: C1::ScalarField,
 76        z_i: C1::ScalarField,
 77        // phi1: &Phi<C>,
 78        // phi2: &Phi<C>,
 79        fw1: FWit<C2>,
 80        fw2: FWit<C2>,
 81    ) -> Result<IVCProof<C1, C2>, SynthesisError> {
 82        tr1.get_challenge();
 83        let r = tr2.get_challenge(); // TODO transcript usage is still WIP, will update with expected adds & gets
 84
 85        // fold phi_i and phiBig_i
 86        let (fw3, phi1, phi2, _T, cmT) =
 87            NIFS::<C2>::P(tr2, &self.pedersen_params_C2, r, r1cs, fw1, fw2);
 88        let phi3 = NIFS::<C2>::V(r, &phi1, &phi2, &cmT);
 89
 90        // TODO compute z_{i+1}
 91        let z_i1 = z_i.clone(); // WIP this will be the actual computed z_{i+1}
 92
 93        let c = AugmentedFCircuit::<C2, GC2> {
 94            _c: PhantomData,
 95            _gc: PhantomData,
 96            poseidon_config: self.poseidon_config.clone(),
 97            i: Some(i),
 98            z_0: Some(z_0),
 99            z_i: Some(z_i),
100            z_i1: Some(z_i1),
101            phi: Some(phi1),
102            phiBig: Some(phi2),
103            phiOut: Some(phi3.clone()),
104            cmT: Some(cmT.0),
105            r: Some(r),
106        };
107
108        c.generate_constraints(cs.clone())?;
109
110        // get w_{i+1}
111        let cs1 = cs.borrow().unwrap();
112        let cs2 = cs1.deref();
113        let w_i1 = cs2.witness_assignment.clone();
114        let x_i1 = cs2.instance_assignment.clone();
115
116        let rW = tr1.get_challenge();
117        let _ = tr2.get_challenge();
118
119        // phi_{i+1} small
120        let phi = Phi::<C1> {
121            cmE: Commitment::<C1>(C1::zero()),
122            u: C1::ScalarField::one(),
123            cmW: Pedersen::commit(&self.pedersen_params_C1, &w_i1, &rW),
124            x: x_i1[0], // check if pos 0 is 1
125        };
126
127        Ok(IVCProof {
128            phiBig: phi3,
129            W: fw3.W,
130            phi,     // phi_{i+1}
131            w: w_i1, // w_{i+1}
132        })
133    }
134}