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::{BigInteger, 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, FCircuit};
 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    FC: FCircuit<C1::ScalarField>,
 33> where
 34    C1: CurveGroup<BaseField = <C2 as Group>::ScalarField>,
 35    C2: CurveGroup<BaseField = <C1 as Group>::ScalarField>,
 36{
 37    _c1: PhantomData<C1>,
 38    _gc1: PhantomData<GC1>,
 39    _c2: PhantomData<C2>,
 40    _gc2: PhantomData<GC2>,
 41    _fc: PhantomData<FC>,
 42
 43    pub poseidon_config: PoseidonConfig<ConstraintF<C2>>,
 44    pub pedersen_params_C1: PedersenParams<C1>,
 45    pub pedersen_params_C2: PedersenParams<C2>,
 46    pub F: FC, // F circuit
 47}
 48
 49impl<
 50        C1: CurveGroup,
 51        GC1: CurveVar<C1, ConstraintF<C1>>,
 52        C2: CurveGroup,
 53        GC2: CurveVar<C2, ConstraintF<C2>>,
 54        FC: FCircuit<C1::ScalarField>,
 55    > IVC<C1, GC1, C2, GC2, FC>
 56where
 57    for<'a> &'a GC1: GroupOpsBounds<'a, C1, GC1>,
 58    for<'a> &'a GC2: GroupOpsBounds<'a, C2, GC2>,
 59    C1: CurveGroup<BaseField = <C2 as Group>::ScalarField>,
 60    C2: CurveGroup<BaseField = <C1 as Group>::ScalarField>,
 61
 62    <C1 as Group>::ScalarField: Absorb,
 63    <C1 as CurveGroup>::BaseField: Absorb,
 64    <<C1 as CurveGroup>::BaseField as Field>::BasePrimeField: Absorb,
 65    <C1 as CurveGroup>::BaseField: PrimeField,
 66    // 2
 67    <C2 as Group>::ScalarField: Absorb,
 68    <C2 as CurveGroup>::BaseField: Absorb,
 69    <<C2 as CurveGroup>::BaseField as Field>::BasePrimeField: Absorb,
 70    <C2 as CurveGroup>::BaseField: PrimeField,
 71{
 72    pub fn prove(
 73        &self,
 74        cs: ConstraintSystemRef<ConstraintF<C2>>,
 75        // TODO move part of these parameters to struct constructor instead of prove method
 76        tr1: &mut Transcript<C1::ScalarField, C1>,
 77        tr2: &mut Transcript<C2::ScalarField, C2>,
 78        r1cs: &R1CS<C2::ScalarField>,
 79        i: C1::ScalarField,
 80        z_0: C1::ScalarField,
 81        z_i: C1::ScalarField,
 82        fw1: FWit<C2>,
 83        fw2: FWit<C2>,
 84    ) -> Result<IVCProof<C1, C2>, SynthesisError> {
 85        tr1.get_challenge();
 86        let r = tr2.get_challenge(); // TODO transcript usage is still WIP, will update with expected adds & gets
 87
 88        // fold phi_i and phiBig_i
 89        let (fw3, phi1, phi2, _T, cmT) =
 90            NIFS::<C2>::P(tr2, &self.pedersen_params_C2, r, r1cs, fw1, fw2);
 91        let phi3 = NIFS::<C2>::V(r, &phi1, &phi2, &cmT);
 92
 93        // get z_{i+1}
 94        let (_, F_z_i1) = self.F.public();
 95
 96        let c = AugmentedFCircuit::<C2, GC2, FC> {
 97            _c: PhantomData,
 98            _gc: PhantomData,
 99            poseidon_config: self.poseidon_config.clone(),
100            i: Some(i),
101            z_0: Some(z_0),
102            z_i: Some(z_i),
103            z_i1: Some(F_z_i1),
104            phi: Some(phi1),
105            phiBig: Some(phi2),
106            phiBigOut: Some(phi3.clone()),
107            cmT: Some(cmT.0),
108            r: Some(r),
109            F: self.F,
110            x: i, // TODO WIP put x in there
111        };
112
113        c.generate_constraints(cs.clone())?;
114
115        // get w_{i+1}
116        let cs1 = cs.borrow().unwrap();
117        let cs2 = cs1.deref();
118        let w_i1 = cs2.witness_assignment.clone();
119        let x_i1 = cs2.instance_assignment.clone();
120
121        let rW = tr1.get_challenge();
122        let _ = tr2.get_challenge();
123
124        // phi_{i+1} small
125        let phi = Phi::<C1> {
126            cmE: Commitment::<C1>(C1::zero()),
127            u: C1::ScalarField::one(),
128            cmW: Pedersen::commit(&self.pedersen_params_C1, &w_i1, &rW),
129            x: x_i1[0], // check if pos 0 is 1
130        };
131
132        Ok(IVCProof {
133            phiBig: phi3,
134            W: fw3.W,
135            phi,     // phi_{i+1}
136            w: w_i1, // w_{i+1}
137        })
138    }
139}