Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GLVParameters trait definition #301

Merged
merged 12 commits into from
Sep 6, 2021
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

### Features

- [\#301](https://github.com/arkworks-rs/algebra/pull/301) (ark-ec) Add `GLVParameters` trait definition.
- [\#312](https://github.com/arkworks-rs/algebra/pull/312) (ark-ec) Add `is_in_correct_subgroup_assuming_on_curve` for all `SWModelParameters`.

### Improvements
Expand Down
56 changes: 56 additions & 0 deletions ec/src/glv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use crate::ModelParameters;

/// The GLV parameters for computing the endomorphism and scalar decomposition.
pub trait GLVParameters: Send + Sync + 'static + ModelParameters {
type CurveAffine;
type CurveProjective;

// Constants that are used to calculate `phi(G) := lambda*G`.

/// Coefficient `a_1` of `f(y) = a_1 * (y + a_2) * (y + a_3)`.
const COEFF_A1: Self::BaseField;
weikengchen marked this conversation as resolved.
Show resolved Hide resolved
/// Coefficient `a_2` of `f(y) = a_1 * (y + a_2) * (y + a_3)`.
const COEFF_A2: Self::BaseField;
/// Coefficient `a_3` of `f(y) = a_1 * (y + a_2) * (y + a_3)`.
const COEFF_A3: Self::BaseField;

/// Coefficient `b_1` of `g(y) = b_1 * (y + b_2) * (y + b_3)`.
const COEFF_B1: Self::BaseField;
/// Coefficient `b_2` of `g(y) = b_1 * (y + b_2) * (y + b_3)`.
const COEFF_B2: Self::BaseField;
/// Coefficient `b_3` of `g(y) = b_1 * (y + b_2) * (y + b_3)`.
const COEFF_B3: Self::BaseField;

/// Coefficient `c_1` of `h(y) = (y + c_1) * (y + c_2)`.
const COEFF_C1: Self::BaseField;
/// Coefficient `c_2` of `h(y) = (y + c_1) * (y + c_2)`.
const COEFF_C2: Self::BaseField;

// Constants for scalar decomposition.
// This is a 2x2 matrix, which is practically the LLL-reduced bases.

/// The first element of the matrix for scalar decomposition.
const COEFF_N11: Self::ScalarField;
/// The second element of the matrix for scalar decomposition.
const COEFF_N12: Self::ScalarField;
/// The third element of the matrix for scalar decomposition.
const COEFF_N21: Self::ScalarField;
/// The forth element of the matrix for the scalar decomposition.
const COEFF_N22: Self::ScalarField;

/// Maps a point G to phi(G):= lambda G where psi is the endomorphism.
// On an affine curve, the function takes the following steps:
// f(y) = a_1 * (y + a_2) * (y + a_3)
// g(y) = b_1 * (y + b_2) * (y + b_3)
// h(y) = (y + c_1) * (y + c_2)
// return (x',y') where
// x' = x * f(y) / y
// y' = g(y) / h(y)
fn endomorphism(base: &Self::CurveAffine) -> Self::CurveAffine;

/// Decomposes a scalar s into k1, k2, s.t. s = k1 + lambda k2,
fn scalar_decomposition(k: &Self::ScalarField) -> (Self::ScalarField, Self::ScalarField);

/// Performs GLV multiplication.
fn glv_mul(base: &Self::CurveAffine, scalar: &Self::ScalarField) -> Self::CurveProjective;
}
20 changes: 11 additions & 9 deletions ec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ use zeroize::Zeroize;
pub mod models;
pub use self::models::*;

pub mod glv;

pub mod group;

pub mod msm;
Expand Down Expand Up @@ -81,13 +83,13 @@ pub trait PairingEngine: Sized + 'static + Copy + Debug + Sync + Send + Eq + Par
/// The extension field that hosts the target group of the pairing.
type Fqk: Field;

/// Compute the product of miller loops for some number of (G1, G2) pairs.
/// Computes the product of miller loops for some number of (G1, G2) pairs.
#[must_use]
fn miller_loop<'a, I>(i: I) -> Self::Fqk
where
I: IntoIterator<Item = &'a (Self::G1Prepared, Self::G2Prepared)>;

/// Perform final exponentiation of the result of a miller loop.
/// Performs final exponentiation of the result of a miller loop.
#[must_use]
fn final_exponentiation(_: &Self::Fqk) -> Option<Self::Fqk>;

Expand Down Expand Up @@ -192,14 +194,14 @@ pub trait ProjectiveCurve:
(*self).into()
}

