pairing 0.24.1

Pairing-friendly elliptic curve library
Documentation
//! A library for working with pairing-friendly curves.

#![no_std]
// `clippy` is a code linting tool for improving code quality by catching
// common mistakes or strange code patterns. If the `cargo-clippy` feature
// is provided, all compiler warnings are prohibited.
#![deny(warnings)]
#![allow(clippy::inline_always)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::unreadable_literal)]
#![allow(clippy::many_single_char_names)]
#![allow(clippy::new_without_default)]
#![allow(clippy::write_literal)]
// Catch documentation errors caused by code changes.
#![deny(rustdoc::broken_intra_doc_links)]
// Force public structures to implement Debug
#![deny(missing_debug_implementations)]

// Re-export group to make version-matching easier.
pub use group;

use core::ops::{Add, AddAssign, Mul};
use group::{
    Group, GroupOps, GroupOpsOwned, ScalarMul, ScalarMulOwned, UncompressedEncoding,
    ff::PrimeField,
    prime::{PrimeCurve, PrimeCurveAffine},
};

/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
/// with well-defined relationships. In particular, the G1/G2 curve groups are
/// of prime order `r`, and are equipped with a bilinear pairing function.
pub trait Engine: Sized + 'static + Clone + Sync + Send + core::fmt::Debug {
    /// This is the scalar field of the engine's groups.
    type Fr: PrimeField;

    /// The projective representation of an element in G1.
    type G1: PrimeCurve<Scalar = Self::Fr, Affine = Self::G1Affine>
        + From<Self::G1Affine>
        + GroupOps<Self::G1Affine>
        + GroupOpsOwned<Self::G1Affine>
        + ScalarMul<Self::Fr>
        + ScalarMulOwned<Self::Fr>;

    /// The affine representation of an element in G1.
    type G1Affine: PairingCurveAffine<
            Scalar = Self::Fr,
            Curve = Self::G1,
            Pair = Self::G2Affine,
            PairingResult = Self::Gt,
        > + From<Self::G1>
        + Mul<Self::Fr, Output = Self::G1>
        + for<'a> Mul<&'a Self::Fr, Output = Self::G1>;

    /// The projective representation of an element in G2.
    type G2: PrimeCurve<Scalar = Self::Fr, Affine = Self::G2Affine>
        + From<Self::G2Affine>
        + GroupOps<Self::G2Affine>
        + GroupOpsOwned<Self::G2Affine>
        + ScalarMul<Self::Fr>
        + ScalarMulOwned<Self::Fr>;

    /// The affine representation of an element in G2.
    type G2Affine: PairingCurveAffine<
            Scalar = Self::Fr,
            Curve = Self::G2,
            Pair = Self::G1Affine,
            PairingResult = Self::Gt,
        > + From<Self::G2>
        + Mul<Self::Fr, Output = Self::G2>
        + for<'a> Mul<&'a Self::Fr, Output = Self::G2>;

    /// The extension field that hosts the target group of the pairing.
    type Gt: Group<Scalar = Self::Fr> + ScalarMul<Self::Fr> + ScalarMulOwned<Self::Fr>;

    /// Invoke the pairing function `G1 x G2 -> Gt` without the use of precomputation and
    /// other optimizations.
    fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt;
}

/// Affine representation of an elliptic curve point that can be used
/// to perform pairings.
pub trait PairingCurveAffine: PrimeCurveAffine + UncompressedEncoding {
    type Pair: PairingCurveAffine<Pair = Self>;
    type PairingResult: Group;

    /// Perform a pairing
    fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult;
}

/// An engine that can compute sums of pairings in an efficient way.
pub trait MultiMillerLoop: Engine {
    /// The prepared form of `Self::G2Affine`.
    ///
    /// The `From<Self::G2Affine>` implementation is assumed to be implemented in constant
    /// time relative to the point.
    type G2Prepared: Clone + Send + Sync + From<Self::G2Affine>;

    /// The type returned by `Engine::miller_loop`.
    type Result: MillerLoopResult<Gt = Self::Gt>;

    /// Prepare a G2 point for repeated use across Miller loops.
    ///
    /// The default implementation calls `Self::G2Prepared::from(q)`. Implementations may
    /// spend more time here to speed up each later loop.
    ///
    /// # Guarantees
    ///
    /// The raw Miller loop result may differ from ordinary preparation, but final
    /// exponentiation **MUST** produce the same pairing result.
    ///
    /// Implementations may be variable time in `q`. This API should only be used with
    /// public points, such as those in Groth16 verifying keys. For all other points,
    /// use `Self::G2Prepared::from(q)` instead.
    fn prepare_reusable_g2(q: Self::G2Affine) -> Self::G2Prepared {
        q.into()
    }

    /// Computes $$\sum_{i=1}^n \textbf{ML}(a_i, b_i)$$ given a series of terms
    /// $$(a_1, b_1), (a_2, b_2), ..., (a_n, b_n).$$
    fn multi_miller_loop(terms: &[(&Self::G1Affine, &Self::G2Prepared)]) -> Self::Result;
}

/// Represents results of a Miller loop, one of the most expensive portions of the pairing
/// function.
///
/// `MillerLoopResult`s cannot be compared with each other until
/// [`MillerLoopResult::final_exponentiation`] is called, which is also expensive.
pub trait MillerLoopResult:
    Clone
    + Copy
    + Default
    + core::fmt::Debug
    + Send
    + Sync
    + Add<Output = Self>
    + for<'a> Add<&'a Self, Output = Self>
    + AddAssign
    + for<'a> AddAssign<&'a Self>
{
    /// The extension field that hosts the target group of the pairing.
    type Gt: Group;

    /// This performs a "final exponentiation" routine to convert the result of a Miller
    /// loop into an element of [`MillerLoopResult::Gt`], so that it can be compared with
    /// other elements of `Gt`.
    fn final_exponentiation(&self) -> Self::Gt;
}