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