diff --git a/substrate/client/consensus/beefy/src/communication/request_response/incoming_requests_handler.rs b/substrate/client/consensus/beefy/src/communication/request_response/incoming_requests_handler.rs index c473c14bccc3..bab2bca9006f 100644 --- a/substrate/client/consensus/beefy/src/communication/request_response/incoming_requests_handler.rs +++ b/substrate/client/consensus/beefy/src/communication/request_response/incoming_requests_handler.rs @@ -148,7 +148,7 @@ where ) -> (Self, Network::RequestResponseProtocolConfig) { let (request_receiver, config): (_, Network::RequestResponseProtocolConfig) = on_demand_justifications_protocol_config::<_, _, Network>(genesis_hash, fork_id); - let justif_protocol_name = config.protocol_name().clone(); + let justif_protocol_name = config.protocol_names().protocol_name().clone(); let metrics = register_metrics(prometheus_registry); ( Self { request_receiver, justif_protocol_name, client, metrics, _block: PhantomData }, diff --git a/substrate/client/network/src/litep2p/shim/request_response/mod.rs b/substrate/client/network/src/litep2p/shim/request_response/mod.rs index bfd7a60ef9fe..c2c111760fcd 100644 --- a/substrate/client/network/src/litep2p/shim/request_response/mod.rs +++ b/substrate/client/network/src/litep2p/shim/request_response/mod.rs @@ -24,6 +24,7 @@ use crate::{ peer_store::PeerStoreProvider, request_responses::{IncomingRequest, OutgoingResponse}, service::{metrics::Metrics, traits::RequestResponseConfig as RequestResponseConfigT}, + types::ProtocolSupportedNames, IfDisconnected, OutboundFailure, ProtocolName, RequestFailure, }; @@ -150,8 +151,8 @@ impl RequestResponseConfig { } impl RequestResponseConfigT for RequestResponseConfig { - fn protocol_name(&self) -> &ProtocolName { - &self.protocol_name + fn protocol_names(&self) -> ProtocolSupportedNames { + ProtocolSupportedNames::new(self.protocol_name.clone(), self.fallback_names.clone()) } } diff --git a/substrate/client/network/src/request_responses.rs b/substrate/client/network/src/request_responses.rs index 6c2631924df4..79a7b740324f 100644 --- a/substrate/client/network/src/request_responses.rs +++ b/substrate/client/network/src/request_responses.rs @@ -37,7 +37,7 @@ use crate::{ peer_store::{PeerStoreProvider, BANNED_THRESHOLD}, service::traits::RequestResponseConfig as RequestResponseConfigT, - types::ProtocolName, + types::{ProtocolName, ProtocolSupportedNames}, ReputationChange, }; @@ -194,8 +194,8 @@ pub struct ProtocolConfig { } impl RequestResponseConfigT for ProtocolConfig { - fn protocol_name(&self) -> &ProtocolName { - &self.name + fn protocol_names(&self) -> ProtocolSupportedNames { + ProtocolSupportedNames::new(self.name.clone(), self.fallback_names.clone()) } } diff --git a/substrate/client/network/src/service/traits.rs b/substrate/client/network/src/service/traits.rs index f5dd2995acb1..447e72dfa744 100644 --- a/substrate/client/network/src/service/traits.rs +++ b/substrate/client/network/src/service/traits.rs @@ -27,7 +27,7 @@ use crate::{ network_state::NetworkState, request_responses::{IfDisconnected, RequestFailure}, service::{metrics::NotificationMetrics, signature::Signature, PeerStoreProvider}, - types::ProtocolName, + types::{ProtocolName, ProtocolSupportedNames}, ReputationChange, }; @@ -94,8 +94,8 @@ pub trait NotificationConfig: Debug { /// Trait defining the required functionality from a request-response protocol configuration. pub trait RequestResponseConfig: Debug { - /// Get protocol name. - fn protocol_name(&self) -> &ProtocolName; + /// Get protocol supported names. + fn protocol_names(&self) -> ProtocolSupportedNames; } /// Trait defining required functionality from `PeerStore`. diff --git a/substrate/client/network/src/types.rs b/substrate/client/network/src/types.rs index 5289389de381..6a5eaf2500a9 100644 --- a/substrate/client/network/src/types.rs +++ b/substrate/client/network/src/types.rs @@ -26,6 +26,39 @@ use std::{ sync::Arc, }; +/// The supported names for a request response protocol. +/// +/// A protocol may support a main protocol name and a list of fallback protocol names. +#[derive(Debug, Clone)] +pub struct ProtocolSupportedNames { + /// The main protocol name. + protocol_name: ProtocolName, + /// The fallback protocol names. + fallback_protocol_names: Vec, +} + +impl ProtocolSupportedNames { + /// Create a new instance of [`ProtocolSupportedNames`]. + pub fn new(protocol_name: ProtocolName, fallback_protocol_names: Vec) -> Self { + Self { protocol_name, fallback_protocol_names } + } + + /// Get the protocol name. + pub fn protocol_name(&self) -> &ProtocolName { + &self.protocol_name + } + + /// Get the fallback protocol names. + pub fn fallback_protocol_names(&self) -> &Vec { + &self.fallback_protocol_names + } + + /// Check if the protocol name is supported. + pub fn is_supported(&self, protocol_name: &ProtocolName) -> bool { + &self.protocol_name == protocol_name || self.fallback_protocol_names.contains(protocol_name) + } +} + /// The protocol name transmitted on the wire. #[derive(Debug, Clone)] pub enum ProtocolName { diff --git a/substrate/client/network/sync/src/block_relay_protocol.rs b/substrate/client/network/sync/src/block_relay_protocol.rs index 13639d851b27..40a0c6f169a6 100644 --- a/substrate/client/network/sync/src/block_relay_protocol.rs +++ b/substrate/client/network/sync/src/block_relay_protocol.rs @@ -17,7 +17,9 @@ //! Block relay protocol related definitions. use futures::channel::oneshot; -use sc_network::{request_responses::RequestFailure, NetworkBackend, ProtocolName}; +use sc_network::{ + request_responses::RequestFailure, types::ProtocolSupportedNames, NetworkBackend, ProtocolName, +}; use sc_network_common::sync::message::{BlockData, BlockRequest}; use sc_network_types::PeerId; use sp_runtime::traits::Block as BlockT; @@ -35,8 +37,8 @@ pub trait BlockServer: Send { /// that can be used to initiate concurrent downloads. #[async_trait::async_trait] pub trait BlockDownloader: fmt::Debug + Send + Sync { - /// Protocol name used by block downloader. - fn protocol_name(&self) -> &ProtocolName; + /// Protocol names used by block downloader. + fn protocol_names(&self) -> ProtocolSupportedNames; /// Performs the protocol specific sequence to fetch the blocks from the peer. /// Output: if the download succeeds, the response is a `Vec` which is diff --git a/substrate/client/network/sync/src/block_request_handler.rs b/substrate/client/network/sync/src/block_request_handler.rs index 80234170bc20..dd919049dfff 100644 --- a/substrate/client/network/sync/src/block_request_handler.rs +++ b/substrate/client/network/sync/src/block_request_handler.rs @@ -38,7 +38,7 @@ use sc_network::{ config::ProtocolId, request_responses::{IfDisconnected, IncomingRequest, OutgoingResponse, RequestFailure}, service::traits::RequestResponseConfig, - types::ProtocolName, + types::{ProtocolName, ProtocolSupportedNames}, NetworkBackend, MAX_RESPONSE_SIZE, }; use sc_network_common::sync::message::{BlockAttributes, BlockData, BlockRequest, FromBlock}; @@ -190,7 +190,7 @@ where BlockRelayParams { server: Box::new(Self { client, request_receiver, seen_requests }), downloader: Arc::new(FullBlockDownloader::new( - protocol_config.protocol_name().clone(), + protocol_config.protocol_names(), network, )), request_response_config: protocol_config, @@ -504,13 +504,13 @@ enum HandleRequestError { /// The full block downloader implementation of [`BlockDownloader]. #[derive(Debug)] pub struct FullBlockDownloader { - protocol_name: ProtocolName, + protocol_names: ProtocolSupportedNames, network: NetworkServiceHandle, } impl FullBlockDownloader { - fn new(protocol_name: ProtocolName, network: NetworkServiceHandle) -> Self { - Self { protocol_name, network } + fn new(protocol_names: ProtocolSupportedNames, network: NetworkServiceHandle) -> Self { + Self { protocol_names, network } } /// Extracts the blocks from the response schema. @@ -577,8 +577,8 @@ impl FullBlockDownloader { #[async_trait::async_trait] impl BlockDownloader for FullBlockDownloader { - fn protocol_name(&self) -> &ProtocolName { - &self.protocol_name + fn protocol_names(&self) -> ProtocolSupportedNames { + self.protocol_names.clone() } async fn download_blocks( @@ -602,7 +602,7 @@ impl BlockDownloader for FullBlockDownloader { let (tx, rx) = oneshot::channel(); self.network.start_request( who, - self.protocol_name.clone(), + self.protocol_names.protocol_name().clone(), bytes, tx, IfDisconnected::ImmediateError, diff --git a/substrate/client/network/sync/src/mock.rs b/substrate/client/network/sync/src/mock.rs index bf25156f9703..db8e01eeb895 100644 --- a/substrate/client/network/sync/src/mock.rs +++ b/substrate/client/network/sync/src/mock.rs @@ -21,7 +21,7 @@ use crate::block_relay_protocol::{BlockDownloader as BlockDownloaderT, BlockResponseError}; use futures::channel::oneshot; -use sc_network::{ProtocolName, RequestFailure}; +use sc_network::{types::ProtocolSupportedNames, ProtocolName, RequestFailure}; use sc_network_common::sync::message::{BlockData, BlockRequest}; use sc_network_types::PeerId; use sp_runtime::traits::Block as BlockT; @@ -32,7 +32,7 @@ mockall::mock! { #[async_trait::async_trait] impl BlockDownloaderT for BlockDownloader { - fn protocol_name(&self) -> &ProtocolName; + fn protocol_names(&self) -> ProtocolSupportedNames; async fn download_blocks( &self, diff --git a/substrate/client/network/sync/src/strategy/chain_sync.rs b/substrate/client/network/sync/src/strategy/chain_sync.rs index 18170b77881e..b7af272cefde 100644 --- a/substrate/client/network/sync/src/strategy/chain_sync.rs +++ b/substrate/client/network/sync/src/strategy/chain_sync.rs @@ -50,7 +50,7 @@ use prometheus_endpoint::{register, Gauge, PrometheusError, Registry, U64}; use prost::Message; use sc_client_api::{blockchain::BlockGap, BlockBackend, ProofProvider}; use sc_consensus::{BlockImportError, BlockImportStatus, IncomingBlock}; -use sc_network::{IfDisconnected, ProtocolName}; +use sc_network::{types::ProtocolSupportedNames, IfDisconnected, ProtocolName}; use sc_network_common::sync::message::{ BlockAnnounce, BlockAttributes, BlockData, BlockRequest, BlockResponse, Direction, FromBlock, }; @@ -326,8 +326,8 @@ pub struct ChainSync { max_parallel_downloads: u32, /// Maximum blocks per request. max_blocks_per_request: u32, - /// Protocol name used to send out state requests - state_request_protocol_name: ProtocolName, + /// Protocol names used to send out state requests + state_request_protocol_names: ProtocolSupportedNames, /// Total number of downloaded blocks. downloaded_blocks: usize, /// State sync in progress, if any. @@ -589,7 +589,7 @@ where return; } - if protocol_name == self.state_request_protocol_name { + if self.state_request_protocol_names.is_supported(&protocol_name) { let Ok(response) = response.downcast::>() else { warn!(target: LOG_TARGET, "Failed to downcast state response"); debug_assert!(false); @@ -599,7 +599,11 @@ where if let Err(bad_peer) = self.on_state_data(&peer_id, &response) { self.actions.push(SyncingAction::DropPeer(bad_peer)); } - } else if &protocol_name == self.block_downloader.protocol_name() { + + return; + } + + if self.block_downloader.protocol_names().is_supported(&protocol_name) { let Ok(response) = response .downcast::<(BlockRequest, Result>, BlockResponseError>)>() else { @@ -636,14 +640,16 @@ where if let Err(bad_peer) = self.on_block_response(peer_id, key, request, blocks) { self.actions.push(SyncingAction::DropPeer(bad_peer)); } - } else { - warn!( - target: LOG_TARGET, - "Unexpected generic response protocol {protocol_name}, strategy key \ - {key:?}", - ); - debug_assert!(false); + + return; } + + warn!( + target: LOG_TARGET, + "Unexpected generic response protocol {protocol_name}, strategy key \ + {key:?}", + ); + debug_assert!(false); } fn on_blocks_processed( @@ -901,7 +907,7 @@ where network_service.start_request( peer_id, - self.state_request_protocol_name.clone(), + self.state_request_protocol_names.protocol_name().clone(), request.encode_to_vec(), tx, IfDisconnected::ImmediateError, @@ -945,7 +951,7 @@ where client: Arc, max_parallel_downloads: u32, max_blocks_per_request: u32, - state_request_protocol_name: ProtocolName, + state_request_protocol_names: ProtocolSupportedNames, block_downloader: Arc>, metrics_registry: Option<&Registry>, initial_peers: impl Iterator)>, @@ -965,7 +971,7 @@ where allowed_requests: Default::default(), max_parallel_downloads, max_blocks_per_request, - state_request_protocol_name, + state_request_protocol_names, downloaded_blocks: 0, state_sync: None, import_existing: false, diff --git a/substrate/client/network/sync/src/strategy/polkadot.rs b/substrate/client/network/sync/src/strategy/polkadot.rs index 44b05966af06..ffb73e554cb9 100644 --- a/substrate/client/network/sync/src/strategy/polkadot.rs +++ b/substrate/client/network/sync/src/strategy/polkadot.rs @@ -36,11 +36,12 @@ use log::{debug, error, info, warn}; use prometheus_endpoint::Registry; use sc_client_api::{BlockBackend, ProofProvider}; use sc_consensus::{BlockImportError, BlockImportStatus}; -use sc_network::ProtocolName; +use sc_network::{types::ProtocolSupportedNames, ProtocolName}; use sc_network_common::sync::{message::BlockAnnounce, SyncMode}; use sc_network_types::PeerId; use sp_blockchain::{Error as ClientError, HeaderBackend, HeaderMetadata}; use sp_runtime::traits::{Block as BlockT, Header, NumberFor}; + use std::{any::Any, collections::HashMap, sync::Arc}; /// Corresponding `ChainSync` mode. @@ -67,8 +68,8 @@ where pub max_blocks_per_request: u32, /// Prometheus metrics registry. pub metrics_registry: Option, - /// Protocol name used to send out state requests - pub state_request_protocol_name: ProtocolName, + /// Protocol names used to send out state requests + pub state_request_protocol_names: ProtocolSupportedNames, /// Block downloader pub block_downloader: Arc>, } @@ -342,7 +343,7 @@ where mut config: PolkadotSyncingStrategyConfig, client: Arc, warp_sync_config: Option>, - warp_sync_protocol_name: Option, + warp_sync_protocol_names: Option, ) -> Result { if config.max_blocks_per_request > MAX_BLOCKS_IN_RESPONSE as u32 { info!( @@ -358,7 +359,7 @@ where let warp_sync = WarpSync::new( client.clone(), warp_sync_config, - warp_sync_protocol_name, + warp_sync_protocol_names, config.block_downloader.clone(), ); Ok(Self { @@ -375,7 +376,7 @@ where client.clone(), config.max_parallel_downloads, config.max_blocks_per_request, - config.state_request_protocol_name.clone(), + config.state_request_protocol_names.clone(), config.block_downloader.clone(), config.metrics_registry.as_ref(), std::iter::empty(), @@ -410,7 +411,7 @@ where self.peer_best_blocks .iter() .map(|(peer_id, (_, best_number))| (*peer_id, *best_number)), - self.config.state_request_protocol_name.clone(), + self.config.state_request_protocol_names.protocol_name().clone(), ); self.warp = None; @@ -427,7 +428,7 @@ where self.client.clone(), self.config.max_parallel_downloads, self.config.max_blocks_per_request, - self.config.state_request_protocol_name.clone(), + self.config.state_request_protocol_names.clone(), self.config.block_downloader.clone(), self.config.metrics_registry.as_ref(), self.peer_best_blocks.iter().map(|(peer_id, (best_hash, best_number))| { @@ -457,7 +458,7 @@ where self.client.clone(), self.config.max_parallel_downloads, self.config.max_blocks_per_request, - self.config.state_request_protocol_name.clone(), + self.config.state_request_protocol_names.clone(), self.config.block_downloader.clone(), self.config.metrics_registry.as_ref(), self.peer_best_blocks.iter().map(|(peer_id, (best_hash, best_number))| { diff --git a/substrate/client/network/sync/src/strategy/warp.rs b/substrate/client/network/sync/src/strategy/warp.rs index 673bc1688ecc..9edea9ed025f 100644 --- a/substrate/client/network/sync/src/strategy/warp.rs +++ b/substrate/client/network/sync/src/strategy/warp.rs @@ -33,7 +33,7 @@ use crate::{ use codec::{Decode, Encode}; use futures::{channel::oneshot, FutureExt}; use log::{debug, error, trace, warn}; -use sc_network::{IfDisconnected, ProtocolName}; +use sc_network::{types::ProtocolSupportedNames, IfDisconnected, ProtocolName}; use sc_network_common::sync::message::{ BlockAnnounce, BlockAttributes, BlockData, BlockRequest, Direction, FromBlock, }; @@ -43,6 +43,7 @@ use sp_runtime::{ traits::{Block as BlockT, Header, NumberFor, Zero}, Justifications, SaturatedConversion, }; + use std::{any::Any, collections::HashMap, fmt, sync::Arc}; /// Number of peers that need to be connected before warp sync is started. @@ -209,7 +210,7 @@ pub struct WarpSync { total_state_bytes: u64, peers: HashMap>, disconnected_peers: DisconnectedPeers, - protocol_name: Option, + protocol_names: Option, block_downloader: Arc>, actions: Vec>, result: Option>, @@ -229,7 +230,7 @@ where pub fn new( client: Arc, warp_sync_config: WarpSyncConfig, - protocol_name: Option, + protocol_names: Option, block_downloader: Arc>, ) -> Self { if client.info().finalized_state.is_some() { @@ -244,7 +245,7 @@ where total_state_bytes: 0, peers: HashMap::new(), disconnected_peers: DisconnectedPeers::new(), - protocol_name, + protocol_names, block_downloader, actions: vec![SyncingAction::Finished], result: None, @@ -264,7 +265,7 @@ where total_state_bytes: 0, peers: HashMap::new(), disconnected_peers: DisconnectedPeers::new(), - protocol_name, + protocol_names, block_downloader, actions: Vec::new(), result: None, @@ -335,7 +336,7 @@ where protocol_name: ProtocolName, response: Box, ) { - if &protocol_name == self.block_downloader.protocol_name() { + if self.block_downloader.protocol_names().is_supported(&protocol_name) { let Ok(response) = response .downcast::<(BlockRequest, Result>, BlockResponseError>)>() else { @@ -553,7 +554,9 @@ where let request = WarpProofRequest { begin }; - let Some(protocol_name) = self.protocol_name.clone() else { + let Some(protocol_name) = + self.protocol_names.as_ref().map(|names| names.protocol_name()).cloned() + else { warn!( target: LOG_TARGET, "Trying to send warp sync request when no protocol is configured {request:?}", diff --git a/substrate/client/service/src/builder.rs b/substrate/client/service/src/builder.rs index ac9371a8941b..2c7f4245e553 100644 --- a/substrate/client/service/src/builder.rs +++ b/substrate/client/service/src/builder.rs @@ -1337,20 +1337,20 @@ where let genesis_hash = client.info().genesis_hash; - let (state_request_protocol_config, state_request_protocol_name) = { + let (state_request_protocol_config, state_request_protocol_names) = { let num_peer_hint = net_config.network_config.default_peers_set_num_full as usize + net_config.network_config.default_peers_set.reserved_nodes.len(); // Allow both outgoing and incoming requests. let (handler, protocol_config) = StateRequestHandler::new::(&protocol_id, fork_id, client.clone(), num_peer_hint); - let config_name = protocol_config.protocol_name().clone(); + let protocol_names = protocol_config.protocol_names(); spawn_handle.spawn("state-request-handler", Some("networking"), handler.run()); - (protocol_config, config_name) + (protocol_config, protocol_names) }; net_config.add_request_response_protocol(state_request_protocol_config); - let (warp_sync_protocol_config, warp_sync_protocol_name) = match warp_sync_config.as_ref() { + let (warp_sync_protocol_config, warp_sync_protocol_names) = match warp_sync_config.as_ref() { Some(WarpSyncConfig::WithProvider(warp_with_provider)) => { // Allow both outgoing and incoming requests. let (handler, protocol_config) = WarpSyncRequestHandler::new::<_, Net>( @@ -1359,10 +1359,10 @@ where fork_id, warp_with_provider.clone(), ); - let config_name = protocol_config.protocol_name().clone(); + let protocol_names = protocol_config.protocol_names(); spawn_handle.spawn("warp-sync-request-handler", Some("networking"), handler.run()); - (Some(protocol_config), Some(config_name)) + (Some(protocol_config), Some(protocol_names)) }, _ => (None, None), }; @@ -1375,13 +1375,13 @@ where max_parallel_downloads: net_config.network_config.max_parallel_downloads, max_blocks_per_request: net_config.network_config.max_blocks_per_request, metrics_registry: metrics_registry.cloned(), - state_request_protocol_name, + state_request_protocol_names, block_downloader, }; Ok(Box::new(PolkadotSyncingStrategy::new( syncing_config, client, warp_sync_config, - warp_sync_protocol_name, + warp_sync_protocol_names, )?)) }