Skip to main content

subsoil/runtime/generic/
header.rs

1// This file is part of Soil.
2
3// Copyright (C) Soil contributors.
4// Copyright (C) Parity Technologies (UK) Ltd.
5// SPDX-License-Identifier: Apache-2.0 OR GPL-3.0-or-later WITH Classpath-exception-2.0
6
7//! Generic implementation of a block header.
8
9use crate::core::U256;
10use crate::runtime::{
11	codec::{Codec, Decode, DecodeWithMemTracking, Encode},
12	generic::Digest,
13	scale_info::TypeInfo,
14	traits::{self, AtLeast32BitUnsigned, BlockNumber, Hash as HashT, MaybeDisplay, Member},
15};
16#[cfg(feature = "serde")]
17use serde::{Deserialize, Serialize};
18
19/// Abstraction over a block header for a substrate chain.
20#[derive(Encode, Decode, DecodeWithMemTracking, PartialEq, Eq, Clone, Debug, TypeInfo)]
21#[scale_info(skip_type_params(Hash))]
22#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
23#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
24#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
25pub struct Header<Number: Copy + Into<U256> + TryFrom<U256>, Hash: HashT> {
26	/// The parent hash.
27	pub parent_hash: Hash::Output,
28	/// The block number.
29	#[cfg_attr(
30		feature = "serde",
31		serde(serialize_with = "serialize_number", deserialize_with = "deserialize_number")
32	)]
33	#[codec(compact)]
34	pub number: Number,
35	/// The state trie merkle root
36	pub state_root: Hash::Output,
37	/// The merkle root of the extrinsics.
38	pub extrinsics_root: Hash::Output,
39	/// A chain-specific digest of data useful for light clients or referencing auxiliary data.
40	pub digest: Digest,
41}
42
43#[cfg(feature = "serde")]
44pub fn serialize_number<S, T: Copy + Into<U256> + TryFrom<U256>>(
45	val: &T,
46	s: S,
47) -> Result<S::Ok, S::Error>
48where
49	S: serde::Serializer,
50{
51	let u256: U256 = (*val).into();
52	serde::Serialize::serialize(&u256, s)
53}
54
55#[cfg(feature = "serde")]
56pub fn deserialize_number<'a, D, T: Copy + Into<U256> + TryFrom<U256>>(d: D) -> Result<T, D::Error>
57where
58	D: serde::Deserializer<'a>,
59{
60	let u256: U256 = serde::Deserialize::deserialize(d)?;
61	TryFrom::try_from(u256).map_err(|_| serde::de::Error::custom("Try from failed"))
62}
63
64impl<Number, Hash> traits::Header for Header<Number, Hash>
65where
66	Number: BlockNumber,
67	Hash: HashT,
68{
69	type Number = Number;
70	type Hash = <Hash as HashT>::Output;
71	type Hashing = Hash;
72
73	fn new(
74		number: Self::Number,
75		extrinsics_root: Self::Hash,
76		state_root: Self::Hash,
77		parent_hash: Self::Hash,
78		digest: Digest,
79	) -> Self {
80		Self { number, extrinsics_root, state_root, parent_hash, digest }
81	}
82	fn number(&self) -> &Self::Number {
83		&self.number
84	}
85
86	fn set_number(&mut self, num: Self::Number) {
87		self.number = num
88	}
89	fn extrinsics_root(&self) -> &Self::Hash {
90		&self.extrinsics_root
91	}
92
93	fn set_extrinsics_root(&mut self, root: Self::Hash) {
94		self.extrinsics_root = root
95	}
96	fn state_root(&self) -> &Self::Hash {
97		&self.state_root
98	}
99
100	fn set_state_root(&mut self, root: Self::Hash) {
101		self.state_root = root
102	}
103	fn parent_hash(&self) -> &Self::Hash {
104		&self.parent_hash
105	}
106
107	fn set_parent_hash(&mut self, hash: Self::Hash) {
108		self.parent_hash = hash
109	}
110
111	fn digest(&self) -> &Digest {
112		&self.digest
113	}
114
115	fn digest_mut(&mut self) -> &mut Digest {
116		#[cfg(feature = "std")]
117		log::debug!(target: "header", "Retrieving mutable reference to digest");
118		&mut self.digest
119	}
120}
121
122impl<Number, Hash> Header<Number, Hash>
123where
124	Number: Member
125		+ ::core::hash::Hash
126		+ Copy
127		+ MaybeDisplay
128		+ AtLeast32BitUnsigned
129		+ Codec
130		+ Into<U256>
131		+ TryFrom<U256>,
132	Hash: HashT,
133{
134	/// Convenience helper for computing the hash of the header without having
135	/// to import the trait.
136	pub fn hash(&self) -> Hash::Output {
137		Hash::hash_of(self)
138	}
139}
140
141#[cfg(all(test, feature = "std"))]
142mod tests {
143	use super::*;
144	use crate::runtime::traits::BlakeTwo256;
145
146	#[test]
147	fn should_serialize_numbers() {
148		fn serialize(num: u128) -> String {
149			let mut v = vec![];
150			{
151				let mut ser = serde_json::Serializer::new(::std::io::Cursor::new(&mut v));
152				serialize_number(&num, &mut ser).unwrap();
153			}
154			String::from_utf8(v).unwrap()
155		}
156
157		assert_eq!(serialize(0), "\"0x0\"".to_owned());
158		assert_eq!(serialize(1), "\"0x1\"".to_owned());
159		assert_eq!(serialize(u64::MAX as u128), "\"0xffffffffffffffff\"".to_owned());
160		assert_eq!(serialize(u64::MAX as u128 + 1), "\"0x10000000000000000\"".to_owned());
161	}
162
163	#[test]
164	fn should_deserialize_number() {
165		fn deserialize(num: &str) -> u128 {
166			let mut der = serde_json::Deserializer::new(serde_json::de::StrRead::new(num));
167			deserialize_number(&mut der).unwrap()
168		}
169
170		assert_eq!(deserialize("\"0x0\""), 0);
171		assert_eq!(deserialize("\"0x1\""), 1);
172		assert_eq!(deserialize("\"0xffffffffffffffff\""), u64::MAX as u128);
173		assert_eq!(deserialize("\"0x10000000000000000\""), u64::MAX as u128 + 1);
174	}
175
176	#[test]
177	fn ensure_format_is_unchanged() {
178		let header = Header::<u32, BlakeTwo256> {
179			parent_hash: BlakeTwo256::hash(b"1"),
180			number: 2,
181			state_root: BlakeTwo256::hash(b"3"),
182			extrinsics_root: BlakeTwo256::hash(b"4"),
183			digest: crate::runtime::generic::Digest {
184				logs: vec![crate::runtime::generic::DigestItem::Other(b"6".to_vec())],
185			},
186		};
187
188		let header_encoded = header.encode();
189		assert_eq!(
190			header_encoded,
191			vec![
192				146, 205, 245, 120, 196, 112, 133, 165, 153, 34, 86, 240, 220, 249, 125, 11, 25,
193				241, 241, 201, 222, 77, 95, 227, 12, 58, 206, 97, 145, 182, 229, 219, 8, 88, 19,
194				72, 51, 123, 15, 62, 20, 134, 32, 23, 61, 170, 165, 249, 77, 0, 216, 129, 112, 93,
195				203, 240, 170, 131, 239, 218, 186, 97, 210, 237, 225, 235, 134, 73, 33, 73, 151,
196				87, 78, 32, 196, 100, 56, 138, 23, 36, 32, 210, 84, 3, 104, 43, 187, 184, 12, 73,
197				104, 49, 200, 204, 31, 143, 13, 4, 0, 4, 54
198			],
199		);
200		assert_eq!(header, Header::<u32, BlakeTwo256>::decode(&mut &header_encoded[..]).unwrap());
201
202		let header = Header::<u32, BlakeTwo256> {
203			parent_hash: BlakeTwo256::hash(b"1000"),
204			number: 2000,
205			state_root: BlakeTwo256::hash(b"3000"),
206			extrinsics_root: BlakeTwo256::hash(b"4000"),
207			digest: crate::runtime::generic::Digest {
208				logs: vec![crate::runtime::generic::DigestItem::Other(b"5000".to_vec())],
209			},
210		};
211
212		let header_encoded = header.encode();
213		assert_eq!(
214			header_encoded,
215			vec![
216				197, 243, 254, 225, 31, 117, 21, 218, 179, 213, 92, 6, 247, 164, 230, 25, 47, 166,
217				140, 117, 142, 159, 195, 202, 67, 196, 238, 26, 44, 18, 33, 92, 65, 31, 219, 225,
218				47, 12, 107, 88, 153, 146, 55, 21, 226, 186, 110, 48, 167, 187, 67, 183, 228, 232,
219				118, 136, 30, 254, 11, 87, 48, 112, 7, 97, 31, 82, 146, 110, 96, 87, 152, 68, 98,
220				162, 227, 222, 78, 14, 244, 194, 120, 154, 112, 97, 222, 144, 174, 101, 220, 44,
221				111, 126, 54, 34, 155, 220, 253, 124, 4, 0, 16, 53, 48, 48, 48
222			],
223		);
224		assert_eq!(header, Header::<u32, BlakeTwo256>::decode(&mut &header_encoded[..]).unwrap());
225	}
226}