Skip to content

Commit

Permalink
Added serde feature
Browse files Browse the repository at this point in the history
  • Loading branch information
d-sonuga committed Dec 9, 2024
1 parent 40e9c78 commit c40b897
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/dusk_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@ jobs:
uses: dusk-network/.github/.github/workflows/run-tests.yml@main
with:
test_flags: --no-default-features

test_serde:
name: Serde tests
uses: dusk-network/.github/.github/workflows/run-tests.yml@main
with:
test_flags: --features=serde
13 changes: 13 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ optional = true
default-features = false
# End Dusk dependendencies

[dependencies.serde]
version = "1.0"
optional = true

[dependencies.serde_json]
version = "1.0"
optional = true

[dependencies.hex]
version = "0.4"
optional = true

[dev-dependencies]
criterion = "0.3"
csv = ">= 1.0, < 1.2" # csv 1.2 has MSRV 1.60
Expand All @@ -86,6 +98,7 @@ default = ["alloc", "bits"]
alloc = ["ff/alloc", "group/alloc"]
bits = ["ff/bits"]
rkyv-impl = ["bytecheck", "dusk-bls12_381/rkyv-impl", "rkyv"]
serde = ["dep:serde", "serde_json", "dusk-bls12_381/serde", "hex"]

[[bench]]
name = "fq_bench"
Expand Down
3 changes: 3 additions & 0 deletions src/dusk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "serde")]
mod serde_support;

use core::ops::Mul;
use ff::Field;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
Expand Down
116 changes: 116 additions & 0 deletions src/dusk/serde_support.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
extern crate alloc;

use alloc::string::String;

use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};

use crate::{AffinePoint, ExtendedPoint, Fr};

impl Serialize for AffinePoint {
fn serialize<S: Serializer>(
&self,
serializer: S,
) -> Result<S::Ok, S::Error> {
let s = hex::encode(self.to_bytes());
serializer.serialize_str(&s)
}
}

impl<'de> Deserialize<'de> for AffinePoint {
fn deserialize<D: Deserializer<'de>>(
deserializer: D,
) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
let bytes: [u8; 32] = hex::decode(s)
.map_err(Error::custom)?
.try_into()
.map_err(|_| {
Error::custom(
"Failed to deserialize AffinePoint: invalid byte length",
)
})?;
AffinePoint::from_bytes(bytes)
.into_option()
.ok_or(Error::custom(
"Failed to deserialize AffinePoint: invalid AffinePoint",
))
}
}

impl Serialize for ExtendedPoint {
fn serialize<S: Serializer>(
&self,
serializer: S,
) -> Result<S::Ok, S::Error> {
AffinePoint::from(self).serialize(serializer)
}
}

impl<'de> Deserialize<'de> for ExtendedPoint {
fn deserialize<D: Deserializer<'de>>(
deserializer: D,
) -> Result<Self, D::Error> {
AffinePoint::deserialize(deserializer).map(Into::into)
}
}

impl Serialize for Fr {
fn serialize<S: Serializer>(
&self,
serializer: S,
) -> Result<S::Ok, S::Error> {
let s = hex::encode(self.to_bytes());
serializer.serialize_str(&s)
}
}

impl<'de> Deserialize<'de> for Fr {
fn deserialize<D: Deserializer<'de>>(
deserializer: D,
) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
let bytes: [u8; 32] = hex::decode(s)
.map_err(Error::custom)?
.try_into()
.map_err(|_| {
Error::custom("Failed to deserialize Fr: invalid byte length")
})?;
Fr::from_bytes(&bytes)
.into_option()
.ok_or(Error::custom("Failed to deserialize Fr: invalid Fr"))
}
}

#[cfg(test)]
mod tests {
use ff::Field;
use group::Group;

use crate::{AffinePoint, ExtendedPoint, Fr};

#[test]
fn affine_point() {
let point = AffinePoint::identity();
let ser = serde_json::to_string(&point).unwrap();
let deser = serde_json::from_str(&ser).unwrap();
assert_eq!(point, deser);
}

#[test]
fn extended_point() {
let mut rng = rand_core::OsRng;
let point = ExtendedPoint::random(&mut rng);
let ser = serde_json::to_string(&point).unwrap();
let deser = serde_json::from_str(&ser).unwrap();
assert_eq!(point, deser);
}

#[test]
fn fr() {
let mut rng = rand_core::OsRng;
let fr = Fr::random(&mut rng);
let ser = serde_json::to_string(&fr).unwrap();
let deser = serde_json::from_str(&ser).unwrap();
assert_eq!(fr, deser);
}
}

0 comments on commit c40b897

Please sign in to comment.