sp_runtime/generic/
block.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 and associated items.
19
20#[cfg(feature = "std")]
21use std::fmt;
22
23#[cfg(feature = "serde")]
24use serde::{Deserialize, Serialize};
25
26use crate::{
27	codec::{Codec, Decode, DecodeWithMemTracking, Encode, EncodeLike},
28	traits::{
29		self, Block as BlockT, Header as HeaderT, LazyExtrinsic, MaybeSerialize,
30		MaybeSerializeDeserialize, Member, NumberFor,
31	},
32	Justifications, OpaqueExtrinsic,
33};
34use alloc::vec::Vec;
35use core::marker::PhantomData;
36use sp_core::RuntimeDebug;
37
38/// Something to identify a block.
39#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
40pub enum BlockId<Block: BlockT> {
41	/// Identify by block header hash.
42	Hash(Block::Hash),
43	/// Identify by block number.
44	Number(NumberFor<Block>),
45}
46
47impl<Block: BlockT> BlockId<Block> {
48	/// Create a block ID from a hash.
49	pub const fn hash(hash: Block::Hash) -> Self {
50		BlockId::Hash(hash)
51	}
52
53	/// Create a block ID from a number.
54	pub const fn number(number: NumberFor<Block>) -> Self {
55		BlockId::Number(number)
56	}
57
58	/// Check if this block ID refers to the pre-genesis state.
59	pub fn is_pre_genesis(&self) -> bool {
60		match self {
61			BlockId::Hash(hash) => hash == &Default::default(),
62			BlockId::Number(_) => false,
63		}
64	}
65
66	/// Create a block ID for a pre-genesis state.
67	pub fn pre_genesis() -> Self {
68		BlockId::Hash(Default::default())
69	}
70}
71
72impl<Block: BlockT> Copy for BlockId<Block> {}
73
74#[cfg(feature = "std")]
75impl<Block: BlockT> fmt::Display for BlockId<Block> {
76	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77		write!(f, "{:?}", self)
78	}
79}
80
81/// Abstraction over a substrate block that allows us to lazily decode its extrinsics.
82#[derive(RuntimeDebug, Encode, Decode, scale_info::TypeInfo)]
83pub struct LazyBlock<Header, Extrinsic> {
84	/// The block header.
85	pub header: Header,
86	/// The accompanying extrinsics.
87	pub extrinsics: Vec<OpaqueExtrinsic>,
88
89	_phantom: PhantomData<Extrinsic>,
90}
91
92impl<Header, Extrinsic: Into<OpaqueExtrinsic>> LazyBlock<Header, Extrinsic> {
93	/// Creates a new instance of `LazyBlock` from its parts.
94	pub fn new(header: Header, extrinsics: Vec<Extrinsic>) -> Self {
95		Self {
96			header,
97			extrinsics: extrinsics.into_iter().map(|xt| xt.into()).collect(),
98			_phantom: Default::default(),
99		}
100	}
101}
102
103impl<Header, Extrinsic: Into<OpaqueExtrinsic>> From<Block<Header, Extrinsic>>
104	for LazyBlock<Header, Extrinsic>
105{
106	fn from(block: Block<Header, Extrinsic>) -> Self {
107		LazyBlock::new(block.header, block.extrinsics)
108	}
109}
110
111impl<Header, Extrinsic> EncodeLike<LazyBlock<Header, Extrinsic>> for Block<Header, Extrinsic>
112where
113	Block<Header, Extrinsic>: Encode,
114	LazyBlock<Header, Extrinsic>: Encode,
115{
116}
117
118impl<Header, Extrinsic> EncodeLike<Block<Header, Extrinsic>> for LazyBlock<Header, Extrinsic>
119where
120	Block<Header, Extrinsic>: Encode,
121	LazyBlock<Header, Extrinsic>: Encode,
122{
123}
124
125impl<Header, Extrinsic> traits::LazyBlock for LazyBlock<Header, Extrinsic>
126where
127	Header: HeaderT,
128	Extrinsic: core::fmt::Debug + LazyExtrinsic,
129{
130	type Extrinsic = Extrinsic;
131	type Header = Header;
132
133	fn header(&self) -> &Self::Header {
134		&self.header
135	}
136
137	fn header_mut(&mut self) -> &mut Self::Header {
138		&mut self.header
139	}
140
141	fn extrinsics(&self) -> impl Iterator<Item = Result<Self::Extrinsic, codec::Error>> {
142		self.extrinsics.iter().map(|xt| Self::Extrinsic::decode_unprefixed(&xt.0))
143	}
144}
145
146/// Abstraction over a substrate block.
147#[derive(
148	PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, scale_info::TypeInfo,
149)]
150#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
151#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
152#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
153pub struct Block<Header, Extrinsic> {
154	/// The block header.
155	pub header: Header,
156	/// The accompanying extrinsics.
157	pub extrinsics: Vec<Extrinsic>,
158}
159
160impl<Header, Extrinsic> traits::HeaderProvider for Block<Header, Extrinsic>
161where
162	Header: HeaderT,
163{
164	type HeaderT = Header;
165}
166
167impl<Header, Extrinsic: MaybeSerialize> traits::Block for Block<Header, Extrinsic>
168where
169	Header: HeaderT + MaybeSerializeDeserialize,
170	Extrinsic: Member
171		+ Codec
172		+ DecodeWithMemTracking
173		+ traits::ExtrinsicLike
174		+ Into<OpaqueExtrinsic>
175		+ LazyExtrinsic,
176{
177	type Extrinsic = Extrinsic;
178	type Header = Header;
179	type Hash = <Self::Header as traits::Header>::Hash;
180	type LazyBlock = LazyBlock<Header, Extrinsic>;
181
182	fn header(&self) -> &Self::Header {
183		&self.header
184	}
185	fn extrinsics(&self) -> &[Self::Extrinsic] {
186		&self.extrinsics[..]
187	}
188	fn deconstruct(self) -> (Self::Header, Vec<Self::Extrinsic>) {
189		(self.header, self.extrinsics)
190	}
191	fn new(header: Self::Header, extrinsics: Vec<Self::Extrinsic>) -> Self {
192		Block { header, extrinsics }
193	}
194}
195
196/// Abstraction over a substrate block and justification.
197#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
198#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
199#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
200#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
201pub struct SignedBlock<Block> {
202	/// Full block.
203	pub block: Block,
204	/// Block justification.
205	pub justifications: Option<Justifications>,
206}