diff --git a/substrate/polkadot/cli/src/lib.rs b/substrate/polkadot/cli/src/lib.rs index 816ec0e758576820b863ade3d9d61fc317dc0037..ea617d4a7ba99809f4816ff807f4a234668f36ad 100644 --- a/substrate/polkadot/cli/src/lib.rs +++ b/substrate/polkadot/cli/src/lib.rs @@ -171,14 +171,11 @@ pub fn run<I, T, W>(args: I, worker: W) -> error::Result<()> where panic_hook::set(); let yaml = load_yaml!("./cli.yml"); - let matches = match clap::App::from_yaml(yaml).version(&(crate_version!().to_owned() + "\n")[..]).get_matches_from_safe(args) { - Ok(m) => m, - Err(ref e) if e.kind == clap::ErrorKind::VersionDisplayed => return Ok(()), - Err(ref e) if e.kind == clap::ErrorKind::HelpDisplayed => { - print!("{}", e); - return Ok(()) - } - Err(e) => e.exit(), + let matches = match clap::App::from_yaml(yaml) + .version(&(crate_version!().to_owned() + "\n")[..]) + .get_matches_from_safe(args) { + Ok(m) => m, + Err(e) => e.exit(), }; // TODO [ToDr] Split parameters parsing from actual execution. diff --git a/substrate/substrate/network-libp2p/src/network_state.rs b/substrate/substrate/network-libp2p/src/network_state.rs index 830a74fc0f431e448f173989141a2cc3f423ed5a..00b97eecf9a8200db12c4ea151f15a46ade05c9f 100644 --- a/substrate/substrate/network-libp2p/src/network_state.rs +++ b/substrate/substrate/network-libp2p/src/network_state.rs @@ -17,7 +17,7 @@ use bytes::Bytes; use fnv::{FnvHashMap, FnvHashSet}; use futures::sync::mpsc; -use libp2p::core::{Multiaddr, AddrComponent, Endpoint, UniqueConnec}; +use libp2p::core::{multiaddr::ToMultiaddr, Multiaddr, AddrComponent, Endpoint, UniqueConnec}; use libp2p::core::{UniqueConnecState, PeerId as PeerstorePeerId, PublicKey}; use libp2p::kad::KadConnecController; use libp2p::peerstore::{Peerstore, PeerAccess}; @@ -150,10 +150,6 @@ impl NetworkState { PeersStorage::Memory(MemoryPeerstore::empty()) }; - for bootnode in config.boot_nodes.iter() { - parse_and_add_to_peerstore(bootnode, &peerstore)?; - } - let reserved_peers = { let mut reserved_peers = FnvHashSet::with_capacity_and_hasher( config.reserved_nodes.len(), @@ -391,6 +387,12 @@ impl NetworkState { Ok(peer_id) } + /// Adds a peer to the internal peer store. + /// Returns an error if the peer address is invalid. + pub fn add_peer(&self, peer: &str) -> Result<PeerstorePeerId, Error> { + parse_and_add_to_peerstore(peer, &self.peerstore) + } + /// Adds a reserved peer to the list of reserved peers. /// Returns an error if the peer address is invalid. pub fn add_reserved_peer(&self, peer: &str) -> Result<(), Error> { @@ -753,13 +755,12 @@ fn num_open_custom_connections(connections: &Connections) -> u32 { /// to the given peerstore. Returns the corresponding peer ID. fn parse_and_add_to_peerstore(addr_str: &str, peerstore: &PeersStorage) -> Result<PeerstorePeerId, Error> { - let mut addr: Multiaddr = addr_str.parse() - .map_err(|_| ErrorKind::AddressParse)?; - let p2p_component = addr.pop().ok_or(ErrorKind::AddressParse)?; - let peer_id = match p2p_component { - AddrComponent::P2P(key) | AddrComponent::IPFS(key) => + + let mut addr = addr_str.to_multiaddr().map_err(|_| ErrorKind::AddressParse)?; + let peer_id = match addr.pop() { + Some(AddrComponent::P2P(key)) | Some(AddrComponent::IPFS(key)) => PeerstorePeerId::from_bytes(key).map_err(|_| ErrorKind::AddressParse)?, - _ => return Err(ErrorKind::BadProtocol.into()), + _ => return Err(ErrorKind::AddressParse.into()), }; // Registering the bootstrap node with a TTL of 100000 years TODO: wrong diff --git a/substrate/substrate/network-libp2p/src/service.rs b/substrate/substrate/network-libp2p/src/service.rs index 6267e4e09c3b81a66cf17202a5ad80770bc16462..23958cca5aaef31f2eedb1142a7bb90c4edc448f 100644 --- a/substrate/substrate/network-libp2p/src/service.rs +++ b/substrate/substrate/network-libp2p/src/service.rs @@ -473,29 +473,51 @@ fn init_thread( }, } } - - // Explicitely connect to the boostrap nodes as a temporary measure. - trace!(target: "sub-libp2p", "Dialing bootnodes"); + // Explicitely connect to _all_ the boostrap nodes as a temporary measure. for bootnode in shared.config.boot_nodes.iter() { - // TODO: this code is copy-pasted from `network_state`, but it is - // temporary anyway - let mut addr: Multiaddr = bootnode.parse() - .map_err(|_| ErrorKind::AddressParse)?; - let p2p_component = addr.pop().ok_or(ErrorKind::AddressParse)?; - let peer_id = match p2p_component { - AddrComponent::P2P(key) | AddrComponent::IPFS(key) => - PeerstorePeerId::from_bytes(key).map_err(|_| ErrorKind::AddressParse)?, - _ => return Err(ErrorKind::BadProtocol.into()), - }; + match shared.network_state.add_peer(bootnode) { + Ok(peer_id) => { + trace!(target: "sub-libp2p", "Dialing bootnode {:?}", peer_id); + for proto in shared.protocols.read().0.clone().into_iter() { + open_peer_custom_proto( + shared.clone(), + transport.clone(), + proto, + peer_id.clone(), + &swarm_controller + ) + } + }, + Err(Error(ErrorKind::AddressParse, _)) => { + // fallback: trying with IP:Port + let multi = match bootnode.parse::<SocketAddr>() { + Ok(SocketAddr::V4(socket)) => + format!("/ip4/{}/tcp/{}", socket.ip(), socket.port()).parse::<Multiaddr>(), + Ok(SocketAddr::V6(socket)) => + format!("/ip6/{}/tcp/{}", socket.ip(), socket.port()).parse::<Multiaddr>(), + _ => { + warn!(target: "sub-libp2p", "Not a valid Bootnode Address {:}", bootnode); + continue; + } + }; - for proto in shared.protocols.read().0.clone().into_iter() { - open_peer_custom_proto( - shared.clone(), - transport.clone(), - proto, - peer_id.clone(), - &swarm_controller - ) + if let Ok(addr) = multi { + trace!(target: "sub-libp2p", "Missing PeerId for Bootnode {:}. Querying", bootnode); + for proto in shared.protocols.read().0.clone().into_iter() { + connect_with_query_peer_id( + shared.clone(), + transport.clone(), + proto, + addr.clone(), + &swarm_controller + ) + } + } else { + warn!(target: "sub-libp2p", "Not a valid Bootnode Address {:}", bootnode); + continue; + } + }, + Err(err) => warn!(target:"sub-libp2p", "Couldn't parse Bootnode Address: {}", err), } } @@ -978,6 +1000,58 @@ fn connect_to_nodes<T, To, St, C>( } } + +fn connect_with_query_peer_id<T, To, St, C>( + shared: Arc<Shared>, + base_transport: T, + proto: RegisteredProtocol<Arc<NetworkProtocolHandler + Send + Sync>>, + addr: Multiaddr, + swarm_controller: &SwarmController<St> +) + where T: MuxedTransport<Output = TransportOutput<To>> + Clone + 'static, + T::MultiaddrFuture: 'static, + To: AsyncRead + AsyncWrite + 'static, + St: MuxedTransport<Output = FinalUpgrade<C>> + Clone + 'static, + C: 'static, +{ + let addr2 = addr.clone(); + let with_proto = base_transport + .clone() + .and_then(move |out, endpoint, client_addr| { + trace!(target: "sub-libp2p", "in"); + let socket = out.socket; + let original_addr = out.original_addr; + out.info + .and_then(move |info| { + let _ = process_identify_info(shared, &info, original_addr, + endpoint, &base_transport); + trace!(target: "sub-libp2p", "Bootnode {:} found with peer id: {:?}", + addr2, info.info.public_key.into_peer_id()); + upgrade::apply(socket, proto, endpoint, client_addr) + }) + }) + .and_then(move |out, _endpoint, client_addr| + client_addr.map(move |client_addr| + (FinalUpgrade::Custom(out, client_addr.clone()), future::ok(client_addr)) + ) + ); + + let with_timeout = TransportTimeout::new(with_proto, Duration::from_secs(10)); + let with_err = with_timeout + .map_err({ + let addr = addr.clone(); + move |err| { + warn!(target: "sub-libp2p", "Error while dialing {:?} to query peer id: {:?}", + addr, err); + err + } + }); + + let _ = swarm_controller.dial(addr.clone(), with_err) + .map_err( move |err| warn!(target: "sub-libp2p", + "Error when querying peer node info {:} of {:}", err, addr)); +} + /// If necessary, dials the given address for the given protocol and using the /// given `swarm_controller`. Has no effect if we already dialed earlier. /// Checks that the peer ID matches `expected_peer_id`.