1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! Common syncing types.
use futures::Stream;
use sc_network_common::{role::Roles, types::ReputationChange};
use crate::strategy::{state_sync::StateSyncProgress, warp::WarpSyncProgress};
use sc_network_types::PeerId;
use sp_runtime::traits::{Block as BlockT, NumberFor};
use std::{fmt, pin::Pin, sync::Arc};
/// The sync status of a peer we are trying to sync with
#[derive(Debug)]
pub struct PeerInfo<Block: BlockT> {
/// Their best block hash.
pub best_hash: Block::Hash,
/// Their best block number.
pub best_number: NumberFor<Block>,
}
/// Info about a peer's known state (both full and light).
#[derive(Debug)]
pub struct ExtendedPeerInfo<B: BlockT> {
/// Roles
pub roles: Roles,
/// Peer best block hash
pub best_hash: B::Hash,
/// Peer best block number
pub best_number: NumberFor<B>,
}
impl<B> Clone for ExtendedPeerInfo<B>
where
B: BlockT,
{
fn clone(&self) -> Self {
Self { roles: self.roles, best_hash: self.best_hash, best_number: self.best_number }
}
}
impl<B> Copy for ExtendedPeerInfo<B> where B: BlockT {}
/// Reported sync state.
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum SyncState<BlockNumber> {
/// Initial sync is complete, keep-up sync is active.
Idle,
/// Actively catching up with the chain.
Downloading { target: BlockNumber },
/// All blocks are downloaded and are being imported.
Importing { target: BlockNumber },
}
impl<BlockNumber> SyncState<BlockNumber> {
/// Are we actively catching up with the chain?
pub fn is_major_syncing(&self) -> bool {
!matches!(self, SyncState::Idle)
}
}
/// Syncing status and statistics.
#[derive(Debug, Clone)]
pub struct SyncStatus<Block: BlockT> {
/// Current global sync state.
pub state: SyncState<NumberFor<Block>>,
/// Target sync block number.
pub best_seen_block: Option<NumberFor<Block>>,
/// Number of peers participating in syncing.
pub num_peers: u32,
/// Number of blocks queued for import
pub queued_blocks: u32,
/// State sync status in progress, if any.
pub state_sync: Option<StateSyncProgress>,
/// Warp sync in progress, if any.
pub warp_sync: Option<WarpSyncProgress<Block>>,
}
/// A peer did not behave as expected and should be reported.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BadPeer(pub PeerId, pub ReputationChange);
impl fmt::Display for BadPeer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Bad peer {}; Reputation change: {:?}", self.0, self.1)
}
}
impl std::error::Error for BadPeer {}
/// Provides high-level status of syncing.
#[async_trait::async_trait]
pub trait SyncStatusProvider<Block: BlockT>: Send + Sync {
/// Get high-level view of the syncing status.
async fn status(&self) -> Result<SyncStatus<Block>, ()>;
}
#[async_trait::async_trait]
impl<T, Block> SyncStatusProvider<Block> for Arc<T>
where
T: ?Sized,
T: SyncStatusProvider<Block>,
Block: BlockT,
{
async fn status(&self) -> Result<SyncStatus<Block>, ()> {
T::status(self).await
}
}
/// Syncing-related events that other protocols can subscribe to.
pub enum SyncEvent {
/// Peer that the syncing implementation is tracking connected.
PeerConnected(PeerId),
/// Peer that the syncing implementation was tracking disconnected.
PeerDisconnected(PeerId),
}
pub trait SyncEventStream: Send + Sync {
/// Subscribe to syncing-related events.
fn event_stream(&self, name: &'static str) -> Pin<Box<dyn Stream<Item = SyncEvent> + Send>>;
}
impl<T> SyncEventStream for Arc<T>
where
T: ?Sized,
T: SyncEventStream,
{
fn event_stream(&self, name: &'static str) -> Pin<Box<dyn Stream<Item = SyncEvent> + Send>> {
T::event_stream(self, name)
}
}