diff --git a/ec/src/models/short_weierstrass/affine.rs b/ec/src/models/short_weierstrass/affine.rs index b1340de3a..78cc834a0 100644 --- a/ec/src/models/short_weierstrass/affine.rs +++ b/ec/src/models/short_weierstrass/affine.rs @@ -343,7 +343,7 @@ impl From> for Affine

{ } } -impl CanonicalSerialize for Affine

{ +impl CanonicalSerializeInner for Affine

{ #[inline] fn serialize_with_mode( &self, @@ -359,6 +359,8 @@ impl CanonicalSerialize for Affine

{ } } +impl CanonicalSerialize for Affine

{} + impl Valid for Affine

{ fn check(&self) -> Result<(), SerializationError> { if self.is_on_curve() && self.is_in_correct_subgroup_assuming_on_curve() { diff --git a/ec/src/models/short_weierstrass/group.rs b/ec/src/models/short_weierstrass/group.rs index 84dfc71d3..d8f771122 100644 --- a/ec/src/models/short_weierstrass/group.rs +++ b/ec/src/models/short_weierstrass/group.rs @@ -571,7 +571,7 @@ impl From> for Projective

{ } } -impl CanonicalSerialize for Projective

{ +impl CanonicalSerializeInner for Projective

{ #[inline] fn serialize_with_mode( &self, @@ -588,6 +588,8 @@ impl CanonicalSerialize for Projective

{ } } +impl CanonicalSerialize for Projective

{} + impl Valid for Projective

{ fn check(&self) -> Result<(), SerializationError> { self.into_affine().check() diff --git a/ec/src/models/twisted_edwards/affine.rs b/ec/src/models/twisted_edwards/affine.rs index a6c908e31..ce270b728 100644 --- a/ec/src/models/twisted_edwards/affine.rs +++ b/ec/src/models/twisted_edwards/affine.rs @@ -300,7 +300,7 @@ impl From> for Affine

{ } } } -impl CanonicalSerialize for Affine

{ +impl CanonicalSerializeInner for Affine

{ #[inline] fn serialize_with_mode( &self, @@ -316,6 +316,8 @@ impl CanonicalSerialize for Affine

{ } } +impl CanonicalSerialize for Affine

{} + impl Valid for Affine

{ fn check(&self) -> Result<(), SerializationError> { if self.is_on_curve() && self.is_in_correct_subgroup_assuming_on_curve() { diff --git a/ec/src/models/twisted_edwards/group.rs b/ec/src/models/twisted_edwards/group.rs index 14eab0ffe..38d7e96fe 100644 --- a/ec/src/models/twisted_edwards/group.rs +++ b/ec/src/models/twisted_edwards/group.rs @@ -422,7 +422,7 @@ impl MontgomeryAffine

{ } } -impl CanonicalSerialize for Projective

{ +impl CanonicalSerializeInner for Projective

{ #[allow(unused_qualifications)] #[inline] fn serialize_with_mode( @@ -440,6 +440,8 @@ impl CanonicalSerialize for Projective

{ } } +impl CanonicalSerialize for Projective

{} + impl Valid for Projective

{ fn check(&self) -> Result<(), SerializationError> { self.into_affine().check() diff --git a/ec/src/pairing.rs b/ec/src/pairing.rs index 8b2623b3f..3b96b9a2f 100644 --- a/ec/src/pairing.rs +++ b/ec/src/pairing.rs @@ -133,7 +133,7 @@ pub trait Pairing: Sized + 'static + Copy + Debug + Sync + Send + Eq { #[must_use] pub struct PairingOutput(pub P::TargetField); -impl CanonicalSerialize for PairingOutput

{ +impl CanonicalSerializeInner for PairingOutput

{ #[allow(unused_qualifications)] #[inline] fn serialize_with_mode( @@ -150,6 +150,8 @@ impl CanonicalSerialize for PairingOutput

{ } } +impl CanonicalSerialize for PairingOutput

{} + impl Valid for PairingOutput

{ fn check(&self) -> Result<(), SerializationError> { if self.0.pow(&P::ScalarField::characteristic()).is_one() { diff --git a/ff/Cargo.toml b/ff/Cargo.toml index ad54c81fa..4114b1c27 100644 --- a/ff/Cargo.toml +++ b/ff/Cargo.toml @@ -22,6 +22,7 @@ derivative = { version = "2", features = ["use_core"] } num-traits = { version = "0.2", default-features = false } paste = "1.0" rayon = { version = "1", optional = true } +serde = { version = "1.0", optional = true, features = ["derive"] } zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] } num-bigint = { version = "0.4", default-features = false } digest = { version = "0.10", default-features = false, features = ["alloc"] } @@ -46,7 +47,7 @@ default = [] std = [ "ark-std/std", "ark-serialize/std", "itertools/use_std" ] parallel = [ "std", "rayon", "ark-std/parallel" ] asm = [] - +serde = [ "dep:serde", "ark-serialize/serde" ] [package.metadata.docs.rs] rustdoc-args = ["--html-in-header", "../doc/katex-header.html"] diff --git a/ff/src/biginteger/mod.rs b/ff/src/biginteger/mod.rs index 19aa582e2..0de0d285f 100644 --- a/ff/src/biginteger/mod.rs +++ b/ff/src/biginteger/mod.rs @@ -5,7 +5,8 @@ use crate::{ #[allow(unused)] use ark_ff_macros::unroll_for_loops; use ark_serialize::{ - CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate, + CanonicalDeserialize, CanonicalSerialize, CanonicalSerializeInner, Compress, + SerializationError, Valid, Validate, }; use ark_std::{ convert::TryFrom, @@ -23,8 +24,73 @@ use zeroize::Zeroize; #[macro_use] pub mod arithmetic; +/// This is a hack to make serialization of BigInt work below. +#[cfg(feature = "serde")] +mod arrays { + use ark_std::vec::Vec; + use ark_std::{convert::TryInto, marker::PhantomData}; + + use serde::{ + de::{SeqAccess, Visitor}, + ser::SerializeTuple, + Deserialize, Deserializer, Serialize, Serializer, + }; + pub fn serialize( + data: &[T; N], + ser: S, + ) -> Result { + let mut s = ser.serialize_tuple(N)?; + for item in data { + s.serialize_element(item)?; + } + s.end() + } + + struct ArrayVisitor(PhantomData); + + impl<'de, T, const N: usize> Visitor<'de> for ArrayVisitor + where + T: Deserialize<'de>, + { + type Value = [T; N]; + + fn expecting(&self, formatter: &mut ark_std::fmt::Formatter<'_>) -> ark_std::fmt::Result { + formatter.write_str(&format!("an array of length {}", N)) + } + + #[inline] + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + // can be optimized using MaybeUninit + let mut data = Vec::with_capacity(N); + for _ in 0..N { + match (seq.next_element())? { + Some(val) => data.push(val), + None => return Err(serde::de::Error::invalid_length(N, &self)), + } + } + match data.try_into() { + Ok(arr) => Ok(arr), + Err(_) => unreachable!(), + } + } + } + pub fn deserialize<'de, D, T, const N: usize>(deserializer: D) -> Result<[T; N], D::Error> + where + D: Deserializer<'de>, + T: Deserialize<'de>, + { + deserializer.deserialize_tuple(N, ArrayVisitor::(PhantomData)) + } +} + #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Zeroize)] -pub struct BigInt(pub [u64; N]); +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct BigInt( + #[cfg_attr(feature = "serde", serde(with = "arrays"))] pub [u64; N], +); impl Default for BigInt { fn default() -> Self { @@ -32,7 +98,7 @@ impl Default for BigInt { } } -impl CanonicalSerialize for BigInt { +impl CanonicalSerializeInner for BigInt { fn serialize_with_mode( &self, writer: W, @@ -46,6 +112,8 @@ impl CanonicalSerialize for BigInt { } } +impl CanonicalSerialize for BigInt {} + impl Valid for BigInt { fn check(&self) -> Result<(), SerializationError> { self.0.check() diff --git a/ff/src/fields/models/cubic_extension.rs b/ff/src/fields/models/cubic_extension.rs index 3f9a3f669..6db4d5385 100644 --- a/ff/src/fields/models/cubic_extension.rs +++ b/ff/src/fields/models/cubic_extension.rs @@ -1,6 +1,7 @@ use ark_serialize::{ CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize, - CanonicalSerializeWithFlags, Compress, EmptyFlags, Flags, SerializationError, Valid, Validate, + CanonicalSerializeInner, CanonicalSerializeWithFlags, Compress, EmptyFlags, Flags, + SerializationError, Valid, Validate, }; use ark_std::{ cmp::{Ord, Ordering, PartialOrd}, @@ -78,6 +79,7 @@ pub trait CubicExtConfig: 'static + Send + Sync + Sized { /// An element of a cubic extension field F_p\[X\]/(X^3 - P::NONRESIDUE) is /// represented as c0 + c1 * X + c2 * X^2, for c0, c1, c2 in `P::BaseField`. +#[cfg_attr(feature = "serde", serde::Serialize, serde::Deserialize)] #[derive(Derivative)] #[derivative( Default(bound = "P: CubicExtConfig"), @@ -624,7 +626,7 @@ impl CanonicalSerializeWithFlags for CubicExtField

{ } } -impl CanonicalSerialize for CubicExtField

{ +impl CanonicalSerializeInner for CubicExtField

{ #[inline] fn serialize_with_mode( &self, @@ -640,6 +642,8 @@ impl CanonicalSerialize for CubicExtField

{ } } +impl CanonicalSerialize for CubicExtField

{} + impl CanonicalDeserializeWithFlags for CubicExtField

{ #[inline] fn deserialize_with_flags( diff --git a/ff/src/fields/models/fp/mod.rs b/ff/src/fields/models/fp/mod.rs index bd776a212..f614c5dbf 100644 --- a/ff/src/fields/models/fp/mod.rs +++ b/ff/src/fields/models/fp/mod.rs @@ -2,7 +2,8 @@ use core::iter; use ark_serialize::{ buffer_byte_size, CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize, - CanonicalSerializeWithFlags, Compress, EmptyFlags, Flags, SerializationError, Valid, Validate, + CanonicalSerializeInner, CanonicalSerializeWithFlags, Compress, EmptyFlags, Flags, + SerializationError, Valid, Validate, }; use ark_std::{ cmp::{Ord, Ordering, PartialOrd}, @@ -100,6 +101,7 @@ pub trait FpConfig: Send + Sync + 'static + Sized { /// Represents an element of the prime field F_p, where `p == P::MODULUS`. /// This type can represent elements in any field of size at most N * 64 bits. +#[cfg_attr(feature = "serde", serde::Serialize, serde::Deserialize)] #[derive(Derivative)] #[derivative( Default(bound = ""), @@ -567,7 +569,7 @@ impl, const N: usize> CanonicalSerializeWithFlags for Fp { } } -impl, const N: usize> CanonicalSerialize for Fp { +impl, const N: usize> CanonicalSerializeInner for Fp { #[inline] fn serialize_with_mode( &self, @@ -583,6 +585,8 @@ impl, const N: usize> CanonicalSerialize for Fp { } } +impl, const N: usize> CanonicalSerialize for Fp {} + impl, const N: usize> CanonicalDeserializeWithFlags for Fp { fn deserialize_with_flags( reader: R, diff --git a/ff/src/fields/models/quadratic_extension.rs b/ff/src/fields/models/quadratic_extension.rs index 49e1eaa69..338d03da5 100644 --- a/ff/src/fields/models/quadratic_extension.rs +++ b/ff/src/fields/models/quadratic_extension.rs @@ -1,6 +1,7 @@ use ark_serialize::{ CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize, - CanonicalSerializeWithFlags, Compress, EmptyFlags, Flags, SerializationError, Valid, Validate, + CanonicalSerializeInner, CanonicalSerializeWithFlags, Compress, EmptyFlags, Flags, + SerializationError, Valid, Validate, }; use ark_std::{ cmp::{Ord, Ordering, PartialOrd}, @@ -93,6 +94,7 @@ pub trait QuadExtConfig: 'static + Send + Sync + Sized { /// An element of a quadratic extension field F_p\[X\]/(X^2 - P::NONRESIDUE) is /// represented as c0 + c1 * X, for c0, c1 in `P::BaseField`. +#[cfg_attr(feature = "serde", serde::Serialize, serde::Deserialize)] #[derive(Derivative)] #[derivative( Default(bound = "P: QuadExtConfig"), @@ -702,7 +704,7 @@ impl CanonicalSerializeWithFlags for QuadExtField

{ } } -impl CanonicalSerialize for QuadExtField

{ +impl CanonicalSerializeInner for QuadExtField

{ #[inline] fn serialize_with_mode( &self, @@ -718,6 +720,8 @@ impl CanonicalSerialize for QuadExtField

{ } } +impl CanonicalSerialize for QuadExtField

{} + impl CanonicalDeserializeWithFlags for QuadExtField

{ #[inline] fn deserialize_with_flags( diff --git a/poly/src/domain/general.rs b/poly/src/domain/general.rs index b58aefd5e..970a52cb6 100644 --- a/poly/src/domain/general.rs +++ b/poly/src/domain/general.rs @@ -12,7 +12,8 @@ use crate::domain::{ }; use ark_ff::FftField; use ark_serialize::{ - CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate, + CanonicalDeserialize, CanonicalSerialize, CanonicalSerializeInner, Compress, + SerializationError, Valid, Validate, }; use ark_std::{ io::{Read, Write}, @@ -39,7 +40,7 @@ macro_rules! map { } } -impl CanonicalSerialize for GeneralEvaluationDomain { +impl CanonicalSerializeInner for GeneralEvaluationDomain { fn serialize_with_mode( &self, mut writer: W, @@ -75,6 +76,8 @@ impl CanonicalSerialize for GeneralEvaluationDomain { } } +impl CanonicalSerialize for GeneralEvaluationDomain {} + impl Valid for GeneralEvaluationDomain { fn check(&self) -> Result<(), SerializationError> { Ok(()) diff --git a/serialize-derive/src/serialize.rs b/serialize-derive/src/serialize.rs index bb82e16fe..7494fc697 100644 --- a/serialize-derive/src/serialize.rs +++ b/serialize-derive/src/serialize.rs @@ -50,7 +50,7 @@ pub(super) fn impl_canonical_serialize(ast: &syn::DeriveInput) -> TokenStream { data_struct.fields.len() } else { panic!( - "`CanonicalSerialize` can only be derived for structs, {} is not a struct", + "`CanonicalSerializeInner` can only be derived for structs, {} is not a struct", name ); }; @@ -90,7 +90,7 @@ pub(super) fn impl_canonical_serialize(ast: &syn::DeriveInput) -> TokenStream { }; let gen = quote! { - impl #impl_generics ark_serialize::CanonicalSerialize for #name #ty_generics #where_clause { + impl #impl_generics ark_serialize::CanonicalSerializeInner for #name #ty_generics #where_clause { #[allow(unused_mut, unused_variables)] fn serialize_with_mode(&self, mut writer: W, compress: ark_serialize::Compress) -> Result<(), ark_serialize::SerializationError> { #(#serialize_body)* @@ -104,5 +104,8 @@ pub(super) fn impl_canonical_serialize(ast: &syn::DeriveInput) -> TokenStream { } } }; - gen + + let gen2 = quote! { impl #impl_generics ark_serialize::CanonicalSerialize for #name #ty_generics #where_clause {} }; + + quote! { #gen #gen2 } } diff --git a/serialize/Cargo.toml b/serialize/Cargo.toml index d57aac57a..2a275a1b4 100644 --- a/serialize/Cargo.toml +++ b/serialize/Cargo.toml @@ -17,6 +17,7 @@ rust-version = "1.56" ark-serialize-derive = { version = "^0.3.0", path = "../serialize-derive", optional = true } ark-std = { version = "^0.3.0", default-features = false } digest = { version = "0.10", default-features = false } +serde = { version = "1.0", optional = true, features = ["derive"] } [dev-dependencies] sha2 = { version = "0.10", default-features = false} @@ -27,3 +28,4 @@ blake2 = { version = "0.10", default-features = false} default = [] std = [ "ark-std/std", ] derive = [ "ark-serialize-derive" ] +serde = [ "dep:serde" ] diff --git a/serialize/src/impls.rs b/serialize/src/impls.rs index 1457097d4..ee55343ef 100644 --- a/serialize/src/impls.rs +++ b/serialize/src/impls.rs @@ -16,7 +16,7 @@ impl Valid for bool { } } -impl CanonicalSerialize for bool { +impl CanonicalSerializeInner for bool { #[inline] fn serialize_with_mode( &self, @@ -33,6 +33,8 @@ impl CanonicalSerialize for bool { } } +impl CanonicalSerialize for bool {} + impl CanonicalDeserialize for bool { #[inline] fn deserialize_with_mode( @@ -50,7 +52,7 @@ impl CanonicalDeserialize for bool { macro_rules! impl_uint { ($type:ty) => { - impl CanonicalSerialize for $type { + impl CanonicalSerializeInner for $type { #[inline] fn serialize_with_mode( &self, @@ -66,6 +68,8 @@ macro_rules! impl_uint { } } + impl CanonicalSerialize for $type {} + impl Valid for $type { #[inline] fn check(&self) -> Result<(), SerializationError> { @@ -103,7 +107,7 @@ impl_uint!(u16); impl_uint!(u32); impl_uint!(u64); -impl CanonicalSerialize for usize { +impl CanonicalSerializeInner for usize { #[inline] fn serialize_with_mode( &self, @@ -119,6 +123,8 @@ impl CanonicalSerialize for usize { } } +impl CanonicalSerialize for usize {} + impl Valid for usize { #[inline] fn check(&self) -> Result<(), SerializationError> { @@ -147,7 +153,7 @@ impl CanonicalDeserialize for usize { } } -impl CanonicalSerialize for Option { +impl CanonicalSerializeInner for Option { #[inline] fn serialize_with_mode( &self, @@ -210,7 +216,7 @@ impl CanonicalDeserialize for Option { } // No-op -impl CanonicalSerialize for PhantomData { +impl CanonicalSerializeInner for PhantomData { #[inline] fn serialize_with_mode( &self, @@ -244,7 +250,7 @@ impl CanonicalDeserialize for PhantomData { } } -impl CanonicalSerialize for Rc { +impl CanonicalSerializeInner for Rc { #[inline] fn serialize_with_mode( &self, @@ -261,7 +267,7 @@ impl CanonicalSerialize for Rc { } #[cfg(feature = "std")] -impl CanonicalSerialize for ark_std::sync::Arc { +impl CanonicalSerializeInner for ark_std::sync::Arc { #[inline] fn serialize_with_mode( &self, @@ -312,7 +318,7 @@ impl CanonicalDeserialize } } -impl<'a, T: CanonicalSerialize + ToOwned> CanonicalSerialize for Cow<'a, T> { +impl<'a, T: CanonicalSerialize + ToOwned> CanonicalSerializeInner for Cow<'a, T> { #[inline] fn serialize_with_mode( &self, @@ -368,7 +374,7 @@ where } } -impl CanonicalSerialize for [T; N] { +impl CanonicalSerializeInner for [T; N] { #[inline] fn serialize_with_mode( &self, @@ -422,7 +428,7 @@ impl CanonicalDeserialize for [T; N] { } } -impl CanonicalSerialize for Vec { +impl CanonicalSerializeInner for Vec { #[inline] fn serialize_with_mode( &self, @@ -479,7 +485,7 @@ impl CanonicalDeserialize for Vec { } } -impl CanonicalSerialize for [T] { +impl CanonicalSerializeInner for [T] { #[inline] fn serialize_with_mode( &self, @@ -503,7 +509,7 @@ impl CanonicalSerialize for [T] { } } -impl<'a, T: CanonicalSerialize> CanonicalSerialize for &'a [T] { +impl<'a, T: CanonicalSerializeInner> CanonicalSerializeInner for &'a [T] { #[inline] fn serialize_with_mode( &self, @@ -519,7 +525,7 @@ impl<'a, T: CanonicalSerialize> CanonicalSerialize for &'a [T] { } } -impl CanonicalSerialize for String { +impl CanonicalSerializeInner for String { #[inline] fn serialize_with_mode( &self, @@ -535,6 +541,8 @@ impl CanonicalSerialize for String { } } +impl CanonicalSerialize for String {} + impl Valid for String { #[inline] fn check(&self) -> Result<(), SerializationError> { @@ -568,7 +576,7 @@ macro_rules! impl_tuple { } #[allow(unused)] - impl<$($ty, )*> CanonicalSerialize for ($($ty,)*) where + impl<$($ty, )*> CanonicalSerializeInner for ($($ty,)*) where $($ty: CanonicalSerialize,)* { #[inline] @@ -605,7 +613,7 @@ impl_tuple!(A:0, B:1,); impl_tuple!(A:0, B:1, C:2,); impl_tuple!(A:0, B:1, C:2, D:3,); -impl CanonicalSerialize for BTreeMap +impl CanonicalSerializeInner for BTreeMap where K: CanonicalSerialize, V: CanonicalSerialize, @@ -674,7 +682,7 @@ where } } -impl CanonicalSerialize for BTreeSet { +impl CanonicalSerializeInner for BTreeSet { /// Serializes a `BTreeSet` as `len(set) || value 1 || value 2 || ... || value n`. fn serialize_with_mode( &self, diff --git a/serialize/src/lib.rs b/serialize/src/lib.rs index d69f43411..83eb527fb 100644 --- a/serialize/src/lib.rs +++ b/serialize/src/lib.rs @@ -79,7 +79,7 @@ pub trait Valid: Sized + Sync { /// b: (u64, (u64, u64)), /// } /// ``` -pub trait CanonicalSerialize { +pub trait CanonicalSerializeInner { /// The general serialize method that takes in customization flags. fn serialize_with_mode( &self, @@ -147,8 +147,14 @@ pub trait CanonicalDeserialize: Valid { } } +#[cfg(feature = "serde")] +pub trait CanonicalSerialize: CanonicalSerializeInner + serde::Serialize {} + +#[cfg(not(feature = "serde"))] +pub trait CanonicalSerialize: CanonicalSerializeInner {} + /// Serializer in little endian format allowing to encode flags. -pub trait CanonicalSerializeWithFlags: CanonicalSerialize { +pub trait CanonicalSerializeWithFlags: CanonicalSerializeInner { /// Serializes `self` and `flags` into `writer`. fn serialize_with_flags( &self, @@ -188,7 +194,7 @@ impl<'a, H: Digest> ark_std::io::Write for HashMarshaller<'a, H> { /// The CanonicalSerialize induces a natural way to hash the /// corresponding value, of which this is the convenience trait. -pub trait CanonicalSerializeHashExt: CanonicalSerialize { +pub trait CanonicalSerializeHashExt: CanonicalSerializeInner { fn hash(&self) -> GenericArray::OutputSize> { let mut hasher = H::new(); self.serialize_compressed(HashMarshaller(&mut hasher)) @@ -235,7 +241,7 @@ mod test { #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] struct Dummy; - impl CanonicalSerialize for Dummy { + impl CanonicalSerializeInner for Dummy { #[inline] fn serialize_with_mode( &self, @@ -256,6 +262,8 @@ mod test { } } + impl CanonicalSerialize for Dummy {} + impl Valid for Dummy { fn check(&self) -> Result<(), SerializationError> { Ok(())