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}