Skip to content

Commit

Permalink
add mul to ModelParam traits (#396)
Browse files Browse the repository at this point in the history
Co-authored-by: Pratyush Mishra <[email protected]>
  • Loading branch information
zhenfeizhang and Pratyush authored Mar 17, 2022
1 parent e5fa00f commit de9758b
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 73 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
- [\#383](https://github.com/arkworks-rs/algebra/pull/383) (`ark-ff`) Rename `BigInteger::add_nocarry` to `add_with_carry` and `sub_noborrow` to `sub_with_borrow`.
- [\#386](https://github.com/arkworks-rs/algebra/pull/386) (`ark-ff`) Remove `PrimeField::GENERATOR`, since it already exists on `FftField`.
- [\#393](https://github.com/arkworks-rs/algebra/pull/393) (`ark-ec`, `ark-ff`) Rename `FpXParams` to `FpXConfig` and `FpXParamsWrapper` to `FpXConfigWrapper`.
- [\#396](https://github.com/arkworks-rs/algebra/pull/396) (`ark-ec`) Remove `mul_bits` feature, and remove default implementations of `mul` and `mul_by_cofactor_to_projective`.

### Features

Expand All @@ -41,6 +42,7 @@
- [\#364](https://github.com/arkworks-rs/algebra/pull/364) (`ark-ec`) Add `ChunkedPippenger` to variable-base MSM.
- [\#371](https://github.com/arkworks-rs/algebra/pull/371) (`ark-serialize`) Add serialization impls for arrays
- [\#386](https://github.com/arkworks-rs/algebra/pull/386) (`ark-ff-macros`, `ark-ff`) Add a macro to derive `MontConfig`.
- [\#396](https://github.com/arkworks-rs/algebra/pull/396) (`ark-ec`) Add a default `mul` function to `{TE,SW}ModelParameters` trait definition.

### Improvements

Expand Down
43 changes: 6 additions & 37 deletions ec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extern crate ark_std;

use ark_ff::{
bytes::{FromBytes, ToBytes},
fields::{BitIteratorBE, Field, PrimeField, SquareRootField},
fields::{Field, PrimeField, SquareRootField},
UniformRand,
};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
Expand Down Expand Up @@ -220,18 +220,7 @@ pub trait ProjectiveCurve:
fn add_assign_mixed(&mut self, other: &Self::Affine);

/// Performs scalar multiplication of this element.
fn mul<S: AsRef<[u64]>>(mut self, other: S) -> Self {
let mut res = Self::zero();
for b in ark_ff::BitIteratorBE::without_leading_zeros(other) {
res.double_in_place();
if b {
res += self;
}
}

self = res;
self
}
fn mul<S: AsRef<[u64]>>(self, other: S) -> Self;
}

/// Affine representation of an elliptic curve point guaranteed to be
Expand Down Expand Up @@ -262,8 +251,8 @@ pub trait AffineCurve:
{
type Parameters: ModelParameters<ScalarField = Self::ScalarField, BaseField = Self::BaseField>;

/// The group defined by this curve has order `h * r` where `r` is a large prime.
/// `Self::ScalarField` is the prime field defined by `r`
/// The group defined by this curve has order `h * r` where `r` is a large
/// prime. `Self::ScalarField` is the prime field defined by `r`
type ScalarField: PrimeField + SquareRootField + Into<<Self::ScalarField as PrimeField>::BigInt>;

/// The finite field over which this curve is defined.
Expand Down Expand Up @@ -293,34 +282,14 @@ pub trait AffineCurve:
/// random group elements from a hash-function or RNG output.
fn from_random_bytes(bytes: &[u8]) -> Option<Self>;

/// Multiplies `self` by the scalar represented by `bits`. `bits` must be a
/// big-endian bit-wise decomposition of the scalar.
fn mul_bits(&self, bits: impl Iterator<Item = bool>) -> Self::Projective {
let mut res = Self::Projective::zero();
// Skip leading zeros.
for i in bits.skip_while(|b| !b) {
res.double_in_place();
if i {
res.add_assign_mixed(&self)
}
}
res
}

/// Performs scalar multiplication of this element with mixed addition.
#[must_use]
#[inline]
fn mul<S: Into<<Self::ScalarField as PrimeField>::BigInt>>(&self, by: S) -> Self::Projective {
self.mul_bits(BitIteratorBE::without_leading_zeros(by.into()))
}
fn mul<S: Into<<Self::ScalarField as PrimeField>::BigInt>>(&self, by: S) -> Self::Projective;

/// Multiplies this element by the cofactor and output the
/// resulting projective element.
#[must_use]
#[inline]
fn mul_by_cofactor_to_projective(&self) -> Self::Projective {
self.mul_bits(BitIteratorBE::new(Self::Parameters::COFACTOR))
}
fn mul_by_cofactor_to_projective(&self) -> Self::Projective;

/// Multiplies this element by the cofactor.
#[must_use]
Expand Down
109 changes: 91 additions & 18 deletions ec/src/models/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::AffineCurve;
use ark_ff::{fields::BitIteratorBE, Field, PrimeField, SquareRootField, Zero};
use crate::ProjectiveCurve;
use ark_ff::{Field, PrimeField, SquareRootField, Zero};

pub mod bls12;
pub mod bn;
Expand All @@ -12,9 +12,9 @@ pub mod twisted_edwards_extended;
/// Elliptic curves can be represented via different "models" with varying
/// efficiency properties.
/// `ModelParameters` bundles together the types that are common
/// to all models of the given curve, namely the `BaseField` over which the curve
/// is defined, and the `ScalarField` defined by the appropriate prime-order
/// subgroup of the curve.
/// to all models of the given curve, namely the `BaseField` over which the
/// curve is defined, and the `ScalarField` defined by the appropriate
/// prime-order subgroup of the curve.
pub trait ModelParameters: Send + Sync + Sized + 'static {
/// Base field that the curve is defined over.
type BaseField: Field + SquareRootField;
Expand All @@ -27,7 +27,8 @@ pub trait ModelParameters: Send + Sync + Sized + 'static {
}

/// Constants and convenience functions that collectively define the [Short Weierstrass model](https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html)
/// of the curve. In this model, the curve equation is `y² = x³ + a * x + b`, for constants `a` and `b`.
/// of the curve. In this model, the curve equation is `y² = x³ + a * x + b`,
/// for constants `a` and `b`.
pub trait SWModelParameters: ModelParameters {
/// Coefficient `a` of the curve equation.
const COEFF_A: Self::BaseField;
Expand All @@ -51,7 +52,8 @@ pub trait SWModelParameters: ModelParameters {
/// Helper method for computing `elem + Self::COEFF_B`.
///
/// The default implementation should be overridden only if
/// the sum can be computed faster than standard field addition (eg: via doubling).
/// the sum can be computed faster than standard field addition (eg: via
/// doubling).
#[inline(always)]
fn add_b(elem: &Self::BaseField) -> Self::BaseField {
if !Self::COEFF_B.is_zero() {
Expand All @@ -64,21 +66,56 @@ pub trait SWModelParameters: ModelParameters {

/// Check if the provided curve point is in the prime-order subgroup.
///
/// The default implementation multiplies `item` by the order `r` of the prime-order
/// subgroup, and checks if the result is one.
/// The default implementation multiplies `item` by the order `r` of the
/// prime-order subgroup, and checks if the result is one.
/// Implementors can choose to override this default impl
/// if the given curve has faster methods
/// for performing this check (for example, via leveraging curve isomorphisms).
/// for performing this check (for example, via leveraging curve
/// isomorphisms).
fn is_in_correct_subgroup_assuming_on_curve(
item: &short_weierstrass_jacobian::GroupAffine<Self>,
) -> bool {
item.mul_bits(BitIteratorBE::new(Self::ScalarField::characteristic()))
.is_zero()
Self::mul_affine(item, Self::ScalarField::characteristic()).is_zero()
}

/// Default implementation of group multiplication for projective
/// coordinates
fn mul_projective(
base: &short_weierstrass_jacobian::GroupProjective<Self>,
scalar: &[u64],
) -> short_weierstrass_jacobian::GroupProjective<Self> {
let mut res = short_weierstrass_jacobian::GroupProjective::<Self>::zero();
for b in ark_ff::BitIteratorBE::without_leading_zeros(scalar) {
res.double_in_place();
if b {
res += base;
}
}

res
}

/// Default implementation of group multiplication for affine
/// coordinates.
fn mul_affine(
base: &short_weierstrass_jacobian::GroupAffine<Self>,
scalar: &[u64],
) -> short_weierstrass_jacobian::GroupProjective<Self> {
let mut res = short_weierstrass_jacobian::GroupProjective::<Self>::zero();
for b in ark_ff::BitIteratorBE::without_leading_zeros(scalar) {
res.double_in_place();
if b {
res.add_assign_mixed(base)
}
}

res
}
}

/// Constants and convenience functions that collectively define the [Twisted Edwards model](https://www.hyperelliptic.org/EFD/g1p/auto-twisted.html)
/// of the curve. In this model, the curve equation is `a * x² + y² = 1 + d * x² * y²`, for constants `a` and `d`.
/// of the curve. In this model, the curve equation is
/// `a * x² + y² = 1 + d * x² * y²`, for constants `a` and `d`.
pub trait TEModelParameters: ModelParameters {
/// Coefficient `a` of the curve equation.
const COEFF_A: Self::BaseField;
Expand All @@ -87,7 +124,8 @@ pub trait TEModelParameters: ModelParameters {
/// Coefficients of the base point of the curve
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField);

/// Model parameters for the Montgomery curve that is birationally equivalent to this curve.
/// Model parameters for the Montgomery curve that is birationally
/// equivalent to this curve.
type MontgomeryModelParameters: MontgomeryModelParameters<BaseField = Self::BaseField>;

/// Helper method for computing `elem * Self::COEFF_A`.
Expand All @@ -107,19 +145,54 @@ pub trait TEModelParameters: ModelParameters {
fn is_in_correct_subgroup_assuming_on_curve(
item: &twisted_edwards_extended::GroupAffine<Self>,
) -> bool {
item.mul_bits(BitIteratorBE::new(Self::ScalarField::characteristic()))
.is_zero()
Self::mul_affine(item, Self::ScalarField::characteristic()).is_zero()
}

/// Default implementation of group multiplication for projective
/// coordinates
fn mul_projective(
base: &twisted_edwards_extended::GroupProjective<Self>,
scalar: &[u64],
) -> twisted_edwards_extended::GroupProjective<Self> {
let mut res = twisted_edwards_extended::GroupProjective::<Self>::zero();
for b in ark_ff::BitIteratorBE::without_leading_zeros(scalar) {
res.double_in_place();
if b {
res += base;
}
}

res
}

/// Default implementation of group multiplication for affine
/// coordinates
fn mul_affine(
base: &twisted_edwards_extended::GroupAffine<Self>,
scalar: &[u64],
) -> twisted_edwards_extended::GroupProjective<Self> {
let mut res = twisted_edwards_extended::GroupProjective::<Self>::zero();
for b in ark_ff::BitIteratorBE::without_leading_zeros(scalar) {
res.double_in_place();
if b {
res.add_assign_mixed(base)
}
}

res
}
}

/// Constants and convenience functions that collectively define the [Montgomery model](https://www.hyperelliptic.org/EFD/g1p/auto-montgom.html)
/// of the curve. In this model, the curve equation is `b * y² = x³ + a * x² + x`, for constants `a` and `b`.
/// of the curve. In this model, the curve equation is
/// `b * y² = x³ + a * x² + x`, for constants `a` and `b`.
pub trait MontgomeryModelParameters: ModelParameters {
/// Coefficient `a` of the curve equation.
const COEFF_A: Self::BaseField;
/// Coefficient `b` of the curve equation.
const COEFF_B: Self::BaseField;

/// Model parameters for the Twisted Edwards curve that is birationally equivalent to this curve.
/// Model parameters for the Twisted Edwards curve that is birationally
/// equivalent to this curve.
type TEModelParameters: TEModelParameters<BaseField = Self::BaseField>;
}
16 changes: 16 additions & 0 deletions ec/src/models/short_weierstrass_jacobian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,17 @@ impl<P: Parameters> AffineCurve for GroupAffine<P> {
}
})
}

fn mul<S: Into<<Self::ScalarField as PrimeField>::BigInt>>(&self, by: S) -> Self::Projective {
P::mul_affine(self, by.into().as_ref())
}

/// Multiplies this element by the cofactor and output the
/// resulting projective element.
#[must_use]
fn mul_by_cofactor_to_projective(&self) -> Self::Projective {
P::mul_affine(self, Self::Parameters::COFACTOR)
}
}

impl<P: Parameters> Neg for GroupAffine<P> {
Expand Down Expand Up @@ -590,6 +601,11 @@ impl<P: Parameters> ProjectiveCurve for GroupProjective<P> {
self.z -= &hh;
}
}

#[inline]
fn mul<S: AsRef<[u64]>>(self, other: S) -> Self {
P::mul_projective(&self, other.as_ref())
}
}

impl<P: Parameters> Neg for GroupProjective<P> {
Expand Down
Loading

0 comments on commit de9758b

Please sign in to comment.