sc_network_sync/
types.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//! Common syncing types.
20
21use futures::Stream;
22use sc_network_common::{role::Roles, types::ReputationChange};
23
24use crate::strategy::{state_sync::StateSyncProgress, warp::WarpSyncProgress};
25
26use sc_network_common::sync::message::BlockRequest;
27use sc_network_types::PeerId;
28use sp_runtime::traits::{Block as BlockT, NumberFor};
29
30use std::{any::Any, fmt, fmt::Formatter, pin::Pin, sync::Arc};
31
32/// The sync status of a peer we are trying to sync with
33#[derive(Debug)]
34pub struct PeerInfo<Block: BlockT> {
35	/// Their best block hash.
36	pub best_hash: Block::Hash,
37	/// Their best block number.
38	pub best_number: NumberFor<Block>,
39}
40
41/// Info about a peer's known state (both full and light).
42#[derive(Debug)]
43pub struct ExtendedPeerInfo<B: BlockT> {
44	/// Roles
45	pub roles: Roles,
46	/// Peer best block hash
47	pub best_hash: B::Hash,
48	/// Peer best block number
49	pub best_number: NumberFor<B>,
50}
51
52impl<B> Clone for ExtendedPeerInfo<B>
53where
54	B: BlockT,
55{
56	fn clone(&self) -> Self {
57		Self { roles: self.roles, best_hash: self.best_hash, best_number: self.best_number }
58	}
59}
60
61impl<B> Copy for ExtendedPeerInfo<B> where B: BlockT {}
62
63/// Reported sync state.
64#[derive(Clone, Eq, PartialEq, Debug)]
65pub enum SyncState<BlockNumber> {
66	/// Initial sync is complete, keep-up sync is active.
67	Idle,
68	/// Actively catching up with the chain.
69	Downloading { target: BlockNumber },
70	/// All blocks are downloaded and are being imported.
71	Importing { target: BlockNumber },
72}
73
74impl<BlockNumber> SyncState<BlockNumber> {
75	/// Are we actively catching up with the chain?
76	pub fn is_major_syncing(&self) -> bool {
77		!matches!(self, SyncState::Idle)
78	}
79}
80
81/// Syncing status and statistics.
82#[derive(Debug, Clone)]
83pub struct SyncStatus<Block: BlockT> {
84	/// Current global sync state.
85	pub state: SyncState<NumberFor<Block>>,
86	/// Target sync block number.
87	pub best_seen_block: Option<NumberFor<Block>>,
88	/// Number of peers participating in syncing.
89	pub num_peers: u32,
90	/// Number of blocks queued for import
91	pub queued_blocks: u32,
92	/// State sync status in progress, if any.
93	pub state_sync: Option<StateSyncProgress>,
94	/// Warp sync in progress, if any.
95	pub warp_sync: Option<WarpSyncProgress<Block>>,
96}
97
98/// A peer did not behave as expected and should be reported.
99#[derive(Debug, Clone, PartialEq, Eq)]
100pub struct BadPeer(pub PeerId, pub ReputationChange);
101
102impl fmt::Display for BadPeer {
103	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104		write!(f, "Bad peer {}; Reputation change: {:?}", self.0, self.1)
105	}
106}
107
108impl std::error::Error for BadPeer {}
109
110#[derive(Debug)]
111pub enum PeerRequest<B: BlockT> {
112	Block(BlockRequest<B>),
113	State,
114	WarpProof,
115}
116
117#[derive(Debug)]
118pub enum PeerRequestType {
119	Block,
120	State,
121	WarpProof,
122}
123
124impl<B: BlockT> PeerRequest<B> {
125	pub fn get_type(&self) -> PeerRequestType {
126		match self {
127			PeerRequest::Block(_) => PeerRequestType::Block,
128			PeerRequest::State => PeerRequestType::State,
129			PeerRequest::WarpProof => PeerRequestType::WarpProof,
130		}
131	}
132}
133
134/// Wrapper for implementation-specific state request.
135///
136/// NOTE: Implementation must be able to encode and decode it for network purposes.
137pub struct OpaqueStateRequest(pub Box<dyn Any + Send>);
138
139impl fmt::Debug for OpaqueStateRequest {
140	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
141		f.debug_struct("OpaqueStateRequest").finish()
142	}
143}
144
145/// Wrapper for implementation-specific state response.
146///
147/// NOTE: Implementation must be able to encode and decode it for network purposes.
148pub struct OpaqueStateResponse(pub Box<dyn Any + Send>);
149
150impl fmt::Debug for OpaqueStateResponse {
151	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
152		f.debug_struct("OpaqueStateResponse").finish()
153	}
154}
155
156/// Provides high-level status of syncing.
157#[async_trait::async_trait]
158pub trait SyncStatusProvider<Block: BlockT>: Send + Sync {
159	/// Get high-level view of the syncing status.
160	async fn status(&self) -> Result<SyncStatus<Block>, ()>;
161}
162
163#[async_trait::async_trait]
164impl<T, Block> SyncStatusProvider<Block> for Arc<T>
165where
166	T: ?Sized,
167	T: SyncStatusProvider<Block>,
168	Block: BlockT,
169{
170	async fn status(&self) -> Result<SyncStatus<Block>, ()> {
171		T::status(self).await
172	}
173}
174
175/// Syncing-related events that other protocols can subscribe to.
176pub enum SyncEvent {
177	/// Peer that the syncing implementation is tracking connected.
178	PeerConnected(PeerId),
179
180	/// Peer that the syncing implementation was tracking disconnected.
181	PeerDisconnected(PeerId),
182}
183
184pub trait SyncEventStream: Send + Sync {
185	/// Subscribe to syncing-related events.
186	fn event_stream(&self, name: &'static str) -> Pin<Box<dyn Stream<Item = SyncEvent> + Send>>;
187}
188
189impl<T> SyncEventStream for Arc<T>
190where
191	T: ?Sized,
192	T: SyncEventStream,
193{
194	fn event_stream(&self, name: &'static str) -> Pin<Box<dyn Stream<Item = SyncEvent> + Send>> {
195		T::event_stream(self, name)
196	}
197}