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::{blake3_hash, blake3_hash_list, Blake3Hash};
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, 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/// BlockWeight type for fork choice rules.
132///
133/// The closer solution's tag is to the target, the heavier it is.
134pub type BlockWeight = 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)]
153pub struct PublicKey([u8; PublicKey::SIZE]);
154
155impl fmt::Debug for PublicKey {
156    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157        write!(f, "{}", hex::encode(self.0))
158    }
159}
160
161#[cfg(feature = "serde")]
162#[derive(Serialize, Deserialize)]
163#[serde(transparent)]
164struct PublicKeyBinary([u8; PublicKey::SIZE]);
165
166#[cfg(feature = "serde")]
167#[derive(Serialize, Deserialize)]
168#[serde(transparent)]
169struct PublicKeyHex(#[serde(with = "hex")] [u8; PublicKey::SIZE]);
170
171#[cfg(feature = "serde")]
172impl Serialize for PublicKey {
173    #[inline]
174    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
175    where
176        S: Serializer,
177    {
178        if serializer.is_human_readable() {
179            PublicKeyHex(self.0).serialize(serializer)
180        } else {
181            PublicKeyBinary(self.0).serialize(serializer)
182        }
183    }
184}
185
186#[cfg(feature = "serde")]
187impl<'de> Deserialize<'de> for PublicKey {
188    #[inline]
189    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
190    where
191        D: Deserializer<'de>,
192    {
193        Ok(Self(if deserializer.is_human_readable() {
194            PublicKeyHex::deserialize(deserializer)?.0
195        } else {
196            PublicKeyBinary::deserialize(deserializer)?.0
197        }))
198    }
199}
200
201impl fmt::Display for PublicKey {
202    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203        write!(f, "{}", hex::encode(self.0))
204    }
205}
206
207impl AsRef<[u8]> for PublicKey {
208    #[inline]
209    fn as_ref(&self) -> &[u8] {
210        &self.0
211    }
212}
213
214impl PublicKey {
215    /// Public key size in bytes
216    pub const SIZE: usize = 32;
217
218    /// Public key hash.
219    pub fn hash(&self) -> Blake3Hash {
220        blake3_hash(&self.0)
221    }
222}
223
224/// Single BLS12-381 scalar with big-endian representation, not guaranteed to be valid
225#[derive(
226    Default,
227    Copy,
228    Clone,
229    Eq,
230    PartialEq,
231    Ord,
232    PartialOrd,
233    Hash,
234    From,
235    Into,
236    AsRef,
237    AsMut,
238    Deref,
239    DerefMut,
240    Encode,
241    Decode,
242    TypeInfo,
243)]
244#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
245#[cfg_attr(feature = "serde", serde(transparent))]
246pub struct ScalarBytes([u8; ScalarBytes::FULL_BYTES]);
247
248impl fmt::Debug for ScalarBytes {
249    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250        write!(f, "{}", hex::encode(self.0))
251    }
252}
253
254impl ScalarBytes {
255    /// How many full bytes can be stored in BLS12-381 scalar (for instance before encoding). It is
256    /// actually 254 bits, but bits are mut harder to work with and likely not worth it.
257    ///
258    /// NOTE: After encoding more bytes can be used, so don't rely on this as the max number of
259    /// bytes stored within at all times!
260    pub const SAFE_BYTES: usize = 31;
261    /// How many bytes Scalar contains physically, use [`Self::SAFE_BYTES`] for the amount of data
262    /// that you can put into it safely (for instance before encoding).
263    pub const FULL_BYTES: usize = 32;
264}
265
266#[expect(clippy::manual_div_ceil)]
267mod private_u256 {
268    //! This module is needed to scope clippy allows
269    use parity_scale_codec::{Decode, Encode};
270    use scale_info::TypeInfo;
271
272    uint::construct_uint! {
273        #[derive(Encode, Decode, TypeInfo)]
274        pub struct U256(4);
275    }
276}
277
278/// 256-bit unsigned integer
279#[derive(
280    Debug,
281    Display,
282    Add,
283    Sub,
284    Mul,
285    Div,
286    Rem,
287    Copy,
288    Clone,
289    Ord,
290    PartialOrd,
291    Eq,
292    PartialEq,
293    Hash,
294    Encode,
295    Decode,
296    TypeInfo,
297)]
298pub struct U256(private_u256::U256);
299
300impl U256 {
301    /// Zero (additive identity) of this type.
302    #[inline]
303    pub const fn zero() -> Self {
304        Self(private_u256::U256::zero())
305    }
306
307    /// One (multiplicative identity) of this type.
308    #[inline]
309    pub fn one() -> Self {
310        Self(private_u256::U256::one())
311    }
312
313    /// Create from big endian bytes
314    pub fn from_be_bytes(bytes: [u8; 32]) -> Self {
315        Self(private_u256::U256::from_big_endian(&bytes))
316    }
317
318    /// Convert to big endian bytes
319    pub fn to_be_bytes(self) -> [u8; 32] {
320        self.0.to_big_endian()
321    }
322
323    /// Create from little endian bytes
324    pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
325        Self(private_u256::U256::from_little_endian(&bytes))
326    }
327
328    /// Convert to little endian bytes
329    pub fn to_le_bytes(self) -> [u8; 32] {
330        self.0.to_little_endian()
331    }
332
333    /// Adds two numbers, checking for overflow. If overflow happens, `None` is returned.
334    pub fn checked_add(&self, v: &Self) -> Option<Self> {
335        self.0.checked_add(v.0).map(Self)
336    }
337
338    /// Subtracts two numbers, checking for underflow. If underflow happens, `None` is returned.
339    pub fn checked_sub(&self, v: &Self) -> Option<Self> {
340        self.0.checked_sub(v.0).map(Self)
341    }
342
343    /// Multiplies two numbers, checking for underflow or overflow. If underflow or overflow
344    /// happens, `None` is returned.
345    pub fn checked_mul(&self, v: &Self) -> Option<Self> {
346        self.0.checked_mul(v.0).map(Self)
347    }
348
349    /// Divides two numbers, checking for underflow, overflow and division by zero. If any of that
350    /// happens, `None` is returned.
351    pub fn checked_div(&self, v: &Self) -> Option<Self> {
352        self.0.checked_div(v.0).map(Self)
353    }
354
355    /// Saturating addition. Computes `self + other`, saturating at the relevant high or low
356    /// boundary of the type.
357    pub fn saturating_add(&self, v: &Self) -> Self {
358        Self(self.0.saturating_add(v.0))
359    }
360
361    /// Saturating subtraction. Computes `self - other`, saturating at the relevant high or low
362    /// boundary of the type.
363    pub fn saturating_sub(&self, v: &Self) -> Self {
364        Self(self.0.saturating_sub(v.0))
365    }
366
367    /// Saturating multiplication. Computes `self * other`, saturating at the relevant high or low
368    /// boundary of the type.
369    pub fn saturating_mul(&self, v: &Self) -> Self {
370        Self(self.0.saturating_mul(v.0))
371    }
372
373    /// The middle of the piece distance field.
374    /// The analogue of `0b1000_0000` for `u8`.
375    pub const MIDDLE: Self = {
376        // TODO: This assumes that numbers are stored little endian,
377        //  should be replaced with just `Self::MAX / 2`, but it is not `const fn` in Rust yet.
378        Self(private_u256::U256([
379            u64::MAX,
380            u64::MAX,
381            u64::MAX,
382            u64::MAX / 2,
383        ]))
384    };
385
386    /// Maximum value.
387    pub const MAX: Self = Self(private_u256::U256::MAX);
388}
389
390// Necessary for division derive
391impl From<U256> for private_u256::U256 {
392    #[inline]
393    fn from(number: U256) -> Self {
394        number.0
395    }
396}
397
398impl WrappingAdd for U256 {
399    #[inline]
400    fn wrapping_add(&self, other: &Self) -> Self {
401        Self(self.0.overflowing_add(other.0).0)
402    }
403}
404
405impl WrappingSub for U256 {
406    #[inline]
407    fn wrapping_sub(&self, other: &Self) -> Self {
408        Self(self.0.overflowing_sub(other.0).0)
409    }
410}
411
412impl From<u8> for U256 {
413    #[inline]
414    fn from(number: u8) -> Self {
415        Self(number.into())
416    }
417}
418
419impl From<u16> for U256 {
420    #[inline]
421    fn from(number: u16) -> Self {
422        Self(number.into())
423    }
424}
425
426impl From<u32> for U256 {
427    #[inline]
428    fn from(number: u32) -> Self {
429        Self(number.into())
430    }
431}
432
433impl From<u64> for U256 {
434    #[inline]
435    fn from(number: u64) -> Self {
436        Self(number.into())
437    }
438}
439
440impl From<u128> for U256 {
441    #[inline]
442    fn from(number: u128) -> Self {
443        Self(number.into())
444    }
445}
446
447impl TryFrom<U256> for u8 {
448    type Error = &'static str;
449
450    #[inline]
451    fn try_from(value: U256) -> Result<Self, Self::Error> {
452        Self::try_from(value.0)
453    }
454}
455
456impl TryFrom<U256> for u16 {
457    type Error = &'static str;
458
459    #[inline]
460    fn try_from(value: U256) -> Result<Self, Self::Error> {
461        Self::try_from(value.0)
462    }
463}
464
465impl TryFrom<U256> for u32 {
466    type Error = &'static str;
467
468    #[inline]
469    fn try_from(value: U256) -> Result<Self, Self::Error> {
470        Self::try_from(value.0)
471    }
472}
473
474impl TryFrom<U256> for u64 {
475    type Error = &'static str;
476
477    #[inline]
478    fn try_from(value: U256) -> Result<Self, Self::Error> {
479        Self::try_from(value.0)
480    }
481}
482
483impl Default for U256 {
484    fn default() -> Self {
485        Self::zero()
486    }
487}