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}