mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-20 16:15:41 +00:00
Move block/state/warpc sync requests/responses to ChainSync (#12739)
* Move block/state/warpc sync requests/responses to `ChainSync` * Apply suggestions from code review Co-authored-by: Bastian Köcher <git@kchr.de> * Apply review suggestions * cargo-fmt + doc fix * Fix tests Co-authored-by: Bastian Köcher <git@kchr.de>
This commit is contained in:
Generated
+3
-2
@@ -340,9 +340,9 @@ checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.57"
|
version = "0.1.58"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f"
|
checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -8321,6 +8321,7 @@ version = "0.10.0-dev"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"array-bytes",
|
"array-bytes",
|
||||||
"async-std",
|
"async-std",
|
||||||
|
"async-trait",
|
||||||
"fork-tree",
|
"fork-tree",
|
||||||
"futures",
|
"futures",
|
||||||
"libp2p",
|
"libp2p",
|
||||||
|
|||||||
@@ -24,14 +24,16 @@ pub mod warp;
|
|||||||
|
|
||||||
use libp2p::PeerId;
|
use libp2p::PeerId;
|
||||||
use message::{BlockAnnounce, BlockData, BlockRequest, BlockResponse};
|
use message::{BlockAnnounce, BlockData, BlockRequest, BlockResponse};
|
||||||
use sc_consensus::{BlockImportError, BlockImportStatus, IncomingBlock};
|
use sc_consensus::{
|
||||||
|
import_queue::RuntimeOrigin, BlockImportError, BlockImportStatus, IncomingBlock,
|
||||||
|
};
|
||||||
use sp_consensus::BlockOrigin;
|
use sp_consensus::BlockOrigin;
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
traits::{Block as BlockT, NumberFor},
|
traits::{Block as BlockT, NumberFor},
|
||||||
Justifications,
|
Justifications,
|
||||||
};
|
};
|
||||||
use std::{any::Any, fmt, fmt::Formatter, task::Poll};
|
use std::{any::Any, fmt, fmt::Formatter, task::Poll};
|
||||||
use warp::{EncodedProof, WarpProofRequest, WarpSyncProgress};
|
use warp::WarpSyncProgress;
|
||||||
|
|
||||||
/// The sync status of a peer we are trying to sync with
|
/// The sync status of a peer we are trying to sync with
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -123,7 +125,7 @@ pub enum OnBlockJustification<Block: BlockT> {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Result of [`ChainSync::on_state_data`].
|
/// Result of `ChainSync::on_state_data`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum OnStateData<Block: BlockT> {
|
pub enum OnStateData<Block: BlockT> {
|
||||||
/// The block and state that should be imported.
|
/// The block and state that should be imported.
|
||||||
@@ -132,6 +134,20 @@ pub enum OnStateData<Block: BlockT> {
|
|||||||
Continue,
|
Continue,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Block or justification request polled from `ChainSync`
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ImportResult<B: BlockT> {
|
||||||
|
BlockImport(BlockOrigin, Vec<IncomingBlock<B>>),
|
||||||
|
JustificationImport(RuntimeOrigin, B::Hash, NumberFor<B>, Justifications),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Value polled from `ChainSync`
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PollResult<B: BlockT> {
|
||||||
|
Import(ImportResult<B>),
|
||||||
|
Announce(PollBlockAnnounceValidation<B::Header>),
|
||||||
|
}
|
||||||
|
|
||||||
/// Result of [`ChainSync::poll_block_announce_validation`].
|
/// Result of [`ChainSync::poll_block_announce_validation`].
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum PollBlockAnnounceValidation<H> {
|
pub enum PollBlockAnnounceValidation<H> {
|
||||||
@@ -186,6 +202,13 @@ pub struct Metrics {
|
|||||||
pub justifications: metrics::Metrics,
|
pub justifications: metrics::Metrics,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PeerRequest<B: BlockT> {
|
||||||
|
Block(BlockRequest<B>),
|
||||||
|
State,
|
||||||
|
WarpProof,
|
||||||
|
}
|
||||||
|
|
||||||
/// Wrapper for implementation-specific state request.
|
/// Wrapper for implementation-specific state request.
|
||||||
///
|
///
|
||||||
/// NOTE: Implementation must be able to encode and decode it for network purposes.
|
/// NOTE: Implementation must be able to encode and decode it for network purposes.
|
||||||
@@ -250,6 +273,9 @@ pub trait ChainSync<Block: BlockT>: Send {
|
|||||||
/// Returns the current number of peers stored within this state machine.
|
/// Returns the current number of peers stored within this state machine.
|
||||||
fn num_peers(&self) -> usize;
|
fn num_peers(&self) -> usize;
|
||||||
|
|
||||||
|
/// Returns the number of peers we're connected to and that are being queried.
|
||||||
|
fn num_active_peers(&self) -> usize;
|
||||||
|
|
||||||
/// Handle a new connected peer.
|
/// Handle a new connected peer.
|
||||||
///
|
///
|
||||||
/// Call this method whenever we connect to a new peer.
|
/// Call this method whenever we connect to a new peer.
|
||||||
@@ -277,22 +303,6 @@ pub trait ChainSync<Block: BlockT>: Send {
|
|||||||
number: NumberFor<Block>,
|
number: NumberFor<Block>,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Get an iterator over all scheduled justification requests.
|
|
||||||
fn justification_requests<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
) -> Box<dyn Iterator<Item = (PeerId, BlockRequest<Block>)> + 'a>;
|
|
||||||
|
|
||||||
/// Get an iterator over all block requests of all peers.
|
|
||||||
fn block_requests<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
) -> Box<dyn Iterator<Item = (PeerId, BlockRequest<Block>)> + 'a>;
|
|
||||||
|
|
||||||
/// Get a state request, if any.
|
|
||||||
fn state_request(&mut self) -> Option<(PeerId, OpaqueStateRequest)>;
|
|
||||||
|
|
||||||
/// Get a warp sync request, if any.
|
|
||||||
fn warp_sync_request(&mut self) -> Option<(PeerId, WarpProofRequest<Block>)>;
|
|
||||||
|
|
||||||
/// Handle a response from the remote to a block request that we made.
|
/// Handle a response from the remote to a block request that we made.
|
||||||
///
|
///
|
||||||
/// `request` must be the original request that triggered `response`.
|
/// `request` must be the original request that triggered `response`.
|
||||||
@@ -307,16 +317,6 @@ pub trait ChainSync<Block: BlockT>: Send {
|
|||||||
response: BlockResponse<Block>,
|
response: BlockResponse<Block>,
|
||||||
) -> Result<OnBlockData<Block>, BadPeer>;
|
) -> Result<OnBlockData<Block>, BadPeer>;
|
||||||
|
|
||||||
/// Handle a response from the remote to a state request that we made.
|
|
||||||
fn on_state_data(
|
|
||||||
&mut self,
|
|
||||||
who: &PeerId,
|
|
||||||
response: OpaqueStateResponse,
|
|
||||||
) -> Result<OnStateData<Block>, BadPeer>;
|
|
||||||
|
|
||||||
/// Handle a response from the remote to a warp proof request that we made.
|
|
||||||
fn on_warp_sync_data(&mut self, who: &PeerId, response: EncodedProof) -> Result<(), BadPeer>;
|
|
||||||
|
|
||||||
/// Handle a response from the remote to a justification request that we made.
|
/// Handle a response from the remote to a justification request that we made.
|
||||||
///
|
///
|
||||||
/// `request` must be the original request that triggered `response`.
|
/// `request` must be the original request that triggered `response`.
|
||||||
@@ -383,15 +383,6 @@ pub trait ChainSync<Block: BlockT>: Send {
|
|||||||
/// Return some key metrics.
|
/// Return some key metrics.
|
||||||
fn metrics(&self) -> Metrics;
|
fn metrics(&self) -> Metrics;
|
||||||
|
|
||||||
/// Create implementation-specific block request.
|
|
||||||
fn create_opaque_block_request(&self, request: &BlockRequest<Block>) -> OpaqueBlockRequest;
|
|
||||||
|
|
||||||
/// Encode implementation-specific block request.
|
|
||||||
fn encode_block_request(&self, request: &OpaqueBlockRequest) -> Result<Vec<u8>, String>;
|
|
||||||
|
|
||||||
/// Decode implementation-specific block response.
|
|
||||||
fn decode_block_response(&self, response: &[u8]) -> Result<OpaqueBlockResponse, String>;
|
|
||||||
|
|
||||||
/// Access blocks from implementation-specific block response.
|
/// Access blocks from implementation-specific block response.
|
||||||
fn block_response_into_blocks(
|
fn block_response_into_blocks(
|
||||||
&self,
|
&self,
|
||||||
@@ -399,19 +390,13 @@ pub trait ChainSync<Block: BlockT>: Send {
|
|||||||
response: OpaqueBlockResponse,
|
response: OpaqueBlockResponse,
|
||||||
) -> Result<Vec<BlockData<Block>>, String>;
|
) -> Result<Vec<BlockData<Block>>, String>;
|
||||||
|
|
||||||
/// Encode implementation-specific state request.
|
|
||||||
fn encode_state_request(&self, request: &OpaqueStateRequest) -> Result<Vec<u8>, String>;
|
|
||||||
|
|
||||||
/// Decode implementation-specific state response.
|
|
||||||
fn decode_state_response(&self, response: &[u8]) -> Result<OpaqueStateResponse, String>;
|
|
||||||
|
|
||||||
/// Advance the state of `ChainSync`
|
/// Advance the state of `ChainSync`
|
||||||
///
|
///
|
||||||
/// Internally calls [`ChainSync::poll_block_announce_validation()`] and
|
/// Internally calls [`ChainSync::poll_block_announce_validation()`] and
|
||||||
/// this function should be polled until it returns [`Poll::Pending`] to
|
/// this function should be polled until it returns [`Poll::Pending`] to
|
||||||
/// consume all pending events.
|
/// consume all pending events.
|
||||||
fn poll(
|
fn poll(&mut self, cx: &mut std::task::Context) -> Poll<PollResult<Block>>;
|
||||||
&mut self,
|
|
||||||
cx: &mut std::task::Context,
|
/// Send block request to peer
|
||||||
) -> Poll<PollBlockAnnounceValidation<Block::Header>>;
|
fn send_block_request(&mut self, who: PeerId, request: BlockRequest<Block>);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ use sc_network_common::{
|
|||||||
ProtocolName,
|
ProtocolName,
|
||||||
},
|
},
|
||||||
request_responses::{IfDisconnected, ProtocolConfig, RequestFailure},
|
request_responses::{IfDisconnected, ProtocolConfig, RequestFailure},
|
||||||
sync::{warp::WarpProofRequest, OpaqueBlockRequest, OpaqueStateRequest},
|
|
||||||
};
|
};
|
||||||
use sc_peerset::{PeersetHandle, ReputationChange};
|
use sc_peerset::{PeersetHandle, ReputationChange};
|
||||||
use sp_blockchain::HeaderBackend;
|
use sp_blockchain::HeaderBackend;
|
||||||
@@ -163,36 +162,6 @@ pub enum BehaviourOut<B: BlockT> {
|
|||||||
messages: Vec<(ProtocolName, Bytes)>,
|
messages: Vec<(ProtocolName, Bytes)>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A new block request must be emitted.
|
|
||||||
BlockRequest {
|
|
||||||
/// Node we send the request to.
|
|
||||||
target: PeerId,
|
|
||||||
/// Opaque implementation-specific block request.
|
|
||||||
request: OpaqueBlockRequest,
|
|
||||||
/// One-shot channel to receive the response.
|
|
||||||
pending_response: oneshot::Sender<Result<Vec<u8>, RequestFailure>>,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// A new state request must be emitted.
|
|
||||||
StateRequest {
|
|
||||||
/// Node we send the request to.
|
|
||||||
target: PeerId,
|
|
||||||
/// Opaque implementation-specific state request.
|
|
||||||
request: OpaqueStateRequest,
|
|
||||||
/// One-shot channel to receive the response.
|
|
||||||
pending_response: oneshot::Sender<Result<Vec<u8>, RequestFailure>>,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// A new warp sync request must be emitted.
|
|
||||||
WarpSyncRequest {
|
|
||||||
/// Node we send the request to.
|
|
||||||
target: PeerId,
|
|
||||||
/// Warp sync request.
|
|
||||||
request: WarpProofRequest<B>,
|
|
||||||
/// One-shot channel to receive the response.
|
|
||||||
pending_response: oneshot::Sender<Result<Vec<u8>, RequestFailure>>,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Now connected to a new peer for syncing purposes.
|
/// Now connected to a new peer for syncing purposes.
|
||||||
SyncConnected(PeerId),
|
SyncConnected(PeerId),
|
||||||
|
|
||||||
@@ -230,21 +199,9 @@ where
|
|||||||
user_agent: String,
|
user_agent: String,
|
||||||
local_public_key: PublicKey,
|
local_public_key: PublicKey,
|
||||||
disco_config: DiscoveryConfig,
|
disco_config: DiscoveryConfig,
|
||||||
block_request_protocol_config: ProtocolConfig,
|
request_response_protocols: Vec<ProtocolConfig>,
|
||||||
state_request_protocol_config: ProtocolConfig,
|
|
||||||
warp_sync_protocol_config: Option<ProtocolConfig>,
|
|
||||||
light_client_request_protocol_config: ProtocolConfig,
|
|
||||||
// All remaining request protocol configs.
|
|
||||||
mut request_response_protocols: Vec<ProtocolConfig>,
|
|
||||||
peerset: PeersetHandle,
|
peerset: PeersetHandle,
|
||||||
) -> Result<Self, request_responses::RegisterError> {
|
) -> Result<Self, request_responses::RegisterError> {
|
||||||
if let Some(config) = warp_sync_protocol_config {
|
|
||||||
request_response_protocols.push(config);
|
|
||||||
}
|
|
||||||
request_response_protocols.push(block_request_protocol_config);
|
|
||||||
request_response_protocols.push(state_request_protocol_config);
|
|
||||||
request_response_protocols.push(light_client_request_protocol_config);
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
substrate,
|
substrate,
|
||||||
peer_info: peer_info::PeerInfoBehaviour::new(user_agent, local_public_key),
|
peer_info: peer_info::PeerInfoBehaviour::new(user_agent, local_public_key),
|
||||||
@@ -356,12 +313,6 @@ impl<B: BlockT> From<CustomMessageOutcome<B>> for BehaviourOut<B> {
|
|||||||
BehaviourOut::BlockImport(origin, blocks),
|
BehaviourOut::BlockImport(origin, blocks),
|
||||||
CustomMessageOutcome::JustificationImport(origin, hash, nb, justification) =>
|
CustomMessageOutcome::JustificationImport(origin, hash, nb, justification) =>
|
||||||
BehaviourOut::JustificationImport(origin, hash, nb, justification),
|
BehaviourOut::JustificationImport(origin, hash, nb, justification),
|
||||||
CustomMessageOutcome::BlockRequest { target, request, pending_response } =>
|
|
||||||
BehaviourOut::BlockRequest { target, request, pending_response },
|
|
||||||
CustomMessageOutcome::StateRequest { target, request, pending_response } =>
|
|
||||||
BehaviourOut::StateRequest { target, request, pending_response },
|
|
||||||
CustomMessageOutcome::WarpSyncRequest { target, request, pending_response } =>
|
|
||||||
BehaviourOut::WarpSyncRequest { target, request, pending_response },
|
|
||||||
CustomMessageOutcome::NotificationStreamOpened {
|
CustomMessageOutcome::NotificationStreamOpened {
|
||||||
remote,
|
remote,
|
||||||
protocol,
|
protocol,
|
||||||
|
|||||||
@@ -101,39 +101,6 @@ where
|
|||||||
/// Block announce protocol configuration
|
/// Block announce protocol configuration
|
||||||
pub block_announce_config: NonDefaultSetConfig,
|
pub block_announce_config: NonDefaultSetConfig,
|
||||||
|
|
||||||
/// Request response configuration for the block request protocol.
|
|
||||||
///
|
|
||||||
/// [`RequestResponseConfig::name`] is used to tag outgoing block requests with the correct
|
|
||||||
/// protocol name. In addition all of [`RequestResponseConfig`] is used to handle incoming
|
|
||||||
/// block requests, if enabled.
|
|
||||||
///
|
|
||||||
/// Can be constructed either via
|
|
||||||
/// `sc_network_sync::block_request_handler::generate_protocol_config` allowing outgoing but
|
|
||||||
/// not incoming requests, or constructed via `sc_network_sync::block_request_handler::
|
|
||||||
/// BlockRequestHandler::new` allowing both outgoing and incoming requests.
|
|
||||||
pub block_request_protocol_config: RequestResponseConfig,
|
|
||||||
|
|
||||||
/// Request response configuration for the light client request protocol.
|
|
||||||
///
|
|
||||||
/// Can be constructed either via
|
|
||||||
/// `sc_network_light::light_client_requests::generate_protocol_config` allowing outgoing but
|
|
||||||
/// not incoming requests, or constructed via
|
|
||||||
/// `sc_network_light::light_client_requests::handler::LightClientRequestHandler::new`
|
|
||||||
/// allowing both outgoing and incoming requests.
|
|
||||||
pub light_client_request_protocol_config: RequestResponseConfig,
|
|
||||||
|
|
||||||
/// Request response configuration for the state request protocol.
|
|
||||||
///
|
|
||||||
/// Can be constructed either via
|
|
||||||
/// `sc_network_sync::state_request_handler::generate_protocol_config` allowing outgoing but
|
|
||||||
/// not incoming requests, or constructed via
|
|
||||||
/// `sc_network_sync::state_request_handler::StateRequestHandler::new` allowing
|
|
||||||
/// both outgoing and incoming requests.
|
|
||||||
pub state_request_protocol_config: RequestResponseConfig,
|
|
||||||
|
|
||||||
/// Optional warp sync protocol config.
|
|
||||||
pub warp_sync_protocol_config: Option<RequestResponseConfig>,
|
|
||||||
|
|
||||||
/// Request response protocol configurations
|
/// Request response protocol configurations
|
||||||
pub request_response_protocol_configs: Vec<RequestResponseConfig>,
|
pub request_response_protocol_configs: Vec<RequestResponseConfig>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,9 @@ use crate::config;
|
|||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use codec::{Decode, DecodeAll, Encode};
|
use codec::{Decode, DecodeAll, Encode};
|
||||||
use futures::{channel::oneshot, prelude::*};
|
use futures::prelude::*;
|
||||||
use libp2p::{
|
use libp2p::{
|
||||||
core::{connection::ConnectionId, transport::ListenerId, ConnectedPoint},
|
core::{connection::ConnectionId, transport::ListenerId, ConnectedPoint},
|
||||||
request_response::OutboundFailure,
|
|
||||||
swarm::{
|
swarm::{
|
||||||
ConnectionHandler, IntoConnectionHandler, NetworkBehaviour, NetworkBehaviourAction,
|
ConnectionHandler, IntoConnectionHandler, NetworkBehaviour, NetworkBehaviourAction,
|
||||||
PollParameters,
|
PollParameters,
|
||||||
@@ -43,15 +42,9 @@ use sc_network_common::{
|
|||||||
config::NonReservedPeerMode,
|
config::NonReservedPeerMode,
|
||||||
error,
|
error,
|
||||||
protocol::{role::Roles, ProtocolName},
|
protocol::{role::Roles, ProtocolName},
|
||||||
request_responses::RequestFailure,
|
|
||||||
sync::{
|
sync::{
|
||||||
message::{
|
message::{BlockAnnounce, BlockAnnouncesHandshake, BlockData, BlockResponse, BlockState},
|
||||||
BlockAnnounce, BlockAnnouncesHandshake, BlockAttributes, BlockData, BlockRequest,
|
BadPeer, ChainSync, ImportResult, OnBlockData, PollBlockAnnounceValidation, PollResult,
|
||||||
BlockResponse, BlockState,
|
|
||||||
},
|
|
||||||
warp::{EncodedProof, WarpProofRequest},
|
|
||||||
BadPeer, ChainSync, OnBlockData, OnBlockJustification, OnStateData, OpaqueBlockRequest,
|
|
||||||
OpaqueBlockResponse, OpaqueStateRequest, OpaqueStateResponse, PollBlockAnnounceValidation,
|
|
||||||
SyncStatus,
|
SyncStatus,
|
||||||
},
|
},
|
||||||
utils::{interval, LruHashSet},
|
utils::{interval, LruHashSet},
|
||||||
@@ -102,18 +95,12 @@ const LIGHT_MAXIMAL_BLOCKS_DIFFERENCE: u64 = 8192;
|
|||||||
|
|
||||||
mod rep {
|
mod rep {
|
||||||
use sc_peerset::ReputationChange as Rep;
|
use sc_peerset::ReputationChange as Rep;
|
||||||
/// Reputation change when a peer doesn't respond in time to our messages.
|
|
||||||
pub const TIMEOUT: Rep = Rep::new(-(1 << 10), "Request timeout");
|
|
||||||
/// Reputation change when a peer refuses a request.
|
|
||||||
pub const REFUSED: Rep = Rep::new(-(1 << 10), "Request refused");
|
|
||||||
/// Reputation change when we are a light client and a peer is behind us.
|
/// Reputation change when we are a light client and a peer is behind us.
|
||||||
pub const PEER_BEHIND_US_LIGHT: Rep = Rep::new(-(1 << 8), "Useless for a light peer");
|
pub const PEER_BEHIND_US_LIGHT: Rep = Rep::new(-(1 << 8), "Useless for a light peer");
|
||||||
/// We received a message that failed to decode.
|
/// We received a message that failed to decode.
|
||||||
pub const BAD_MESSAGE: Rep = Rep::new(-(1 << 12), "Bad message");
|
pub const BAD_MESSAGE: Rep = Rep::new(-(1 << 12), "Bad message");
|
||||||
/// Peer has different genesis.
|
/// Peer has different genesis.
|
||||||
pub const GENESIS_MISMATCH: Rep = Rep::new_fatal("Genesis mismatch");
|
pub const GENESIS_MISMATCH: Rep = Rep::new_fatal("Genesis mismatch");
|
||||||
/// Peer is on unsupported protocol version.
|
|
||||||
pub const BAD_PROTOCOL: Rep = Rep::new_fatal("Unsupported protocol");
|
|
||||||
/// Peer role does not match (e.g. light peer connecting to another light peer).
|
/// Peer role does not match (e.g. light peer connecting to another light peer).
|
||||||
pub const BAD_ROLE: Rep = Rep::new_fatal("Unsupported role");
|
pub const BAD_ROLE: Rep = Rep::new_fatal("Unsupported role");
|
||||||
/// Peer send us a block announcement that failed at validation.
|
/// Peer send us a block announcement that failed at validation.
|
||||||
@@ -204,19 +191,10 @@ pub struct Protocol<B: BlockT, Client> {
|
|||||||
block_announce_data_cache: LruCache<B::Hash, Vec<u8>>,
|
block_announce_data_cache: LruCache<B::Hash, Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum PeerRequest<B: BlockT> {
|
|
||||||
Block(BlockRequest<B>),
|
|
||||||
State,
|
|
||||||
WarpProof,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Peer information
|
/// Peer information
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Peer<B: BlockT> {
|
struct Peer<B: BlockT> {
|
||||||
info: PeerInfo<B>,
|
info: PeerInfo<B>,
|
||||||
/// Current request, if any. Started by emitting [`CustomMessageOutcome::BlockRequest`].
|
|
||||||
request: Option<(PeerRequest<B>, oneshot::Receiver<Result<Vec<u8>, RequestFailure>>)>,
|
|
||||||
/// Holds a set of blocks known to this peer.
|
/// Holds a set of blocks known to this peer.
|
||||||
known_blocks: LruHashSet<B::Hash>,
|
known_blocks: LruHashSet<B::Hash>,
|
||||||
}
|
}
|
||||||
@@ -432,7 +410,7 @@ where
|
|||||||
|
|
||||||
/// Returns the number of peers we're connected to and that are being queried.
|
/// Returns the number of peers we're connected to and that are being queried.
|
||||||
pub fn num_active_peers(&self) -> usize {
|
pub fn num_active_peers(&self) -> usize {
|
||||||
self.peers.values().filter(|p| p.request.is_some()).count()
|
self.chain_sync.num_active_peers()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Current global sync state.
|
/// Current global sync state.
|
||||||
@@ -521,106 +499,6 @@ where
|
|||||||
self.peerset_handle.report_peer(who, reputation)
|
self.peerset_handle.report_peer(who, reputation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Must be called in response to a [`CustomMessageOutcome::BlockRequest`] being emitted.
|
|
||||||
/// Must contain the same `PeerId` and request that have been emitted.
|
|
||||||
pub fn on_block_response(
|
|
||||||
&mut self,
|
|
||||||
peer_id: PeerId,
|
|
||||||
request: BlockRequest<B>,
|
|
||||||
response: OpaqueBlockResponse,
|
|
||||||
) -> CustomMessageOutcome<B> {
|
|
||||||
let blocks = match self.chain_sync.block_response_into_blocks(&request, response) {
|
|
||||||
Ok(blocks) => blocks,
|
|
||||||
Err(err) => {
|
|
||||||
debug!(target: "sync", "Failed to decode block response from {}: {}", peer_id, err);
|
|
||||||
self.peerset_handle.report_peer(peer_id, rep::BAD_MESSAGE);
|
|
||||||
return CustomMessageOutcome::None
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let block_response = BlockResponse::<B> { id: request.id, blocks };
|
|
||||||
|
|
||||||
let blocks_range = || match (
|
|
||||||
block_response
|
|
||||||
.blocks
|
|
||||||
.first()
|
|
||||||
.and_then(|b| b.header.as_ref().map(|h| h.number())),
|
|
||||||
block_response.blocks.last().and_then(|b| b.header.as_ref().map(|h| h.number())),
|
|
||||||
) {
|
|
||||||
(Some(first), Some(last)) if first != last => format!(" ({}..{})", first, last),
|
|
||||||
(Some(first), Some(_)) => format!(" ({})", first),
|
|
||||||
_ => Default::default(),
|
|
||||||
};
|
|
||||||
trace!(target: "sync", "BlockResponse {} from {} with {} blocks {}",
|
|
||||||
block_response.id,
|
|
||||||
peer_id,
|
|
||||||
block_response.blocks.len(),
|
|
||||||
blocks_range(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if request.fields == BlockAttributes::JUSTIFICATION {
|
|
||||||
match self.chain_sync.on_block_justification(peer_id, block_response) {
|
|
||||||
Ok(OnBlockJustification::Nothing) => CustomMessageOutcome::None,
|
|
||||||
Ok(OnBlockJustification::Import { peer, hash, number, justifications }) =>
|
|
||||||
CustomMessageOutcome::JustificationImport(peer, hash, number, justifications),
|
|
||||||
Err(BadPeer(id, repu)) => {
|
|
||||||
self.behaviour.disconnect_peer(&id, HARDCODED_PEERSETS_SYNC);
|
|
||||||
self.peerset_handle.report_peer(id, repu);
|
|
||||||
CustomMessageOutcome::None
|
|
||||||
},
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match self.chain_sync.on_block_data(&peer_id, Some(request), block_response) {
|
|
||||||
Ok(OnBlockData::Import(origin, blocks)) =>
|
|
||||||
CustomMessageOutcome::BlockImport(origin, blocks),
|
|
||||||
Ok(OnBlockData::Request(peer, req)) =>
|
|
||||||
prepare_block_request(self.chain_sync.as_ref(), &mut self.peers, peer, req),
|
|
||||||
Ok(OnBlockData::Continue) => CustomMessageOutcome::None,
|
|
||||||
Err(BadPeer(id, repu)) => {
|
|
||||||
self.behaviour.disconnect_peer(&id, HARDCODED_PEERSETS_SYNC);
|
|
||||||
self.peerset_handle.report_peer(id, repu);
|
|
||||||
CustomMessageOutcome::None
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Must be called in response to a [`CustomMessageOutcome::StateRequest`] being emitted.
|
|
||||||
/// Must contain the same `PeerId` and request that have been emitted.
|
|
||||||
pub fn on_state_response(
|
|
||||||
&mut self,
|
|
||||||
peer_id: PeerId,
|
|
||||||
response: OpaqueStateResponse,
|
|
||||||
) -> CustomMessageOutcome<B> {
|
|
||||||
match self.chain_sync.on_state_data(&peer_id, response) {
|
|
||||||
Ok(OnStateData::Import(origin, block)) =>
|
|
||||||
CustomMessageOutcome::BlockImport(origin, vec![block]),
|
|
||||||
Ok(OnStateData::Continue) => CustomMessageOutcome::None,
|
|
||||||
Err(BadPeer(id, repu)) => {
|
|
||||||
self.behaviour.disconnect_peer(&id, HARDCODED_PEERSETS_SYNC);
|
|
||||||
self.peerset_handle.report_peer(id, repu);
|
|
||||||
CustomMessageOutcome::None
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Must be called in response to a [`CustomMessageOutcome::WarpSyncRequest`] being emitted.
|
|
||||||
/// Must contain the same `PeerId` and request that have been emitted.
|
|
||||||
pub fn on_warp_sync_response(
|
|
||||||
&mut self,
|
|
||||||
peer_id: PeerId,
|
|
||||||
response: EncodedProof,
|
|
||||||
) -> CustomMessageOutcome<B> {
|
|
||||||
match self.chain_sync.on_warp_sync_data(&peer_id, response) {
|
|
||||||
Ok(()) => CustomMessageOutcome::None,
|
|
||||||
Err(BadPeer(id, repu)) => {
|
|
||||||
self.behaviour.disconnect_peer(&id, HARDCODED_PEERSETS_SYNC);
|
|
||||||
self.peerset_handle.report_peer(id, repu);
|
|
||||||
CustomMessageOutcome::None
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Perform time based maintenance.
|
/// Perform time based maintenance.
|
||||||
///
|
///
|
||||||
/// > **Note**: This method normally doesn't have to be called except for testing purposes.
|
/// > **Note**: This method normally doesn't have to be called except for testing purposes.
|
||||||
@@ -721,7 +599,6 @@ where
|
|||||||
best_hash: status.best_hash,
|
best_hash: status.best_hash,
|
||||||
best_number: status.best_number,
|
best_number: status.best_number,
|
||||||
},
|
},
|
||||||
request: None,
|
|
||||||
known_blocks: LruHashSet::new(
|
known_blocks: LruHashSet::new(
|
||||||
NonZeroUsize::new(MAX_KNOWN_BLOCKS).expect("Constant is nonzero"),
|
NonZeroUsize::new(MAX_KNOWN_BLOCKS).expect("Constant is nonzero"),
|
||||||
),
|
),
|
||||||
@@ -750,12 +627,7 @@ where
|
|||||||
.push_back(CustomMessageOutcome::PeerNewBest(who, status.best_number));
|
.push_back(CustomMessageOutcome::PeerNewBest(who, status.best_number));
|
||||||
|
|
||||||
if let Some(req) = req {
|
if let Some(req) = req {
|
||||||
self.pending_messages.push_back(prepare_block_request(
|
self.chain_sync.send_block_request(who, req);
|
||||||
self.chain_sync.as_ref(),
|
|
||||||
&mut self.peers,
|
|
||||||
who,
|
|
||||||
req,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -921,8 +793,10 @@ where
|
|||||||
match blocks_to_import {
|
match blocks_to_import {
|
||||||
Ok(OnBlockData::Import(origin, blocks)) =>
|
Ok(OnBlockData::Import(origin, blocks)) =>
|
||||||
CustomMessageOutcome::BlockImport(origin, blocks),
|
CustomMessageOutcome::BlockImport(origin, blocks),
|
||||||
Ok(OnBlockData::Request(peer, req)) =>
|
Ok(OnBlockData::Request(peer, req)) => {
|
||||||
prepare_block_request(self.chain_sync.as_ref(), &mut self.peers, peer, req),
|
self.chain_sync.send_block_request(peer, req);
|
||||||
|
CustomMessageOutcome::None
|
||||||
|
},
|
||||||
Ok(OnBlockData::Continue) => CustomMessageOutcome::None,
|
Ok(OnBlockData::Continue) => CustomMessageOutcome::None,
|
||||||
Err(BadPeer(id, repu)) => {
|
Err(BadPeer(id, repu)) => {
|
||||||
self.behaviour.disconnect_peer(&id, HARDCODED_PEERSETS_SYNC);
|
self.behaviour.disconnect_peer(&id, HARDCODED_PEERSETS_SYNC);
|
||||||
@@ -963,14 +837,7 @@ where
|
|||||||
let results = self.chain_sync.on_blocks_processed(imported, count, results);
|
let results = self.chain_sync.on_blocks_processed(imported, count, results);
|
||||||
for result in results {
|
for result in results {
|
||||||
match result {
|
match result {
|
||||||
Ok((id, req)) => {
|
Ok((id, req)) => self.chain_sync.send_block_request(id, req),
|
||||||
self.pending_messages.push_back(prepare_block_request(
|
|
||||||
self.chain_sync.as_ref(),
|
|
||||||
&mut self.peers,
|
|
||||||
id,
|
|
||||||
req,
|
|
||||||
));
|
|
||||||
},
|
|
||||||
Err(BadPeer(id, repu)) => {
|
Err(BadPeer(id, repu)) => {
|
||||||
self.behaviour.disconnect_peer(&id, HARDCODED_PEERSETS_SYNC);
|
self.behaviour.disconnect_peer(&id, HARDCODED_PEERSETS_SYNC);
|
||||||
self.peerset_handle.report_peer(id, repu)
|
self.peerset_handle.report_peer(id, repu)
|
||||||
@@ -1096,16 +963,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode implementation-specific block request.
|
|
||||||
pub fn encode_block_request(&self, request: &OpaqueBlockRequest) -> Result<Vec<u8>, String> {
|
|
||||||
self.chain_sync.encode_block_request(request)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Encode implementation-specific state request.
|
|
||||||
pub fn encode_state_request(&self, request: &OpaqueStateRequest) -> Result<Vec<u8>, String> {
|
|
||||||
self.chain_sync.encode_state_request(request)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn report_metrics(&self) {
|
fn report_metrics(&self) {
|
||||||
if let Some(metrics) = &self.metrics {
|
if let Some(metrics) = &self.metrics {
|
||||||
let n = u64::try_from(self.peers.len()).unwrap_or(std::u64::MAX);
|
let n = u64::try_from(self.peers.len()).unwrap_or(std::u64::MAX);
|
||||||
@@ -1136,49 +993,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_block_request<B: BlockT>(
|
|
||||||
chain_sync: &dyn ChainSync<B>,
|
|
||||||
peers: &mut HashMap<PeerId, Peer<B>>,
|
|
||||||
who: PeerId,
|
|
||||||
request: BlockRequest<B>,
|
|
||||||
) -> CustomMessageOutcome<B> {
|
|
||||||
let (tx, rx) = oneshot::channel();
|
|
||||||
|
|
||||||
if let Some(ref mut peer) = peers.get_mut(&who) {
|
|
||||||
peer.request = Some((PeerRequest::Block(request.clone()), rx));
|
|
||||||
}
|
|
||||||
|
|
||||||
let request = chain_sync.create_opaque_block_request(&request);
|
|
||||||
|
|
||||||
CustomMessageOutcome::BlockRequest { target: who, request, pending_response: tx }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prepare_state_request<B: BlockT>(
|
|
||||||
peers: &mut HashMap<PeerId, Peer<B>>,
|
|
||||||
who: PeerId,
|
|
||||||
request: OpaqueStateRequest,
|
|
||||||
) -> CustomMessageOutcome<B> {
|
|
||||||
let (tx, rx) = oneshot::channel();
|
|
||||||
|
|
||||||
if let Some(ref mut peer) = peers.get_mut(&who) {
|
|
||||||
peer.request = Some((PeerRequest::State, rx));
|
|
||||||
}
|
|
||||||
CustomMessageOutcome::StateRequest { target: who, request, pending_response: tx }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prepare_warp_sync_request<B: BlockT>(
|
|
||||||
peers: &mut HashMap<PeerId, Peer<B>>,
|
|
||||||
who: PeerId,
|
|
||||||
request: WarpProofRequest<B>,
|
|
||||||
) -> CustomMessageOutcome<B> {
|
|
||||||
let (tx, rx) = oneshot::channel();
|
|
||||||
|
|
||||||
if let Some(ref mut peer) = peers.get_mut(&who) {
|
|
||||||
peer.request = Some((PeerRequest::WarpProof, rx));
|
|
||||||
}
|
|
||||||
CustomMessageOutcome::WarpSyncRequest { target: who, request, pending_response: tx }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Outcome of an incoming custom message.
|
/// Outcome of an incoming custom message.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@@ -1210,24 +1024,6 @@ pub enum CustomMessageOutcome<B: BlockT> {
|
|||||||
remote: PeerId,
|
remote: PeerId,
|
||||||
messages: Vec<(ProtocolName, Bytes)>,
|
messages: Vec<(ProtocolName, Bytes)>,
|
||||||
},
|
},
|
||||||
/// A new block request must be emitted.
|
|
||||||
BlockRequest {
|
|
||||||
target: PeerId,
|
|
||||||
request: OpaqueBlockRequest,
|
|
||||||
pending_response: oneshot::Sender<Result<Vec<u8>, RequestFailure>>,
|
|
||||||
},
|
|
||||||
/// A new storage request must be emitted.
|
|
||||||
StateRequest {
|
|
||||||
target: PeerId,
|
|
||||||
request: OpaqueStateRequest,
|
|
||||||
pending_response: oneshot::Sender<Result<Vec<u8>, RequestFailure>>,
|
|
||||||
},
|
|
||||||
/// A new warp sync request must be emitted.
|
|
||||||
WarpSyncRequest {
|
|
||||||
target: PeerId,
|
|
||||||
request: WarpProofRequest<B>,
|
|
||||||
pending_response: oneshot::Sender<Result<Vec<u8>, RequestFailure>>,
|
|
||||||
},
|
|
||||||
/// Peer has a reported a new head of chain.
|
/// Peer has a reported a new head of chain.
|
||||||
PeerNewBest(PeerId, NumberFor<B>),
|
PeerNewBest(PeerId, NumberFor<B>),
|
||||||
/// Now connected to a new peer for syncing purposes.
|
/// Now connected to a new peer for syncing purposes.
|
||||||
@@ -1305,165 +1101,35 @@ where
|
|||||||
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(message))
|
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(message))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for finished outgoing requests.
|
|
||||||
let mut finished_block_requests = Vec::new();
|
|
||||||
let mut finished_state_requests = Vec::new();
|
|
||||||
let mut finished_warp_sync_requests = Vec::new();
|
|
||||||
for (id, peer) in self.peers.iter_mut() {
|
|
||||||
if let Peer { request: Some((_, pending_response)), .. } = peer {
|
|
||||||
match pending_response.poll_unpin(cx) {
|
|
||||||
Poll::Ready(Ok(Ok(resp))) => {
|
|
||||||
let (req, _) = peer.request.take().unwrap();
|
|
||||||
match req {
|
|
||||||
PeerRequest::Block(req) => {
|
|
||||||
let response =
|
|
||||||
match self.chain_sync.decode_block_response(&resp[..]) {
|
|
||||||
Ok(proto) => proto,
|
|
||||||
Err(e) => {
|
|
||||||
debug!(
|
|
||||||
target: "sync",
|
|
||||||
"Failed to decode block response from peer {:?}: {:?}.",
|
|
||||||
id,
|
|
||||||
e
|
|
||||||
);
|
|
||||||
self.peerset_handle.report_peer(*id, rep::BAD_MESSAGE);
|
|
||||||
self.behaviour
|
|
||||||
.disconnect_peer(id, HARDCODED_PEERSETS_SYNC);
|
|
||||||
continue
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
finished_block_requests.push((*id, req, response));
|
|
||||||
},
|
|
||||||
PeerRequest::State => {
|
|
||||||
let response =
|
|
||||||
match self.chain_sync.decode_state_response(&resp[..]) {
|
|
||||||
Ok(proto) => proto,
|
|
||||||
Err(e) => {
|
|
||||||
debug!(
|
|
||||||
target: "sync",
|
|
||||||
"Failed to decode state response from peer {:?}: {:?}.",
|
|
||||||
id,
|
|
||||||
e
|
|
||||||
);
|
|
||||||
self.peerset_handle.report_peer(*id, rep::BAD_MESSAGE);
|
|
||||||
self.behaviour
|
|
||||||
.disconnect_peer(id, HARDCODED_PEERSETS_SYNC);
|
|
||||||
continue
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
finished_state_requests.push((*id, response));
|
|
||||||
},
|
|
||||||
PeerRequest::WarpProof => {
|
|
||||||
finished_warp_sync_requests.push((*id, resp));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Poll::Ready(Ok(Err(e))) => {
|
|
||||||
peer.request.take();
|
|
||||||
debug!(target: "sync", "Request to peer {:?} failed: {:?}.", id, e);
|
|
||||||
|
|
||||||
match e {
|
|
||||||
RequestFailure::Network(OutboundFailure::Timeout) => {
|
|
||||||
self.peerset_handle.report_peer(*id, rep::TIMEOUT);
|
|
||||||
self.behaviour.disconnect_peer(id, HARDCODED_PEERSETS_SYNC);
|
|
||||||
},
|
|
||||||
RequestFailure::Network(OutboundFailure::UnsupportedProtocols) => {
|
|
||||||
self.peerset_handle.report_peer(*id, rep::BAD_PROTOCOL);
|
|
||||||
self.behaviour.disconnect_peer(id, HARDCODED_PEERSETS_SYNC);
|
|
||||||
},
|
|
||||||
RequestFailure::Network(OutboundFailure::DialFailure) => {
|
|
||||||
self.behaviour.disconnect_peer(id, HARDCODED_PEERSETS_SYNC);
|
|
||||||
},
|
|
||||||
RequestFailure::Refused => {
|
|
||||||
self.peerset_handle.report_peer(*id, rep::REFUSED);
|
|
||||||
self.behaviour.disconnect_peer(id, HARDCODED_PEERSETS_SYNC);
|
|
||||||
},
|
|
||||||
RequestFailure::Network(OutboundFailure::ConnectionClosed) |
|
|
||||||
RequestFailure::NotConnected => {
|
|
||||||
self.behaviour.disconnect_peer(id, HARDCODED_PEERSETS_SYNC);
|
|
||||||
},
|
|
||||||
RequestFailure::UnknownProtocol => {
|
|
||||||
debug_assert!(
|
|
||||||
false,
|
|
||||||
"Block request protocol should always be known."
|
|
||||||
);
|
|
||||||
},
|
|
||||||
RequestFailure::Obsolete => {
|
|
||||||
debug_assert!(
|
|
||||||
false,
|
|
||||||
"Can not receive `RequestFailure::Obsolete` after dropping the \
|
|
||||||
response receiver.",
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Poll::Ready(Err(oneshot::Canceled)) => {
|
|
||||||
peer.request.take();
|
|
||||||
trace!(
|
|
||||||
target: "sync",
|
|
||||||
"Request to peer {:?} failed due to oneshot being canceled.",
|
|
||||||
id,
|
|
||||||
);
|
|
||||||
self.behaviour.disconnect_peer(id, HARDCODED_PEERSETS_SYNC);
|
|
||||||
},
|
|
||||||
Poll::Pending => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (id, req, response) in finished_block_requests {
|
|
||||||
let ev = self.on_block_response(id, req, response);
|
|
||||||
self.pending_messages.push_back(ev);
|
|
||||||
}
|
|
||||||
for (id, response) in finished_state_requests {
|
|
||||||
let ev = self.on_state_response(id, response);
|
|
||||||
self.pending_messages.push_back(ev);
|
|
||||||
}
|
|
||||||
for (id, response) in finished_warp_sync_requests {
|
|
||||||
let ev = self.on_warp_sync_response(id, EncodedProof(response));
|
|
||||||
self.pending_messages.push_back(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
while let Poll::Ready(Some(())) = self.tick_timeout.poll_next_unpin(cx) {
|
|
||||||
self.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (id, request) in self
|
|
||||||
.chain_sync
|
|
||||||
.block_requests()
|
|
||||||
.map(|(peer_id, request)| (peer_id, request))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
{
|
|
||||||
let event =
|
|
||||||
prepare_block_request(self.chain_sync.as_ref(), &mut self.peers, id, request);
|
|
||||||
self.pending_messages.push_back(event);
|
|
||||||
}
|
|
||||||
if let Some((id, request)) = self.chain_sync.state_request() {
|
|
||||||
let event = prepare_state_request(&mut self.peers, id, request);
|
|
||||||
self.pending_messages.push_back(event);
|
|
||||||
}
|
|
||||||
for (id, request) in self.chain_sync.justification_requests().collect::<Vec<_>>() {
|
|
||||||
let event =
|
|
||||||
prepare_block_request(self.chain_sync.as_ref(), &mut self.peers, id, request);
|
|
||||||
self.pending_messages.push_back(event);
|
|
||||||
}
|
|
||||||
if let Some((id, request)) = self.chain_sync.warp_sync_request() {
|
|
||||||
let event = prepare_warp_sync_request(&mut self.peers, id, request);
|
|
||||||
self.pending_messages.push_back(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Advance the state of `ChainSync`
|
// Advance the state of `ChainSync`
|
||||||
//
|
//
|
||||||
// Process any received requests received from `NetworkService` and
|
// Process any received requests received from `NetworkService` and
|
||||||
// check if there is any block announcement validation finished.
|
// check if there is any block announcement validation finished.
|
||||||
while let Poll::Ready(result) = self.chain_sync.poll(cx) {
|
while let Poll::Ready(result) = self.chain_sync.poll(cx) {
|
||||||
match self.process_block_announce_validation_result(result) {
|
match result {
|
||||||
CustomMessageOutcome::None => {},
|
PollResult::Import(import) => self.pending_messages.push_back(match import {
|
||||||
outcome => self.pending_messages.push_back(outcome),
|
ImportResult::BlockImport(origin, blocks) =>
|
||||||
|
CustomMessageOutcome::BlockImport(origin, blocks),
|
||||||
|
ImportResult::JustificationImport(origin, hash, number, justifications) =>
|
||||||
|
CustomMessageOutcome::JustificationImport(
|
||||||
|
origin,
|
||||||
|
hash,
|
||||||
|
number,
|
||||||
|
justifications,
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
PollResult::Announce(announce) =>
|
||||||
|
match self.process_block_announce_validation_result(announce) {
|
||||||
|
CustomMessageOutcome::None => {},
|
||||||
|
outcome => self.pending_messages.push_back(outcome),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while let Poll::Ready(Some(())) = self.tick_timeout.poll_next_unpin(cx) {
|
||||||
|
self.tick();
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(message) = self.pending_messages.pop_front() {
|
if let Some(message) = self.pending_messages.pop_front() {
|
||||||
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(message))
|
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(message))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ use crate::{
|
|||||||
transport, ChainSyncInterface, ReputationChange,
|
transport, ChainSyncInterface, ReputationChange,
|
||||||
};
|
};
|
||||||
|
|
||||||
use codec::Encode;
|
|
||||||
use futures::{channel::oneshot, prelude::*};
|
use futures::{channel::oneshot, prelude::*};
|
||||||
use libp2p::{
|
use libp2p::{
|
||||||
core::{either::EitherError, upgrade, ConnectedPoint, Executor},
|
core::{either::EitherError, upgrade, ConnectedPoint, Executor},
|
||||||
@@ -264,11 +263,6 @@ where
|
|||||||
let num_connected = Arc::new(AtomicUsize::new(0));
|
let num_connected = Arc::new(AtomicUsize::new(0));
|
||||||
let is_major_syncing = Arc::new(AtomicBool::new(false));
|
let is_major_syncing = Arc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
let block_request_protocol_name = params.block_request_protocol_config.name.clone();
|
|
||||||
let state_request_protocol_name = params.state_request_protocol_config.name.clone();
|
|
||||||
let warp_sync_protocol_name =
|
|
||||||
params.warp_sync_protocol_config.as_ref().map(|c| c.name.clone());
|
|
||||||
|
|
||||||
// Build the swarm.
|
// Build the swarm.
|
||||||
let (mut swarm, bandwidth): (Swarm<Behaviour<B, Client>>, _) = {
|
let (mut swarm, bandwidth): (Swarm<Behaviour<B, Client>>, _) = {
|
||||||
let user_agent = format!(
|
let user_agent = format!(
|
||||||
@@ -366,10 +360,6 @@ where
|
|||||||
user_agent,
|
user_agent,
|
||||||
local_public,
|
local_public,
|
||||||
discovery_config,
|
discovery_config,
|
||||||
params.block_request_protocol_config,
|
|
||||||
params.state_request_protocol_config,
|
|
||||||
params.warp_sync_protocol_config,
|
|
||||||
params.light_client_request_protocol_config,
|
|
||||||
params.network_config.request_response_protocols,
|
params.network_config.request_response_protocols,
|
||||||
peerset_handle.clone(),
|
peerset_handle.clone(),
|
||||||
);
|
);
|
||||||
@@ -466,9 +456,6 @@ where
|
|||||||
peers_notifications_sinks,
|
peers_notifications_sinks,
|
||||||
metrics,
|
metrics,
|
||||||
boot_node_ids,
|
boot_node_ids,
|
||||||
block_request_protocol_name,
|
|
||||||
state_request_protocol_name,
|
|
||||||
warp_sync_protocol_name,
|
|
||||||
_marker: Default::default(),
|
_marker: Default::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1287,15 +1274,6 @@ where
|
|||||||
/// For each peer and protocol combination, an object that allows sending notifications to
|
/// For each peer and protocol combination, an object that allows sending notifications to
|
||||||
/// that peer. Shared with the [`NetworkService`].
|
/// that peer. Shared with the [`NetworkService`].
|
||||||
peers_notifications_sinks: Arc<Mutex<HashMap<(PeerId, ProtocolName), NotificationsSink>>>,
|
peers_notifications_sinks: Arc<Mutex<HashMap<(PeerId, ProtocolName), NotificationsSink>>>,
|
||||||
/// Protocol name used to send out block requests via
|
|
||||||
/// [`crate::request_responses::RequestResponsesBehaviour`].
|
|
||||||
block_request_protocol_name: ProtocolName,
|
|
||||||
/// Protocol name used to send out state requests via
|
|
||||||
/// [`crate::request_responses::RequestResponsesBehaviour`].
|
|
||||||
state_request_protocol_name: ProtocolName,
|
|
||||||
/// Protocol name used to send out warp sync requests via
|
|
||||||
/// [`crate::request_responses::RequestResponsesBehaviour`].
|
|
||||||
warp_sync_protocol_name: Option<ProtocolName>,
|
|
||||||
/// Marker to pin the `H` generic. Serves no purpose except to not break backwards
|
/// Marker to pin the `H` generic. Serves no purpose except to not break backwards
|
||||||
/// compatibility.
|
/// compatibility.
|
||||||
_marker: PhantomData<H>,
|
_marker: PhantomData<H>,
|
||||||
@@ -1474,84 +1452,6 @@ where
|
|||||||
}
|
}
|
||||||
this.import_queue.import_justifications(origin, hash, nb, justifications);
|
this.import_queue.import_justifications(origin, hash, nb, justifications);
|
||||||
},
|
},
|
||||||
Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::BlockRequest {
|
|
||||||
target,
|
|
||||||
request,
|
|
||||||
pending_response,
|
|
||||||
})) => {
|
|
||||||
match this
|
|
||||||
.network_service
|
|
||||||
.behaviour()
|
|
||||||
.user_protocol()
|
|
||||||
.encode_block_request(&request)
|
|
||||||
{
|
|
||||||
Ok(data) => {
|
|
||||||
this.network_service.behaviour_mut().send_request(
|
|
||||||
&target,
|
|
||||||
&this.block_request_protocol_name,
|
|
||||||
data,
|
|
||||||
pending_response,
|
|
||||||
IfDisconnected::ImmediateError,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
log::warn!(
|
|
||||||
target: "sync",
|
|
||||||
"Failed to encode block request {:?}: {:?}",
|
|
||||||
request, err
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::StateRequest {
|
|
||||||
target,
|
|
||||||
request,
|
|
||||||
pending_response,
|
|
||||||
})) => {
|
|
||||||
match this
|
|
||||||
.network_service
|
|
||||||
.behaviour()
|
|
||||||
.user_protocol()
|
|
||||||
.encode_state_request(&request)
|
|
||||||
{
|
|
||||||
Ok(data) => {
|
|
||||||
this.network_service.behaviour_mut().send_request(
|
|
||||||
&target,
|
|
||||||
&this.state_request_protocol_name,
|
|
||||||
data,
|
|
||||||
pending_response,
|
|
||||||
IfDisconnected::ImmediateError,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
log::warn!(
|
|
||||||
target: "sync",
|
|
||||||
"Failed to encode state request {:?}: {:?}",
|
|
||||||
request, err
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::WarpSyncRequest {
|
|
||||||
target,
|
|
||||||
request,
|
|
||||||
pending_response,
|
|
||||||
})) => match &this.warp_sync_protocol_name {
|
|
||||||
Some(name) => this.network_service.behaviour_mut().send_request(
|
|
||||||
&target,
|
|
||||||
&name,
|
|
||||||
request.encode(),
|
|
||||||
pending_response,
|
|
||||||
IfDisconnected::ImmediateError,
|
|
||||||
),
|
|
||||||
None => {
|
|
||||||
log::warn!(
|
|
||||||
target: "sync",
|
|
||||||
"Trying to send warp sync request when no protocol is configured {:?}",
|
|
||||||
request,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::InboundRequest {
|
Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::InboundRequest {
|
||||||
protocol,
|
protocol,
|
||||||
result,
|
result,
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ use sc_block_builder::BlockBuilderProvider;
|
|||||||
use sc_client_api::HeaderBackend;
|
use sc_client_api::HeaderBackend;
|
||||||
use sc_consensus::JustificationSyncLink;
|
use sc_consensus::JustificationSyncLink;
|
||||||
use sc_network_common::{
|
use sc_network_common::{
|
||||||
config::{MultiaddrWithPeerId, SetConfig},
|
config::{MultiaddrWithPeerId, ProtocolId, SetConfig},
|
||||||
protocol::event::Event,
|
protocol::{event::Event, role::Roles, ProtocolName},
|
||||||
service::NetworkSyncForkRequest,
|
service::NetworkSyncForkRequest,
|
||||||
sync::{SyncState, SyncStatus},
|
sync::{SyncState, SyncStatus},
|
||||||
};
|
};
|
||||||
@@ -39,7 +39,6 @@ use sp_runtime::{
|
|||||||
traits::{Block as BlockT, Header as _},
|
traits::{Block as BlockT, Header as _},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
iter,
|
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
task::Poll,
|
task::Poll,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
@@ -49,10 +48,6 @@ use substrate_test_runtime_client::{TestClientBuilder, TestClientBuilderExt as _
|
|||||||
fn set_default_expecations_no_peers(
|
fn set_default_expecations_no_peers(
|
||||||
chain_sync: &mut MockChainSync<substrate_test_runtime_client::runtime::Block>,
|
chain_sync: &mut MockChainSync<substrate_test_runtime_client::runtime::Block>,
|
||||||
) {
|
) {
|
||||||
chain_sync.expect_block_requests().returning(|| Box::new(iter::empty()));
|
|
||||||
chain_sync.expect_state_request().returning(|| None);
|
|
||||||
chain_sync.expect_justification_requests().returning(|| Box::new(iter::empty()));
|
|
||||||
chain_sync.expect_warp_sync_request().returning(|| None);
|
|
||||||
chain_sync.expect_poll().returning(|_| Poll::Pending);
|
chain_sync.expect_poll().returning(|_| Poll::Pending);
|
||||||
chain_sync.expect_status().returning(|| SyncStatus {
|
chain_sync.expect_status().returning(|| SyncStatus {
|
||||||
state: SyncState::Idle,
|
state: SyncState::Idle,
|
||||||
@@ -342,13 +337,19 @@ async fn disconnect_peer_using_chain_sync_handle() {
|
|||||||
sc_network_sync::service::network::NetworkServiceProvider::new();
|
sc_network_sync::service::network::NetworkServiceProvider::new();
|
||||||
let handle_clone = chain_sync_network_handle.clone();
|
let handle_clone = chain_sync_network_handle.clone();
|
||||||
|
|
||||||
let (chain_sync, chain_sync_service) = ChainSync::new(
|
let (chain_sync, chain_sync_service, _) = ChainSync::new(
|
||||||
sc_network_common::sync::SyncMode::Full,
|
sc_network_common::sync::SyncMode::Full,
|
||||||
client.clone(),
|
client.clone(),
|
||||||
|
ProtocolId::from("test-protocol-name"),
|
||||||
|
&Some(String::from("test-fork-id")),
|
||||||
|
Roles::from(&config::Role::Full),
|
||||||
Box::new(sp_consensus::block_validation::DefaultBlockAnnounceValidator),
|
Box::new(sp_consensus::block_validation::DefaultBlockAnnounceValidator),
|
||||||
1u32,
|
1u32,
|
||||||
None,
|
None,
|
||||||
chain_sync_network_handle.clone(),
|
chain_sync_network_handle.clone(),
|
||||||
|
ProtocolName::from("block-request"),
|
||||||
|
ProtocolName::from("state-request"),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -216,31 +216,6 @@ impl TestNetworkBuilder {
|
|||||||
None,
|
None,
|
||||||
)));
|
)));
|
||||||
|
|
||||||
let (chain_sync_network_provider, chain_sync_network_handle) =
|
|
||||||
self.chain_sync_network.unwrap_or(NetworkServiceProvider::new());
|
|
||||||
|
|
||||||
let (chain_sync, chain_sync_service) = self.chain_sync.unwrap_or({
|
|
||||||
let (chain_sync, chain_sync_service) = ChainSync::new(
|
|
||||||
match network_config.sync_mode {
|
|
||||||
config::SyncMode::Full => sc_network_common::sync::SyncMode::Full,
|
|
||||||
config::SyncMode::Fast { skip_proofs, storage_chain_mode } =>
|
|
||||||
sc_network_common::sync::SyncMode::LightState {
|
|
||||||
skip_proofs,
|
|
||||||
storage_chain_mode,
|
|
||||||
},
|
|
||||||
config::SyncMode::Warp => sc_network_common::sync::SyncMode::Warp,
|
|
||||||
},
|
|
||||||
client.clone(),
|
|
||||||
Box::new(sp_consensus::block_validation::DefaultBlockAnnounceValidator),
|
|
||||||
network_config.max_parallel_downloads,
|
|
||||||
None,
|
|
||||||
chain_sync_network_handle,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
(Box::new(chain_sync), chain_sync_service)
|
|
||||||
});
|
|
||||||
|
|
||||||
let protocol_id = ProtocolId::from("test-protocol-name");
|
let protocol_id = ProtocolId::from("test-protocol-name");
|
||||||
let fork_id = Some(String::from("test-fork-id"));
|
let fork_id = Some(String::from("test-fork-id"));
|
||||||
|
|
||||||
@@ -289,6 +264,37 @@ impl TestNetworkBuilder {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let (chain_sync_network_provider, chain_sync_network_handle) =
|
||||||
|
self.chain_sync_network.unwrap_or(NetworkServiceProvider::new());
|
||||||
|
|
||||||
|
let (chain_sync, chain_sync_service) = self.chain_sync.unwrap_or({
|
||||||
|
let (chain_sync, chain_sync_service, _) = ChainSync::new(
|
||||||
|
match network_config.sync_mode {
|
||||||
|
config::SyncMode::Full => sc_network_common::sync::SyncMode::Full,
|
||||||
|
config::SyncMode::Fast { skip_proofs, storage_chain_mode } =>
|
||||||
|
sc_network_common::sync::SyncMode::LightState {
|
||||||
|
skip_proofs,
|
||||||
|
storage_chain_mode,
|
||||||
|
},
|
||||||
|
config::SyncMode::Warp => sc_network_common::sync::SyncMode::Warp,
|
||||||
|
},
|
||||||
|
client.clone(),
|
||||||
|
protocol_id.clone(),
|
||||||
|
&fork_id,
|
||||||
|
Roles::from(&config::Role::Full),
|
||||||
|
Box::new(sp_consensus::block_validation::DefaultBlockAnnounceValidator),
|
||||||
|
network_config.max_parallel_downloads,
|
||||||
|
None,
|
||||||
|
chain_sync_network_handle,
|
||||||
|
block_request_protocol_config.name.clone(),
|
||||||
|
state_request_protocol_config.name.clone(),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
(Box::new(chain_sync), chain_sync_service)
|
||||||
|
});
|
||||||
|
|
||||||
let worker = NetworkWorker::<
|
let worker = NetworkWorker::<
|
||||||
substrate_test_runtime_client::runtime::Block,
|
substrate_test_runtime_client::runtime::Block,
|
||||||
substrate_test_runtime_client::runtime::Hash,
|
substrate_test_runtime_client::runtime::Hash,
|
||||||
@@ -305,11 +311,12 @@ impl TestNetworkBuilder {
|
|||||||
chain_sync,
|
chain_sync,
|
||||||
chain_sync_service,
|
chain_sync_service,
|
||||||
metrics_registry: None,
|
metrics_registry: None,
|
||||||
block_request_protocol_config,
|
request_response_protocol_configs: [
|
||||||
state_request_protocol_config,
|
block_request_protocol_config,
|
||||||
light_client_request_protocol_config,
|
state_request_protocol_config,
|
||||||
warp_sync_protocol_config: None,
|
light_client_request_protocol_config,
|
||||||
request_response_protocol_configs: Vec::new(),
|
]
|
||||||
|
.to_vec(),
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ prost-build = "0.11"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
array-bytes = "4.1"
|
array-bytes = "4.1"
|
||||||
|
async-trait = "0.1.58"
|
||||||
codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] }
|
codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] }
|
||||||
futures = "0.3.21"
|
futures = "0.3.21"
|
||||||
libp2p = "0.49.0"
|
libp2p = "0.49.0"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -24,10 +24,8 @@ use libp2p::PeerId;
|
|||||||
use sc_consensus::{BlockImportError, BlockImportStatus};
|
use sc_consensus::{BlockImportError, BlockImportStatus};
|
||||||
use sc_network_common::sync::{
|
use sc_network_common::sync::{
|
||||||
message::{BlockAnnounce, BlockData, BlockRequest, BlockResponse},
|
message::{BlockAnnounce, BlockData, BlockRequest, BlockResponse},
|
||||||
warp::{EncodedProof, WarpProofRequest},
|
BadPeer, ChainSync as ChainSyncT, Metrics, OnBlockData, OnBlockJustification,
|
||||||
BadPeer, ChainSync as ChainSyncT, Metrics, OnBlockData, OnBlockJustification, OnStateData,
|
OpaqueBlockResponse, PeerInfo, PollBlockAnnounceValidation, PollResult, SyncStatus,
|
||||||
OpaqueBlockRequest, OpaqueBlockResponse, OpaqueStateRequest, OpaqueStateResponse, PeerInfo,
|
|
||||||
PollBlockAnnounceValidation, SyncStatus,
|
|
||||||
};
|
};
|
||||||
use sp_runtime::traits::{Block as BlockT, NumberFor};
|
use sp_runtime::traits::{Block as BlockT, NumberFor};
|
||||||
|
|
||||||
@@ -40,6 +38,7 @@ mockall::mock! {
|
|||||||
fn num_sync_requests(&self) -> usize;
|
fn num_sync_requests(&self) -> usize;
|
||||||
fn num_downloaded_blocks(&self) -> usize;
|
fn num_downloaded_blocks(&self) -> usize;
|
||||||
fn num_peers(&self) -> usize;
|
fn num_peers(&self) -> usize;
|
||||||
|
fn num_active_peers(&self) -> usize;
|
||||||
fn new_peer(
|
fn new_peer(
|
||||||
&mut self,
|
&mut self,
|
||||||
who: PeerId,
|
who: PeerId,
|
||||||
@@ -55,24 +54,12 @@ mockall::mock! {
|
|||||||
hash: &Block::Hash,
|
hash: &Block::Hash,
|
||||||
number: NumberFor<Block>,
|
number: NumberFor<Block>,
|
||||||
);
|
);
|
||||||
fn justification_requests<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
) -> Box<dyn Iterator<Item = (PeerId, BlockRequest<Block>)> + 'a>;
|
|
||||||
fn block_requests<'a>(&'a mut self) -> Box<dyn Iterator<Item = (PeerId, BlockRequest<Block>)> + 'a>;
|
|
||||||
fn state_request(&mut self) -> Option<(PeerId, OpaqueStateRequest)>;
|
|
||||||
fn warp_sync_request(&mut self) -> Option<(PeerId, WarpProofRequest<Block>)>;
|
|
||||||
fn on_block_data(
|
fn on_block_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
who: &PeerId,
|
who: &PeerId,
|
||||||
request: Option<BlockRequest<Block>>,
|
request: Option<BlockRequest<Block>>,
|
||||||
response: BlockResponse<Block>,
|
response: BlockResponse<Block>,
|
||||||
) -> Result<OnBlockData<Block>, BadPeer>;
|
) -> Result<OnBlockData<Block>, BadPeer>;
|
||||||
fn on_state_data(
|
|
||||||
&mut self,
|
|
||||||
who: &PeerId,
|
|
||||||
response: OpaqueStateResponse,
|
|
||||||
) -> Result<OnStateData<Block>, BadPeer>;
|
|
||||||
fn on_warp_sync_data(&mut self, who: &PeerId, response: EncodedProof) -> Result<(), BadPeer>;
|
|
||||||
fn on_block_justification(
|
fn on_block_justification(
|
||||||
&mut self,
|
&mut self,
|
||||||
who: PeerId,
|
who: PeerId,
|
||||||
@@ -104,19 +91,19 @@ mockall::mock! {
|
|||||||
) -> Poll<PollBlockAnnounceValidation<Block::Header>>;
|
) -> Poll<PollBlockAnnounceValidation<Block::Header>>;
|
||||||
fn peer_disconnected(&mut self, who: &PeerId) -> Option<OnBlockData<Block>>;
|
fn peer_disconnected(&mut self, who: &PeerId) -> Option<OnBlockData<Block>>;
|
||||||
fn metrics(&self) -> Metrics;
|
fn metrics(&self) -> Metrics;
|
||||||
fn create_opaque_block_request(&self, request: &BlockRequest<Block>) -> OpaqueBlockRequest;
|
|
||||||
fn encode_block_request(&self, request: &OpaqueBlockRequest) -> Result<Vec<u8>, String>;
|
|
||||||
fn decode_block_response(&self, response: &[u8]) -> Result<OpaqueBlockResponse, String>;
|
|
||||||
fn block_response_into_blocks(
|
fn block_response_into_blocks(
|
||||||
&self,
|
&self,
|
||||||
request: &BlockRequest<Block>,
|
request: &BlockRequest<Block>,
|
||||||
response: OpaqueBlockResponse,
|
response: OpaqueBlockResponse,
|
||||||
) -> Result<Vec<BlockData<Block>>, String>;
|
) -> Result<Vec<BlockData<Block>>, String>;
|
||||||
fn encode_state_request(&self, request: &OpaqueStateRequest) -> Result<Vec<u8>, String>;
|
|
||||||
fn decode_state_response(&self, response: &[u8]) -> Result<OpaqueStateResponse, String>;
|
|
||||||
fn poll<'a>(
|
fn poll<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cx: &mut std::task::Context<'a>,
|
cx: &mut std::task::Context<'a>,
|
||||||
) -> Poll<PollBlockAnnounceValidation<Block::Header>>;
|
) -> Poll<PollResult<Block>>;
|
||||||
|
fn send_block_request(
|
||||||
|
&mut self,
|
||||||
|
who: PeerId,
|
||||||
|
request: BlockRequest<Block>,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,16 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use sc_network_common::service::{NetworkPeers, NetworkSyncForkRequest};
|
use futures::channel::oneshot;
|
||||||
use sp_runtime::traits::{Block as BlockT, NumberFor};
|
|
||||||
|
|
||||||
pub use libp2p::{identity::error::SigningError, kad::record::Key as KademliaKey};
|
|
||||||
use libp2p::{Multiaddr, PeerId};
|
use libp2p::{Multiaddr, PeerId};
|
||||||
use sc_network_common::{config::MultiaddrWithPeerId, protocol::ProtocolName};
|
use sc_network_common::{
|
||||||
|
config::MultiaddrWithPeerId,
|
||||||
|
protocol::ProtocolName,
|
||||||
|
request_responses::{IfDisconnected, RequestFailure},
|
||||||
|
service::{NetworkPeers, NetworkRequest, NetworkSyncForkRequest},
|
||||||
|
};
|
||||||
use sc_peerset::ReputationChange;
|
use sc_peerset::ReputationChange;
|
||||||
|
use sp_runtime::traits::{Block as BlockT, NumberFor};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
mockall::mock! {
|
mockall::mock! {
|
||||||
@@ -72,4 +75,23 @@ mockall::mock! {
|
|||||||
fn remove_from_peers_set(&self, protocol: ProtocolName, peers: Vec<PeerId>);
|
fn remove_from_peers_set(&self, protocol: ProtocolName, peers: Vec<PeerId>);
|
||||||
fn sync_num_connected(&self) -> usize;
|
fn sync_num_connected(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl NetworkRequest for Network {
|
||||||
|
async fn request(
|
||||||
|
&self,
|
||||||
|
target: PeerId,
|
||||||
|
protocol: ProtocolName,
|
||||||
|
request: Vec<u8>,
|
||||||
|
connect: IfDisconnected,
|
||||||
|
) -> Result<Vec<u8>, RequestFailure>;
|
||||||
|
fn start_request(
|
||||||
|
&self,
|
||||||
|
target: PeerId,
|
||||||
|
protocol: ProtocolName,
|
||||||
|
request: Vec<u8>,
|
||||||
|
tx: oneshot::Sender<Result<Vec<u8>, RequestFailure>>,
|
||||||
|
connect: IfDisconnected,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,17 +16,21 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use futures::StreamExt;
|
use futures::{channel::oneshot, StreamExt};
|
||||||
use libp2p::PeerId;
|
use libp2p::PeerId;
|
||||||
use sc_network_common::{protocol::ProtocolName, service::NetworkPeers};
|
use sc_network_common::{
|
||||||
|
protocol::ProtocolName,
|
||||||
|
request_responses::{IfDisconnected, RequestFailure},
|
||||||
|
service::{NetworkPeers, NetworkRequest},
|
||||||
|
};
|
||||||
use sc_peerset::ReputationChange;
|
use sc_peerset::ReputationChange;
|
||||||
use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
|
use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Network-related services required by `sc-network-sync`
|
/// Network-related services required by `sc-network-sync`
|
||||||
pub trait Network: NetworkPeers {}
|
pub trait Network: NetworkPeers + NetworkRequest {}
|
||||||
|
|
||||||
impl<T> Network for T where T: NetworkPeers {}
|
impl<T> Network for T where T: NetworkPeers + NetworkRequest {}
|
||||||
|
|
||||||
/// Network service provider for `ChainSync`
|
/// Network service provider for `ChainSync`
|
||||||
///
|
///
|
||||||
@@ -43,6 +47,15 @@ pub enum ToServiceCommand {
|
|||||||
|
|
||||||
/// Call `NetworkPeers::report_peer()`
|
/// Call `NetworkPeers::report_peer()`
|
||||||
ReportPeer(PeerId, ReputationChange),
|
ReportPeer(PeerId, ReputationChange),
|
||||||
|
|
||||||
|
/// Call `NetworkRequest::start_request()`
|
||||||
|
StartRequest(
|
||||||
|
PeerId,
|
||||||
|
ProtocolName,
|
||||||
|
Vec<u8>,
|
||||||
|
oneshot::Sender<Result<Vec<u8>, RequestFailure>>,
|
||||||
|
IfDisconnected,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle that is (temporarily) passed to `ChainSync` so it can
|
/// Handle that is (temporarily) passed to `ChainSync` so it can
|
||||||
@@ -67,6 +80,20 @@ impl NetworkServiceHandle {
|
|||||||
pub fn disconnect_peer(&self, who: PeerId, protocol: ProtocolName) {
|
pub fn disconnect_peer(&self, who: PeerId, protocol: ProtocolName) {
|
||||||
let _ = self.tx.unbounded_send(ToServiceCommand::DisconnectPeer(who, protocol));
|
let _ = self.tx.unbounded_send(ToServiceCommand::DisconnectPeer(who, protocol));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send request to peer
|
||||||
|
pub fn start_request(
|
||||||
|
&self,
|
||||||
|
who: PeerId,
|
||||||
|
protocol: ProtocolName,
|
||||||
|
request: Vec<u8>,
|
||||||
|
tx: oneshot::Sender<Result<Vec<u8>, RequestFailure>>,
|
||||||
|
connect: IfDisconnected,
|
||||||
|
) {
|
||||||
|
let _ = self
|
||||||
|
.tx
|
||||||
|
.unbounded_send(ToServiceCommand::StartRequest(who, protocol, request, tx, connect));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetworkServiceProvider {
|
impl NetworkServiceProvider {
|
||||||
@@ -85,6 +112,8 @@ impl NetworkServiceProvider {
|
|||||||
service.disconnect_peer(peer, protocol_name),
|
service.disconnect_peer(peer, protocol_name),
|
||||||
ToServiceCommand::ReportPeer(peer, reputation_change) =>
|
ToServiceCommand::ReportPeer(peer, reputation_change) =>
|
||||||
service.report_peer(peer, reputation_change),
|
service.report_peer(peer, reputation_change),
|
||||||
|
ToServiceCommand::StartRequest(peer, protocol, request, tx, connect) =>
|
||||||
|
service.start_request(peer, protocol, request, tx, connect),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,15 @@
|
|||||||
use crate::{service::network::NetworkServiceProvider, ChainSync, ForkTarget};
|
use crate::{service::network::NetworkServiceProvider, ChainSync, ForkTarget};
|
||||||
|
|
||||||
use libp2p::PeerId;
|
use libp2p::PeerId;
|
||||||
use sc_network_common::{service::NetworkSyncForkRequest, sync::ChainSync as ChainSyncT};
|
use sc_network_common::{
|
||||||
|
config::ProtocolId,
|
||||||
|
protocol::{
|
||||||
|
role::{Role, Roles},
|
||||||
|
ProtocolName,
|
||||||
|
},
|
||||||
|
service::NetworkSyncForkRequest,
|
||||||
|
sync::ChainSync as ChainSyncT,
|
||||||
|
};
|
||||||
use sp_consensus::block_validation::DefaultBlockAnnounceValidator;
|
use sp_consensus::block_validation::DefaultBlockAnnounceValidator;
|
||||||
use sp_core::H256;
|
use sp_core::H256;
|
||||||
use std::{sync::Arc, task::Poll};
|
use std::{sync::Arc, task::Poll};
|
||||||
@@ -30,13 +38,19 @@ use substrate_test_runtime_client::{TestClientBuilder, TestClientBuilderExt as _
|
|||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn delegate_to_chainsync() {
|
async fn delegate_to_chainsync() {
|
||||||
let (_chain_sync_network_provider, chain_sync_network_handle) = NetworkServiceProvider::new();
|
let (_chain_sync_network_provider, chain_sync_network_handle) = NetworkServiceProvider::new();
|
||||||
let (mut chain_sync, chain_sync_service) = ChainSync::new(
|
let (mut chain_sync, chain_sync_service, _) = ChainSync::new(
|
||||||
sc_network_common::sync::SyncMode::Full,
|
sc_network_common::sync::SyncMode::Full,
|
||||||
Arc::new(TestClientBuilder::with_default_backend().build_with_longest_chain().0),
|
Arc::new(TestClientBuilder::with_default_backend().build_with_longest_chain().0),
|
||||||
|
ProtocolId::from("test-protocol-name"),
|
||||||
|
&Some(String::from("test-fork-id")),
|
||||||
|
Roles::from(&Role::Full),
|
||||||
Box::new(DefaultBlockAnnounceValidator),
|
Box::new(DefaultBlockAnnounceValidator),
|
||||||
1u32,
|
1u32,
|
||||||
None,
|
None,
|
||||||
chain_sync_network_handle,
|
chain_sync_network_handle,
|
||||||
|
ProtocolName::from("block-request"),
|
||||||
|
ProtocolName::from("state-request"),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ use sp_core::H256;
|
|||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
codec::{Decode, Encode},
|
codec::{Decode, Encode},
|
||||||
generic::{BlockId, OpaqueDigestItemId},
|
generic::{BlockId, OpaqueDigestItemId},
|
||||||
traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero},
|
traits::{Block as BlockT, Header as HeaderT, NumberFor},
|
||||||
Justification, Justifications,
|
Justification, Justifications,
|
||||||
};
|
};
|
||||||
use substrate_test_runtime_client::AccountKeyring;
|
use substrate_test_runtime_client::AccountKeyring;
|
||||||
@@ -869,7 +869,7 @@ where
|
|||||||
.unwrap_or_else(|| Box::new(DefaultBlockAnnounceValidator));
|
.unwrap_or_else(|| Box::new(DefaultBlockAnnounceValidator));
|
||||||
let (chain_sync_network_provider, chain_sync_network_handle) =
|
let (chain_sync_network_provider, chain_sync_network_handle) =
|
||||||
NetworkServiceProvider::new();
|
NetworkServiceProvider::new();
|
||||||
let (chain_sync, chain_sync_service) = ChainSync::new(
|
let (chain_sync, chain_sync_service, block_announce_config) = ChainSync::new(
|
||||||
match network_config.sync_mode {
|
match network_config.sync_mode {
|
||||||
SyncMode::Full => sc_network_common::sync::SyncMode::Full,
|
SyncMode::Full => sc_network_common::sync::SyncMode::Full,
|
||||||
SyncMode::Fast { skip_proofs, storage_chain_mode } =>
|
SyncMode::Fast { skip_proofs, storage_chain_mode } =>
|
||||||
@@ -880,24 +880,18 @@ where
|
|||||||
SyncMode::Warp => sc_network_common::sync::SyncMode::Warp,
|
SyncMode::Warp => sc_network_common::sync::SyncMode::Warp,
|
||||||
},
|
},
|
||||||
client.clone(),
|
client.clone(),
|
||||||
|
protocol_id.clone(),
|
||||||
|
&fork_id,
|
||||||
|
Roles::from(if config.is_authority { &Role::Authority } else { &Role::Full }),
|
||||||
block_announce_validator,
|
block_announce_validator,
|
||||||
network_config.max_parallel_downloads,
|
network_config.max_parallel_downloads,
|
||||||
Some(warp_sync),
|
Some(warp_sync),
|
||||||
chain_sync_network_handle,
|
chain_sync_network_handle,
|
||||||
|
block_request_protocol_config.name.clone(),
|
||||||
|
state_request_protocol_config.name.clone(),
|
||||||
|
Some(warp_protocol_config.name.clone()),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let block_announce_config = chain_sync.get_block_announce_proto_config(
|
|
||||||
protocol_id.clone(),
|
|
||||||
&fork_id,
|
|
||||||
Roles::from(if config.is_authority { &Role::Authority } else { &Role::Full }),
|
|
||||||
client.info().best_number,
|
|
||||||
client.info().best_hash,
|
|
||||||
client
|
|
||||||
.block_hash(Zero::zero())
|
|
||||||
.ok()
|
|
||||||
.flatten()
|
|
||||||
.expect("Genesis block exists; qed"),
|
|
||||||
);
|
|
||||||
|
|
||||||
let network = NetworkWorker::new(sc_network::config::Params {
|
let network = NetworkWorker::new(sc_network::config::Params {
|
||||||
role: if config.is_authority { Role::Authority } else { Role::Full },
|
role: if config.is_authority { Role::Authority } else { Role::Full },
|
||||||
@@ -911,11 +905,13 @@ where
|
|||||||
chain_sync_service,
|
chain_sync_service,
|
||||||
metrics_registry: None,
|
metrics_registry: None,
|
||||||
block_announce_config,
|
block_announce_config,
|
||||||
block_request_protocol_config,
|
request_response_protocol_configs: [
|
||||||
state_request_protocol_config,
|
block_request_protocol_config,
|
||||||
light_client_request_protocol_config,
|
state_request_protocol_config,
|
||||||
warp_sync_protocol_config: Some(warp_protocol_config),
|
light_client_request_protocol_config,
|
||||||
request_response_protocol_configs: Vec::new(),
|
warp_protocol_config,
|
||||||
|
]
|
||||||
|
.to_vec(),
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -994,6 +990,7 @@ where
|
|||||||
return Poll::Pending
|
return Poll::Pending
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Poll::Ready(())
|
Poll::Ready(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -846,7 +846,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
let (chain_sync_network_provider, chain_sync_network_handle) = NetworkServiceProvider::new();
|
let (chain_sync_network_provider, chain_sync_network_handle) = NetworkServiceProvider::new();
|
||||||
let (chain_sync, chain_sync_service) = ChainSync::new(
|
let (chain_sync, chain_sync_service, block_announce_config) = ChainSync::new(
|
||||||
match config.network.sync_mode {
|
match config.network.sync_mode {
|
||||||
SyncMode::Full => sc_network_common::sync::SyncMode::Full,
|
SyncMode::Full => sc_network_common::sync::SyncMode::Full,
|
||||||
SyncMode::Fast { skip_proofs, storage_chain_mode } =>
|
SyncMode::Fast { skip_proofs, storage_chain_mode } =>
|
||||||
@@ -854,25 +854,18 @@ where
|
|||||||
SyncMode::Warp => sc_network_common::sync::SyncMode::Warp,
|
SyncMode::Warp => sc_network_common::sync::SyncMode::Warp,
|
||||||
},
|
},
|
||||||
client.clone(),
|
client.clone(),
|
||||||
|
protocol_id.clone(),
|
||||||
|
&config.chain_spec.fork_id().map(ToOwned::to_owned),
|
||||||
|
Roles::from(&config.role),
|
||||||
block_announce_validator,
|
block_announce_validator,
|
||||||
config.network.max_parallel_downloads,
|
config.network.max_parallel_downloads,
|
||||||
warp_sync_provider,
|
warp_sync_provider,
|
||||||
chain_sync_network_handle,
|
chain_sync_network_handle,
|
||||||
|
block_request_protocol_config.name.clone(),
|
||||||
|
state_request_protocol_config.name.clone(),
|
||||||
|
warp_sync_protocol_config.as_ref().map(|config| config.name.clone()),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let block_announce_config = chain_sync.get_block_announce_proto_config(
|
|
||||||
protocol_id.clone(),
|
|
||||||
&config.chain_spec.fork_id().map(ToOwned::to_owned),
|
|
||||||
Roles::from(&config.role.clone()),
|
|
||||||
client.info().best_number,
|
|
||||||
client.info().best_hash,
|
|
||||||
client
|
|
||||||
.block_hash(Zero::zero())
|
|
||||||
.ok()
|
|
||||||
.flatten()
|
|
||||||
.expect("Genesis block exists; qed"),
|
|
||||||
);
|
|
||||||
|
|
||||||
request_response_protocol_configs.push(config.network.ipfs_server.then(|| {
|
request_response_protocol_configs.push(config.network.ipfs_server.then(|| {
|
||||||
let (handler, protocol_config) = BitswapRequestHandler::new(client.clone());
|
let (handler, protocol_config) = BitswapRequestHandler::new(client.clone());
|
||||||
spawn_handle.spawn("bitswap-request-handler", Some("networking"), handler.run());
|
spawn_handle.spawn("bitswap-request-handler", Some("networking"), handler.run());
|
||||||
@@ -896,12 +889,14 @@ where
|
|||||||
chain_sync_service,
|
chain_sync_service,
|
||||||
metrics_registry: config.prometheus_config.as_ref().map(|config| config.registry.clone()),
|
metrics_registry: config.prometheus_config.as_ref().map(|config| config.registry.clone()),
|
||||||
block_announce_config,
|
block_announce_config,
|
||||||
block_request_protocol_config,
|
|
||||||
state_request_protocol_config,
|
|
||||||
warp_sync_protocol_config,
|
|
||||||
light_client_request_protocol_config,
|
|
||||||
request_response_protocol_configs: request_response_protocol_configs
|
request_response_protocol_configs: request_response_protocol_configs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
.chain([
|
||||||
|
Some(block_request_protocol_config),
|
||||||
|
Some(state_request_protocol_config),
|
||||||
|
Some(light_client_request_protocol_config),
|
||||||
|
warp_sync_protocol_config,
|
||||||
|
])
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user