Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@
- [\#430](https://github.com/arkworks-rs/algebra/pull/430) (`ark-ec`) Add functionality for mapping a field element to a curve element for hash-to-curve.
- [\#440](https://github.com/arkworks-rs/algebra/pull/440) (`ark-ff`) Add a method to construct a field element from an element of the underlying base prime field.
- [\#446](https://github.com/arkworks-rs/algebra/pull/446) (`ark-ff`) Add `CyclotomicMultSubgroup` trait and impl for extension fields
- [\#467](https://github.com/arkworks-rs/algebra/pull/467) (`ark-ec`)
- Move implementation of `serialize_with_mode()`, `deserialize_with_mode()`, and `serialized_size()` into `{SW,TE}CurveConfig` to allow customization.

### Improvements

Expand Down
71 changes: 8 additions & 63 deletions ec/src/models/short_weierstrass/affine.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use ark_serialize::{
CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize,
CanonicalSerializeWithFlags, Compress, SerializationError, Valid, Validate,
CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate,
};
use ark_std::{
borrow::Borrow,
Expand Down Expand Up @@ -125,7 +124,7 @@ impl<P: SWCurveConfig> Affine<P> {
///
/// The results are sorted by lexicographical order.
/// This means that, if `P::BaseField: PrimeField`, the results are sorted as integers.
fn get_ys_from_x_unchecked(x: P::BaseField) -> Option<(P::BaseField, P::BaseField)> {
pub fn get_ys_from_x_unchecked(x: P::BaseField) -> Option<(P::BaseField, P::BaseField)> {
Comment thread
alexander-zw marked this conversation as resolved.
// Compute the curve equation x^3 + Ax + B.
// Since Rust does not optimise away additions with zero, we explicitly check
// for that case here, and avoid multiplication by `a` if possible.
Expand Down Expand Up @@ -186,6 +185,7 @@ impl<P: SWCurveConfig> Zeroize for Affine<P> {
}

impl<P: SWCurveConfig> Distribution<Affine<P>> for Standard {
/// Generates a uniformly random instance of the curve.
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Affine<P> {
loop {
Expand Down Expand Up @@ -344,38 +344,18 @@ impl<P: SWCurveConfig> From<Projective<P>> for Affine<P> {
}

impl<P: SWCurveConfig> CanonicalSerialize for Affine<P> {
#[allow(unused_qualifications)]
Comment thread
alexander-zw marked this conversation as resolved.
#[inline]
fn serialize_with_mode<W: Write>(
&self,
mut writer: W,
Comment thread
alexander-zw marked this conversation as resolved.
writer: W,
compress: ark_serialize::Compress,
) -> Result<(), SerializationError> {
let (x, y, flags) = match self.infinity {
true => (
P::BaseField::zero(),
P::BaseField::zero(),
SWFlags::infinity(),
),
false => (self.x, self.y, self.to_flags()),
};

match compress {
Compress::Yes => x.serialize_with_flags(writer, flags),
Compress::No => {
x.serialize_with_mode(&mut writer, compress)?;
y.serialize_with_flags(&mut writer, flags)
},
}
P::serialize_with_mode(self, writer, compress)
}

#[inline]
fn serialized_size(&self, compress: Compress) -> usize {
let zero = P::BaseField::zero();
match compress {
Compress::Yes => zero.serialized_size_with_flags::<SWFlags>(),
Compress::No => zero.compressed_size() + zero.serialized_size_with_flags::<SWFlags>(),
}
P::serialized_size(compress)
}
}

Expand All @@ -390,47 +370,12 @@ impl<P: SWCurveConfig> Valid for Affine<P> {
}
Comment thread
alexander-zw marked this conversation as resolved.

impl<P: SWCurveConfig> CanonicalDeserialize for Affine<P> {
#[allow(unused_qualifications)]
fn deserialize_with_mode<R: Read>(
mut reader: R,
reader: R,
compress: Compress,
validate: Validate,
) -> Result<Self, SerializationError> {
let (x, y, flags) = match compress {
Compress::Yes => {
let (x, flags): (_, SWFlags) =
CanonicalDeserializeWithFlags::deserialize_with_flags(reader)?;
match flags {
SWFlags::PointAtInfinity => (Self::identity().x, Self::identity().y, flags),
_ => {
let is_positive = flags.is_positive().unwrap();
let (y, neg_y) = Self::get_ys_from_x_unchecked(x)
.ok_or(SerializationError::InvalidData)?;
if is_positive {
(x, y, flags)
} else {
(x, neg_y, flags)
}
},
}
},
Compress::No => {
let x: P::BaseField =
CanonicalDeserialize::deserialize_with_mode(&mut reader, compress, validate)?;
let (y, flags): (_, SWFlags) =
CanonicalDeserializeWithFlags::deserialize_with_flags(&mut reader)?;
(x, y, flags)
},
};
if flags.is_infinity() {
Ok(Self::identity())
} else {
let point = Self::new_unchecked(x, y);
if let Validate::Yes = validate {
point.check()?;
}
Ok(point)
}
P::deserialize_with_mode(reader, compress, validate)
}
}

Expand Down
10 changes: 4 additions & 6 deletions ec/src/models/short_weierstrass/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ impl<P: SWCurveConfig> Hash for Projective<P> {
}

impl<P: SWCurveConfig> Distribution<Projective<P>> for Standard {
/// Generates a uniformly random instance of the curve.
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Projective<P> {
loop {
Expand Down Expand Up @@ -504,21 +505,19 @@ impl<P: SWCurveConfig> From<Affine<P>> for Projective<P> {
}

impl<P: SWCurveConfig> CanonicalSerialize for Projective<P> {
#[allow(unused_qualifications)]
#[inline]
fn serialize_with_mode<W: Write>(
&self,
writer: W,
compress: Compress,
) -> Result<(), SerializationError> {
let aff = Affine::<P>::from(*self);
aff.serialize_with_mode(writer, compress)
P::serialize_with_mode(&aff, writer, compress)
}

#[inline]
fn serialized_size(&self, compress: Compress) -> usize {
let aff = Affine::<P>::from(*self);
aff.serialized_size(compress)
P::serialized_size(compress)
}
}

Expand All @@ -540,13 +539,12 @@ impl<P: SWCurveConfig> Valid for Projective<P> {
}

impl<P: SWCurveConfig> CanonicalDeserialize for Projective<P> {
#[allow(unused_qualifications)]
fn deserialize_with_mode<R: Read>(
reader: R,
compress: Compress,
validate: Validate,
) -> Result<Self, SerializationError> {
let aff = Affine::<P>::deserialize_with_mode(reader, compress, validate)?;
let aff = P::deserialize_with_mode(reader, compress, validate)?;
Ok(aff.into())
}
}
Expand Down
89 changes: 89 additions & 0 deletions ec/src/models/short_weierstrass/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
use ark_serialize::{
CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize,
CanonicalSerializeWithFlags, Compress, SerializationError, Valid, Validate,
};
use ark_std::io::{Read, Write};

use ark_ff::fields::Field;

use crate::{AffineRepr, Group};
Expand Down Expand Up @@ -98,4 +104,87 @@ pub trait SWCurveConfig: super::CurveConfig {

res
}

/// If uncompressed, serializes both x and y coordinates as well as a bit for whether it is
/// infinity. If compressed, serializes x coordinate with two bits to encode whether y is
/// positive, negative, or infinity.
#[inline]
fn serialize_with_mode<W: Write>(
item: &Affine<Self>,
mut writer: W,
compress: ark_serialize::Compress,
) -> Result<(), SerializationError> {
let (x, y, flags) = match item.infinity {
true => (
Self::BaseField::zero(),
Self::BaseField::zero(),
SWFlags::infinity(),
),
false => (item.x, item.y, item.to_flags()),
};

match compress {
Compress::Yes => x.serialize_with_flags(writer, flags),
Compress::No => {
x.serialize_with_mode(&mut writer, compress)?;
y.serialize_with_flags(&mut writer, flags)
},
}
}

/// If `validate` is `Yes`, calls `check()` to make sure the element is valid.
fn deserialize_with_mode<R: Read>(
mut reader: R,
compress: Compress,
validate: Validate,
) -> Result<Affine<Self>, SerializationError> {
let (x, y, flags) = match compress {
Compress::Yes => {
let (x, flags): (_, SWFlags) =
CanonicalDeserializeWithFlags::deserialize_with_flags(reader)?;
match flags {
SWFlags::PointAtInfinity => (
Affine::<Self>::identity().x,
Affine::<Self>::identity().y,
flags,
),
_ => {
let is_positive = flags.is_positive().unwrap();
let (y, neg_y) = Affine::<Self>::get_ys_from_x_unchecked(x)
.ok_or(SerializationError::InvalidData)?;
if is_positive {
(x, y, flags)
} else {
(x, neg_y, flags)
}
},
}
},
Compress::No => {
let x: Self::BaseField =
CanonicalDeserialize::deserialize_with_mode(&mut reader, compress, validate)?;
let (y, flags): (_, SWFlags) =
CanonicalDeserializeWithFlags::deserialize_with_flags(&mut reader)?;
(x, y, flags)
},
};
if flags.is_infinity() {
Ok(Affine::<Self>::identity())
} else {
let point = Affine::<Self>::new_unchecked(x, y);
if let Validate::Yes = validate {
point.check()?;
}
Ok(point)
}
}

#[inline]
fn serialized_size(compress: Compress) -> usize {
let zero = Self::BaseField::zero();
match compress {
Compress::Yes => zero.serialized_size_with_flags::<SWFlags>(),
Compress::No => zero.compressed_size() + zero.serialized_size_with_flags::<SWFlags>(),
}
}
}
49 changes: 7 additions & 42 deletions ec/src/models/twisted_edwards/affine.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use ark_serialize::{
CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize,
CanonicalSerializeWithFlags, Compress, SerializationError, Valid, Validate,
CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate,
};
use ark_std::{
borrow::Borrow,
Expand Down Expand Up @@ -260,6 +259,7 @@ impl<P: TECurveConfig> Default for Affine<P> {
}

impl<P: TECurveConfig> Distribution<Affine<P>> for Standard {
/// Generates a uniformly random instance of the curve.
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Affine<P> {
loop {
Expand Down Expand Up @@ -301,30 +301,18 @@ impl<P: TECurveConfig> From<Projective<P>> for Affine<P> {
}
}
impl<P: TECurveConfig> CanonicalSerialize for Affine<P> {
#[allow(unused_qualifications)]
#[inline]
fn serialize_with_mode<W: Write>(
&self,
mut writer: W,
writer: W,
compress: ark_serialize::Compress,
) -> Result<(), SerializationError> {
let flags = TEFlags::from_x_coordinate(self.x);
match compress {
Compress::Yes => self.y.serialize_with_flags(writer, flags),
Compress::No => {
self.x.serialize_uncompressed(&mut writer)?;
self.y.serialize_uncompressed(&mut writer)
},
}
P::serialize_with_mode(self, writer, compress)
}

#[inline]
fn serialized_size(&self, compress: Compress) -> usize {
let zero = P::BaseField::zero();
match compress {
Compress::Yes => zero.serialized_size_with_flags::<TEFlags>(),
Compress::No => self.x.uncompressed_size() + self.y.uncompressed_size(),
}
P::serialized_size(compress)
}
}

Expand All @@ -339,35 +327,12 @@ impl<P: TECurveConfig> Valid for Affine<P> {
}

impl<P: TECurveConfig> CanonicalDeserialize for Affine<P> {
#[allow(unused_qualifications)]
fn deserialize_with_mode<R: Read>(
mut reader: R,
reader: R,
compress: Compress,
validate: Validate,
) -> Result<Self, SerializationError> {
let (x, y) = match compress {
Compress::Yes => {
let (y, flags): (_, TEFlags) =
CanonicalDeserializeWithFlags::deserialize_with_flags(reader)?;
let (x, neg_x) =
Self::get_xs_from_y_unchecked(y).ok_or(SerializationError::InvalidData)?;
if flags.is_negative() {
(neg_x, y)
} else {
(x, y)
}
},
Compress::No => {
let x: P::BaseField = CanonicalDeserialize::deserialize_uncompressed(&mut reader)?;
let y: P::BaseField = CanonicalDeserialize::deserialize_uncompressed(&mut reader)?;
(x, y)
},
};
let point = Self::new_unchecked(x, y);
if let Validate::Yes = validate {
point.check()?;
}
Ok(point)
P::deserialize_with_mode(reader, compress, validate)
}
}

Expand Down
8 changes: 4 additions & 4 deletions ec/src/models/twisted_edwards/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ impl<P: TECurveConfig> Hash for Projective<P> {
}

impl<P: TECurveConfig> Distribution<Projective<P>> for Standard {
/// Generates a uniformly random instance of the curve.
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Projective<P> {
loop {
Expand Down Expand Up @@ -430,13 +431,12 @@ impl<P: TECurveConfig> CanonicalSerialize for Projective<P> {
compress: Compress,
) -> Result<(), SerializationError> {
let aff = Affine::<P>::from(*self);
aff.serialize_with_mode(writer, compress)
P::serialize_with_mode(&aff, writer, compress)
}

#[inline]
fn serialized_size(&self, compress: Compress) -> usize {
let aff = Affine::<P>::from(*self);
aff.serialized_size(compress)
P::serialized_size(compress)
}
}

Expand Down Expand Up @@ -464,7 +464,7 @@ impl<P: TECurveConfig> CanonicalDeserialize for Projective<P> {
compress: Compress,
validate: Validate,
) -> Result<Self, SerializationError> {
let aff = Affine::<P>::deserialize_with_mode(reader, compress, validate)?;
let aff = P::deserialize_with_mode(reader, compress, validate)?;
Ok(aff.into())
}
}
Expand Down
Loading