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