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::{boolean::Boolean, prelude::CurveVar};
 4use ark_relations::r1cs::SynthesisError;
 5use core::marker::PhantomData;
 6
 7use super::CF;
 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, CF<C>>> {
13    _c: PhantomData<C>,
14    _gc: PhantomData<GC>,
15}
16impl<C: CurveGroup, GC: CurveVar<C, CF<C>>> ECRLC<C, GC> {
17    pub fn check(
18        // get r in bits format, so it can be reused across many instances of ECRLC gadget,
19        // reducing the number of constraints needed
20        r_bits: Vec<Boolean<CF<C>>>,
21        p1: GC,
22        p2: GC,
23        p3: GC,
24    ) -> Result<Boolean<CF<C>>, SynthesisError> {
25        p3.is_eq(&(p1 + p2.scalar_mul_le(r_bits.iter())?))
26    }
27}
28
29#[cfg(test)]
30mod tests {
31    use super::*;
32    use ark_ff::{BigInteger, PrimeField};
33    use ark_pallas::{constraints::GVar, Fq, Fr, Projective};
34    use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget};
35    use ark_relations::r1cs::ConstraintSystem;
36    use ark_std::UniformRand;
37    use std::ops::Mul;
38
39    /// Let Curve1=pallas and Curve2=vesta. Here our constraints system will work over Curve2::Fr =
40    /// vesta::Fr (=pallas::Fq), thus our points are P_i \in Curve1 (=pasta).
41    #[test]
42    fn test_ecrlc_check() {
43        let mut rng = ark_std::test_rng();
44
45        let r = Fr::rand(&mut rng);
46        let p1 = Projective::rand(&mut rng);
47        let p2 = Projective::rand(&mut rng);
48        let p3 = p1 + p2.mul(r);
49
50        let cs = ConstraintSystem::<Fq>::new_ref(); // CS over Curve2::Fr = Curve1::Fq
51
52        // prepare circuit inputs
53        let rbitsVar: Vec<Boolean<Fq>> =
54            Vec::new_witness(cs.clone(), || Ok(r.into_bigint().to_bits_le())).unwrap();
55
56        let p1Var = GVar::new_witness(cs.clone(), || Ok(p1)).unwrap();
57        let p2Var = GVar::new_witness(cs.clone(), || Ok(p2)).unwrap();
58        let p3Var = GVar::new_witness(cs.clone(), || Ok(p3)).unwrap();
59
60        // check ECRLC circuit
61        let check_pass = ECRLC::<Projective, GVar>::check(rbitsVar, p1Var, p2Var, p3Var).unwrap();
62        check_pass.enforce_equal(&Boolean::<Fq>::TRUE).unwrap();
63        assert!(cs.is_satisfied().unwrap());
64    }
65}