subspace_core_primitives/
pot.rsuse crate::hashes::{blake3_hash, blake3_hash_list, Blake3Hash};
use crate::Randomness;
use core::fmt;
use core::num::NonZeroU8;
use core::str::FromStr;
use derive_more::{AsMut, AsRef, Deref, DerefMut, From};
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};
#[derive(
Debug,
Default,
Copy,
Clone,
Eq,
PartialEq,
From,
AsRef,
AsMut,
Deref,
DerefMut,
Encode,
Decode,
TypeInfo,
MaxEncodedLen,
)]
pub struct PotKey([u8; Self::SIZE]);
#[cfg(feature = "serde")]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct PotKeyBinary([u8; PotKey::SIZE]);
#[cfg(feature = "serde")]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct PotKeyHex(#[serde(with = "hex")] [u8; PotKey::SIZE]);
#[cfg(feature = "serde")]
impl Serialize for PotKey {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if serializer.is_human_readable() {
PotKeyHex(self.0).serialize(serializer)
} else {
PotKeyBinary(self.0).serialize(serializer)
}
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for PotKey {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(Self(if deserializer.is_human_readable() {
PotKeyHex::deserialize(deserializer)?.0
} else {
PotKeyBinary::deserialize(deserializer)?.0
}))
}
}
impl fmt::Display for PotKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode(self.0))
}
}
impl FromStr for PotKey {
type Err = hex::FromHexError;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut key = Self::default();
hex::decode_to_slice(s, key.as_mut())?;
Ok(key)
}
}
impl PotKey {
pub const SIZE: usize = 16;
}
#[derive(
Debug,
Default,
Copy,
Clone,
Eq,
PartialEq,
Hash,
From,
AsRef,
AsMut,
Deref,
DerefMut,
Encode,
Decode,
TypeInfo,
MaxEncodedLen,
)]
pub struct PotSeed([u8; Self::SIZE]);
#[cfg(feature = "serde")]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct PotSeedBinary([u8; PotSeed::SIZE]);
#[cfg(feature = "serde")]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct PotSeedHex(#[serde(with = "hex")] [u8; PotSeed::SIZE]);
#[cfg(feature = "serde")]
impl Serialize for PotSeed {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if serializer.is_human_readable() {
PotSeedHex(self.0).serialize(serializer)
} else {
PotSeedBinary(self.0).serialize(serializer)
}
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for PotSeed {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(Self(if deserializer.is_human_readable() {
PotSeedHex::deserialize(deserializer)?.0
} else {
PotSeedBinary::deserialize(deserializer)?.0
}))
}
}
impl fmt::Display for PotSeed {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode(self.0))
}
}
impl PotSeed {
pub const SIZE: usize = 16;
#[inline]
pub fn from_genesis(genesis_block_hash: &[u8], external_entropy: &[u8]) -> Self {
let hash = blake3_hash_list(&[genesis_block_hash, external_entropy]);
let mut seed = Self::default();
seed.copy_from_slice(&hash[..Self::SIZE]);
seed
}
#[inline]
pub fn key(&self) -> PotKey {
let mut key = PotKey::default();
key.copy_from_slice(&blake3_hash(&self.0)[..Self::SIZE]);
key
}
}
#[derive(
Debug,
Default,
Copy,
Clone,
Eq,
PartialEq,
Hash,
From,
AsRef,
AsMut,
Deref,
DerefMut,
Encode,
Decode,
TypeInfo,
MaxEncodedLen,
)]
pub struct PotOutput([u8; Self::SIZE]);
#[cfg(feature = "serde")]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct PotOutputBinary([u8; PotOutput::SIZE]);
#[cfg(feature = "serde")]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct PotOutputHex(#[serde(with = "hex")] [u8; PotOutput::SIZE]);
#[cfg(feature = "serde")]
impl Serialize for PotOutput {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if serializer.is_human_readable() {
PotOutputHex(self.0).serialize(serializer)
} else {
PotOutputBinary(self.0).serialize(serializer)
}
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for PotOutput {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(Self(if deserializer.is_human_readable() {
PotOutputHex::deserialize(deserializer)?.0
} else {
PotOutputBinary::deserialize(deserializer)?.0
}))
}
}
impl fmt::Display for PotOutput {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode(self.0))
}
}
impl PotOutput {
pub const SIZE: usize = 16;
#[inline]
pub fn derive_global_randomness(&self) -> Randomness {
Randomness::from(*blake3_hash(&self.0))
}
#[inline]
pub fn seed(&self) -> PotSeed {
PotSeed(self.0)
}
#[inline]
pub fn seed_with_entropy(&self, entropy: &Blake3Hash) -> PotSeed {
let hash = blake3_hash_list(&[entropy.as_ref(), &self.0]);
let mut seed = PotSeed::default();
seed.copy_from_slice(&hash[..Self::SIZE]);
seed
}
}
#[derive(
Debug,
Default,
Copy,
Clone,
Eq,
PartialEq,
Hash,
Deref,
DerefMut,
Encode,
Decode,
TypeInfo,
MaxEncodedLen,
)]
pub struct PotCheckpoints([PotOutput; Self::NUM_CHECKPOINTS.get() as usize]);
impl PotCheckpoints {
pub const NUM_CHECKPOINTS: NonZeroU8 = NonZeroU8::new(8).expect("Not zero; qed");
#[inline]
pub fn output(&self) -> PotOutput {
self.0[Self::NUM_CHECKPOINTS.get() as usize - 1]
}
}