Move transactions protocol to its own crate (#12264)

* Move transaction protocol to its own crate

* Update Cargo.lock

* Fix binaries

* Update client/network/transactions/src/lib.rs

Co-authored-by: Dmitry Markin <dmitry@markin.tech>

* Update client/service/src/builder.rs

Co-authored-by: Bastian Köcher <info@kchr.de>

* Apply review comments

* Revert one change and apply cargo-fmt

* Remove Transaction from Message

* Add array-bytes

* trigger CI

* Add comment about codec index

Co-authored-by: Dmitry Markin <dmitry@markin.tech>
Co-authored-by: Bastian Köcher <info@kchr.de>
This commit is contained in:
Aaro Altonen
2022-09-26 15:10:09 +03:00
committed by GitHub
parent ea377d0b17
commit 4c19c13d05
32 changed files with 466 additions and 471 deletions
+24
View File
@@ -468,6 +468,7 @@ dependencies = [
"sc-finality-grandpa", "sc-finality-grandpa",
"sc-keystore", "sc-keystore",
"sc-network", "sc-network",
"sc-network-common",
"sc-network-gossip", "sc-network-gossip",
"sc-network-test", "sc-network-test",
"sc-utils", "sc-utils",
@@ -7934,6 +7935,7 @@ dependencies = [
"sc-client-db", "sc-client-db",
"sc-keystore", "sc-keystore",
"sc-network", "sc-network",
"sc-network-common",
"sc-service", "sc-service",
"sc-telemetry", "sc-telemetry",
"sc-tracing", "sc-tracing",
@@ -8547,7 +8549,9 @@ dependencies = [
"bitflags", "bitflags",
"bytes", "bytes",
"futures", "futures",
"futures-timer",
"libp2p", "libp2p",
"linked_hash_set",
"parity-scale-codec", "parity-scale-codec",
"prost-build 0.10.4", "prost-build 0.10.4",
"sc-consensus", "sc-consensus",
@@ -8558,6 +8562,7 @@ dependencies = [
"sp-consensus", "sp-consensus",
"sp-finality-grandpa", "sp-finality-grandpa",
"sp-runtime", "sp-runtime",
"substrate-prometheus-endpoint",
"thiserror", "thiserror",
] ]
@@ -8663,6 +8668,24 @@ dependencies = [
"substrate-test-runtime-client", "substrate-test-runtime-client",
] ]
[[package]]
name = "sc-network-transactions"
version = "0.10.0-dev"
dependencies = [
"array-bytes",
"futures",
"hex",
"libp2p",
"log",
"parity-scale-codec",
"pin-project",
"sc-network-common",
"sc-peerset",
"sp-consensus",
"sp-runtime",
"substrate-prometheus-endpoint",
]
[[package]] [[package]]
name = "sc-offchain" name = "sc-offchain"
version = "4.0.0-dev" version = "4.0.0-dev"
@@ -8851,6 +8874,7 @@ dependencies = [
"sc-network-common", "sc-network-common",
"sc-network-light", "sc-network-light",
"sc-network-sync", "sc-network-sync",
"sc-network-transactions",
"sc-offchain", "sc-offchain",
"sc-rpc", "sc-rpc",
"sc-rpc-server", "sc-rpc-server",
@@ -191,7 +191,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
Vec::default(), Vec::default(),
)); ));
let (network, system_rpc_tx, network_starter) = let (network, system_rpc_tx, tx_handler_controller, network_starter) =
sc_service::build_network(sc_service::BuildNetworkParams { sc_service::build_network(sc_service::BuildNetworkParams {
config: &config, config: &config,
client: client.clone(), client: client.clone(),
@@ -238,6 +238,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
rpc_builder: rpc_extensions_builder, rpc_builder: rpc_extensions_builder,
backend, backend,
system_rpc_tx, system_rpc_tx,
tx_handler_controller,
config, config,
telemetry: telemetry.as_mut(), telemetry: telemetry.as_mut(),
})?; })?;
+2 -1
View File
@@ -354,7 +354,7 @@ pub fn new_full_base(
Vec::default(), Vec::default(),
)); ));
let (network, system_rpc_tx, network_starter) = let (network, system_rpc_tx, tx_handler_controller, network_starter) =
sc_service::build_network(sc_service::BuildNetworkParams { sc_service::build_network(sc_service::BuildNetworkParams {
config: &config, config: &config,
client: client.clone(), client: client.clone(),
@@ -392,6 +392,7 @@ pub fn new_full_base(
transaction_pool: transaction_pool.clone(), transaction_pool: transaction_pool.clone(),
task_manager: &mut task_manager, task_manager: &mut task_manager,
system_rpc_tx, system_rpc_tx,
tx_handler_controller,
telemetry: telemetry.as_mut(), telemetry: telemetry.as_mut(),
})?; })?;
+1
View File
@@ -27,6 +27,7 @@ sc-consensus = { version = "0.10.0-dev", path = "../consensus/common" }
sc-finality-grandpa = { version = "0.10.0-dev", path = "../../client/finality-grandpa" } sc-finality-grandpa = { version = "0.10.0-dev", path = "../../client/finality-grandpa" }
sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sc-keystore = { version = "4.0.0-dev", path = "../keystore" }
sc-network = { version = "0.10.0-dev", path = "../network" } sc-network = { version = "0.10.0-dev", path = "../network" }
sc-network-common = { version = "0.10.0-dev", path = "../network/common" }
sc-network-gossip = { version = "0.10.0-dev", path = "../network-gossip" } sc-network-gossip = { version = "0.10.0-dev", path = "../network-gossip" }
sc-utils = { version = "4.0.0-dev", path = "../utils" } sc-utils = { version = "4.0.0-dev", path = "../utils" }
sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" }
+2 -2
View File
@@ -83,8 +83,8 @@ pub(crate) mod beefy_protocol_name {
/// For standard protocol name see [`beefy_protocol_name::standard_name`]. /// For standard protocol name see [`beefy_protocol_name::standard_name`].
pub fn beefy_peers_set_config( pub fn beefy_peers_set_config(
protocol_name: ProtocolName, protocol_name: ProtocolName,
) -> sc_network::config::NonDefaultSetConfig { ) -> sc_network_common::config::NonDefaultSetConfig {
let mut cfg = sc_network::config::NonDefaultSetConfig::new(protocol_name, 1024 * 1024); let mut cfg = sc_network_common::config::NonDefaultSetConfig::new(protocol_name, 1024 * 1024);
cfg.allow_non_reserved(25, 25); cfg.allow_non_reserved(25, 25);
cfg.add_fallback_names(beefy_protocol_name::LEGACY_NAMES.iter().map(|&n| n.into()).collect()); cfg.add_fallback_names(beefy_protocol_name::LEGACY_NAMES.iter().map(|&n| n.into()).collect());
+1
View File
@@ -34,6 +34,7 @@ sc-client-api = { version = "4.0.0-dev", path = "../api" }
sc-client-db = { version = "0.10.0-dev", default-features = false, path = "../db" } sc-client-db = { version = "0.10.0-dev", default-features = false, path = "../db" }
sc-keystore = { version = "4.0.0-dev", path = "../keystore" } sc-keystore = { version = "4.0.0-dev", path = "../keystore" }
sc-network = { version = "0.10.0-dev", path = "../network" } sc-network = { version = "0.10.0-dev", path = "../network" }
sc-network-common = { version = "0.10.0-dev", path = "../network/common" }
sc-service = { version = "0.10.0-dev", default-features = false, path = "../service" } sc-service = { version = "0.10.0-dev", default-features = false, path = "../service" }
sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" }
sc-tracing = { version = "4.0.0-dev", path = "../tracing" } sc-tracing = { version = "4.0.0-dev", path = "../tracing" }
@@ -19,11 +19,10 @@
use crate::{arg_enums::SyncMode, params::node_key_params::NodeKeyParams}; use crate::{arg_enums::SyncMode, params::node_key_params::NodeKeyParams};
use clap::Args; use clap::Args;
use sc_network::{ use sc_network::{
config::{ config::{NetworkConfiguration, NodeKeyConfig},
NetworkConfiguration, NodeKeyConfig, NonReservedPeerMode, SetConfig, TransportConfig,
},
multiaddr::Protocol, multiaddr::Protocol,
}; };
use sc_network_common::config::{NonReservedPeerMode, SetConfig, TransportConfig};
use sc_service::{ use sc_service::{
config::{Multiaddr, MultiaddrWithPeerId}, config::{Multiaddr, MultiaddrWithPeerId},
ChainSpec, ChainType, ChainSpec, ChainType,
+4 -4
View File
@@ -688,18 +688,18 @@ pub struct GrandpaParams<Block: BlockT, C, N, SC, VR> {
/// For standard protocol name see [`crate::protocol_standard_name`]. /// For standard protocol name see [`crate::protocol_standard_name`].
pub fn grandpa_peers_set_config( pub fn grandpa_peers_set_config(
protocol_name: ProtocolName, protocol_name: ProtocolName,
) -> sc_network::config::NonDefaultSetConfig { ) -> sc_network_common::config::NonDefaultSetConfig {
use communication::grandpa_protocol_name; use communication::grandpa_protocol_name;
sc_network::config::NonDefaultSetConfig { sc_network_common::config::NonDefaultSetConfig {
notifications_protocol: protocol_name, notifications_protocol: protocol_name,
fallback_names: grandpa_protocol_name::LEGACY_NAMES.iter().map(|&n| n.into()).collect(), fallback_names: grandpa_protocol_name::LEGACY_NAMES.iter().map(|&n| n.into()).collect(),
// Notifications reach ~256kiB in size at the time of writing on Kusama and Polkadot. // Notifications reach ~256kiB in size at the time of writing on Kusama and Polkadot.
max_notification_size: 1024 * 1024, max_notification_size: 1024 * 1024,
set_config: sc_network::config::SetConfig { set_config: sc_network_common::config::SetConfig {
in_peers: 0, in_peers: 0,
out_peers: 0, out_peers: 0,
reserved_nodes: Vec::new(), reserved_nodes: Vec::new(),
non_reserved_mode: sc_network::config::NonReservedPeerMode::Deny, non_reserved_mode: sc_network_common::config::NonReservedPeerMode::Deny,
}, },
} }
} }
@@ -24,7 +24,10 @@ codec = { package = "parity-scale-codec", version = "3.0.0", features = [
"derive", "derive",
] } ] }
futures = "0.3.21" futures = "0.3.21"
futures-timer = "3.0.2"
libp2p = "0.46.1" libp2p = "0.46.1"
linked_hash_set = "0.1.3"
prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../../utils/prometheus" }
smallvec = "1.8.0" smallvec = "1.8.0"
sc-consensus = { version = "0.10.0-dev", path = "../../consensus/common" } sc-consensus = { version = "0.10.0-dev", path = "../../consensus/common" }
sc-peerset = { version = "4.0.0-dev", path = "../../peerset" } sc-peerset = { version = "4.0.0-dev", path = "../../peerset" }
@@ -18,6 +18,8 @@
//! Configuration of the networking layer. //! Configuration of the networking layer.
use crate::protocol;
use libp2p::{multiaddr, Multiaddr, PeerId}; use libp2p::{multiaddr, Multiaddr, PeerId};
use std::{fmt, str, str::FromStr}; use std::{fmt, str, str::FromStr};
@@ -171,3 +173,129 @@ impl From<multiaddr::Error> for ParseErr {
Self::MultiaddrParse(err) Self::MultiaddrParse(err)
} }
} }
/// Configuration for a set of nodes.
#[derive(Clone, Debug)]
pub struct SetConfig {
/// Maximum allowed number of incoming substreams related to this set.
pub in_peers: u32,
/// Number of outgoing substreams related to this set that we're trying to maintain.
pub out_peers: u32,
/// List of reserved node addresses.
pub reserved_nodes: Vec<MultiaddrWithPeerId>,
/// Whether nodes that aren't in [`SetConfig::reserved_nodes`] are accepted or automatically
/// refused.
pub non_reserved_mode: NonReservedPeerMode,
}
impl Default for SetConfig {
fn default() -> Self {
Self {
in_peers: 25,
out_peers: 75,
reserved_nodes: Vec::new(),
non_reserved_mode: NonReservedPeerMode::Accept,
}
}
}
/// Extension to [`SetConfig`] for sets that aren't the default set.
///
/// > **Note**: As new fields might be added in the future, please consider using the `new` method
/// > and modifiers instead of creating this struct manually.
#[derive(Clone, Debug)]
pub struct NonDefaultSetConfig {
/// Name of the notifications protocols of this set. A substream on this set will be
/// considered established once this protocol is open.
///
/// > **Note**: This field isn't present for the default set, as this is handled internally
/// > by the networking code.
pub notifications_protocol: protocol::ProtocolName,
/// If the remote reports that it doesn't support the protocol indicated in the
/// `notifications_protocol` field, then each of these fallback names will be tried one by
/// one.
///
/// If a fallback is used, it will be reported in
/// `sc_network::protocol::event::Event::NotificationStreamOpened::negotiated_fallback`
pub fallback_names: Vec<protocol::ProtocolName>,
/// Maximum allowed size of single notifications.
pub max_notification_size: u64,
/// Base configuration.
pub set_config: SetConfig,
}
impl NonDefaultSetConfig {
/// Creates a new [`NonDefaultSetConfig`]. Zero slots and accepts only reserved nodes.
pub fn new(notifications_protocol: protocol::ProtocolName, max_notification_size: u64) -> Self {
Self {
notifications_protocol,
max_notification_size,
fallback_names: Vec::new(),
set_config: SetConfig {
in_peers: 0,
out_peers: 0,
reserved_nodes: Vec::new(),
non_reserved_mode: NonReservedPeerMode::Deny,
},
}
}
/// Modifies the configuration to allow non-reserved nodes.
pub fn allow_non_reserved(&mut self, in_peers: u32, out_peers: u32) {
self.set_config.in_peers = in_peers;
self.set_config.out_peers = out_peers;
self.set_config.non_reserved_mode = NonReservedPeerMode::Accept;
}
/// Add a node to the list of reserved nodes.
pub fn add_reserved(&mut self, peer: MultiaddrWithPeerId) {
self.set_config.reserved_nodes.push(peer);
}
/// Add a list of protocol names used for backward compatibility.
///
/// See the explanations in [`NonDefaultSetConfig::fallback_names`].
pub fn add_fallback_names(&mut self, fallback_names: Vec<protocol::ProtocolName>) {
self.fallback_names.extend(fallback_names);
}
}
/// Configuration for the transport layer.
#[derive(Clone, Debug)]
pub enum TransportConfig {
/// Normal transport mode.
Normal {
/// If true, the network will use mDNS to discover other libp2p nodes on the local network
/// and connect to them if they support the same chain.
enable_mdns: bool,
/// If true, allow connecting to private IPv4 addresses (as defined in
/// [RFC1918](https://tools.ietf.org/html/rfc1918)). Irrelevant for addresses that have
/// been passed in `::sc_network::config::NetworkConfiguration::boot_nodes`.
allow_private_ipv4: bool,
},
/// Only allow connections within the same process.
/// Only addresses of the form `/memory/...` will be supported.
MemoryOnly,
}
/// The policy for connections to non-reserved peers.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum NonReservedPeerMode {
/// Accept them. This is the default.
Accept,
/// Deny them.
Deny,
}
impl NonReservedPeerMode {
/// Attempt to parse the peer mode from a string.
pub fn parse(s: &str) -> Option<Self> {
match s {
"accept" => Some(Self::Accept),
"deny" => Some(Self::Deny),
_ => None,
}
}
}
@@ -18,9 +18,8 @@
//! Substrate network possible errors. //! Substrate network possible errors.
use crate::config::TransportConfig; use crate::{config::TransportConfig, protocol::ProtocolName};
use libp2p::{Multiaddr, PeerId}; use libp2p::{Multiaddr, PeerId};
use sc_network_common::protocol::ProtocolName;
use std::fmt; use std::fmt;
@@ -19,8 +19,16 @@
//! Common data structures of the networking layer. //! Common data structures of the networking layer.
pub mod config; pub mod config;
pub mod error;
pub mod message; pub mod message;
pub mod protocol; pub mod protocol;
pub mod request_responses; pub mod request_responses;
pub mod service; pub mod service;
pub mod sync; pub mod sync;
pub mod utils;
/// Minimum Requirements for a Hash within Networking
pub trait ExHashT: std::hash::Hash + Eq + std::fmt::Debug + Clone + Send + Sync + 'static {}
impl<T> ExHashT for T where T: std::hash::Hash + Eq + std::fmt::Debug + Clone + Send + Sync + 'static
{}
@@ -604,35 +604,6 @@ where
} }
} }
/// Provides ability to propagate transactions over the network.
pub trait NetworkTransaction<H> {
/// You may call this when new transactions are imported by the transaction pool.
///
/// All transactions will be fetched from the `TransactionPool` that was passed at
/// initialization as part of the configuration and propagated to peers.
fn trigger_repropagate(&self);
/// You must call when new transaction is imported by the transaction pool.
///
/// This transaction will be fetched from the `TransactionPool` that was passed at
/// initialization as part of the configuration and propagated to peers.
fn propagate_transaction(&self, hash: H);
}
impl<T, H> NetworkTransaction<H> for Arc<T>
where
T: ?Sized,
T: NetworkTransaction<H>,
{
fn trigger_repropagate(&self) {
T::trigger_repropagate(self)
}
fn propagate_transaction(&self, hash: H) {
T::propagate_transaction(self, hash)
}
}
/// Provides ability to announce blocks to the network. /// Provides ability to announce blocks to the network.
pub trait NetworkBlock<BlockHash, BlockNumber> { pub trait NetworkBlock<BlockHash, BlockNumber> {
/// Make sure an important block is propagated to peers. /// Make sure an important block is propagated to peers.
+6 -203
View File
@@ -27,24 +27,24 @@ pub use sc_network_common::{
IncomingRequest, OutgoingResponse, ProtocolConfig as RequestResponseConfig, IncomingRequest, OutgoingResponse, ProtocolConfig as RequestResponseConfig,
}, },
sync::warp::WarpSyncProvider, sync::warp::WarpSyncProvider,
ExHashT,
}; };
pub use libp2p::{build_multiaddr, core::PublicKey, identity}; pub use libp2p::{build_multiaddr, core::PublicKey, identity};
use crate::ExHashT;
use core::{fmt, iter}; use core::{fmt, iter};
use futures::future;
use libp2p::{ use libp2p::{
identity::{ed25519, Keypair}, identity::{ed25519, Keypair},
multiaddr, Multiaddr, multiaddr, Multiaddr,
}; };
use prometheus_endpoint::Registry; use prometheus_endpoint::Registry;
use sc_consensus::ImportQueue; use sc_consensus::ImportQueue;
use sc_network_common::{config::MultiaddrWithPeerId, protocol::ProtocolName, sync::ChainSync}; use sc_network_common::{
config::{MultiaddrWithPeerId, NonDefaultSetConfig, SetConfig, TransportConfig},
sync::ChainSync,
};
use sp_runtime::traits::Block as BlockT; use sp_runtime::traits::Block as BlockT;
use std::{ use std::{
collections::HashMap,
error::Error, error::Error,
fs, fs,
future::Future, future::Future,
@@ -52,16 +52,14 @@ use std::{
net::Ipv4Addr, net::Ipv4Addr,
path::{Path, PathBuf}, path::{Path, PathBuf},
pin::Pin, pin::Pin,
str,
sync::Arc, sync::Arc,
}; };
use zeroize::Zeroize; use zeroize::Zeroize;
/// Network initialization parameters. /// Network initialization parameters.
pub struct Params<B, H, Client> pub struct Params<B, Client>
where where
B: BlockT + 'static, B: BlockT + 'static,
H: ExHashT,
{ {
/// Assigned role for our node (full, light, ...). /// Assigned role for our node (full, light, ...).
pub role: Role, pub role: Role,
@@ -70,21 +68,12 @@ where
/// default. /// default.
pub executor: Option<Box<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send>>, pub executor: Option<Box<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send>>,
/// How to spawn the background task dedicated to the transactions handler.
pub transactions_handler_executor: Box<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send>,
/// Network layer configuration. /// Network layer configuration.
pub network_config: NetworkConfiguration, pub network_config: NetworkConfiguration,
/// Client that contains the blockchain. /// Client that contains the blockchain.
pub chain: Arc<Client>, pub chain: Arc<Client>,
/// Pool of transactions.
///
/// The network worker will fetch transactions from this object in order to propagate them on
/// the network.
pub transaction_pool: Arc<dyn TransactionPool<H, B>>,
/// Legacy name of the protocol to use on the wire. Should be different for each chain. /// Legacy name of the protocol to use on the wire. Should be different for each chain.
pub protocol_id: ProtocolId, pub protocol_id: ProtocolId,
@@ -166,66 +155,6 @@ impl fmt::Display for Role {
} }
} }
/// Result of the transaction import.
#[derive(Clone, Copy, Debug)]
pub enum TransactionImport {
/// Transaction is good but already known by the transaction pool.
KnownGood,
/// Transaction is good and not yet known.
NewGood,
/// Transaction is invalid.
Bad,
/// Transaction import was not performed.
None,
}
/// Future resolving to transaction import result.
pub type TransactionImportFuture = Pin<Box<dyn Future<Output = TransactionImport> + Send>>;
/// Transaction pool interface
pub trait TransactionPool<H: ExHashT, B: BlockT>: Send + Sync {
/// Get transactions from the pool that are ready to be propagated.
fn transactions(&self) -> Vec<(H, B::Extrinsic)>;
/// Get hash of transaction.
fn hash_of(&self, transaction: &B::Extrinsic) -> H;
/// Import a transaction into the pool.
///
/// This will return future.
fn import(&self, transaction: B::Extrinsic) -> TransactionImportFuture;
/// Notify the pool about transactions broadcast.
fn on_broadcasted(&self, propagations: HashMap<H, Vec<String>>);
/// Get transaction by hash.
fn transaction(&self, hash: &H) -> Option<B::Extrinsic>;
}
/// Dummy implementation of the [`TransactionPool`] trait for a transaction pool that is always
/// empty and discards all incoming transactions.
///
/// Requires the "hash" type to implement the `Default` trait.
///
/// Useful for testing purposes.
pub struct EmptyTransactionPool;
impl<H: ExHashT + Default, B: BlockT> TransactionPool<H, B> for EmptyTransactionPool {
fn transactions(&self) -> Vec<(H, B::Extrinsic)> {
Vec::new()
}
fn hash_of(&self, _transaction: &B::Extrinsic) -> H {
Default::default()
}
fn import(&self, _transaction: B::Extrinsic) -> TransactionImportFuture {
Box::pin(future::ready(TransactionImport::KnownGood))
}
fn on_broadcasted(&self, _: HashMap<H, Vec<String>>) {}
fn transaction(&self, _h: &H) -> Option<B::Extrinsic> {
None
}
}
/// Sync operation mode. /// Sync operation mode.
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SyncMode { pub enum SyncMode {
@@ -394,132 +323,6 @@ impl NetworkConfiguration {
} }
} }
/// Configuration for a set of nodes.
#[derive(Clone, Debug)]
pub struct SetConfig {
/// Maximum allowed number of incoming substreams related to this set.
pub in_peers: u32,
/// Number of outgoing substreams related to this set that we're trying to maintain.
pub out_peers: u32,
/// List of reserved node addresses.
pub reserved_nodes: Vec<MultiaddrWithPeerId>,
/// Whether nodes that aren't in [`SetConfig::reserved_nodes`] are accepted or automatically
/// refused.
pub non_reserved_mode: NonReservedPeerMode,
}
impl Default for SetConfig {
fn default() -> Self {
Self {
in_peers: 25,
out_peers: 75,
reserved_nodes: Vec::new(),
non_reserved_mode: NonReservedPeerMode::Accept,
}
}
}
/// Extension to [`SetConfig`] for sets that aren't the default set.
///
/// > **Note**: As new fields might be added in the future, please consider using the `new` method
/// > and modifiers instead of creating this struct manually.
#[derive(Clone, Debug)]
pub struct NonDefaultSetConfig {
/// Name of the notifications protocols of this set. A substream on this set will be
/// considered established once this protocol is open.
///
/// > **Note**: This field isn't present for the default set, as this is handled internally
/// > by the networking code.
pub notifications_protocol: ProtocolName,
/// If the remote reports that it doesn't support the protocol indicated in the
/// `notifications_protocol` field, then each of these fallback names will be tried one by
/// one.
///
/// If a fallback is used, it will be reported in
/// [`crate::Event::NotificationStreamOpened::negotiated_fallback`].
pub fallback_names: Vec<ProtocolName>,
/// Maximum allowed size of single notifications.
pub max_notification_size: u64,
/// Base configuration.
pub set_config: SetConfig,
}
impl NonDefaultSetConfig {
/// Creates a new [`NonDefaultSetConfig`]. Zero slots and accepts only reserved nodes.
pub fn new(notifications_protocol: ProtocolName, max_notification_size: u64) -> Self {
Self {
notifications_protocol,
max_notification_size,
fallback_names: Vec::new(),
set_config: SetConfig {
in_peers: 0,
out_peers: 0,
reserved_nodes: Vec::new(),
non_reserved_mode: NonReservedPeerMode::Deny,
},
}
}
/// Modifies the configuration to allow non-reserved nodes.
pub fn allow_non_reserved(&mut self, in_peers: u32, out_peers: u32) {
self.set_config.in_peers = in_peers;
self.set_config.out_peers = out_peers;
self.set_config.non_reserved_mode = NonReservedPeerMode::Accept;
}
/// Add a node to the list of reserved nodes.
pub fn add_reserved(&mut self, peer: MultiaddrWithPeerId) {
self.set_config.reserved_nodes.push(peer);
}
/// Add a list of protocol names used for backward compatibility.
///
/// See the explanations in [`NonDefaultSetConfig::fallback_names`].
pub fn add_fallback_names(&mut self, fallback_names: Vec<ProtocolName>) {
self.fallback_names.extend(fallback_names);
}
}
/// Configuration for the transport layer.
#[derive(Clone, Debug)]
pub enum TransportConfig {
/// Normal transport mode.
Normal {
/// If true, the network will use mDNS to discover other libp2p nodes on the local network
/// and connect to them if they support the same chain.
enable_mdns: bool,
/// If true, allow connecting to private IPv4 addresses (as defined in
/// [RFC1918](https://tools.ietf.org/html/rfc1918)). Irrelevant for addresses that have
/// been passed in [`NetworkConfiguration::boot_nodes`].
allow_private_ipv4: bool,
},
/// Only allow connections within the same process.
/// Only addresses of the form `/memory/...` will be supported.
MemoryOnly,
}
/// The policy for connections to non-reserved peers.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum NonReservedPeerMode {
/// Accept them. This is the default.
Accept,
/// Deny them.
Deny,
}
impl NonReservedPeerMode {
/// Attempt to parse the peer mode from a string.
pub fn parse(s: &str) -> Option<Self> {
match s {
"accept" => Some(Self::Accept),
"deny" => Some(Self::Deny),
_ => None,
}
}
}
/// The configuration of a node's secret key, describing the type of key /// The configuration of a node's secret key, describing the type of key
/// and how it is obtained. A node's identity keypair is the result of /// and how it is obtained. A node's identity keypair is the result of
/// the evaluation of the node key configuration. /// the evaluation of the node key configuration.
+1 -2
View File
@@ -46,7 +46,6 @@
//! active mechanism that asks nodes for the addresses they are listening on. Whenever we learn //! active mechanism that asks nodes for the addresses they are listening on. Whenever we learn
//! of a node's address, you must call `add_self_reported_address`. //! of a node's address, you must call `add_self_reported_address`.
use crate::utils::LruHashSet;
use futures::prelude::*; use futures::prelude::*;
use futures_timer::Delay; use futures_timer::Delay;
use ip_network::IpNetwork; use ip_network::IpNetwork;
@@ -72,7 +71,7 @@ use libp2p::{
}, },
}; };
use log::{debug, error, info, trace, warn}; use log::{debug, error, info, trace, warn};
use sc_network_common::config::ProtocolId; use sc_network_common::{config::ProtocolId, utils::LruHashSet};
use sp_core::hexdisplay::HexDisplay; use sp_core::hexdisplay::HexDisplay;
use std::{ use std::{
cmp, cmp,
+2 -11
View File
@@ -251,12 +251,9 @@ mod protocol;
mod request_responses; mod request_responses;
mod service; mod service;
mod transport; mod transport;
mod utils;
pub mod config; pub mod config;
pub mod error;
pub mod network_state; pub mod network_state;
pub mod transactions;
#[doc(inline)] #[doc(inline)]
pub use libp2p::{multiaddr, Multiaddr, PeerId}; pub use libp2p::{multiaddr, Multiaddr, PeerId};
@@ -269,8 +266,8 @@ pub use sc_network_common::{
request_responses::{IfDisconnected, RequestFailure}, request_responses::{IfDisconnected, RequestFailure},
service::{ service::{
KademliaKey, NetworkBlock, NetworkDHTProvider, NetworkRequest, NetworkSigner, KademliaKey, NetworkBlock, NetworkDHTProvider, NetworkRequest, NetworkSigner,
NetworkStateInfo, NetworkStatus, NetworkStatusProvider, NetworkSyncForkRequest, NetworkStateInfo, NetworkStatus, NetworkStatusProvider, NetworkSyncForkRequest, Signature,
NetworkTransaction, Signature, SigningError, SigningError,
}, },
sync::{ sync::{
warp::{WarpSyncPhase, WarpSyncProgress}, warp::{WarpSyncPhase, WarpSyncProgress},
@@ -295,9 +292,3 @@ const MAX_CONNECTIONS_PER_PEER: usize = 2;
/// The maximum number of concurrent established connections that were incoming. /// The maximum number of concurrent established connections that were incoming.
const MAX_CONNECTIONS_ESTABLISHED_INCOMING: u32 = 10_000; const MAX_CONNECTIONS_ESTABLISHED_INCOMING: u32 = 10_000;
/// Minimum Requirements for a Hash within Networking
pub trait ExHashT: std::hash::Hash + Eq + std::fmt::Debug + Clone + Send + Sync + 'static {}
impl<T> ExHashT for T where T: std::hash::Hash + Eq + std::fmt::Debug + Clone + Send + Sync + 'static
{}
+1 -1
View File
@@ -16,7 +16,6 @@
// 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 crate::utils::interval;
use fnv::FnvHashMap; use fnv::FnvHashMap;
use futures::prelude::*; use futures::prelude::*;
use libp2p::{ use libp2p::{
@@ -33,6 +32,7 @@ use libp2p::{
Multiaddr, Multiaddr,
}; };
use log::{debug, error, trace}; use log::{debug, error, trace};
use sc_network_common::utils::interval;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::{ use std::{
collections::hash_map::Entry, collections::hash_map::Entry,
+6 -7
View File
@@ -16,10 +16,7 @@
// 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 crate::{ use crate::config;
config, error,
utils::{interval, LruHashSet},
};
use bytes::Bytes; use bytes::Bytes;
use codec::{Decode, DecodeAll, Encode}; use codec::{Decode, DecodeAll, Encode};
@@ -45,7 +42,8 @@ use sc_consensus::import_queue::{
BlockImportError, BlockImportStatus, IncomingBlock, RuntimeOrigin, BlockImportError, BlockImportStatus, IncomingBlock, RuntimeOrigin,
}; };
use sc_network_common::{ use sc_network_common::{
config::ProtocolId, config::{NonReservedPeerMode, ProtocolId},
error,
protocol::ProtocolName, protocol::ProtocolName,
request_responses::RequestFailure, request_responses::RequestFailure,
sync::{ sync::{
@@ -57,6 +55,7 @@ use sc_network_common::{
OpaqueBlockResponse, OpaqueStateRequest, OpaqueStateResponse, PollBlockAnnounceValidation, OpaqueBlockResponse, OpaqueStateRequest, OpaqueStateResponse, PollBlockAnnounceValidation,
SyncStatus, SyncStatus,
}, },
utils::{interval, LruHashSet},
}; };
use sp_arithmetic::traits::SaturatedConversion; use sp_arithmetic::traits::SaturatedConversion;
use sp_consensus::BlockOrigin; use sp_consensus::BlockOrigin;
@@ -341,7 +340,7 @@ where
bootnodes, bootnodes,
reserved_nodes: default_sets_reserved.clone(), reserved_nodes: default_sets_reserved.clone(),
reserved_only: network_config.default_peers_set.non_reserved_mode == reserved_only: network_config.default_peers_set.non_reserved_mode ==
config::NonReservedPeerMode::Deny, NonReservedPeerMode::Deny,
}); });
for set_cfg in &network_config.extra_sets { for set_cfg in &network_config.extra_sets {
@@ -352,7 +351,7 @@ where
} }
let reserved_only = let reserved_only =
set_cfg.set_config.non_reserved_mode == config::NonReservedPeerMode::Deny; set_cfg.set_config.non_reserved_mode == NonReservedPeerMode::Deny;
sets.push(sc_peerset::SetConfig { sets.push(sc_peerset::SetConfig {
in_peers: set_cfg.set_config.in_peers, in_peers: set_cfg.set_config.in_peers,
@@ -36,9 +36,6 @@ pub type Message<B> = generic::Message<
<B as BlockT>::Extrinsic, <B as BlockT>::Extrinsic,
>; >;
/// A set of transactions.
pub type Transactions<E> = Vec<E>;
/// Remote call response. /// Remote call response.
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct RemoteCallResponse { pub struct RemoteCallResponse {
@@ -59,7 +56,7 @@ pub struct RemoteReadResponse {
/// Generic types. /// Generic types.
pub mod generic { pub mod generic {
use super::{RemoteCallResponse, RemoteReadResponse, Transactions}; use super::{RemoteCallResponse, RemoteReadResponse};
use bitflags::bitflags; use bitflags::bitflags;
use codec::{Decode, Encode, Input, Output}; use codec::{Decode, Encode, Input, Output};
use sc_client_api::StorageProof; use sc_client_api::StorageProof;
@@ -146,9 +143,10 @@ pub mod generic {
BlockResponse(BlockResponse<Header, Hash, Extrinsic>), BlockResponse(BlockResponse<Header, Hash, Extrinsic>),
/// Block announce. /// Block announce.
BlockAnnounce(BlockAnnounce<Header>), BlockAnnounce(BlockAnnounce<Header>),
/// Transactions.
Transactions(Transactions<Extrinsic>),
/// Consensus protocol message. /// Consensus protocol message.
// NOTE: index is incremented by 1 due to transaction-related
// message that was removed
#[codec(index = 6)]
Consensus(ConsensusMessage), Consensus(ConsensusMessage),
/// Remote method call request. /// Remote method call request.
RemoteCallRequest(RemoteCallRequest<Hash>), RemoteCallRequest(RemoteCallRequest<Hash>),
+16 -61
View File
@@ -29,9 +29,8 @@
use crate::{ use crate::{
behaviour::{self, Behaviour, BehaviourOut}, behaviour::{self, Behaviour, BehaviourOut},
config::{Params, TransportConfig}, config::Params,
discovery::DiscoveryConfig, discovery::DiscoveryConfig,
error::Error,
network_state::{ network_state::{
NetworkState, NotConnectedPeer as NetworkStateNotConnectedPeer, Peer as NetworkStatePeer, NetworkState, NotConnectedPeer as NetworkStateNotConnectedPeer, Peer as NetworkStatePeer,
}, },
@@ -39,7 +38,7 @@ use crate::{
self, message::generic::Roles, NotificationsSink, NotifsHandlerError, PeerInfo, Protocol, self, message::generic::Roles, NotificationsSink, NotifsHandlerError, PeerInfo, Protocol,
Ready, Ready,
}, },
transactions, transport, ExHashT, ReputationChange, transport, ReputationChange,
}; };
use codec::Encode as _; use codec::Encode as _;
@@ -60,7 +59,8 @@ use metrics::{Histogram, HistogramVec, MetricSources, Metrics};
use parking_lot::Mutex; use parking_lot::Mutex;
use sc_consensus::{BlockImportError, BlockImportStatus, ImportQueue, Link}; use sc_consensus::{BlockImportError, BlockImportStatus, ImportQueue, Link};
use sc_network_common::{ use sc_network_common::{
config::MultiaddrWithPeerId, config::{MultiaddrWithPeerId, TransportConfig},
error::Error,
protocol::{ protocol::{
event::{DhtEvent, Event}, event::{DhtEvent, Event},
ProtocolName, ProtocolName,
@@ -73,6 +73,7 @@ use sc_network_common::{
NotificationSenderReady as NotificationSenderReadyT, Signature, SigningError, NotificationSenderReady as NotificationSenderReadyT, Signature, SigningError,
}, },
sync::{SyncState, SyncStatus}, sync::{SyncState, SyncStatus},
ExHashT,
}; };
use sc_peerset::PeersetHandle; use sc_peerset::PeersetHandle;
use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
@@ -101,7 +102,7 @@ mod out_events;
mod tests; mod tests;
pub use libp2p::identity::{error::DecodingError, Keypair, PublicKey}; pub use libp2p::identity::{error::DecodingError, Keypair, PublicKey};
use sc_network_common::service::{NetworkBlock, NetworkRequest, NetworkTransaction}; use sc_network_common::service::{NetworkBlock, NetworkRequest};
/// Substrate network service. Handles network IO and manages connectivity. /// Substrate network service. Handles network IO and manages connectivity.
pub struct NetworkService<B: BlockT + 'static, H: ExHashT> { pub struct NetworkService<B: BlockT + 'static, H: ExHashT> {
@@ -121,7 +122,7 @@ pub struct NetworkService<B: BlockT + 'static, H: ExHashT> {
/// nodes it should be connected to or not. /// nodes it should be connected to or not.
peerset: PeersetHandle, peerset: PeersetHandle,
/// Channel that sends messages to the actual worker. /// Channel that sends messages to the actual worker.
to_worker: TracingUnboundedSender<ServiceToWorkerMsg<B, H>>, to_worker: TracingUnboundedSender<ServiceToWorkerMsg<B>>,
/// 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. Updated by the [`NetworkWorker`]. /// that peer. Updated by the [`NetworkWorker`].
peers_notifications_sinks: Arc<Mutex<HashMap<(PeerId, ProtocolName), NotificationsSink>>>, peers_notifications_sinks: Arc<Mutex<HashMap<(PeerId, ProtocolName), NotificationsSink>>>,
@@ -144,7 +145,7 @@ where
/// Returns a `NetworkWorker` that implements `Future` and must be regularly polled in order /// Returns a `NetworkWorker` that implements `Future` and must be regularly polled in order
/// for the network processing to advance. From it, you can extract a `NetworkService` using /// for the network processing to advance. From it, you can extract a `NetworkService` using
/// `worker.service()`. The `NetworkService` can be shared through the codebase. /// `worker.service()`. The `NetworkService` can be shared through the codebase.
pub fn new(mut params: Params<B, H, Client>) -> Result<Self, Error> { pub fn new(mut params: Params<B, Client>) -> Result<Self, Error> {
// Private and public keys configuration. // Private and public keys configuration.
let local_identity = params.network_config.node_key.clone().into_keypair()?; let local_identity = params.network_config.node_key.clone().into_keypair()?;
let local_public = local_identity.public(); let local_public = local_identity.public();
@@ -215,21 +216,6 @@ where
fs::create_dir_all(path)?; fs::create_dir_all(path)?;
} }
let transactions_handler_proto = transactions::TransactionsHandlerPrototype::new(
params.protocol_id.clone(),
params
.chain
.hash(0u32.into())
.ok()
.flatten()
.expect("Genesis block exists; qed"),
params.fork_id.clone(),
);
params
.network_config
.extra_sets
.insert(0, transactions_handler_proto.set_config());
info!( info!(
target: "sub-libp2p", target: "sub-libp2p",
"🏷 Local node identity is: {}", "🏷 Local node identity is: {}",
@@ -244,11 +230,8 @@ where
params.protocol_id.clone(), params.protocol_id.clone(),
&params.fork_id, &params.fork_id,
&params.network_config, &params.network_config,
iter::once(Vec::new()) (0..params.network_config.extra_sets.len())
.chain( .map(|_| default_notif_handshake_message.clone())
(0..params.network_config.extra_sets.len() - 1)
.map(|_| default_notif_handshake_message.clone()),
)
.collect(), .collect(),
params.metrics_registry.as_ref(), params.metrics_registry.as_ref(),
params.chain_sync, params.chain_sync,
@@ -465,13 +448,6 @@ where
_marker: PhantomData, _marker: PhantomData,
}); });
let (tx_handler, tx_handler_controller) = transactions_handler_proto.build(
service.clone(),
params.transaction_pool,
params.metrics_registry.as_ref(),
)?;
(params.transactions_handler_executor)(tx_handler.run().boxed());
Ok(NetworkWorker { Ok(NetworkWorker {
external_addresses, external_addresses,
num_connected, num_connected,
@@ -482,9 +458,9 @@ where
from_service, from_service,
event_streams: out_events::OutChannels::new(params.metrics_registry.as_ref())?, event_streams: out_events::OutChannels::new(params.metrics_registry.as_ref())?,
peers_notifications_sinks, peers_notifications_sinks,
tx_handler_controller,
metrics, metrics,
boot_node_ids, boot_node_ids,
_marker: Default::default(),
}) })
} }
@@ -1149,20 +1125,6 @@ where
} }
} }
impl<B, H> NetworkTransaction<H> for NetworkService<B, H>
where
B: BlockT + 'static,
H: ExHashT,
{
fn trigger_repropagate(&self) {
let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::PropagateTransactions);
}
fn propagate_transaction(&self, hash: H) {
let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::PropagateTransaction(hash));
}
}
impl<B, H> NetworkBlock<B::Hash, NumberFor<B>> for NetworkService<B, H> impl<B, H> NetworkBlock<B::Hash, NumberFor<B>> for NetworkService<B, H>
where where
B: BlockT + 'static, B: BlockT + 'static,
@@ -1249,9 +1211,7 @@ impl<'a> NotificationSenderReadyT for NotificationSenderReady<'a> {
/// Messages sent from the `NetworkService` to the `NetworkWorker`. /// Messages sent from the `NetworkService` to the `NetworkWorker`.
/// ///
/// Each entry corresponds to a method of `NetworkService`. /// Each entry corresponds to a method of `NetworkService`.
enum ServiceToWorkerMsg<B: BlockT, H: ExHashT> { enum ServiceToWorkerMsg<B: BlockT> {
PropagateTransaction(H),
PropagateTransactions,
RequestJustification(B::Hash, NumberFor<B>), RequestJustification(B::Hash, NumberFor<B>),
ClearJustificationRequests, ClearJustificationRequests,
AnnounceBlock(B::Hash, Option<Vec<u8>>), AnnounceBlock(B::Hash, Option<Vec<u8>>),
@@ -1309,7 +1269,7 @@ where
/// The import queue that was passed at initialization. /// The import queue that was passed at initialization.
import_queue: Box<dyn ImportQueue<B>>, import_queue: Box<dyn ImportQueue<B>>,
/// Messages from the [`NetworkService`] that must be processed. /// Messages from the [`NetworkService`] that must be processed.
from_service: TracingUnboundedReceiver<ServiceToWorkerMsg<B, H>>, from_service: TracingUnboundedReceiver<ServiceToWorkerMsg<B>>,
/// Senders for events that happen on the network. /// Senders for events that happen on the network.
event_streams: out_events::OutChannels, event_streams: out_events::OutChannels,
/// Prometheus network metrics. /// Prometheus network metrics.
@@ -1319,8 +1279,9 @@ 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>>>,
/// Controller for the handler of incoming and outgoing transactions. /// Marker to pin the `H` generic. Serves no purpose except to not break backwards
tx_handler_controller: transactions::TransactionsHandlerController<H>, /// compatibility.
_marker: PhantomData<H>,
} }
impl<B, H, Client> Future for NetworkWorker<B, H, Client> impl<B, H, Client> Future for NetworkWorker<B, H, Client>
@@ -1376,10 +1337,6 @@ where
.behaviour_mut() .behaviour_mut()
.user_protocol_mut() .user_protocol_mut()
.clear_justification_requests(), .clear_justification_requests(),
ServiceToWorkerMsg::PropagateTransaction(hash) =>
this.tx_handler_controller.propagate_transaction(hash),
ServiceToWorkerMsg::PropagateTransactions =>
this.tx_handler_controller.propagate_transactions(),
ServiceToWorkerMsg::GetValue(key) => ServiceToWorkerMsg::GetValue(key) =>
this.network_service.behaviour_mut().get_value(key), this.network_service.behaviour_mut().get_value(key),
ServiceToWorkerMsg::PutValue(key, value) => ServiceToWorkerMsg::PutValue(key, value) =>
@@ -1922,8 +1879,6 @@ where
SyncState::Downloading => true, SyncState::Downloading => true,
}; };
this.tx_handler_controller.set_gossip_enabled(!is_major_syncing);
this.is_major_syncing.store(is_major_syncing, Ordering::Relaxed); this.is_major_syncing.store(is_major_syncing, Ordering::Relaxed);
if let Some(metrics) = this.metrics.as_ref() { if let Some(metrics) = this.metrics.as_ref() {
+23 -33
View File
@@ -21,7 +21,7 @@ use crate::{config, NetworkService, NetworkWorker};
use futures::prelude::*; use futures::prelude::*;
use libp2p::PeerId; use libp2p::PeerId;
use sc_network_common::{ use sc_network_common::{
config::{MultiaddrWithPeerId, ProtocolId}, config::{MultiaddrWithPeerId, NonDefaultSetConfig, ProtocolId, SetConfig, TransportConfig},
protocol::event::Event, protocol::event::Event,
service::{NetworkEventStream, NetworkNotification, NetworkPeers, NetworkStateInfo}, service::{NetworkEventStream, NetworkNotification, NetworkPeers, NetworkStateInfo},
}; };
@@ -135,12 +135,8 @@ fn build_test_full_node(
let worker = NetworkWorker::new(config::Params { let worker = NetworkWorker::new(config::Params {
role: config::Role::Full, role: config::Role::Full,
executor: None, executor: None,
transactions_handler_executor: Box::new(|task| {
async_std::task::spawn(task);
}),
network_config, network_config,
chain: client.clone(), chain: client.clone(),
transaction_pool: Arc::new(config::EmptyTransactionPool),
protocol_id, protocol_id,
fork_id, fork_id,
import_queue, import_queue,
@@ -178,23 +174,23 @@ fn build_nodes_one_proto() -> (
let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())]; let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())];
let (node1, events_stream1) = build_test_full_node(config::NetworkConfiguration { let (node1, events_stream1) = build_test_full_node(config::NetworkConfiguration {
extra_sets: vec![config::NonDefaultSetConfig { extra_sets: vec![NonDefaultSetConfig {
notifications_protocol: PROTOCOL_NAME.into(), notifications_protocol: PROTOCOL_NAME.into(),
fallback_names: Vec::new(), fallback_names: Vec::new(),
max_notification_size: 1024 * 1024, max_notification_size: 1024 * 1024,
set_config: Default::default(), set_config: Default::default(),
}], }],
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
transport: config::TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
..config::NetworkConfiguration::new_local() ..config::NetworkConfiguration::new_local()
}); });
let (node2, events_stream2) = build_test_full_node(config::NetworkConfiguration { let (node2, events_stream2) = build_test_full_node(config::NetworkConfiguration {
extra_sets: vec![config::NonDefaultSetConfig { extra_sets: vec![NonDefaultSetConfig {
notifications_protocol: PROTOCOL_NAME.into(), notifications_protocol: PROTOCOL_NAME.into(),
fallback_names: Vec::new(), fallback_names: Vec::new(),
max_notification_size: 1024 * 1024, max_notification_size: 1024 * 1024,
set_config: config::SetConfig { set_config: SetConfig {
reserved_nodes: vec![MultiaddrWithPeerId { reserved_nodes: vec![MultiaddrWithPeerId {
multiaddr: listen_addr, multiaddr: listen_addr,
peer_id: node1.local_peer_id(), peer_id: node1.local_peer_id(),
@@ -203,7 +199,7 @@ fn build_nodes_one_proto() -> (
}, },
}], }],
listen_addresses: vec![], listen_addresses: vec![],
transport: config::TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
..config::NetworkConfiguration::new_local() ..config::NetworkConfiguration::new_local()
}); });
@@ -368,13 +364,13 @@ fn lots_of_incoming_peers_works() {
let (main_node, _) = build_test_full_node(config::NetworkConfiguration { let (main_node, _) = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
extra_sets: vec![config::NonDefaultSetConfig { extra_sets: vec![NonDefaultSetConfig {
notifications_protocol: PROTOCOL_NAME.into(), notifications_protocol: PROTOCOL_NAME.into(),
fallback_names: Vec::new(), fallback_names: Vec::new(),
max_notification_size: 1024 * 1024, max_notification_size: 1024 * 1024,
set_config: config::SetConfig { in_peers: u32::MAX, ..Default::default() }, set_config: SetConfig { in_peers: u32::MAX, ..Default::default() },
}], }],
transport: config::TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
..config::NetworkConfiguration::new_local() ..config::NetworkConfiguration::new_local()
}); });
@@ -387,11 +383,11 @@ fn lots_of_incoming_peers_works() {
for _ in 0..32 { for _ in 0..32 {
let (_dialing_node, event_stream) = build_test_full_node(config::NetworkConfiguration { let (_dialing_node, event_stream) = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![], listen_addresses: vec![],
extra_sets: vec![config::NonDefaultSetConfig { extra_sets: vec![NonDefaultSetConfig {
notifications_protocol: PROTOCOL_NAME.into(), notifications_protocol: PROTOCOL_NAME.into(),
fallback_names: Vec::new(), fallback_names: Vec::new(),
max_notification_size: 1024 * 1024, max_notification_size: 1024 * 1024,
set_config: config::SetConfig { set_config: SetConfig {
reserved_nodes: vec![MultiaddrWithPeerId { reserved_nodes: vec![MultiaddrWithPeerId {
multiaddr: listen_addr.clone(), multiaddr: listen_addr.clone(),
peer_id: main_node_peer_id, peer_id: main_node_peer_id,
@@ -399,7 +395,7 @@ fn lots_of_incoming_peers_works() {
..Default::default() ..Default::default()
}, },
}], }],
transport: config::TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
..config::NetworkConfiguration::new_local() ..config::NetworkConfiguration::new_local()
}); });
@@ -504,23 +500,23 @@ fn fallback_name_working() {
let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())]; let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())];
let (node1, mut events_stream1) = build_test_full_node(config::NetworkConfiguration { let (node1, mut events_stream1) = build_test_full_node(config::NetworkConfiguration {
extra_sets: vec![config::NonDefaultSetConfig { extra_sets: vec![NonDefaultSetConfig {
notifications_protocol: NEW_PROTOCOL_NAME.into(), notifications_protocol: NEW_PROTOCOL_NAME.into(),
fallback_names: vec![PROTOCOL_NAME.into()], fallback_names: vec![PROTOCOL_NAME.into()],
max_notification_size: 1024 * 1024, max_notification_size: 1024 * 1024,
set_config: Default::default(), set_config: Default::default(),
}], }],
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
transport: config::TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
..config::NetworkConfiguration::new_local() ..config::NetworkConfiguration::new_local()
}); });
let (_, mut events_stream2) = build_test_full_node(config::NetworkConfiguration { let (_, mut events_stream2) = build_test_full_node(config::NetworkConfiguration {
extra_sets: vec![config::NonDefaultSetConfig { extra_sets: vec![NonDefaultSetConfig {
notifications_protocol: PROTOCOL_NAME.into(), notifications_protocol: PROTOCOL_NAME.into(),
fallback_names: Vec::new(), fallback_names: Vec::new(),
max_notification_size: 1024 * 1024, max_notification_size: 1024 * 1024,
set_config: config::SetConfig { set_config: SetConfig {
reserved_nodes: vec![MultiaddrWithPeerId { reserved_nodes: vec![MultiaddrWithPeerId {
multiaddr: listen_addr, multiaddr: listen_addr,
peer_id: node1.local_peer_id(), peer_id: node1.local_peer_id(),
@@ -529,7 +525,7 @@ fn fallback_name_working() {
}, },
}], }],
listen_addresses: vec![], listen_addresses: vec![],
transport: config::TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
..config::NetworkConfiguration::new_local() ..config::NetworkConfiguration::new_local()
}); });
@@ -572,7 +568,7 @@ fn ensure_listen_addresses_consistent_with_transport_memory() {
let _ = build_test_full_node(config::NetworkConfiguration { let _ = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
transport: config::TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
..config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None) ..config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None)
}); });
} }
@@ -599,7 +595,7 @@ fn ensure_boot_node_addresses_consistent_with_transport_memory() {
let _ = build_test_full_node(config::NetworkConfiguration { let _ = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
transport: config::TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
boot_nodes: vec![boot_node], boot_nodes: vec![boot_node],
..config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None) ..config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None)
}); });
@@ -632,11 +628,8 @@ fn ensure_reserved_node_addresses_consistent_with_transport_memory() {
let _ = build_test_full_node(config::NetworkConfiguration { let _ = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
transport: config::TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
default_peers_set: config::SetConfig { default_peers_set: SetConfig { reserved_nodes: vec![reserved_node], ..Default::default() },
reserved_nodes: vec![reserved_node],
..Default::default()
},
..config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None) ..config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None)
}); });
} }
@@ -652,10 +645,7 @@ fn ensure_reserved_node_addresses_consistent_with_transport_not_memory() {
let _ = build_test_full_node(config::NetworkConfiguration { let _ = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
default_peers_set: config::SetConfig { default_peers_set: SetConfig { reserved_nodes: vec![reserved_node], ..Default::default() },
reserved_nodes: vec![reserved_node],
..Default::default()
},
..config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None) ..config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None)
}); });
} }
@@ -668,7 +658,7 @@ fn ensure_public_addresses_consistent_with_transport_memory() {
let _ = build_test_full_node(config::NetworkConfiguration { let _ = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()], listen_addresses: vec![listen_addr.clone()],
transport: config::TransportConfig::MemoryOnly, transport: TransportConfig::MemoryOnly,
public_addresses: vec![public_address], public_addresses: vec![public_address],
..config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None) ..config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None)
}); });
+4 -10
View File
@@ -47,16 +47,14 @@ use sc_consensus::{
ForkChoiceStrategy, ImportResult, JustificationImport, JustificationSyncLink, LongestChain, ForkChoiceStrategy, ImportResult, JustificationImport, JustificationSyncLink, LongestChain,
Verifier, Verifier,
}; };
pub use sc_network::config::EmptyTransactionPool;
use sc_network::{ use sc_network::{
config::{ config::{NetworkConfiguration, Role, SyncMode},
NetworkConfiguration, NonDefaultSetConfig, NonReservedPeerMode, Role, SyncMode,
TransportConfig,
},
Multiaddr, NetworkService, NetworkWorker, Multiaddr, NetworkService, NetworkWorker,
}; };
use sc_network_common::{ use sc_network_common::{
config::{MultiaddrWithPeerId, ProtocolId}, config::{
MultiaddrWithPeerId, NonDefaultSetConfig, NonReservedPeerMode, ProtocolId, TransportConfig,
},
protocol::ProtocolName, protocol::ProtocolName,
service::{NetworkBlock, NetworkStateInfo, NetworkSyncForkRequest}, service::{NetworkBlock, NetworkStateInfo, NetworkSyncForkRequest},
sync::warp::{AuthorityList, EncodedProof, SetId, VerificationResult, WarpSyncProvider}, sync::warp::{AuthorityList, EncodedProof, SetId, VerificationResult, WarpSyncProvider},
@@ -879,12 +877,8 @@ where
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 },
executor: None, executor: None,
transactions_handler_executor: Box::new(|task| {
async_std::task::spawn(task);
}),
network_config, network_config,
chain: client.clone(), chain: client.clone(),
transaction_pool: Arc::new(EmptyTransactionPool),
protocol_id, protocol_id,
fork_id, fork_id,
import_queue, import_queue,
@@ -0,0 +1,28 @@
[package]
description = "Substrate transaction protocol"
name = "sc-network-transactions"
version = "0.10.0-dev"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
homepage = "https://substrate.io"
repository = "https://github.com/paritytech/substrate/"
documentation = "https://docs.rs/sc-network-transactions"
readme = "README.md"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
array-bytes = "4.1"
codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] }
futures = "0.3.21"
hex = "0.4.0"
libp2p = "0.46.1"
log = "0.4.17"
pin-project = "1.0.10"
prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../../utils/prometheus" }
sc-network-common = { version = "0.10.0-dev", path = "../common" }
sc-peerset = { version = "4.0.0-dev", path = "../../peerset" }
sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" }
sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" }
@@ -0,0 +1,98 @@
// This file is part of Substrate.
// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! Configuration of the transaction protocol
use futures::prelude::*;
use sc_network_common::ExHashT;
use sp_runtime::traits::Block as BlockT;
use std::{collections::HashMap, future::Future, pin::Pin, time};
/// Interval at which we propagate transactions;
pub(crate) const PROPAGATE_TIMEOUT: time::Duration = time::Duration::from_millis(2900);
/// Maximum number of known transaction hashes to keep for a peer.
///
/// This should be approx. 2 blocks full of transactions for the network to function properly.
pub(crate) const MAX_KNOWN_TRANSACTIONS: usize = 10240; // ~300kb per peer + overhead.
/// Maximum allowed size for a transactions notification.
pub(crate) const MAX_TRANSACTIONS_SIZE: u64 = 16 * 1024 * 1024;
/// Maximum number of transaction validation request we keep at any moment.
pub(crate) const MAX_PENDING_TRANSACTIONS: usize = 8192;
/// Result of the transaction import.
#[derive(Clone, Copy, Debug)]
pub enum TransactionImport {
/// Transaction is good but already known by the transaction pool.
KnownGood,
/// Transaction is good and not yet known.
NewGood,
/// Transaction is invalid.
Bad,
/// Transaction import was not performed.
None,
}
/// Future resolving to transaction import result.
pub type TransactionImportFuture = Pin<Box<dyn Future<Output = TransactionImport> + Send>>;
/// Transaction pool interface
pub trait TransactionPool<H: ExHashT, B: BlockT>: Send + Sync {
/// Get transactions from the pool that are ready to be propagated.
fn transactions(&self) -> Vec<(H, B::Extrinsic)>;
/// Get hash of transaction.
fn hash_of(&self, transaction: &B::Extrinsic) -> H;
/// Import a transaction into the pool.
///
/// This will return future.
fn import(&self, transaction: B::Extrinsic) -> TransactionImportFuture;
/// Notify the pool about transactions broadcast.
fn on_broadcasted(&self, propagations: HashMap<H, Vec<String>>);
/// Get transaction by hash.
fn transaction(&self, hash: &H) -> Option<B::Extrinsic>;
}
/// Dummy implementation of the [`TransactionPool`] trait for a transaction pool that is always
/// empty and discards all incoming transactions.
///
/// Requires the "hash" type to implement the `Default` trait.
///
/// Useful for testing purposes.
pub struct EmptyTransactionPool;
impl<H: ExHashT + Default, B: BlockT> TransactionPool<H, B> for EmptyTransactionPool {
fn transactions(&self) -> Vec<(H, B::Extrinsic)> {
Vec::new()
}
fn hash_of(&self, _transaction: &B::Extrinsic) -> H {
Default::default()
}
fn import(&self, _transaction: B::Extrinsic) -> TransactionImportFuture {
Box::pin(future::ready(TransactionImport::KnownGood))
}
fn on_broadcasted(&self, _: HashMap<H, Vec<String>>) {}
fn transaction(&self, _h: &H) -> Option<B::Extrinsic> {
None
}
}
@@ -26,27 +26,22 @@
//! - Use [`TransactionsHandlerPrototype::build`] then [`TransactionsHandler::run`] to obtain a //! - Use [`TransactionsHandlerPrototype::build`] then [`TransactionsHandler::run`] to obtain a
//! `Future` that processes transactions. //! `Future` that processes transactions.
use crate::{ use crate::config::*;
config::{self, TransactionImport, TransactionImportFuture, TransactionPool},
error,
protocol::message,
service::NetworkService,
utils::{interval, LruHashSet},
ExHashT,
};
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use futures::{channel::mpsc, prelude::*, stream::FuturesUnordered}; use futures::{channel::mpsc, prelude::*, stream::FuturesUnordered};
use libp2p::{multiaddr, PeerId}; use libp2p::{multiaddr, PeerId};
use log::{debug, trace, warn}; use log::{debug, trace, warn};
use prometheus_endpoint::{register, Counter, PrometheusError, Registry, U64}; use prometheus_endpoint::{register, Counter, PrometheusError, Registry, U64};
use sc_network_common::{ use sc_network_common::{
config::ProtocolId, config::{NonDefaultSetConfig, NonReservedPeerMode, ProtocolId, SetConfig},
error,
protocol::{ protocol::{
event::{Event, ObservedRole}, event::{Event, ObservedRole},
ProtocolName, ProtocolName,
}, },
service::{NetworkEventStream, NetworkNotification, NetworkPeers}, service::{NetworkEventStream, NetworkNotification, NetworkPeers},
utils::{interval, LruHashSet},
ExHashT,
}; };
use sp_runtime::traits::Block as BlockT; use sp_runtime::traits::Block as BlockT;
use std::{ use std::{
@@ -54,27 +49,14 @@ use std::{
iter, iter,
num::NonZeroUsize, num::NonZeroUsize,
pin::Pin, pin::Pin,
sync::{ sync::Arc,
atomic::{AtomicBool, Ordering},
Arc,
},
task::Poll, task::Poll,
time,
}; };
/// Interval at which we propagate transactions; pub mod config;
const PROPAGATE_TIMEOUT: time::Duration = time::Duration::from_millis(2900);
/// Maximum number of known transaction hashes to keep for a peer. /// A set of transactions.
/// pub type Transactions<E> = Vec<E>;
/// This should be approx. 2 blocks full of transactions for the network to function properly.
const MAX_KNOWN_TRANSACTIONS: usize = 10240; // ~300kb per peer + overhead.
/// Maximum allowed size for a transactions notification.
const MAX_TRANSACTIONS_SIZE: u64 = 16 * 1024 * 1024;
/// Maximum number of transaction validation request we keep at any moment.
const MAX_PENDING_TRANSACTIONS: usize = 8192;
mod rep { mod rep {
use sc_peerset::ReputationChange as Rep; use sc_peerset::ReputationChange as Rep;
@@ -141,7 +123,7 @@ impl TransactionsHandlerPrototype {
pub fn new<Hash: AsRef<[u8]>>( pub fn new<Hash: AsRef<[u8]>>(
protocol_id: ProtocolId, protocol_id: ProtocolId,
genesis_hash: Hash, genesis_hash: Hash,
fork_id: Option<String>, fork_id: Option<&str>,
) -> Self { ) -> Self {
let genesis_hash = genesis_hash.as_ref(); let genesis_hash = genesis_hash.as_ref();
let protocol_name = if let Some(fork_id) = fork_id { let protocol_name = if let Some(fork_id) = fork_id {
@@ -158,16 +140,16 @@ impl TransactionsHandlerPrototype {
} }
/// Returns the configuration of the set to put in the network configuration. /// Returns the configuration of the set to put in the network configuration.
pub fn set_config(&self) -> config::NonDefaultSetConfig { pub fn set_config(&self) -> NonDefaultSetConfig {
config::NonDefaultSetConfig { NonDefaultSetConfig {
notifications_protocol: self.protocol_name.clone(), notifications_protocol: self.protocol_name.clone(),
fallback_names: self.fallback_protocol_names.clone(), fallback_names: self.fallback_protocol_names.clone(),
max_notification_size: MAX_TRANSACTIONS_SIZE, max_notification_size: MAX_TRANSACTIONS_SIZE,
set_config: config::SetConfig { set_config: SetConfig {
in_peers: 0, in_peers: 0,
out_peers: 0, out_peers: 0,
reserved_nodes: Vec::new(), reserved_nodes: Vec::new(),
non_reserved_mode: config::NonReservedPeerMode::Deny, non_reserved_mode: NonReservedPeerMode::Deny,
}, },
} }
} }
@@ -176,23 +158,25 @@ impl TransactionsHandlerPrototype {
/// the behaviour of the handler while it's running. /// the behaviour of the handler while it's running.
/// ///
/// Important: the transactions handler is initially disabled and doesn't gossip transactions. /// Important: the transactions handler is initially disabled and doesn't gossip transactions.
/// You must call [`TransactionsHandlerController::set_gossip_enabled`] to enable it. /// Gossiping is enabled when major syncing is done.
pub fn build<B: BlockT + 'static, H: ExHashT>( pub fn build<
B: BlockT + 'static,
H: ExHashT,
S: NetworkPeers + NetworkEventStream + NetworkNotification + sp_consensus::SyncOracle,
>(
self, self,
service: Arc<NetworkService<B, H>>, service: S,
transaction_pool: Arc<dyn TransactionPool<H, B>>, transaction_pool: Arc<dyn TransactionPool<H, B>>,
metrics_registry: Option<&Registry>, metrics_registry: Option<&Registry>,
) -> error::Result<(TransactionsHandler<B, H>, TransactionsHandlerController<H>)> { ) -> error::Result<(TransactionsHandler<B, H, S>, TransactionsHandlerController<H>)> {
let event_stream = service.event_stream("transactions-handler"); let event_stream = service.event_stream("transactions-handler");
let (to_handler, from_controller) = mpsc::unbounded(); let (to_handler, from_controller) = mpsc::unbounded();
let gossip_enabled = Arc::new(AtomicBool::new(false));
let handler = TransactionsHandler { let handler = TransactionsHandler {
protocol_name: self.protocol_name, protocol_name: self.protocol_name,
propagate_timeout: Box::pin(interval(PROPAGATE_TIMEOUT)), propagate_timeout: Box::pin(interval(PROPAGATE_TIMEOUT)),
pending_transactions: FuturesUnordered::new(), pending_transactions: FuturesUnordered::new(),
pending_transactions_peers: HashMap::new(), pending_transactions_peers: HashMap::new(),
gossip_enabled: gossip_enabled.clone(),
service, service,
event_stream, event_stream,
peers: HashMap::new(), peers: HashMap::new(),
@@ -205,7 +189,7 @@ impl TransactionsHandlerPrototype {
}, },
}; };
let controller = TransactionsHandlerController { to_handler, gossip_enabled }; let controller = TransactionsHandlerController { to_handler };
Ok((handler, controller)) Ok((handler, controller))
} }
@@ -214,15 +198,9 @@ impl TransactionsHandlerPrototype {
/// Controls the behaviour of a [`TransactionsHandler`] it is connected to. /// Controls the behaviour of a [`TransactionsHandler`] it is connected to.
pub struct TransactionsHandlerController<H: ExHashT> { pub struct TransactionsHandlerController<H: ExHashT> {
to_handler: mpsc::UnboundedSender<ToHandler<H>>, to_handler: mpsc::UnboundedSender<ToHandler<H>>,
gossip_enabled: Arc<AtomicBool>,
} }
impl<H: ExHashT> TransactionsHandlerController<H> { impl<H: ExHashT> TransactionsHandlerController<H> {
/// Controls whether transactions are being gossiped on the network.
pub fn set_gossip_enabled(&mut self, enabled: bool) {
self.gossip_enabled.store(enabled, Ordering::Relaxed);
}
/// You may call this when new transactions are imported by the transaction pool. /// You may call this when new transactions are imported by the transaction pool.
/// ///
/// All transactions will be fetched from the `TransactionPool` that was passed at /// All transactions will be fetched from the `TransactionPool` that was passed at
@@ -246,7 +224,11 @@ enum ToHandler<H: ExHashT> {
} }
/// Handler for transactions. Call [`TransactionsHandler::run`] to start the processing. /// Handler for transactions. Call [`TransactionsHandler::run`] to start the processing.
pub struct TransactionsHandler<B: BlockT + 'static, H: ExHashT> { pub struct TransactionsHandler<
B: BlockT + 'static,
H: ExHashT,
S: NetworkPeers + NetworkEventStream + NetworkNotification + sp_consensus::SyncOracle,
> {
protocol_name: ProtocolName, protocol_name: ProtocolName,
/// Interval at which we call `propagate_transactions`. /// Interval at which we call `propagate_transactions`.
propagate_timeout: Pin<Box<dyn Stream<Item = ()> + Send>>, propagate_timeout: Pin<Box<dyn Stream<Item = ()> + Send>>,
@@ -258,13 +240,12 @@ pub struct TransactionsHandler<B: BlockT + 'static, H: ExHashT> {
/// multiple times concurrently. /// multiple times concurrently.
pending_transactions_peers: HashMap<H, Vec<PeerId>>, pending_transactions_peers: HashMap<H, Vec<PeerId>>,
/// Network service to use to send messages and manage peers. /// Network service to use to send messages and manage peers.
service: Arc<NetworkService<B, H>>, service: S,
/// Stream of networking events. /// Stream of networking events.
event_stream: Pin<Box<dyn Stream<Item = Event> + Send>>, event_stream: Pin<Box<dyn Stream<Item = Event> + Send>>,
// All connected peers // All connected peers
peers: HashMap<PeerId, Peer<H>>, peers: HashMap<PeerId, Peer<H>>,
transaction_pool: Arc<dyn TransactionPool<H, B>>, transaction_pool: Arc<dyn TransactionPool<H, B>>,
gossip_enabled: Arc<AtomicBool>,
from_controller: mpsc::UnboundedReceiver<ToHandler<H>>, from_controller: mpsc::UnboundedReceiver<ToHandler<H>>,
/// Prometheus metrics. /// Prometheus metrics.
metrics: Option<Metrics>, metrics: Option<Metrics>,
@@ -278,7 +259,12 @@ struct Peer<H: ExHashT> {
role: ObservedRole, role: ObservedRole,
} }
impl<B: BlockT + 'static, H: ExHashT> TransactionsHandler<B, H> { impl<B, H, S> TransactionsHandler<B, H, S>
where
B: BlockT + 'static,
H: ExHashT,
S: NetworkPeers + NetworkEventStream + NetworkNotification + sp_consensus::SyncOracle,
{
/// Turns the [`TransactionsHandler`] into a future that should run forever and not be /// Turns the [`TransactionsHandler`] into a future that should run forever and not be
/// interrupted. /// interrupted.
pub async fn run(mut self) { pub async fn run(mut self) {
@@ -360,9 +346,9 @@ impl<B: BlockT + 'static, H: ExHashT> TransactionsHandler<B, H> {
continue continue
} }
if let Ok(m) = <message::Transactions<B::Extrinsic> as Decode>::decode( if let Ok(m) =
&mut message.as_ref(), <Transactions<B::Extrinsic> as Decode>::decode(&mut message.as_ref())
) { {
self.on_transactions(remote, m); self.on_transactions(remote, m);
} else { } else {
warn!(target: "sub-libp2p", "Failed to decode transactions list"); warn!(target: "sub-libp2p", "Failed to decode transactions list");
@@ -376,10 +362,10 @@ impl<B: BlockT + 'static, H: ExHashT> TransactionsHandler<B, H> {
} }
/// Called when peer sends us new transactions /// Called when peer sends us new transactions
fn on_transactions(&mut self, who: PeerId, transactions: message::Transactions<B::Extrinsic>) { fn on_transactions(&mut self, who: PeerId, transactions: Transactions<B::Extrinsic>) {
// Accept transactions only when enabled // Accept transactions only when node is not major syncing
if !self.gossip_enabled.load(Ordering::Relaxed) { if self.service.is_major_syncing() {
trace!(target: "sync", "{} Ignoring transactions while disabled", who); trace!(target: "sync", "{} Ignoring transactions while major syncing", who);
return return
} }
@@ -428,10 +414,11 @@ impl<B: BlockT + 'static, H: ExHashT> TransactionsHandler<B, H> {
/// Propagate one transaction. /// Propagate one transaction.
pub fn propagate_transaction(&mut self, hash: &H) { pub fn propagate_transaction(&mut self, hash: &H) {
// Accept transactions only when enabled // Accept transactions only when node is not major syncing
if !self.gossip_enabled.load(Ordering::Relaxed) { if self.service.is_major_syncing() {
return return
} }
debug!(target: "sync", "Propagating transaction [{:?}]", hash); debug!(target: "sync", "Propagating transaction [{:?}]", hash);
if let Some(transaction) = self.transaction_pool.transaction(hash) { if let Some(transaction) = self.transaction_pool.transaction(hash) {
let propagated_to = self.do_propagate_transactions(&[(hash.clone(), transaction)]); let propagated_to = self.do_propagate_transactions(&[(hash.clone(), transaction)]);
@@ -479,10 +466,11 @@ impl<B: BlockT + 'static, H: ExHashT> TransactionsHandler<B, H> {
/// Call when we must propagate ready transactions to peers. /// Call when we must propagate ready transactions to peers.
fn propagate_transactions(&mut self) { fn propagate_transactions(&mut self) {
// Accept transactions only when enabled // Accept transactions only when node is not major syncing
if !self.gossip_enabled.load(Ordering::Relaxed) { if self.service.is_major_syncing() {
return return
} }
debug!(target: "sync", "Propagating transactions"); debug!(target: "sync", "Propagating transactions");
let transactions = self.transaction_pool.transactions(); let transactions = self.transaction_pool.transactions();
let propagated_to = self.do_propagate_transactions(&transactions); let propagated_to = self.do_propagate_transactions(&transactions);
+1
View File
@@ -56,6 +56,7 @@ sc-network-bitswap = { version = "0.10.0-dev", path = "../network/bitswap" }
sc-network-common = { version = "0.10.0-dev", path = "../network/common" } sc-network-common = { version = "0.10.0-dev", path = "../network/common" }
sc-network-light = { version = "0.10.0-dev", path = "../network/light" } sc-network-light = { version = "0.10.0-dev", path = "../network/light" }
sc-network-sync = { version = "0.10.0-dev", path = "../network/sync" } sc-network-sync = { version = "0.10.0-dev", path = "../network/sync" }
sc-network-transactions = { version = "0.10.0-dev", path = "../network/transactions" }
sc-chain-spec = { version = "4.0.0-dev", path = "../chain-spec" } sc-chain-spec = { version = "4.0.0-dev", path = "../chain-spec" }
sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-client-api = { version = "4.0.0-dev", path = "../api" }
sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" }
+41 -21
View File
@@ -40,7 +40,7 @@ use sc_keystore::LocalKeystore;
use sc_network::{config::SyncMode, NetworkService}; use sc_network::{config::SyncMode, NetworkService};
use sc_network_bitswap::BitswapRequestHandler; use sc_network_bitswap::BitswapRequestHandler;
use sc_network_common::{ use sc_network_common::{
service::{NetworkStateInfo, NetworkStatusProvider, NetworkTransaction}, service::{NetworkStateInfo, NetworkStatusProvider},
sync::warp::WarpSyncProvider, sync::warp::WarpSyncProvider,
}; };
use sc_network_light::light_client_requests::handler::LightClientRequestHandler; use sc_network_light::light_client_requests::handler::LightClientRequestHandler;
@@ -326,7 +326,6 @@ where
pub trait SpawnTaskNetwork<Block: BlockT>: pub trait SpawnTaskNetwork<Block: BlockT>:
sc_offchain::NetworkProvider sc_offchain::NetworkProvider
+ NetworkStateInfo + NetworkStateInfo
+ NetworkTransaction<Block::Hash>
+ NetworkStatusProvider<Block> + NetworkStatusProvider<Block>
+ Send + Send
+ Sync + Sync
@@ -339,7 +338,6 @@ where
Block: BlockT, Block: BlockT,
T: sc_offchain::NetworkProvider T: sc_offchain::NetworkProvider
+ NetworkStateInfo + NetworkStateInfo
+ NetworkTransaction<Block::Hash>
+ NetworkStatusProvider<Block> + NetworkStatusProvider<Block>
+ Send + Send
+ Sync + Sync
@@ -368,6 +366,9 @@ pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool, TRpc, Backend> {
pub network: Arc<dyn SpawnTaskNetwork<TBl>>, pub network: Arc<dyn SpawnTaskNetwork<TBl>>,
/// A Sender for RPC requests. /// A Sender for RPC requests.
pub system_rpc_tx: TracingUnboundedSender<sc_rpc::system::Request<TBl>>, pub system_rpc_tx: TracingUnboundedSender<sc_rpc::system::Request<TBl>>,
/// Controller for transactions handlers
pub tx_handler_controller:
sc_network_transactions::TransactionsHandlerController<<TBl as BlockT>::Hash>,
/// Telemetry instance for this node. /// Telemetry instance for this node.
pub telemetry: Option<&'a mut Telemetry>, pub telemetry: Option<&'a mut Telemetry>,
} }
@@ -446,6 +447,7 @@ where
rpc_builder, rpc_builder,
network, network,
system_rpc_tx, system_rpc_tx,
tx_handler_controller,
telemetry, telemetry,
} = params; } = params;
@@ -481,7 +483,11 @@ where
spawn_handle.spawn( spawn_handle.spawn(
"on-transaction-imported", "on-transaction-imported",
Some("transaction-pool"), Some("transaction-pool"),
transaction_notifications(transaction_pool.clone(), network.clone(), telemetry.clone()), transaction_notifications(
transaction_pool.clone(),
tx_handler_controller,
telemetry.clone(),
),
); );
// Prometheus metrics. // Prometheus metrics.
@@ -544,20 +550,21 @@ where
Ok(rpc_handlers) Ok(rpc_handlers)
} }
async fn transaction_notifications<Block, ExPool, Network>( async fn transaction_notifications<Block, ExPool>(
transaction_pool: Arc<ExPool>, transaction_pool: Arc<ExPool>,
network: Network, tx_handler_controller: sc_network_transactions::TransactionsHandlerController<
<Block as BlockT>::Hash,
>,
telemetry: Option<TelemetryHandle>, telemetry: Option<TelemetryHandle>,
) where ) where
Block: BlockT, Block: BlockT,
ExPool: MaintainedTransactionPool<Block = Block, Hash = <Block as BlockT>::Hash>, ExPool: MaintainedTransactionPool<Block = Block, Hash = <Block as BlockT>::Hash>,
Network: NetworkTransaction<<Block as BlockT>::Hash> + Send + Sync,
{ {
// transaction notifications // transaction notifications
transaction_pool transaction_pool
.import_notification_stream() .import_notification_stream()
.for_each(move |hash| { .for_each(move |hash| {
network.propagate_transaction(hash); tx_handler_controller.propagate_transaction(hash);
let status = transaction_pool.status(); let status = transaction_pool.status();
telemetry!( telemetry!(
telemetry; telemetry;
@@ -719,6 +726,7 @@ pub fn build_network<TBl, TExPool, TImpQu, TCl>(
( (
Arc<NetworkService<TBl, <TBl as BlockT>::Hash>>, Arc<NetworkService<TBl, <TBl as BlockT>::Hash>>,
TracingUnboundedSender<sc_rpc::system::Request<TBl>>, TracingUnboundedSender<sc_rpc::system::Request<TBl>>,
sc_network_transactions::TransactionsHandlerController<<TBl as BlockT>::Hash>,
NetworkStarter, NetworkStarter,
), ),
Error, Error,
@@ -761,9 +769,6 @@ where
} }
} }
let transaction_pool_adapter =
Arc::new(TransactionPoolAdapter { pool: transaction_pool, client: client.clone() });
let protocol_id = config.protocol_id(); let protocol_id = config.protocol_id();
let block_announce_validator = if let Some(f) = block_announce_validator_builder { let block_announce_validator = if let Some(f) = block_announce_validator_builder {
@@ -845,7 +850,7 @@ where
protocol_config protocol_config
})); }));
let network_params = sc_network::config::Params { let mut network_params = sc_network::config::Params {
role: config.role.clone(), role: config.role.clone(),
executor: { executor: {
let spawn_handle = Clone::clone(&spawn_handle); let spawn_handle = Clone::clone(&spawn_handle);
@@ -853,16 +858,9 @@ where
spawn_handle.spawn("libp2p-node", Some("networking"), fut); spawn_handle.spawn("libp2p-node", Some("networking"), fut);
})) }))
}, },
transactions_handler_executor: {
let spawn_handle = Clone::clone(&spawn_handle);
Box::new(move |fut| {
spawn_handle.spawn("network-transactions-handler", Some("networking"), fut);
})
},
network_config: config.network.clone(), network_config: config.network.clone(),
chain: client.clone(), chain: client.clone(),
transaction_pool: transaction_pool_adapter as _, protocol_id: protocol_id.clone(),
protocol_id,
fork_id: config.chain_spec.fork_id().map(ToOwned::to_owned), fork_id: config.chain_spec.fork_id().map(ToOwned::to_owned),
import_queue: Box::new(import_queue), import_queue: Box::new(import_queue),
chain_sync: Box::new(chain_sync), chain_sync: Box::new(chain_sync),
@@ -877,10 +875,32 @@ where
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
}; };
// crate transactions protocol and add it to the list of supported protocols of `network_params`
let transactions_handler_proto = sc_network_transactions::TransactionsHandlerPrototype::new(
protocol_id.clone(),
client
.block_hash(0u32.into())
.ok()
.flatten()
.expect("Genesis block exists; qed"),
config.chain_spec.fork_id(),
);
network_params
.network_config
.extra_sets
.insert(0, transactions_handler_proto.set_config());
let has_bootnodes = !network_params.network_config.boot_nodes.is_empty(); let has_bootnodes = !network_params.network_config.boot_nodes.is_empty();
let network_mut = sc_network::NetworkWorker::new(network_params)?; let network_mut = sc_network::NetworkWorker::new(network_params)?;
let network = network_mut.service().clone(); let network = network_mut.service().clone();
let (tx_handler, tx_handler_controller) = transactions_handler_proto.build(
network.clone(),
Arc::new(TransactionPoolAdapter { pool: transaction_pool, client: client.clone() }),
config.prometheus_config.as_ref().map(|config| &config.registry),
)?;
spawn_handle.spawn("network-transactions-handler", Some("networking"), tx_handler.run());
let (system_rpc_tx, system_rpc_rx) = tracing_unbounded("mpsc_system_rpc"); let (system_rpc_tx, system_rpc_rx) = tracing_unbounded("mpsc_system_rpc");
let future = build_network_future( let future = build_network_future(
@@ -928,7 +948,7 @@ where
future.await future.await
}); });
Ok((network, system_rpc_tx, NetworkStarter(network_start_tx))) Ok((network, system_rpc_tx, tx_handler_controller, NetworkStarter(network_start_tx)))
} }
/// Object used to start the network. /// Object used to start the network.
+2 -4
View File
@@ -24,13 +24,11 @@ pub use sc_executor::WasmExecutionMethod;
#[cfg(feature = "wasmtime")] #[cfg(feature = "wasmtime")]
pub use sc_executor::WasmtimeInstantiationStrategy; pub use sc_executor::WasmtimeInstantiationStrategy;
pub use sc_network::{ pub use sc_network::{
config::{ config::{NetworkConfiguration, NodeKeyConfig, Role},
NetworkConfiguration, NodeKeyConfig, NonDefaultSetConfig, Role, SetConfig, TransportConfig,
},
Multiaddr, Multiaddr,
}; };
pub use sc_network_common::{ pub use sc_network_common::{
config::{MultiaddrWithPeerId, ProtocolId}, config::{MultiaddrWithPeerId, NonDefaultSetConfig, ProtocolId, SetConfig, TransportConfig},
request_responses::{ request_responses::{
IncomingRequest, OutgoingResponse, ProtocolConfig as RequestResponseConfig, IncomingRequest, OutgoingResponse, ProtocolConfig as RequestResponseConfig,
}, },
+1 -2
View File
@@ -19,7 +19,6 @@
//! Errors that can occur during the service operation. //! Errors that can occur during the service operation.
use sc_keystore; use sc_keystore;
use sc_network;
use sp_blockchain; use sp_blockchain;
use sp_consensus; use sp_consensus;
@@ -41,7 +40,7 @@ pub enum Error {
Consensus(#[from] sp_consensus::Error), Consensus(#[from] sp_consensus::Error),
#[error(transparent)] #[error(transparent)]
Network(#[from] sc_network::error::Error), Network(#[from] sc_network_common::error::Error),
#[error(transparent)] #[error(transparent)]
Keystore(#[from] sc_keystore::Error), Keystore(#[from] sc_keystore::Error),
+4 -3
View File
@@ -72,7 +72,7 @@ pub use sc_chain_spec::{
pub use sc_consensus::ImportQueue; pub use sc_consensus::ImportQueue;
pub use sc_executor::NativeExecutionDispatch; pub use sc_executor::NativeExecutionDispatch;
#[doc(hidden)] #[doc(hidden)]
pub use sc_network::config::{TransactionImport, TransactionImportFuture}; pub use sc_network_transactions::config::{TransactionImport, TransactionImportFuture};
pub use sc_rpc::{ pub use sc_rpc::{
RandomIntegerSubscriptionId, RandomStringSubscriptionId, RpcSubscriptionIdProvider, RandomIntegerSubscriptionId, RandomStringSubscriptionId, RpcSubscriptionIdProvider,
}; };
@@ -148,7 +148,7 @@ async fn build_network_future<
+ Send + Send
+ Sync + Sync
+ 'static, + 'static,
H: sc_network::ExHashT, H: sc_network_common::ExHashT,
>( >(
role: Role, role: Role,
mut network: sc_network::NetworkWorker<B, H, C>, mut network: sc_network::NetworkWorker<B, H, C>,
@@ -415,7 +415,8 @@ where
.collect() .collect()
} }
impl<B, H, C, Pool, E> sc_network::config::TransactionPool<H, B> for TransactionPoolAdapter<C, Pool> impl<B, H, C, Pool, E> sc_network_transactions::config::TransactionPool<H, B>
for TransactionPoolAdapter<C, Pool>
where where
C: HeaderBackend<B> C: HeaderBackend<B>
+ BlockBackend<B> + BlockBackend<B>
+2 -5
View File
@@ -22,12 +22,9 @@ use futures::{task::Poll, Future, TryFutureExt as _};
use log::{debug, info}; use log::{debug, info};
use parking_lot::Mutex; use parking_lot::Mutex;
use sc_client_api::{Backend, CallExecutor}; use sc_client_api::{Backend, CallExecutor};
use sc_network::{ use sc_network::{config::NetworkConfiguration, multiaddr};
config::{NetworkConfiguration, TransportConfig},
multiaddr,
};
use sc_network_common::{ use sc_network_common::{
config::MultiaddrWithPeerId, config::{MultiaddrWithPeerId, TransportConfig},
service::{NetworkBlock, NetworkPeers, NetworkStateInfo}, service::{NetworkBlock, NetworkPeers, NetworkStateInfo},
}; };
use sc_service::{ use sc_service::{