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}