Skip to content

Commit

Permalink
Merge pull request #3184 from autonomys/serde-encoding-improvements
Browse files Browse the repository at this point in the history
Serde encoding improvements
  • Loading branch information
nazar-pc authored Oct 28, 2024
2 parents a88cbf8 + ba52cc7 commit 1aad248
Show file tree
Hide file tree
Showing 13 changed files with 598 additions and 300 deletions.
10 changes: 10 additions & 0 deletions 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
69 changes: 45 additions & 24 deletions crates/subspace-core-primitives/src/hashes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@
use crate::ScalarBytes;
use core::array::TryFromSliceError;
use core::fmt;
use derive_more::{AsMut, AsRef, Deref, DerefMut, From};
use hex::FromHex;
use derive_more::{AsMut, AsRef, Deref, DerefMut, From, Into};
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 @@ -36,6 +37,7 @@ use serde::{Deserialize, Serialize};
PartialOrd,
Hash,
From,
Into,
AsRef,
AsMut,
Deref,
Expand All @@ -45,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; Self::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 @@ -69,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 All @@ -97,13 +125,6 @@ impl TryFrom<&[u8]> for Blake3Hash {
}
}

impl From<Blake3Hash> for [u8; Blake3Hash::SIZE] {
#[inline]
fn from(value: Blake3Hash) -> Self {
value.0
}
}

impl Blake3Hash {
/// Size of BLAKE3 hash output (in bytes).
pub const SIZE: usize = 32;
Expand Down
100 changes: 87 additions & 13 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 @@ -55,9 +57,6 @@ const_assert!(core::mem::size_of::<usize>() >= core::mem::size_of::<u32>());
/// Signing context used for creating reward signatures by farmers.
pub const REWARD_SIGNING_CONTEXT: &[u8] = b"subspace_reward";

/// Byte length of a randomness type.
pub const RANDOMNESS_LENGTH: usize = 32;

/// Type of randomness.
#[derive(
Debug,
Expand All @@ -74,8 +73,47 @@ pub const RANDOMNESS_LENGTH: usize = 32;
TypeInfo,
MaxEncodedLen,
)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Randomness(#[cfg_attr(feature = "serde", serde(with = "hex"))] [u8; RANDOMNESS_LENGTH]);
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 All @@ -92,6 +130,9 @@ impl AsMut<[u8]> for Randomness {
}

impl Randomness {
/// Size of randomness (in bytes).
pub const SIZE: usize = 32;

/// Derive global slot challenge from global randomness.
// TODO: Separate type for global challenge
pub fn derive_global_challenge(&self, slot: SlotNumber) -> Blake3Hash {
Expand Down Expand Up @@ -129,20 +170,53 @@ pub type BlockWeight = u128;
TypeInfo,
Deref,
From,
Into,
)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PublicKey(#[cfg_attr(feature = "serde", serde(with = "hex"))] [u8; Self::SIZE]);
pub struct PublicKey([u8; PublicKey::SIZE]);

impl fmt::Display for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode(self.0))
#[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)
}
}
}

impl From<PublicKey> for [u8; PublicKey::SIZE] {
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for PublicKey {
#[inline]
fn from(value: PublicKey) -> Self {
value.0
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 {
write!(f, "{}", hex::encode(self.0))
}
}

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 1aad248

Please sign in to comment.