/// Set `self` to be `self + other`, where `other: Self::Affine`.
/// Sets `self` to be `self + other`, where `other: Self::Affine`.
/// This is usually faster than adding `other` in projective form.
fn add_mixed(mut self, other: &Self::Affine) -> Self {
self.add_assign_mixed(other);
self
}

/// Set `self` to be `self + other`, where `other: Self::Affine`.
/// Sets `self` to be `self + other`, where `other: Self::Affine`.
/// This is usually faster than adding `other` in projective form.
fn add_assign_mixed(&mut self, other: &Self::Affine);

Expand Down Expand Up @@ -270,18 +272,18 @@ pub trait AffineCurve:
fn mul<S: Into<<Self::ScalarField as PrimeField>::BigInt>>(&self, other: S)
-> Self::Projective;

/// Multiply this element by the cofactor and output the
/// Multiplies this element by the cofactor and output the
/// resulting projective element.
#[must_use]
fn mul_by_cofactor_to_projective(&self) -> Self::Projective;

/// Multiply this element by the cofactor.
/// Multiplies this element by the cofactor.
#[must_use]
fn mul_by_cofactor(&self) -> Self {
self.mul_by_cofactor_to_projective().into()
}

/// Multiply this element by the inverse of the cofactor in
/// Multiplies this element by the inverse of the cofactor in
/// `Self::ScalarField`.
#[must_use]
fn mul_by_cofactor_inv(&self) -> Self;
Expand All @@ -304,13 +306,13 @@ impl<C: ProjectiveCurve> Group for C {
}
}

/// Preprocess a G1 element for use in a pairing.
/// Preprocesses a G1 element for use in a pairing.
pub fn prepare_g1<E: PairingEngine>(g: impl Into<E::G1Affine>) -> E::G1Prepared {
let g: E::G1Affine = g.into();
E::G1Prepared::from(g)
}

