Skip to main content

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