mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 12:51:05 +00:00
Split the Roles in three types (#5520)
* Split the Roles bitfield in three * Forgot to include some changes * Fix cli test * More test fixes * Oh God, merging master broke other tests * Didn't run the doctests * Address review * I'm trying to fix the build blindly because it's taking a good hour to compile on my machine * Address some review * Also update the peerset's API to make sense * Fix peerset tests * Fix browser node * client: distinguish between local and network authority Co-authored-by: André Silva <andre.beat@gmail.com>
This commit is contained in:
@@ -72,16 +72,11 @@ macro_rules! new_full_start {
|
|||||||
pub fn new_full(config: Configuration)
|
pub fn new_full(config: Configuration)
|
||||||
-> Result<impl AbstractService, ServiceError>
|
-> Result<impl AbstractService, ServiceError>
|
||||||
{
|
{
|
||||||
let is_authority = config.roles.is_authority();
|
let role = config.role.clone();
|
||||||
let force_authoring = config.force_authoring;
|
let force_authoring = config.force_authoring;
|
||||||
let name = config.name.clone();
|
let name = config.name.clone();
|
||||||
let disable_grandpa = config.disable_grandpa;
|
let disable_grandpa = config.disable_grandpa;
|
||||||
|
|
||||||
// sentry nodes announce themselves as authorities to the network
|
|
||||||
// and should run the same protocols authorities do, but it should
|
|
||||||
// never actively participate in any consensus process.
|
|
||||||
let participates_in_consensus = is_authority && !config.sentry_mode;
|
|
||||||
|
|
||||||
let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config);
|
let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config);
|
||||||
|
|
||||||
let (block_import, grandpa_link) =
|
let (block_import, grandpa_link) =
|
||||||
@@ -96,11 +91,9 @@ pub fn new_full(config: Configuration)
|
|||||||
})?
|
})?
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
if participates_in_consensus {
|
if role.is_authority() {
|
||||||
let proposer = sc_basic_authorship::ProposerFactory::new(
|
let proposer =
|
||||||
service.client(),
|
sc_basic_authorship::ProposerFactory::new(service.client(), service.transaction_pool());
|
||||||
service.transaction_pool()
|
|
||||||
);
|
|
||||||
|
|
||||||
let client = service.client();
|
let client = service.client();
|
||||||
let select_chain = service.select_chain()
|
let select_chain = service.select_chain()
|
||||||
@@ -129,7 +122,7 @@ pub fn new_full(config: Configuration)
|
|||||||
|
|
||||||
// if the node isn't actively participating in consensus then it doesn't
|
// if the node isn't actively participating in consensus then it doesn't
|
||||||
// need a keystore, regardless of which protocol we use below.
|
// need a keystore, regardless of which protocol we use below.
|
||||||
let keystore = if participates_in_consensus {
|
let keystore = if role.is_authority() {
|
||||||
Some(service.keystore())
|
Some(service.keystore())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -142,7 +135,7 @@ pub fn new_full(config: Configuration)
|
|||||||
name: Some(name),
|
name: Some(name),
|
||||||
observer_enabled: false,
|
observer_enabled: false,
|
||||||
keystore,
|
keystore,
|
||||||
is_authority,
|
is_authority: role.is_network_authority(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let enable_grandpa = !disable_grandpa;
|
let enable_grandpa = !disable_grandpa;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ async fn start_inner(chain_spec: String, log_level: String) -> Result<Client, Bo
|
|||||||
info!("❤️ by Parity Technologies, 2017-2020");
|
info!("❤️ by Parity Technologies, 2017-2020");
|
||||||
info!("📋 Chain specification: {}", config.expect_chain_spec().name());
|
info!("📋 Chain specification: {}", config.expect_chain_spec().name());
|
||||||
info!("🏷 Node name: {}", config.name);
|
info!("🏷 Node name: {}", config.name);
|
||||||
info!("👤 Roles: {:?}", config.roles);
|
info!("👤 Role: {:?}", config.role);
|
||||||
|
|
||||||
// Create the service. This is the most heavy initialization step.
|
// Create the service. This is the most heavy initialization step.
|
||||||
let service = crate::service::new_light(config)
|
let service = crate::service::new_light(config)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use sc_cli::VersionInfo;
|
use sc_cli::VersionInfo;
|
||||||
use sc_service::{Roles as ServiceRoles};
|
use sc_service::{Role as ServiceRole};
|
||||||
use node_transaction_factory::RuntimeAdapter;
|
use node_transaction_factory::RuntimeAdapter;
|
||||||
use crate::{Cli, service, ChainSpec, load_spec, Subcommand, factory_impl::FactoryState};
|
use crate::{Cli, service, ChainSpec, load_spec, Subcommand, factory_impl::FactoryState};
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ where
|
|||||||
cli_args.shared_params.update_config(&mut config, load_spec, &version)?;
|
cli_args.shared_params.update_config(&mut config, load_spec, &version)?;
|
||||||
cli_args.import_params.update_config(
|
cli_args.import_params.update_config(
|
||||||
&mut config,
|
&mut config,
|
||||||
ServiceRoles::FULL,
|
&ServiceRole::Full,
|
||||||
cli_args.shared_params.dev,
|
cli_args.shared_params.dev,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|||||||
@@ -120,24 +120,17 @@ macro_rules! new_full {
|
|||||||
use sc_client_api::ExecutorProvider;
|
use sc_client_api::ExecutorProvider;
|
||||||
|
|
||||||
let (
|
let (
|
||||||
is_authority,
|
role,
|
||||||
force_authoring,
|
force_authoring,
|
||||||
name,
|
name,
|
||||||
disable_grandpa,
|
disable_grandpa,
|
||||||
sentry_nodes,
|
|
||||||
) = (
|
) = (
|
||||||
$config.roles.is_authority(),
|
$config.role.clone(),
|
||||||
$config.force_authoring,
|
$config.force_authoring,
|
||||||
$config.name.clone(),
|
$config.name.clone(),
|
||||||
$config.disable_grandpa,
|
$config.disable_grandpa,
|
||||||
$config.network.sentry_nodes.clone(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// sentry nodes announce themselves as authorities to the network
|
|
||||||
// and should run the same protocols authorities do, but it should
|
|
||||||
// never actively participate in any consensus process.
|
|
||||||
let participates_in_consensus = is_authority && !$config.sentry_mode;
|
|
||||||
|
|
||||||
let (builder, mut import_setup, inherent_data_providers) = new_full_start!($config);
|
let (builder, mut import_setup, inherent_data_providers) = new_full_start!($config);
|
||||||
|
|
||||||
let service = builder
|
let service = builder
|
||||||
@@ -153,7 +146,7 @@ macro_rules! new_full {
|
|||||||
|
|
||||||
($with_startup_data)(&block_import, &babe_link);
|
($with_startup_data)(&block_import, &babe_link);
|
||||||
|
|
||||||
if participates_in_consensus {
|
if let sc_service::config::Role::Authority { sentry_nodes } = &role {
|
||||||
let proposer = sc_basic_authorship::ProposerFactory::new(
|
let proposer = sc_basic_authorship::ProposerFactory::new(
|
||||||
service.client(),
|
service.client(),
|
||||||
service.transaction_pool()
|
service.transaction_pool()
|
||||||
@@ -190,7 +183,7 @@ macro_rules! new_full {
|
|||||||
let authority_discovery = sc_authority_discovery::AuthorityDiscovery::new(
|
let authority_discovery = sc_authority_discovery::AuthorityDiscovery::new(
|
||||||
service.client(),
|
service.client(),
|
||||||
network,
|
network,
|
||||||
sentry_nodes,
|
sentry_nodes.clone(),
|
||||||
service.keystore(),
|
service.keystore(),
|
||||||
dht_event_stream,
|
dht_event_stream,
|
||||||
service.prometheus_registry(),
|
service.prometheus_registry(),
|
||||||
@@ -201,7 +194,7 @@ macro_rules! new_full {
|
|||||||
|
|
||||||
// if the node isn't actively participating in consensus then it doesn't
|
// if the node isn't actively participating in consensus then it doesn't
|
||||||
// need a keystore, regardless of which protocol we use below.
|
// need a keystore, regardless of which protocol we use below.
|
||||||
let keystore = if participates_in_consensus {
|
let keystore = if role.is_authority() {
|
||||||
Some(service.keystore())
|
Some(service.keystore())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -214,7 +207,7 @@ macro_rules! new_full {
|
|||||||
name: Some(name),
|
name: Some(name),
|
||||||
observer_enabled: false,
|
observer_enabled: false,
|
||||||
keystore,
|
keystore,
|
||||||
is_authority,
|
is_authority: role.is_network_authority(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let enable_grandpa = !disable_grandpa;
|
let enable_grandpa = !disable_grandpa;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ impl InspectCmd {
|
|||||||
// and all import params (especially pruning that has to match db meta)
|
// and all import params (especially pruning that has to match db meta)
|
||||||
self.import_params.update_config(
|
self.import_params.update_config(
|
||||||
&mut config,
|
&mut config,
|
||||||
sc_service::Roles::FULL,
|
&sc_service::Role::Full,
|
||||||
self.shared_params.dev,
|
self.shared_params.dev,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|||||||
@@ -56,12 +56,11 @@ use futures_timer::Delay;
|
|||||||
|
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use error::{Error, Result};
|
use error::{Error, Result};
|
||||||
use libp2p::Multiaddr;
|
|
||||||
use log::{debug, error, log_enabled, warn};
|
use log::{debug, error, log_enabled, warn};
|
||||||
use prometheus_endpoint::{Counter, CounterVec, Gauge, Opts, U64, register};
|
use prometheus_endpoint::{Counter, CounterVec, Gauge, Opts, U64, register};
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
use sc_client_api::blockchain::HeaderBackend;
|
use sc_client_api::blockchain::HeaderBackend;
|
||||||
use sc_network::{DhtEvent, ExHashT, NetworkStateInfo};
|
use sc_network::{Multiaddr, config::MultiaddrWithPeerId, DhtEvent, ExHashT, NetworkStateInfo};
|
||||||
use sp_authority_discovery::{AuthorityDiscoveryApi, AuthorityId, AuthoritySignature, AuthorityPair};
|
use sp_authority_discovery::{AuthorityDiscoveryApi, AuthorityId, AuthoritySignature, AuthorityPair};
|
||||||
use sp_core::crypto::{key_types, CryptoTypePublicPair, Pair};
|
use sp_core::crypto::{key_types, CryptoTypePublicPair, Pair};
|
||||||
use sp_core::traits::BareCryptoStorePtr;
|
use sp_core::traits::BareCryptoStorePtr;
|
||||||
@@ -187,7 +186,7 @@ where
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
network: Arc<Network>,
|
network: Arc<Network>,
|
||||||
sentry_nodes: Vec<String>,
|
sentry_nodes: Vec<MultiaddrWithPeerId>,
|
||||||
key_store: BareCryptoStorePtr,
|
key_store: BareCryptoStorePtr,
|
||||||
dht_event_rx: Pin<Box<dyn Stream<Item = DhtEvent> + Send>>,
|
dht_event_rx: Pin<Box<dyn Stream<Item = DhtEvent> + Send>>,
|
||||||
prometheus_registry: Option<prometheus_endpoint::Registry>,
|
prometheus_registry: Option<prometheus_endpoint::Registry>,
|
||||||
@@ -210,18 +209,7 @@ where
|
|||||||
);
|
);
|
||||||
|
|
||||||
let sentry_nodes = if !sentry_nodes.is_empty() {
|
let sentry_nodes = if !sentry_nodes.is_empty() {
|
||||||
let addrs = sentry_nodes.into_iter().filter_map(|a| match a.parse() {
|
Some(sentry_nodes.into_iter().map(|ma| ma.concat()).collect::<Vec<_>>())
|
||||||
Ok(addr) => Some(addr),
|
|
||||||
Err(e) => {
|
|
||||||
error!(
|
|
||||||
target: "sub-authority-discovery",
|
|
||||||
"Failed to parse sentry node public address '{:?}', continuing anyways.", e,
|
|
||||||
);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}).collect::<Vec<Multiaddr>>();
|
|
||||||
|
|
||||||
Some(addrs)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ use sp_runtime::BuildStorage;
|
|||||||
use serde_json as json;
|
use serde_json as json;
|
||||||
use crate::RuntimeGenesis;
|
use crate::RuntimeGenesis;
|
||||||
use crate::extension::GetExtension;
|
use crate::extension::GetExtension;
|
||||||
use sc_network::Multiaddr;
|
use sc_network::config::MultiaddrWithPeerId;
|
||||||
use sc_telemetry::TelemetryEndpoints;
|
use sc_telemetry::TelemetryEndpoints;
|
||||||
|
|
||||||
enum GenesisSource<G> {
|
enum GenesisSource<G> {
|
||||||
@@ -137,7 +137,7 @@ enum Genesis<G> {
|
|||||||
struct ClientSpec<E> {
|
struct ClientSpec<E> {
|
||||||
name: String,
|
name: String,
|
||||||
id: String,
|
id: String,
|
||||||
boot_nodes: Vec<String>,
|
boot_nodes: Vec<MultiaddrWithPeerId>,
|
||||||
telemetry_endpoints: Option<TelemetryEndpoints>,
|
telemetry_endpoints: Option<TelemetryEndpoints>,
|
||||||
protocol_id: Option<String>,
|
protocol_id: Option<String>,
|
||||||
properties: Option<Properties>,
|
properties: Option<Properties>,
|
||||||
@@ -174,7 +174,7 @@ impl<G, E: Clone> Clone for ChainSpec<G, E> {
|
|||||||
|
|
||||||
impl<G, E> ChainSpec<G, E> {
|
impl<G, E> ChainSpec<G, E> {
|
||||||
/// A list of bootnode addresses.
|
/// A list of bootnode addresses.
|
||||||
pub fn boot_nodes(&self) -> &[String] {
|
pub fn boot_nodes(&self) -> &[MultiaddrWithPeerId] {
|
||||||
&self.client_spec.boot_nodes
|
&self.client_spec.boot_nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,8 +206,8 @@ impl<G, E> ChainSpec<G, E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add a bootnode to the list.
|
/// Add a bootnode to the list.
|
||||||
pub fn add_boot_node(&mut self, addr: Multiaddr) {
|
pub fn add_boot_node(&mut self, addr: MultiaddrWithPeerId) {
|
||||||
self.client_spec.boot_nodes.push(addr.to_string())
|
self.client_spec.boot_nodes.push(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to defined chain spec extensions.
|
/// Returns a reference to defined chain spec extensions.
|
||||||
@@ -220,7 +220,7 @@ impl<G, E> ChainSpec<G, E> {
|
|||||||
name: &str,
|
name: &str,
|
||||||
id: &str,
|
id: &str,
|
||||||
constructor: F,
|
constructor: F,
|
||||||
boot_nodes: Vec<String>,
|
boot_nodes: Vec<MultiaddrWithPeerId>,
|
||||||
telemetry_endpoints: Option<TelemetryEndpoints>,
|
telemetry_endpoints: Option<TelemetryEndpoints>,
|
||||||
protocol_id: Option<&str>,
|
protocol_id: Option<&str>,
|
||||||
properties: Option<Properties>,
|
properties: Option<Properties>,
|
||||||
@@ -320,7 +320,7 @@ where
|
|||||||
G: RuntimeGenesis,
|
G: RuntimeGenesis,
|
||||||
E: GetExtension + serde::Serialize + Clone + Send,
|
E: GetExtension + serde::Serialize + Clone + Send,
|
||||||
{
|
{
|
||||||
fn boot_nodes(&self) -> &[String] {
|
fn boot_nodes(&self) -> &[MultiaddrWithPeerId] {
|
||||||
ChainSpec::boot_nodes(self)
|
ChainSpec::boot_nodes(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,7 +344,7 @@ where
|
|||||||
ChainSpec::properties(self)
|
ChainSpec::properties(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_boot_node(&mut self, addr: Multiaddr) {
|
fn add_boot_node(&mut self, addr: MultiaddrWithPeerId) {
|
||||||
ChainSpec::add_boot_node(self, addr)
|
ChainSpec::add_boot_node(self, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ pub use sc_chain_spec_derive::{ChainSpecExtension, ChainSpecGroup};
|
|||||||
|
|
||||||
use serde::{Serialize, de::DeserializeOwned};
|
use serde::{Serialize, de::DeserializeOwned};
|
||||||
use sp_runtime::BuildStorage;
|
use sp_runtime::BuildStorage;
|
||||||
use sc_network::Multiaddr;
|
use sc_network::config::MultiaddrWithPeerId;
|
||||||
use sc_telemetry::TelemetryEndpoints;
|
use sc_telemetry::TelemetryEndpoints;
|
||||||
|
|
||||||
/// A set of traits for the runtime genesis config.
|
/// A set of traits for the runtime genesis config.
|
||||||
@@ -131,7 +131,7 @@ pub trait ChainSpec: BuildStorage + Send {
|
|||||||
/// Spec id.
|
/// Spec id.
|
||||||
fn id(&self) -> &str;
|
fn id(&self) -> &str;
|
||||||
/// A list of bootnode addresses.
|
/// A list of bootnode addresses.
|
||||||
fn boot_nodes(&self) -> &[String];
|
fn boot_nodes(&self) -> &[MultiaddrWithPeerId];
|
||||||
/// Telemetry endpoints (if any)
|
/// Telemetry endpoints (if any)
|
||||||
fn telemetry_endpoints(&self) -> &Option<TelemetryEndpoints>;
|
fn telemetry_endpoints(&self) -> &Option<TelemetryEndpoints>;
|
||||||
/// Network protocol id.
|
/// Network protocol id.
|
||||||
@@ -143,7 +143,7 @@ pub trait ChainSpec: BuildStorage + Send {
|
|||||||
/// Returns a reference to defined chain spec extensions.
|
/// Returns a reference to defined chain spec extensions.
|
||||||
fn extensions(&self) -> &dyn GetExtension;
|
fn extensions(&self) -> &dyn GetExtension;
|
||||||
/// Add a bootnode to the list.
|
/// Add a bootnode to the list.
|
||||||
fn add_boot_node(&mut self, addr: Multiaddr);
|
fn add_boot_node(&mut self, addr: MultiaddrWithPeerId);
|
||||||
/// Return spec as JSON.
|
/// Return spec as JSON.
|
||||||
fn as_json(&self, raw: bool) -> Result<String, String>;
|
fn as_json(&self, raw: bool) -> Result<String, String>;
|
||||||
/// Return StorageBuilder for this spec.
|
/// Return StorageBuilder for this spec.
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use log::info;
|
use log::info;
|
||||||
use sc_network::config::build_multiaddr;
|
use sc_network::config::{build_multiaddr, MultiaddrWithPeerId};
|
||||||
use sc_service::{Configuration, ChainSpec};
|
use sc_service::{Configuration, ChainSpec};
|
||||||
|
|
||||||
use crate::error;
|
use crate::error;
|
||||||
@@ -60,11 +60,10 @@ impl BuildSpecCmd {
|
|||||||
if spec.boot_nodes().is_empty() && !self.disable_default_bootnode {
|
if spec.boot_nodes().is_empty() && !self.disable_default_bootnode {
|
||||||
let keys = config.network.node_key.into_keypair()?;
|
let keys = config.network.node_key.into_keypair()?;
|
||||||
let peer_id = keys.public().into_peer_id();
|
let peer_id = keys.public().into_peer_id();
|
||||||
let addr = build_multiaddr![
|
let addr = MultiaddrWithPeerId {
|
||||||
Ip4([127, 0, 0, 1]),
|
multiaddr: build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(30333u16)],
|
||||||
Tcp(30333u16),
|
peer_id,
|
||||||
P2p(peer_id)
|
};
|
||||||
];
|
|
||||||
spec.add_boot_node(addr)
|
spec.add_boot_node(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use std::fmt::Debug;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use sc_service::{
|
use sc_service::{
|
||||||
Configuration, ServiceBuilderCommand, Roles, ChainSpec,
|
Configuration, ServiceBuilderCommand, Role, ChainSpec,
|
||||||
};
|
};
|
||||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||||
use sp_runtime::generic::BlockId;
|
use sp_runtime::generic::BlockId;
|
||||||
@@ -93,7 +93,7 @@ impl CheckBlockCmd {
|
|||||||
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
||||||
{
|
{
|
||||||
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
||||||
self.import_params.update_config(&mut config, Roles::FULL, self.shared_params.dev)?;
|
self.import_params.update_config(&mut config, &Role::Full, self.shared_params.dev)?;
|
||||||
config.use_in_memory_keystore()?;
|
config.use_in_memory_keystore()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use log::info;
|
|||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use sc_service::{
|
use sc_service::{
|
||||||
Configuration, ServiceBuilderCommand, ChainSpec,
|
Configuration, ServiceBuilderCommand, ChainSpec,
|
||||||
config::DatabaseConfig, Roles,
|
config::DatabaseConfig, Role,
|
||||||
};
|
};
|
||||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ impl ExportBlocksCmd {
|
|||||||
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
||||||
{
|
{
|
||||||
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
||||||
self.pruning_params.update_config(&mut config, Roles::FULL, true)?;
|
self.pruning_params.update_config(&mut config, &Role::Full, true)?;
|
||||||
config.use_in_memory_keystore()?;
|
config.use_in_memory_keystore()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use std::fs;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use sc_service::{
|
use sc_service::{
|
||||||
Configuration, ServiceBuilderCommand, ChainSpec, Roles,
|
Configuration, ServiceBuilderCommand, ChainSpec, Role,
|
||||||
};
|
};
|
||||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ impl ImportBlocksCmd {
|
|||||||
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
||||||
{
|
{
|
||||||
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
||||||
self.import_params.update_config(&mut config, Roles::FULL, self.shared_params.dev)?;
|
self.import_params.update_config(&mut config, &Role::Full, self.shared_params.dev)?;
|
||||||
config.use_in_memory_keystore()?;
|
config.use_in_memory_keystore()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use sc_service::{
|
use sc_service::{
|
||||||
Configuration, ServiceBuilderCommand, ChainSpec, Roles,
|
Configuration, ServiceBuilderCommand, ChainSpec, Role,
|
||||||
};
|
};
|
||||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ impl RevertCmd {
|
|||||||
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
||||||
{
|
{
|
||||||
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
||||||
self.pruning_params.update_config(&mut config, Roles::FULL, true)?;
|
self.pruning_params.update_config(&mut config, &Role::Full, true)?;
|
||||||
config.use_in_memory_keystore()?;
|
config.use_in_memory_keystore()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ use names::{Generator, Name};
|
|||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use sc_service::{
|
use sc_service::{
|
||||||
AbstractService, Configuration, ChainSpec, Roles,
|
AbstractService, Configuration, ChainSpec, Role,
|
||||||
config::{KeystoreConfig, PrometheusConfig},
|
config::{MultiaddrWithPeerId, KeystoreConfig, PrometheusConfig},
|
||||||
};
|
};
|
||||||
use sc_telemetry::TelemetryEndpoints;
|
use sc_telemetry::TelemetryEndpoints;
|
||||||
|
|
||||||
@@ -78,9 +78,10 @@ pub struct RunCmd {
|
|||||||
/// available to relay to private nodes.
|
/// available to relay to private nodes.
|
||||||
#[structopt(
|
#[structopt(
|
||||||
long = "sentry",
|
long = "sentry",
|
||||||
conflicts_with_all = &[ "validator", "light" ]
|
conflicts_with_all = &[ "validator", "light" ],
|
||||||
|
parse(try_from_str)
|
||||||
)]
|
)]
|
||||||
pub sentry: bool,
|
pub sentry: Vec<MultiaddrWithPeerId>,
|
||||||
|
|
||||||
/// Disable GRANDPA voter when running in validator mode, otherwise disable the GRANDPA observer.
|
/// Disable GRANDPA voter when running in validator mode, otherwise disable the GRANDPA observer.
|
||||||
#[structopt(long = "no-grandpa")]
|
#[structopt(long = "no-grandpa")]
|
||||||
@@ -329,18 +330,20 @@ impl RunCmd {
|
|||||||
let keyring = self.get_keyring();
|
let keyring = self.get_keyring();
|
||||||
let is_dev = self.shared_params.dev;
|
let is_dev = self.shared_params.dev;
|
||||||
let is_light = self.light;
|
let is_light = self.light;
|
||||||
let is_authority = (self.validator || self.sentry || is_dev || keyring.is_some())
|
let is_authority = (self.validator || is_dev || keyring.is_some())
|
||||||
&& !is_light;
|
&& !is_light;
|
||||||
let role =
|
let role =
|
||||||
if is_light {
|
if is_light {
|
||||||
sc_service::Roles::LIGHT
|
sc_service::Role::Light
|
||||||
} else if is_authority {
|
} else if is_authority {
|
||||||
sc_service::Roles::AUTHORITY
|
sc_service::Role::Authority { sentry_nodes: self.network_config.sentry_nodes.clone() }
|
||||||
|
} else if !self.sentry.is_empty() {
|
||||||
|
sc_service::Role::Sentry { validators: self.sentry.clone() }
|
||||||
} else {
|
} else {
|
||||||
sc_service::Roles::FULL
|
sc_service::Role::Full
|
||||||
};
|
};
|
||||||
|
|
||||||
self.import_params.update_config(&mut config, role, is_dev)?;
|
self.import_params.update_config(&mut config, &role, is_dev)?;
|
||||||
|
|
||||||
config.name = match (self.name.as_ref(), keyring) {
|
config.name = match (self.name.as_ref(), keyring) {
|
||||||
(Some(name), _) => name.to_string(),
|
(Some(name), _) => name.to_string(),
|
||||||
@@ -356,17 +359,14 @@ impl RunCmd {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// set sentry mode (i.e. act as an authority but **never** actively participate)
|
config.offchain_worker = match (&self.offchain_worker, &role) {
|
||||||
config.sentry_mode = self.sentry;
|
(OffchainWorkerEnabled::WhenValidating, sc_service::Role::Authority { .. }) => true,
|
||||||
|
|
||||||
config.offchain_worker = match (&self.offchain_worker, role) {
|
|
||||||
(OffchainWorkerEnabled::WhenValidating, sc_service::Roles::AUTHORITY) => true,
|
|
||||||
(OffchainWorkerEnabled::Always, _) => true,
|
(OffchainWorkerEnabled::Always, _) => true,
|
||||||
(OffchainWorkerEnabled::Never, _) => false,
|
(OffchainWorkerEnabled::Never, _) => false,
|
||||||
(OffchainWorkerEnabled::WhenValidating, _) => false,
|
(OffchainWorkerEnabled::WhenValidating, _) => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
config.roles = role;
|
config.role = role;
|
||||||
config.disable_grandpa = self.no_grandpa;
|
config.disable_grandpa = self.no_grandpa;
|
||||||
|
|
||||||
let client_id = config.client_id();
|
let client_id = config.client_id();
|
||||||
@@ -463,10 +463,10 @@ impl RunCmd {
|
|||||||
info!("❤️ by {}, {}-{}", version.author, version.copyright_start_year, Local::today().year());
|
info!("❤️ by {}, {}-{}", version.author, version.copyright_start_year, Local::today().year());
|
||||||
info!("📋 Chain specification: {}", config.expect_chain_spec().name());
|
info!("📋 Chain specification: {}", config.expect_chain_spec().name());
|
||||||
info!("🏷 Node name: {}", config.name);
|
info!("🏷 Node name: {}", config.name);
|
||||||
info!("👤 Roles: {}", config.display_role());
|
info!("👤 Role: {}", config.display_role());
|
||||||
|
|
||||||
match config.roles {
|
match config.role {
|
||||||
Roles::LIGHT => run_service_until_exit(
|
Role::Light => run_service_until_exit(
|
||||||
config,
|
config,
|
||||||
new_light,
|
new_light,
|
||||||
),
|
),
|
||||||
@@ -688,7 +688,7 @@ mod tests {
|
|||||||
"test",
|
"test",
|
||||||
"test-id",
|
"test-id",
|
||||||
|| (),
|
|| (),
|
||||||
vec!["boo".to_string()],
|
vec!["/ip4/127.0.0.1/tcp/30333/p2p/QmdSHZLmwEL5Axz5JvWNE2mmxU7qyd7xHBFpyUfktgAdg7".parse().unwrap()],
|
||||||
Some(TelemetryEndpoints::new(vec![("wss://foo/bar".to_string(), 42)])
|
Some(TelemetryEndpoints::new(vec![("wss://foo/bar".to_string(), 42)])
|
||||||
.expect("provided url should be valid")),
|
.expect("provided url should be valid")),
|
||||||
None,
|
None,
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ impl ImportParams {
|
|||||||
pub fn update_config(
|
pub fn update_config(
|
||||||
&self,
|
&self,
|
||||||
mut config: &mut Configuration,
|
mut config: &mut Configuration,
|
||||||
role: sc_service::Roles,
|
role: &sc_service::Role,
|
||||||
is_dev: bool,
|
is_dev: bool,
|
||||||
) -> error::Result<()> {
|
) -> error::Result<()> {
|
||||||
use sc_client_api::execution_extensions::ExecutionStrategies;
|
use sc_client_api::execution_extensions::ExecutionStrategies;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use std::iter;
|
|||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use sc_network::{
|
use sc_network::{
|
||||||
config::{NonReservedPeerMode, TransportConfig}, multiaddr::Protocol,
|
config::{MultiaddrWithPeerId, NonReservedPeerMode, TransportConfig}, multiaddr::Protocol, Multiaddr,
|
||||||
};
|
};
|
||||||
use sc_service::Configuration;
|
use sc_service::Configuration;
|
||||||
|
|
||||||
@@ -30,12 +30,12 @@ use crate::params::node_key_params::NodeKeyParams;
|
|||||||
#[derive(Debug, StructOpt, Clone)]
|
#[derive(Debug, StructOpt, Clone)]
|
||||||
pub struct NetworkConfigurationParams {
|
pub struct NetworkConfigurationParams {
|
||||||
/// Specify a list of bootnodes.
|
/// Specify a list of bootnodes.
|
||||||
#[structopt(long = "bootnodes", value_name = "URL")]
|
#[structopt(long = "bootnodes", value_name = "ADDR")]
|
||||||
pub bootnodes: Vec<String>,
|
pub bootnodes: Vec<MultiaddrWithPeerId>,
|
||||||
|
|
||||||
/// Specify a list of reserved node addresses.
|
/// Specify a list of reserved node addresses.
|
||||||
#[structopt(long = "reserved-nodes", value_name = "URL")]
|
#[structopt(long = "reserved-nodes", value_name = "ADDR")]
|
||||||
pub reserved_nodes: Vec<String>,
|
pub reserved_nodes: Vec<MultiaddrWithPeerId>,
|
||||||
|
|
||||||
/// Whether to only allow connections to/from reserved nodes.
|
/// Whether to only allow connections to/from reserved nodes.
|
||||||
///
|
///
|
||||||
@@ -47,14 +47,14 @@ pub struct NetworkConfigurationParams {
|
|||||||
/// Specify a list of sentry node public addresses.
|
/// Specify a list of sentry node public addresses.
|
||||||
#[structopt(
|
#[structopt(
|
||||||
long = "sentry-nodes",
|
long = "sentry-nodes",
|
||||||
value_name = "URL",
|
value_name = "ADDR",
|
||||||
conflicts_with_all = &[ "sentry" ]
|
conflicts_with_all = &[ "sentry" ]
|
||||||
)]
|
)]
|
||||||
pub sentry_nodes: Vec<String>,
|
pub sentry_nodes: Vec<MultiaddrWithPeerId>,
|
||||||
|
|
||||||
/// Listen on this multiaddress.
|
/// Listen on this multiaddress.
|
||||||
#[structopt(long = "listen-addr", value_name = "LISTEN_ADDR")]
|
#[structopt(long = "listen-addr", value_name = "LISTEN_ADDR")]
|
||||||
pub listen_addr: Vec<String>,
|
pub listen_addr: Vec<Multiaddr>,
|
||||||
|
|
||||||
/// Specify p2p protocol TCP port.
|
/// Specify p2p protocol TCP port.
|
||||||
///
|
///
|
||||||
@@ -117,13 +117,7 @@ impl NetworkConfigurationParams {
|
|||||||
config.network.non_reserved_mode = NonReservedPeerMode::Deny;
|
config.network.non_reserved_mode = NonReservedPeerMode::Deny;
|
||||||
}
|
}
|
||||||
|
|
||||||
config.network.sentry_nodes.extend(self.sentry_nodes.clone());
|
config.network.listen_addresses.extend(self.listen_addr.iter().cloned());
|
||||||
|
|
||||||
for addr in self.listen_addr.iter() {
|
|
||||||
let addr = addr.parse().ok().ok_or(error::Error::InvalidListenMultiaddress)?;
|
|
||||||
config.network.listen_addresses.push(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.network.listen_addresses.is_empty() {
|
if config.network.listen_addresses.is_empty() {
|
||||||
let port = match self.port {
|
let port = match self.port {
|
||||||
Some(port) => port,
|
Some(port) => port,
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ impl PruningParams {
|
|||||||
pub fn update_config(
|
pub fn update_config(
|
||||||
&self,
|
&self,
|
||||||
mut config: &mut Configuration,
|
mut config: &mut Configuration,
|
||||||
role: sc_service::Roles,
|
role: &sc_service::Role,
|
||||||
unsafe_pruning: bool,
|
unsafe_pruning: bool,
|
||||||
) -> error::Result<()> {
|
) -> error::Result<()> {
|
||||||
// by default we disable pruning if the node is an authority (i.e.
|
// by default we disable pruning if the node is an authority (i.e.
|
||||||
@@ -45,10 +45,10 @@ impl PruningParams {
|
|||||||
// unless `unsafe_pruning` is set.
|
// unless `unsafe_pruning` is set.
|
||||||
config.pruning = match &self.pruning {
|
config.pruning = match &self.pruning {
|
||||||
Some(ref s) if s == "archive" => PruningMode::ArchiveAll,
|
Some(ref s) if s == "archive" => PruningMode::ArchiveAll,
|
||||||
None if role == sc_service::Roles::AUTHORITY => PruningMode::ArchiveAll,
|
None if role.is_network_authority() => PruningMode::ArchiveAll,
|
||||||
None => PruningMode::default(),
|
None => PruningMode::default(),
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
if role == sc_service::Roles::AUTHORITY && !unsafe_pruning {
|
if role.is_network_authority() && !unsafe_pruning {
|
||||||
return Err(error::Error::Input(
|
return Err(error::Error::Input(
|
||||||
"Validators should run with state pruning disabled (i.e. archive). \
|
"Validators should run with state pruning disabled (i.e. archive). \
|
||||||
You can ignore this check with `--unsafe-pruning`.".to_string()
|
You can ignore this check with `--unsafe-pruning`.".to_string()
|
||||||
|
|||||||
@@ -84,7 +84,7 @@
|
|||||||
|
|
||||||
use sp_runtime::traits::{NumberFor, Block as BlockT, Zero};
|
use sp_runtime::traits::{NumberFor, Block as BlockT, Zero};
|
||||||
use sc_network_gossip::{MessageIntent, ValidatorContext};
|
use sc_network_gossip::{MessageIntent, ValidatorContext};
|
||||||
use sc_network::{config::Roles, PeerId, ReputationChange};
|
use sc_network::{ObservedRole, PeerId, ReputationChange};
|
||||||
use parity_scale_codec::{Encode, Decode};
|
use parity_scale_codec::{Encode, Decode};
|
||||||
use sp_finality_grandpa::AuthorityId;
|
use sp_finality_grandpa::AuthorityId;
|
||||||
|
|
||||||
@@ -439,11 +439,11 @@ impl Misbehavior {
|
|||||||
|
|
||||||
struct PeerInfo<N> {
|
struct PeerInfo<N> {
|
||||||
view: View<N>,
|
view: View<N>,
|
||||||
roles: Roles,
|
roles: ObservedRole,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N> PeerInfo<N> {
|
impl<N> PeerInfo<N> {
|
||||||
fn new(roles: Roles) -> Self {
|
fn new(roles: ObservedRole) -> Self {
|
||||||
PeerInfo {
|
PeerInfo {
|
||||||
view: View::default(),
|
view: View::default(),
|
||||||
roles,
|
roles,
|
||||||
@@ -469,14 +469,17 @@ impl<N> Default for Peers<N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Ord> Peers<N> {
|
impl<N: Ord> Peers<N> {
|
||||||
fn new_peer(&mut self, who: PeerId, roles: Roles) {
|
fn new_peer(&mut self, who: PeerId, role: ObservedRole) {
|
||||||
if roles.is_authority() && self.lucky_authorities.len() < MIN_LUCKY {
|
match role {
|
||||||
self.lucky_authorities.insert(who.clone());
|
ObservedRole::Authority if self.lucky_authorities.len() < MIN_LUCKY => {
|
||||||
|
self.lucky_authorities.insert(who.clone());
|
||||||
|
},
|
||||||
|
ObservedRole::Full | ObservedRole::Light if self.lucky_peers.len() < MIN_LUCKY => {
|
||||||
|
self.lucky_peers.insert(who.clone());
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
if !roles.is_authority() && self.lucky_peers.len() < MIN_LUCKY {
|
self.inner.insert(who, PeerInfo::new(role));
|
||||||
self.lucky_peers.insert(who.clone());
|
|
||||||
}
|
|
||||||
self.inner.insert(who, PeerInfo::new(roles));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peer_disconnected(&mut self, who: &PeerId) {
|
fn peer_disconnected(&mut self, who: &PeerId) {
|
||||||
@@ -539,21 +542,28 @@ impl<N: Ord> Peers<N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn authorities(&self) -> usize {
|
fn authorities(&self) -> usize {
|
||||||
self.inner.iter().filter(|(_, info)| info.roles.is_authority()).count()
|
// Note that our sentry and our validator are neither authorities nor non-authorities.
|
||||||
|
self.inner.iter().filter(|(_, info)| matches!(info.roles, ObservedRole::Authority)).count()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn non_authorities(&self) -> usize {
|
fn non_authorities(&self) -> usize {
|
||||||
self.inner.iter().filter(|(_, info)| !info.roles.is_authority()).count()
|
// Note that our sentry and our validator are neither authorities nor non-authorities.
|
||||||
|
self.inner
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, info)| matches!(info.roles, ObservedRole::Full | ObservedRole::Light))
|
||||||
|
.count()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reshuffle(&mut self) {
|
fn reshuffle(&mut self) {
|
||||||
let mut lucky_peers: Vec<_> = self.inner
|
let mut lucky_peers: Vec<_> = self.inner
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(id, info)| if !info.roles.is_authority() { Some(id.clone()) } else { None })
|
.filter_map(|(id, info)|
|
||||||
|
if matches!(info.roles, ObservedRole::Full | ObservedRole::Light) { Some(id.clone()) } else { None })
|
||||||
.collect();
|
.collect();
|
||||||
let mut lucky_authorities: Vec<_> = self.inner
|
let mut lucky_authorities: Vec<_> = self.inner
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(id, info)| if info.roles.is_authority() { Some(id.clone()) } else { None })
|
.filter_map(|(id, info)|
|
||||||
|
if matches!(info.roles, ObservedRole::Authority) { Some(id.clone()) } else { None })
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let num_non_authorities = ((lucky_peers.len() as f32).sqrt() as usize)
|
let num_non_authorities = ((lucky_peers.len() as f32).sqrt() as usize)
|
||||||
@@ -633,8 +643,11 @@ impl CatchUpConfig {
|
|||||||
fn request_allowed<N>(&self, peer: &PeerInfo<N>) -> bool {
|
fn request_allowed<N>(&self, peer: &PeerInfo<N>) -> bool {
|
||||||
match self {
|
match self {
|
||||||
CatchUpConfig::Disabled => false,
|
CatchUpConfig::Disabled => false,
|
||||||
CatchUpConfig::Enabled { only_from_authorities, .. } =>
|
CatchUpConfig::Enabled { only_from_authorities, .. } => match peer.roles {
|
||||||
!only_from_authorities || peer.roles.is_authority(),
|
ObservedRole::Authority | ObservedRole::OurSentry |
|
||||||
|
ObservedRole::OurGuardedAuthority => true,
|
||||||
|
_ => !only_from_authorities
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1121,34 +1134,38 @@ impl<Block: BlockT> Inner<Block> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if peer.roles.is_authority() {
|
match peer.roles {
|
||||||
let authorities = self.peers.authorities();
|
ObservedRole::OurGuardedAuthority | ObservedRole::OurSentry => true,
|
||||||
|
ObservedRole::Authority => {
|
||||||
|
let authorities = self.peers.authorities();
|
||||||
|
|
||||||
// the target node is an authority, on the first round duration we start by
|
// the target node is an authority, on the first round duration we start by
|
||||||
// sending the message to only `sqrt(authorities)` (if we're
|
// sending the message to only `sqrt(authorities)` (if we're
|
||||||
// connected to at least `MIN_LUCKY`).
|
// connected to at least `MIN_LUCKY`).
|
||||||
if round_elapsed < round_duration * PROPAGATION_ALL_AUTHORITIES
|
if round_elapsed < round_duration * PROPAGATION_ALL_AUTHORITIES
|
||||||
&& authorities > MIN_LUCKY
|
&& authorities > MIN_LUCKY
|
||||||
{
|
{
|
||||||
self.peers.lucky_authorities.contains(who)
|
self.peers.lucky_authorities.contains(who)
|
||||||
} else {
|
} else {
|
||||||
// otherwise we already went through the step above, so
|
// otherwise we already went through the step above, so
|
||||||
// we won't filter the message and send it to all
|
// we won't filter the message and send it to all
|
||||||
// authorities for whom it is polite to do so
|
// authorities for whom it is polite to do so
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
} else {
|
},
|
||||||
// the node is not an authority so we apply stricter filters
|
ObservedRole::Full | ObservedRole::Light => {
|
||||||
if round_elapsed >= round_duration * PROPAGATION_ALL {
|
// the node is not an authority so we apply stricter filters
|
||||||
// if we waited for 3 (or more) rounds
|
if round_elapsed >= round_duration * PROPAGATION_ALL {
|
||||||
// then it is allowed to be sent to all peers.
|
// if we waited for 3 (or more) rounds
|
||||||
true
|
// then it is allowed to be sent to all peers.
|
||||||
} else if round_elapsed >= round_duration * PROPAGATION_SOME_NON_AUTHORITIES {
|
true
|
||||||
// otherwise we only send it to `sqrt(non-authorities)`.
|
} else if round_elapsed >= round_duration * PROPAGATION_SOME_NON_AUTHORITIES {
|
||||||
self.peers.lucky_peers.contains(who)
|
// otherwise we only send it to `sqrt(non-authorities)`.
|
||||||
} else {
|
self.peers.lucky_peers.contains(who)
|
||||||
false
|
} else {
|
||||||
}
|
false
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1170,38 +1187,42 @@ impl<Block: BlockT> Inner<Block> {
|
|||||||
let round_duration = self.config.gossip_duration * ROUND_DURATION;
|
let round_duration = self.config.gossip_duration * ROUND_DURATION;
|
||||||
let round_elapsed = self.round_start.elapsed();
|
let round_elapsed = self.round_start.elapsed();
|
||||||
|
|
||||||
if peer.roles.is_authority() {
|
match peer.roles {
|
||||||
let authorities = self.peers.authorities();
|
ObservedRole::OurSentry | ObservedRole::OurGuardedAuthority => true,
|
||||||
|
ObservedRole::Authority => {
|
||||||
|
let authorities = self.peers.authorities();
|
||||||
|
|
||||||
// the target node is an authority, on the first round duration we start by
|
// the target node is an authority, on the first round duration we start by
|
||||||
// sending the message to only `sqrt(authorities)` (if we're
|
// sending the message to only `sqrt(authorities)` (if we're
|
||||||
// connected to at least `MIN_LUCKY`).
|
// connected to at least `MIN_LUCKY`).
|
||||||
if round_elapsed < round_duration * PROPAGATION_ALL_AUTHORITIES
|
if round_elapsed < round_duration * PROPAGATION_ALL_AUTHORITIES
|
||||||
&& authorities > MIN_LUCKY
|
&& authorities > MIN_LUCKY
|
||||||
{
|
{
|
||||||
self.peers.lucky_authorities.contains(who)
|
self.peers.lucky_authorities.contains(who)
|
||||||
} else {
|
} else {
|
||||||
// otherwise we already went through the step above, so
|
// otherwise we already went through the step above, so
|
||||||
// we won't filter the message and send it to all
|
// we won't filter the message and send it to all
|
||||||
// authorities for whom it is polite to do so
|
// authorities for whom it is polite to do so
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
} else {
|
},
|
||||||
let non_authorities = self.peers.non_authorities();
|
ObservedRole::Full | ObservedRole::Light => {
|
||||||
|
let non_authorities = self.peers.non_authorities();
|
||||||
|
|
||||||
// the target node is not an authority, on the first and second
|
// the target node is not an authority, on the first and second
|
||||||
// round duration we start by sending the message to only
|
// round duration we start by sending the message to only
|
||||||
// `sqrt(non_authorities)` (if we're connected to at least
|
// `sqrt(non_authorities)` (if we're connected to at least
|
||||||
// `MIN_LUCKY`).
|
// `MIN_LUCKY`).
|
||||||
if round_elapsed < round_duration * PROPAGATION_SOME_NON_AUTHORITIES
|
if round_elapsed < round_duration * PROPAGATION_SOME_NON_AUTHORITIES
|
||||||
&& non_authorities > MIN_LUCKY
|
&& non_authorities > MIN_LUCKY
|
||||||
{
|
{
|
||||||
self.peers.lucky_peers.contains(who)
|
self.peers.lucky_peers.contains(who)
|
||||||
} else {
|
} else {
|
||||||
// otherwise we already went through the step above, so
|
// otherwise we already went through the step above, so
|
||||||
// we won't filter the message and send it to all
|
// we won't filter the message and send it to all
|
||||||
// non-authorities for whom it is polite to do so
|
// non-authorities for whom it is polite to do so
|
||||||
true
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1397,7 +1418,7 @@ impl<Block: BlockT> GossipValidator<Block> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<Block: BlockT> sc_network_gossip::Validator<Block> for GossipValidator<Block> {
|
impl<Block: BlockT> sc_network_gossip::Validator<Block> for GossipValidator<Block> {
|
||||||
fn new_peer(&self, context: &mut dyn ValidatorContext<Block>, who: &PeerId, roles: Roles) {
|
fn new_peer(&self, context: &mut dyn ValidatorContext<Block>, who: &PeerId, roles: ObservedRole) {
|
||||||
let packet = {
|
let packet = {
|
||||||
let mut inner = self.inner.write();
|
let mut inner = self.inner.write();
|
||||||
inner.peers.new_peer(who.clone(), roles);
|
inner.peers.new_peer(who.clone(), roles);
|
||||||
@@ -1657,7 +1678,7 @@ mod tests {
|
|||||||
assert!(res.unwrap().is_none());
|
assert!(res.unwrap().is_none());
|
||||||
|
|
||||||
// connect & disconnect.
|
// connect & disconnect.
|
||||||
peers.new_peer(id.clone(), Roles::AUTHORITY);
|
peers.new_peer(id.clone(), ObservedRole::Authority);
|
||||||
peers.peer_disconnected(&id);
|
peers.peer_disconnected(&id);
|
||||||
|
|
||||||
let res = peers.update_peer_state(&id, update.clone());
|
let res = peers.update_peer_state(&id, update.clone());
|
||||||
@@ -1693,7 +1714,7 @@ mod tests {
|
|||||||
let mut peers = Peers::default();
|
let mut peers = Peers::default();
|
||||||
let id = PeerId::random();
|
let id = PeerId::random();
|
||||||
|
|
||||||
peers.new_peer(id.clone(), Roles::AUTHORITY);
|
peers.new_peer(id.clone(), ObservedRole::Authority);
|
||||||
|
|
||||||
let mut check_update = move |update: NeighborPacket<_>| {
|
let mut check_update = move |update: NeighborPacket<_>| {
|
||||||
let view = peers.update_peer_state(&id, update.clone()).unwrap().unwrap();
|
let view = peers.update_peer_state(&id, update.clone()).unwrap().unwrap();
|
||||||
@@ -1713,7 +1734,7 @@ mod tests {
|
|||||||
let mut peers = Peers::default();
|
let mut peers = Peers::default();
|
||||||
|
|
||||||
let id = PeerId::random();
|
let id = PeerId::random();
|
||||||
peers.new_peer(id.clone(), Roles::AUTHORITY);
|
peers.new_peer(id.clone(), ObservedRole::Authority);
|
||||||
|
|
||||||
peers.update_peer_state(&id, NeighborPacket {
|
peers.update_peer_state(&id, NeighborPacket {
|
||||||
round: Round(10),
|
round: Round(10),
|
||||||
@@ -1914,7 +1935,7 @@ mod tests {
|
|||||||
// add the peer making the request to the validator,
|
// add the peer making the request to the validator,
|
||||||
// otherwise it is discarded
|
// otherwise it is discarded
|
||||||
let mut inner = val.inner.write();
|
let mut inner = val.inner.write();
|
||||||
inner.peers.new_peer(peer.clone(), Roles::AUTHORITY);
|
inner.peers.new_peer(peer.clone(), ObservedRole::Authority);
|
||||||
|
|
||||||
let res = inner.handle_catch_up_request(
|
let res = inner.handle_catch_up_request(
|
||||||
&peer,
|
&peer,
|
||||||
@@ -1965,7 +1986,7 @@ mod tests {
|
|||||||
// add the peer making the request to the validator,
|
// add the peer making the request to the validator,
|
||||||
// otherwise it is discarded
|
// otherwise it is discarded
|
||||||
let peer = PeerId::random();
|
let peer = PeerId::random();
|
||||||
val.inner.write().peers.new_peer(peer.clone(), Roles::AUTHORITY);
|
val.inner.write().peers.new_peer(peer.clone(), ObservedRole::Authority);
|
||||||
|
|
||||||
let send_request = |set_id, round| {
|
let send_request = |set_id, round| {
|
||||||
let mut inner = val.inner.write();
|
let mut inner = val.inner.write();
|
||||||
@@ -2045,7 +2066,7 @@ mod tests {
|
|||||||
// add the peer making the request to the validator,
|
// add the peer making the request to the validator,
|
||||||
// otherwise it is discarded.
|
// otherwise it is discarded.
|
||||||
let peer = PeerId::random();
|
let peer = PeerId::random();
|
||||||
val.inner.write().peers.new_peer(peer.clone(), Roles::AUTHORITY);
|
val.inner.write().peers.new_peer(peer.clone(), ObservedRole::Authority);
|
||||||
|
|
||||||
let import_neighbor_message = |set_id, round| {
|
let import_neighbor_message = |set_id, round| {
|
||||||
let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message(
|
let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message(
|
||||||
@@ -2119,7 +2140,7 @@ mod tests {
|
|||||||
// add the peer making the request to the validator,
|
// add the peer making the request to the validator,
|
||||||
// otherwise it is discarded.
|
// otherwise it is discarded.
|
||||||
let peer = PeerId::random();
|
let peer = PeerId::random();
|
||||||
val.inner.write().peers.new_peer(peer.clone(), Roles::AUTHORITY);
|
val.inner.write().peers.new_peer(peer.clone(), ObservedRole::Authority);
|
||||||
|
|
||||||
// importing a neighbor message from a peer in the same set in a later
|
// importing a neighbor message from a peer in the same set in a later
|
||||||
// round should lead to a catch up request but since they're disabled
|
// round should lead to a catch up request but since they're disabled
|
||||||
@@ -2155,8 +2176,8 @@ mod tests {
|
|||||||
let peer_authority = PeerId::random();
|
let peer_authority = PeerId::random();
|
||||||
let peer_full = PeerId::random();
|
let peer_full = PeerId::random();
|
||||||
|
|
||||||
val.inner.write().peers.new_peer(peer_authority.clone(), Roles::AUTHORITY);
|
val.inner.write().peers.new_peer(peer_authority.clone(), ObservedRole::Authority);
|
||||||
val.inner.write().peers.new_peer(peer_full.clone(), Roles::FULL);
|
val.inner.write().peers.new_peer(peer_full.clone(), ObservedRole::Full);
|
||||||
|
|
||||||
let import_neighbor_message = |peer| {
|
let import_neighbor_message = |peer| {
|
||||||
let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message(
|
let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message(
|
||||||
@@ -2213,7 +2234,7 @@ mod tests {
|
|||||||
// add the peer making the requests to the validator, otherwise it is
|
// add the peer making the requests to the validator, otherwise it is
|
||||||
// discarded.
|
// discarded.
|
||||||
let peer_full = PeerId::random();
|
let peer_full = PeerId::random();
|
||||||
val.inner.write().peers.new_peer(peer_full.clone(), Roles::FULL);
|
val.inner.write().peers.new_peer(peer_full.clone(), ObservedRole::Full);
|
||||||
|
|
||||||
let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message(
|
let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message(
|
||||||
&peer_full,
|
&peer_full,
|
||||||
@@ -2290,8 +2311,8 @@ mod tests {
|
|||||||
full_nodes.resize_with(30, || PeerId::random());
|
full_nodes.resize_with(30, || PeerId::random());
|
||||||
|
|
||||||
for i in 0..30 {
|
for i in 0..30 {
|
||||||
val.inner.write().peers.new_peer(authorities[i].clone(), Roles::AUTHORITY);
|
val.inner.write().peers.new_peer(authorities[i].clone(), ObservedRole::Authority);
|
||||||
val.inner.write().peers.new_peer(full_nodes[i].clone(), Roles::FULL);
|
val.inner.write().peers.new_peer(full_nodes[i].clone(), ObservedRole::Full);
|
||||||
}
|
}
|
||||||
|
|
||||||
let test = |num_round, peers| {
|
let test = |num_round, peers| {
|
||||||
@@ -2363,7 +2384,7 @@ mod tests {
|
|||||||
let mut authorities = Vec::new();
|
let mut authorities = Vec::new();
|
||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
let peer_id = PeerId::random();
|
let peer_id = PeerId::random();
|
||||||
val.inner.write().peers.new_peer(peer_id.clone(), Roles::AUTHORITY);
|
val.inner.write().peers.new_peer(peer_id.clone(), ObservedRole::Authority);
|
||||||
authorities.push(peer_id);
|
authorities.push(peer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2403,7 +2424,7 @@ mod tests {
|
|||||||
let mut authorities = Vec::new();
|
let mut authorities = Vec::new();
|
||||||
for _ in 0..100 {
|
for _ in 0..100 {
|
||||||
let peer_id = PeerId::random();
|
let peer_id = PeerId::random();
|
||||||
val.inner.write().peers.new_peer(peer_id.clone(), Roles::AUTHORITY);
|
val.inner.write().peers.new_peer(peer_id.clone(), ObservedRole::Authority);
|
||||||
authorities.push(peer_id);
|
authorities.push(peer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2454,7 +2475,7 @@ mod tests {
|
|||||||
val.inner
|
val.inner
|
||||||
.write()
|
.write()
|
||||||
.peers
|
.peers
|
||||||
.new_peer(peer1.clone(), Roles::AUTHORITY);
|
.new_peer(peer1.clone(), ObservedRole::Authority);
|
||||||
|
|
||||||
val.inner
|
val.inner
|
||||||
.write()
|
.write()
|
||||||
@@ -2474,7 +2495,7 @@ mod tests {
|
|||||||
val.inner
|
val.inner
|
||||||
.write()
|
.write()
|
||||||
.peers
|
.peers
|
||||||
.new_peer(peer2.clone(), Roles::AUTHORITY);
|
.new_peer(peer2.clone(), ObservedRole::Authority);
|
||||||
|
|
||||||
// create a commit for round 1 of set id 1
|
// create a commit for round 1 of set id 1
|
||||||
// targeting a block at height 2
|
// targeting a block at height 2
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use sc_network::{Event as NetworkEvent, PeerId, config::Roles};
|
use sc_network::{Event as NetworkEvent, ObservedRole, PeerId};
|
||||||
use sc_network_test::{Block, Hash};
|
use sc_network_test::{Block, Hash};
|
||||||
use sc_network_gossip::Validator;
|
use sc_network_gossip::Validator;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -256,7 +256,7 @@ fn good_commit_leads_to_relay() {
|
|||||||
let test = make_test_network().0
|
let test = make_test_network().0
|
||||||
.then(move |tester| {
|
.then(move |tester| {
|
||||||
// register a peer.
|
// register a peer.
|
||||||
tester.gossip_validator.new_peer(&mut NoopContext, &id, sc_network::config::Roles::FULL);
|
tester.gossip_validator.new_peer(&mut NoopContext, &id, ObservedRole::Full);
|
||||||
future::ready((tester, id))
|
future::ready((tester, id))
|
||||||
})
|
})
|
||||||
.then(move |(tester, id)| {
|
.then(move |(tester, id)| {
|
||||||
@@ -284,7 +284,7 @@ fn good_commit_leads_to_relay() {
|
|||||||
let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened {
|
let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened {
|
||||||
remote: sender_id.clone(),
|
remote: sender_id.clone(),
|
||||||
engine_id: GRANDPA_ENGINE_ID,
|
engine_id: GRANDPA_ENGINE_ID,
|
||||||
roles: Roles::FULL,
|
role: ObservedRole::Full,
|
||||||
});
|
});
|
||||||
|
|
||||||
let _ = sender.unbounded_send(NetworkEvent::NotificationsReceived {
|
let _ = sender.unbounded_send(NetworkEvent::NotificationsReceived {
|
||||||
@@ -297,7 +297,7 @@ fn good_commit_leads_to_relay() {
|
|||||||
let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened {
|
let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened {
|
||||||
remote: receiver_id.clone(),
|
remote: receiver_id.clone(),
|
||||||
engine_id: GRANDPA_ENGINE_ID,
|
engine_id: GRANDPA_ENGINE_ID,
|
||||||
roles: Roles::FULL,
|
role: ObservedRole::Full,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Announce its local set has being on the current set id through a neighbor
|
// Announce its local set has being on the current set id through a neighbor
|
||||||
@@ -404,7 +404,7 @@ fn bad_commit_leads_to_report() {
|
|||||||
let test = make_test_network().0
|
let test = make_test_network().0
|
||||||
.map(move |tester| {
|
.map(move |tester| {
|
||||||
// register a peer.
|
// register a peer.
|
||||||
tester.gossip_validator.new_peer(&mut NoopContext, &id, sc_network::config::Roles::FULL);
|
tester.gossip_validator.new_peer(&mut NoopContext, &id, ObservedRole::Full);
|
||||||
(tester, id)
|
(tester, id)
|
||||||
})
|
})
|
||||||
.then(move |(tester, id)| {
|
.then(move |(tester, id)| {
|
||||||
@@ -431,7 +431,7 @@ fn bad_commit_leads_to_report() {
|
|||||||
let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened {
|
let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened {
|
||||||
remote: sender_id.clone(),
|
remote: sender_id.clone(),
|
||||||
engine_id: GRANDPA_ENGINE_ID,
|
engine_id: GRANDPA_ENGINE_ID,
|
||||||
roles: Roles::FULL,
|
role: ObservedRole::Full,
|
||||||
});
|
});
|
||||||
let _ = sender.unbounded_send(NetworkEvent::NotificationsReceived {
|
let _ = sender.unbounded_send(NetworkEvent::NotificationsReceived {
|
||||||
remote: sender_id.clone(),
|
remote: sender_id.clone(),
|
||||||
@@ -482,7 +482,7 @@ fn peer_with_higher_view_leads_to_catch_up_request() {
|
|||||||
let test = tester
|
let test = tester
|
||||||
.map(move |tester| {
|
.map(move |tester| {
|
||||||
// register a peer with authority role.
|
// register a peer with authority role.
|
||||||
tester.gossip_validator.new_peer(&mut NoopContext, &id, sc_network::config::Roles::AUTHORITY);
|
tester.gossip_validator.new_peer(&mut NoopContext, &id, ObservedRole::Authority);
|
||||||
(tester, id)
|
(tester, id)
|
||||||
})
|
})
|
||||||
.then(move |(tester, id)| {
|
.then(move |(tester, id)| {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use sc_network_test::{
|
|||||||
Block, Hash, TestNetFactory, BlockImportAdapter, Peer,
|
Block, Hash, TestNetFactory, BlockImportAdapter, Peer,
|
||||||
PeersClient, PassThroughVerifier, PeersFullClient,
|
PeersClient, PassThroughVerifier, PeersFullClient,
|
||||||
};
|
};
|
||||||
use sc_network::config::{ProtocolConfig, Roles, BoxFinalityProofRequestBuilder};
|
use sc_network::config::{ProtocolConfig, BoxFinalityProofRequestBuilder};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use futures_timer::Delay;
|
use futures_timer::Delay;
|
||||||
use tokio::runtime::{Runtime, Handle};
|
use tokio::runtime::{Runtime, Handle};
|
||||||
@@ -74,9 +74,8 @@ impl GrandpaTestNet {
|
|||||||
peers: Vec::with_capacity(n_peers),
|
peers: Vec::with_capacity(n_peers),
|
||||||
test_config,
|
test_config,
|
||||||
};
|
};
|
||||||
let config = Self::default_config();
|
|
||||||
for _ in 0..n_peers {
|
for _ in 0..n_peers {
|
||||||
net.add_full_peer(&config);
|
net.add_full_peer();
|
||||||
}
|
}
|
||||||
net
|
net
|
||||||
}
|
}
|
||||||
@@ -95,10 +94,8 @@ impl TestNetFactory for GrandpaTestNet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn default_config() -> ProtocolConfig {
|
fn default_config() -> ProtocolConfig {
|
||||||
// the authority role ensures gossip hits all nodes here.
|
// This is unused.
|
||||||
let mut config = ProtocolConfig::default();
|
ProtocolConfig::default()
|
||||||
config.roles = Roles::AUTHORITY;
|
|
||||||
config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_verifier(
|
fn make_verifier(
|
||||||
@@ -1303,7 +1300,7 @@ fn finality_proof_is_fetched_by_light_client_when_consensus_data_changes() {
|
|||||||
|
|
||||||
let peers = &[Ed25519Keyring::Alice];
|
let peers = &[Ed25519Keyring::Alice];
|
||||||
let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 1);
|
let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 1);
|
||||||
net.add_light_peer(&GrandpaTestNet::default_config());
|
net.add_light_peer();
|
||||||
|
|
||||||
// import block#1 WITH consensus data change. Light client ignores justification
|
// import block#1 WITH consensus data change. Light client ignores justification
|
||||||
// && instead fetches finality proof for block #1
|
// && instead fetches finality proof for block #1
|
||||||
@@ -1380,7 +1377,7 @@ fn empty_finality_proof_is_returned_to_light_client_when_authority_set_is_differ
|
|||||||
run_to_completion(&mut runtime, 11, net.clone(), peers_a);
|
run_to_completion(&mut runtime, 11, net.clone(), peers_a);
|
||||||
|
|
||||||
// request finalization by light client
|
// request finalization by light client
|
||||||
net.lock().add_light_peer(&GrandpaTestNet::default_config());
|
net.lock().add_light_peer();
|
||||||
net.lock().block_until_sync();
|
net.lock().block_until_sync();
|
||||||
|
|
||||||
// check block, finalized on light client
|
// check block, finalized on light client
|
||||||
|
|||||||
@@ -137,11 +137,11 @@ impl<B: BlockT> Future for GossipEngine<B> {
|
|||||||
loop {
|
loop {
|
||||||
match this.network_event_stream.poll_next_unpin(cx) {
|
match this.network_event_stream.poll_next_unpin(cx) {
|
||||||
Poll::Ready(Some(event)) => match event {
|
Poll::Ready(Some(event)) => match event {
|
||||||
Event::NotificationStreamOpened { remote, engine_id: msg_engine_id, roles } => {
|
Event::NotificationStreamOpened { remote, engine_id: msg_engine_id, role } => {
|
||||||
if msg_engine_id != this.engine_id {
|
if msg_engine_id != this.engine_id {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this.state_machine.new_peer(&mut *this.network, remote, roles);
|
this.state_machine.new_peer(&mut *this.network, remote, role);
|
||||||
}
|
}
|
||||||
Event::NotificationStreamClosed { remote, engine_id: msg_engine_id } => {
|
Event::NotificationStreamClosed { remote, engine_id: msg_engine_id } => {
|
||||||
if msg_engine_id != this.engine_id {
|
if msg_engine_id != this.engine_id {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ use lru::LruCache;
|
|||||||
use libp2p::PeerId;
|
use libp2p::PeerId;
|
||||||
use sp_runtime::traits::{Block as BlockT, Hash, HashFor};
|
use sp_runtime::traits::{Block as BlockT, Hash, HashFor};
|
||||||
use sp_runtime::ConsensusEngineId;
|
use sp_runtime::ConsensusEngineId;
|
||||||
use sc_network::config::Roles;
|
use sc_network::ObservedRole;
|
||||||
use wasm_timer::Instant;
|
use wasm_timer::Instant;
|
||||||
|
|
||||||
// FIXME: Add additional spam/DoS attack protection: https://github.com/paritytech/substrate/issues/1115
|
// FIXME: Add additional spam/DoS attack protection: https://github.com/paritytech/substrate/issues/1115
|
||||||
@@ -51,7 +51,7 @@ mod rep {
|
|||||||
|
|
||||||
struct PeerConsensus<H> {
|
struct PeerConsensus<H> {
|
||||||
known_messages: HashSet<H>,
|
known_messages: HashSet<H>,
|
||||||
roles: Roles,
|
role: ObservedRole,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Topic stream message with sender.
|
/// Topic stream message with sender.
|
||||||
@@ -192,10 +192,10 @@ impl<B: BlockT> ConsensusGossip<B> {
|
|||||||
validator: Arc<dyn Validator<B>>
|
validator: Arc<dyn Validator<B>>
|
||||||
) {
|
) {
|
||||||
self.register_validator_internal(engine_id, validator.clone());
|
self.register_validator_internal(engine_id, validator.clone());
|
||||||
let peers: Vec<_> = self.peers.iter().map(|(id, peer)| (id.clone(), peer.roles)).collect();
|
let peers: Vec<_> = self.peers.iter().map(|(id, peer)| (id.clone(), peer.role.clone())).collect();
|
||||||
for (id, roles) in peers {
|
for (id, role) in peers {
|
||||||
let mut context = NetworkContext { gossip: self, network, engine_id: engine_id.clone() };
|
let mut context = NetworkContext { gossip: self, network, engine_id: engine_id.clone() };
|
||||||
validator.new_peer(&mut context, &id, roles);
|
validator.new_peer(&mut context, &id, role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,20 +204,20 @@ impl<B: BlockT> ConsensusGossip<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Handle new connected peer.
|
/// Handle new connected peer.
|
||||||
pub fn new_peer(&mut self, network: &mut dyn Network<B>, who: PeerId, roles: Roles) {
|
pub fn new_peer(&mut self, network: &mut dyn Network<B>, who: PeerId, role: ObservedRole) {
|
||||||
// light nodes are not valid targets for consensus gossip messages
|
// light nodes are not valid targets for consensus gossip messages
|
||||||
if !roles.is_full() {
|
if role.is_light() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!(target:"gossip", "Registering {:?} {}", roles, who);
|
trace!(target:"gossip", "Registering {:?} {}", role, who);
|
||||||
self.peers.insert(who.clone(), PeerConsensus {
|
self.peers.insert(who.clone(), PeerConsensus {
|
||||||
known_messages: HashSet::new(),
|
known_messages: HashSet::new(),
|
||||||
roles,
|
role: role.clone(),
|
||||||
});
|
});
|
||||||
for (engine_id, v) in self.validators.clone() {
|
for (engine_id, v) in self.validators.clone() {
|
||||||
let mut context = NetworkContext { gossip: self, network, engine_id: engine_id.clone() };
|
let mut context = NetworkContext { gossip: self, network, engine_id: engine_id.clone() };
|
||||||
v.new_peer(&mut context, &who, roles);
|
v.new_peer(&mut context, &who, role.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,7 +696,7 @@ mod tests {
|
|||||||
let mut network = TestNetwork;
|
let mut network = TestNetwork;
|
||||||
|
|
||||||
let peer_id = PeerId::random();
|
let peer_id = PeerId::random();
|
||||||
consensus.new_peer(&mut network, peer_id.clone(), Roles::FULL);
|
consensus.new_peer(&mut network, peer_id.clone(), ObservedRole::Full);
|
||||||
assert!(consensus.peers.contains_key(&peer_id));
|
assert!(consensus.peers.contains_key(&peer_id));
|
||||||
|
|
||||||
consensus.peer_disconnected(&mut network, peer_id.clone());
|
consensus.peer_disconnected(&mut network, peer_id.clone());
|
||||||
|
|||||||
@@ -14,13 +14,13 @@
|
|||||||
// 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use sc_network::{config::Roles, PeerId};
|
use sc_network::{ObservedRole, PeerId};
|
||||||
use sp_runtime::traits::Block as BlockT;
|
use sp_runtime::traits::Block as BlockT;
|
||||||
|
|
||||||
/// Validates consensus messages.
|
/// Validates consensus messages.
|
||||||
pub trait Validator<B: BlockT>: Send + Sync {
|
pub trait Validator<B: BlockT>: Send + Sync {
|
||||||
/// New peer is connected.
|
/// New peer is connected.
|
||||||
fn new_peer(&self, _context: &mut dyn ValidatorContext<B>, _who: &PeerId, _roles: Roles) {
|
fn new_peer(&self, _context: &mut dyn ValidatorContext<B>, _who: &PeerId, _role: ObservedRole) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// New connection is dropped.
|
/// New connection is dropped.
|
||||||
|
|||||||
@@ -15,18 +15,19 @@
|
|||||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
config::Role,
|
||||||
debug_info, discovery::DiscoveryBehaviour, discovery::DiscoveryOut,
|
debug_info, discovery::DiscoveryBehaviour, discovery::DiscoveryOut,
|
||||||
Event, protocol::event::DhtEvent, ExHashT,
|
Event, ObservedRole, DhtEvent, ExHashT,
|
||||||
};
|
};
|
||||||
use crate::protocol::{self, light_client_handler, CustomMessageOutcome, Protocol};
|
use crate::protocol::{self, light_client_handler, message::Roles, CustomMessageOutcome, Protocol};
|
||||||
use libp2p::NetworkBehaviour;
|
use libp2p::NetworkBehaviour;
|
||||||
use libp2p::core::{Multiaddr, PeerId, PublicKey};
|
use libp2p::core::{Multiaddr, PeerId, PublicKey};
|
||||||
use libp2p::kad::record;
|
use libp2p::kad::record;
|
||||||
use libp2p::swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters};
|
use libp2p::swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use sp_consensus::{BlockOrigin, import_queue::{IncomingBlock, Origin}};
|
use sp_consensus::{BlockOrigin, import_queue::{IncomingBlock, Origin}};
|
||||||
use sp_runtime::{traits::{Block as BlockT, NumberFor}, Justification};
|
use sp_runtime::{traits::{Block as BlockT, NumberFor}, ConsensusEngineId, Justification};
|
||||||
use std::{iter, task::Context, task::Poll};
|
use std::{borrow::Cow, iter, task::Context, task::Poll};
|
||||||
use void;
|
use void;
|
||||||
|
|
||||||
/// General behaviour of the network. Combines all protocols together.
|
/// General behaviour of the network. Combines all protocols together.
|
||||||
@@ -44,9 +45,14 @@ pub struct Behaviour<B: BlockT, H: ExHashT> {
|
|||||||
block_requests: protocol::BlockRequests<B>,
|
block_requests: protocol::BlockRequests<B>,
|
||||||
/// Light client request handling.
|
/// Light client request handling.
|
||||||
light_client_handler: protocol::LightClientHandler<B>,
|
light_client_handler: protocol::LightClientHandler<B>,
|
||||||
|
|
||||||
/// Queue of events to produce for the outside.
|
/// Queue of events to produce for the outside.
|
||||||
#[behaviour(ignore)]
|
#[behaviour(ignore)]
|
||||||
events: Vec<BehaviourOut<B>>,
|
events: Vec<BehaviourOut<B>>,
|
||||||
|
|
||||||
|
/// Role of our local node, as originally passed from the configuration.
|
||||||
|
#[behaviour(ignore)]
|
||||||
|
role: Role,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Event generated by `Behaviour`.
|
/// Event generated by `Behaviour`.
|
||||||
@@ -63,6 +69,7 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
|
|||||||
/// Builds a new `Behaviour`.
|
/// Builds a new `Behaviour`.
|
||||||
pub async fn new(
|
pub async fn new(
|
||||||
substrate: Protocol<B, H>,
|
substrate: Protocol<B, H>,
|
||||||
|
role: Role,
|
||||||
user_agent: String,
|
user_agent: String,
|
||||||
local_public_key: PublicKey,
|
local_public_key: PublicKey,
|
||||||
known_addresses: Vec<(PeerId, Multiaddr)>,
|
known_addresses: Vec<(PeerId, Multiaddr)>,
|
||||||
@@ -84,7 +91,8 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
|
|||||||
).await,
|
).await,
|
||||||
block_requests,
|
block_requests,
|
||||||
light_client_handler,
|
light_client_handler,
|
||||||
events: Vec::new()
|
events: Vec::new(),
|
||||||
|
role,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +120,32 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
|
|||||||
self.debug_info.node(peer_id)
|
self.debug_info.node(peer_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Registers a new notifications protocol.
|
||||||
|
///
|
||||||
|
/// After that, you can call `write_notifications`.
|
||||||
|
///
|
||||||
|
/// Please call `event_stream` before registering a protocol, otherwise you may miss events
|
||||||
|
/// about the protocol that you have registered.
|
||||||
|
///
|
||||||
|
/// You are very strongly encouraged to call this method very early on. Any connection open
|
||||||
|
/// will retain the protocols that were registered then, and not any new one.
|
||||||
|
pub fn register_notifications_protocol(
|
||||||
|
&mut self,
|
||||||
|
engine_id: ConsensusEngineId,
|
||||||
|
protocol_name: impl Into<Cow<'static, [u8]>>,
|
||||||
|
) {
|
||||||
|
let list = self.substrate.register_notifications_protocol(engine_id, protocol_name);
|
||||||
|
for (remote, roles) in list {
|
||||||
|
let role = reported_roles_to_observed_role(&self.role, remote, roles);
|
||||||
|
let ev = Event::NotificationStreamOpened {
|
||||||
|
remote: remote.clone(),
|
||||||
|
engine_id,
|
||||||
|
role,
|
||||||
|
};
|
||||||
|
self.events.push(BehaviourOut::Event(ev));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a shared reference to the user protocol.
|
/// Returns a shared reference to the user protocol.
|
||||||
pub fn user_protocol(&self) -> &Protocol<B, H> {
|
pub fn user_protocol(&self) -> &Protocol<B, H> {
|
||||||
&self.substrate
|
&self.substrate
|
||||||
@@ -138,6 +172,22 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reported_roles_to_observed_role(local_role: &Role, remote: &PeerId, roles: Roles) -> ObservedRole {
|
||||||
|
if roles.is_authority() {
|
||||||
|
match local_role {
|
||||||
|
Role::Authority { sentry_nodes }
|
||||||
|
if sentry_nodes.iter().any(|s| s.peer_id == *remote) => ObservedRole::OurSentry,
|
||||||
|
Role::Sentry { validators }
|
||||||
|
if validators.iter().any(|s| s.peer_id == *remote) => ObservedRole::OurGuardedAuthority,
|
||||||
|
_ => ObservedRole::Authority
|
||||||
|
}
|
||||||
|
} else if roles.is_full() {
|
||||||
|
ObservedRole::Full
|
||||||
|
} else {
|
||||||
|
ObservedRole::Light
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<B: BlockT, H: ExHashT> NetworkBehaviourEventProcess<void::Void> for
|
impl<B: BlockT, H: ExHashT> NetworkBehaviourEventProcess<void::Void> for
|
||||||
Behaviour<B, H> {
|
Behaviour<B, H> {
|
||||||
fn inject_event(&mut self, event: void::Void) {
|
fn inject_event(&mut self, event: void::Void) {
|
||||||
@@ -155,14 +205,16 @@ Behaviour<B, H> {
|
|||||||
self.events.push(BehaviourOut::JustificationImport(origin, hash, nb, justification)),
|
self.events.push(BehaviourOut::JustificationImport(origin, hash, nb, justification)),
|
||||||
CustomMessageOutcome::FinalityProofImport(origin, hash, nb, proof) =>
|
CustomMessageOutcome::FinalityProofImport(origin, hash, nb, proof) =>
|
||||||
self.events.push(BehaviourOut::FinalityProofImport(origin, hash, nb, proof)),
|
self.events.push(BehaviourOut::FinalityProofImport(origin, hash, nb, proof)),
|
||||||
CustomMessageOutcome::NotificationStreamOpened { remote, protocols, roles } =>
|
CustomMessageOutcome::NotificationStreamOpened { remote, protocols, roles } => {
|
||||||
|
let role = reported_roles_to_observed_role(&self.role, &remote, roles);
|
||||||
for engine_id in protocols {
|
for engine_id in protocols {
|
||||||
self.events.push(BehaviourOut::Event(Event::NotificationStreamOpened {
|
self.events.push(BehaviourOut::Event(Event::NotificationStreamOpened {
|
||||||
remote: remote.clone(),
|
remote: remote.clone(),
|
||||||
engine_id,
|
engine_id,
|
||||||
roles,
|
role: role.clone(),
|
||||||
}));
|
}));
|
||||||
},
|
}
|
||||||
|
},
|
||||||
CustomMessageOutcome::NotificationStreamClosed { remote, protocols } =>
|
CustomMessageOutcome::NotificationStreamClosed { remote, protocols } =>
|
||||||
for engine_id in protocols {
|
for engine_id in protocols {
|
||||||
self.events.push(BehaviourOut::Event(Event::NotificationStreamClosed {
|
self.events.push(BehaviourOut::Event(Event::NotificationStreamClosed {
|
||||||
|
|||||||
@@ -31,23 +31,21 @@ pub use crate::protocol::ProtocolConfig;
|
|||||||
|
|
||||||
use crate::service::ExHashT;
|
use crate::service::ExHashT;
|
||||||
|
|
||||||
use bitflags::bitflags;
|
|
||||||
use sp_consensus::{block_validation::BlockAnnounceValidator, import_queue::ImportQueue};
|
use sp_consensus::{block_validation::BlockAnnounceValidator, import_queue::ImportQueue};
|
||||||
use sp_runtime::traits::{Block as BlockT};
|
use sp_runtime::traits::{Block as BlockT};
|
||||||
use libp2p::identity::{Keypair, ed25519};
|
use libp2p::identity::{Keypair, ed25519};
|
||||||
use libp2p::wasm_ext;
|
use libp2p::wasm_ext;
|
||||||
use libp2p::{PeerId, Multiaddr, multiaddr};
|
use libp2p::{PeerId, Multiaddr, multiaddr};
|
||||||
use core::{fmt, iter};
|
use core::{fmt, iter};
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{convert::TryFrom, future::Future, pin::Pin, str::FromStr};
|
||||||
use std::{error::Error, fs, io::{self, Write}, net::Ipv4Addr, path::{Path, PathBuf}, sync::Arc};
|
use std::{error::Error, fs, io::{self, Write}, net::Ipv4Addr, path::{Path, PathBuf}, sync::Arc};
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
use prometheus_endpoint::Registry;
|
use prometheus_endpoint::Registry;
|
||||||
|
|
||||||
|
|
||||||
/// Network initialization parameters.
|
/// Network initialization parameters.
|
||||||
pub struct Params<B: BlockT, H: ExHashT> {
|
pub struct Params<B: BlockT, H: ExHashT> {
|
||||||
/// Assigned roles for our node (full, light, ...).
|
/// Assigned role for our node (full, light, ...).
|
||||||
pub roles: Roles,
|
pub role: Role,
|
||||||
|
|
||||||
/// How to spawn background tasks. If you pass `None`, then a threads pool will be used by
|
/// How to spawn background tasks. If you pass `None`, then a threads pool will be used by
|
||||||
/// default.
|
/// default.
|
||||||
@@ -97,54 +95,48 @@ pub struct Params<B: BlockT, H: ExHashT> {
|
|||||||
pub metrics_registry: Option<Registry>,
|
pub metrics_registry: Option<Registry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
/// Role of the local node.
|
||||||
/// Bitmask of the roles that a node fulfills.
|
#[derive(Debug, Clone)]
|
||||||
pub struct Roles: u8 {
|
pub enum Role {
|
||||||
/// No network.
|
/// Regular full node.
|
||||||
const NONE = 0b00000000;
|
Full,
|
||||||
/// Full node, does not participate in consensus.
|
/// Regular light node.
|
||||||
const FULL = 0b00000001;
|
Light,
|
||||||
/// Light client node.
|
/// Sentry node that guards an authority. Will be reported as "authority" on the wire protocol.
|
||||||
const LIGHT = 0b00000010;
|
Sentry {
|
||||||
/// Act as an authority
|
/// Address and identity of the validator nodes that we're guarding.
|
||||||
const AUTHORITY = 0b00000100;
|
///
|
||||||
|
/// The nodes will be granted some priviledged status.
|
||||||
|
validators: Vec<MultiaddrWithPeerId>,
|
||||||
|
},
|
||||||
|
/// Actual authority.
|
||||||
|
Authority {
|
||||||
|
/// List of public addresses and identities of our sentry nodes.
|
||||||
|
sentry_nodes: Vec<MultiaddrWithPeerId>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Roles {
|
impl Role {
|
||||||
/// Does this role represents a client that holds full chain data locally?
|
/// True for `Role::Authority`
|
||||||
pub fn is_full(&self) -> bool {
|
|
||||||
self.intersects(Roles::FULL | Roles::AUTHORITY)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Does this role represents a client that does not participates in the consensus?
|
|
||||||
pub fn is_authority(&self) -> bool {
|
pub fn is_authority(&self) -> bool {
|
||||||
*self == Roles::AUTHORITY
|
matches!(self, Role::Authority { .. })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Does this role represents a client that does not hold full chain data locally?
|
/// True for `Role::Authority` and `Role::Sentry` since they're both
|
||||||
pub fn is_light(&self) -> bool {
|
/// announced as having the authority role to the network.
|
||||||
!self.is_full()
|
pub fn is_network_authority(&self) -> bool {
|
||||||
|
matches!(self, Role::Authority { .. } | Role::Sentry { .. })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Roles {
|
impl fmt::Display for Role {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{:?}", self)
|
match self {
|
||||||
}
|
Role::Full => write!(f, "FULL"),
|
||||||
}
|
Role::Light => write!(f, "LIGHT"),
|
||||||
|
Role::Sentry { .. } => write!(f, "SENTRY"),
|
||||||
impl codec::Encode for Roles {
|
Role::Authority { .. } => write!(f, "AUTHORITY"),
|
||||||
fn encode_to<T: codec::Output>(&self, dest: &mut T) {
|
}
|
||||||
dest.push_byte(self.bits())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl codec::EncodeLike for Roles {}
|
|
||||||
|
|
||||||
impl codec::Decode for Roles {
|
|
||||||
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
|
|
||||||
Self::from_bits(input.read_byte()?).ok_or_else(|| codec::Error::from("Invalid bytes"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,6 +206,67 @@ pub fn parse_addr(mut addr: Multiaddr)-> Result<(PeerId, Multiaddr), ParseErr> {
|
|||||||
Ok((who, addr))
|
Ok((who, addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Address of a node, including its identity.
|
||||||
|
///
|
||||||
|
/// This struct represents a decoded version of a multiaddress that ends with `/p2p/<peerid>`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use sc_network::{Multiaddr, PeerId, config::MultiaddrWithPeerId};
|
||||||
|
/// let addr: MultiaddrWithPeerId =
|
||||||
|
/// "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".parse().unwrap();
|
||||||
|
/// assert_eq!(addr.peer_id.to_base58(), "QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV");
|
||||||
|
/// assert_eq!(addr.multiaddr.to_string(), "/ip4/198.51.100.19/tcp/30333");
|
||||||
|
/// ```
|
||||||
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
#[serde(try_from = "String", into = "String")]
|
||||||
|
pub struct MultiaddrWithPeerId {
|
||||||
|
/// Address of the node.
|
||||||
|
pub multiaddr: Multiaddr,
|
||||||
|
/// Its identity.
|
||||||
|
pub peer_id: PeerId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MultiaddrWithPeerId {
|
||||||
|
/// Concatenates the multiaddress and peer ID into one multiaddress containing both.
|
||||||
|
pub fn concat(&self) -> Multiaddr {
|
||||||
|
let proto = multiaddr::Protocol::P2p(From::from(self.peer_id.clone()));
|
||||||
|
self.multiaddr.clone().with(proto)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for MultiaddrWithPeerId {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt::Display::fmt(&self.concat(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for MultiaddrWithPeerId {
|
||||||
|
type Err = ParseErr;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let (peer_id, multiaddr) = parse_str_addr(s)?;
|
||||||
|
Ok(MultiaddrWithPeerId {
|
||||||
|
peer_id,
|
||||||
|
multiaddr,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<MultiaddrWithPeerId> for String {
|
||||||
|
fn from(ma: MultiaddrWithPeerId) -> String {
|
||||||
|
format!("{}", ma)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<String> for MultiaddrWithPeerId {
|
||||||
|
type Error = ParseErr;
|
||||||
|
fn try_from(string: String) -> Result<Self, Self::Error> {
|
||||||
|
string.parse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Error that can be generated by `parse_str_addr`.
|
/// Error that can be generated by `parse_str_addr`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ParseErr {
|
pub enum ParseErr {
|
||||||
@@ -263,7 +316,7 @@ pub struct NetworkConfiguration {
|
|||||||
/// Multiaddresses to advertise. Detected automatically if empty.
|
/// Multiaddresses to advertise. Detected automatically if empty.
|
||||||
pub public_addresses: Vec<Multiaddr>,
|
pub public_addresses: Vec<Multiaddr>,
|
||||||
/// List of initial node addresses
|
/// List of initial node addresses
|
||||||
pub boot_nodes: Vec<String>,
|
pub boot_nodes: Vec<MultiaddrWithPeerId>,
|
||||||
/// The node key configuration, which determines the node's network identity keypair.
|
/// The node key configuration, which determines the node's network identity keypair.
|
||||||
pub node_key: NodeKeyConfig,
|
pub node_key: NodeKeyConfig,
|
||||||
/// Maximum allowed number of incoming connections.
|
/// Maximum allowed number of incoming connections.
|
||||||
@@ -271,11 +324,9 @@ pub struct NetworkConfiguration {
|
|||||||
/// Number of outgoing connections we're trying to maintain.
|
/// Number of outgoing connections we're trying to maintain.
|
||||||
pub out_peers: u32,
|
pub out_peers: u32,
|
||||||
/// List of reserved node addresses.
|
/// List of reserved node addresses.
|
||||||
pub reserved_nodes: Vec<String>,
|
pub reserved_nodes: Vec<MultiaddrWithPeerId>,
|
||||||
/// The non-reserved peer mode.
|
/// The non-reserved peer mode.
|
||||||
pub non_reserved_mode: NonReservedPeerMode,
|
pub non_reserved_mode: NonReservedPeerMode,
|
||||||
/// List of sentry node public addresses.
|
|
||||||
pub sentry_nodes: Vec<String>,
|
|
||||||
/// Client identifier. Sent over the wire for debugging purposes.
|
/// Client identifier. Sent over the wire for debugging purposes.
|
||||||
pub client_version: String,
|
pub client_version: String,
|
||||||
/// Name of the node. Sent over the wire for debugging purposes.
|
/// Name of the node. Sent over the wire for debugging purposes.
|
||||||
@@ -299,7 +350,6 @@ impl Default for NetworkConfiguration {
|
|||||||
out_peers: 75,
|
out_peers: 75,
|
||||||
reserved_nodes: Vec::new(),
|
reserved_nodes: Vec::new(),
|
||||||
non_reserved_mode: NonReservedPeerMode::Accept,
|
non_reserved_mode: NonReservedPeerMode::Accept,
|
||||||
sentry_nodes: Vec::new(),
|
|
||||||
client_version: "unknown".into(),
|
client_version: "unknown".into(),
|
||||||
node_name: "unknown".into(),
|
node_name: "unknown".into(),
|
||||||
transport: TransportConfig::Normal {
|
transport: TransportConfig::Normal {
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ pub mod network_state;
|
|||||||
|
|
||||||
pub use service::{NetworkService, NetworkStateInfo, NetworkWorker, ExHashT, ReportHandle};
|
pub use service::{NetworkService, NetworkStateInfo, NetworkWorker, ExHashT, ReportHandle};
|
||||||
pub use protocol::PeerInfo;
|
pub use protocol::PeerInfo;
|
||||||
pub use protocol::event::{Event, DhtEvent};
|
pub use protocol::event::{Event, DhtEvent, ObservedRole};
|
||||||
pub use protocol::sync::SyncState;
|
pub use protocol::sync::SyncState;
|
||||||
pub use libp2p::{Multiaddr, PeerId};
|
pub use libp2p::{Multiaddr, PeerId};
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
|
|||||||
@@ -39,11 +39,11 @@ use sp_runtime::traits::{
|
|||||||
};
|
};
|
||||||
use sp_arithmetic::traits::SaturatedConversion;
|
use sp_arithmetic::traits::SaturatedConversion;
|
||||||
use message::{BlockAnnounce, Message};
|
use message::{BlockAnnounce, Message};
|
||||||
use message::generic::{Message as GenericMessage, ConsensusMessage};
|
use message::generic::{Message as GenericMessage, ConsensusMessage, Roles};
|
||||||
use prometheus_endpoint::{Registry, Gauge, GaugeVec, HistogramVec, PrometheusError, Opts, register, U64};
|
use prometheus_endpoint::{Registry, Gauge, GaugeVec, HistogramVec, PrometheusError, Opts, register, U64};
|
||||||
use sync::{ChainSync, SyncState};
|
use sync::{ChainSync, SyncState};
|
||||||
use crate::service::{TransactionPool, ExHashT};
|
use crate::service::{TransactionPool, ExHashT};
|
||||||
use crate::config::{BoxFinalityProofRequestBuilder, Roles};
|
use crate::config::BoxFinalityProofRequestBuilder;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
|
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -338,7 +338,7 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
|
|||||||
|
|
||||||
let important_peers = {
|
let important_peers = {
|
||||||
let mut imp_p = HashSet::new();
|
let mut imp_p = HashSet::new();
|
||||||
for reserved in &peerset_config.reserved_nodes {
|
for reserved in peerset_config.priority_groups.iter().flat_map(|(_, l)| l.iter()) {
|
||||||
imp_p.insert(reserved.clone());
|
imp_p.insert(reserved.clone());
|
||||||
}
|
}
|
||||||
imp_p.shrink_to_fit();
|
imp_p.shrink_to_fit();
|
||||||
@@ -1033,13 +1033,14 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
|
|||||||
|
|
||||||
/// Registers a new notifications protocol.
|
/// Registers a new notifications protocol.
|
||||||
///
|
///
|
||||||
/// You are very strongly encouraged to call this method very early on. Any connection open
|
/// While registering a protocol while we already have open connections is discouraged, we
|
||||||
/// will retain the protocols that were registered then, and not any new one.
|
/// nonetheless handle it by notifying that we opened channels with everyone. This function
|
||||||
pub fn register_notifications_protocol(
|
/// returns a list of substreams to open as a result.
|
||||||
&mut self,
|
pub fn register_notifications_protocol<'a>(
|
||||||
|
&'a mut self,
|
||||||
engine_id: ConsensusEngineId,
|
engine_id: ConsensusEngineId,
|
||||||
protocol_name: impl Into<Cow<'static, [u8]>>,
|
protocol_name: impl Into<Cow<'static, [u8]>>,
|
||||||
) -> Vec<event::Event> {
|
) -> impl ExactSizeIterator<Item = (&'a PeerId, Roles)> + 'a {
|
||||||
let protocol_name = protocol_name.into();
|
let protocol_name = protocol_name.into();
|
||||||
if self.protocol_name_by_engine.insert(engine_id, protocol_name.clone()).is_some() {
|
if self.protocol_name_by_engine.insert(engine_id, protocol_name.clone()).is_some() {
|
||||||
error!(target: "sub-libp2p", "Notifications protocol already registered: {:?}", protocol_name);
|
error!(target: "sub-libp2p", "Notifications protocol already registered: {:?}", protocol_name);
|
||||||
@@ -1048,16 +1049,8 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
|
|||||||
self.legacy_equiv_by_name.insert(protocol_name, Fallback::Consensus(engine_id));
|
self.legacy_equiv_by_name.insert(protocol_name, Fallback::Consensus(engine_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registering a protocol while we already have open connections isn't great, but for now
|
|
||||||
// we handle it by notifying that we opened channels with everyone.
|
|
||||||
self.context_data.peers.iter()
|
self.context_data.peers.iter()
|
||||||
.map(|(peer_id, peer)|
|
.map(|(peer_id, peer)| (peer_id, peer.info.roles))
|
||||||
event::Event::NotificationStreamOpened {
|
|
||||||
remote: peer_id.clone(),
|
|
||||||
engine_id,
|
|
||||||
roles: peer.info.roles,
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when peer sends us new extrinsics
|
/// Called when peer sends us new extrinsics
|
||||||
@@ -2021,7 +2014,7 @@ impl<B: BlockT, H: ExHashT> Drop for Protocol<B, H> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::PeerId;
|
use crate::PeerId;
|
||||||
use crate::config::{EmptyTransactionPool, Roles};
|
use crate::config::EmptyTransactionPool;
|
||||||
use super::{CustomMessageOutcome, Protocol, ProtocolConfig};
|
use super::{CustomMessageOutcome, Protocol, ProtocolConfig};
|
||||||
|
|
||||||
use sp_consensus::block_validation::DefaultBlockAnnounceValidator;
|
use sp_consensus::block_validation::DefaultBlockAnnounceValidator;
|
||||||
@@ -2034,10 +2027,7 @@ mod tests {
|
|||||||
let client = Arc::new(TestClientBuilder::with_default_backend().build_with_longest_chain().0);
|
let client = Arc::new(TestClientBuilder::with_default_backend().build_with_longest_chain().0);
|
||||||
|
|
||||||
let (mut protocol, _) = Protocol::<Block, Hash>::new(
|
let (mut protocol, _) = Protocol::<Block, Hash>::new(
|
||||||
ProtocolConfig {
|
ProtocolConfig::default(),
|
||||||
roles: Roles::FULL,
|
|
||||||
max_parallel_downloads: 10,
|
|
||||||
},
|
|
||||||
client.clone(),
|
client.clone(),
|
||||||
Arc::new(EmptyTransactionPool),
|
Arc::new(EmptyTransactionPool),
|
||||||
None,
|
None,
|
||||||
@@ -2048,7 +2038,7 @@ mod tests {
|
|||||||
out_peers: 10,
|
out_peers: 10,
|
||||||
bootnodes: Vec::new(),
|
bootnodes: Vec::new(),
|
||||||
reserved_only: false,
|
reserved_only: false,
|
||||||
reserved_nodes: Vec::new(),
|
priority_groups: Vec::new(),
|
||||||
},
|
},
|
||||||
Box::new(DefaultBlockAnnounceValidator::new(client.clone())),
|
Box::new(DefaultBlockAnnounceValidator::new(client.clone())),
|
||||||
None,
|
None,
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
//! Network event types. These are are not the part of the protocol, but rather
|
//! Network event types. These are are not the part of the protocol, but rather
|
||||||
//! events that happen on the network like DHT get/put results received.
|
//! events that happen on the network like DHT get/put results received.
|
||||||
|
|
||||||
use crate::config::Roles;
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use libp2p::core::PeerId;
|
use libp2p::core::PeerId;
|
||||||
use libp2p::kad::record::Key;
|
use libp2p::kad::record::Key;
|
||||||
@@ -55,8 +54,8 @@ pub enum Event {
|
|||||||
remote: PeerId,
|
remote: PeerId,
|
||||||
/// The concerned protocol. Each protocol uses a different substream.
|
/// The concerned protocol. Each protocol uses a different substream.
|
||||||
engine_id: ConsensusEngineId,
|
engine_id: ConsensusEngineId,
|
||||||
/// Roles that the remote .
|
/// Role of the remote.
|
||||||
roles: Roles,
|
role: ObservedRole,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Closed a substream with the given node. Always matches a corresponding previous
|
/// Closed a substream with the given node. Always matches a corresponding previous
|
||||||
@@ -76,3 +75,26 @@ pub enum Event {
|
|||||||
messages: Vec<(ConsensusEngineId, Bytes)>,
|
messages: Vec<(ConsensusEngineId, Bytes)>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Role that the peer sent to us during the handshake, with the addition of what our local node
|
||||||
|
/// knows about that peer.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum ObservedRole {
|
||||||
|
/// Full node.
|
||||||
|
Full,
|
||||||
|
/// Light node.
|
||||||
|
Light,
|
||||||
|
/// When we are a validator node, this is a sentry that protects us.
|
||||||
|
OurSentry,
|
||||||
|
/// When we are a sentry node, this is the authority we are protecting.
|
||||||
|
OurGuardedAuthority,
|
||||||
|
/// Third-party authority.
|
||||||
|
Authority,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObservedRole {
|
||||||
|
/// Returns `true` for `ObservedRole::Light`.
|
||||||
|
pub fn is_light(&self) -> bool {
|
||||||
|
matches!(self, ObservedRole::Light)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ fn build_nodes() -> (Swarm<CustomProtoWithAddr>, Swarm<CustomProtoWithAddr>) {
|
|||||||
vec![]
|
vec![]
|
||||||
},
|
},
|
||||||
reserved_only: false,
|
reserved_only: false,
|
||||||
reserved_nodes: Vec::new(),
|
priority_groups: Vec::new(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let behaviour = CustomProtoWithAddr {
|
let behaviour = CustomProtoWithAddr {
|
||||||
|
|||||||
@@ -1423,7 +1423,7 @@ mod tests {
|
|||||||
out_peers: 128,
|
out_peers: 128,
|
||||||
bootnodes: Vec::new(),
|
bootnodes: Vec::new(),
|
||||||
reserved_only: false,
|
reserved_only: false,
|
||||||
reserved_nodes: Vec::new(),
|
priority_groups: Vec::new(),
|
||||||
};
|
};
|
||||||
sc_peerset::Peerset::from_config(cfg)
|
sc_peerset::Peerset::from_config(cfg)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ pub use self::generic::{
|
|||||||
RemoteHeaderRequest, RemoteHeaderResponse,
|
RemoteHeaderRequest, RemoteHeaderResponse,
|
||||||
RemoteChangesRequest, RemoteChangesResponse,
|
RemoteChangesRequest, RemoteChangesResponse,
|
||||||
FinalityProofRequest, FinalityProofResponse,
|
FinalityProofRequest, FinalityProofResponse,
|
||||||
FromBlock, RemoteReadChildRequest,
|
FromBlock, RemoteReadChildRequest, Roles,
|
||||||
};
|
};
|
||||||
use sc_client_api::StorageProof;
|
use sc_client_api::StorageProof;
|
||||||
|
|
||||||
@@ -137,14 +137,71 @@ pub struct RemoteReadResponse {
|
|||||||
|
|
||||||
/// Generic types.
|
/// Generic types.
|
||||||
pub mod generic {
|
pub mod generic {
|
||||||
|
use bitflags::bitflags;
|
||||||
use codec::{Encode, Decode, Input, Output};
|
use codec::{Encode, Decode, Input, Output};
|
||||||
use sp_runtime::Justification;
|
use sp_runtime::Justification;
|
||||||
use crate::config::Roles;
|
|
||||||
use super::{
|
use super::{
|
||||||
RemoteReadResponse, Transactions, Direction,
|
RemoteReadResponse, Transactions, Direction,
|
||||||
RequestId, BlockAttributes, RemoteCallResponse, ConsensusEngineId,
|
RequestId, BlockAttributes, RemoteCallResponse, ConsensusEngineId,
|
||||||
BlockState, StorageProof,
|
BlockState, StorageProof,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// Bitmask of the roles that a node fulfills.
|
||||||
|
pub struct Roles: u8 {
|
||||||
|
/// No network.
|
||||||
|
const NONE = 0b00000000;
|
||||||
|
/// Full node, does not participate in consensus.
|
||||||
|
const FULL = 0b00000001;
|
||||||
|
/// Light client node.
|
||||||
|
const LIGHT = 0b00000010;
|
||||||
|
/// Act as an authority
|
||||||
|
const AUTHORITY = 0b00000100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Roles {
|
||||||
|
/// Does this role represents a client that holds full chain data locally?
|
||||||
|
pub fn is_full(&self) -> bool {
|
||||||
|
self.intersects(Roles::FULL | Roles::AUTHORITY)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does this role represents a client that does not participates in the consensus?
|
||||||
|
pub fn is_authority(&self) -> bool {
|
||||||
|
*self == Roles::AUTHORITY
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does this role represents a client that does not hold full chain data locally?
|
||||||
|
pub fn is_light(&self) -> bool {
|
||||||
|
!self.is_full()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a crate::config::Role> for Roles {
|
||||||
|
fn from(roles: &'a crate::config::Role) -> Self {
|
||||||
|
match roles {
|
||||||
|
crate::config::Role::Full => Roles::FULL,
|
||||||
|
crate::config::Role::Light => Roles::LIGHT,
|
||||||
|
crate::config::Role::Sentry { .. } => Roles::AUTHORITY,
|
||||||
|
crate::config::Role::Authority { .. } => Roles::AUTHORITY,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl codec::Encode for Roles {
|
||||||
|
fn encode_to<T: codec::Output>(&self, dest: &mut T) {
|
||||||
|
dest.push_byte(self.bits())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl codec::EncodeLike for Roles {}
|
||||||
|
|
||||||
|
impl codec::Decode for Roles {
|
||||||
|
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
|
||||||
|
Self::from_bits(input.read_byte()?).ok_or_else(|| codec::Error::from("Invalid bytes"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Consensus is mostly opaque to us
|
/// Consensus is mostly opaque to us
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
||||||
pub struct ConsensusMessage {
|
pub struct ConsensusMessage {
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ use sp_consensus::{BlockOrigin, BlockStatus,
|
|||||||
import_queue::{IncomingBlock, BlockImportResult, BlockImportError}
|
import_queue::{IncomingBlock, BlockImportResult, BlockImportError}
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Roles, BoxFinalityProofRequestBuilder},
|
config::BoxFinalityProofRequestBuilder,
|
||||||
protocol::message::{self, generic::FinalityProofRequest, BlockAnnounce, BlockAttributes, BlockRequest, BlockResponse,
|
protocol::message::{self, generic::FinalityProofRequest, BlockAnnounce, BlockAttributes, BlockRequest, BlockResponse,
|
||||||
FinalityProofResponse},
|
FinalityProofResponse, Roles},
|
||||||
};
|
};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use extra_requests::ExtraRequests;
|
use extra_requests::ExtraRequests;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
behaviour::{Behaviour, BehaviourOut},
|
behaviour::{Behaviour, BehaviourOut},
|
||||||
config::{parse_addr, parse_str_addr, NonReservedPeerMode, Params, TransportConfig},
|
config::{parse_addr, parse_str_addr, NonReservedPeerMode, Params, Role, TransportConfig},
|
||||||
error::Error,
|
error::Error,
|
||||||
network_state::{
|
network_state::{
|
||||||
NetworkState, NotConnectedPeer as NetworkStateNotConnectedPeer, Peer as NetworkStatePeer,
|
NetworkState, NotConnectedPeer as NetworkStateNotConnectedPeer, Peer as NetworkStatePeer,
|
||||||
@@ -181,19 +181,13 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkWorker<B, H> {
|
|||||||
// List of multiaddresses that we know in the network.
|
// List of multiaddresses that we know in the network.
|
||||||
let mut known_addresses = Vec::new();
|
let mut known_addresses = Vec::new();
|
||||||
let mut bootnodes = Vec::new();
|
let mut bootnodes = Vec::new();
|
||||||
let mut reserved_nodes = Vec::new();
|
|
||||||
let mut boot_node_ids = HashSet::new();
|
let mut boot_node_ids = HashSet::new();
|
||||||
|
|
||||||
// Process the bootnodes.
|
// Process the bootnodes.
|
||||||
for bootnode in params.network_config.boot_nodes.iter() {
|
for bootnode in params.network_config.boot_nodes.iter() {
|
||||||
match parse_str_addr(bootnode) {
|
bootnodes.push(bootnode.peer_id.clone());
|
||||||
Ok((peer_id, addr)) => {
|
boot_node_ids.insert(bootnode.peer_id.clone());
|
||||||
bootnodes.push(peer_id.clone());
|
known_addresses.push((bootnode.peer_id.clone(), bootnode.multiaddr.clone()));
|
||||||
boot_node_ids.insert(peer_id.clone());
|
|
||||||
known_addresses.push((peer_id, addr));
|
|
||||||
},
|
|
||||||
Err(_) => warn!(target: "sub-libp2p", "Not a valid bootnode address: {}", bootnode),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let boot_node_ids = Arc::new(boot_node_ids);
|
let boot_node_ids = Arc::new(boot_node_ids);
|
||||||
@@ -215,22 +209,43 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkWorker<B, H> {
|
|||||||
}
|
}
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Initialize the reserved peers.
|
// Initialize the peers we should always be connected to.
|
||||||
for reserved in params.network_config.reserved_nodes.iter() {
|
let priority_groups = {
|
||||||
if let Ok((peer_id, addr)) = parse_str_addr(reserved) {
|
let mut reserved_nodes = HashSet::new();
|
||||||
reserved_nodes.push(peer_id.clone());
|
for reserved in params.network_config.reserved_nodes.iter() {
|
||||||
known_addresses.push((peer_id, addr));
|
reserved_nodes.insert(reserved.peer_id.clone());
|
||||||
} else {
|
known_addresses.push((reserved.peer_id.clone(), reserved.multiaddr.clone()));
|
||||||
warn!(target: "sub-libp2p", "Not a valid reserved node address: {}", reserved);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
let mut sentries_and_validators = HashSet::new();
|
||||||
|
match ¶ms.role {
|
||||||
|
Role::Sentry { validators } => {
|
||||||
|
for validator in validators {
|
||||||
|
sentries_and_validators.insert(validator.peer_id.clone());
|
||||||
|
known_addresses.push((validator.peer_id.clone(), validator.multiaddr.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Role::Authority { sentry_nodes } => {
|
||||||
|
for sentry_node in sentry_nodes {
|
||||||
|
sentries_and_validators.insert(sentry_node.peer_id.clone());
|
||||||
|
known_addresses.push((sentry_node.peer_id.clone(), sentry_node.multiaddr.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec![
|
||||||
|
("reserved".to_owned(), reserved_nodes),
|
||||||
|
("sentries_and_validators".to_owned(), sentries_and_validators),
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
let peerset_config = sc_peerset::PeersetConfig {
|
let peerset_config = sc_peerset::PeersetConfig {
|
||||||
in_peers: params.network_config.in_peers,
|
in_peers: params.network_config.in_peers,
|
||||||
out_peers: params.network_config.out_peers,
|
out_peers: params.network_config.out_peers,
|
||||||
bootnodes,
|
bootnodes,
|
||||||
reserved_only: params.network_config.non_reserved_mode == NonReservedPeerMode::Deny,
|
reserved_only: params.network_config.non_reserved_mode == NonReservedPeerMode::Deny,
|
||||||
reserved_nodes,
|
priority_groups,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Private and public keys configuration.
|
// Private and public keys configuration.
|
||||||
@@ -253,7 +268,7 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkWorker<B, H> {
|
|||||||
let is_major_syncing = Arc::new(AtomicBool::new(false));
|
let is_major_syncing = Arc::new(AtomicBool::new(false));
|
||||||
let (protocol, peerset_handle) = Protocol::new(
|
let (protocol, peerset_handle) = Protocol::new(
|
||||||
protocol::ProtocolConfig {
|
protocol::ProtocolConfig {
|
||||||
roles: params.roles,
|
roles: From::from(¶ms.role),
|
||||||
max_parallel_downloads: params.network_config.max_parallel_downloads,
|
max_parallel_downloads: params.network_config.max_parallel_downloads,
|
||||||
},
|
},
|
||||||
params.chain.clone(),
|
params.chain.clone(),
|
||||||
@@ -285,6 +300,7 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkWorker<B, H> {
|
|||||||
};
|
};
|
||||||
let behaviour = futures::executor::block_on(Behaviour::new(
|
let behaviour = futures::executor::block_on(Behaviour::new(
|
||||||
protocol,
|
protocol,
|
||||||
|
params.role,
|
||||||
user_agent,
|
user_agent,
|
||||||
local_public,
|
local_public,
|
||||||
known_addresses,
|
known_addresses,
|
||||||
@@ -971,11 +987,8 @@ impl<B: BlockT + 'static, H: ExHashT> Future for NetworkWorker<B, H> {
|
|||||||
this.network_service.user_protocol_mut().write_notification(target, engine_id, message)
|
this.network_service.user_protocol_mut().write_notification(target, engine_id, message)
|
||||||
},
|
},
|
||||||
ServiceToWorkerMsg::RegisterNotifProtocol { engine_id, protocol_name } => {
|
ServiceToWorkerMsg::RegisterNotifProtocol { engine_id, protocol_name } => {
|
||||||
let events = this.network_service.user_protocol_mut()
|
this.network_service
|
||||||
.register_notifications_protocol(engine_id, protocol_name);
|
.register_notifications_protocol(engine_id, protocol_name);
|
||||||
for event in events {
|
|
||||||
this.event_streams.retain(|sender| sender.unbounded_send(event.clone()).is_ok());
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
ServiceToWorkerMsg::DisconnectPeer(who) =>
|
ServiceToWorkerMsg::DisconnectPeer(who) =>
|
||||||
this.network_service.user_protocol_mut().disconnect_peer(&who),
|
this.network_service.user_protocol_mut().disconnect_peer(&who),
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ use sp_blockchain::{
|
|||||||
use sc_client_api::{BlockchainEvents, BlockImportNotification, FinalityNotifications, ImportNotifications, FinalityNotification, backend::{TransactionFor, AuxStore, Backend, Finalizer}, BlockBackend};
|
use sc_client_api::{BlockchainEvents, BlockImportNotification, FinalityNotifications, ImportNotifications, FinalityNotification, backend::{TransactionFor, AuxStore, Backend, Finalizer}, BlockBackend};
|
||||||
use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
|
use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
|
||||||
use sc_client::LongestChain;
|
use sc_client::LongestChain;
|
||||||
use sc_network::config::Roles;
|
use sc_network::config::Role;
|
||||||
use sp_consensus::block_validation::DefaultBlockAnnounceValidator;
|
use sp_consensus::block_validation::DefaultBlockAnnounceValidator;
|
||||||
use sp_consensus::import_queue::{
|
use sp_consensus::import_queue::{
|
||||||
BasicQueue, BoxJustificationImport, Verifier, BoxFinalityProofImport,
|
BasicQueue, BoxJustificationImport, Verifier, BoxFinalityProofImport,
|
||||||
@@ -557,17 +557,17 @@ pub trait TestNetFactory: Sized {
|
|||||||
|
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
trace!(target: "test_network", "Adding peer {}", i);
|
trace!(target: "test_network", "Adding peer {}", i);
|
||||||
net.add_full_peer(&config);
|
net.add_full_peer();
|
||||||
}
|
}
|
||||||
net
|
net
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_full_peer(&mut self, config: &ProtocolConfig) {
|
fn add_full_peer(&mut self) {
|
||||||
self.add_full_peer_with_states(config, None)
|
self.add_full_peer_with_states(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a full peer.
|
/// Add a full peer.
|
||||||
fn add_full_peer_with_states(&mut self, config: &ProtocolConfig, keep_blocks: Option<u32>) {
|
fn add_full_peer_with_states(&mut self, keep_blocks: Option<u32>) {
|
||||||
let test_client_builder = match keep_blocks {
|
let test_client_builder = match keep_blocks {
|
||||||
Some(keep_blocks) => TestClientBuilder::with_pruning_window(keep_blocks),
|
Some(keep_blocks) => TestClientBuilder::with_pruning_window(keep_blocks),
|
||||||
None => TestClientBuilder::with_default_backend(),
|
None => TestClientBuilder::with_default_backend(),
|
||||||
@@ -586,7 +586,7 @@ pub trait TestNetFactory: Sized {
|
|||||||
|
|
||||||
let verifier = self.make_verifier(
|
let verifier = self.make_verifier(
|
||||||
PeersClient::Full(client.clone(), backend.clone()),
|
PeersClient::Full(client.clone(), backend.clone()),
|
||||||
config,
|
&Default::default(),
|
||||||
&data,
|
&data,
|
||||||
);
|
);
|
||||||
let verifier = VerifierAdapter::new(Arc::new(Mutex::new(Box::new(verifier) as Box<_>)));
|
let verifier = VerifierAdapter::new(Arc::new(Mutex::new(Box::new(verifier) as Box<_>)));
|
||||||
@@ -601,7 +601,7 @@ pub trait TestNetFactory: Sized {
|
|||||||
let listen_addr = build_multiaddr![Memory(rand::random::<u64>())];
|
let listen_addr = build_multiaddr![Memory(rand::random::<u64>())];
|
||||||
|
|
||||||
let network = NetworkWorker::new(sc_network::config::Params {
|
let network = NetworkWorker::new(sc_network::config::Params {
|
||||||
roles: config.roles,
|
role: Role::Full,
|
||||||
executor: None,
|
executor: None,
|
||||||
network_config: NetworkConfiguration {
|
network_config: NetworkConfiguration {
|
||||||
listen_addresses: vec![listen_addr.clone()],
|
listen_addresses: vec![listen_addr.clone()],
|
||||||
@@ -644,10 +644,7 @@ pub trait TestNetFactory: Sized {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add a light peer.
|
/// Add a light peer.
|
||||||
fn add_light_peer(&mut self, config: &ProtocolConfig) {
|
fn add_light_peer(&mut self) {
|
||||||
let mut config = config.clone();
|
|
||||||
config.roles = Roles::LIGHT;
|
|
||||||
|
|
||||||
let (c, backend) = substrate_test_runtime_client::new_light();
|
let (c, backend) = substrate_test_runtime_client::new_light();
|
||||||
let client = Arc::new(c);
|
let client = Arc::new(c);
|
||||||
let (
|
let (
|
||||||
@@ -660,7 +657,7 @@ pub trait TestNetFactory: Sized {
|
|||||||
|
|
||||||
let verifier = self.make_verifier(
|
let verifier = self.make_verifier(
|
||||||
PeersClient::Light(client.clone(), backend.clone()),
|
PeersClient::Light(client.clone(), backend.clone()),
|
||||||
&config,
|
&Default::default(),
|
||||||
&data,
|
&data,
|
||||||
);
|
);
|
||||||
let verifier = VerifierAdapter::new(Arc::new(Mutex::new(Box::new(verifier) as Box<_>)));
|
let verifier = VerifierAdapter::new(Arc::new(Mutex::new(Box::new(verifier) as Box<_>)));
|
||||||
@@ -675,7 +672,7 @@ pub trait TestNetFactory: Sized {
|
|||||||
let listen_addr = build_multiaddr![Memory(rand::random::<u64>())];
|
let listen_addr = build_multiaddr![Memory(rand::random::<u64>())];
|
||||||
|
|
||||||
let network = NetworkWorker::new(sc_network::config::Params {
|
let network = NetworkWorker::new(sc_network::config::Params {
|
||||||
roles: config.roles,
|
role: Role::Light,
|
||||||
executor: None,
|
executor: None,
|
||||||
network_config: NetworkConfiguration {
|
network_config: NetworkConfiguration {
|
||||||
listen_addresses: vec![listen_addr.clone()],
|
listen_addresses: vec![listen_addr.clone()],
|
||||||
|
|||||||
@@ -14,7 +14,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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use sc_network::config::Roles;
|
|
||||||
use sp_consensus::BlockOrigin;
|
use sp_consensus::BlockOrigin;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use futures::executor::block_on;
|
use futures::executor::block_on;
|
||||||
@@ -372,10 +371,8 @@ fn blocks_are_not_announced_by_light_nodes() {
|
|||||||
|
|
||||||
// full peer0 is connected to light peer
|
// full peer0 is connected to light peer
|
||||||
// light peer1 is connected to full peer2
|
// light peer1 is connected to full peer2
|
||||||
let mut light_config = ProtocolConfig::default();
|
net.add_full_peer();
|
||||||
light_config.roles = Roles::LIGHT;
|
net.add_light_peer();
|
||||||
net.add_full_peer(&ProtocolConfig::default());
|
|
||||||
net.add_light_peer(&light_config);
|
|
||||||
|
|
||||||
// Sync between 0 and 1.
|
// Sync between 0 and 1.
|
||||||
net.peer(0).push_blocks(1, false);
|
net.peer(0).push_blocks(1, false);
|
||||||
@@ -384,7 +381,7 @@ fn blocks_are_not_announced_by_light_nodes() {
|
|||||||
assert_eq!(net.peer(1).client.info().best_number, 1);
|
assert_eq!(net.peer(1).client.info().best_number, 1);
|
||||||
|
|
||||||
// Add another node and remove node 0.
|
// Add another node and remove node 0.
|
||||||
net.add_full_peer(&ProtocolConfig::default());
|
net.add_full_peer();
|
||||||
net.peers.remove(0);
|
net.peers.remove(0);
|
||||||
|
|
||||||
// Poll for a few seconds and make sure 1 and 2 (now 0 and 1) don't sync together.
|
// Poll for a few seconds and make sure 1 and 2 (now 0 and 1) don't sync together.
|
||||||
@@ -465,7 +462,7 @@ fn can_not_sync_from_light_peer() {
|
|||||||
|
|
||||||
// given the network with 1 full nodes (#0) and 1 light node (#1)
|
// given the network with 1 full nodes (#0) and 1 light node (#1)
|
||||||
let mut net = TestNet::new(1);
|
let mut net = TestNet::new(1);
|
||||||
net.add_light_peer(&Default::default());
|
net.add_light_peer();
|
||||||
|
|
||||||
// generate some blocks on #0
|
// generate some blocks on #0
|
||||||
net.peer(0).push_blocks(1, false);
|
net.peer(0).push_blocks(1, false);
|
||||||
@@ -481,7 +478,7 @@ fn can_not_sync_from_light_peer() {
|
|||||||
assert_eq!(light_info.best_hash, full0_info.best_hash);
|
assert_eq!(light_info.best_hash, full0_info.best_hash);
|
||||||
|
|
||||||
// add new full client (#2) && remove #0
|
// add new full client (#2) && remove #0
|
||||||
net.add_full_peer(&Default::default());
|
net.add_full_peer();
|
||||||
net.peers.remove(0);
|
net.peers.remove(0);
|
||||||
|
|
||||||
// ensure that the #2 (now #1) fails to sync block #1 even after 5 seconds
|
// ensure that the #2 (now #1) fails to sync block #1 even after 5 seconds
|
||||||
@@ -511,7 +508,7 @@ fn light_peer_imports_header_from_announce() {
|
|||||||
|
|
||||||
// given the network with 1 full nodes (#0) and 1 light node (#1)
|
// given the network with 1 full nodes (#0) and 1 light node (#1)
|
||||||
let mut net = TestNet::new(1);
|
let mut net = TestNet::new(1);
|
||||||
net.add_light_peer(&Default::default());
|
net.add_light_peer();
|
||||||
|
|
||||||
// let them connect to each other
|
// let them connect to each other
|
||||||
net.block_until_sync();
|
net.block_until_sync();
|
||||||
@@ -583,9 +580,8 @@ fn can_sync_explicit_forks() {
|
|||||||
fn syncs_header_only_forks() {
|
fn syncs_header_only_forks() {
|
||||||
let _ = ::env_logger::try_init();
|
let _ = ::env_logger::try_init();
|
||||||
let mut net = TestNet::new(0);
|
let mut net = TestNet::new(0);
|
||||||
let config = ProtocolConfig::default();
|
net.add_full_peer_with_states(None);
|
||||||
net.add_full_peer_with_states(&config, None);
|
net.add_full_peer_with_states(Some(3));
|
||||||
net.add_full_peer_with_states(&config, Some(3));
|
|
||||||
net.peer(0).push_blocks(2, false);
|
net.peer(0).push_blocks(2, false);
|
||||||
net.peer(1).push_blocks(2, false);
|
net.peer(1).push_blocks(2, false);
|
||||||
|
|
||||||
|
|||||||
@@ -163,14 +163,14 @@ pub struct PeersetConfig {
|
|||||||
/// > otherwise it will not be able to connect to them.
|
/// > otherwise it will not be able to connect to them.
|
||||||
pub bootnodes: Vec<PeerId>,
|
pub bootnodes: Vec<PeerId>,
|
||||||
|
|
||||||
/// If true, we only accept reserved nodes.
|
/// If true, we only accept nodes in [`PeersetConfig::priority_groups`].
|
||||||
pub reserved_only: bool,
|
pub reserved_only: bool,
|
||||||
|
|
||||||
/// List of nodes that we should always be connected to.
|
/// Lists of nodes we should always be connected to.
|
||||||
///
|
///
|
||||||
/// > **Note**: Keep in mind that the networking has to know an address for these nodes,
|
/// > **Note**: Keep in mind that the networking has to know an address for these nodes,
|
||||||
/// > otherwise it will not be able to connect to them.
|
/// > otherwise it will not be able to connect to them.
|
||||||
pub reserved_nodes: Vec<PeerId>,
|
pub priority_groups: Vec<(String, HashSet<PeerId>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Side of the peer set manager owned by the network. In other words, the "receiving" side.
|
/// Side of the peer set manager owned by the network. In other words, the "receiving" side.
|
||||||
@@ -215,7 +215,10 @@ impl Peerset {
|
|||||||
latest_time_update: now,
|
latest_time_update: now,
|
||||||
};
|
};
|
||||||
|
|
||||||
peerset.data.set_priority_group(RESERVED_NODES, config.reserved_nodes.into_iter().collect());
|
for (group, nodes) in config.priority_groups {
|
||||||
|
peerset.data.set_priority_group(&group, nodes);
|
||||||
|
}
|
||||||
|
|
||||||
for peer_id in config.bootnodes {
|
for peer_id in config.bootnodes {
|
||||||
if let peersstate::Peer::Unknown(entry) = peerset.data.peer(&peer_id) {
|
if let peersstate::Peer::Unknown(entry) = peerset.data.peer(&peer_id) {
|
||||||
entry.discover();
|
entry.discover();
|
||||||
@@ -597,7 +600,7 @@ mod tests {
|
|||||||
out_peers: 2,
|
out_peers: 2,
|
||||||
bootnodes: vec![bootnode],
|
bootnodes: vec![bootnode],
|
||||||
reserved_only: true,
|
reserved_only: true,
|
||||||
reserved_nodes: Vec::new(),
|
priority_groups: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (peerset, handle) = Peerset::from_config(config);
|
let (peerset, handle) = Peerset::from_config(config);
|
||||||
@@ -625,7 +628,7 @@ mod tests {
|
|||||||
out_peers: 1,
|
out_peers: 1,
|
||||||
bootnodes: vec![bootnode.clone()],
|
bootnodes: vec![bootnode.clone()],
|
||||||
reserved_only: false,
|
reserved_only: false,
|
||||||
reserved_nodes: Vec::new(),
|
priority_groups: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (mut peerset, _handle) = Peerset::from_config(config);
|
let (mut peerset, _handle) = Peerset::from_config(config);
|
||||||
@@ -652,7 +655,7 @@ mod tests {
|
|||||||
out_peers: 2,
|
out_peers: 2,
|
||||||
bootnodes: vec![bootnode.clone()],
|
bootnodes: vec![bootnode.clone()],
|
||||||
reserved_only: false,
|
reserved_only: false,
|
||||||
reserved_nodes: vec![],
|
priority_groups: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let (mut peerset, _handle) = Peerset::from_config(config);
|
let (mut peerset, _handle) = Peerset::from_config(config);
|
||||||
@@ -673,7 +676,7 @@ mod tests {
|
|||||||
out_peers: 25,
|
out_peers: 25,
|
||||||
bootnodes: vec![],
|
bootnodes: vec![],
|
||||||
reserved_only: false,
|
reserved_only: false,
|
||||||
reserved_nodes: vec![],
|
priority_groups: vec![],
|
||||||
});
|
});
|
||||||
|
|
||||||
// We ban a node by setting its reputation under the threshold.
|
// We ban a node by setting its reputation under the threshold.
|
||||||
|
|||||||
@@ -43,12 +43,15 @@ fn test_once() {
|
|||||||
known_nodes.insert(id.clone());
|
known_nodes.insert(id.clone());
|
||||||
id
|
id
|
||||||
}).collect(),
|
}).collect(),
|
||||||
reserved_nodes: (0 .. Uniform::new_inclusive(0, 2).sample(&mut rng)).map(|_| {
|
priority_groups: {
|
||||||
let id = PeerId::random();
|
let list = (0 .. Uniform::new_inclusive(0, 2).sample(&mut rng)).map(|_| {
|
||||||
known_nodes.insert(id.clone());
|
let id = PeerId::random();
|
||||||
reserved_nodes.insert(id.clone());
|
known_nodes.insert(id.clone());
|
||||||
id
|
reserved_nodes.insert(id.clone());
|
||||||
}).collect(),
|
id
|
||||||
|
}).collect();
|
||||||
|
vec![("reserved".to_owned(), list)]
|
||||||
|
},
|
||||||
reserved_only: Uniform::new_inclusive(0, 10).sample(&mut rng) == 0,
|
reserved_only: Uniform::new_inclusive(0, 10).sample(&mut rng) == 0,
|
||||||
in_peers: Uniform::new_inclusive(0, 25).sample(&mut rng),
|
in_peers: Uniform::new_inclusive(0, 25).sample(&mut rng),
|
||||||
out_peers: Uniform::new_inclusive(0, 25).sample(&mut rng),
|
out_peers: Uniform::new_inclusive(0, 25).sample(&mut rng),
|
||||||
|
|||||||
@@ -83,8 +83,8 @@ pub enum NodeRole {
|
|||||||
LightClient,
|
LightClient,
|
||||||
/// The node is an authority
|
/// The node is an authority
|
||||||
Authority,
|
Authority,
|
||||||
/// An unknown role with a bit number
|
/// The node is a sentry
|
||||||
UnknownRole(u8)
|
Sentry,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use sc_network::{self, PeerId};
|
use sc_network::{self, PeerId};
|
||||||
use sc_network::config::Roles;
|
use sc_network::config::Role;
|
||||||
use substrate_test_runtime_client::runtime::Block;
|
use substrate_test_runtime_client::runtime::Block;
|
||||||
use assert_matches::assert_matches;
|
use assert_matches::assert_matches;
|
||||||
use futures::{prelude::*, channel::mpsc};
|
use futures::{prelude::*, channel::mpsc};
|
||||||
@@ -60,7 +60,7 @@ fn api<T: Into<Option<Status>>>(sync: T) -> System<Block> {
|
|||||||
for _peer in 0..status.peers {
|
for _peer in 0..status.peers {
|
||||||
peers.push(PeerInfo {
|
peers.push(PeerInfo {
|
||||||
peer_id: status.peer_id.to_base58(),
|
peer_id: status.peer_id.to_base58(),
|
||||||
roles: format!("{:?}", Roles::FULL),
|
roles: format!("{}", Role::Full),
|
||||||
protocol_version: 1,
|
protocol_version: 1,
|
||||||
best_hash: Default::default(),
|
best_hash: Default::default(),
|
||||||
best_number: 1,
|
best_number: 1,
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ use futures::{
|
|||||||
};
|
};
|
||||||
use sc_keystore::{Store as Keystore};
|
use sc_keystore::{Store as Keystore};
|
||||||
use log::{info, warn, error};
|
use log::{info, warn, error};
|
||||||
use sc_network::config::{FinalityProofProvider, OnDemand, BoxFinalityProofRequestBuilder};
|
use sc_network::config::{Role, FinalityProofProvider, OnDemand, BoxFinalityProofRequestBuilder};
|
||||||
use sc_network::{NetworkService, NetworkStateInfo};
|
use sc_network::{NetworkService, NetworkStateInfo};
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use sp_runtime::generic::BlockId;
|
use sp_runtime::generic::BlockId;
|
||||||
@@ -840,7 +840,7 @@ ServiceBuilder<
|
|||||||
.register_transaction_pool(Arc::downgrade(&transaction_pool) as _);
|
.register_transaction_pool(Arc::downgrade(&transaction_pool) as _);
|
||||||
|
|
||||||
let transaction_pool_adapter = Arc::new(TransactionPoolAdapter {
|
let transaction_pool_adapter = Arc::new(TransactionPoolAdapter {
|
||||||
imports_external_transactions: !config.roles.is_light(),
|
imports_external_transactions: !matches!(config.role, Role::Light),
|
||||||
pool: transaction_pool.clone(),
|
pool: transaction_pool.clone(),
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
executor: tasks_builder.spawn_handle(),
|
executor: tasks_builder.spawn_handle(),
|
||||||
@@ -863,7 +863,7 @@ ServiceBuilder<
|
|||||||
Box::new(sp_consensus::block_validation::DefaultBlockAnnounceValidator::new(client.clone()));
|
Box::new(sp_consensus::block_validation::DefaultBlockAnnounceValidator::new(client.clone()));
|
||||||
|
|
||||||
let network_params = sc_network::config::Params {
|
let network_params = sc_network::config::Params {
|
||||||
roles: config.roles,
|
role: config.role.clone(),
|
||||||
executor: {
|
executor: {
|
||||||
let spawn_handle = tasks_builder.spawn_handle();
|
let spawn_handle = tasks_builder.spawn_handle();
|
||||||
Some(Box::new(move |fut| {
|
Some(Box::new(move |fut| {
|
||||||
@@ -913,7 +913,7 @@ ServiceBuilder<
|
|||||||
let offchain = offchain_workers.as_ref().map(Arc::downgrade);
|
let offchain = offchain_workers.as_ref().map(Arc::downgrade);
|
||||||
let notifications_spawn_handle = tasks_builder.spawn_handle();
|
let notifications_spawn_handle = tasks_builder.spawn_handle();
|
||||||
let network_state_info: Arc<dyn NetworkStateInfo + Send + Sync> = network.clone();
|
let network_state_info: Arc<dyn NetworkStateInfo + Send + Sync> = network.clone();
|
||||||
let is_validator = config.roles.is_authority();
|
let is_validator = config.role.is_authority();
|
||||||
|
|
||||||
let (import_stream, finality_stream) = (
|
let (import_stream, finality_stream) = (
|
||||||
client.import_notification_stream().map(|n| ChainEvent::NewBlock {
|
client.import_notification_stream().map(|n| ChainEvent::NewBlock {
|
||||||
@@ -1003,9 +1003,16 @@ ServiceBuilder<
|
|||||||
.const_label("version", config.impl_version)
|
.const_label("version", config.impl_version)
|
||||||
.const_label("commit", config.impl_commit),
|
.const_label("commit", config.impl_commit),
|
||||||
)?, ®istry)?.set(1);
|
)?, ®istry)?.set(1);
|
||||||
|
|
||||||
|
let role_bits = match config.role {
|
||||||
|
Role::Full => 1,
|
||||||
|
Role::Light => 2,
|
||||||
|
Role::Sentry { .. } => 3,
|
||||||
|
Role::Authority { .. } => 4,
|
||||||
|
};
|
||||||
register(Gauge::<U64>::new(
|
register(Gauge::<U64>::new(
|
||||||
"node_roles", "The roles the node is running as",
|
"node_role", "The role the node is running as",
|
||||||
)?, ®istry)?.set(u64::from(config.roles.bits()));
|
)?, ®istry)?.set(role_bits);
|
||||||
|
|
||||||
let metrics = ServiceMetrics::register(®istry)?;
|
let metrics = ServiceMetrics::register(®istry)?;
|
||||||
|
|
||||||
@@ -1198,7 +1205,7 @@ ServiceBuilder<
|
|||||||
spawn_handle.spawn(
|
spawn_handle.spawn(
|
||||||
"network-worker",
|
"network-worker",
|
||||||
build_network_future(
|
build_network_future(
|
||||||
config.roles,
|
config.role.clone(),
|
||||||
network_mut,
|
network_mut,
|
||||||
client.clone(),
|
client.clone(),
|
||||||
network_status_sinks.clone(),
|
network_status_sinks.clone(),
|
||||||
@@ -1212,7 +1219,7 @@ ServiceBuilder<
|
|||||||
|
|
||||||
// Telemetry
|
// Telemetry
|
||||||
let telemetry = config.telemetry_endpoints.clone().map(|endpoints| {
|
let telemetry = config.telemetry_endpoints.clone().map(|endpoints| {
|
||||||
let is_authority = config.roles.is_authority();
|
let is_authority = config.role.is_authority();
|
||||||
let network_id = network.local_peer_id().to_base58();
|
let network_id = network.local_peer_id().to_base58();
|
||||||
let name = config.name.clone();
|
let name = config.name.clone();
|
||||||
let impl_name = config.impl_name.to_owned();
|
let impl_name = config.impl_name.to_owned();
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
pub use sc_client::ExecutionStrategies;
|
pub use sc_client::ExecutionStrategies;
|
||||||
pub use sc_client_db::{kvdb::KeyValueDB, PruningMode};
|
pub use sc_client_db::{kvdb::KeyValueDB, PruningMode};
|
||||||
pub use sc_network::config::{ExtTransport, NetworkConfiguration, Roles};
|
pub use sc_network::{Multiaddr, config::{MultiaddrWithPeerId, ExtTransport, NetworkConfiguration, Role}};
|
||||||
pub use sc_executor::WasmExecutionMethod;
|
pub use sc_executor::WasmExecutionMethod;
|
||||||
|
|
||||||
use std::{future::Future, path::{PathBuf, Path}, pin::Pin, net::SocketAddr, sync::Arc};
|
use std::{future::Future, path::{PathBuf, Path}, pin::Pin, net::SocketAddr, sync::Arc};
|
||||||
@@ -58,8 +58,8 @@ pub struct Configuration {
|
|||||||
pub impl_version: &'static str,
|
pub impl_version: &'static str,
|
||||||
/// Git commit if any.
|
/// Git commit if any.
|
||||||
pub impl_commit: &'static str,
|
pub impl_commit: &'static str,
|
||||||
/// Node roles.
|
/// Node role.
|
||||||
pub roles: Roles,
|
pub role: Role,
|
||||||
/// How to spawn background tasks. Mandatory, otherwise creating a `Service` will error.
|
/// How to spawn background tasks. Mandatory, otherwise creating a `Service` will error.
|
||||||
pub task_executor: Option<Arc<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send + Sync>>,
|
pub task_executor: Option<Arc<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send + Sync>>,
|
||||||
/// Extrinsic pool configuration.
|
/// Extrinsic pool configuration.
|
||||||
@@ -105,10 +105,6 @@ pub struct Configuration {
|
|||||||
pub default_heap_pages: Option<u64>,
|
pub default_heap_pages: Option<u64>,
|
||||||
/// Should offchain workers be executed.
|
/// Should offchain workers be executed.
|
||||||
pub offchain_worker: bool,
|
pub offchain_worker: bool,
|
||||||
/// Sentry mode is enabled, the node's role is AUTHORITY but it should not
|
|
||||||
/// actively participate in consensus (i.e. no keystores should be passed to
|
|
||||||
/// consensus modules).
|
|
||||||
pub sentry_mode: bool,
|
|
||||||
/// Enable authoring even when offline.
|
/// Enable authoring even when offline.
|
||||||
pub force_authoring: bool,
|
pub force_authoring: bool,
|
||||||
/// Disable GRANDPA when running in validator mode
|
/// Disable GRANDPA when running in validator mode
|
||||||
@@ -204,7 +200,7 @@ impl Default for Configuration {
|
|||||||
chain_spec: None,
|
chain_spec: None,
|
||||||
config_dir: None,
|
config_dir: None,
|
||||||
name: Default::default(),
|
name: Default::default(),
|
||||||
roles: Roles::FULL,
|
role: Role::Full,
|
||||||
task_executor: None,
|
task_executor: None,
|
||||||
transaction_pool: Default::default(),
|
transaction_pool: Default::default(),
|
||||||
network: Default::default(),
|
network: Default::default(),
|
||||||
@@ -224,7 +220,6 @@ impl Default for Configuration {
|
|||||||
telemetry_external_transport: None,
|
telemetry_external_transport: None,
|
||||||
default_heap_pages: None,
|
default_heap_pages: None,
|
||||||
offchain_worker: Default::default(),
|
offchain_worker: Default::default(),
|
||||||
sentry_mode: false,
|
|
||||||
force_authoring: false,
|
force_authoring: false,
|
||||||
disable_grandpa: false,
|
disable_grandpa: false,
|
||||||
dev_key_seed: None,
|
dev_key_seed: None,
|
||||||
@@ -286,15 +281,9 @@ impl Configuration {
|
|||||||
self.database.as_ref().expect("database must be specified")
|
self.database.as_ref().expect("database must be specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a string displaying the node role, special casing the sentry mode
|
/// Returns a string displaying the node role.
|
||||||
/// (returning `SENTRY`), since the node technically has an `AUTHORITY` role but
|
|
||||||
/// doesn't participate.
|
|
||||||
pub fn display_role(&self) -> String {
|
pub fn display_role(&self) -> String {
|
||||||
if self.sentry_mode {
|
self.role.to_string()
|
||||||
"SENTRY".to_string()
|
|
||||||
} else {
|
|
||||||
self.roles.to_string()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use in memory keystore config when it is not required at all.
|
/// Use in memory keystore config when it is not required at all.
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ pub use self::builder::{
|
|||||||
ServiceBuilder, ServiceBuilderCommand, TFullClient, TLightClient, TFullBackend, TLightBackend,
|
ServiceBuilder, ServiceBuilderCommand, TFullClient, TLightClient, TFullBackend, TLightBackend,
|
||||||
TFullCallExecutor, TLightCallExecutor,
|
TFullCallExecutor, TLightCallExecutor,
|
||||||
};
|
};
|
||||||
pub use config::{Configuration, Roles, PruningMode, DatabaseConfig};
|
pub use config::{Configuration, Role, PruningMode, DatabaseConfig};
|
||||||
pub use sc_chain_spec::{
|
pub use sc_chain_spec::{
|
||||||
ChainSpec, GenericChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension
|
ChainSpec, GenericChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension
|
||||||
};
|
};
|
||||||
@@ -322,7 +322,7 @@ fn build_network_future<
|
|||||||
C: sc_client::BlockchainEvents<B>,
|
C: sc_client::BlockchainEvents<B>,
|
||||||
H: sc_network::ExHashT
|
H: sc_network::ExHashT
|
||||||
> (
|
> (
|
||||||
roles: Roles,
|
role: Role,
|
||||||
mut network: sc_network::NetworkWorker<B, H>,
|
mut network: sc_network::NetworkWorker<B, H>,
|
||||||
client: Arc<C>,
|
client: Arc<C>,
|
||||||
status_sinks: Arc<Mutex<status_sinks::StatusSinks<(NetworkStatus<B>, NetworkState)>>>,
|
status_sinks: Arc<Mutex<status_sinks::StatusSinks<(NetworkStatus<B>, NetworkState)>>>,
|
||||||
@@ -399,17 +399,14 @@ fn build_network_future<
|
|||||||
sc_rpc::system::Request::NodeRoles(sender) => {
|
sc_rpc::system::Request::NodeRoles(sender) => {
|
||||||
use sc_rpc::system::NodeRole;
|
use sc_rpc::system::NodeRole;
|
||||||
|
|
||||||
let node_roles = (0 .. 8)
|
let node_role = match role {
|
||||||
.filter(|&bit_number| (roles.bits() >> bit_number) & 1 == 1)
|
Role::Authority { .. } => NodeRole::Authority,
|
||||||
.map(|bit_number| match Roles::from_bits(1 << bit_number) {
|
Role::Light => NodeRole::LightClient,
|
||||||
Some(Roles::AUTHORITY) => NodeRole::Authority,
|
Role::Full => NodeRole::Full,
|
||||||
Some(Roles::LIGHT) => NodeRole::LightClient,
|
Role::Sentry { .. } => NodeRole::Sentry,
|
||||||
Some(Roles::FULL) => NodeRole::Full,
|
};
|
||||||
_ => NodeRole::UnknownRole(bit_number),
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let _ = sender.send(node_roles);
|
let _ = sender.send(vec![node_role]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ use sc_service::{
|
|||||||
Configuration,
|
Configuration,
|
||||||
config::{DatabaseConfig, KeystoreConfig},
|
config::{DatabaseConfig, KeystoreConfig},
|
||||||
RuntimeGenesis,
|
RuntimeGenesis,
|
||||||
Roles,
|
Role,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
use sc_network::{multiaddr, Multiaddr, NetworkStateInfo};
|
use sc_network::{multiaddr, Multiaddr, NetworkStateInfo};
|
||||||
@@ -134,7 +134,7 @@ where F: Send + 'static, L: Send +'static, U: Clone + Send + 'static
|
|||||||
fn node_config<G: RuntimeGenesis + 'static, E: ChainSpecExtension + Clone + 'static + Send> (
|
fn node_config<G: RuntimeGenesis + 'static, E: ChainSpecExtension + Clone + 'static + Send> (
|
||||||
index: usize,
|
index: usize,
|
||||||
spec: &GenericChainSpec<G, E>,
|
spec: &GenericChainSpec<G, E>,
|
||||||
role: Roles,
|
role: Role,
|
||||||
task_executor: Arc<dyn Fn(Pin<Box<dyn futures::Future<Output = ()> + Send>>) + Send + Sync>,
|
task_executor: Arc<dyn Fn(Pin<Box<dyn futures::Future<Output = ()> + Send>>) + Send + Sync>,
|
||||||
key_seed: Option<String>,
|
key_seed: Option<String>,
|
||||||
base_port: u16,
|
base_port: u16,
|
||||||
@@ -161,7 +161,6 @@ fn node_config<G: RuntimeGenesis + 'static, E: ChainSpecExtension + Clone + 'sta
|
|||||||
out_peers: 450,
|
out_peers: 450,
|
||||||
reserved_nodes: vec![],
|
reserved_nodes: vec![],
|
||||||
non_reserved_mode: NonReservedPeerMode::Accept,
|
non_reserved_mode: NonReservedPeerMode::Accept,
|
||||||
sentry_nodes: vec![],
|
|
||||||
client_version: "network/test/0.1".to_owned(),
|
client_version: "network/test/0.1".to_owned(),
|
||||||
node_name: "unknown".to_owned(),
|
node_name: "unknown".to_owned(),
|
||||||
transport: TransportConfig::Normal {
|
transport: TransportConfig::Normal {
|
||||||
@@ -177,7 +176,7 @@ fn node_config<G: RuntimeGenesis + 'static, E: ChainSpecExtension + Clone + 'sta
|
|||||||
impl_name: "network-test-impl",
|
impl_name: "network-test-impl",
|
||||||
impl_version: "0.1",
|
impl_version: "0.1",
|
||||||
impl_commit: "",
|
impl_commit: "",
|
||||||
roles: role,
|
role,
|
||||||
task_executor: Some(task_executor),
|
task_executor: Some(task_executor),
|
||||||
transaction_pool: Default::default(),
|
transaction_pool: Default::default(),
|
||||||
network: network_config,
|
network: network_config,
|
||||||
@@ -206,7 +205,6 @@ fn node_config<G: RuntimeGenesis + 'static, E: ChainSpecExtension + Clone + 'sta
|
|||||||
telemetry_external_transport: None,
|
telemetry_external_transport: None,
|
||||||
default_heap_pages: None,
|
default_heap_pages: None,
|
||||||
offchain_worker: false,
|
offchain_worker: false,
|
||||||
sentry_mode: false,
|
|
||||||
force_authoring: false,
|
force_authoring: false,
|
||||||
disable_grandpa: false,
|
disable_grandpa: false,
|
||||||
dev_key_seed: key_seed,
|
dev_key_seed: key_seed,
|
||||||
@@ -267,7 +265,7 @@ impl<G, E, F, L, U> TestNet<G, E, F, L, U> where
|
|||||||
let node_config = node_config(
|
let node_config = node_config(
|
||||||
self.nodes,
|
self.nodes,
|
||||||
&self.chain_spec,
|
&self.chain_spec,
|
||||||
Roles::AUTHORITY,
|
Role::Authority { sentry_nodes: Vec::new() },
|
||||||
task_executor,
|
task_executor,
|
||||||
Some(key),
|
Some(key),
|
||||||
self.base_port,
|
self.base_port,
|
||||||
@@ -288,7 +286,7 @@ impl<G, E, F, L, U> TestNet<G, E, F, L, U> where
|
|||||||
let executor = executor.clone();
|
let executor = executor.clone();
|
||||||
Arc::new(move |fut: Pin<Box<dyn futures::Future<Output = ()> + Send>>| executor.spawn(fut.unit_error().compat()))
|
Arc::new(move |fut: Pin<Box<dyn futures::Future<Output = ()> + Send>>| executor.spawn(fut.unit_error().compat()))
|
||||||
};
|
};
|
||||||
let node_config = node_config(self.nodes, &self.chain_spec, Roles::FULL, task_executor, None, self.base_port, &temp);
|
let node_config = node_config(self.nodes, &self.chain_spec, Role::Full, task_executor, None, self.base_port, &temp);
|
||||||
let addr = node_config.network.listen_addresses.iter().next().unwrap().clone();
|
let addr = node_config.network.listen_addresses.iter().next().unwrap().clone();
|
||||||
let (service, user_data) = full(node_config).expect("Error creating test node service");
|
let (service, user_data) = full(node_config).expect("Error creating test node service");
|
||||||
let service = SyncService::from(service);
|
let service = SyncService::from(service);
|
||||||
@@ -304,7 +302,7 @@ impl<G, E, F, L, U> TestNet<G, E, F, L, U> where
|
|||||||
let executor = executor.clone();
|
let executor = executor.clone();
|
||||||
Arc::new(move |fut: Pin<Box<dyn futures::Future<Output = ()> + Send>>| executor.spawn(fut.unit_error().compat()))
|
Arc::new(move |fut: Pin<Box<dyn futures::Future<Output = ()> + Send>>| executor.spawn(fut.unit_error().compat()))
|
||||||
};
|
};
|
||||||
let node_config = node_config(self.nodes, &self.chain_spec, Roles::LIGHT, task_executor, None, self.base_port, &temp);
|
let node_config = node_config(self.nodes, &self.chain_spec, Role::Light, task_executor, None, self.base_port, &temp);
|
||||||
let addr = node_config.network.listen_addresses.iter().next().unwrap().clone();
|
let addr = node_config.network.listen_addresses.iter().next().unwrap().clone();
|
||||||
let service = SyncService::from(light(node_config).expect("Error creating test node service"));
|
let service = SyncService::from(light(node_config).expect("Error creating test node service"));
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use futures01::sync::mpsc as mpsc01;
|
|||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use sc_service::{
|
use sc_service::{
|
||||||
AbstractService, RpcSession, Roles, Configuration, config::{DatabaseConfig, KeystoreConfig},
|
AbstractService, RpcSession, Role, Configuration, config::{DatabaseConfig, KeystoreConfig},
|
||||||
GenericChainSpec, RuntimeGenesis
|
GenericChainSpec, RuntimeGenesis
|
||||||
};
|
};
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
@@ -57,7 +57,7 @@ where
|
|||||||
wasm_bindgen_futures::spawn_local(fut)
|
wasm_bindgen_futures::spawn_local(fut)
|
||||||
}));
|
}));
|
||||||
config.telemetry_external_transport = Some(transport);
|
config.telemetry_external_transport = Some(transport);
|
||||||
config.roles = Roles::LIGHT;
|
config.role = Role::Light;
|
||||||
config.name = format!("{} (Browser)", name);
|
config.name = format!("{} (Browser)", name);
|
||||||
config.database = Some({
|
config.database = Some({
|
||||||
info!("Opening Indexed DB database '{}'...", name);
|
info!("Opening Indexed DB database '{}'...", name);
|
||||||
|
|||||||
Reference in New Issue
Block a user