subspace_core_primitives/
pot.rs1use crate::hashes::{blake3_hash, blake3_hash_list, Blake3Hash};
4use crate::Randomness;
5use core::fmt;
6use core::num::NonZeroU8;
7use core::str::FromStr;
8use derive_more::{AsMut, AsRef, Deref, DerefMut, From};
9use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
10use scale_info::TypeInfo;
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13#[cfg(feature = "serde")]
14use serde::{Deserializer, Serializer};
15
16#[derive(
18 Default,
19 Copy,
20 Clone,
21 Eq,
22 PartialEq,
23 From,
24 AsRef,
25 AsMut,
26 Deref,
27 DerefMut,
28 Encode,
29 Decode,
30 TypeInfo,
31 MaxEncodedLen,
32)]
33pub struct PotKey([u8; Self::SIZE]);
34
35impl fmt::Debug for PotKey {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 write!(f, "{}", hex::encode(self.0))
38 }
39}
40
41#[cfg(feature = "serde")]
42#[derive(Serialize, Deserialize)]
43#[serde(transparent)]
44struct PotKeyBinary([u8; PotKey::SIZE]);
45
46#[cfg(feature = "serde")]
47#[derive(Serialize, Deserialize)]
48#[serde(transparent)]
49struct PotKeyHex(#[serde(with = "hex")] [u8; PotKey::SIZE]);
50
51#[cfg(feature = "serde")]
52impl Serialize for PotKey {
53 #[inline]
54 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
55 where
56 S: Serializer,
57 {
58 if serializer.is_human_readable() {
59 PotKeyHex(self.0).serialize(serializer)
60 } else {
61 PotKeyBinary(self.0).serialize(serializer)
62 }
63 }
64}
65
66#[cfg(feature = "serde")]
67impl<'de> Deserialize<'de> for PotKey {
68 #[inline]
69 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
70 where
71 D: Deserializer<'de>,
72 {
73 Ok(Self(if deserializer.is_human_readable() {
74 PotKeyHex::deserialize(deserializer)?.0
75 } else {
76 PotKeyBinary::deserialize(deserializer)?.0
77 }))
78 }
79}
80
81impl fmt::Display for PotKey {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 write!(f, "{}", hex::encode(self.0))
84 }
85}
86
87impl FromStr for PotKey {
88 type Err = hex::FromHexError;
89
90 #[inline]
91 fn from_str(s: &str) -> Result<Self, Self::Err> {
92 let mut key = Self::default();
93 hex::decode_to_slice(s, key.as_mut())?;
94
95 Ok(key)
96 }
97}
98
99impl PotKey {
100 pub const SIZE: usize = 16;
102}
103
104#[derive(
106 Default,
107 Copy,
108 Clone,
109 Eq,
110 PartialEq,
111 Hash,
112 From,
113 AsRef,
114 AsMut,
115 Deref,
116 DerefMut,
117 Encode,
118 Decode,
119 TypeInfo,
120 MaxEncodedLen,
121)]
122pub struct PotSeed([u8; Self::SIZE]);
123
124impl fmt::Debug for PotSeed {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 write!(f, "{}", hex::encode(self.0))
127 }
128}
129
130#[cfg(feature = "serde")]
131#[derive(Serialize, Deserialize)]
132#[serde(transparent)]
133struct PotSeedBinary([u8; PotSeed::SIZE]);
134
135#[cfg(feature = "serde")]
136#[derive(Serialize, Deserialize)]
137#[serde(transparent)]
138struct PotSeedHex(#[serde(with = "hex")] [u8; PotSeed::SIZE]);
139
140#[cfg(feature = "serde")]
141impl Serialize for PotSeed {
142 #[inline]
143 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
144 where
145 S: Serializer,
146 {
147 if serializer.is_human_readable() {
148 PotSeedHex(self.0).serialize(serializer)
149 } else {
150 PotSeedBinary(self.0).serialize(serializer)
151 }
152 }
153}
154
155#[cfg(feature = "serde")]
156impl<'de> Deserialize<'de> for PotSeed {
157 #[inline]
158 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
159 where
160 D: Deserializer<'de>,
161 {
162 Ok(Self(if deserializer.is_human_readable() {
163 PotSeedHex::deserialize(deserializer)?.0
164 } else {
165 PotSeedBinary::deserialize(deserializer)?.0
166 }))
167 }
168}
169
170impl fmt::Display for PotSeed {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 write!(f, "{}", hex::encode(self.0))
173 }
174}
175
176impl PotSeed {
177 pub const SIZE: usize = 16;
179
180 #[inline]
182 pub fn from_genesis(genesis_block_hash: &[u8], external_entropy: &[u8]) -> Self {
183 let hash = blake3_hash_list(&[genesis_block_hash, external_entropy]);
184 let mut seed = Self::default();
185 seed.copy_from_slice(&hash[..Self::SIZE]);
186 seed
187 }
188
189 #[inline]
191 pub fn key(&self) -> PotKey {
192 let mut key = PotKey::default();
193 key.copy_from_slice(&blake3_hash(&self.0)[..Self::SIZE]);
194 key
195 }
196}
197
198#[derive(
200 Default,
201 Copy,
202 Clone,
203 Eq,
204 PartialEq,
205 Hash,
206 From,
207 AsRef,
208 AsMut,
209 Deref,
210 DerefMut,
211 Encode,
212 Decode,
213 TypeInfo,
214 MaxEncodedLen,
215)]
216pub struct PotOutput([u8; Self::SIZE]);
217
218impl fmt::Debug for PotOutput {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 write!(f, "{}", hex::encode(self.0))
221 }
222}
223
224#[cfg(feature = "serde")]
225#[derive(Serialize, Deserialize)]
226#[serde(transparent)]
227struct PotOutputBinary([u8; PotOutput::SIZE]);
228
229#[cfg(feature = "serde")]
230#[derive(Serialize, Deserialize)]
231#[serde(transparent)]
232struct PotOutputHex(#[serde(with = "hex")] [u8; PotOutput::SIZE]);
233
234#[cfg(feature = "serde")]
235impl Serialize for PotOutput {
236 #[inline]
237 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
238 where
239 S: Serializer,
240 {
241 if serializer.is_human_readable() {
242 PotOutputHex(self.0).serialize(serializer)
243 } else {
244 PotOutputBinary(self.0).serialize(serializer)
245 }
246 }
247}
248
249#[cfg(feature = "serde")]
250impl<'de> Deserialize<'de> for PotOutput {
251 #[inline]
252 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
253 where
254 D: Deserializer<'de>,
255 {
256 Ok(Self(if deserializer.is_human_readable() {
257 PotOutputHex::deserialize(deserializer)?.0
258 } else {
259 PotOutputBinary::deserialize(deserializer)?.0
260 }))
261 }
262}
263
264impl fmt::Display for PotOutput {
265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266 write!(f, "{}", hex::encode(self.0))
267 }
268}
269
270impl PotOutput {
271 pub const SIZE: usize = 16;
273
274 #[inline]
276 pub fn derive_global_randomness(&self) -> Randomness {
277 Randomness::from(*blake3_hash(&self.0))
278 }
279
280 #[inline]
282 pub fn seed(&self) -> PotSeed {
283 PotSeed(self.0)
284 }
285
286 #[inline]
288 pub fn seed_with_entropy(&self, entropy: &Blake3Hash) -> PotSeed {
289 let hash = blake3_hash_list(&[entropy.as_ref(), &self.0]);
290 let mut seed = PotSeed::default();
291 seed.copy_from_slice(&hash[..Self::SIZE]);
292 seed
293 }
294}
295
296#[derive(
298 Debug,
299 Default,
300 Copy,
301 Clone,
302 Eq,
303 PartialEq,
304 Hash,
305 Deref,
306 DerefMut,
307 Encode,
308 Decode,
309 TypeInfo,
310 MaxEncodedLen,
311)]
312pub struct PotCheckpoints([PotOutput; Self::NUM_CHECKPOINTS.get() as usize]);
313
314impl PotCheckpoints {
315 pub const NUM_CHECKPOINTS: NonZeroU8 = NonZeroU8::new(8).expect("Not zero; qed");
317
318 #[inline]
320 pub fn output(&self) -> PotOutput {
321 self.0[Self::NUM_CHECKPOINTS.get() as usize - 1]
322 }
323}