Skip to content

Commit

Permalink
♻️ Update affine/projective curve trait to grouped ver
Browse files Browse the repository at this point in the history
  • Loading branch information
sheagrief committed Sep 26, 2023
1 parent 889e438 commit f4c0bfc
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 20 deletions.
14 changes: 10 additions & 4 deletions arkworks/algebra/ec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,16 @@ pub trait PairingEngine: Sized + 'static + Copy + Debug + Sync + Send + Eq + Par
type G1Projective: ProjectiveCurve<BaseField = Self::Fq, ScalarField = Self::Fr, Affine = Self::G1Affine>
+ From<Self::G1Affine>
+ Into<Self::G1Affine>
+ MulAssign<Self::Fr>; // needed due to https://github.com/rust-lang/rust/issues/69640
+ MulAssign<Self::Fr>
// needed due to https://github.com/rust-lang/rust/issues/69640
+ Group<ScalarField = Self::Fr>;

/// The affine representation of an element in G1.
type G1Affine: AffineCurve<BaseField = Self::Fq, ScalarField = Self::Fr, Projective = Self::G1Projective>
+ From<Self::G1Projective>
+ Into<Self::G1Projective>
+ Into<Self::G1Prepared>;
+ Into<Self::G1Prepared>
+ Group<ScalarField = Self::Fr>;

/// A G1 element that has been preprocessed for use in a pairing.
type G1Prepared: ToBytes + Default + Clone + Send + Sync + Debug + From<Self::G1Affine>;
Expand All @@ -61,13 +64,16 @@ pub trait PairingEngine: Sized + 'static + Copy + Debug + Sync + Send + Eq + Par
type G2Projective: ProjectiveCurve<BaseField = Self::Fqe, ScalarField = Self::Fr, Affine = Self::G2Affine>
+ From<Self::G2Affine>
+ Into<Self::G2Affine>
+ MulAssign<Self::Fr>; // needed due to https://github.com/rust-lang/rust/issues/69640
+ MulAssign<Self::Fr>
// needed due to https://github.com/rust-lang/rust/issues/69640
+ Group<ScalarField = Self::Fr>;

/// The affine representation of an element in G2.
type G2Affine: AffineCurve<BaseField = Self::Fqe, ScalarField = Self::Fr, Projective = Self::G2Projective>
+ From<Self::G2Projective>
+ Into<Self::G2Projective>
+ Into<Self::G2Prepared>;
+ Into<Self::G2Prepared>
+ Group<ScalarField = Self::Fr>;

/// A G2 element that has been preprocessed for use in a pairing.
type G2Prepared: ToBytes + Default + Clone + Send + Sync + Debug + From<Self::G2Affine>;
Expand Down
112 changes: 96 additions & 16 deletions arkworks/algebra/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 @@ -87,8 +87,8 @@ impl<P: Parameters> GroupAffine<P> {
self.mul_bits(cofactor)
}

/// Multiplies `self` by the scalar represented by `bits`. `bits` must be a big-endian
/// bit-wise decomposition of the scalar.
/// Multiplies `self` by the scalar represented by `bits`. `bits` must be a
/// big-endian bit-wise decomposition of the scalar.
pub(crate) fn mul_bits(&self, bits: impl Iterator<Item = bool>) -> GroupProjective<P> {
let mut res = GroupProjective::zero();
// Skip leading zeros.
Expand Down Expand Up @@ -214,7 +214,9 @@ 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 @@ -252,6 +254,63 @@ impl<P: Parameters> Neg for GroupAffine<P> {
}
}

impl<'a, P: Parameters> Add<&'a Self> for GroupAffine<P> {
type Output = Self;
fn add(self, other: &'a Self) -> Self {
let mut copy = self;
copy += other;
copy
}
}

impl<P: Parameters> AddAssign<Self> for GroupAffine<P> {
fn add_assign(&mut self, other: Self) {
self.add_assign(other)
}
}

