From f4c0bfc5073ebee47ec653e472f63138fe229311 Mon Sep 17 00:00:00 2001 From: sheagrief <3a.mad1earth4@gmail.com> Date: Tue, 26 Sep 2023 17:33:23 +0900 Subject: [PATCH] :recycle: Update affine/projective curve trait to grouped ver --- arkworks/algebra/ec/src/lib.rs | 14 ++- .../src/models/short_weierstrass_jacobian.rs | 112 +++++++++++++++--- 2 files changed, 106 insertions(+), 20 deletions(-) diff --git a/arkworks/algebra/ec/src/lib.rs b/arkworks/algebra/ec/src/lib.rs index 82dbb1ae..23bd0498 100644 --- a/arkworks/algebra/ec/src/lib.rs +++ b/arkworks/algebra/ec/src/lib.rs @@ -46,13 +46,16 @@ pub trait PairingEngine: Sized + 'static + Copy + Debug + Sync + Send + Eq + Par type G1Projective: ProjectiveCurve + From + Into - + MulAssign; // needed due to https://github.com/rust-lang/rust/issues/69640 + + MulAssign + // needed due to https://github.com/rust-lang/rust/issues/69640 + + Group; /// The affine representation of an element in G1. type G1Affine: AffineCurve + From + Into - + Into; + + Into + + Group; /// A G1 element that has been preprocessed for use in a pairing. type G1Prepared: ToBytes + Default + Clone + Send + Sync + Debug + From; @@ -61,13 +64,16 @@ pub trait PairingEngine: Sized + 'static + Copy + Debug + Sync + Send + Eq + Par type G2Projective: ProjectiveCurve + From + Into - + MulAssign; // needed due to https://github.com/rust-lang/rust/issues/69640 + + MulAssign + // needed due to https://github.com/rust-lang/rust/issues/69640 + + Group; /// The affine representation of an element in G2. type G2Affine: AffineCurve + From + Into - + Into; + + Into + + Group; /// A G2 element that has been preprocessed for use in a pairing. type G2Prepared: ToBytes + Default + Clone + Send + Sync + Debug + From; diff --git a/arkworks/algebra/ec/src/models/short_weierstrass_jacobian.rs b/arkworks/algebra/ec/src/models/short_weierstrass_jacobian.rs index ee4046df..77293f03 100644 --- a/arkworks/algebra/ec/src/models/short_weierstrass_jacobian.rs +++ b/arkworks/algebra/ec/src/models/short_weierstrass_jacobian.rs @@ -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"), @@ -87,8 +87,8 @@ impl GroupAffine

{ 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) -> GroupProjective

{ let mut res = GroupProjective::zero(); // Skip leading zeros. @@ -214,7 +214,9 @@ impl AffineCurve for GroupAffine

{ 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 } @@ -252,6 +254,63 @@ impl Neg for GroupAffine

{ } } +impl<'a, P: Parameters> Add<&'a Self> for GroupAffine

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

{ + fn add_assign(&mut self, other: Self) { + self.add_assign(other) + } +} + +impl Sub for GroupAffine

{ + 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

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

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

{ + fn sub_assign(&mut self, other: &'a Self) { + *self += &(-(*other)); + } +} + +impl MulAssign for GroupAffine

{ + fn mul_assign(&mut self, other: P::ScalarField) { + *self = self.mul(other.into_repr()).into() + } +} + +impl UniformRand for GroupAffine

{ + fn rand(rng: &mut R) -> Self { + todo!() + } +} + impl ToBytes for GroupAffine

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

{ } } -/// 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 Group for GroupAffine

{ + 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( @@ -395,7 +471,8 @@ impl GroupProjective

{ impl Zeroize for GroupProjective

{ 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(); @@ -439,12 +516,15 @@ impl ProjectiveCurve for GroupProjective

{ /// 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::>(); @@ -463,8 +543,8 @@ impl ProjectiveCurve for GroupProjective

{ } /// 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 { @@ -535,8 +615,8 @@ impl ProjectiveCurve for GroupProjective

{ } } - /// 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

) { if other.is_zero() {