Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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