From 0aa22d0ae28972cf893d2ea261e088ba2f8aabc1 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sat, 29 Apr 2023 08:15:31 +0200 Subject: [PATCH] circuits PhiVar parse, NIFS.V gadget implemented, added circuits tests --- src/circuits.rs | 215 +++++++++++++++++++++++++++++++++++++++--------- src/sumcheck.rs | 6 +- 2 files changed, 180 insertions(+), 41 deletions(-) diff --git a/src/circuits.rs b/src/circuits.rs index 69b77df..2a13c04 100644 --- a/src/circuits.rs +++ b/src/circuits.rs @@ -1,16 +1,21 @@ use ark_crypto_primitives::snark::{FromFieldElementsGadget, SNARKGadget, SNARK}; use ark_ec::AffineRepr; -use ark_ec::CurveGroup; +use ark_ec::{CurveGroup, Group}; use ark_ff::{fields::Fp256, Field, PrimeField}; use ark_r1cs_std::{ alloc::{AllocVar, AllocationMode}, bits::uint8::UInt8, boolean::Boolean, eq::EqGadget, - fields::{fp::FpVar, FieldVar}, + fields::{ + fp::{AllocatedFp, FpVar}, + nonnative::NonNativeFieldVar, + FieldVar, + }, + groups::curves::short_weierstrass::ProjectiveVar, groups::GroupOpsBounds, prelude::CurveVar, - ToBitsGadget, + ToBitsGadget, ToBytesGadget, ToConstraintFieldGadget, }; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; use ark_std::ops::Mul; @@ -18,7 +23,98 @@ use ark_std::ops::Mul; use core::{borrow::Borrow, marker::PhantomData}; use derivative::Derivative; -// pub trait Nova {} +use crate::nifs::Phi; + +pub type ConstraintF = <::BaseField as Field>::BasePrimeField; + +#[derive(Debug, Derivative)] +#[derivative(Clone(bound = "C: CurveGroup, GC: CurveVar>"))] +pub struct PhiVar>> +where + for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, +{ + _c: PhantomData, + cmE: GC, + u: NonNativeFieldVar>, + cmW: GC, + x: NonNativeFieldVar>, +} + +impl AllocVar, ConstraintF> for PhiVar +where + C: CurveGroup, + GC: CurveVar>, + for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, +{ + fn new_variable>>( + cs: impl Into>>, + f: impl FnOnce() -> Result, + mode: AllocationMode, + ) -> Result { + f().and_then(|val| { + let cs = cs.into(); + + let u = NonNativeFieldVar::>::new_variable( + cs.clone(), + || Ok(val.borrow().u), + mode, + )?; + let cmE = GC::new_variable(cs.clone(), || Ok(val.borrow().cmE.0), mode)?; + let cmW = GC::new_variable(cs.clone(), || Ok(val.borrow().cmW.0), mode)?; + + let x = NonNativeFieldVar::>::new_variable( + cs.clone(), + || Ok(val.borrow().x), + mode, + )?; + + Ok(Self { + _c: PhantomData, + cmE, + u, + cmW, + x, + }) + }) + } +} + +pub struct NIFSGadget>> { + _c: PhantomData, + _gc: PhantomData, +} + +impl>> NIFSGadget +where + C: CurveGroup, + GC: CurveVar>, + for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, +{ + // implements the constraints for NIFS.V + pub fn verify( + r: NonNativeFieldVar>, + cmT: GC, + phi1: PhiVar, + phi2: PhiVar, + phi3: PhiVar, + ) -> Result>, SynthesisError> { + let r2 = r.square()?; + + phi3.cmE.is_eq( + &(phi1.cmE + + cmT.scalar_mul_le(r.to_bits_le()?.iter())? + + phi2.cmE.scalar_mul_le(r2.to_bits_le()?.iter())?), + )?; + phi3.u.is_eq(&(phi1.u + r.clone() * phi2.u))?; + phi3.cmW + .is_eq(&(phi1.cmW + phi2.cmW.scalar_mul_le(r.to_bits_le()?.iter())?))?; + + // wip x's check + phi3.x.is_eq(&(phi1.x + r.clone() * phi2.x)) + } +} + +//// pub trait Config { type AugmentedFunctionCircuit: SNARK; // F' @@ -46,41 +142,84 @@ impl, Cfg: Co } } -pub struct NIFSGadget> { - _f: PhantomData, - _c: PhantomData, - _gc: PhantomData, -} +#[cfg(test)] +mod test { + use super::*; -impl> NIFSGadget { - // implements the constraints for NIFS.V - pub fn verify( - r: FpVar, - cmT: GC, - // phi1, phi2 and phi3 - cmE1: GC, - cmE2: GC, - cmE3: GC, - u1: FpVar, - u2: FpVar, - u3: FpVar, - cmW1: GC, - cmW2: GC, - cmW3: GC, - // x's size will depend on the num_publicinputs of F circuit - x1: Vec>, - x2: Vec>, - x3: Vec>, - ) -> Result, SynthesisError> { - let r2 = r.square()?; - cmE3.is_eq( - &(cmE1 - + cmT.scalar_mul_le(r.to_bits_le()?.iter())? - + cmE2.scalar_mul_le(r2.to_bits_le()?.iter())?), - )?; - u3.is_eq(&(u1 + r.clone() * u2))?; - cmW3.is_eq(&(cmW1 + cmW2.scalar_mul_le(r.to_bits_le()?.iter())?)) + use crate::transcript::Transcript; + use ark_relations::r1cs::ConstraintSystem; + use ark_std::{ + rand::{Rng, RngCore}, + UniformRand, + }; + + use crate::nifs; + use crate::pedersen; + use ark_ec::CurveGroup; + // use ark_ed_on_mnt4_298::{constraints::EdwardsVar, EdwardsProjective}; + use crate::pedersen::Commitment; + use ark_mnt4_298::{constraints::G1Var as MNT4G1Var, Fq, Fr, G1Projective as MNT4G1Projective}; + use ark_mnt6_298::{constraints::G1Var as MNT6G1Var, G1Projective as MNT6G1Projective}; + use ark_std::{One, Zero}; + + // mnt4's Fr is the Constraint Field, + // while mnt4's Fq is the Field where we work, which is the C::ScalarField for C==MNT6G1 + + #[test] + fn test_phi_var() { + let mut rng = ark_std::test_rng(); + + let phi = Phi:: { + cmE: Commitment(MNT6G1Projective::generator()), + u: Fq::one(), + cmW: Commitment(MNT6G1Projective::generator()), + x: Fq::one(), + }; + + let cs = ConstraintSystem::::new_ref(); + let phiVar = + PhiVar::::new_witness(cs.clone(), || Ok(phi)).unwrap(); + // println!("num_constraints={:?}", cs.num_constraints()); + } + + #[test] + fn test_nifs_gadget() { + let mut rng = ark_std::test_rng(); + let pedersen_params = pedersen::Pedersen::::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec + + let cs = ConstraintSystem::::new_ref(); + + let (r1cs, w1, w2, _, x1, x2, _) = nifs::gen_test_values::<_, Fq>(&mut rng); + let (A, B, C) = (r1cs.A.clone(), r1cs.B.clone(), r1cs.C.clone()); + + let r = Fq::rand(&mut rng); // this would come from the transcript + + let fw1 = nifs::FWit::::new(w1.clone(), A.len()); + let fw2 = nifs::FWit::::new(w2.clone(), A.len()); + let mut transcript_p = Transcript::::new(); + let (fw3, phi1, phi2, T, cmT) = nifs::NIFS::::P( + &mut transcript_p, + &pedersen_params, + r, + &r1cs, + fw1, + fw2, + ); + let phi3 = nifs::NIFS::::V(r, &phi1, &phi2, &cmT); + + let phi1Var = + PhiVar::::new_witness(cs.clone(), || Ok(phi1)).unwrap(); + let phi2Var = + PhiVar::::new_witness(cs.clone(), || Ok(phi2)).unwrap(); + let phi3Var = + PhiVar::::new_witness(cs.clone(), || Ok(phi3)).unwrap(); + + let cmTVar = MNT6G1Var::new_witness(cs.clone(), || Ok(cmT.0)).unwrap(); + let rVar = NonNativeFieldVar::::new_witness(cs.clone(), || Ok(r)).unwrap(); - // TODO x's check + let valid = NIFSGadget::::verify( + rVar, cmTVar, phi1Var, phi2Var, phi3Var, + ); + println!("num_constraints={:?}", cs.num_constraints()); } } diff --git a/src/sumcheck.rs b/src/sumcheck.rs index 43eb9a2..407131d 100644 --- a/src/sumcheck.rs +++ b/src/sumcheck.rs @@ -1,5 +1,5 @@ -// Sum-check protocol initial implementation, not used by the rest of the repo but implemented as -// an exercise and it will probably be used in the future. +// this file contains a sum-check protocol initial implementation, not used by the rest of the repo +// but implemented as an exercise and it will probably be used in the future. use ark_ff::{BigInteger, PrimeField}; use ark_poly::{ @@ -200,7 +200,7 @@ impl< #[cfg(test)] mod tests { use super::*; - use ark_bn254::Fr; // scalar field + use ark_mnt4_298::Fr; // scalar field #[test] fn test_new_point() {