Skip to content

Commit

Permalink
Added serde support
Browse files Browse the repository at this point in the history
  • Loading branch information
d-sonuga committed Dec 6, 2024
1 parent b3807b5 commit b18f8e5
Show file tree
Hide file tree
Showing 5 changed files with 285 additions and 2 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/dusk_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ jobs:
name: Nightly std tests
uses: dusk-network/.github/.github/workflows/run-tests.yml@main
with:
test_flags: --features=rkyv-impl,rkyv/size_16
test_flags: --features=rkyv-impl,rkyv/size_16,serde

test_parallel:
name: Nightly std tests parallel
uses: dusk-network/.github/.github/workflows/run-tests.yml@main
with:
test_flags: --features=parallel,rkyv-impl,rkyv/size_16
test_flags: --features=parallel,rkyv-impl,rkyv/size_16,serde
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ zeroize = { version = "1", default-features = false, features = ["derive"] }
rkyv = { version = "0.7", optional = true, default-features = false }
bytecheck = { version = "0.6", optional = true, default-features = false }
rayon = { version = "1.8", optional = true }
serde = { version = "1.0", optional = true }
bs58 = { version = "0.4" , optional = true }
serde_json = { version = "1.0", optional = true }

[dev-dependencies]
rand = "0.8"
Expand All @@ -34,3 +37,4 @@ rkyv-impl = [
"bytecheck",
]
parallel = ["dep:rayon"]
serde = ["dep:serde", "bs58", "serde_json"]
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ pub use keys::{
};
pub use signatures::{MultisigSignature, Signature};

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

#[cfg(feature = "rkyv-impl")]
pub use crate::keys::{
public::{
Expand Down
213 changes: 213 additions & 0 deletions src/serde_support.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) DUSK NETWORK. All rights reserved.

extern crate alloc;

use alloc::format;
use alloc::string::String;

use bs58;
use dusk_bytes::Serializable;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};

use crate::{
MultisigPublicKey, MultisigSignature, PublicKey, SecretKey, Signature,
};

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

impl<'de> Deserialize<'de> for PublicKey {
fn deserialize<D: Deserializer<'de>>(
deserializer: D,
) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
let mut bytes: [u8; Self::SIZE] = [0; Self::SIZE];
match bs58::decode(&s).into(&mut bytes) {
Ok(n) => {
if n != Self::SIZE {
return Err(de::Error::custom(
"failed to deserialize PublicKey: invalid byte length",
));
}
}
Err(err) => {
return Err(de::Error::custom(format!(
"failed to deserialize PublicKey: {err:?}"
)))
}
}
let pubk = PublicKey::from_bytes(&bytes).map_err(|err| {
de::Error::custom(format!(
"failed to deserialize PublicKey: {err:?}"
))
})?;
Ok(pubk)
}
}

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

impl<'de> Deserialize<'de> for MultisigPublicKey {
fn deserialize<D: Deserializer<'de>>(
deserializer: D,
) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
let mut bytes: [u8; Self::SIZE] = [0; Self::SIZE];
match bs58::decode(&s).into(&mut bytes) {
Ok(n) => {
if n != Self::SIZE {
return Err(de::Error::custom(
"failed to deserialize MultisigPublicKey: invalid byte length",
));
}
}
Err(err) => {
return Err(de::Error::custom(format!(
"failed to deserialize MultisigPublicKey: {err:?}"
)))
}
}
let pubk = MultisigPublicKey::from_bytes(&bytes).map_err(|err| {
de::Error::custom(format!(
"failed to deserialize MultisigPublicKey: {err:?}"
))
})?;
Ok(pubk)
}
}

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

impl<'de> Deserialize<'de> for Signature {
fn deserialize<D: Deserializer<'de>>(
deserializer: D,
) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
let mut bytes: [u8; Self::SIZE] = [0; Self::SIZE];
match bs58::decode(&s).into(&mut bytes) {
Ok(n) => {
if n != Self::SIZE {
return Err(de::Error::custom(
"failed to deserialize Signature: invalid byte length",
));
}
}
Err(err) => {
return Err(de::Error::custom(format!(
"failed to deserialize Signature: {err:?}"
)))
}
}
let sig = Signature::from_bytes(&bytes).map_err(|err| {
de::Error::custom(format!(
"failed to deserialize Signature: {err:?}"
))
})?;
Ok(sig)
}
}

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

