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::{ConstraintSystem, SynthesisError};
  5
  6pub mod bls12;
  7pub mod mnt4;
  8pub mod mnt6;
  9
 10pub trait PairingGadget<PairingE: PairingEngine, ConstraintF: Field> {
 11    type G1Gadget: GroupGadget<PairingE::G1Projective, ConstraintF>;
 12    type G2Gadget: GroupGadget<PairingE::G2Projective, ConstraintF>;
 13    type G1PreparedGadget: AllocGadget<PairingE::G1Prepared, ConstraintF>
 14        + ToBytesGadget<ConstraintF>
 15        + Clone
 16        + Debug;
 17    type G2PreparedGadget: AllocGadget<PairingE::G2Prepared, ConstraintF>
 18        + ToBytesGadget<ConstraintF>
 19        + Clone
 20        + Debug;
 21    type GTGadget: FieldGadget<PairingE::Fqk, ConstraintF> + Clone;
 22
 23    fn miller_loop<CS: ConstraintSystem<ConstraintF>>(
 24        cs: CS,
 25        p: &[Self::G1PreparedGadget],
 26        q: &[Self::G2PreparedGadget],
 27    ) -> Result<Self::GTGadget, SynthesisError>;
 28
 29    fn final_exponentiation<CS: ConstraintSystem<ConstraintF>>(
 30        cs: CS,
 31        p: &Self::GTGadget,
 32    ) -> Result<Self::GTGadget, SynthesisError>;
 33
 34    fn pairing<CS: ConstraintSystem<ConstraintF>>(
 35        mut cs: CS,
 36        p: Self::G1PreparedGadget,
 37        q: Self::G2PreparedGadget,
 38    ) -> Result<Self::GTGadget, SynthesisError> {
 39        let tmp = Self::miller_loop(cs.ns(|| "miller loop"), &[p], &[q])?;
 40        Self::final_exponentiation(cs.ns(|| "final_exp"), &tmp)
 41    }
 42
 43    /// Computes a product of pairings.
 44    #[must_use]
 45    fn product_of_pairings<CS: ConstraintSystem<ConstraintF>>(
 46        mut cs: CS,
 47        p: &[Self::G1PreparedGadget],
 48        q: &[Self::G2PreparedGadget],
 49    ) -> Result<Self::GTGadget, SynthesisError> {
 50        let miller_result = Self::miller_loop(&mut cs.ns(|| "Miller loop"), p, q)?;
 51        Self::final_exponentiation(&mut cs.ns(|| "Final Exp"), &miller_result)
 52    }
 53
 54    fn prepare_g1<CS: ConstraintSystem<ConstraintF>>(
 55        cs: CS,
 56        q: &Self::G1Gadget,
 57    ) -> Result<Self::G1PreparedGadget, SynthesisError>;
 58
 59    fn prepare_g2<CS: ConstraintSystem<ConstraintF>>(
 60        cs: CS,
 61        q: &Self::G2Gadget,
 62    ) -> Result<Self::G2PreparedGadget, SynthesisError>;
 63}
 64
 65#[cfg(test)]
 66pub(crate) mod tests {
 67    use crate::{
 68        bits::boolean::Boolean, prelude::*, test_constraint_system::TestConstraintSystem, Vec,
 69    };
 70    use algebra::{test_rng, BitIterator, Field, PairingEngine, PrimeField, UniformRand};
 71    use r1cs_core::ConstraintSystem;
 72
 73    #[allow(dead_code)]
 74    pub(crate) fn bilinearity_test<
 75        E: PairingEngine,
 76        ConstraintF: Field,
 77        P: PairingGadget<E, ConstraintF>,
 78    >() {
 79        let mut cs = TestConstraintSystem::<ConstraintF>::new();
 80
 81        let mut rng = test_rng();
 82        let a = E::G1Projective::rand(&mut rng);
 83        let b = E::G2Projective::rand(&mut rng);
 84        let s = E::Fr::rand(&mut rng);
 85
 86        let mut sa = a;
 87        sa *= s;
 88        let mut sb = b;
 89        sb *= s;
 90
 91        let a_g = P::G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
 92        let b_g = P::G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
 93        let sa_g = P::G1Gadget::alloc(&mut cs.ns(|| "sa"), || Ok(sa)).unwrap();
 94        let sb_g = P::G2Gadget::alloc(&mut cs.ns(|| "sb"), || Ok(sb)).unwrap();
 95
 96        let a_prep_g = P::prepare_g1(&mut cs.ns(|| "a_prep"), &a_g).unwrap();
 97        let b_prep_g = P::prepare_g2(&mut cs.ns(|| "b_prep"), &b_g).unwrap();
 98
 99        let sa_prep_g = P::prepare_g1(&mut cs.ns(|| "sa_prep"), &sa_g).unwrap();
100        let sb_prep_g = P::prepare_g2(&mut cs.ns(|| "sb_prep"), &sb_g).unwrap();
101
102        let (ans1_g, ans1_n) = {
103            let ans_g = P::pairing(cs.ns(|| "pair(sa, b)"), sa_prep_g, b_prep_g.clone()).unwrap();
104            let ans_n = E::pairing(sa, b);
105            (ans_g, ans_n)
106        };
107
108        let (ans2_g, ans2_n) = {
109            let ans_g = P::pairing(cs.ns(|| "pair(a, sb)"), a_prep_g.clone(), sb_prep_g).unwrap();
110            let ans_n = E::pairing(a, sb);
111            (ans_g, ans_n)
112        };
113
114        let (ans3_g, ans3_n) = {
115            let s_iter = BitIterator::new(s.into_repr())
116                .map(Boolean::constant)
117                .collect::<Vec<_>>();
118
119            let mut ans_g = P::pairing(cs.ns(|| "pair(a, b)"), a_prep_g, b_prep_g).unwrap();
120            let mut ans_n = E::pairing(a, b);
121            ans_n = ans_n.pow(s.into_repr());
122            ans_g = ans_g.pow(cs.ns(|| "pow"), &s_iter).unwrap();
123
124            (ans_g, ans_n)
125        };
126
127        assert_eq!(ans1_n, ans2_n, "Failed ans1_native == ans2_native");
128        assert_eq!(ans2_n, ans3_n, "Failed ans2_native == ans3_native");
129        assert_eq!(
130            ans1_g.get_value(),
131            ans3_g.get_value(),
132            "Failed ans1 == ans3"
133        );
134        assert_eq!(
135            ans1_g.get_value(),
136            ans2_g.get_value(),
137            "Failed ans1 == ans2"
138        );
139        assert_eq!(
140            ans2_g.get_value(),
141            ans3_g.get_value(),
142            "Failed ans2 == ans3"
143        );
144
145        ans1_g
146            .enforce_equal(&mut cs.ns(|| "ans1 == ans2?"), &ans2_g)
147            .unwrap();
148        ans2_g
149            .enforce_equal(&mut cs.ns(|| "ans2 == ans3?"), &ans3_g)
150            .unwrap();
151
152        assert_eq!(ans1_g.get_value().unwrap(), ans1_n, "Failed native test 1");
153        assert_eq!(ans2_g.get_value().unwrap(), ans2_n, "Failed native test 2");
154        assert_eq!(ans3_g.get_value().unwrap(), ans3_n, "Failed native test 3");
155
156        if !cs.is_satisfied() {
157            println!("Unsatisfied: {:?}", cs.which_is_unsatisfied());
158        }
159
160        assert!(cs.is_satisfied(), "cs is not satisfied");
161    }
162}