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}