impl<'de> Deserialize<'de> for MultisigSignature {
fn deserialize<D: Deserializer<'de>>(
deserializer: D,
) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
let mut bytes: [u8; Self::SIZE] = [0; Self::SIZE];
match bs58::decode(&s).into(&mut bytes) {
Ok(n) => {
if n != Self::SIZE {
return Err(de::Error::custom(
"failed to deserialize MultisigSignature: invalid byte length",
));
}
}
Err(err) => {
return Err(de::Error::custom(format!(
"failed to deserialize MultisigSignature: {err:?}"
)))
}
}
let sig = MultisigSignature::from_bytes(&bytes).map_err(|err| {
de::Error::custom(format!(
"failed to deserialize MultisigSignature: {err:?}"
))
})?;
Ok(sig)
}
}

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

impl<'de> Deserialize<'de> for SecretKey {
fn deserialize<D: Deserializer<'de>>(
deserializer: D,
) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
let mut bytes: [u8; Self::SIZE] = [0; Self::SIZE];
match bs58::decode(&s).into(&mut bytes) {
Ok(n) => {
if n != Self::SIZE {
return Err(de::Error::custom(
"failed to deserialize SecretKey: invalid byte length",
));
}
}
Err(err) => {
return Err(de::Error::custom(format!(
"failed to deserialize SecretKey: {err:?}"
)))
}
}
let sk = SecretKey::from_bytes(&bytes).map_err(|err| {
de::Error::custom(format!(
"failed to deserialize SecretKey: {err:?}"
))
})?;
Ok(sk)
}
}
63 changes: 63 additions & 0 deletions tests/serde.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) DUSK NETWORK. All rights reserved.

#[cfg(feature = "serde")]
mod tests {
use bls12_381_bls::{MultisigPublicKey, PublicKey, SecretKey};
use rand::rngs::StdRng;
use rand::SeedableRng;

#[test]
fn public_key() {
let mut rng = StdRng::seed_from_u64(0xbeef);
let pk = PublicKey::from(&SecretKey::random(&mut rng));
let ser = serde_json::to_string(&pk);
let deser = serde_json::from_str(&ser.unwrap());
assert_eq!(pk, deser.unwrap());
}

#[test]
fn multisig_public_key() {
let mut rng = StdRng::seed_from_u64(0xbeef);
let pk = MultisigPublicKey::aggregate(&[PublicKey::from(
&SecretKey::random(&mut rng),
)])
.unwrap();
let ser = serde_json::to_string(&pk);
let deser = serde_json::from_str(&ser.unwrap());
assert_eq!(pk, deser.unwrap());
}

#[test]
fn signature() {
let mut rng = StdRng::seed_from_u64(0xbeef);
let sk = SecretKey::random(&mut rng);
let signature = sk.sign(b"a message");
let ser = serde_json::to_string(&signature).unwrap();
let deser = serde_json::from_str(&ser).unwrap();
assert_eq!(signature, deser);
}

#[test]
fn multisig_signature() {
let mut rng = StdRng::seed_from_u64(0xbeef);
let sk = SecretKey::random(&mut rng);
let pk = PublicKey::from(&sk);
let signature = sk.sign_multisig(&pk, b"a message");
let ser = serde_json::to_string(&signature).unwrap();
let deser = serde_json::from_str(&ser).unwrap();
assert_eq!(signature, deser);
}

#[test]
fn secret_key() {
let mut rng = StdRng::seed_from_u64(0xbeef);
let sk = SecretKey::random(&mut rng);
let ser = serde_json::to_string(&sk).unwrap();
let deser = serde_json::from_str(&ser).unwrap();
assert_eq!(sk, deser);
}
}

0 comments on commit b18f8e5

Please sign in to comment.