mirror of
https://github.com/arnaucube/sonobe.git
synced 2026-01-09 07:21:28 +01:00
Implement Nova's NIFS.Verify circuits (with CycleFold) (#11)
* Implement Nova's NIFS.Verify circuits (with CycleFold) - Add circuit for NIFS.Verify on the main curve to check the folded `u` & `x` - Add circuit for NIFS.Verify on the CycleFold's auxiliary curve to check the folded `cm(E)` & `cm(W)` - Add transcript.get_challenge_nbits - Add tests for utils::vec.rs * replace bls12-377 & bw6-761 by pallas & vesta curves (only affects tests) We will use pallas & vesta curves (for tests only, the non-tests code uses generics) for the logic that does not require pairings, and while Grumpkin is not available (https://github.com/privacy-scaling-explorations/folding-schemes/issues/12). * update links to papers to markdown style
This commit is contained in:
@@ -1,26 +1,28 @@
|
||||
/// Implements the C_{EC} circuit described in CycleFold paper https://eprint.iacr.org/2023/1192.pdf
|
||||
/// Implements the C_{EC} circuit described in [CycleFold paper](https://eprint.iacr.org/2023/1192.pdf)
|
||||
use ark_ec::CurveGroup;
|
||||
use ark_r1cs_std::{fields::nonnative::NonNativeFieldVar, prelude::CurveVar, ToBitsGadget};
|
||||
use ark_r1cs_std::{boolean::Boolean, prelude::CurveVar};
|
||||
use ark_relations::r1cs::SynthesisError;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use super::ConstraintF;
|
||||
use super::CF;
|
||||
|
||||
/// ECRLC implements gadget that checks the Elliptic Curve points RandomLinearCombination described
|
||||
/// in CycleFold (https://eprint.iacr.org/2023/1192.pdf).
|
||||
/// in [CycleFold](https://eprint.iacr.org/2023/1192.pdf).
|
||||
#[derive(Debug)]
|
||||
pub struct ECRLC<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>> {
|
||||
pub struct ECRLC<C: CurveGroup, GC: CurveVar<C, CF<C>>> {
|
||||
_c: PhantomData<C>,
|
||||
_gc: PhantomData<GC>,
|
||||
}
|
||||
impl<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>> ECRLC<C, GC> {
|
||||
impl<C: CurveGroup, GC: CurveVar<C, CF<C>>> ECRLC<C, GC> {
|
||||
pub fn check(
|
||||
r: NonNativeFieldVar<C::ScalarField, ConstraintF<C>>,
|
||||
// get r in bits format, so it can be reused across many instances of ECRLC gadget,
|
||||
// reducing the number of constraints needed
|
||||
r_bits: Vec<Boolean<CF<C>>>,
|
||||
p1: GC,
|
||||
p2: GC,
|
||||
p3: GC,
|
||||
) -> Result<(), SynthesisError> {
|
||||
p3.enforce_equal(&(p1 + p2.scalar_mul_le(r.to_bits_le()?.iter())?))?;
|
||||
p3.enforce_equal(&(p1 + p2.scalar_mul_le(r_bits.iter())?))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -28,35 +30,36 @@ impl<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>> ECRLC<C, GC> {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use ark_bls12_377::{constraints::G1Var, Fq, Fr, G1Projective};
|
||||
use ark_ff::{BigInteger, PrimeField};
|
||||
use ark_pallas::{constraints::GVar, Fq, Fr, Projective};
|
||||
use ark_r1cs_std::alloc::AllocVar;
|
||||
use ark_relations::r1cs::ConstraintSystem;
|
||||
use ark_std::UniformRand;
|
||||
use std::ops::Mul;
|
||||
|
||||
/// Let Curve1=bls12-377::G1 and Curve2=bw6-761::G1. Here we have our constraint system will
|
||||
/// work over Curve2::Fr = bw6-761::Fr (=bls12-377::Fq), thus our points are P_i \in Curve1
|
||||
/// (=bls12-377).
|
||||
/// Let Curve1=pallas and Curve2=vesta. Here our constraints system will work over Curve2::Fr =
|
||||
/// vesta::Fr (=pallas::Fq), thus our points are P_i \in Curve1 (=pasta).
|
||||
#[test]
|
||||
fn test_ecrlc_check() {
|
||||
let mut rng = ark_std::test_rng();
|
||||
|
||||
let r = Fr::rand(&mut rng);
|
||||
let p1 = G1Projective::rand(&mut rng);
|
||||
let p2 = G1Projective::rand(&mut rng);
|
||||
let p1 = Projective::rand(&mut rng);
|
||||
let p2 = Projective::rand(&mut rng);
|
||||
let p3 = p1 + p2.mul(r);
|
||||
|
||||
let cs = ConstraintSystem::<Fq>::new_ref(); // CS over Curve2::Fr = Curve1::Fq
|
||||
|
||||
// prepare circuit inputs
|
||||
let rVar = NonNativeFieldVar::<Fr, Fq>::new_witness(cs.clone(), || Ok(r)).unwrap();
|
||||
let p1Var = G1Var::new_witness(cs.clone(), || Ok(p1)).unwrap();
|
||||
let p2Var = G1Var::new_witness(cs.clone(), || Ok(p2)).unwrap();
|
||||
let p3Var = G1Var::new_witness(cs.clone(), || Ok(p3)).unwrap();
|
||||
let rbitsVar: Vec<Boolean<Fq>> =
|
||||
Vec::new_witness(cs.clone(), || Ok(r.into_bigint().to_bits_le())).unwrap();
|
||||
|
||||
let p1Var = GVar::new_witness(cs.clone(), || Ok(p1)).unwrap();
|
||||
let p2Var = GVar::new_witness(cs.clone(), || Ok(p2)).unwrap();
|
||||
let p3Var = GVar::new_witness(cs.clone(), || Ok(p3)).unwrap();
|
||||
|
||||
// check ECRLC circuit
|
||||
ECRLC::<G1Projective, G1Var>::check(rVar, p1Var, p2Var, p3Var).unwrap();
|
||||
ECRLC::<Projective, GVar>::check(rbitsVar, p1Var, p2Var, p3Var).unwrap();
|
||||
assert!(cs.is_satisfied().unwrap());
|
||||
// dbg!(cs.num_constraints());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user