subspace_core_primitives/
lib.rs

1//! Core primitives for Subspace Network.
2
3#![cfg_attr(not(feature = "std"), no_std)]
4#![warn(rust_2018_idioms, missing_docs)]
5#![cfg_attr(feature = "std", warn(missing_debug_implementations))]
6#![feature(
7    array_chunks,
8    const_trait_impl,
9    const_try,
10    new_zeroed_alloc,
11    portable_simd,
12    step_trait
13)]
14
15pub mod checksum;
16pub mod hashes;
17pub mod objects;
18pub mod pieces;
19pub mod pos;
20pub mod pot;
21pub mod sectors;
22pub mod segments;
23pub mod solutions;
24#[cfg(test)]
25mod tests;
26
27use crate::hashes::{Blake3Hash, blake3_hash, blake3_hash_list};
28use core::fmt;
29use derive_more::{Add, AsMut, AsRef, Deref, DerefMut, Display, Div, From, Into, Mul, Rem, Sub};
30use num_traits::{WrappingAdd, WrappingSub};
31use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
32use scale_info::TypeInfo;
33#[cfg(feature = "serde")]
34use serde::{Deserialize, Serialize};
35#[cfg(feature = "serde")]
36use serde::{Deserializer, Serializer};
37use static_assertions::const_assert;
38
39// Refuse to compile on lower than 32-bit platforms
40const_assert!(core::mem::size_of::<usize>() >= core::mem::size_of::<u32>());
41
42/// Signing context used for creating reward signatures by farmers.
43pub const REWARD_SIGNING_CONTEXT: &[u8] = b"subspace_reward";
44
45/// Type of randomness.
46#[derive(
47    Default, Copy, Clone, Eq, PartialEq, From, Into, Deref, Encode, Decode, TypeInfo, MaxEncodedLen,
48)]
49pub struct Randomness([u8; Randomness::SIZE]);
50
51impl fmt::Debug for Randomness {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        write!(f, "{}", hex::encode(self.0))
54    }
55}
56
57#[cfg(feature = "serde")]
58#[derive(Serialize, Deserialize)]
59#[serde(transparent)]
60struct RandomnessBinary([u8; Randomness::SIZE]);
61
62#[cfg(feature = "serde")]
63#[derive(Serialize, Deserialize)]
64#[serde(transparent)]
65struct RandomnessHex(#[serde(with = "hex")] [u8; Randomness::SIZE]);
66
67#[cfg(feature = "serde")]
68impl Serialize for Randomness {
69    #[inline]
70    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
71    where
72        S: Serializer,
73    {
74        if serializer.is_human_readable() {
75            RandomnessHex(self.0).serialize(serializer)
76        } else {
77            RandomnessBinary(self.0).serialize(serializer)
78        }
79    }
80}
81
82#[cfg(feature = "serde")]
83impl<'de> Deserialize<'de> for Randomness {
84    #[inline]
85    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
86    where
87        D: Deserializer<'de>,
88    {
89        Ok(Self(if deserializer.is_human_readable() {
90            RandomnessHex::deserialize(deserializer)?.0
91        } else {
92            RandomnessBinary::deserialize(deserializer)?.0
93        }))
94    }
95}
96
97impl AsRef<[u8]> for Randomness {
98    #[inline]
99    fn as_ref(&self) -> &[u8] {
100        &self.0
101    }
102}
103
104impl AsMut<[u8]> for Randomness {
105    #[inline]
106    fn as_mut(&mut self) -> &mut [u8] {
107        &mut self.0
108    }
109}
110
111impl Randomness {
112    /// Size of randomness (in bytes).
113    pub const SIZE: usize = 32;
114
115    /// Derive global slot challenge from global randomness.
116    // TODO: Separate type for global challenge
117    pub fn derive_global_challenge(&self, slot: SlotNumber) -> Blake3Hash {
118        blake3_hash_list(&[&self.0, &slot.to_le_bytes()])
119    }
120}
121
122/// Block number in Subspace network.
123pub type BlockNumber = u32;
124
125/// Block hash in Subspace network.
126pub type BlockHash = [u8; 32];
127
128/// Slot number in Subspace network.
129pub type SlotNumber = u64;
130
131/// BlockForkWeight type for fork choice rules.
132///
133/// The narrower the solution range, the heavier the block is.
134pub type BlockForkWeight = u128;
135
136/// A Ristretto Schnorr public key as bytes produced by `schnorrkel` crate.
137#[derive(
138    Default,
139    Copy,
140    Clone,
141    PartialEq,
142    Eq,
143    Ord,
144    PartialOrd,
145    Hash,
146    Encode,
147    Decode,
148    TypeInfo,
149    Deref,
150    From,
151    Into,
152    DecodeWithMemTracking,
153)]
154pub struct PublicKey([u8; PublicKey::SIZE]);
155
156impl fmt::Debug for PublicKey {
157    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158        write!(f, "{}", hex::encode(self.0))
159    }
160}
161
162#[cfg(feature = "serde")]
163#[derive(Serialize, Deserialize)]
164#[serde(transparent)]
165struct PublicKeyBinary([u8; PublicKey::SIZE]);
166
167#[cfg(feature = "serde")]
168#[derive(Serialize, Deserialize)]
169#[serde(transparent)]
170struct PublicKeyHex(#[serde(with = "hex")] [u8; PublicKey::SIZE]);
171
172#[cfg(feature = "serde")]
173impl Serialize for PublicKey {
174    #[inline]
175    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
176    where
177        S: Serializer,
178    {
179        if serializer.is_human_readable() {
180            PublicKeyHex(self.0).serialize(serializer)
181        } else {
182            PublicKeyBinary(self.0).serialize(serializer)
183        }
184    }
185}
186
187#[cfg(feature = "serde")]
188impl<'de> Deserialize<'de> for PublicKey {
189    #[inline]
190    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
191    where
192        D: Deserializer<'de>,
193    {
194        Ok(Self(if deserializer.is_human_readable() {
195            PublicKeyHex::deserialize(deserializer)?.0
196        } else {
197            PublicKeyBinary::deserialize(deserializer)?.0
198        }))
199    }
200}
201
202impl fmt::Display for PublicKey {
203    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204        write!(f, "{}", hex::encode(self.0))
205    }
206}
207
208impl AsRef<[u8]> for PublicKey {
209    #[inline]
210    fn as_ref(&self) -> &[u8] {
211        &self.0
212    }
213}
214
215impl PublicKey {
216    /// Public key size in bytes
217    pub const SIZE: usize = 32;
218
219    /// Public key hash.
220    pub fn hash(&self) -> Blake3Hash {
221        blake3_hash(&self.0)
222    }
223}
224
225/// Single BLS12-381 scalar with big-endian representation, not guaranteed to be valid
226#[derive(
227    Default,
228    Copy,
229    Clone,
230    Eq,
231    PartialEq,
232    Ord,
233    PartialOrd,
234    Hash,
235    From,
236    Into,
237    AsRef,
238    AsMut,
239    Deref,
240    DerefMut,
241    Encode,
242    Decode,
243    TypeInfo,
244    DecodeWithMemTracking,
245)]
246#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
247#[cfg_attr(feature = "serde", serde(transparent))]
248pub struct ScalarBytes([u8; ScalarBytes::FULL_BYTES]);
249
250impl fmt::Debug for ScalarBytes {
251    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
252        write!(f, "{}", hex::encode(self.0))
253    }
254}
255
256impl ScalarBytes {
257    /// How many full bytes can be stored in BLS12-381 scalar (for instance before encoding). It is
258    /// actually 254 bits, but bits are mut harder to work with and likely not worth it.
259    ///
260    /// NOTE: After encoding more bytes can be used, so don't rely on this as the max number of
261    /// bytes stored within at all times!
262    pub const SAFE_BYTES: usize = 31;
263    /// How many bytes Scalar contains physically, use [`Self::SAFE_BYTES`] for the amount of data
264    /// that you can put into it safely (for instance before encoding).
265    pub const FULL_BYTES: usize = 32;
266}
267
268#[expect(clippy::manual_div_ceil)]
269mod private_u256 {
270    //! This module is needed to scope clippy allows
271    use parity_scale_codec::{Decode, Encode};
272    use scale_info::TypeInfo;
273
274    uint::construct_uint! {
275        #[derive(Encode, Decode, TypeInfo)]
276        pub struct U256(4);
277    }
278}
279
280/// 256-bit unsigned integer
281#[derive(
282    Debug,
283    Display,
284    Add,
285    Sub,
286    Mul,
287    Div,
288    Rem,
289    Copy,
290    Clone,
291    Ord,
292    PartialOrd,
293    Eq,
294    PartialEq,
295    Hash,
296    Encode,
297    Decode,
298    TypeInfo,
299)]
300pub struct U256(private_u256::U256);
301
302impl U256 {
303    /// Zero (additive identity) of this type.
304    #[inline]
305    pub const fn zero() -> Self {
306        Self(private_u256::U256::zero())
307    }
308
309    /// One (multiplicative identity) of this type.
310    #[inline]
311    pub fn one() -> Self {
312        Self(private_u256::U256::one())
313    }
314
315    /// Create from big endian bytes
316    pub fn from_be_bytes(bytes: [u8; 32]) -> Self {
317        Self(private_u256::U256::from_big_endian(&bytes))
318    }
319
320    /// Convert to big endian bytes
321    pub fn to_be_bytes(self) -> [u8; 32] {
322        self.0.to_big_endian()
323    }
324
325    /// Create from little endian bytes
326    pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
327        Self(private_u256::U256::from_little_endian(&bytes))
328    }
329
330    /// Convert to little endian bytes
331    pub fn to_le_bytes(self) -> [u8; 32] {
332        self.0.to_little_endian()
333    }
334
335    /// Adds two numbers, checking for overflow. If overflow happens, `None` is returned.
336    pub fn checked_add(&self, v: &Self) -> Option<Self> {
337        self.0.checked_add(v.0).map(Self)
338    }
339
340    /// Subtracts two numbers, checking for underflow. If underflow happens, `None` is returned.
341    pub fn checked_sub(&self, v: &Self) -> Option<Self> {
342        self.0.checked_sub(v.0).map(Self)
343    }
344
345    /// Multiplies two numbers, checking for underflow or overflow. If underflow or overflow
346    /// happens, `None` is returned.
347    pub fn checked_mul(&self, v: &Self) -> Option<Self> {
348        self.0.checked_mul(v.0).map(Self)
349    }
350
351    /// Divides two numbers, checking for underflow, overflow and division by zero. If any of that
352    /// happens, `None` is returned.
353    pub fn checked_div(&self, v: &Self) -> Option<Self> {
354        self.0.checked_div(v.0).map(Self)
355    }
356
357    /// Saturating addition. Computes `self + other`, saturating at the relevant high or low
358    /// boundary of the type.
359    pub fn saturating_add(&self, v: &Self) -> Self {
360        Self(self.0.saturating_add(v.0))
361    }
362
363    /// Saturating subtraction. Computes `self - other`, saturating at the relevant high or low
364    /// boundary of the type.
365    pub fn saturating_sub(&self, v: &Self) -> Self {
366        Self(self.0.saturating_sub(v.0))
367    }
368
369    /// Saturating multiplication. Computes `self * other`, saturating at the relevant high or low
370    /// boundary of the type.
371    pub fn saturating_mul(&self, v: &Self) -> Self {
372        Self(self.0.saturating_mul(v.0))
373    }
374
375    /// The middle of the piece distance field.
376    /// The analogue of `0b1000_0000` for `u8`.
377    pub const MIDDLE: Self = {
378        // TODO: This assumes that numbers are stored little endian,
379        //  should be replaced with just `Self::MAX / 2`, but it is not `const fn` in Rust yet.
380        Self(private_u256::U256([
381            u64::MAX,
382            u64::MAX,
383            u64::MAX,
384            u64::MAX / 2,
385        ]))
386    };
387
388    /// Maximum value.
389    pub const MAX: Self = Self(private_u256::U256::MAX);
390}
391
392// Necessary for division derive
393impl From<U256> for private_u256::U256 {
394    #[inline]
395    fn from(number: U256) -> Self {
396        number.0
397    }
398}
399
400impl WrappingAdd for U256 {
401    #[inline]
402    fn wrapping_add(&self, other: &Self) -> Self {
403        Self(self.0.overflowing_add(other.0).0)
404    }
405}
406
407impl WrappingSub for U256 {
408    #[inline]
409    fn wrapping_sub(&self, other: &Self) -> Self {
410        Self(self.0.overflowing_sub(other.0).0)
411    }
412}
413
414impl From<u8> for U256 {
415    #[inline]
416    fn from(number: u8) -> Self {
417        Self(number.into())
418    }
419}
420
421impl From<u16> for U256 {
422    #[inline]
423    fn from(number: u16) -> Self {
424        Self(number.into())
425    }
426}
427
428impl From<u32> for U256 {
429    #[inline]
430    fn from(number: u32) -> Self {
431        Self(number.into())
432    }
433}
434
435impl From<u64> for U256 {
436    #[inline]
437    fn from(number: u64) -> Self {
438        Self(number.into())
439    }
440}
441
442impl From<u128> for U256 {
443    #[inline]
444    fn from(number: u128) -> Self {
445        Self(number.into())
446    }
447}
448
449impl TryFrom<U256> for u8 {
450    type Error = &'static str;
451
452    #[inline]
453    fn try_from(value: U256) -> Result<Self, Self::Error> {
454        Self::try_from(value.0)
455    }
456}
457
458impl TryFrom<U256> for u16 {
459    type Error = &'static str;
460
461    #[inline]
462    fn try_from(value: U256) -> Result<Self, Self::Error> {
463        Self::try_from(value.0)
464    }
465}
466
467impl TryFrom<U256> for u32 {
468    type Error = &'static str;
469
470    #[inline]
471    fn try_from(value: U256) -> Result<Self, Self::Error> {
472        Self::try_from(value.0)
473    }
474}
475
476impl TryFrom<U256> for u64 {
477    type Error = &'static str;
478
479    #[inline]
480    fn try_from(value: U256) -> Result<Self, Self::Error> {
481        Self::try_from(value.0)
482    }
483}
484
485impl Default for U256 {
486    fn default() -> Self {
487        Self::zero()
488    }
489}