Skip to main content

zksync_pairing/
lib.rs

1#![allow(clippy::too_many_arguments, clippy::needless_borrows_for_generic_args)]
2// Force public structures to implement Debug
3#![deny(missing_debug_implementations)]
4// Asm is only available on nightly, with this unstable feature
5#![cfg_attr(feature = "asm", feature(asm_const))]
6
7extern crate byteorder;
8extern crate rand as rand_crate;
9
10#[cfg(test)]
11pub mod tests;
12
13pub extern crate ff;
14
15pub use ff::*;
16
17pub mod bls12_381;
18pub mod bn256;
19pub mod compact_bn256;
20
21mod wnaf;
22pub use self::wnaf::Wnaf;
23
24mod base;
25pub use self::base::*;
26
27use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, ScalarEngine, SqrtField};
28use std::error::Error;
29use std::fmt;
30
31pub mod rand {
32    pub use crate::ff::rand::Rng;
33    pub use crate::ff::Rand;
34    pub use crate::rand_crate::{distributions, random, rngs, seq, thread_rng, RngCore, SeedableRng};
35
36    #[derive(Clone, Debug)]
37    pub struct XorShiftRng(pub rand_xorshift::XorShiftRng);
38
39    impl XorShiftRng {
40        pub fn from_seed(seed: [u32; 4]) -> Self {
41            let mut seed_bytes = [0u8; 16];
42            for (chunk, word) in seed_bytes.chunks_exact_mut(4).zip(seed.iter()) {
43                chunk.copy_from_slice(&word.to_le_bytes());
44            }
45
46            <Self as SeedableRng>::from_seed(seed_bytes)
47        }
48    }
49
50    impl RngCore for XorShiftRng {
51        fn next_u32(&mut self) -> u32 {
52            self.0.next_u32()
53        }
54
55        fn next_u64(&mut self) -> u64 {
56            self.0.next_u64()
57        }
58
59        fn fill_bytes(&mut self, dest: &mut [u8]) {
60            self.0.fill_bytes(dest)
61        }
62
63        fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), crate::rand_crate::Error> {
64            self.0.try_fill_bytes(dest)
65        }
66    }
67
68    impl SeedableRng for XorShiftRng {
69        type Seed = <rand_xorshift::XorShiftRng as SeedableRng>::Seed;
70
71        fn from_seed(seed: Self::Seed) -> Self {
72            Self(rand_xorshift::XorShiftRng::from_seed(seed))
73        }
74    }
75}
76
77/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
78/// with well-defined relationships. In particular, the G1/G2 curve groups are
79/// of prime order `r`, and are equipped with a bilinear pairing function.
80pub trait Engine: ScalarEngine {
81    /// The projective representation of an element in G1.
82    type G1: CurveProjective<Engine = Self, Base = Self::Fq, Scalar = Self::Fr, Affine = Self::G1Affine> + From<Self::G1Affine>;
83
84    /// The affine representation of an element in G1.
85    type G1Affine: CurveAffine<Engine = Self, Base = Self::Fq, Scalar = Self::Fr, Projective = Self::G1, Pair = Self::G2Affine, PairingResult = Self::Fqk> + From<Self::G1> + RawEncodable;
86
87    /// The projective representation of an element in G2.
88    type G2: CurveProjective<Engine = Self, Base = Self::Fqe, Scalar = Self::Fr, Affine = Self::G2Affine> + From<Self::G2Affine>;
89
90    /// The affine representation of an element in G2.
91    type G2Affine: CurveAffine<Engine = Self, Base = Self::Fqe, Scalar = Self::Fr, Projective = Self::G2, Pair = Self::G1Affine, PairingResult = Self::Fqk> + From<Self::G2>;
92
93    /// The base field that hosts G1.
94    type Fq: PrimeField + SqrtField;
95
96    /// The extension field that hosts G2.
97    type Fqe: SqrtField;
98
99    /// The extension field that hosts the target group of the pairing.
100    type Fqk: Field;
101
102    /// Perform a miller loop with some number of (G1, G2) pairs.
103    fn miller_loop<'a, I>(i: I) -> Self::Fqk
104    where
105        I: IntoIterator<Item = &'a (&'a <Self::G1Affine as CurveAffine>::Prepared, &'a <Self::G2Affine as CurveAffine>::Prepared)>;
106
107    /// Perform final exponentiation of the result of a miller loop.
108    fn final_exponentiation(r: &Self::Fqk) -> Option<Self::Fqk>;
109
110    /// Performs a complete pairing operation `(p, q)`.
111    fn pairing<G1, G2>(p: G1, q: G2) -> Self::Fqk
112    where
113        G1: Into<Self::G1Affine>,
114        G2: Into<Self::G2Affine>,
115    {
116        Self::final_exponentiation(&Self::miller_loop([(&(p.into().prepare()), &(q.into().prepare()))].iter())).unwrap()
117    }
118}
119
120/// Projective representation of an elliptic curve point guaranteed to be
121/// in the correct prime order subgroup.
122pub trait CurveProjective: PartialEq + Eq + Sized + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + ff::Rand + 'static {
123    type Engine: Engine<Fr = Self::Scalar>;
124    type Scalar: PrimeField + SqrtField;
125    type Base: SqrtField;
126    type Affine: CurveAffine<Projective = Self, Scalar = Self::Scalar, Base = Self::Base>;
127
128    /// Returns the additive identity.
129    fn zero() -> Self;
130
131    /// Returns a fixed generator of unknown exponent.
132    fn one() -> Self;
133
134    /// Determines if this point is the point at infinity.
135    fn is_zero(&self) -> bool;
136
137    /// Normalizes a slice of projective elements so that
138    /// conversion to affine is cheap.
139    fn batch_normalization(v: &mut [Self]);
140
141    /// Checks if the point is already "normalized" so that
142    /// cheap affine conversion is possible.
143    fn is_normalized(&self) -> bool;
144
145    /// Doubles this element.
146    fn double(&mut self);
147
148    /// Adds another element to this element.
149    fn add_assign(&mut self, other: &Self);
150
151    /// Subtracts another element from this element.
152    fn sub_assign(&mut self, other: &Self) {
153        let mut tmp = *other;
154        tmp.negate();
155        self.add_assign(&tmp);
156    }
157
158    /// Adds an affine element to this element.
159    fn add_assign_mixed(&mut self, other: &Self::Affine);
160
161    /// Negates this element.
162    fn negate(&mut self);
163
164    /// Performs scalar multiplication of this element.
165    fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S);
166
167    /// Converts this element into its affine representation.
168    fn into_affine(&self) -> Self::Affine;
169
170    /// Recommends a wNAF window table size given a scalar. Always returns a number
171    /// between 2 and 22, inclusive.
172    fn recommended_wnaf_for_scalar(scalar: <Self::Scalar as PrimeField>::Repr) -> usize;
173
174    /// Recommends a wNAF window size given the number of scalars you intend to multiply
175    /// a base by. Always returns a number between 2 and 22, inclusive.
176    fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize;
177
178    /// Returns references to underlying X, Y and Z coordinates. Users should check for infinity
179    /// outside of this call
180    fn as_xyz(&self) -> (&Self::Base, &Self::Base, &Self::Base) {
181        unimplemented!("default implementation does not exist for this function")
182    }
183
184    /// Returns underlying X, Y and Z coordinates. Users should check for infinity
185    /// outside of this call
186    fn into_xyz_unchecked(self) -> (Self::Base, Self::Base, Self::Base) {
187        unimplemented!("default implementation does not exist for this function")
188    }
189
190    /// Creates a point from raw X, Y and Z coordinates. Point of infinity is encoded as (0,1,0) by default.
191    /// On-curve check is NOT performed
192    fn from_xyz_unchecked(_x: Self::Base, _y: Self::Base, _z: Self::Base) -> Self {
193        unimplemented!("default implementation does not exist for this function")
194    }
195
196    /// Creates a point from raw X, Y and Z coordinates. Point of infinity is encoded as (0,1,0) by default.
197    /// On-curve check is performed
198    fn from_xyz_checked(_x: Self::Base, _y: Self::Base, _z: Self::Base) -> Result<Self, GroupDecodingError> {
199        unimplemented!("default implementation does not exist for this function")
200    }
201}
202
203/// Affine representation of an elliptic curve point guaranteed to be
204/// in the correct prime order subgroup.
205pub trait CurveAffine: Copy + Clone + Sized + Send + Sync + fmt::Debug + fmt::Display + PartialEq + Eq + 'static + serde::Serialize + serde::de::DeserializeOwned {
206    type Engine: Engine<Fr = Self::Scalar>;
207    type Scalar: PrimeField + SqrtField;
208    type Base: SqrtField;
209    type Projective: CurveProjective<Affine = Self, Scalar = Self::Scalar, Base = Self::Base>;
210    type Prepared: Clone + Send + Sync + 'static;
211    type Uncompressed: EncodedPoint<Affine = Self>;
212    type Compressed: EncodedPoint<Affine = Self>;
213    type Pair: CurveAffine<Pair = Self>;
214    type PairingResult: Field;
215
216    /// Returns the additive identity.
217    fn zero() -> Self;
218
219    /// Returns a fixed generator of unknown exponent.
220    fn one() -> Self;
221
222    /// Determines if this point represents the point at infinity; the
223    /// additive identity.
224    fn is_zero(&self) -> bool;
225
226    /// Negates this element.
227    fn negate(&mut self);
228
229    /// Performs scalar multiplication of this element with mixed addition.
230    fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, other: S) -> Self::Projective;
231
232    /// Prepares this element for pairing purposes.
233    fn prepare(&self) -> Self::Prepared;
234
235    /// Perform a pairing
236    fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult;
237
238    /// Converts this element into its affine representation.
239    fn into_projective(&self) -> Self::Projective;
240
241    /// Converts this element into its compressed encoding, so long as it's not
242    /// the point at infinity.
243    fn into_compressed(&self) -> Self::Compressed {
244        <Self::Compressed as EncodedPoint>::from_affine(*self)
245    }
246
247    /// Converts this element into its uncompressed encoding, so long as it's not
248    /// the point at infinity.
249    fn into_uncompressed(&self) -> Self::Uncompressed {
250        <Self::Uncompressed as EncodedPoint>::from_affine(*self)
251    }
252
253    /// Returns references to underlying X and Y coordinates. Users should check for infinity
254    /// outside of this call
255    fn as_xy(&self) -> (&Self::Base, &Self::Base);
256
257    /// Returns underlying X and Y coordinates. Users should check for infinity
258    /// outside of this call
259    fn into_xy_unchecked(self) -> (Self::Base, Self::Base);
260
261    /// Creates a point from raw X and Y coordinates. Point of infinity is encoded as (0,0) by default.
262    /// On-curve check is NOT performed
263    fn from_xy_unchecked(x: Self::Base, y: Self::Base) -> Self;
264
265    /// Creates a point from raw X and Y coordinates. Point of infinity is encoded as (0,0) by default.
266    /// On-curve check is performed
267    fn from_xy_checked(x: Self::Base, y: Self::Base) -> Result<Self, GroupDecodingError>;
268
269    /// returns A coefficient for a short Weierstrass form
270    fn a_coeff() -> Self::Base;
271
272    /// returns B coefficient for a short Weierstrass form
273    fn b_coeff() -> Self::Base;
274}
275
276pub trait RawEncodable: CurveAffine {
277    /// Converts this element into its uncompressed encoding, so long as it's not
278    /// the point at infinity. Leaves coordinates in Montgommery form
279    fn into_raw_uncompressed_le(&self) -> Self::Uncompressed;
280
281    /// Creates a point from raw encoded coordinates without checking on curve
282    fn from_raw_uncompressed_le_unchecked(encoded: &Self::Uncompressed, infinity: bool) -> Result<Self, GroupDecodingError>;
283
284    /// Creates a point from raw encoded coordinates
285    fn from_raw_uncompressed_le(encoded: &Self::Uncompressed, infinity: bool) -> Result<Self, GroupDecodingError>;
286}
287
288/// An encoded elliptic curve point, which should essentially wrap a `[u8; N]`.
289pub trait EncodedPoint: Sized + Send + Sync + AsRef<[u8]> + AsMut<[u8]> + Clone + Copy + 'static {
290    type Affine: CurveAffine;
291
292    /// Creates an empty representation.
293    fn empty() -> Self;
294
295    /// Returns the number of bytes consumed by this representation.
296    fn size() -> usize;
297
298    /// Converts an `EncodedPoint` into a `CurveAffine` element,
299    /// if the encoding represents a valid element.
300    fn into_affine(&self) -> Result<Self::Affine, GroupDecodingError>;
301
302    /// Converts an `EncodedPoint` into a `CurveAffine` element,
303    /// without guaranteeing that the encoding represents a valid
304    /// element. This is useful when the caller knows the encoding is
305    /// valid already.
306    ///
307    /// If the encoding is invalid, this can break API invariants,
308    /// so caution is strongly encouraged.
309    fn into_affine_unchecked(&self) -> Result<Self::Affine, GroupDecodingError>;
310
311    /// Creates an `EncodedPoint` from an affine point, as long as the
312    /// point is not the point at infinity.
313    fn from_affine(affine: Self::Affine) -> Self;
314}
315
316/// An error that may occur when trying to decode an `EncodedPoint`.
317#[derive(Debug)]
318pub enum GroupDecodingError {
319    /// The coordinate(s) do not lie on the curve.
320    NotOnCurve,
321    /// The element is not part of the r-order subgroup.
322    NotInSubgroup,
323    /// One of the coordinates could not be decoded
324    CoordinateDecodingError(&'static str, PrimeFieldDecodingError),
325    /// The compression mode of the encoded element was not as expected
326    UnexpectedCompressionMode,
327    /// The encoding contained bits that should not have been set
328    UnexpectedInformation,
329}
330
331impl GroupDecodingError {
332    fn self_description(&self) -> &str {
333        match *self {
334            GroupDecodingError::NotOnCurve => "coordinate(s) do not lie on the curve",
335            GroupDecodingError::NotInSubgroup => "the element is not part of an r-order subgroup",
336            GroupDecodingError::CoordinateDecodingError(..) => "coordinate(s) could not be decoded",
337            GroupDecodingError::UnexpectedCompressionMode => "encoding has unexpected compression mode",
338            GroupDecodingError::UnexpectedInformation => "encoding has unexpected information",
339        }
340    }
341}
342
343impl Error for GroupDecodingError {
344    fn description(&self) -> &str {
345        self.self_description()
346    }
347}
348
349impl fmt::Display for GroupDecodingError {
350    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
351        match *self {
352            GroupDecodingError::CoordinateDecodingError(description, ref err) => {
353                write!(f, "{} decoding error: {}", description, err)
354            }
355            _ => write!(f, "{}", self.self_description()),
356        }
357    }
358}