reuse beacon_node methods for initializing network configs in boot_node (#1520)

## Issue Addressed

#1378

## Proposed Changes

Boot node reuses code from beacon_node to initialize network config. This also enables using the network directory to store/load the enr and the private key.

## Additional Info

Note that before this PR the port cli arguments were off (the argument was named `enr-port` but used as `boot-node-enr-port`).
Therefore as port always the cli port argument was used (for both enr and listening). Now the enr-port argument can be used to overwrite the listening port as the public port others should connect to.

Last but not least note, that this restructuring reuses `ethlibp2p::NetworkConfig` that has many more options than the ones used in the boot node. For example the network config has an own `discv5_config` field that gets never used in the boot node and instead another `Discv5Config` gets created later in the boot node process.

Co-authored-by: Age Manning <Age@AgeManning.com>
This commit is contained in:
blacktemplar
2020-08-21 12:00:01 +00:00
parent 3cfd70d7fd
commit 2bc9115a94
10 changed files with 296 additions and 274 deletions

View File

@@ -1,7 +1,12 @@
use beacon_node::{get_data_dir, set_network_config};
use clap::ArgMatches;
use discv5::{enr::CombinedKey, Enr};
use eth2_libp2p::{
discovery::{create_enr_builder_from_config, use_or_load_enr},
load_private_key, CombinedKeyExt, NetworkConfig,
};
use std::convert::TryFrom;
use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
use std::net::SocketAddr;
/// A set of configuration parameters for the bootnode, established from CLI arguments.
pub struct BootNodeConfig {
@@ -17,17 +22,22 @@ impl TryFrom<&ArgMatches<'_>> for BootNodeConfig {
type Error = String;
fn try_from(matches: &ArgMatches<'_>) -> Result<Self, Self::Error> {
let listen_address = matches
.value_of("listen-address")
.expect("required parameter")
.parse::<IpAddr>()
.map_err(|_| "Invalid listening address".to_string())?;
let data_dir = get_data_dir(matches);
let listen_port = matches
.value_of("port")
.expect("required parameter")
.parse::<u16>()
.map_err(|_| "Invalid listening port".to_string())?;
let mut network_config = NetworkConfig::default();
let logger = slog_scope::logger();
set_network_config(&mut network_config, matches, &data_dir, &logger, true)?;
let private_key = load_private_key(&network_config, &logger);
let local_key = CombinedKey::from_libp2p(&private_key)?;
let mut local_enr = create_enr_builder_from_config(&network_config)
.build(&local_key)
.map_err(|e| format!("Failed to build ENR: {:?}", e))?;
use_or_load_enr(&local_key, &mut local_enr, &network_config, &logger)?;
let boot_nodes = {
if let Some(boot_nodes) = matches.value_of("boot-nodes") {
@@ -40,34 +50,11 @@ impl TryFrom<&ArgMatches<'_>> for BootNodeConfig {
}
};
let enr_port = {
if let Some(port) = matches.value_of("boot-node-enr-port") {
port.parse::<u16>()
.map_err(|_| "Invalid ENR port".to_string())?
} else {
listen_port
}
};
let enr_address = {
let address_string = matches
.value_of("boot-node-enr-address")
.expect("required parameter");
resolve_address(address_string.into(), enr_port)?
};
let auto_update = matches.is_present("enable-enr_auto_update");
// the address to listen on
let listen_socket = SocketAddr::new(listen_address, enr_port);
// Generate a new key and build a new ENR
let local_key = CombinedKey::generate_secp256k1();
let local_enr = discv5::enr::EnrBuilder::new("v4")
.ip(enr_address)
.udp(enr_port)
.build(&local_key)
.map_err(|e| format!("Failed to build ENR: {:?}", e))?;
let listen_socket =
SocketAddr::new(network_config.listen_address, network_config.discovery_port);
Ok(BootNodeConfig {
listen_socket,
@@ -78,25 +65,3 @@ impl TryFrom<&ArgMatches<'_>> for BootNodeConfig {
})
}
}
/// Resolves an IP/DNS string to an IpAddr.
fn resolve_address(address_string: String, port: u16) -> Result<IpAddr, String> {
match address_string.parse::<IpAddr>() {
Ok(addr) => Ok(addr), // valid IpAddr
Err(_) => {
let mut addr = address_string.clone();
// Appending enr-port to the dns hostname to appease `to_socket_addrs()` parsing.
addr.push_str(&format!(":{}", port.to_string()));
// `to_socket_addr()` does the dns resolution
// Note: `to_socket_addrs()` is a blocking call
addr.to_socket_addrs()
.map(|mut resolved_addrs|
// Pick the first ip from the list of resolved addresses
resolved_addrs
.next()
.map(|a| a.ip())
.ok_or_else(|| "Resolved dns addr contains no entries".to_string()))
.map_err(|_| format!("Failed to parse enr-address: {}", address_string))?
}
}
}