arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/r1cs-std/src/pairing/mod.rs
r1cs-std/src/pairing/mod.rsRaw
  1use crate::prelude::*;
  2use algebra::{Field, PairingEngine};
  3use core::fmt::Debug;
  4use r1cs_core::SynthesisError;
  5
  6pub mod bls12;
  7pub mod mnt4;
  8pub mod mnt6;
  9
 10pub trait PairingVar<E: PairingEngine, ConstraintF: Field = <E as PairingEngine>::Fq> {
 11    type G1Var: CurveVar<E::G1Projective, ConstraintF>
 12        + AllocVar<E::G1Projective, ConstraintF>
 13        + AllocVar<E::G1Affine, ConstraintF>;
 14    type G2Var: CurveVar<E::G2Projective, ConstraintF>
 15        + AllocVar<E::G2Projective, ConstraintF>
 16        + AllocVar<E::G2Affine, ConstraintF>;
 17
 18    type GTVar: FieldVar<E::Fqk, ConstraintF>;
 19
 20    type G1PreparedVar: ToBytesGadget<ConstraintF>
 21        + AllocVar<E::G1Prepared, ConstraintF>
 22        + Clone
 23        + Debug;
 24    type G2PreparedVar: ToBytesGadget<ConstraintF>
 25        + AllocVar<E::G2Prepared, ConstraintF>
 26        + Clone
 27        + Debug;
 28
 29    fn miller_loop(
 30        p: &[Self::G1PreparedVar],
 31        q: &[Self::G2PreparedVar],
 32    ) -> Result<Self::GTVar, SynthesisError>;
 33
 34    fn final_exponentiation(p: &Self::GTVar) -> Result<Self::GTVar, SynthesisError>;
 35
 36    #[tracing::instrument(target = "r1cs")]
 37    fn pairing(
 38        p: Self::G1PreparedVar,
 39        q: Self::G2PreparedVar,
 40    ) -> Result<Self::GTVar, SynthesisError> {
 41        let tmp = Self::miller_loop(&[p], &[q])?;
 42        Self::final_exponentiation(&tmp)
 43    }
 44
 45    /// Computes a product of pairings.
 46    #[must_use]
 47    #[tracing::instrument(target = "r1cs")]
 48    fn product_of_pairings(
 49        p: &[Self::G1PreparedVar],
 50        q: &[Self::G2PreparedVar],
 51    ) -> Result<Self::GTVar, SynthesisError> {
 52        let miller_result = Self::miller_loop(p, q)?;
 53        Self::final_exponentiation(&miller_result)
 54    }
 55
 56    fn prepare_g1(q: &Self::G1Var) -> Result<Self::G1PreparedVar, SynthesisError>;
 57
 58    fn prepare_g2(q: &Self::G2Var) -> Result<Self::G2PreparedVar, SynthesisError>;
 59}
 60
 61#[cfg(test)]
 62pub(crate) mod tests {
 63    use crate::{prelude::*, Vec};
 64    use algebra::{
 65        test_rng, BitIteratorLE, Field, PairingEngine, PrimeField, ProjectiveCurve, UniformRand,
 66    };
 67    use r1cs_core::{ConstraintSystem, SynthesisError};
 68
 69    #[allow(dead_code)]
 70    pub(crate) fn bilinearity_test<E: PairingEngine, P: PairingVar<E>>(
 71    ) -> Result<(), SynthesisError>
 72    where
 73        for<'a> &'a P::G1Var: GroupOpsBounds<'a, E::G1Projective, P::G1Var>,
 74        for<'a> &'a P::G2Var: GroupOpsBounds<'a, E::G2Projective, P::G2Var>,
 75        for<'a> &'a P::GTVar: FieldOpsBounds<'a, E::Fqk, P::GTVar>,
 76    {
 77        let cs = ConstraintSystem::<E::Fq>::new_ref();
 78
 79        let mut rng = test_rng();
 80        let a = E::G1Projective::rand(&mut rng);
 81        let b = E::G2Projective::rand(&mut rng);
 82        let s = E::Fr::rand(&mut rng);
 83
 84        let mut sa = a;
 85        sa *= s;
 86        let mut sb = b;
 87        sb *= s;
 88
 89        let a_g = P::G1Var::new_witness(cs.clone(), || Ok(a.into_affine()))?;
 90        let b_g = P::G2Var::new_witness(cs.clone(), || Ok(b.into_affine()))?;
 91        let sa_g = P::G1Var::new_witness(cs.clone(), || Ok(sa.into_affine()))?;
 92        let sb_g = P::G2Var::new_witness(cs.clone(), || Ok(sb.into_affine()))?;
 93
 94        let mut preparation_num_constraints = cs.num_constraints();
 95        let a_prep_g = P::prepare_g1(&a_g)?;
 96        let b_prep_g = P::prepare_g2(&b_g)?;
 97        preparation_num_constraints = cs.num_constraints() - preparation_num_constraints;
 98        println!(
 99            "Preparation num constraints: {}",
100            preparation_num_constraints
101        );
102
103        let sa_prep_g = P::prepare_g1(&sa_g)?;
104        let sb_prep_g = P::prepare_g2(&sb_g)?;
105
106        let (ans1_g, ans1_n) = {
107            let ml_constraints = cs.num_constraints();
108            let ml_g = P::miller_loop(&[sa_prep_g], &[b_prep_g.clone()])?;
109            println!(
110                "ML num constraints: {}",
111                cs.num_constraints() - ml_constraints
112            );
113            let fe_constraints = cs.num_constraints();
114            let ans_g = P::final_exponentiation(&ml_g)?;
115            println!(
116                "FE num constraints: {}",
117                cs.num_constraints() - fe_constraints
118            );
119            let ans_n = E::pairing(sa, b);
120            (ans_g, ans_n)
121        };
122
123        let (ans2_g, ans2_n) = {
124            let ans_g = P::pairing(a_prep_g.clone(), sb_prep_g)?;
125            let ans_n = E::pairing(a, sb);
126            (ans_g, ans_n)
127        };
128
129        let (ans3_g, ans3_n) = {
130            let s_iter = BitIteratorLE::without_trailing_zeros(s.into_repr())
131                .map(Boolean::constant)
132                .collect::<Vec<_>>();
133
134            let mut ans_g = P::pairing(a_prep_g, b_prep_g)?;
135            let mut ans_n = E::pairing(a, b);
136            ans_n = ans_n.pow(s.into_repr());
137            ans_g = ans_g.pow_le(&s_iter)?;
138
139            (ans_g, ans_n)
140        };
141
142        ans1_g.enforce_equal(&ans2_g)?;
143        ans2_g.enforce_equal(&ans3_g)?;
144
145        assert_eq!(ans1_g.value()?, ans1_n, "Failed native test 1");
146        assert_eq!(ans2_g.value()?, ans2_n, "Failed native test 2");
147        assert_eq!(ans3_g.value()?, ans3_n, "Failed native test 3");
148
149        assert_eq!(ans1_n, ans2_n, "Failed ans1_native == ans2_native");
150        assert_eq!(ans2_n, ans3_n, "Failed ans2_native == ans3_native");
151        assert_eq!(ans1_g.value()?, ans3_g.value()?, "Failed ans1 == ans3");
152        assert_eq!(ans1_g.value()?, ans2_g.value()?, "Failed ans1 == ans2");
153        assert_eq!(ans2_g.value()?, ans3_g.value()?, "Failed ans2 == ans3");
154
155        if !cs.is_satisfied().unwrap() {
156            println!("Unsatisfied: {:?}", cs.which_is_unsatisfied());
157        }
158
159        assert!(cs.is_satisfied().unwrap(), "cs is not satisfied");
160        Ok(())
161    }
162}