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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
- #126 (ark-ec) Use `ark_ff::batch_inversion` for point normalization
- #131, #137 (ark-ff) Speedup `sqrt` on fields when a square root exists. (And slows it down when doesn't exist)
- #141 (ark-ff) Add `Fp64`
- #144 (ark-poly) Add serialization for polynomials and evaluations

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is a breaking change, can you move it to the relevant section. (Its added a serialization trait bound to all polynomials)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the polynomial implementations in this repo have now implemented the serialization. I assume there is another project also using polynomial?

@ValarDragon ValarDragon Dec 18, 2020

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDK if there exists another project that implements polynomial, but if they did their implementation is now broken
Having all the reasons your code may be broken after an upgrade is really useful though

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also could the ark-poly readme be updated for this change (https://github.com/arkworks-rs/algebra/tree/master/poly)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the way


### Bug fixes
- #36 (ark-ec) In Short-Weierstrass curves, include an infinity bit in `ToConstraintField`.
Expand Down
123 changes: 122 additions & 1 deletion poly/src/domain/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ use crate::domain::{
DomainCoeff, EvaluationDomain, MixedRadixEvaluationDomain, Radix2EvaluationDomain,
};
use ark_ff::{FftField, FftParameters};
use ark_std::vec::Vec;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SerializationError};
use ark_std::{
io::{Read, Write},
vec::Vec,
};

/// Defines a domain over which finite field (I)FFTs can be performed.
/// Generally tries to build a radix-2 domain and falls back to a mixed-radix
Expand All @@ -33,6 +37,123 @@ macro_rules! map {
}
}

impl<F: FftField> CanonicalSerialize for GeneralEvaluationDomain<F> {
fn serialize<W: Write>(&self, mut writer: W) -> Result<(), SerializationError> {
let type_id = match self {
GeneralEvaluationDomain::Radix2(_) => 0u8,
GeneralEvaluationDomain::MixedRadix(_) => 1u8,
};
type_id.serialize(&mut writer)?;

match self {
GeneralEvaluationDomain::Radix2(d) => d.serialize(&mut writer),

@ValarDragon ValarDragon Dec 18, 2020

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we instead add a serialization method on the underlying domains, instead of serializing the degree directly?

Feels to weird to only have the general evaluation domain have serialize, and not the underlying domains

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh I see the underlying methods the d here is domain, not degree. Can the variable be changed throughout the file to be domain instead of d

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I can do the change. I also have implemented the serialization for domains.

The serialization of domains is needed to serialize the evaluations.

GeneralEvaluationDomain::MixedRadix(d) => d.serialize(&mut writer),
}
}

fn serialized_size(&self) -> usize {
let type_id = match self {
GeneralEvaluationDomain::Radix2(_) => 0u8,
GeneralEvaluationDomain::MixedRadix(_) => 1u8,
};

type_id.serialized_size()
+ match self {
GeneralEvaluationDomain::Radix2(d) => d.serialized_size(),
GeneralEvaluationDomain::MixedRadix(d) => d.serialized_size(),
}
}

fn serialize_uncompressed<W: Write>(&self, mut writer: W) -> Result<(), SerializationError> {
let type_id = match self {
GeneralEvaluationDomain::Radix2(_) => 0u8,
GeneralEvaluationDomain::MixedRadix(_) => 1u8,
};
type_id.serialize_uncompressed(&mut writer)?;

match self {
GeneralEvaluationDomain::Radix2(d) => d.serialize_uncompressed(&mut writer),
GeneralEvaluationDomain::MixedRadix(d) => d.serialize_uncompressed(&mut writer),
}
}

fn serialize_unchecked<W: Write>(&self, mut writer: W) -> Result<(), SerializationError> {
let type_id = match self {
GeneralEvaluationDomain::Radix2(_) => 0u8,
GeneralEvaluationDomain::MixedRadix(_) => 1u8,
};
type_id.serialize_unchecked(&mut writer)?;

match self {
GeneralEvaluationDomain::Radix2(d) => d.serialize_unchecked(&mut writer),
GeneralEvaluationDomain::MixedRadix(d) => d.serialize_unchecked(&mut writer),
}
}

fn uncompressed_size(&self) -> usize {
let type_id = match self {
GeneralEvaluationDomain::Radix2(_) => 0u8,
GeneralEvaluationDomain::MixedRadix(_) => 1u8,
};

type_id.uncompressed_size()
+ match self {
GeneralEvaluationDomain::Radix2(d) => d.uncompressed_size(),
GeneralEvaluationDomain::MixedRadix(d) => d.uncompressed_size(),
}
}
}

