ab_core_primitives/
pos.rs

1//! Proof of space-related data structures.
2
3use crate::hashes::Blake3Hash;
4use ab_blake3::single_block_hash;
5use ab_io_type::trivial_type::TrivialType;
6use core::fmt;
7use derive_more::{Deref, DerefMut, From, Into};
8#[cfg(feature = "scale-codec")]
9use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
10#[cfg(feature = "scale-codec")]
11use scale_info::TypeInfo;
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14#[cfg(feature = "serde")]
15use serde::{Deserializer, Serializer};
16#[cfg(feature = "serde")]
17use serde_big_array::BigArray;
18
19/// Proof of space seed.
20#[derive(Copy, Clone, Eq, PartialEq, Deref, From, Into)]
21pub struct PosSeed([u8; PosSeed::SIZE]);
22
23impl fmt::Debug for PosSeed {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        for byte in self.0 {
26            write!(f, "{byte:02x}")?;
27        }
28        Ok(())
29    }
30}
31
32impl PosSeed {
33    /// Size of proof of space seed in bytes.
34    pub const SIZE: usize = 32;
35}
36
37/// Proof of space proof bytes.
38#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut, From, Into, TrivialType)]
39#[cfg_attr(
40    feature = "scale-codec",
41    derive(Encode, Decode, TypeInfo, MaxEncodedLen)
42)]
43#[repr(C)]
44pub struct PosProof([u8; PosProof::SIZE]);
45
46impl fmt::Debug for PosProof {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        for byte in self.0 {
49            write!(f, "{byte:02x}")?;
50        }
51        Ok(())
52    }
53}
54
55#[cfg(feature = "serde")]
56#[derive(Serialize, Deserialize)]
57#[serde(transparent)]
58struct PosProofBinary(#[serde(with = "BigArray")] [u8; PosProof::SIZE]);
59
60#[cfg(feature = "serde")]
61#[derive(Serialize, Deserialize)]
62#[serde(transparent)]
63struct PosProofHex(#[serde(with = "hex")] [u8; PosProof::SIZE]);
64
65#[cfg(feature = "serde")]
66impl Serialize for PosProof {
67    #[inline]
68    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
69    where
70        S: Serializer,
71    {
72        if serializer.is_human_readable() {
73            PosProofHex(self.0).serialize(serializer)
74        } else {
75            PosProofBinary(self.0).serialize(serializer)
76        }
77    }
78}
79
80#[cfg(feature = "serde")]
81impl<'de> Deserialize<'de> for PosProof {
82    #[inline]
83    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
84    where
85        D: Deserializer<'de>,
86    {
87        Ok(Self(if deserializer.is_human_readable() {
88            PosProofHex::deserialize(deserializer)?.0
89        } else {
90            PosProofBinary::deserialize(deserializer)?.0
91        }))
92    }
93}
94
95impl Default for PosProof {
96    #[inline]
97    fn default() -> Self {
98        Self([0; Self::SIZE])
99    }
100}
101
102impl PosProof {
103    /// Constant K used for proof of space
104    pub const K: u8 = 20;
105    /// Size of proof of space proof in bytes.
106    pub const SIZE: usize = Self::K as usize * 8;
107
108    /// Proof hash.
109    pub fn hash(&self) -> Blake3Hash {
110        Blake3Hash::new(
111            single_block_hash(&self.0).expect("Less than a single block worth of bytes; qed"),
112        )
113    }
114}