subspace_core_primitives/
lib.rs1#![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
39const_assert!(core::mem::size_of::<usize>() >= core::mem::size_of::<u32>());
41
42pub const REWARD_SIGNING_CONTEXT: &[u8] = b"subspace_reward";
44
45#[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 pub const SIZE: usize = 32;
114
115 pub fn derive_global_challenge(&self, slot: SlotNumber) -> Blake3Hash {
118 blake3_hash_list(&[&self.0, &slot.to_le_bytes()])
119 }
120}
121
122pub type BlockNumber = u32;
124
125pub type BlockHash = [u8; 32];
127
128pub type SlotNumber = u64;
130
131pub type BlockWeight = u128;
135
136#[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 pub const SIZE: usize = 32;
217
218 pub fn hash(&self) -> Blake3Hash {
220 blake3_hash(&self.0)
221 }
222}
223
224#[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 pub const SAFE_BYTES: usize = 31;
261 pub const FULL_BYTES: usize = 32;
264}
265
266#[expect(clippy::manual_div_ceil)]
267mod private_u256 {
268 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#[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 #[inline]
303 pub const fn zero() -> Self {
304 Self(private_u256::U256::zero())
305 }
306
307 #[inline]
309 pub fn one() -> Self {
310 Self(private_u256::U256::one())
311 }
312
313 pub fn from_be_bytes(bytes: [u8; 32]) -> Self {
315 Self(private_u256::U256::from_big_endian(&bytes))
316 }
317
318 pub fn to_be_bytes(self) -> [u8; 32] {
320 self.0.to_big_endian()
321 }
322
323 pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
325 Self(private_u256::U256::from_little_endian(&bytes))
326 }
327
328 pub fn to_le_bytes(self) -> [u8; 32] {
330 self.0.to_little_endian()
331 }
332
333 pub fn checked_add(&self, v: &Self) -> Option<Self> {
335 self.0.checked_add(v.0).map(Self)
336 }
337
338 pub fn checked_sub(&self, v: &Self) -> Option<Self> {
340 self.0.checked_sub(v.0).map(Self)
341 }
342
343 pub fn checked_mul(&self, v: &Self) -> Option<Self> {
346 self.0.checked_mul(v.0).map(Self)
347 }
348
349 pub fn checked_div(&self, v: &Self) -> Option<Self> {
352 self.0.checked_div(v.0).map(Self)
353 }
354
355 pub fn saturating_add(&self, v: &Self) -> Self {
358 Self(self.0.saturating_add(v.0))
359 }
360
361 pub fn saturating_sub(&self, v: &Self) -> Self {
364 Self(self.0.saturating_sub(v.0))
365 }
366
367 pub fn saturating_mul(&self, v: &Self) -> Self {
370 Self(self.0.saturating_mul(v.0))
371 }
372
373 pub const MIDDLE: Self = {
376 Self(private_u256::U256([
379 u64::MAX,
380 u64::MAX,
381 u64::MAX,
382 u64::MAX / 2,
383 ]))
384 };
385
386 pub const MAX: Self = Self(private_u256::U256::MAX);
388}
389
390impl 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}