// Copyright 2018-2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see .
use std::path::PathBuf;
use std::iter;
use std::net::Ipv4Addr;
use structopt::StructOpt;
use sc_network::{
config::{NonReservedPeerMode, TransportConfig}, multiaddr::Protocol,
};
use sc_service::Configuration;
use crate::error;
use crate::params::node_key_params::NodeKeyParams;
/// Parameters used to create the network configuration.
#[derive(Debug, StructOpt, Clone)]
pub struct NetworkConfigurationParams {
/// Specify a list of bootnodes.
#[structopt(long = "bootnodes", value_name = "URL")]
pub bootnodes: Vec,
/// Specify a list of reserved node addresses.
#[structopt(long = "reserved-nodes", value_name = "URL")]
pub reserved_nodes: Vec,
/// Whether to only allow connections to/from reserved nodes.
///
/// If you are a validator your node might still connect to other validator
/// nodes regardless of whether they are defined as reserved nodes.
#[structopt(long = "reserved-only")]
pub reserved_only: bool,
/// Specify a list of sentry node public addresses.
#[structopt(
long = "sentry-nodes",
value_name = "URL",
conflicts_with_all = &[ "sentry" ]
)]
pub sentry_nodes: Vec,
/// Listen on this multiaddress.
#[structopt(long = "listen-addr", value_name = "LISTEN_ADDR")]
pub listen_addr: Vec,
/// Specify p2p protocol TCP port.
///
/// Only used if --listen-addr is not specified.
#[structopt(long = "port", value_name = "PORT")]
pub port: Option,
/// Forbid connecting to private IPv4 addresses (as specified in
/// [RFC1918](https://tools.ietf.org/html/rfc1918)), unless the address was passed with
/// `--reserved-nodes` or `--bootnodes`.
#[structopt(long = "no-private-ipv4")]
pub no_private_ipv4: bool,
/// Specify the number of outgoing connections we're trying to maintain.
#[structopt(long = "out-peers", value_name = "COUNT", default_value = "25")]
pub out_peers: u32,
/// Specify the maximum number of incoming connections we're accepting.
#[structopt(long = "in-peers", value_name = "COUNT", default_value = "25")]
pub in_peers: u32,
/// Disable mDNS discovery.
///
/// By default, the network will use mDNS to discover other nodes on the
/// local network. This disables it. Automatically implied when using --dev.
#[structopt(long = "no-mdns")]
pub no_mdns: bool,
/// Maximum number of peers to ask the same blocks in parallel.
///
/// This allows downlading announced blocks from multiple peers. Decrease to save
/// traffic and risk increased latency.
#[structopt(long = "max-parallel-downloads", value_name = "COUNT", default_value = "5")]
pub max_parallel_downloads: u32,
#[allow(missing_docs)]
#[structopt(flatten)]
pub node_key_params: NodeKeyParams,
/// Experimental feature flag.
#[structopt(long = "use-yamux-flow-control")]
pub use_yamux_flow_control: bool,
}
impl NetworkConfigurationParams {
/// Fill the given `NetworkConfiguration` by looking at the cli parameters.
pub fn update_config(
&self,
mut config: &mut Configuration,
config_path: PathBuf,
client_id: String,
is_dev: bool,
) -> error::Result<()> {
config.network.boot_nodes.extend(self.bootnodes.clone());
config.network.config_path = Some(config_path.clone());
config.network.net_config_path = Some(config_path.clone());
config.network.reserved_nodes.extend(self.reserved_nodes.clone());
if self.reserved_only {
config.network.non_reserved_mode = NonReservedPeerMode::Deny;
}
config.network.sentry_nodes.extend(self.sentry_nodes.clone());
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() {
let port = match self.port {
Some(port) => port,
None => 30333,
};
config.network.listen_addresses = vec![
iter::once(Protocol::Ip4(Ipv4Addr::new(0, 0, 0, 0)))
.chain(iter::once(Protocol::Tcp(port)))
.collect()
];
}
config.network.client_version = client_id;
self.node_key_params.update_config(&mut config, Some(&config_path))?;
config.network.in_peers = self.in_peers;
config.network.out_peers = self.out_peers;
config.network.transport = TransportConfig::Normal {
enable_mdns: !is_dev && !self.no_mdns,
allow_private_ipv4: !self.no_private_ipv4,
wasm_external_transport: None,
use_yamux_flow_control: self.use_yamux_flow_control,
};
config.network.max_parallel_downloads = self.max_parallel_downloads;
Ok(())
}
}