sp_runtime/generic/
header.rs

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