-
Notifications
You must be signed in to change notification settings - Fork 7
feat(akita-field): add serde to akita-field #400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
8b021f7
226fbe0
ad582d3
f464251
2368c7c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| //! `serde` for the extension fields, as base-coefficient arrays. | ||
| //! | ||
| //! An element encodes as its `[F; K]` coefficients in the same basis order as | ||
| //! [`AkitaSerialize`](akita_serialization::AkitaSerialize), so canonicality is | ||
| //! enforced by the base field's own decode. As with the prime fields, this is a | ||
| //! host and tooling surface: verifier-reachable decoding stays on | ||
| //! [`AkitaDeserialize`](akita_serialization::AkitaDeserialize), which is the | ||
| //! only path that bounds container lengths. | ||
|
|
||
| use serde::{Deserialize, Deserializer, Serialize, Serializer}; | ||
|
|
||
| use super::{FpExt2, FpExt2Config, FpExt4, FpExt8}; | ||
| use crate::FieldCore; | ||
|
|
||
| /// Implements serde for one extension arity. `$cfg` is the extension-config | ||
| /// parameter, which only `FpExt2` carries. | ||
| macro_rules! impl_ext_serde { | ||
| ($ty:ident $(, $cfg:ident: $bound:path)?; $k:literal; |$coeffs:ident| $new:expr) => { | ||
| impl<F: FieldCore + Serialize $(, $cfg: $bound)?> Serialize for $ty<F $(, $cfg)?> { | ||
| fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { | ||
| self.coeffs.serialize(serializer) | ||
| } | ||
| } | ||
|
|
||
| impl<'de, F: FieldCore + Deserialize<'de> $(, $cfg: $bound)?> Deserialize<'de> | ||
| for $ty<F $(, $cfg)?> | ||
| { | ||
| fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { | ||
| let $coeffs = <[F; $k]>::deserialize(deserializer)?; | ||
| Ok($new) | ||
| } | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| impl_ext_serde!(FpExt2, C: FpExt2Config<F>; 2; |coeffs| Self::new(coeffs[0], coeffs[1])); | ||
| impl_ext_serde!(FpExt4; 4; |coeffs| Self::new(coeffs)); | ||
|
Comment on lines
+34
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Worth aligning the definitions/API or are there reasons to specify C and pass the coeffs explicitly for FpExt2? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The difference follows the underlying public types. I therefore would not add a forwarding constructor or reshape the field APIs in this Serde PR just to make these three macro calls look identical. We can make the |
||
| impl_ext_serde!(FpExt8; 8; |coeffs| Self::new(coeffs)); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| //! `serde` for the prime fields, over the canonical residue. | ||
| //! | ||
| //! An element encodes as its canonical representative in the field's storage | ||
| //! width; decode rejects non-canonical values (`val >= P`) rather than reducing. | ||
| //! | ||
| //! This is a host and tooling surface. Akita's protocol wire format is | ||
| //! [`AkitaSerialize`](akita_serialization::AkitaSerialize) / | ||
| //! [`AkitaDeserialize`](akita_serialization::AkitaDeserialize), and | ||
| //! verifier-reachable decoding stays there: a serde format bounds sequence | ||
| //! lengths only if its consumer configured a limit, so these impls cannot make | ||
| //! the container guarantee that `AkitaDeserialize` does. | ||
|
|
||
| use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; | ||
|
|
||
| use super::{Fp128, Fp32, Fp64}; | ||
| use crate::CanonicalField; | ||
|
|
||
| macro_rules! impl_prime_serde { | ||
| ($ty:ident<$p:ident: $p_ty:ty>) => { | ||
| impl<const $p: $p_ty> Serialize for $ty<$p> { | ||
| fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { | ||
| (self.to_canonical_u128() as $p_ty).serialize(serializer) | ||
| } | ||
| } | ||
|
|
||
| impl<'de, const $p: $p_ty> Deserialize<'de> for $ty<$p> { | ||
| fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { | ||
| let raw = <$p_ty as Deserialize>::deserialize(deserializer)?; | ||
| Self::from_canonical_u128_checked(u128::from(raw)).ok_or_else(|| { | ||
| de::Error::custom(format_args!( | ||
| concat!(stringify!($ty), " value {} is not a canonical residue"), | ||
| raw | ||
| )) | ||
| }) | ||
| } | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| impl_prime_serde!(Fp32<P: u32>); | ||
| impl_prime_serde!(Fp64<P: u64>); | ||
| impl_prime_serde!(Fp128<P: u128>); |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason to not use a more recent version? say
serde = "1.0.229"or is just to be aligned with jolt?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
serde = "1"already accepts every compatible Serde 1.x release. It is equivalent to Jolt'sversion = "1.0"requirement. The PR lock currently resolves 1.0.228, while Jolt's latestmainresolves 1.0.229. Writing"1.0.229"would raise the minimum accepted version to 1.0.229, but it would not pin that exact release. An exact pin would require"=1.0.229".We do not use an API introduced in 1.0.229, so I think
"1"is the truthful manifest requirement and is aligned with Jolt. If we want the current resolved release in this PR, we can refresh the lock without raising the crate's minimum Serde version.