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, const_try, 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)]
262#[expect(clippy::double_parens)]
263mod private_u256 {
264    //! This module is needed to scope clippy allows
265    use parity_scale_codec::{Decode, Encode};
266    use scale_info::TypeInfo;
267
268    uint::construct_uint! {
269        #[derive(Encode, Decode, TypeInfo)]
270        pub struct U256(4);
271    }
272}
273
274/// 256-bit unsigned integer
275#[derive(
276    Debug,
277    Display,
278    Add,
279    Sub,
280    Mul,
281    Div,
282    Rem,
283    Copy,
284    Clone,
285    Ord,
286    PartialOrd,
287    Eq,
288    PartialEq,
289    Hash,
290    Encode,
291    Decode,
292    TypeInfo,
293)]
294pub struct U256(private_u256::U256);
295
296impl U256 {
297    /// Zero (additive identity) of this type.
298    #[inline]
299    pub const fn zero() -> Self {
300        Self(private_u256::U256::zero())
301    }
302
303    /// One (multiplicative identity) of this type.
304    #[inline]
305    pub fn one() -> Self {
306        Self(private_u256::U256::one())
307    }
308
309    /// Create from big endian bytes
310    pub fn from_be_bytes(bytes: [u8; 32]) -> Self {
311        Self(private_u256::U256::from_big_endian(&bytes))
312    }
313
314    /// Convert to big endian bytes
315    pub fn to_be_bytes(self) -> [u8; 32] {
316        self.0.to_big_endian()
317    }
318
319    /// Create from little endian bytes
320    pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
321        Self(private_u256::U256::from_little_endian(&bytes))
322    }
323
324    /// Convert to little endian bytes
325    pub fn to_le_bytes(self) -> [u8; 32] {
326        self.0.to_little_endian()
327    }
328
329    /// Adds two numbers, checking for overflow. If overflow happens, `None` is returned.
330    pub fn checked_add(&self, v: &Self) -> Option<Self> {
331        self.0.checked_add(v.0).map(Self)
332    }
333
334    /// Subtracts two numbers, checking for underflow. If underflow happens, `None` is returned.
335    pub fn checked_sub(&self, v: &Self) -> Option<Self> {
336        self.0.checked_sub(v.0).map(Self)
337    }
338
339    /// Multiplies two numbers, checking for underflow or overflow. If underflow or overflow
340    /// happens, `None` is returned.
341    pub fn checked_mul(&self, v: &Self) -> Option<Self> {
342        self.0.checked_mul(v.0).map(Self)
343    }
344
345    /// Divides two numbers, checking for underflow, overflow and division by zero. If any of that
346    /// happens, `None` is returned.
347    pub fn checked_div(&self, v: &Self) -> Option<Self> {
348        self.0.checked_div(v.0).map(Self)
349    }
350
351    /// Saturating addition. Computes `self + other`, saturating at the relevant high or low
352    /// boundary of the type.
353    pub fn saturating_add(&self, v: &Self) -> Self {
354        Self(self.0.saturating_add(v.0))
355    }
356
357    /// Saturating subtraction. Computes `self - other`, saturating at the relevant high or low
358    /// boundary of the type.
359    pub fn saturating_sub(&self, v: &Self) -> Self {
360        Self(self.0.saturating_sub(v.0))
361    }
362
363    /// Saturating multiplication. Computes `self * other`, saturating at the relevant high or low
364    /// boundary of the type.
365    pub fn saturating_mul(&self, v: &Self) -> Self {
366        Self(self.0.saturating_mul(v.0))
367    }
368
369    /// The middle of the piece distance field.
370    /// The analogue of `0b1000_0000` for `u8`.
371    pub const MIDDLE: Self = {
372        // TODO: This assumes that numbers are stored little endian,
373        //  should be replaced with just `Self::MAX / 2`, but it is not `const fn` in Rust yet.
374        Self(private_u256::U256([
375            u64::MAX,
376            u64::MAX,
377            u64::MAX,
378            u64::MAX / 2,
379        ]))
380    };
381
382    /// Maximum value.
383    pub const MAX: Self = Self(private_u256::U256::MAX);
384}
385
386// Necessary for division derive
387impl From<U256> for private_u256::U256 {
388    #[inline]
389    fn from(number: U256) -> Self {
390        number.0
391    }
392}
393
394impl WrappingAdd for U256 {
395    #[inline]
396    fn wrapping_add(&self, other: &Self) -> Self {
397        Self(self.0.overflowing_add(other.0).0)
398    }
399}
400
401impl WrappingSub for U256 {
402    #[inline]
403    fn wrapping_sub(&self, other: &Self) -> Self {
404        Self(self.0.overflowing_sub(other.0).0)
405    }
406}
407
408impl From<u8> for U256 {
409    #[inline]
410    fn from(number: u8) -> Self {
411        Self(number.into())
412    }
413}
414
415impl From<u16> for U256 {
416    #[inline]
417    fn from(number: u16) -> Self {
418        Self(number.into())
419    }
420}
421
422impl From<u32> for U256 {
423    #[inline]
424    fn from(number: u32) -> Self {
425        Self(number.into())
426    }
427}
428
429impl From<u64> for U256 {
430    #[inline]
431    fn from(number: u64) -> Self {
432        Self(number.into())
433    }
434}
435
436impl From<u128> for U256 {
437    #[inline]
438    fn from(number: u128) -> Self {
439        Self(number.into())
440    }
441}
442
443impl TryFrom<U256> for u8 {
444    type Error = &'static str;
445
446    #[inline]
447    fn try_from(value: U256) -> Result<Self, Self::Error> {
448        Self::try_from(value.0)
449    }
450}
451
452impl TryFrom<U256> for u16 {
453    type Error = &'static str;
454
455    #[inline]
456    fn try_from(value: U256) -> Result<Self, Self::Error> {
457        Self::try_from(value.0)
458    }
459}
460
461impl TryFrom<U256> for u32 {
462    type Error = &'static str;
463
464    #[inline]
465    fn try_from(value: U256) -> Result<Self, Self::Error> {
466        Self::try_from(value.0)
467    }
468}
469
470impl TryFrom<U256> for u64 {
471    type Error = &'static str;
472
473    #[inline]
474    fn try_from(value: U256) -> Result<Self, Self::Error> {
475        Self::try_from(value.0)
476    }
477}
478
479impl Default for U256 {
480    fn default() -> Self {
481        Self::zero()
482    }
483}