1use ark_ff::{AdditiveGroup, CyclotomicMultSubgroup, Field, One, PrimeField};
2use ark_serialize::{
3 CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate,
4};
5use ark_std::{
6 borrow::Borrow,
7 fmt::{Debug, Display, Formatter, Result as FmtResult},
8 io::{Read, Write},
9 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
10 rand::{
11 distributions::{Distribution, Standard},
12 Rng,
13 },
14 vec::*,
15 UniformRand, Zero,
16};
17use derivative::Derivative;
18use zeroize::Zeroize;
19
20use crate::{AffineRepr, CurveGroup, PrimeGroup, VariableBaseMSM};
21
22pub trait Pairing: Sized + 'static + Copy + Debug + Sync + Send + Eq {
25 type BaseField: PrimeField;
27
28 type ScalarField: PrimeField;
30
31 type G1: CurveGroup<ScalarField = Self::ScalarField, Affine = Self::G1Affine>
33 + From<Self::G1Affine>
34 + Into<Self::G1Affine>
35 + MulAssign<Self::ScalarField>;
37
38 type G1Affine: AffineRepr<Group = Self::G1, ScalarField = Self::ScalarField>
39 + From<Self::G1>
40 + Into<Self::G1>
41 + Into<Self::G1Prepared>;
42
43 type G1Prepared: Default
45 + Clone
46 + Send
47 + Sync
48 + Debug
49 + CanonicalSerialize
50 + CanonicalDeserialize
51 + for<'a> From<&'a Self::G1>
52 + for<'a> From<&'a Self::G1Affine>
53 + From<Self::G1>
54 + From<Self::G1Affine>;
55
56 type G2: CurveGroup<ScalarField = Self::ScalarField, Affine = Self::G2Affine>
58 + From<Self::G2Affine>
59 + Into<Self::G2Affine>
60 + MulAssign<Self::ScalarField>;
62
63 type G2Affine: AffineRepr<Group = Self::G2, ScalarField = Self::ScalarField>
65 + From<Self::G2>
66 + Into<Self::G2>
67 + Into<Self::G2Prepared>;
68
69 type G2Prepared: Default
71 + Clone
72 + Send
73 + Sync
74 + Debug
75 + CanonicalSerialize
76 + CanonicalDeserialize
77 + for<'a> From<&'a Self::G2>
78 + for<'a> From<&'a Self::G2Affine>
79 + From<Self::G2>
80 + From<Self::G2Affine>;
81
82 type TargetField: CyclotomicMultSubgroup;
84
85 fn multi_miller_loop(
87 a: impl IntoIterator<Item = impl Into<Self::G1Prepared>>,
88 b: impl IntoIterator<Item = impl Into<Self::G2Prepared>>,
89 ) -> MillerLoopOutput<Self>;
90
91 fn miller_loop(
93 a: impl Into<Self::G1Prepared>,
94 b: impl Into<Self::G2Prepared>,
95 ) -> MillerLoopOutput<Self> {
96 Self::multi_miller_loop([a], [b])
97 }
98
99 #[must_use]
101 fn final_exponentiation(mlo: MillerLoopOutput<Self>) -> Option<PairingOutput<Self>>;
102
103 fn multi_pairing(
105 a: impl IntoIterator<Item = impl Into<Self::G1Prepared>>,
106 b: impl IntoIterator<Item = impl Into<Self::G2Prepared>>,
107 ) -> PairingOutput<Self> {
108 Self::final_exponentiation(Self::multi_miller_loop(a, b)).unwrap()
109 }
110
111 fn pairing(
113 p: impl Into<Self::G1Prepared>,
114 q: impl Into<Self::G2Prepared>,
115 ) -> PairingOutput<Self> {
116 Self::multi_pairing([p], [q])
117 }
118}
119
120#[derive(Derivative)]
123#[derivative(
124 Copy(bound = "P: Pairing"),
125 Clone(bound = "P: Pairing"),
126 Debug(bound = "P: Pairing"),
127 PartialEq(bound = "P: Pairing"),
128 Eq(bound = "P: Pairing"),
129 PartialOrd(bound = "P: Pairing"),
130 Ord(bound = "P: Pairing"),
131 Hash(bound = "P: Pairing")
132)]
133#[must_use]
134pub struct PairingOutput<P: Pairing>(pub P::TargetField);
135
136impl<P: Pairing> Default for PairingOutput<P> {
137 fn default() -> Self {
138 Self::ZERO
140 }
141}
142
143impl<P: Pairing> CanonicalSerialize for PairingOutput<P> {
144 #[allow(unused_qualifications)]
145 #[inline]
146 fn serialize_with_mode<W: Write>(
147 &self,
148 writer: W,
149 compress: Compress,
150 ) -> Result<(), SerializationError> {
151 self.0.serialize_with_mode(writer, compress)
152 }
153
154 #[inline]
155 fn serialized_size(&self, compress: Compress) -> usize {
156 self.0.serialized_size(compress)
157 }
158}
159
160impl<P: Pairing> Valid for PairingOutput<P> {
161 fn check(&self) -> Result<(), SerializationError> {
162 if self.0.pow(P::ScalarField::characteristic()).is_one() {
163 Ok(())
164 } else {
165 Err(SerializationError::InvalidData)
166 }
167 }
168}
169
170impl<P: Pairing> CanonicalDeserialize for PairingOutput<P> {
171 fn deserialize_with_mode<R: Read>(
172 reader: R,
173 compress: Compress,
174 validate: Validate,
175 ) -> Result<Self, SerializationError> {
176 let f = P::TargetField::deserialize_with_mode(reader, compress, validate).map(Self)?;
177 if let Validate::Yes = validate {
178 f.check()?;
179 }
180 Ok(f)
181 }
182}
183
184impl<P: Pairing> Display for PairingOutput<P> {
185 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
186 write!(f, "{}", self.0)
187 }
188}
189
190impl<P: Pairing> Zero for PairingOutput<P> {
191 fn zero() -> Self {
193 Self(P::TargetField::one())
194 }
195
196 fn is_zero(&self) -> bool {
197 self.0.is_one()
198 }
199}
200
201impl<'a, P: Pairing> Add<&'a Self> for PairingOutput<P> {
202 type Output = Self;
203
204 #[inline]
205 fn add(mut self, other: &'a Self) -> Self {
206 self += other;
207 self
208 }
209}
210
211impl<'a, P: Pairing> AddAssign<&'a Self> for PairingOutput<P> {
212 fn add_assign(&mut self, other: &'a Self) {
213 self.0 *= other.0;
214 }
215}
216
217impl<'a, P: Pairing> SubAssign<&'a Self> for PairingOutput<P> {
218 fn sub_assign(&mut self, other: &'a Self) {
219 self.0 *= other.0.cyclotomic_inverse().unwrap();
220 }
221}
222
223impl<'a, P: Pairing> Sub<&'a Self> for PairingOutput<P> {
224 type Output = Self;
225
226 #[inline]
227 fn sub(mut self, other: &'a Self) -> Self {
228 self -= other;
229 self
230 }
231}
232
233ark_ff::impl_additive_ops_from_ref!(PairingOutput, Pairing);
234
235impl<P: Pairing, T: Borrow<P::ScalarField>> MulAssign<T> for PairingOutput<P> {
236 fn mul_assign(&mut self, other: T) {
237 *self = self.mul_bigint(other.borrow().into_bigint());
238 }
239}
240
241impl<P: Pairing, T: Borrow<P::ScalarField>> Mul<T> for PairingOutput<P> {
242 type Output = Self;
243
244 fn mul(self, other: T) -> Self {
245 self.mul_bigint(other.borrow().into_bigint())
246 }
247}
248
249impl<P: Pairing> Zeroize for PairingOutput<P> {
250 fn zeroize(&mut self) {
251 self.0.zeroize()
252 }
253}
254
255impl<P: Pairing> Neg for PairingOutput<P> {
256 type Output = Self;
257
258 #[inline]
259 fn neg(self) -> Self {
260 Self(self.0.cyclotomic_inverse().unwrap())
261 }
262}
263
264impl<P: Pairing> Distribution<PairingOutput<P>> for Standard {
265 #[inline]
266 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> PairingOutput<P> {
267 let g1 = P::G1::rand(rng);
269 let g2 = P::G2::rand(rng);
271 P::pairing(g1, g2)
272 }
273}
274
275impl<P: Pairing> AdditiveGroup for PairingOutput<P> {
276 type Scalar = P::ScalarField;
277
278 const ZERO: Self = Self(P::TargetField::ONE);
279
280 fn double_in_place(&mut self) -> &mut Self {
281 self.0.cyclotomic_square_in_place();
282 self
283 }
284}
285
286impl<P: Pairing> PrimeGroup for PairingOutput<P> {
287 type ScalarField = P::ScalarField;
288
289 fn generator() -> Self {
290 let g1 = P::G1::generator();
293 let g2 = P::G2::generator();
295 P::pairing(g1.into(), g2.into())
296 }
297
298 fn mul_bigint(&self, other: impl AsRef<[u64]>) -> Self {
299 Self(self.0.cyclotomic_exp(other.as_ref()))
300 }
301
302 fn mul_bits_be(&self, other: impl Iterator<Item = bool>) -> Self {
303 let other = other
305 .collect::<Vec<_>>()
306 .chunks(64)
307 .map(|chunk| {
308 chunk
309 .iter()
310 .enumerate()
311 .fold(0, |r, (i, bit)| r | u64::from(*bit) << i)
312 })
313 .collect::<Vec<_>>();
314 Self(self.0.cyclotomic_exp(&other))
315 }
316}
317
318impl<P: Pairing> crate::ScalarMul for PairingOutput<P> {
319 type MulBase = Self;
320 const NEGATION_IS_CHEAP: bool = P::TargetField::INVERSE_IS_FAST;
321
322 fn batch_convert_to_mul_base(bases: &[Self]) -> Vec<Self::MulBase> {
323 bases.to_vec()
324 }
325}
326
327impl<P: Pairing> VariableBaseMSM for PairingOutput<P> {}
328
329#[derive(Derivative)]
331#[derivative(
332 Copy(bound = "P: Pairing"),
333 Clone(bound = "P: Pairing"),
334 Debug(bound = "P: Pairing"),
335 PartialEq(bound = "P: Pairing"),
336 Eq(bound = "P: Pairing"),
337 PartialOrd(bound = "P: Pairing"),
338 Ord(bound = "P: Pairing")
339)]
340#[must_use]
341pub struct MillerLoopOutput<P: Pairing>(pub P::TargetField);
342
343impl<P: Pairing> Mul<P::ScalarField> for MillerLoopOutput<P> {
344 type Output = Self;
345
346 fn mul(self, other: P::ScalarField) -> Self {
347 Self(self.0.pow(other.into_bigint()))
348 }
349}
350
351pub fn prepare_g1<E: Pairing>(g: impl Into<E::G1Affine>) -> E::G1Prepared {
353 let g: E::G1Affine = g.into();
354 E::G1Prepared::from(g)
355}
356
357pub fn prepare_g2<E: Pairing>(g: impl Into<E::G2Affine>) -> E::G2Prepared {
359 let g: E::G2Affine = g.into();
360 E::G2Prepared::from(g)
361}