arnaucube
arnaucube/nova-studyPublic Self-hosted repository
nova-study/src/circuits.rs
src/circuits.rsRaw
  1use ark_crypto_primitives::snark::{FromFieldElementsGadget, SNARKGadget, SNARK};
  2use ark_ec::AffineRepr;
  3use ark_ec::{CurveGroup, Group};
  4use ark_ff::{fields::Fp256, Field, PrimeField};
  5use ark_r1cs_std::{
  6    alloc::{AllocVar, AllocationMode},
  7    bits::uint8::UInt8,
  8    boolean::Boolean,
  9    eq::EqGadget,
 10    fields::{
 11        fp::{AllocatedFp, FpVar},
 12        nonnative::NonNativeFieldVar,
 13        FieldVar,
 14    },
 15    groups::curves::short_weierstrass::ProjectiveVar,
 16    groups::GroupOpsBounds,
 17    prelude::CurveVar,
 18    ToBitsGadget, ToBytesGadget, ToConstraintFieldGadget,
 19};
 20use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError};
 21use ark_std::ops::Mul;
 22
 23use core::{borrow::Borrow, marker::PhantomData};
 24use derivative::Derivative;
 25
 26use crate::nifs::Phi;
 27
 28pub type ConstraintF<C> = <<C as CurveGroup>::BaseField as Field>::BasePrimeField;
 29
 30#[derive(Debug, Derivative)]
 31#[derivative(Clone(bound = "C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>"))]
 32pub struct PhiVar<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>>
 33where
 34    for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
 35{
 36    _c: PhantomData<C>,
 37    cmE: GC,
 38    u: NonNativeFieldVar<C::ScalarField, ConstraintF<C>>,
 39    cmW: GC,
 40    x: NonNativeFieldVar<C::ScalarField, ConstraintF<C>>,
 41}
 42
 43impl<C, GC> AllocVar<Phi<C>, ConstraintF<C>> for PhiVar<C, GC>
 44where
 45    C: CurveGroup,
 46    GC: CurveVar<C, ConstraintF<C>>,
 47    for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
 48{
 49    fn new_variable<T: Borrow<Phi<C>>>(
 50        cs: impl Into<Namespace<ConstraintF<C>>>,
 51        f: impl FnOnce() -> Result<T, SynthesisError>,
 52        mode: AllocationMode,
 53    ) -> Result<Self, SynthesisError> {
 54        f().and_then(|val| {
 55            let cs = cs.into();
 56
 57            let u = NonNativeFieldVar::<C::ScalarField, ConstraintF<C>>::new_variable(
 58                cs.clone(),
 59                || Ok(val.borrow().u),
 60                mode,
 61            )?;
 62            let cmE = GC::new_variable(cs.clone(), || Ok(val.borrow().cmE.0), mode)?;
 63            let cmW = GC::new_variable(cs.clone(), || Ok(val.borrow().cmW.0), mode)?;
 64
 65            let x = NonNativeFieldVar::<C::ScalarField, ConstraintF<C>>::new_variable(
 66                cs.clone(),
 67                || Ok(val.borrow().x),
 68                mode,
 69            )?;
 70
 71            Ok(Self {
 72                _c: PhantomData,
 73                cmE,
 74                u,
 75                cmW,
 76                x,
 77            })
 78        })
 79    }
 80}
 81
 82pub struct NIFSGadget<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>> {
 83    _c: PhantomData<C>,
 84    _gc: PhantomData<GC>,
 85}
 86
 87impl<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>> NIFSGadget<C, GC>
 88where
 89    C: CurveGroup,
 90    GC: CurveVar<C, ConstraintF<C>>,
 91    for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
 92{
 93    // implements the constraints for NIFS.V
 94    pub fn verify(
 95        r: NonNativeFieldVar<C::ScalarField, ConstraintF<C>>,
 96        cmT: GC,
 97        phi1: PhiVar<C, GC>,
 98        phi2: PhiVar<C, GC>,
 99        phi3: PhiVar<C, GC>,
100    ) -> Result<Boolean<ConstraintF<C>>, SynthesisError> {
101        let r2 = r.square()?;
102
103        phi3.cmE.is_eq(
104            &(phi1.cmE
105                + cmT.scalar_mul_le(r.to_bits_le()?.iter())?
106                + phi2.cmE.scalar_mul_le(r2.to_bits_le()?.iter())?),
107        )?;
108        phi3.u.is_eq(&(phi1.u + r.clone() * phi2.u))?;
109        phi3.cmW
110            .is_eq(&(phi1.cmW + phi2.cmW.scalar_mul_le(r.to_bits_le()?.iter())?))?;
111
112        // wip x's check
113        phi3.x.is_eq(&(phi1.x + r.clone() * phi2.x))
114    }
115}
116
117////
118
119pub trait Config<Fq: PrimeField, Fr: PrimeField> {
120    type AugmentedFunctionCircuit: SNARK<Fq>; // F'
121    type FunctionCircuit: ConstraintSynthesizer<Fq>; // F
122    type DummyStepCircuit: SNARK<Fr>;
123}
124
125pub struct AugmentedFCircuit<
126    Fq: PrimeField,
127    Fr: PrimeField,
128    C: CurveGroup,
129    GC: CurveVar<C, Fq>,
130    Cfg: Config<Fq, Fr>,
131> {
132    pub dummystep_vk: Option<<Cfg::DummyStepCircuit as SNARK<Fr>>::VerifyingKey>,
133    _c: PhantomData<C>,
134    _gc: PhantomData<GC>,
135}
136
137impl<Fq: PrimeField, Fr: PrimeField, C: CurveGroup, GC: CurveVar<C, Fq>, Cfg: Config<Fq, Fr>>
138    ConstraintSynthesizer<Fq> for AugmentedFCircuit<Fq, Fr, C, GC, Cfg>
139{
140    fn generate_constraints(self, cs: ConstraintSystemRef<Fq>) -> Result<(), SynthesisError> {
141        unimplemented!();
142    }
143}
144
145#[cfg(test)]
146mod test {
147    use super::*;
148
149    use crate::transcript::Transcript;
150    use ark_relations::r1cs::ConstraintSystem;
151    use ark_std::{
152        rand::{Rng, RngCore},
153        UniformRand,
154    };
155
156    use crate::nifs;
157    use crate::pedersen;
158    use ark_ec::CurveGroup;
159    // use ark_ed_on_mnt4_298::{constraints::EdwardsVar, EdwardsProjective};
160    use crate::pedersen::Commitment;
161    use ark_mnt4_298::{constraints::G1Var as MNT4G1Var, Fq, Fr, G1Projective as MNT4G1Projective};
162    use ark_mnt6_298::{constraints::G1Var as MNT6G1Var, G1Projective as MNT6G1Projective};
163    use ark_std::{One, Zero};
164
165    // mnt4's Fr is the Constraint Field,
166    // while mnt4's Fq is the Field where we work, which is the C::ScalarField for C==MNT6G1
167
168    #[test]
169    fn test_phi_var() {
170        let mut rng = ark_std::test_rng();
171
172        let phi = Phi::<MNT6G1Projective> {
173            cmE: Commitment(MNT6G1Projective::generator()),
174            u: Fq::one(),
175            cmW: Commitment(MNT6G1Projective::generator()),
176            x: Fq::one(),
177        };
178
179        let cs = ConstraintSystem::<Fr>::new_ref();
180        let phiVar =
181            PhiVar::<MNT6G1Projective, MNT6G1Var>::new_witness(cs.clone(), || Ok(phi)).unwrap();
182        // println!("num_constraints={:?}", cs.num_constraints());
183    }
184
185    #[test]
186    fn test_nifs_gadget() {
187        let mut rng = ark_std::test_rng();
188        let pedersen_params = pedersen::Pedersen::<MNT6G1Projective>::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec
189
190        let cs = ConstraintSystem::<Fr>::new_ref();
191
192        let (r1cs, w1, w2, _, x1, x2, _) = nifs::gen_test_values::<_, Fq>(&mut rng);
193        let (A, B, C) = (r1cs.A.clone(), r1cs.B.clone(), r1cs.C.clone());
194
195        let r = Fq::rand(&mut rng); // this would come from the transcript
196
197        let fw1 = nifs::FWit::<MNT6G1Projective>::new(w1.clone(), A.len());
198        let fw2 = nifs::FWit::<MNT6G1Projective>::new(w2.clone(), A.len());
199        let mut transcript_p = Transcript::<Fq>::new();
200        let (fw3, phi1, phi2, T, cmT) = nifs::NIFS::<MNT6G1Projective>::P(
201            &mut transcript_p,
202            &pedersen_params,
203            r,
204            &r1cs,
205            fw1,
206            fw2,
207        );
208        let phi3 = nifs::NIFS::<MNT6G1Projective>::V(r, &phi1, &phi2, &cmT);
209
210        let phi1Var =
211            PhiVar::<MNT6G1Projective, MNT6G1Var>::new_witness(cs.clone(), || Ok(phi1)).unwrap();
212        let phi2Var =
213            PhiVar::<MNT6G1Projective, MNT6G1Var>::new_witness(cs.clone(), || Ok(phi2)).unwrap();
214        let phi3Var =
215            PhiVar::<MNT6G1Projective, MNT6G1Var>::new_witness(cs.clone(), || Ok(phi3)).unwrap();
216
217        let cmTVar = MNT6G1Var::new_witness(cs.clone(), || Ok(cmT.0)).unwrap();
218        let rVar = NonNativeFieldVar::<Fq, Fr>::new_witness(cs.clone(), || Ok(r)).unwrap();
219
220        let valid = NIFSGadget::<MNT6G1Projective, MNT6G1Var>::verify(
221            rVar, cmTVar, phi1Var, phi2Var, phi3Var,
222        );
223        println!("num_constraints={:?}", cs.num_constraints());
224    }
225}