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::{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
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 BlockForkWeight = 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 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 pub const SIZE: usize = 32;
218
219 pub fn hash(&self) -> Blake3Hash {
221 blake3_hash(&self.0)
222 }
223}
224
225#[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 pub const SAFE_BYTES: usize = 31;
263 pub const FULL_BYTES: usize = 32;
266}
267
268#[expect(clippy::manual_div_ceil)]
269mod private_u256 {
270 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#[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 #[inline]
305 pub const fn zero() -> Self {
306 Self(private_u256::U256::zero())
307 }
308
309 #[inline]
311 pub fn one() -> Self {
312 Self(private_u256::U256::one())
313 }
314
315 pub fn from_be_bytes(bytes: [u8; 32]) -> Self {
317 Self(private_u256::U256::from_big_endian(&bytes))
318 }
319
320 pub fn to_be_bytes(self) -> [u8; 32] {
322 self.0.to_big_endian()
323 }
324
325 pub fn from_le_bytes(bytes: [u8; 32]) -> Self {
327 Self(private_u256::U256::from_little_endian(&bytes))
328 }
329
330 pub fn to_le_bytes(self) -> [u8; 32] {
332 self.0.to_little_endian()
333 }
334
335 pub fn checked_add(&self, v: &Self) -> Option<Self> {
337 self.0.checked_add(v.0).map(Self)
338 }
339
340 pub fn checked_sub(&self, v: &Self) -> Option<Self> {
342 self.0.checked_sub(v.0).map(Self)
343 }
344
345 pub fn checked_mul(&self, v: &Self) -> Option<Self> {
348 self.0.checked_mul(v.0).map(Self)
349 }
350
351 pub fn checked_div(&self, v: &Self) -> Option<Self> {
354 self.0.checked_div(v.0).map(Self)
355 }
356
357 pub fn saturating_add(&self, v: &Self) -> Self {
360 Self(self.0.saturating_add(v.0))
361 }
362
363 pub fn saturating_sub(&self, v: &Self) -> Self {
366 Self(self.0.saturating_sub(v.0))
367 }
368
369 pub fn saturating_mul(&self, v: &Self) -> Self {
372 Self(self.0.saturating_mul(v.0))
373 }
374
375 pub const MIDDLE: Self = {
378 Self(private_u256::U256([
381 u64::MAX,
382 u64::MAX,
383 u64::MAX,
384 u64::MAX / 2,
385 ]))
386 };
387
388 pub const MAX: Self = Self(private_u256::U256::MAX);
390}
391
392impl 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}