pub mod message;
pub mod metrics;
pub mod warp;
use libp2p::PeerId;
use message::{BlockAnnounce, BlockData, BlockRequest, BlockResponse};
use sc_consensus::{import_queue::RuntimeOrigin, IncomingBlock};
use sp_consensus::BlockOrigin;
use sp_runtime::{
traits::{Block as BlockT, NumberFor},
Justifications,
};
use std::{any::Any, fmt, fmt::Formatter, task::Poll};
use warp::WarpSyncProgress;
#[derive(Debug)]
pub struct PeerInfo<Block: BlockT> {
pub best_hash: Block::Hash,
pub best_number: NumberFor<Block>,
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum SyncState<BlockNumber> {
Idle,
Downloading { target: BlockNumber },
Importing { target: BlockNumber },
}
impl<BlockNumber> SyncState<BlockNumber> {
pub fn is_major_syncing(&self) -> bool {
!matches!(self, SyncState::Idle)
}
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct StateDownloadProgress {
pub percentage: u32,
pub size: u64,
}
#[derive(Debug, Clone)]
pub struct SyncStatus<Block: BlockT> {
pub state: SyncState<NumberFor<Block>>,
pub best_seen_block: Option<NumberFor<Block>>,
pub num_peers: u32,
pub queued_blocks: u32,
pub state_sync: Option<StateDownloadProgress>,
pub warp_sync: Option<WarpSyncProgress<Block>>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BadPeer(pub PeerId, pub sc_peerset::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 {}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OnBlockData<Block: BlockT> {
Import(BlockOrigin, Vec<IncomingBlock<Block>>),
Request(PeerId, BlockRequest<Block>),
Continue,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OnBlockJustification<Block: BlockT> {
Nothing,
Import {
peer: PeerId,
hash: Block::Hash,
number: NumberFor<Block>,
justifications: Justifications,
},
}
#[derive(Debug)]
pub enum OnStateData<Block: BlockT> {
Import(BlockOrigin, IncomingBlock<Block>),
Continue,
}
#[derive(Debug)]
pub enum ImportResult<B: BlockT> {
BlockImport(BlockOrigin, Vec<IncomingBlock<B>>),
JustificationImport(RuntimeOrigin, B::Hash, NumberFor<B>, Justifications),
}
#[derive(Debug)]
pub enum PollResult<B: BlockT> {
Import(ImportResult<B>),
Announce(PollBlockAnnounceValidation<B::Header>),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PollBlockAnnounceValidation<H> {
Failure {
who: PeerId,
disconnect: bool,
},
Nothing {
who: PeerId,
is_best: bool,
announce: BlockAnnounce<H>,
},
ImportHeader {
who: PeerId,
is_best: bool,
announce: BlockAnnounce<H>,
},
Skip,
}
#[derive(Debug, PartialEq, Eq)]
pub enum SyncMode {
Light,
Full,
LightState { storage_chain_mode: bool, skip_proofs: bool },
Warp,
}
#[derive(Debug)]
pub struct Metrics {
pub queued_blocks: u32,
pub fork_targets: u32,
pub justifications: metrics::Metrics,
}
#[derive(Debug)]
pub enum PeerRequest<B: BlockT> {
Block(BlockRequest<B>),
State,
WarpProof,
}
pub struct OpaqueStateRequest(pub Box<dyn Any + Send>);
impl fmt::Debug for OpaqueStateRequest {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("OpaqueStateRequest").finish()
}
}
pub struct OpaqueStateResponse(pub Box<dyn Any + Send>);
impl fmt::Debug for OpaqueStateResponse {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("OpaqueStateResponse").finish()
}
}
pub struct OpaqueBlockRequest(pub Box<dyn Any + Send>);
impl fmt::Debug for OpaqueBlockRequest {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("OpaqueBlockRequest").finish()
}
}
pub struct OpaqueBlockResponse(pub Box<dyn Any + Send>);
impl fmt::Debug for OpaqueBlockResponse {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("OpaqueBlockResponse").finish()
}
}
pub trait ChainSync<Block: BlockT>: Send {
fn peer_info(&self, who: &PeerId) -> Option<PeerInfo<Block>>;
fn status(&self) -> SyncStatus<Block>;
fn num_sync_requests(&self) -> usize;
fn num_downloaded_blocks(&self) -> usize;
fn num_peers(&self) -> usize;
fn num_active_peers(&self) -> usize;
fn new_peer(
&mut self,
who: PeerId,
best_hash: Block::Hash,
best_number: NumberFor<Block>,
) -> Result<Option<BlockRequest<Block>>, BadPeer>;
fn update_chain_info(&mut self, best_hash: &Block::Hash, best_number: NumberFor<Block>);
fn request_justification(&mut self, hash: &Block::Hash, number: NumberFor<Block>);
fn clear_justification_requests(&mut self);
fn set_sync_fork_request(
&mut self,
peers: Vec<PeerId>,
hash: &Block::Hash,
number: NumberFor<Block>,
);
fn on_block_data(
&mut self,
who: &PeerId,
request: Option<BlockRequest<Block>>,
response: BlockResponse<Block>,
) -> Result<OnBlockData<Block>, BadPeer>;
fn process_block_response_data(
&mut self,
blocks_to_import: Result<OnBlockData<Block>, BadPeer>,
);
fn on_block_justification(
&mut self,
who: PeerId,
response: BlockResponse<Block>,
) -> Result<OnBlockJustification<Block>, BadPeer>;
fn on_justification_import(
&mut self,
hash: Block::Hash,
number: NumberFor<Block>,
success: bool,
);
fn on_block_finalized(&mut self, hash: &Block::Hash, number: NumberFor<Block>);
fn push_block_announce_validation(
&mut self,
who: PeerId,
hash: Block::Hash,
announce: BlockAnnounce<Block::Header>,
is_best: bool,
);
fn poll_block_announce_validation<'a>(
&mut self,
cx: &mut std::task::Context<'a>,
) -> Poll<PollBlockAnnounceValidation<Block::Header>>;
fn peer_disconnected(&mut self, who: &PeerId);
fn metrics(&self) -> Metrics;
fn block_response_into_blocks(
&self,
request: &BlockRequest<Block>,
response: OpaqueBlockResponse,
) -> Result<Vec<BlockData<Block>>, String>;
fn poll(
&mut self,
cx: &mut std::task::Context,
) -> Poll<PollBlockAnnounceValidation<Block::Header>>;
fn send_block_request(&mut self, who: PeerId, request: BlockRequest<Block>);
}