arnaucube
arnaucube/sonobePublic Self-hosted repository
sonobe/src/folding/circuits/cyclefold.rs
src/folding/circuits/cyclefold.rsRaw
 1/// Implements the C_{EC} circuit described in CycleFold paper https://eprint.iacr.org/2023/1192.pdf
 2use ark_ec::CurveGroup;
 3use ark_r1cs_std::{fields::nonnative::NonNativeFieldVar, prelude::CurveVar, ToBitsGadget};
 4use ark_relations::r1cs::SynthesisError;
 5use core::marker::PhantomData;
 6
 7use super::ConstraintF;
 8
 9/// ECRLC implements gadget that checks the Elliptic Curve points RandomLinearCombination described
10/// in CycleFold (https://eprint.iacr.org/2023/1192.pdf).
11#[derive(Debug)]
12pub struct ECRLC<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>> {
13    _c: PhantomData<C>,
14    _gc: PhantomData<GC>,
15}
16impl<C: CurveGroup, GC: CurveVar<C, ConstraintF<C>>> ECRLC<C, GC> {
17    pub fn check(
18        r: NonNativeFieldVar<C::ScalarField, ConstraintF<C>>,
19        p1: GC,
20        p2: GC,
21        p3: GC,
22    ) -> Result<(), SynthesisError> {
23        p3.enforce_equal(&(p1 + p2.scalar_mul_le(r.to_bits_le()?.iter())?))?;
24        Ok(())
25    }
26}
27
28#[cfg(test)]
29mod test {
30    use super::*;
31    use ark_bls12_377::{constraints::G1Var, Fq, Fr, G1Projective};
32    use ark_r1cs_std::alloc::AllocVar;
33    use ark_relations::r1cs::ConstraintSystem;
34    use ark_std::UniformRand;
35    use std::ops::Mul;
36
37    /// Let Curve1=bls12-377::G1 and Curve2=bw6-761::G1. Here we have our constraint system will
38    /// work over Curve2::Fr = bw6-761::Fr (=bls12-377::Fq), thus our points are P_i \in Curve1
39    /// (=bls12-377).
40    #[test]
41    fn test_ecrlc_check() {
42        let mut rng = ark_std::test_rng();
43
44        let r = Fr::rand(&mut rng);
45        let p1 = G1Projective::rand(&mut rng);
46        let p2 = G1Projective::rand(&mut rng);
47        let p3 = p1 + p2.mul(r);
48
49        let cs = ConstraintSystem::<Fq>::new_ref(); // CS over Curve2::Fr = Curve1::Fq
50
51        // prepare circuit inputs
52        let rVar = NonNativeFieldVar::<Fr, Fq>::new_witness(cs.clone(), || Ok(r)).unwrap();
53        let p1Var = G1Var::new_witness(cs.clone(), || Ok(p1)).unwrap();
54        let p2Var = G1Var::new_witness(cs.clone(), || Ok(p2)).unwrap();
55        let p3Var = G1Var::new_witness(cs.clone(), || Ok(p3)).unwrap();
56
57        // check ECRLC circuit
58        ECRLC::<G1Projective, G1Var>::check(rVar, p1Var, p2Var, p3Var).unwrap();
59        assert!(cs.is_satisfied().unwrap());
60        // dbg!(cs.num_constraints());
61    }
62}