ab_core_primitives/
pos.rs

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