/// Preprocess a G2 element for use in a pairing.
/// Preprocesses a G2 element for use in a pairing.
pub fn prepare_g2<E: PairingEngine>(g: impl Into<E::G2Affine>) -> E::G2Prepared {
let g: E::G2Affine = g.into();
E::G2Prepared::from(g)
Expand Down
10 changes: 6 additions & 4 deletions ec/src/models/bn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ pub enum TwistType {
}

pub trait BnParameters: 'static {
// The absolute value of the BN curve parameter `X` (as in `q = 36 X^4 + 36 X^3 + 24 X^2 + 6 X + 1`).
/// The absolute value of the BN curve parameter `X`
/// (as in `q = 36 X^4 + 36 X^3 + 24 X^2 + 6 X + 1`).
const X: &'static [u64];
// Whether or not `X` is negative.

/// Whether or not `X` is negative.
const X_IS_NEGATIVE: bool;

// The absolute value of `6X + 2`.
/// The absolute value of `6X + 2`.
const ATE_LOOP_COUNT: &'static [i8];

const TWIST_TYPE: TwistType;
Expand Down Expand Up @@ -53,7 +55,7 @@ pub use self::{
pub struct Bn<P: BnParameters>(PhantomData<fn() -> P>);

impl<P: BnParameters> Bn<P> {
// Evaluate the line function at point p.
/// Evaluates the line function at point p.
fn ell(f: &mut Fp12<P::Fp12Params>, coeffs: &g2::EllCoeff<Fp2<P::Fp2Params>>, p: &G1Affine<P>) {
let mut c0 = coeffs.0;
let mut c1 = coeffs.1;
Expand Down
2 changes: 2 additions & 0 deletions ec/src/models/bw6/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ impl<P: BW6Parameters> BW6<P> {
fn final_exponentiation_last_chunk(f: &Fp6<P::Fp6Params>) -> Fp6<P::Fp6Params> {
// hard_part
// From https://eprint.iacr.org/2020/351.pdf, Alg.6

#[rustfmt::skip]
// R0(x) := (-103*x^7 + 70*x^6 + 269*x^5 - 197*x^4 - 314*x^3 - 73*x^2 - 263*x - 220)
// R1(x) := (103*x^9 - 276*x^8 + 77*x^7 + 492*x^6 - 445*x^5 - 65*x^4 + 452*x^3 - 181*x^2 + 34*x + 229)
// f ^ R0(u) * (f ^ q) ^ R1(u) in a 2-NAF multi-exp fashion.
Expand Down
18 changes: 11 additions & 7 deletions ec/src/models/short_weierstrass_jacobian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ use ark_std::rand::{
#[cfg(feature = "parallel")]
use rayon::prelude::*;

/// Affine coordinates for a point on an elliptic curve in short Weierstrass form,
/// over the base field `P::BaseField`.
/// Affine coordinates for a point on an elliptic curve in short Weierstrass
/// form, over the base field `P::BaseField`.
#[derive(Derivative)]
#[derivative(
Copy(bound = "P: Parameters"),
Expand Down Expand Up @@ -206,7 +206,8 @@ impl<P: Parameters> AffineCurve for GroupAffine<P> {
if x.is_zero() && flags.is_infinity() {
Some(Self::zero())
} else if let Some(y_is_positive) = flags.is_positive() {
Self::get_point_from_x(x, y_is_positive) // Unwrap is safe because it's not zero.
Self::get_point_from_x(x, y_is_positive)
// Unwrap is safe because it's not zero.
} else {
None
}
Expand Down Expand Up @@ -428,12 +429,15 @@ impl<P: Parameters> ProjectiveCurve for GroupProjective<P> {
/// Normalizes a slice of projective elements so that
/// conversion to affine is cheap.
///
/// In more detail, this method converts a curve point in Jacobian coordinates
/// (x, y, z) into an equivalent representation (x/z^2, y/z^3, 1).
/// In more detail, this method converts a curve point in Jacobian
/// coordinates (x, y, z) into an equivalent representation (x/z^2,
/// y/z^3, 1).
///
/// For `N = v.len()`, this costs 1 inversion + 6N field multiplications + N field squarings.
/// For `N = v.len()`, this costs 1 inversion + 6N field multiplications + N
/// field squarings.
///
/// (Where batch inversion comprises 3N field multiplications + 1 inversion of these operations)
/// (Where batch inversion comprises 3N field multiplications + 1 inversion
/// of these operations)
#[inline]
fn batch_normalization(v: &mut [Self]) {
let mut z_s = v.iter().map(|g| g.z).collect::<Vec<_>>();
Expand Down
3 changes: 2 additions & 1 deletion ec/src/models/twisted_edwards_extended.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,8 @@ mod group_impl {
/// `GroupProjective` implements Extended Twisted Edwards Coordinates
/// as described in [\[HKCD08\]](https://eprint.iacr.org/2008/522.pdf).
///
/// This implementation uses the unified addition formulae from that paper (see Section 3.1).
/// This implementation uses the unified addition formulae from that paper (see
/// Section 3.1).
#[derive(Derivative)]
#[derivative(
Copy(bound = "P: Parameters"),
Expand Down
14 changes: 8 additions & 6 deletions ec/src/wnaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub struct WnafContext {
}

impl WnafContext {
/// Construct a new context for a window of size `window_size`.
/// Constructs a new context for a window of size `window_size`.
pub fn new(window_size: usize) -> Self {
assert!(window_size >= 2);
assert!(window_size < 64);
Expand All @@ -29,17 +29,19 @@ impl WnafContext {

/// Computes scalar multiplication of a group element `g` by `scalar`.
///
/// This method uses the wNAF algorithm to perform the scalar multiplication;
/// first, it uses `Self::table` to calculate an appropriate table of multiples of `g`,
/// and then uses the wNAF algorithm to compute the scalar multiple.
/// This method uses the wNAF algorithm to perform the scalar
/// multiplication; first, it uses `Self::table` to calculate an
/// appropriate table of multiples of `g`, and then uses the wNAF
/// algorithm to compute the scalar multiple.
pub fn mul<G: ProjectiveCurve>(&self, g: G, scalar: &G::ScalarField) -> G {
let table = self.table(g);
self.mul_with_table(&table, scalar).unwrap()
}

/// Computes scalar multiplication of a group element by `scalar`.
/// `base_table` holds precomputed multiples of the group element; it can be generated using `Self::table`.
/// `scalar` is an element of `G::ScalarField`.
/// `base_table` holds precomputed multiples of the group element; it can be
/// generated using `Self::table`. `scalar` is an element of
/// `G::ScalarField`.
///
/// Returns `None` if the table is too small.
pub fn mul_with_table<G: ProjectiveCurve>(
Expand Down