diff --git a/substrate/core/cli/src/lib.rs b/substrate/core/cli/src/lib.rs index 51363445dc..3b4953312a 100644 --- a/substrate/core/cli/src/lib.rs +++ b/substrate/core/cli/src/lib.rs @@ -269,22 +269,24 @@ pub struct ParseAndPrepareRun<'a, RP> { impl<'a, RP> ParseAndPrepareRun<'a, RP> { /// Runs the command and runs the main client. - pub fn run( + pub fn run( self, spec_factory: S, exit: Exit, run_service: RS, ) -> error::Result<()> - where S: FnOnce(&str) -> Result>, String>, + where + S: FnOnce(&str) -> Result>, String>, + E: Into, RP: StructOpt + Clone, C: Default, G: RuntimeGenesis, - E: ChainSpecExtension, + CE: ChainSpecExtension, Exit: IntoExit, - RS: FnOnce(Exit, RunCmd, RP, Configuration) -> Result<(), String> + RS: FnOnce(Exit, RunCmd, RP, Configuration) -> Result<(), E> { let config = create_run_node_config( - self.params.left.clone(), spec_factory, self.impl_name, self.version + self.params.left.clone(), spec_factory, self.impl_name, self.version, )?; run_service(exit, self.params.left, self.params.right, config).map_err(Into::into) @@ -633,7 +635,7 @@ fn fill_config_keystore_password( } fn create_run_node_config( - cli: RunCmd, spec_factory: S, impl_name: &'static str, version: &VersionInfo + cli: RunCmd, spec_factory: S, impl_name: &'static str, version: &VersionInfo, ) -> error::Result> where C: Default, diff --git a/substrate/core/network/src/error.rs b/substrate/core/network/src/error.rs index 95a1dc5abe..c3f89e43c1 100644 --- a/substrate/core/network/src/error.rs +++ b/substrate/core/network/src/error.rs @@ -18,16 +18,42 @@ use client; +use libp2p::{PeerId, Multiaddr}; + +use std::fmt; + /// Result type alias for the network. pub type Result = std::result::Result; /// Error type for the network. -#[derive(Debug, derive_more::Display, derive_more::From)] +#[derive(derive_more::Display, derive_more::From)] pub enum Error { /// Io error Io(std::io::Error), /// Client error Client(client::error::Error), + /// The same bootnode (based on address) is registered with two different peer ids. + #[display( + fmt = "The same bootnode (`{}`) is registered with two different peer ids: `{}` and `{}`", + address, + first_id, + second_id, + )] + DuplicateBootnode { + /// The address of the bootnode. + address: Multiaddr, + /// The first peer id that was found for the bootnode. + first_id: PeerId, + /// The second peer id that was found for the bootnode. + second_id: PeerId, + }, +} + +// Make `Debug` use the `Display` implementation. +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } } impl std::error::Error for Error { @@ -35,6 +61,7 @@ impl std::error::Error for Error { match self { Error::Io(ref err) => Some(err), Error::Client(ref err) => Some(err), + Error::DuplicateBootnode { .. } => None, } } } diff --git a/substrate/core/network/src/service.rs b/substrate/core/network/src/service.rs index 5e8d41340c..1c44826062 100644 --- a/substrate/core/network/src/service.rs +++ b/substrate/core/network/src/service.rs @@ -52,14 +52,11 @@ use crate::protocol::specialization::NetworkSpecialization; use crate::protocol::sync::SyncState; /// Minimum Requirements for a Hash within Networking -pub trait ExHashT: - ::std::hash::Hash + Eq + ::std::fmt::Debug + Clone + Send + Sync + 'static -{ -} +pub trait ExHashT: std::hash::Hash + Eq + std::fmt::Debug + Clone + Send + Sync + 'static {} + impl ExHashT for T where - T: ::std::hash::Hash + Eq + ::std::fmt::Debug + Clone + Send + Sync + 'static -{ -} + T: std::hash::Hash + Eq + std::fmt::Debug + Clone + Send + Sync + 'static +{} /// Transaction pool interface pub trait TransactionPool: Send + Sync { @@ -152,6 +149,23 @@ impl, H: ExHashT> NetworkWorker } } + // Check for duplicate bootnodes. + known_addresses.iter() + .try_for_each(|(peer_id, addr)| + if let Some(other) = known_addresses + .iter() + .find(|o| o.1 == *addr && o.0 != *peer_id) + { + Err(Error::DuplicateBootnode { + address: addr.clone(), + first_id: peer_id.clone(), + second_id: other.0.clone(), + }) + } else { + Ok(()) + } + )?; + // Initialize the reserved peers. for reserved in params.network_config.reserved_nodes.iter() { if let Ok((peer_id, addr)) = parse_str_addr(reserved) { @@ -553,8 +567,9 @@ impl, H: ExHashT> NetworkServic } } -impl, H: ExHashT> - ::consensus::SyncOracle for NetworkService { +impl, H: ExHashT> consensus::SyncOracle + for NetworkService +{ fn is_major_syncing(&mut self) -> bool { NetworkService::is_major_syncing(self) } @@ -564,8 +579,9 @@ impl, H: ExHashT> } } -impl<'a, B: BlockT + 'static, S: NetworkSpecialization, H: ExHashT> - ::consensus::SyncOracle for &'a NetworkService { +impl<'a, B: BlockT + 'static, S: NetworkSpecialization, H: ExHashT> consensus::SyncOracle + for &'a NetworkService +{ fn is_major_syncing(&mut self) -> bool { NetworkService::is_major_syncing(self) } diff --git a/substrate/node-template/src/cli.rs b/substrate/node-template/src/cli.rs index f0b429e0fa..15c1a0486f 100644 --- a/substrate/node-template/src/cli.rs +++ b/substrate/node-template/src/cli.rs @@ -29,15 +29,15 @@ pub fn run(args: I, exit: E, version: VersionInfo) -> error::Result<()> match config.roles { ServiceRoles::LIGHT => run_until_exit( runtime, - service::new_light(config).map_err(|e| format!("{:?}", e))?, + service::new_light(config)?, exit ), _ => run_until_exit( runtime, - service::new_full(config).map_err(|e| format!("{:?}", e))?, + service::new_full(config)?, exit ), - }.map_err(|e| format!("{:?}", e)) + } }), ParseAndPrepare::BuildSpec(cmd) => cmd.run(load_spec), ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder(|config: Config<_>| diff --git a/substrate/node-template/src/main.rs b/substrate/node-template/src/main.rs index 024efcc7db..1f286a2237 100644 --- a/substrate/node-template/src/main.rs +++ b/substrate/node-template/src/main.rs @@ -10,7 +10,7 @@ mod cli; pub use substrate_cli::{VersionInfo, IntoExit, error}; -fn main() { +fn main() -> Result<(), cli::error::Error> { let version = VersionInfo { name: "Substrate Node", commit: env!("VERGEN_SHA_SHORT"), @@ -21,8 +21,5 @@ fn main() { support_url: "support.anonymous.an", }; - if let Err(e) = cli::run(::std::env::args(), cli::Exit, version) { - eprintln!("Fatal error: {}\n\n{:?}", e, e); - std::process::exit(1) - } + cli::run(std::env::args(), cli::Exit, version) } diff --git a/substrate/node/cli/src/lib.rs b/substrate/node/cli/src/lib.rs index 7eb3bb89c3..d339952ca8 100644 --- a/substrate/node/cli/src/lib.rs +++ b/substrate/node/cli/src/lib.rs @@ -172,15 +172,15 @@ pub fn run(args: I, exit: E, version: cli::VersionInfo) -> error::Resul match config.roles { ServiceRoles::LIGHT => run_until_exit( runtime, - service::new_light(config).map_err(|e| format!("{:?}", e))?, + service::new_light(config)?, exit ), _ => run_until_exit( runtime, - service::new_full(config).map_err(|e| format!("{:?}", e))?, + service::new_full(config)?, exit ), - }.map_err(|e| format!("{:?}", e)) + } }), ParseAndPrepare::BuildSpec(cmd) => cmd.run(load_spec), ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder(|config: Config<_, _>| diff --git a/substrate/node/src/main.rs b/substrate/node/src/main.rs index ca4a6b4c60..9f76cf638c 100644 --- a/substrate/node/src/main.rs +++ b/substrate/node/src/main.rs @@ -43,7 +43,7 @@ impl cli::IntoExit for Exit { } } -fn main() { +fn main() -> Result<(), cli::error::Error> { let version = VersionInfo { name: "Substrate Node", commit: env!("VERGEN_SHA_SHORT"), @@ -54,8 +54,5 @@ fn main() { support_url: "https://github.com/paritytech/substrate/issues/new", }; - if let Err(e) = cli::run(::std::env::args(), Exit, version) { - eprintln!("Fatal error: {}\n\n{:?}", e, e); - std::process::exit(1) - } + cli::run(std::env::args(), Exit, version) }