impl<F: FftField> CanonicalDeserialize for GeneralEvaluationDomain<F> {
fn deserialize<R: Read>(mut reader: R) -> Result<Self, SerializationError> {
let type_id = u8::deserialize(&mut reader)?;

if type_id == 0u8 {
Ok(Self::Radix2(Radix2EvaluationDomain::<F>::deserialize(
&mut reader,
)?))
} else if type_id == 1u8 {
Ok(Self::MixedRadix(
MixedRadixEvaluationDomain::<F>::deserialize(&mut reader)?,
))
} else {
Err(SerializationError::InvalidData)
}
}

fn deserialize_uncompressed<R: Read>(mut reader: R) -> Result<Self, SerializationError> {
let type_id = u8::deserialize_uncompressed(&mut reader)?;

if type_id == 0u8 {
Ok(Self::Radix2(
Radix2EvaluationDomain::<F>::deserialize_uncompressed(&mut reader)?,
))
} else if type_id == 1u8 {
Ok(Self::MixedRadix(
MixedRadixEvaluationDomain::<F>::deserialize_uncompressed(&mut reader)?,
))
} else {
Err(SerializationError::InvalidData)
}
}

fn deserialize_unchecked<R: Read>(mut reader: R) -> Result<Self, SerializationError> {
let type_id = u8::deserialize_unchecked(&mut reader)?;

if type_id == 0u8 {
Ok(Self::Radix2(
Radix2EvaluationDomain::<F>::deserialize_unchecked(&mut reader)?,
))
} else if type_id == 1u8 {
Ok(Self::MixedRadix(
MixedRadixEvaluationDomain::<F>::deserialize_unchecked(&mut reader)?,
))
} else {
Err(SerializationError::InvalidData)
}
}
}

impl<F: FftField> EvaluationDomain<F> for GeneralEvaluationDomain<F> {
type Elements = GeneralElements<F>;

Expand Down
11 changes: 9 additions & 2 deletions poly/src/domain/mixed_radix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,21 @@ use crate::domain::{
DomainCoeff, EvaluationDomain,
};
use ark_ff::{fields::utils::k_adicity, FftField, FftParameters};
use ark_std::{cmp::min, convert::TryFrom, fmt, vec::Vec};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SerializationError};
use ark_std::{
cmp::min,
convert::TryFrom,
fmt,
io::{Read, Write},
vec::Vec,
};
#[cfg(feature = "parallel")]
use rayon::prelude::*;

