referrerpolicy=no-referrer-when-downgrade

sc_network_common/sync/
message.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! Network packet message types. These get serialized and put into the lower level protocol
20//! payload.
21
22use crate::role::Roles;
23
24use bitflags::bitflags;
25use codec::{Decode, Encode, Error, Input, Output};
26pub use generic::{BlockAnnounce, FromBlock};
27use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
28
29/// Type alias for using the block request type using block type parameters.
30pub type BlockRequest<B> =
31	generic::BlockRequest<<B as BlockT>::Hash, <<B as BlockT>::Header as HeaderT>::Number>;
32
33/// Type alias for using the BlockData type using block type parameters.
34pub type BlockData<B> =
35	generic::BlockData<<B as BlockT>::Header, <B as BlockT>::Hash, <B as BlockT>::Extrinsic>;
36
37/// Type alias for using the BlockResponse type using block type parameters.
38pub type BlockResponse<B> =
39	generic::BlockResponse<<B as BlockT>::Header, <B as BlockT>::Hash, <B as BlockT>::Extrinsic>;
40
41// Bits of block data and associated artifacts to request.
42bitflags! {
43	/// Node roles bitmask.
44	pub struct BlockAttributes: u8 {
45		/// Include block header.
46		const HEADER = 0b00000001;
47		/// Include block body.
48		const BODY = 0b00000010;
49		/// Include block receipt.
50		const RECEIPT = 0b00000100;
51		/// Include block message queue.
52		const MESSAGE_QUEUE = 0b00001000;
53		/// Include a justification for the block.
54		const JUSTIFICATION = 0b00010000;
55		/// Deprecated indexed-body attribute bit. Kept so that requests from older peers
56		/// still decode; the bit is ignored.
57		const DEPRECATED_INDEXED_BODY = 0b00100000;
58	}
59}
60
61impl BlockAttributes {
62	/// Encodes attributes as big endian u32, compatible with SCALE-encoding (i.e the
63	/// significant byte has zero index).
64	pub fn to_be_u32(&self) -> u32 {
65		u32::from_be_bytes([self.bits(), 0, 0, 0])
66	}
67
68	/// Decodes attributes, encoded with the `encode_to_be_u32()` call.
69	pub fn from_be_u32(encoded: u32) -> Result<Self, Error> {
70		Self::from_bits(encoded.to_be_bytes()[0])
71			.ok_or_else(|| Error::from("Invalid BlockAttributes"))
72	}
73}
74
75impl Encode for BlockAttributes {
76	fn encode_to<T: Output + ?Sized>(&self, dest: &mut T) {
77		dest.push_byte(self.bits())
78	}
79}
80
81impl codec::EncodeLike for BlockAttributes {}
82
83impl Decode for BlockAttributes {
84	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
85		Self::from_bits(input.read_byte()?).ok_or_else(|| Error::from("Invalid bytes"))
86	}
87}
88
89#[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, Decode)]
90/// Block enumeration direction.
91pub enum Direction {
92	/// Enumerate in ascending order (from child to parent).
93	Ascending = 0,
94	/// Enumerate in descending order (from parent to canonical child).
95	Descending = 1,
96}
97
98/// Block state in the chain.
99#[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, Decode)]
100pub enum BlockState {
101	/// Block is not part of the best chain.
102	Normal,
103	/// Latest best block.
104	Best,
105}
106
107/// Announcement summary used for debug logging.
108#[derive(Debug)]
109pub struct AnnouncementSummary<H: HeaderT> {
110	pub block_hash: H::Hash,
111	pub number: H::Number,
112	pub parent_hash: H::Hash,
113	pub state: Option<BlockState>,
114}
115
116impl<H: HeaderT> BlockAnnounce<H> {
117	pub fn summary(&self) -> AnnouncementSummary<H> {
118		AnnouncementSummary {
119			block_hash: self.header.hash(),
120			number: *self.header.number(),
121			parent_hash: *self.header.parent_hash(),
122			state: self.state,
123		}
124	}
125}
126
127/// Generic types.
128pub mod generic {
129	use super::{BlockAttributes, BlockState, Direction};
130	use crate::message::RequestId;
131	use codec::{Decode, Encode, Input, Output};
132	use sp_runtime::{EncodedJustification, Justifications};
133
134	/// Block data sent in the response.
135	#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
136	pub struct BlockData<Header, Hash, Extrinsic> {
137		/// Block header hash.
138		pub hash: Hash,
139		/// Block header if requested.
140		pub header: Option<Header>,
141		/// Block body if requested.
142		pub body: Option<Vec<Extrinsic>>,
143		/// Block receipt if requested.
144		pub receipt: Option<Vec<u8>>,
145		/// Block message queue if requested.
146		pub message_queue: Option<Vec<u8>>,
147		/// Justification if requested.
148		pub justification: Option<EncodedJustification>,
149		/// Justifications if requested.
150		pub justifications: Option<Justifications>,
151	}
152
153	/// Request block data from a peer.
154	#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
155	pub struct BlockRequest<Hash, Number> {
156		/// Unique request id.
157		pub id: RequestId,
158		/// Bits of block data to request.
159		pub fields: BlockAttributes,
160		/// Start from this block.
161		pub from: FromBlock<Hash, Number>,
162		/// Sequence direction.
163		pub direction: Direction,
164		/// Maximum number of blocks to return. An implementation defined maximum is used when
165		/// unspecified.
166		pub max: Option<u32>,
167	}
168
169	/// Identifies starting point of a block sequence.
170	#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
171	pub enum FromBlock<Hash, Number> {
172		/// Start with given hash.
173		Hash(Hash),
174		/// Start with given block number.
175		Number(Number),
176	}
177
178	/// Response to `BlockRequest`
179	#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
180	pub struct BlockResponse<Header, Hash, Extrinsic> {
181		/// Id of a request this response was made for.
182		pub id: RequestId,
183		/// Block data for the requested sequence.
184		pub blocks: Vec<BlockData<Header, Hash, Extrinsic>>,
185	}
186
187	/// Announce a new complete block on the network.
188	#[derive(Debug, PartialEq, Eq, Clone)]
189	pub struct BlockAnnounce<H> {
190		/// New block header.
191		pub header: H,
192		/// Block state. TODO: Remove `Option` and custom encoding when v4 becomes common.
193		pub state: Option<BlockState>,
194		/// Data associated with this block announcement, e.g. a candidate message.
195		pub data: Option<Vec<u8>>,
196	}
197
198	// Custom Encode/Decode impl to maintain backwards compatibility with v3.
199	// This assumes that the packet contains nothing but the announcement message.
200	// TODO: Get rid of it once protocol v4 is common.
201	impl<H: Encode> Encode for BlockAnnounce<H> {
202		fn encode_to<T: Output + ?Sized>(&self, dest: &mut T) {
203			self.header.encode_to(dest);
204			if let Some(state) = &self.state {
205				state.encode_to(dest);
206			}
207			if let Some(data) = &self.data {
208				data.encode_to(dest)
209			}
210		}
211	}
212
213	impl<H: Decode> Decode for BlockAnnounce<H> {
214		fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
215			let header = H::decode(input)?;
216			let state = BlockState::decode(input).ok();
217			let data = Vec::decode(input).ok();
218			Ok(Self { header, state, data })
219		}
220	}
221}
222
223/// Handshake sent when we open a block announces substream.
224#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
225pub struct BlockAnnouncesHandshake<B: BlockT> {
226	/// Roles of the node.
227	pub roles: Roles,
228	/// Best block number.
229	pub best_number: NumberFor<B>,
230	/// Best block hash.
231	pub best_hash: B::Hash,
232	/// Genesis block hash.
233	pub genesis_hash: B::Hash,
234}
235
236impl<B: BlockT> BlockAnnouncesHandshake<B> {
237	pub fn build(
238		roles: Roles,
239		best_number: NumberFor<B>,
240		best_hash: B::Hash,
241		genesis_hash: B::Hash,
242	) -> Self {
243		Self { genesis_hash, roles, best_number, best_hash }
244	}
245}