diff --git a/beacon_node/src/cli.rs b/beacon_node/src/cli.rs index 9a2dfc1d49..8f42037f64 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -94,10 +94,12 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { Arg::with_name("enr-address") .long("enr-address") .value_name("ADDRESS") - .help("The IP address to broadcast to other peers on how to reach this node. \ + .help("The IP address/ DNS address to broadcast to other peers on how to reach this node. \ + If a DNS address is provided, the enr-address is set to the IP address it resolves to and \ + does not auto-update based on PONG responses in discovery. \ Set this only if you are sure other nodes can connect to your local node on this address. \ - Discovery will automatically find your external address,if possible. - ") + Discovery will automatically find your external address,if possible.") + .requires("enr-udp-port") .takes_value(true), ) .arg( diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index b852bb7f3d..2b848c81b3 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -9,7 +9,7 @@ use ssz::Encode; use std::fs; use std::fs::File; use std::io::prelude::*; -use std::net::{IpAddr, Ipv4Addr}; +use std::net::{IpAddr, Ipv4Addr, ToSocketAddrs}; use std::net::{TcpListener, UdpSocket}; use std::path::PathBuf; use types::{ChainSpec, EthSpec}; @@ -141,14 +141,6 @@ pub fn get_config( .collect::, _>>()?; } - if let Some(enr_address_str) = cli_args.value_of("enr-address") { - client_config.network.enr_address = Some( - enr_address_str - .parse() - .map_err(|_| format!("Invalid discovery address: {:?}", enr_address_str))?, - ) - } - if let Some(enr_udp_port_str) = cli_args.value_of("enr-udp-port") { client_config.network.enr_udp_port = Some( enr_udp_port_str @@ -178,6 +170,40 @@ pub fn get_config( client_config.network.enr_udp_port = Some(client_config.network.discovery_port); } + if let Some(enr_address) = cli_args.value_of("enr-address") { + let resolved_addr = match enr_address.parse::() { + Ok(addr) => addr, // // Input is an IpAddr + Err(_) => { + let mut addr = enr_address.to_string(); + // Appending enr-port to the dns hostname to appease `to_socket_addrs()` parsing. + // Since enr-update is disabled with a dns address, not setting the enr-udp-port + // will make the node undiscoverable. + if let Some(enr_udp_port) = client_config.network.enr_udp_port { + addr.push_str(&format!(":{}", enr_udp_port.to_string())); + } else { + return Err( + "enr-udp-port must be set for node to be discoverable with dns address" + .into(), + ); + } + // `to_socket_addr()` does the dns resolution + // Note: `to_socket_addrs()` is a blocking call + let resolved_addr = if let Ok(mut resolved_addrs) = addr.to_socket_addrs() { + // Pick the first ip from the list of resolved addresses + resolved_addrs + .next() + .map(|a| a.ip()) + .ok_or_else(|| format!("Resolved dns addr contains no entries"))? + } else { + return Err(format!("Failed to parse enr-address: {}", enr_address)); + }; + client_config.network.discv5_config.enr_update = false; + resolved_addr + } + }; + client_config.network.enr_address = Some(resolved_addr); + } + if cli_args.is_present("disable_enr_auto_update") { client_config.network.discv5_config.enr_update = false; }