From 94b17ce02bfdc6072ba9f25d10973535ff6edeba Mon Sep 17 00:00:00 2001 From: Sean Date: Fri, 2 Oct 2020 08:47:00 +0000 Subject: [PATCH] Add UPnP support for Lighthouse (#1587) Adding UPnP support will help grow the DHT by allowing NAT traversal for peers with UPnP supported routers. ## Issue Addressed #927 ## Proposed Changes Using IGD library: https://docs.rs/igd/0.10.0/igd/ Adding the the libp2p tcp port and discovery udp port. If this fails it simply logs the attempt and moves on ## Additional Info Co-authored-by: Age Manning --- Cargo.lock | 41 +++++ account_manager/Cargo.toml | 2 +- beacon_node/Cargo.toml | 2 +- beacon_node/beacon_chain/Cargo.toml | 2 +- beacon_node/client/Cargo.toml | 2 +- beacon_node/eth1/Cargo.toml | 2 +- beacon_node/eth2_libp2p/Cargo.toml | 4 +- beacon_node/eth2_libp2p/src/config.rs | 4 + beacon_node/eth2_libp2p/src/discovery/mod.rs | 56 ++++++- beacon_node/genesis/Cargo.toml | 2 +- beacon_node/network/Cargo.toml | 6 +- beacon_node/network/src/lib.rs | 1 + beacon_node/network/src/nat.rs | 154 +++++++++++++++++++ beacon_node/network/src/service.rs | 53 ++++++- beacon_node/rest_api/Cargo.toml | 2 +- beacon_node/src/cli.rs | 6 + beacon_node/src/config.rs | 6 +- beacon_node/timer/Cargo.toml | 2 +- beacon_node/websocket_server/Cargo.toml | 2 +- boot_node/Cargo.toml | 2 +- common/hashset_delay/Cargo.toml | 4 +- common/rest_types/Cargo.toml | 2 +- lcli/Cargo.toml | 2 +- lighthouse/Cargo.toml | 2 +- lighthouse/environment/Cargo.toml | 2 +- lighthouse/environment/src/lib.rs | 4 +- testing/eth1_test_rig/Cargo.toml | 2 +- testing/simulator/Cargo.toml | 2 +- validator_client/Cargo.toml | 4 +- 29 files changed, 342 insertions(+), 33 deletions(-) create mode 100644 beacon_node/network/src/nat.rs diff --git a/Cargo.lock b/Cargo.lock index 3679b598a55..535511c438c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -256,6 +256,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0db678acb667b525ac40a324fc5f7d3390e29239b31c7327bb8157f5b4fff593" +[[package]] +name = "attohttpc" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf13118df3e3dce4b5ac930641343b91b656e4e72c8f8325838b01a4b1c9d45" +dependencies = [ + "http 0.2.1", + "log 0.4.11", + "url 2.1.1", +] + [[package]] name = "atty" version = "0.2.14" @@ -2400,6 +2411,19 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "igd" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd32c880165b2f776af0b38d206d1cabaebcf46c166ac6ae004a5d45f7d48ef" +dependencies = [ + "attohttpc", + "log 0.4.11", + "rand 0.7.3", + "url 2.1.1", + "xmltree", +] + [[package]] name = "impl-codec" version = "0.4.2" @@ -3316,8 +3340,10 @@ dependencies = [ "fnv", "futures 0.3.5", "genesis", + "get_if_addrs", "hashset_delay", "hex 0.4.2", + "igd", "itertools 0.9.0", "lazy_static", "lighthouse_metrics", @@ -6462,6 +6488,21 @@ dependencies = [ "zeroize", ] +[[package]] +name = "xml-rs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" + +[[package]] +name = "xmltree" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f76badaccb0313f1f0cb6582c2973f2dd0620f9652eb7a5ff6ced0cc3ac922b3" +dependencies = [ + "xml-rs", +] + [[package]] name = "yaml-rust" version = "0.4.4" diff --git a/account_manager/Cargo.toml b/account_manager/Cargo.toml index 9a533aea28d..a225af0812d 100644 --- a/account_manager/Cargo.toml +++ b/account_manager/Cargo.toml @@ -28,6 +28,6 @@ eth2_wallet = { path = "../crypto/eth2_wallet" } eth2_wallet_manager = { path = "../common/eth2_wallet_manager" } rand = "0.7.2" validator_dir = { path = "../common/validator_dir" } -tokio = { version = "0.2.21", features = ["full"] } +tokio = { version = "0.2.22", features = ["full"] } eth2_keystore = { path = "../crypto/eth2_keystore" } account_utils = { path = "../common/account_utils" } diff --git a/beacon_node/Cargo.toml b/beacon_node/Cargo.toml index 0fb55b6f84f..bce3c402ece 100644 --- a/beacon_node/Cargo.toml +++ b/beacon_node/Cargo.toml @@ -26,7 +26,7 @@ slog = { version = "2.5.2", features = ["max_level_trace", "release_max_level_tr slog-term = "2.5.0" slog-async = "2.5.0" ctrlc = { version = "3.1.4", features = ["termination"] } -tokio = { version = "0.2.21", features = ["time"] } +tokio = { version = "0.2.22", features = ["time"] } exit-future = "0.2.0" dirs = "2.0.2" logging = { path = "../common/logging" } diff --git a/beacon_node/beacon_chain/Cargo.toml b/beacon_node/beacon_chain/Cargo.toml index 9694e8fb39d..481039c489e 100644 --- a/beacon_node/beacon_chain/Cargo.toml +++ b/beacon_node/beacon_chain/Cargo.toml @@ -39,7 +39,7 @@ eth2_ssz_derive = "0.1.0" state_processing = { path = "../../consensus/state_processing" } tree_hash = "0.1.0" types = { path = "../../consensus/types" } -tokio = "0.2.21" +tokio = "0.2.22" eth1 = { path = "../eth1" } websocket_server = { path = "../websocket_server" } futures = "0.3.5" diff --git a/beacon_node/client/Cargo.toml b/beacon_node/client/Cargo.toml index de6f7e59d76..8af3bccf48b 100644 --- a/beacon_node/client/Cargo.toml +++ b/beacon_node/client/Cargo.toml @@ -28,7 +28,7 @@ error-chain = "0.12.2" serde_yaml = "0.8.11" slog = { version = "2.5.2", features = ["max_level_trace"] } slog-async = "2.5.0" -tokio = "0.2.21" +tokio = "0.2.22" dirs = "2.0.2" futures = "0.3.5" reqwest = { version = "0.10.4", features = ["native-tls-vendored"] } diff --git a/beacon_node/eth1/Cargo.toml b/beacon_node/eth1/Cargo.toml index 404078c802d..37eea241261 100644 --- a/beacon_node/eth1/Cargo.toml +++ b/beacon_node/eth1/Cargo.toml @@ -24,7 +24,7 @@ tree_hash = "0.1.0" eth2_hashing = "0.1.0" parking_lot = "0.11.0" slog = "2.5.2" -tokio = { version = "0.2.21", features = ["full"] } +tokio = { version = "0.2.22", features = ["full"] } state_processing = { path = "../../consensus/state_processing" } libflate = "1.0.0" lighthouse_metrics = { path = "../../common/lighthouse_metrics"} diff --git a/beacon_node/eth2_libp2p/Cargo.toml b/beacon_node/eth2_libp2p/Cargo.toml index 2df5123b55b..e095739172f 100644 --- a/beacon_node/eth2_libp2p/Cargo.toml +++ b/beacon_node/eth2_libp2p/Cargo.toml @@ -15,7 +15,7 @@ eth2_ssz = "0.1.2" eth2_ssz_derive = "0.1.0" slog = { version = "2.5.2", features = ["max_level_trace"] } lighthouse_version = { path = "../../common/lighthouse_version" } -tokio = { version = "0.2.21", features = ["time", "macros"] } +tokio = { version = "0.2.22", features = ["time", "macros"] } futures = "0.3.5" error-chain = "0.12.2" dirs = "2.0.2" @@ -46,7 +46,7 @@ default-features = false features = ["websocket", "identify", "mplex", "noise", "gossipsub", "dns", "tcp-tokio"] [dev-dependencies] -tokio = { version = "0.2.21", features = ["full"] } +tokio = { version = "0.2.22", features = ["full"] } slog-stdlog = "4.0.0" slog-term = "2.5.0" slog-async = "2.5.0" diff --git a/beacon_node/eth2_libp2p/src/config.rs b/beacon_node/eth2_libp2p/src/config.rs index 73094642d77..9499f213f8b 100644 --- a/beacon_node/eth2_libp2p/src/config.rs +++ b/beacon_node/eth2_libp2p/src/config.rs @@ -67,6 +67,9 @@ pub struct Config { /// Disables the discovery protocol from starting. pub disable_discovery: bool, + /// Attempt to construct external port mappings with UPnP. + pub upnp_enabled: bool, + /// List of extra topics to initially subscribe to as strings. pub topics: Vec, } @@ -136,6 +139,7 @@ impl Default for Config { trusted_peers: vec![], client_version: lighthouse_version::version_with_platform(), disable_discovery: false, + upnp_enabled: true, topics: Vec::new(), } } diff --git a/beacon_node/eth2_libp2p/src/discovery/mod.rs b/beacon_node/eth2_libp2p/src/discovery/mod.rs index b1a74b2d282..b065265da40 100644 --- a/beacon_node/eth2_libp2p/src/discovery/mod.rs +++ b/beacon_node/eth2_libp2p/src/discovery/mod.rs @@ -155,7 +155,7 @@ pub struct Discovery { /// Indicates if the discovery service has been started. When the service is disabled, this is /// always false. - started: bool, + pub started: bool, /// Logger for the discovery behaviour. log: slog::Logger, @@ -358,6 +358,54 @@ impl Discovery { } } + /// Updates the local ENR TCP port. + /// There currently isn't a case to update the address here. We opt for discovery to + /// automatically update the external address. + /// + /// If the external address needs to be modified, use `update_enr_udp_socket. + pub fn update_enr_tcp_port(&mut self, port: u16) -> Result<(), String> { + self.discv5 + .enr_insert("tcp", port.to_be_bytes().into()) + .map_err(|e| format!("{:?}", e))?; + + // replace the global version + *self.network_globals.local_enr.write() = self.discv5.local_enr(); + // persist modified enr to disk + enr::save_enr_to_disk(Path::new(&self.enr_dir), &self.local_enr(), &self.log); + Ok(()) + } + + /// Updates the local ENR UDP socket. + /// + /// This is with caution. Discovery should automatically maintain this. This should only be + /// used when automatic discovery is disabled. + pub fn update_enr_udp_socket(&mut self, socket_addr: SocketAddr) -> Result<(), String> { + match socket_addr { + SocketAddr::V4(socket) => { + self.discv5 + .enr_insert("ip", socket.ip().octets().into()) + .map_err(|e| format!("{:?}", e))?; + self.discv5 + .enr_insert("udp", socket.port().to_be_bytes().into()) + .map_err(|e| format!("{:?}", e))?; + } + SocketAddr::V6(socket) => { + self.discv5 + .enr_insert("ip6", socket.ip().octets().into()) + .map_err(|e| format!("{:?}", e))?; + self.discv5 + .enr_insert("udp6", socket.port().to_be_bytes().into()) + .map_err(|e| format!("{:?}", e))?; + } + } + + // replace the global version + *self.network_globals.local_enr.write() = self.discv5.local_enr(); + // persist modified enr to disk + enr::save_enr_to_disk(Path::new(&self.enr_dir), &self.local_enr(), &self.log); + Ok(()) + } + /// Adds/Removes a subnet from the ENR Bitfield pub fn update_enr_bitfield(&mut self, subnet_id: SubnetId, value: bool) -> Result<(), String> { let id = *subnet_id as usize; @@ -390,9 +438,9 @@ impl Discovery { .map_err(|_| String::from("Subnet ID out of bounds, could not set subnet ID"))?; // insert the bitfield into the ENR record - let _ = self - .discv5 - .enr_insert(BITFIELD_ENR_KEY, current_bitfield.as_ssz_bytes()); + self.discv5 + .enr_insert(BITFIELD_ENR_KEY, current_bitfield.as_ssz_bytes()) + .map_err(|e| format!("{:?}", e))?; // replace the global version *self.network_globals.local_enr.write() = self.discv5.local_enr(); diff --git a/beacon_node/genesis/Cargo.toml b/beacon_node/genesis/Cargo.toml index c7e2f62ff48..9510a840db2 100644 --- a/beacon_node/genesis/Cargo.toml +++ b/beacon_node/genesis/Cargo.toml @@ -18,7 +18,7 @@ merkle_proof = { path = "../../consensus/merkle_proof" } eth2_ssz = "0.1.2" eth2_hashing = "0.1.0" tree_hash = "0.1.0" -tokio = { version = "0.2.21", features = ["full"] } +tokio = { version = "0.2.22", features = ["full"] } parking_lot = "0.11.0" slog = "2.5.2" exit-future = "0.2.0" diff --git a/beacon_node/network/Cargo.toml b/beacon_node/network/Cargo.toml index 0448e7762f8..c5d786ff016 100644 --- a/beacon_node/network/Cargo.toml +++ b/beacon_node/network/Cargo.toml @@ -28,17 +28,17 @@ eth2_ssz_types = { path = "../../consensus/ssz_types" } tree_hash = "0.1.0" futures = "0.3.5" error-chain = "0.12.2" -tokio = { version = "0.2.21", features = ["full"] } +tokio = { version = "0.2.22", features = ["full"] } parking_lot = "0.11.0" smallvec = "1.4.1" -# TODO: Remove rand crate for mainnet -# NOTE: why? rand = "0.7.3" fnv = "1.0.6" rlp = "0.4.5" lazy_static = "1.4.0" lighthouse_metrics = { path = "../../common/lighthouse_metrics" } environment = { path = "../../lighthouse/environment" } +igd = "0.11.1" itertools = "0.9.0" num_cpus = "1.13.0" lru_cache = { path = "../../common/lru_cache" } +get_if_addrs = "0.5.3" diff --git a/beacon_node/network/src/lib.rs b/beacon_node/network/src/lib.rs index 30795a63ef3..5ac74e2edd6 100644 --- a/beacon_node/network/src/lib.rs +++ b/beacon_node/network/src/lib.rs @@ -8,6 +8,7 @@ pub mod service; mod attestation_service; mod beacon_processor; mod metrics; +mod nat; mod persisted_dht; mod router; mod sync; diff --git a/beacon_node/network/src/nat.rs b/beacon_node/network/src/nat.rs new file mode 100644 index 00000000000..5a1edd68264 --- /dev/null +++ b/beacon_node/network/src/nat.rs @@ -0,0 +1,154 @@ +//! This houses various NAT hole punching strategies. +//! +//! Currently supported strategies: +//! - UPnP + +use crate::{NetworkConfig, NetworkMessage}; +use get_if_addrs::get_if_addrs; +use slog::{debug, info, warn}; +use std::net::{IpAddr, SocketAddr, SocketAddrV4}; +use tokio::sync::mpsc; +use types::EthSpec; + +/// Configuration required to construct the UPnP port mappings. +pub struct UPnPConfig { + /// The local tcp port. + tcp_port: u16, + /// The local udp port. + udp_port: u16, + /// Whether discovery is enabled or not. + disable_discovery: bool, +} + +impl From<&NetworkConfig> for UPnPConfig { + fn from(config: &NetworkConfig) -> Self { + UPnPConfig { + tcp_port: config.libp2p_port, + udp_port: config.discovery_port, + disable_discovery: config.disable_discovery, + } + } +} + +/// Attempts to construct external port mappings with UPnP. +pub fn construct_upnp_mappings( + config: UPnPConfig, + network_send: mpsc::UnboundedSender>, + log: slog::Logger, +) { + debug!(log, "UPnP Initialising routes"); + match igd::search_gateway(Default::default()) { + Err(e) => debug!(log, "UPnP not available"; "error" => %e), + Ok(gateway) => { + // Need to find the local listening address matched with the router subnet + let mut local_ip = None; + let interfaces = match get_if_addrs() { + Ok(v) => v, + Err(e) => { + debug!(log, "UPnP failed to get local interfaces"; "error" => %e); + return; + } + }; + for interface in interfaces { + // Just use the first IP of the first interface that is not a loopback + if !interface.is_loopback() { + local_ip = Some(interface.ip()); + } + } + + if local_ip.is_none() { + debug!(log, "UPnP failed to find local IP address"); + return; + } + + let local_ip = local_ip.expect("IP exists"); + + match local_ip { + IpAddr::V4(address) => { + let libp2p_socket = SocketAddrV4::new(address, config.tcp_port); + let external_ip = gateway.get_external_ip(); + // We add specific port mappings rather than getting the router to arbitrary assign + // one. + // I've found this to be more reliable. If multiple users are behind a single + // router, they should ideally try to set different port numbers. + let tcp_socket = match gateway.add_port( + igd::PortMappingProtocol::TCP, + libp2p_socket.port(), + libp2p_socket, + 0, + "lighthouse-tcp", + ) { + Err(e) => { + debug!(log, "UPnP could not construct libp2p port route"; "error" => %e); + None + } + Ok(_) => { + info!(log, "UPnP TCP route established"; "external_socket" => format!("{}:{}", external_ip.as_ref().map(|ip| ip.to_string()).unwrap_or_else(|_| "".into()), config.tcp_port)); + external_ip + .as_ref() + .map(|ip| SocketAddr::new(ip.clone().into(), config.tcp_port)) + .ok() + } + }; + + let udp_socket = if !config.disable_discovery { + let discovery_socket = SocketAddrV4::new(address, config.udp_port); + match gateway.add_port( + igd::PortMappingProtocol::UDP, + discovery_socket.port(), + discovery_socket, + 0, + "lighthouse-udp", + ) { + Err(e) => { + debug!(log, "UPnP could not construct discovery port route"; "error" => %e); + None + } + Ok(_) => { + info!(log, "UPnP UDP route established"; "external_socket" => format!("{}:{}", external_ip.as_ref().map(|ip| ip.to_string()).unwrap_or_else(|_| "".into()), config.tcp_port)); + external_ip + .map(|ip| SocketAddr::new(ip.into(), config.tcp_port)) + .ok() + } + } + } else { + None + }; + + // report any updates to the network service. + network_send.send(NetworkMessage::UPnPMappingEstablished{ tcp_socket, udp_socket }) + .unwrap_or_else(|e| warn!(log, "Could not send message to the network service"; "error" => %e)); + } + _ => debug!(log, "UPnP no routes constructed. IPv6 not supported"), + } + } + }; +} + +/// Removes the specified TCP and UDP port mappings. +pub fn remove_mappings(tcp_port: Option, udp_port: Option, log: &slog::Logger) { + if tcp_port.is_some() || udp_port.is_some() { + debug!(log, "Removing UPnP port mappings"); + match igd::search_gateway(Default::default()) { + Ok(gateway) => { + if let Some(tcp_port) = tcp_port { + match gateway.remove_port(igd::PortMappingProtocol::TCP, tcp_port) { + Ok(()) => debug!(log, "UPnP Removed TCP port mapping"; "port" => tcp_port), + Err(e) => { + debug!(log, "UPnP Failed to remove TCP port mapping"; "port" => tcp_port, "error" => %e) + } + } + } + if let Some(udp_port) = udp_port { + match gateway.remove_port(igd::PortMappingProtocol::UDP, udp_port) { + Ok(()) => debug!(log, "UPnP Removed UDP port mapping"; "port" => udp_port), + Err(e) => { + debug!(log, "UPnP Failed to remove UDP port mapping"; "port" => udp_port, "error" => %e) + } + } + } + } + Err(e) => debug!(log, "UPnP failed to remove mappings"; "error" => %e), + } + } +} diff --git a/beacon_node/network/src/service.rs b/beacon_node/network/src/service.rs index 1147562b4c7..a2af46e68b8 100644 --- a/beacon_node/network/src/service.rs +++ b/beacon_node/network/src/service.rs @@ -17,7 +17,7 @@ use eth2_libp2p::{MessageAcceptance, Service as LibP2PService}; use futures::prelude::*; use rest_types::ValidatorSubscription; use slog::{debug, error, info, o, trace, warn}; -use std::{collections::HashMap, sync::Arc, time::Duration}; +use std::{collections::HashMap, net::SocketAddr, sync::Arc, time::Duration}; use store::HotColdDB; use tokio::sync::mpsc; use tokio::time::Delay; @@ -70,6 +70,13 @@ pub enum NetworkMessage { /// The result of the validation validation_result: MessageAcceptance, }, + /// Called if a known external TCP socket address has been updated. + UPnPMappingEstablished { + /// The external TCP address has been updated. + tcp_socket: Option, + /// The external UDP address has been updated. + udp_socket: Option, + }, /// Reports a peer to the peer manager for performing an action. ReportPeer { peer_id: PeerId, action: PeerAction }, /// Disconnect an ban a peer, providing a reason. @@ -96,6 +103,12 @@ pub struct NetworkService { store: Arc>, /// A collection of global variables, accessible outside of the network service. network_globals: Arc>, + /// Stores potentially created UPnP mappings to be removed on shutdown. (TCP port and UDP + /// port). + upnp_mappings: (Option, Option), + /// Keeps track of if discovery is auto-updating or not. This is used to inform us if we should + /// update the UDP socket of discovery if the UPnP mappings get established. + discovery_auto_update: bool, /// A delay that expires when a new fork takes place. next_fork_update: Option, /// A timer for updating various network metrics. @@ -117,6 +130,20 @@ impl NetworkService { let network_log = executor.log().clone(); // build the network channel let (network_send, network_recv) = mpsc::unbounded_channel::>(); + + // try and construct UPnP port mappings if required. + let upnp_config = crate::nat::UPnPConfig::from(config); + let upnp_log = network_log.new(o!("service" => "UPnP")); + let upnp_network_send = network_send.clone(); + if config.upnp_enabled { + executor.spawn_blocking( + move || { + crate::nat::construct_upnp_mappings(upnp_config, upnp_network_send, upnp_log) + }, + "UPnP", + ); + } + // get a reference to the beacon chain store let store = beacon_chain.store.clone(); @@ -167,6 +194,8 @@ impl NetworkService { router_send, store, network_globals: network_globals.clone(), + upnp_mappings: (None, None), + discovery_auto_update: config.discv5_config.enr_update, next_fork_update, metrics_update, log: network_log, @@ -201,7 +230,6 @@ fn spawn_service( "Persisting DHT to store"; "Number of peers" => format!("{}", enrs.len()), ); - match persist_dht::(service.store.clone(), enrs) { Err(e) => error!( service.log, @@ -214,6 +242,9 @@ fn spawn_service( ), } + // attempt to remove port mappings + crate::nat::remove_mappings(service.upnp_mappings.0, service.upnp_mappings.1, &service.log); + info!(service.log, "Network service shutdown"); return; } @@ -240,6 +271,24 @@ fn spawn_service( NetworkMessage::SendError{ peer_id, error, id, reason } => { service.libp2p.respond_with_error(peer_id, id, error, reason); } + NetworkMessage::UPnPMappingEstablished { tcp_socket, udp_socket} => { + service.upnp_mappings = (tcp_socket.map(|s| s.port()), udp_socket.map(|s| s.port())); + // If there is an external TCP port update, modify our local ENR. + if let Some(tcp_socket) = tcp_socket { + if let Err(e) = service.libp2p.swarm.peer_manager().discovery_mut().update_enr_tcp_port(tcp_socket.port()) { + warn!(service.log, "Failed to update ENR"; "error" => e); + } + } + // if the discovery service is not auto-updating, update it with the + // UPnP mappings + if !service.discovery_auto_update { + if let Some(udp_socket) = udp_socket { + if let Err(e) = service.libp2p.swarm.peer_manager().discovery_mut().update_enr_udp_socket(udp_socket) { + warn!(service.log, "Failed to update ENR"; "error" => e); + } + } + } + }, NetworkMessage::ValidationResult { propagation_source, message_id, diff --git a/beacon_node/rest_api/Cargo.toml b/beacon_node/rest_api/Cargo.toml index 38a5a1e7d55..359d4e73656 100644 --- a/beacon_node/rest_api/Cargo.toml +++ b/beacon_node/rest_api/Cargo.toml @@ -24,7 +24,7 @@ state_processing = { path = "../../consensus/state_processing" } types = { path = "../../consensus/types" } http = "0.2.1" hyper = "0.13.5" -tokio = { version = "0.2.21", features = ["sync"] } +tokio = { version = "0.2.22", features = ["sync"] } url = "2.1.1" lazy_static = "1.4.0" eth2_config = { path = "../../common/eth2_config" } diff --git a/beacon_node/src/cli.rs b/beacon_node/src/cli.rs index 987f151adf5..aabafe40e41 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -75,6 +75,12 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .help("One or more comma-delimited base64-encoded ENR's to bootstrap the p2p network. Multiaddr is also supported.") .takes_value(true), ) + .arg( + Arg::with_name("disable-upnp") + .long("disable-upnp") + .help("Disables UPnP support. Setting this will prevent Lighthouse from attempting to automatically establish external port mappings.") + .takes_value(false), + ) .arg( Arg::with_name("enr-udp-port") .long("enr-udp-port") diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index ccd965381fb..46a96f1af85 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -474,7 +474,7 @@ pub fn set_network_config( config.enr_address = Some(resolved_addr); } - if cli_args.is_present("disable_enr_auto_update") { + if cli_args.is_present("disable-enr-auto-update") { config.discv5_config.enr_update = false; } @@ -483,6 +483,10 @@ pub fn set_network_config( warn!(log, "Discovery is disabled. New peers will not be found"); } + if cli_args.is_present("disable-upnp") { + config.upnp_enabled = false; + } + Ok(()) } diff --git a/beacon_node/timer/Cargo.toml b/beacon_node/timer/Cargo.toml index f7c35530274..2cee2c5deb3 100644 --- a/beacon_node/timer/Cargo.toml +++ b/beacon_node/timer/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" beacon_chain = { path = "../beacon_chain" } types = { path = "../../consensus/types" } slot_clock = { path = "../../common/slot_clock" } -tokio = { version = "0.2.21", features = ["full"] } +tokio = { version = "0.2.22", features = ["full"] } slog = "2.5.2" parking_lot = "0.11.0" futures = "0.3.5" diff --git a/beacon_node/websocket_server/Cargo.toml b/beacon_node/websocket_server/Cargo.toml index be914f19285..00aa24973d3 100644 --- a/beacon_node/websocket_server/Cargo.toml +++ b/beacon_node/websocket_server/Cargo.toml @@ -12,7 +12,7 @@ serde = "1.0.110" serde_derive = "1.0.110" serde_json = "1.0.52" slog = "2.5.2" -tokio = { version = "0.2.21", features = ["full"] } +tokio = { version = "0.2.22", features = ["full"] } types = { path = "../../consensus/types" } ws = "0.9.1" environment = { path = "../../lighthouse/environment" } diff --git a/boot_node/Cargo.toml b/boot_node/Cargo.toml index c788c2f1174..a5895f4c31e 100644 --- a/boot_node/Cargo.toml +++ b/boot_node/Cargo.toml @@ -13,7 +13,7 @@ eth2_testnet_config = { path = "../common/eth2_testnet_config" } eth2_ssz = { path = "../consensus/ssz" } slog = "2.5.2" sloggers = "1.0.1" -tokio = "0.2.21" +tokio = "0.2.22" log = "0.4.8" slog-term = "2.6.0" logging = { path = "../common/logging" } diff --git a/common/hashset_delay/Cargo.toml b/common/hashset_delay/Cargo.toml index 9fa9dfbd90c..b577b97d60c 100644 --- a/common/hashset_delay/Cargo.toml +++ b/common/hashset_delay/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] futures = "0.3.5" -tokio = { version = "0.2.21", features = ["time"] } +tokio = { version = "0.2.22", features = ["time"] } [dev-dependencies] -tokio = { version = "0.2.21", features = ["time", "rt-threaded", "macros"] } +tokio = { version = "0.2.22", features = ["time", "rt-threaded", "macros"] } diff --git a/common/rest_types/Cargo.toml b/common/rest_types/Cargo.toml index d9e021fe19d..c7e33d8b461 100644 --- a/common/rest_types/Cargo.toml +++ b/common/rest_types/Cargo.toml @@ -15,7 +15,7 @@ bls = { path = "../../crypto/bls" } serde = { version = "1.0.110", features = ["derive"] } rayon = "1.3.0" hyper = "0.13.5" -tokio = { version = "0.2.21", features = ["sync"] } +tokio = { version = "0.2.22", features = ["sync"] } environment = { path = "../../lighthouse/environment" } store = { path = "../../beacon_node/store" } beacon_chain = { path = "../../beacon_node/beacon_chain" } diff --git a/lcli/Cargo.toml b/lcli/Cargo.toml index c2c2c09b89e..70a17e237a3 100644 --- a/lcli/Cargo.toml +++ b/lcli/Cargo.toml @@ -28,7 +28,7 @@ dirs = "2.0.2" genesis = { path = "../beacon_node/genesis" } deposit_contract = { path = "../common/deposit_contract" } tree_hash = "0.1.0" -tokio = { version = "0.2.21", features = ["full"] } +tokio = { version = "0.2.22", features = ["full"] } clap_utils = { path = "../common/clap_utils" } eth2_libp2p = { path = "../beacon_node/eth2_libp2p" } validator_dir = { path = "../common/validator_dir", features = ["insecure_keys"] } diff --git a/lighthouse/Cargo.toml b/lighthouse/Cargo.toml index 3bc232d9fa4..5673bde53e6 100644 --- a/lighthouse/Cargo.toml +++ b/lighthouse/Cargo.toml @@ -14,7 +14,7 @@ milagro = ["bls/milagro"] [dependencies] beacon_node = { "path" = "../beacon_node" } -tokio = "0.2.21" +tokio = "0.2.22" slog = { version = "2.5.2", features = ["max_level_trace"] } sloggers = "1.0.0" types = { "path" = "../consensus/types" } diff --git a/lighthouse/environment/Cargo.toml b/lighthouse/environment/Cargo.toml index ee191f38d02..54a1f1f18ad 100644 --- a/lighthouse/environment/Cargo.toml +++ b/lighthouse/environment/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Paul Hauner "] edition = "2018" [dependencies] -tokio = { version = "0.2.21", features = ["macros"] } +tokio = { version = "0.2.22", features = ["macros"] } slog = { version = "2.5.2", features = ["max_level_trace"] } sloggers = "1.0.0" types = { "path" = "../../consensus/types" } diff --git a/lighthouse/environment/src/lib.rs b/lighthouse/environment/src/lib.rs index 81e8eee60fa..c175e6caba3 100644 --- a/lighthouse/environment/src/lib.rs +++ b/lighthouse/environment/src/lib.rs @@ -30,6 +30,8 @@ mod metrics; pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml"; const LOG_CHANNEL_SIZE: usize = 2048; +/// The maximum time in seconds the client will wait for all internal tasks to shutdown. +const MAXIMUM_SHUTDOWN_TIME: u64 = 3; /// Builds an `Environment`. pub struct EnvironmentBuilder { @@ -424,7 +426,7 @@ impl Environment { /// Shutdown the `tokio` runtime when all tasks are idle. pub fn shutdown_on_idle(self) { self.runtime - .shutdown_timeout(std::time::Duration::from_secs(2)) + .shutdown_timeout(std::time::Duration::from_secs(MAXIMUM_SHUTDOWN_TIME)) } /// Fire exit signal which shuts down all spawned services diff --git a/testing/eth1_test_rig/Cargo.toml b/testing/eth1_test_rig/Cargo.toml index 12d13b45169..cd0d1e85878 100644 --- a/testing/eth1_test_rig/Cargo.toml +++ b/testing/eth1_test_rig/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Paul Hauner "] edition = "2018" [dependencies] -tokio = { version = "0.2.21", features = ["time"] } +tokio = { version = "0.2.22", features = ["time"] } web3 = "0.11.0" futures = { version = "0.3.5", features = ["compat"] } types = { path = "../../consensus/types"} diff --git a/testing/simulator/Cargo.toml b/testing/simulator/Cargo.toml index 6670e3557c9..773d56bcb4a 100644 --- a/testing/simulator/Cargo.toml +++ b/testing/simulator/Cargo.toml @@ -13,7 +13,7 @@ types = { path = "../../consensus/types" } validator_client = { path = "../../validator_client" } parking_lot = "0.11.0" futures = "0.3.5" -tokio = "0.2.21" +tokio = "0.2.22" eth1_test_rig = { path = "../eth1_test_rig" } env_logger = "0.7.1" clap = "2.33.0" diff --git a/validator_client/Cargo.toml b/validator_client/Cargo.toml index 1bbde0c5adb..18c5cf4bf93 100644 --- a/validator_client/Cargo.toml +++ b/validator_client/Cargo.toml @@ -9,7 +9,7 @@ name = "validator_client" path = "src/lib.rs" [dev-dependencies] -tokio = { version = "0.2.21", features = ["time", "rt-threaded", "macros"] } +tokio = { version = "0.2.22", features = ["time", "rt-threaded", "macros"] } [dependencies] eth2_ssz = "0.1.2" @@ -28,7 +28,7 @@ serde_yaml = "0.8.13" slog = { version = "2.5.2", features = ["max_level_trace", "release_max_level_trace"] } slog-async = "2.5.0" slog-term = "2.5.0" -tokio = { version = "0.2.21", features = ["time"] } +tokio = { version = "0.2.22", features = ["time"] } futures = { version = "0.3.5", features = ["compat"] } dirs = "2.0.2" logging = { path = "../common/logging" }