Skip to content

Commit

Permalink
Use hex for human-readable serde encoding and binary otherwise
Browse files Browse the repository at this point in the history
  • Loading branch information
nazar-pc committed Oct 28, 2024
1 parent 0fde4c6 commit 65828e9
Show file tree
Hide file tree
Showing 13 changed files with 575 additions and 257 deletions.
12 changes: 11 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/subspace-core-primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ parity-scale-codec = { version = "3.6.12", default-features = false, features =
rayon = { version = "1.10.0", optional = true }
scale-info = { version = "2.11.2", default-features = false, features = ["derive"] }
serde = { version = "1.0.110", optional = true, default-features = false, features = ["alloc", "derive"] }
serde-big-array = "0.5.1"
static_assertions = "1.1.0"
uint = { version = "0.10.0", default-features = false }

Expand All @@ -39,6 +40,7 @@ parallel = [
]
serde = [
"dep:serde",
"bytes/serde",
"hex/serde",
]
std = [
Expand Down
59 changes: 43 additions & 16 deletions crates/subspace-core-primitives/src/hashes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ use crate::ScalarBytes;
use core::array::TryFromSliceError;
use core::fmt;
use derive_more::{AsMut, AsRef, Deref, DerefMut, From, Into};
use hex::FromHex;
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "serde")]
use serde::{Deserializer, Serializer};

/// BLAKE3 hash output transparent wrapper
#[derive(
Expand All @@ -46,9 +47,47 @@ use serde::{Deserialize, Serialize};
TypeInfo,
MaxEncodedLen,
)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct Blake3Hash(#[cfg_attr(feature = "serde", serde(with = "hex"))] [u8; Blake3Hash::SIZE]);
pub struct Blake3Hash([u8; Blake3Hash::SIZE]);

#[cfg(feature = "serde")]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct Blake3HashBinary([u8; Blake3Hash::SIZE]);

#[cfg(feature = "serde")]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct Blake3HashHex(#[serde(with = "hex")] [u8; Blake3Hash::SIZE]);

#[cfg(feature = "serde")]
impl Serialize for Blake3Hash {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if serializer.is_human_readable() {
Blake3HashHex(self.0).serialize(serializer)
} else {
Blake3HashBinary(self.0).serialize(serializer)
}
}
}

#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for Blake3Hash {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(Self(if deserializer.is_human_readable() {
Blake3HashHex::deserialize(deserializer)?.0
} else {
Blake3HashBinary::deserialize(deserializer)?.0
}))
}
}

impl fmt::Debug for Blake3Hash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand All @@ -70,18 +109,6 @@ impl AsMut<[u8]> for Blake3Hash {
}
}

impl FromHex for Blake3Hash {
type Error = hex::FromHexError;

fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
let data = hex::decode(hex)?
.try_into()
.map_err(|_| hex::FromHexError::InvalidStringLength)?;

Ok(Self(data))
}
}

impl From<&[u8; Self::SIZE]> for Blake3Hash {
#[inline]
fn from(value: &[u8; Self::SIZE]) -> Self {
Expand Down
88 changes: 84 additions & 4 deletions crates/subspace-core-primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "serde")]
use serde::{Deserializer, Serializer};
use static_assertions::const_assert;

// Refuse to compile on lower than 32-bit platforms
Expand All @@ -71,8 +73,47 @@ pub const REWARD_SIGNING_CONTEXT: &[u8] = b"subspace_reward";
TypeInfo,
MaxEncodedLen,
)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Randomness(#[cfg_attr(feature = "serde", serde(with = "hex"))] [u8; Randomness::SIZE]);
pub struct Randomness([u8; Randomness::SIZE]);

#[cfg(feature = "serde")]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct RandomnessBinary([u8; Randomness::SIZE]);

#[cfg(feature = "serde")]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct RandomnessHex(#[serde(with = "hex")] [u8; Randomness::SIZE]);

#[cfg(feature = "serde")]
impl Serialize for Randomness {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if serializer.is_human_readable() {
RandomnessHex(self.0).serialize(serializer)
} else {
RandomnessBinary(self.0).serialize(serializer)
}
}
}

#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for Randomness {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(Self(if deserializer.is_human_readable() {
RandomnessHex::deserialize(deserializer)?.0
} else {
RandomnessBinary::deserialize(deserializer)?.0
}))
}
}

impl AsRef<[u8]> for Randomness {
#[inline]
Expand Down Expand Up @@ -131,8 +172,47 @@ pub type BlockWeight = u128;
From,
Into,
)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PublicKey(#[cfg_attr(feature = "serde", serde(with = "hex"))] [u8; PublicKey::SIZE]);
pub struct PublicKey([u8; PublicKey::SIZE]);

#[cfg(feature = "serde")]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct PublicKeyBinary([u8; PublicKey::SIZE]);

#[cfg(feature = "serde")]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct PublicKeyHex(#[serde(with = "hex")] [u8; PublicKey::SIZE]);

#[cfg(feature = "serde")]
impl Serialize for PublicKey {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if serializer.is_human_readable() {
PublicKeyHex(self.0).serialize(serializer)
} else {
PublicKeyBinary(self.0).serialize(serializer)
}
}
}

#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for PublicKey {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(Self(if deserializer.is_human_readable() {
PublicKeyHex::deserialize(deserializer)?.0
} else {
PublicKeyBinary::deserialize(deserializer)?.0
}))
}
}

impl fmt::Display for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down
1 change: 0 additions & 1 deletion crates/subspace-core-primitives/src/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct BlockObject {
/// Object hash
#[cfg_attr(feature = "serde", serde(with = "hex"))]
pub hash: Blake3Hash,
/// Offset of object in the encoded block.
pub offset: u32,
Expand Down
Loading

0 comments on commit 65828e9

Please sign in to comment.