subspace_core_primitives/
pot.rs1use crate::Randomness;
4use crate::hashes::{Blake3Hash, blake3_hash, blake3_hash_list};
5use core::num::NonZeroU8;
6use core::str::FromStr;
7use core::{fmt, mem};
8use derive_more::{AsMut, AsRef, Deref, DerefMut, From};
9use parity_scale_codec::{Decode, DecodeWithMemTracking, 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; PotKey::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; PotSeed::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 DecodeWithMemTracking,
216)]
217#[repr(C)]
218pub struct PotOutput([u8; PotOutput::SIZE]);
219
220impl fmt::Debug for PotOutput {
221 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222 write!(f, "{}", hex::encode(self.0))
223 }
224}
225
226#[cfg(feature = "serde")]
227#[derive(Serialize, Deserialize)]
228#[serde(transparent)]
229struct PotOutputBinary([u8; PotOutput::SIZE]);
230
231#[cfg(feature = "serde")]
232#[derive(Serialize, Deserialize)]
233#[serde(transparent)]
234struct PotOutputHex(#[serde(with = "hex")] [u8; PotOutput::SIZE]);
235
236#[cfg(feature = "serde")]
237impl Serialize for PotOutput {
238 #[inline]
239 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
240 where
241 S: Serializer,
242 {
243 if serializer.is_human_readable() {
244 PotOutputHex(self.0).serialize(serializer)
245 } else {
246 PotOutputBinary(self.0).serialize(serializer)
247 }
248 }
249}
250
251#[cfg(feature = "serde")]
252impl<'de> Deserialize<'de> for PotOutput {
253 #[inline]
254 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
255 where
256 D: Deserializer<'de>,
257 {
258 Ok(Self(if deserializer.is_human_readable() {
259 PotOutputHex::deserialize(deserializer)?.0
260 } else {
261 PotOutputBinary::deserialize(deserializer)?.0
262 }))
263 }
264}
265
266impl fmt::Display for PotOutput {
267 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
268 write!(f, "{}", hex::encode(self.0))
269 }
270}
271
272impl PotOutput {
273 pub const SIZE: usize = 16;
275
276 #[inline]
278 pub fn derive_global_randomness(&self) -> Randomness {
279 Randomness::from(*blake3_hash(&self.0))
280 }
281
282 #[inline]
284 pub fn seed(&self) -> PotSeed {
285 PotSeed(self.0)
286 }
287
288 #[inline]
290 pub fn seed_with_entropy(&self, entropy: &Blake3Hash) -> PotSeed {
291 let hash = blake3_hash_list(&[entropy.as_ref(), &self.0]);
292 let mut seed = PotSeed::default();
293 seed.copy_from_slice(&hash[..Self::SIZE]);
294 seed
295 }
296
297 #[inline(always)]
299 pub const fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
300 unsafe { mem::transmute(value) }
302 }
303
304 #[inline(always)]
306 pub const fn repr_from_slice(value: &[Self]) -> &[[u8; Self::SIZE]] {
307 unsafe { mem::transmute(value) }
309 }
310}
311
312#[derive(
314 Debug,
315 Default,
316 Copy,
317 Clone,
318 Eq,
319 PartialEq,
320 Hash,
321 Deref,
322 DerefMut,
323 Encode,
324 Decode,
325 TypeInfo,
326 MaxEncodedLen,
327)]
328pub struct PotCheckpoints([PotOutput; Self::NUM_CHECKPOINTS.get() as usize]);
329
330impl PotCheckpoints {
331 pub const NUM_CHECKPOINTS: NonZeroU8 = NonZeroU8::new(8).expect("Not zero; qed");
333
334 #[inline]
336 pub fn output(&self) -> PotOutput {
337 self.0[Self::NUM_CHECKPOINTS.get() as usize - 1]
338 }
339}