/// Defines a domain over which finite field (I)FFTs can be performed. Works
/// only for fields that have a multiplicative subgroup of size that is
/// a power-of-2 and another small subgroup over a different base defined.
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
#[derive(Copy, Clone, Hash, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
pub struct MixedRadixEvaluationDomain<F: FftField> {
/// The size of the domain.
pub size: u64,
Expand Down
3 changes: 2 additions & 1 deletion poly/src/domain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//! polynomial arithmetic is performed.

use ark_ff::FftField;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::{fmt, hash, vec::Vec};
use rand::Rng;

Expand All @@ -30,7 +31,7 @@ pub use radix2::Radix2EvaluationDomain;
/// subgroup. For efficiency, we recommend that the field has at least one large
/// subgroup generated by a root of unity.
pub trait EvaluationDomain<F: FftField>:
Copy + Clone + hash::Hash + Eq + PartialEq + fmt::Debug
Copy + Clone + hash::Hash + Eq + PartialEq + fmt::Debug + CanonicalSerialize + CanonicalDeserialize
{
/// The type of the elements iterator.
type Elements: Iterator<Item = F> + Sized;
Expand Down
10 changes: 8 additions & 2 deletions poly/src/domain/radix2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,21 @@ use crate::domain::{
DomainCoeff, EvaluationDomain,
};
use ark_ff::{FftField, FftParameters};
use ark_std::{convert::TryFrom, fmt, vec::Vec};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SerializationError};
use ark_std::{
convert::TryFrom,
fmt,
io::{Read, Write},
vec::Vec,
};

#[cfg(feature = "parallel")]
use rayon::prelude::*;

/// Defines a domain over which finite field (I)FFTs can be performed. Works
/// only for fields that have a large multiplicative subgroup of size that is
/// a power-of-2.
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
#[derive(Copy, Clone, Hash, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
pub struct Radix2EvaluationDomain<F: FftField> {
/// The size of the domain.
pub size: u64,
Expand Down
4 changes: 3 additions & 1 deletion poly/src/evaluations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
use crate::univariate::DensePolynomial;
use crate::{EvaluationDomain, GeneralEvaluationDomain, UVPolynomial};
use ark_ff::{batch_inversion, FftField};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SerializationError};
use ark_std::{
io::{Read, Write},
ops::{Add, AddAssign, Div, DivAssign, Index, Mul, MulAssign, Sub, SubAssign},
vec::Vec,
};
Expand All @@ -12,7 +14,7 @@ use ark_std::{
use rayon::prelude::*;

/// Stores a polynomial in evaluation form.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
#[derive(Clone, PartialEq, Eq, Hash, Debug, CanonicalSerialize, CanonicalDeserialize)]
pub struct Evaluations<F: FftField, D: EvaluationDomain<F> = GeneralEvaluationDomain<F>> {
/// The evaluations of a polynomial over the domain `D`
pub evals: Vec<F>,
Expand Down
6 changes: 3 additions & 3 deletions poly/src/polynomial/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ pub trait Polynomial<F: Field>:
+ Add
+ Neg
+ Zero
+ CanonicalSerialize
+ CanonicalDeserialize
+ for<'a> AddAssign<&'a Self>
+ for<'a> AddAssign<(F, &'a Self)>
+ for<'a> SubAssign<&'a Self>
Expand All @@ -38,9 +40,7 @@ pub trait Polynomial<F: Field>:
}

/// Describes the interface for univariate polynomials
pub trait UVPolynomial<F: Field>:
Polynomial<F, Point = F> + CanonicalSerialize + CanonicalDeserialize
{
pub trait UVPolynomial<F: Field>: Polynomial<F, Point = F> {
/// Constructs a new polynomial from a list of coefficients.
fn from_coefficients_slice(coeffs: &[F]) -> Self;

Expand Down
8 changes: 7 additions & 1 deletion poly/src/polynomial/multivariate/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
//! Work with sparse multivariate polynomials.
use ark_ff::Field;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SerializationError};
use ark_std::{
cmp::Ordering,
fmt::{Debug, Error, Formatter},
hash::Hash,
io::{Read, Write},
ops::Deref,
vec::Vec,
};
Expand All @@ -27,6 +29,8 @@ pub trait Term:
+ Deref<Target = [(usize, usize)]>
+ Send
+ Sync
+ CanonicalSerialize
+ CanonicalDeserialize
{
/// Create a new `Term` from a list of tuples of the form `(variable, power)`
fn new(term: Vec<(usize, usize)>) -> Self;
Expand All @@ -49,7 +53,9 @@ pub trait Term:

/// Stores a term (monomial) in a multivariate polynomial.
/// Each element is of the form `(variable, power)`.
#[derive(Clone, PartialOrd, PartialEq, Eq, Hash, Default)]
#[derive(
Clone, PartialOrd, PartialEq, Eq, Hash, Default, CanonicalSerialize, CanonicalDeserialize,
)]
pub struct SparseTerm(Vec<(usize, usize)>);

impl SparseTerm {
Expand Down
4 changes: 3 additions & 1 deletion poly/src/polynomial/multivariate/sparse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ use crate::{
MVPolynomial, Polynomial,
};
use ark_ff::{Field, Zero};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SerializationError};
use ark_std::{
cmp::Ordering,
fmt,
io::{Read, Write},
ops::{Add, AddAssign, Neg, Sub, SubAssign},
vec::Vec,
};
Expand All @@ -16,7 +18,7 @@ use rand::Rng;
use rayon::prelude::*;

/// Stores a sparse multivariate polynomial in coefficient form.
#[derive(Derivative)]
#[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)]
#[derivative(Clone, PartialEq, Eq, Hash, Default)]
pub struct SparsePolynomial<F: Field, T: Term> {
/// The number of variables the polynomial supports
Expand Down
4 changes: 3 additions & 1 deletion poly/src/polynomial/univariate/sparse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ use crate::polynomial::Polynomial;
use crate::univariate::{DenseOrSparsePolynomial, DensePolynomial};
use crate::{EvaluationDomain, Evaluations, UVPolynomial};
use ark_ff::{FftField, Field, Zero};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SerializationError};
use ark_std::{
collections::BTreeMap,
fmt,
io::{Read, Write},
ops::{Add, AddAssign, Neg, SubAssign},
vec::Vec,
};

/// Stores a sparse polynomial in coefficient form.
#[derive(Clone, PartialEq, Eq, Hash, Default)]
#[derive(Clone, PartialEq, Eq, Hash, Default, CanonicalSerialize, CanonicalDeserialize)]
pub struct SparsePolynomial<F: Field> {
/// The coefficient a_i of `x^i` is stored as (i, a_i) in `self.coeffs`.
/// the entries in `self.coeffs` *must* be sorted in increasing order of
Expand Down