1use super::{Config, DefaultExtrinsicParams, DefaultExtrinsicParamsBuilder, Hasher, Header};
8pub use crate::utils::{AccountId32, MultiAddress, MultiSignature};
9use alloc::format;
10use alloc::vec::Vec;
11use codec::{Decode, Encode};
12pub use primitive_types::{H256, U256};
13use serde::{Deserialize, Serialize};
14use subxt_metadata::Metadata;
15
16#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
22pub enum SubstrateConfig {}
23
24impl Config for SubstrateConfig {
25 type AccountId = AccountId32;
26 type Address = MultiAddress<Self::AccountId, u32>;
27 type Signature = MultiSignature;
28 type Hasher = DynamicHasher256;
29 type Header = SubstrateHeader<u32, DynamicHasher256>;
30 type ExtrinsicParams = SubstrateExtrinsicParams<Self>;
31 type AssetId = u32;
32}
33
34pub type SubstrateExtrinsicParams<T> = DefaultExtrinsicParams<T>;
37
38pub type SubstrateExtrinsicParamsBuilder<T> = DefaultExtrinsicParamsBuilder<T>;
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub struct BlakeTwo256;
45
46impl Hasher for BlakeTwo256 {
47 type Output = H256;
48
49 fn new(_metadata: &Metadata) -> Self {
50 Self
51 }
52
53 fn hash(&self, s: &[u8]) -> Self::Output {
54 sp_crypto_hashing::blake2_256(s).into()
55 }
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub struct DynamicHasher256(HashType);
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66enum HashType {
67 BlakeTwo256,
69 Keccak256,
71 Unknown,
73}
74
75impl Hasher for DynamicHasher256 {
76 type Output = H256;
77
78 fn new(metadata: &Metadata) -> Self {
79 let Some(system_pallet) = metadata.pallet_by_name("System") else {
81 return Self(HashType::Unknown);
82 };
83 let Some(hash_ty_id) = system_pallet.associated_type_id("Hashing") else {
84 return Self(HashType::Unknown);
85 };
86
87 let ty = metadata
88 .types()
89 .resolve(hash_ty_id)
90 .expect("Type information for 'Hashing' associated type should be in metadata");
91
92 let hash_type = match ty.path.ident().as_deref().unwrap_or("") {
93 "BlakeTwo256" => HashType::BlakeTwo256,
94 "Keccak256" => HashType::Keccak256,
95 _ => HashType::Unknown,
96 };
97
98 Self(hash_type)
99 }
100
101 fn hash(&self, s: &[u8]) -> Self::Output {
102 match self.0 {
103 HashType::BlakeTwo256 | HashType::Unknown => sp_crypto_hashing::blake2_256(s).into(),
104 HashType::Keccak256 => sp_crypto_hashing::keccak_256(s).into(),
105 }
106 }
107}
108
109#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
112#[serde(rename_all = "camelCase")]
113pub struct SubstrateHeader<N: Copy + Into<U256> + TryFrom<U256>, H: Hasher> {
114 pub parent_hash: H::Output,
116 #[serde(
118 serialize_with = "serialize_number",
119 deserialize_with = "deserialize_number"
120 )]
121 #[codec(compact)]
122 pub number: N,
123 pub state_root: H::Output,
125 pub extrinsics_root: H::Output,
127 pub digest: Digest,
129}
130
131impl<N, H> Header for SubstrateHeader<N, H>
132where
133 N: Copy + Into<u64> + Into<U256> + TryFrom<U256> + Encode,
134 H: Hasher,
135 SubstrateHeader<N, H>: Encode + Decode,
136{
137 type Number = N;
138 type Hasher = H;
139
140 fn number(&self) -> Self::Number {
141 self.number
142 }
143}
144
145#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Default)]
147pub struct Digest {
148 pub logs: Vec<DigestItem>,
150}
151
152#[derive(Debug, PartialEq, Eq, Clone)]
155pub enum DigestItem {
156 PreRuntime(ConsensusEngineId, Vec<u8>),
169
170 Consensus(ConsensusEngineId, Vec<u8>),
174
175 Seal(ConsensusEngineId, Vec<u8>),
178
179 Other(Vec<u8>),
181
182 RuntimeEnvironmentUpdated,
189}
190
191#[repr(u32)]
193#[derive(Encode, Decode)]
194enum DigestItemType {
195 Other = 0u32,
196 Consensus = 4u32,
197 Seal = 5u32,
198 PreRuntime = 6u32,
199 RuntimeEnvironmentUpdated = 8u32,
200}
201impl Encode for DigestItem {
202 fn encode(&self) -> Vec<u8> {
203 let mut v = Vec::new();
204
205 match self {
206 Self::Consensus(val, data) => {
207 DigestItemType::Consensus.encode_to(&mut v);
208 (val, data).encode_to(&mut v);
209 }
210 Self::Seal(val, sig) => {
211 DigestItemType::Seal.encode_to(&mut v);
212 (val, sig).encode_to(&mut v);
213 }
214 Self::PreRuntime(val, data) => {
215 DigestItemType::PreRuntime.encode_to(&mut v);
216 (val, data).encode_to(&mut v);
217 }
218 Self::Other(val) => {
219 DigestItemType::Other.encode_to(&mut v);
220 val.encode_to(&mut v);
221 }
222 Self::RuntimeEnvironmentUpdated => {
223 DigestItemType::RuntimeEnvironmentUpdated.encode_to(&mut v);
224 }
225 }
226
227 v
228 }
229}
230impl Decode for DigestItem {
231 fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
232 let item_type: DigestItemType = Decode::decode(input)?;
233 match item_type {
234 DigestItemType::PreRuntime => {
235 let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
236 Ok(Self::PreRuntime(vals.0, vals.1))
237 }
238 DigestItemType::Consensus => {
239 let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
240 Ok(Self::Consensus(vals.0, vals.1))
241 }
242 DigestItemType::Seal => {
243 let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
244 Ok(Self::Seal(vals.0, vals.1))
245 }
246 DigestItemType::Other => Ok(Self::Other(Decode::decode(input)?)),
247 DigestItemType::RuntimeEnvironmentUpdated => Ok(Self::RuntimeEnvironmentUpdated),
248 }
249 }
250}
251
252pub type ConsensusEngineId = [u8; 4];
254
255impl serde::Serialize for DigestItem {
256 fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
257 where
258 S: serde::Serializer,
259 {
260 self.using_encoded(|bytes| impl_serde::serialize::serialize(bytes, seq))
261 }
262}
263
264impl<'a> serde::Deserialize<'a> for DigestItem {
265 fn deserialize<D>(de: D) -> Result<Self, D::Error>
266 where
267 D: serde::Deserializer<'a>,
268 {
269 let r = impl_serde::serialize::deserialize(de)?;
270 Decode::decode(&mut &r[..])
271 .map_err(|e| serde::de::Error::custom(format!("Decode error: {e}")))
272 }
273}
274
275fn serialize_number<S, T: Copy + Into<U256>>(val: &T, s: S) -> Result<S::Ok, S::Error>
276where
277 S: serde::Serializer,
278{
279 let u256: U256 = (*val).into();
280 serde::Serialize::serialize(&u256, s)
281}
282
283fn deserialize_number<'a, D, T: TryFrom<U256>>(d: D) -> Result<T, D::Error>
284where
285 D: serde::Deserializer<'a>,
286{
287 let number_or_hex = NumberOrHex::deserialize(d)?;
290 let u256 = number_or_hex.into_u256();
291 TryFrom::try_from(u256).map_err(|_| serde::de::Error::custom("Try from failed"))
292}
293
294#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
303#[serde(untagged)]
304pub enum NumberOrHex {
305 Number(u64),
307 Hex(U256),
309}
310
311impl NumberOrHex {
312 pub fn into_u256(self) -> U256 {
314 match self {
315 NumberOrHex::Number(n) => n.into(),
316 NumberOrHex::Hex(h) => h,
317 }
318 }
319}
320
321impl From<NumberOrHex> for U256 {
322 fn from(num_or_hex: NumberOrHex) -> U256 {
323 num_or_hex.into_u256()
324 }
325}
326
327macro_rules! into_number_or_hex {
328 ($($t: ty)+) => {
329 $(
330 impl From<$t> for NumberOrHex {
331 fn from(x: $t) -> Self {
332 NumberOrHex::Number(x.into())
333 }
334 }
335 )+
336 }
337}
338into_number_or_hex!(u8 u16 u32 u64);
339
340impl From<u128> for NumberOrHex {
341 fn from(n: u128) -> Self {
342 NumberOrHex::Hex(n.into())
343 }
344}
345
346impl From<U256> for NumberOrHex {
347 fn from(n: U256) -> Self {
348 NumberOrHex::Hex(n)
349 }
350}
351
352#[cfg(test)]
353mod test {
354 use super::*;
355
356 #[test]
359 fn can_deserialize_numeric_block_number() {
360 let numeric_block_number_json = r#"
361 {
362 "digest": {
363 "logs": []
364 },
365 "extrinsicsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
366 "number": 4,
367 "parentHash": "0xcb2690b2c85ceab55be03fc7f7f5f3857e7efeb7a020600ebd4331e10be2f7a5",
368 "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000"
369 }
370 "#;
371
372 let header: SubstrateHeader<u32, BlakeTwo256> =
373 serde_json::from_str(numeric_block_number_json).expect("valid block header");
374 assert_eq!(header.number(), 4);
375 }
376
377 #[test]
379 fn can_deserialize_hex_block_number() {
380 let numeric_block_number_json = r#"
381 {
382 "digest": {
383 "logs": []
384 },
385 "extrinsicsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
386 "number": "0x04",
387 "parentHash": "0xcb2690b2c85ceab55be03fc7f7f5f3857e7efeb7a020600ebd4331e10be2f7a5",
388 "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000"
389 }
390 "#;
391
392 let header: SubstrateHeader<u32, BlakeTwo256> =
393 serde_json::from_str(numeric_block_number_json).expect("valid block header");
394 assert_eq!(header.number(), 4);
395 }
396}