impl<P: Parameters> Sub<Self> for GroupAffine<P> {
type Output = Self;
fn sub(self, other: Self) -> Self {
let mut copy = self;
copy -= other;
copy
}
}

impl<'a, P: Parameters> Sub<&'a Self> for GroupAffine<P> {
type Output = Self;
fn sub(self, other: &'a Self) -> Self {
let mut copy = self;
copy -= other;
copy
}
}

impl<P: Parameters> SubAssign<Self> for GroupAffine<P> {
fn sub_assign(&mut self, other: Self) {
self.sub_assign(other)
}
}

impl<'a, P: Parameters> SubAssign<&'a Self> for GroupAffine<P> {
fn sub_assign(&mut self, other: &'a Self) {
*self += &(-(*other));
}
}

impl<P: Parameters> MulAssign<P::ScalarField> for GroupAffine<P> {
fn mul_assign(&mut self, other: P::ScalarField) {
*self = self.mul(other.into_repr()).into()
}
}

impl<P: Parameters> UniformRand for GroupAffine<P> {
fn rand<R: Rng + ?Sized>(rng: &mut R) -> Self {
todo!()
}
}

impl<P: Parameters> ToBytes for GroupAffine<P> {
#[inline]
fn write<W: Write>(&self, mut writer: W) -> IoResult<()> {
Expand Down Expand Up @@ -292,8 +351,25 @@ impl<'a, P: Parameters> core::iter::Sum<&'a Self> for GroupAffine<P> {
}
}

/// Jacobian coordinates for a point on an elliptic curve in short Weierstrass form,
/// over the base field `P::BaseField`. This struct implements arithmetic
mod group_impl {
use super::*;
use crate::group::Group;

impl<P: Parameters> Group for GroupAffine<P> {
type ScalarField = P::ScalarField;

fn double(&self) -> Self {
todo!()
}

fn double_in_place(&mut self) -> &mut Self {
todo!()
}
}
}

/// Jacobian coordinates for a point on an elliptic curve in short Weierstrass
/// form, over the base field `P::BaseField`. This struct implements arithmetic
/// via the Jacobian formulae
#[derive(Derivative)]
#[derivative(
Expand Down Expand Up @@ -395,7 +471,8 @@ impl<P: Parameters> GroupProjective<P> {

impl<P: Parameters> Zeroize for GroupProjective<P> {
fn zeroize(&mut self) {
// `PhantomData` does not contain any data and thus does not need to be zeroized.
// `PhantomData` does not contain any data and thus does not need to be
// zeroized.
self.x.zeroize();
self.y.zeroize();
self.z.zeroize();
Expand Down Expand Up @@ -439,12 +516,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 All @@ -463,8 +543,8 @@ impl<P: Parameters> ProjectiveCurve for GroupProjective<P> {
}

/// Sets `self = 2 * self`. Note that Jacobian formulae are incomplete, and
/// so doubling cannot be computed as `self + self`. Instead, this implementation
/// uses the following specialized doubling formulae:
/// so doubling cannot be computed as `self + self`. Instead, this
/// implementation uses the following specialized doubling formulae:
/// * [`P::A` is zero](http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l)
/// * [`P::A` is not zero](https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-2007-bl)
fn double_in_place(&mut self) -> &mut Self {
Expand Down Expand Up @@ -535,8 +615,8 @@ impl<P: Parameters> ProjectiveCurve for GroupProjective<P> {
}
}

/// When `other.is_normalized()` (i.e., `other.z == 1`), we can use a more efficient
/// [formula](http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl)
/// When `other.is_normalized()` (i.e., `other.z == 1`), we can use a more
/// efficient [formula](http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl)
/// to compute `self + other`.
fn add_assign_mixed(&mut self, other: &GroupAffine<P>) {
if other.is_zero() {
Expand Down

0 comments on commit f4c0bfc

Please sign in to comment.