subspace_core_primitives/
lib.rs#![cfg_attr(not(feature = "std"), no_std)]
#![warn(rust_2018_idioms, missing_docs)]
#![cfg_attr(feature = "std", warn(missing_debug_implementations))]
#![feature(
array_chunks,
const_trait_impl,
const_try,
new_zeroed_alloc,
portable_simd,
step_trait
)]
pub mod checksum;
pub mod hashes;
pub mod objects;
pub mod pieces;
pub mod pos;
pub mod pot;
pub mod sectors;
pub mod segments;
pub mod solutions;
#[cfg(test)]
mod tests;
use crate::hashes::{blake3_hash, blake3_hash_list, Blake3Hash};
use core::fmt;
use derive_more::{Add, AsMut, AsRef, Deref, DerefMut, Display, Div, From, Into, Mul, Rem, Sub};
use num_traits::{WrappingAdd, WrappingSub};
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;
const_assert!(core::mem::size_of::<usize>() >= core::mem::size_of::<u32>());
pub const REWARD_SIGNING_CONTEXT: &[u8] = b"subspace_reward";
#[derive(
Debug,
Default,
Copy,
Clone,
Eq,
PartialEq,
From,
Into,
Deref,
Encode,
Decode,
TypeInfo,
MaxEncodedLen,
)]
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]
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl AsMut<[u8]> for Randomness {
#[inline]
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl Randomness {
pub const SIZE: usize = 32;
pub fn derive_global_challenge(&self, slot: SlotNumber) -> Blake3Hash {
blake3_hash_list(&[&self.0, &slot.to_le_bytes()])
}
}
pub type BlockNumber = u32;
pub type BlockHash = [u8; 32];
pub type SlotNumber = u64;
pub type BlockWeight = u128;
#[derive(
Debug,
Default,
Copy,
Clone,
PartialEq,
Eq,
Ord,
PartialOrd,
Hash,
Encode,
Decode,
TypeInfo,
Deref,
From,
Into,
)]
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 {
write!(f, "{}", hex::encode(self.0))
}
}
impl AsRef<[u8]> for PublicKey {
#[inline]
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl PublicKey {
pub const SIZE: usize = 32;
pub fn hash(&self) -> Blake3Hash {
blake3_hash(&self.0)
}
}
#[derive(
Debug,
Default,
Copy,
Clone,
Eq,
PartialEq,
Ord,
PartialOrd,
Hash,
From,
Into,
AsRef,
AsMut,
Deref,
DerefMut,
Encode,
Decode,
TypeInfo,
)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct ScalarBytes([u8; ScalarBytes::FULL_BYTES]);
impl ScalarBytes {
pub const SAFE_BYTES: usize = 31;
pub const FULL_BYTES: usize = 32;
}
#[allow(clippy::assign_op_pattern, clippy::ptr_offset_with_cast)]
mod private_u256 {
use parity_scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
uint::construct_uint! {
#[derive(Encode, Decode, TypeInfo)]
pub struct U256(4);
}
}
#[derive(
Debug,
Display,
Add,
Sub,
Mul,
Div,
Rem,
Copy,
Clone,
Ord,
PartialOrd,
Eq,
PartialEq,
Hash,
Encode,
Decode,
TypeInfo,
)]
pub struct U256(private_u256::U256);
impl U256 {
#[inline]
pub const fn zero() -> Self {
Self(private_u256::U256::zero())
}
#[inline]
pub fn one() -> Self {
Self(private_u256::U256::one())
}
pub fn from_be_bytes(bytes: [u8; 32]) -> Self {
Self(private_u256::U256::from_big_endian(&bytes))
}
pub fn to_be_bytes(self) -> [u8; 32] {
self.0.to_big_endian()
}
pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
Self(private_u256::U256::from_little_endian(&bytes))
}
pub fn to_le_bytes(self) -> [u8; 32] {
self.0.to_little_endian()
}
pub fn checked_add(&self, v: &Self) -> Option<Self> {
self.0.checked_add(v.0).map(Self)
}
pub fn checked_sub(&self, v: &Self) -> Option<Self> {
self.0.checked_sub(v.0).map(Self)
}
pub fn checked_mul(&self, v: &Self) -> Option<Self> {
self.0.checked_mul(v.0).map(Self)
}
pub fn checked_div(&self, v: &Self) -> Option<Self> {
self.0.checked_div(v.0).map(Self)
}
pub fn saturating_add(&self, v: &Self) -> Self {
Self(self.0.saturating_add(v.0))
}
pub fn saturating_sub(&self, v: &Self) -> Self {
Self(self.0.saturating_sub(v.0))
}
pub fn saturating_mul(&self, v: &Self) -> Self {
Self(self.0.saturating_mul(v.0))
}
pub const MIDDLE: Self = {
Self(private_u256::U256([
u64::MAX,
u64::MAX,
u64::MAX,
u64::MAX / 2,
]))
};
pub const MAX: Self = Self(private_u256::U256::MAX);
}
impl From<U256> for private_u256::U256 {
#[inline]
fn from(number: U256) -> Self {
number.0
}
}
impl WrappingAdd for U256 {
#[inline]
fn wrapping_add(&self, other: &Self) -> Self {
Self(self.0.overflowing_add(other.0).0)
}
}
impl WrappingSub for U256 {
#[inline]
fn wrapping_sub(&self, other: &Self) -> Self {
Self(self.0.overflowing_sub(other.0).0)
}
}
impl From<u8> for U256 {
#[inline]
fn from(number: u8) -> Self {
Self(number.into())
}
}
impl From<u16> for U256 {
#[inline]
fn from(number: u16) -> Self {
Self(number.into())
}
}
impl From<u32> for U256 {
#[inline]
fn from(number: u32) -> Self {
Self(number.into())
}
}
impl From<u64> for U256 {
#[inline]
fn from(number: u64) -> Self {
Self(number.into())
}
}
impl From<u128> for U256 {
#[inline]
fn from(number: u128) -> Self {
Self(number.into())
}
}
impl TryFrom<U256> for u8 {
type Error = &'static str;
#[inline]
fn try_from(value: U256) -> Result<Self, Self::Error> {
Self::try_from(value.0)
}
}
impl TryFrom<U256> for u16 {
type Error = &'static str;
#[inline]
fn try_from(value: U256) -> Result<Self, Self::Error> {
Self::try_from(value.0)
}
}
impl TryFrom<U256> for u32 {
type Error = &'static str;
#[inline]
fn try_from(value: U256) -> Result<Self, Self::Error> {
Self::try_from(value.0)
}
}
impl TryFrom<U256> for u64 {
type Error = &'static str;
#[inline]
fn try_from(value: U256) -> Result<Self, Self::Error> {
Self::try_from(value.0)
}
}
impl Default for U256 {
fn default() -> Self {
Self::zero()
}
}