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    fn pairing(
 37        p: Self::G1PreparedVar,
 38        q: Self::G2PreparedVar,
 39    ) -> Result<Self::GTVar, SynthesisError> {
 40        let tmp = Self::miller_loop(&[p], &[q])?;
 41        Self::final_exponentiation(&tmp)
 42    }
 43
 44    /// Computes a product of pairings.
 45    #[must_use]
 46    fn product_of_pairings(
 47        p: &[Self::G1PreparedVar],
 48        q: &[Self::G2PreparedVar],
 49    ) -> Result<Self::GTVar, SynthesisError> {
 50        let miller_result = Self::miller_loop(p, q)?;
 51        Self::final_exponentiation(&miller_result)
 52    }
 53
 54    fn prepare_g1(q: &Self::G1Var) -> Result<Self::G1PreparedVar, SynthesisError>;
 55
 56    fn prepare_g2(q: &Self::G2Var) -> Result<Self::G2PreparedVar, SynthesisError>;
 57}
 58
 59#[cfg(test)]
 60pub(crate) mod tests {
 61    use crate::{prelude::*, Vec};
 62    use algebra::{
 63        test_rng, BitIterator, Field, PairingEngine, PrimeField, ProjectiveCurve, UniformRand,
 64    };
 65    use r1cs_core::{ConstraintSystem, SynthesisError};
 66
 67    #[allow(dead_code)]
 68    pub(crate) fn bilinearity_test<E: PairingEngine, P: PairingVar<E>>(
 69    ) -> Result<(), SynthesisError>
 70    where
 71        for<'a> &'a P::G1Var: GroupOpsBounds<'a, E::G1Projective, P::G1Var>,
 72        for<'a> &'a P::G2Var: GroupOpsBounds<'a, E::G2Projective, P::G2Var>,
 73        for<'a> &'a P::GTVar: FieldOpsBounds<'a, E::Fqk, P::GTVar>,
 74    {
 75        let cs = ConstraintSystem::<E::Fq>::new_ref();
 76
 77        let mut rng = test_rng();
 78        let a = E::G1Projective::rand(&mut rng);
 79        let b = E::G2Projective::rand(&mut rng);
 80        let s = E::Fr::rand(&mut rng);
 81
 82        let mut sa = a;
 83        sa *= s;
 84        let mut sb = b;
 85        sb *= s;
 86
 87        let a_g = P::G1Var::new_witness(cs.ns("a"), || Ok(a.into_affine()))?;
 88        let b_g = P::G2Var::new_witness(cs.ns("b"), || Ok(b.into_affine()))?;
 89        let sa_g = P::G1Var::new_witness(cs.ns("sa"), || Ok(sa.into_affine()))?;
 90        let sb_g = P::G2Var::new_witness(cs.ns("sb"), || Ok(sb.into_affine()))?;
 91
 92        let mut preparation_num_constraints = cs.num_constraints();
 93        let a_prep_g = P::prepare_g1(&a_g)?;
 94        let b_prep_g = P::prepare_g2(&b_g)?;
 95        preparation_num_constraints = cs.num_constraints() - preparation_num_constraints;
 96        println!(
 97            "Preparation num constraints: {}",
 98            preparation_num_constraints
 99        );
100
101        let sa_prep_g = P::prepare_g1(&sa_g)?;
102        let sb_prep_g = P::prepare_g2(&sb_g)?;
103
104        let (ans1_g, ans1_n) = {
105            let ml_constraints = cs.num_constraints();
106            let ml_g = P::miller_loop(&[sa_prep_g], &[b_prep_g.clone()])?;
107            println!(
108                "ML num constraints: {}",
109                cs.num_constraints() - ml_constraints
110            );
111            let fe_constraints = cs.num_constraints();
112            let ans_g = P::final_exponentiation(&ml_g)?;
113            println!(
114                "FE num constraints: {}",
115                cs.num_constraints() - fe_constraints
116            );
117            let ans_n = E::pairing(sa, b);
118            (ans_g, ans_n)
119        };
120
121        let (ans2_g, ans2_n) = {
122            let ans_g = P::pairing(a_prep_g.clone(), sb_prep_g)?;
123            let ans_n = E::pairing(a, sb);
124            (ans_g, ans_n)
125        };
126
127        let (ans3_g, ans3_n) = {
128            let s_iter = BitIterator::new(s.into_repr())
129                .map(Boolean::constant)
130                .collect::<Vec<_>>();
131
132            let mut ans_g = P::pairing(a_prep_g, b_prep_g)?;
133            let mut ans_n = E::pairing(a, b);
134            ans_n = ans_n.pow(s.into_repr());
135            ans_g = ans_g.pow(&s_iter)?;
136
137            (ans_g, ans_n)
138        };
139
140        ans1_g.enforce_equal(&ans2_g)?;
141        ans2_g.enforce_equal(&ans3_g)?;
142
143        assert_eq!(ans1_g.value()?, ans1_n, "Failed native test 1");
144        assert_eq!(ans2_g.value()?, ans2_n, "Failed native test 2");
145        assert_eq!(ans3_g.value()?, ans3_n, "Failed native test 3");
146
147        assert_eq!(ans1_n, ans2_n, "Failed ans1_native == ans2_native");
148        assert_eq!(ans2_n, ans3_n, "Failed ans2_native == ans3_native");
149        assert_eq!(ans1_g.value()?, ans3_g.value()?, "Failed ans1 == ans3");
150        assert_eq!(ans1_g.value()?, ans2_g.value()?, "Failed ans1 == ans2");
151        assert_eq!(ans2_g.value()?, ans3_g.value()?, "Failed ans2 == ans3");
152
153        if !cs.is_satisfied().unwrap() {
154            println!("Unsatisfied: {:?}", cs.which_is_unsatisfied());
155        }
156
157        assert!(cs.is_satisfied().unwrap(), "cs is not satisfied");
158        Ok(())
159    }
160}