pub mod chain_sync;
mod disconnected_peers;
pub mod polkadot;
pub mod state;
pub mod state_sync;
pub mod warp;
use crate::{
pending_responses::ResponseFuture,
service::network::NetworkServiceHandle,
types::{BadPeer, SyncStatus},
};
use sc_consensus::{BlockImportError, BlockImportStatus, IncomingBlock};
use sc_network::ProtocolName;
use sc_network_common::sync::message::BlockAnnounce;
use sc_network_types::PeerId;
use sp_blockchain::Error as ClientError;
use sp_consensus::BlockOrigin;
use sp_runtime::{
traits::{Block as BlockT, NumberFor},
Justifications,
};
use std::any::Any;
pub trait SyncingStrategy<B: BlockT>: Send
where
B: BlockT,
{
fn add_peer(&mut self, peer_id: PeerId, best_hash: B::Hash, best_number: NumberFor<B>);
fn remove_peer(&mut self, peer_id: &PeerId);
#[must_use]
fn on_validated_block_announce(
&mut self,
is_best: bool,
peer_id: PeerId,
announce: &BlockAnnounce<B::Header>,
) -> Option<(B::Hash, NumberFor<B>)>;
fn set_sync_fork_request(&mut self, peers: Vec<PeerId>, hash: &B::Hash, number: NumberFor<B>);
fn request_justification(&mut self, hash: &B::Hash, number: NumberFor<B>);
fn clear_justification_requests(&mut self);
fn on_justification_import(&mut self, hash: B::Hash, number: NumberFor<B>, success: bool);
fn on_generic_response(
&mut self,
peer_id: &PeerId,
key: StrategyKey,
protocol_name: ProtocolName,
response: Box<dyn Any + Send>,
);
fn on_blocks_processed(
&mut self,
imported: usize,
count: usize,
results: Vec<(Result<BlockImportStatus<NumberFor<B>>, BlockImportError>, B::Hash)>,
);
fn on_block_finalized(&mut self, hash: &B::Hash, number: NumberFor<B>);
fn update_chain_info(&mut self, best_hash: &B::Hash, best_number: NumberFor<B>);
fn is_major_syncing(&self) -> bool;
fn num_peers(&self) -> usize;
fn status(&self) -> SyncStatus<B>;
fn num_downloaded_blocks(&self) -> usize;
fn num_sync_requests(&self) -> usize;
#[must_use]
fn actions(
&mut self,
network_service: &NetworkServiceHandle,
) -> Result<Vec<SyncingAction<B>>, ClientError>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StrategyKey(&'static str);
impl StrategyKey {
pub const fn new(key: &'static str) -> Self {
Self(key)
}
}
pub enum SyncingAction<B: BlockT> {
StartRequest {
peer_id: PeerId,
key: StrategyKey,
request: ResponseFuture,
remove_obsolete: bool,
},
CancelRequest { peer_id: PeerId, key: StrategyKey },
DropPeer(BadPeer),
ImportBlocks { origin: BlockOrigin, blocks: Vec<IncomingBlock<B>> },
ImportJustifications {
peer_id: PeerId,
hash: B::Hash,
number: NumberFor<B>,
justifications: Justifications,
},
Finished,
}
impl<B> std::fmt::Debug for SyncingAction<B>
where
B: BlockT,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self {
Self::StartRequest { peer_id, key, remove_obsolete, .. } => {
write!(
f,
"StartRequest {{ peer_id: {:?}, key: {:?}, remove_obsolete: {:?} }}",
peer_id, key, remove_obsolete
)
},
Self::CancelRequest { peer_id, key } => {
write!(f, "CancelRequest {{ peer_id: {:?}, key: {:?} }}", peer_id, key)
},
Self::DropPeer(peer) => write!(f, "DropPeer({:?})", peer),
Self::ImportBlocks { blocks, .. } => write!(f, "ImportBlocks({:?})", blocks),
Self::ImportJustifications { hash, number, .. } => {
write!(f, "ImportJustifications({:?}, {:?})", hash, number)
},
Self::Finished => write!(f, "Finished"),
}
}
}
impl<B: BlockT> SyncingAction<B> {
pub fn is_finished(&self) -> bool {
matches!(self, SyncingAction::Finished)
}
#[cfg(test)]
pub(crate) fn name(&self) -> &'static str {
match self {
Self::StartRequest { .. } => "StartRequest",
Self::CancelRequest { .. } => "CancelRequest",
Self::DropPeer(_) => "DropPeer",
Self::ImportBlocks { .. } => "ImportBlocks",
Self::ImportJustifications { .. } => "ImportJustifications",
Self::Finished => "Finished",
}
}
}