diff --git a/beacon_node/client/Cargo.toml b/beacon_node/client/Cargo.toml index 04f80e76b..46394ac91 100644 --- a/beacon_node/client/Cargo.toml +++ b/beacon_node/client/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] beacon_chain = { path = "../beacon_chain" } network = { path = "../network" } +libp2p = { path = "../libp2p" } sync = { path = "../sync" } db = { path = "../db" } fork_choice = { path = "../../eth2/fork_choice" } diff --git a/beacon_node/client/src/client_config.rs b/beacon_node/client/src/client_config.rs index 3f5fbab2f..18b39277a 100644 --- a/beacon_node/client/src/client_config.rs +++ b/beacon_node/client/src/client_config.rs @@ -1,10 +1,12 @@ use clap::ArgMatches; use db::DBType; use fork_choice::ForkChoiceAlgorithm; +use libp2p::multiaddr::ToMultiaddr; use network::NetworkConfig; use slog::error; use std::fs; use std::net::IpAddr; +use std::net::SocketAddr; use std::path::PathBuf; use types::ChainSpec; @@ -52,16 +54,6 @@ impl ClientConfig { // Network related args - // Custom listening address ipv4/ipv6 - // TODO: Handle list of addresses - if let Some(listen_address_str) = args.value_of("listen_address") { - if let Ok(listen_address) = listen_address_str.parse::() { - config.net_conf.listen_addresses = vec![listen_address]; - } else { - error!(log, "Invalid IP Address"; "Address" => listen_address_str); - return Err("Invalid IP Address"); - } - } // Custom p2p listen port if let Some(port_str) = args.value_of("port") { if let Ok(port) = port_str.parse::() { @@ -71,6 +63,19 @@ impl ClientConfig { return Err("Invalid port"); } } + // Custom listening address ipv4/ipv6 + // TODO: Handle list of addresses + if let Some(listen_address_str) = args.value_of("listen_address") { + if let Ok(listen_address) = listen_address_str.parse::() { + let multiaddr = SocketAddr::new(listen_address, config.net_conf.listen_port) + .to_multiaddr() + .expect("Invalid listen address format"); + config.net_conf.listen_addresses = vec![multiaddr]; + } else { + error!(log, "Invalid IP Address"; "Address" => listen_address_str); + return Err("Invalid IP Address"); + } + } // filesystem args diff --git a/beacon_node/libp2p/Cargo.toml b/beacon_node/libp2p/Cargo.toml index 9c4c6e7a5..d78ddd882 100644 --- a/beacon_node/libp2p/Cargo.toml +++ b/beacon_node/libp2p/Cargo.toml @@ -11,3 +11,4 @@ slog = "2.4.1" version = { path = "../version" } tokio = "0.1.16" futures = "0.1.25" +parity-multiaddr = "0.2.0" diff --git a/beacon_node/libp2p/src/lib.rs b/beacon_node/libp2p/src/lib.rs index 01dc42073..1a24165ba 100644 --- a/beacon_node/libp2p/src/lib.rs +++ b/beacon_node/libp2p/src/lib.rs @@ -6,6 +6,8 @@ mod behaviour; mod network_config; mod service; +pub use libp2p::multiaddr; +pub use libp2p::Multiaddr; pub use libp2p::{ gossipsub::{GossipsubConfig, GossipsubConfigBuilder}, PeerId, diff --git a/beacon_node/libp2p/src/network_config.rs b/beacon_node/libp2p/src/network_config.rs index 7cb1cf6bb..8eeb33861 100644 --- a/beacon_node/libp2p/src/network_config.rs +++ b/beacon_node/libp2p/src/network_config.rs @@ -1,20 +1,20 @@ use libp2p::gossipsub::{GossipsubConfig, GossipsubConfigBuilder}; use libp2p::secio; +use libp2p::Multiaddr; use std::fmt; -use std::net::IpAddr; #[derive(Clone)] /// Network configuration for lighthouse. pub struct NetworkConfig { //TODO: stubbing networking initial params, change in the future /// IP address to listen on. - pub listen_addresses: Vec, + pub listen_addresses: Vec, /// Listen port UDP/TCP. pub listen_port: u16, /// Gossipsub configuration parameters. pub gs_config: GossipsubConfig, /// List of nodes to initially connect to. - pub boot_nodes: Vec, + pub boot_nodes: Vec, /// Peer key related to this nodes PeerId. pub local_private_key: secio::SecioKeyPair, /// Client version @@ -24,21 +24,15 @@ pub struct NetworkConfig { impl Default for NetworkConfig { /// Generate a default network configuration. fn default() -> Self { - // hard-coded defaults - let bootnodes = ["127.0.0.1"]; - let default_port = 9000; - // TODO: Currently using ed25519 key pairs. Wire protocol specifies RSA. Waiting for this // PR to be merged to generate RSA keys: https://github.com/briansmith/ring/pull/733 - NetworkConfig { - listen_addresses: vec!["127.0.0.1".parse().expect("correct IP address")], - listen_port: default_port, + listen_addresses: vec!["/ip4/127.0.0.1/tcp/9000" + .parse() + .expect("is a correct multi-address")], + listen_port: 9000, gs_config: GossipsubConfigBuilder::new().build(), - boot_nodes: bootnodes - .iter() - .map(|s| s.parse().expect("Bootnodes must be IP addresses")) - .collect(), + boot_nodes: Vec::new(), local_private_key: secio::SecioKeyPair::ed25519_generated().unwrap(), client_version: version::version(), } diff --git a/beacon_node/libp2p/src/service.rs b/beacon_node/libp2p/src/service.rs index 7ed715bd6..8e1670701 100644 --- a/beacon_node/libp2p/src/service.rs +++ b/beacon_node/libp2p/src/service.rs @@ -5,12 +5,12 @@ use libp2p::core::{ muxing::StreamMuxerBox, nodes::Substream, transport::boxed::Boxed, - upgrade::{InboundUpgrade, InboundUpgradeExt, OutboundUpgrade, OutboundUpgradeExt}, + upgrade::{InboundUpgradeExt, OutboundUpgradeExt}, }; -use libp2p::{build_tcp_ws_secio_mplex_yamux, core, secio, Transport}; +use libp2p::multiaddr::Protocol; +use libp2p::{core, secio, Transport}; use libp2p::{PeerId, Swarm}; -use slog::debug; -use std::error; +use slog::{debug, info, warn}; use std::io::{Error, ErrorKind}; use std::time::Duration; @@ -21,9 +21,6 @@ pub struct Service { /// This node's PeerId. local_peer_id: PeerId, } -//Swarm>>> - -//swarm: Swarm, Behaviour>>, impl Service { pub fn new(config: NetworkConfig, log: slog::Logger) -> Self { @@ -33,14 +30,37 @@ impl Service { let local_peer_id = local_private_key.to_peer_id(); debug!(log, "Local peer id: {:?}", local_peer_id); - // Set up the transport - let transport = build_transport(local_private_key); - // Set up gossipsub routing - let behaviour = Behaviour::new(local_peer_id.clone(), config.gs_config); - // Set up Topology - let topology = local_peer_id.clone(); + let mut swarm = { + // Set up the transport + let transport = build_transport(local_private_key); + // Set up gossipsub routing + let behaviour = Behaviour::new(local_peer_id.clone(), config.gs_config); + // Set up Topology + let topology = local_peer_id.clone(); + Swarm::new(transport, behaviour, topology) + }; - let swarm = Swarm::new(transport, behaviour, topology); + // listen on all addresses + for address in &config.listen_addresses { + match Swarm::listen_on(&mut swarm, address.clone()) { + Ok(mut listen_addr) => { + listen_addr.append(Protocol::P2p(local_peer_id.clone().into())); + info!(log, "Listening on: {}", listen_addr); + } + Err(err) => warn!(log, "Cannot listen on: {} : {:?}", address, err), + }; + } + // connect to boot nodes - these are currently stored as multiadders + // Once we have discovery, can set to peerId + for bootnode in config.boot_nodes { + match Swarm::dial_addr(&mut swarm, bootnode.clone()) { + Ok(()) => debug!(log, "Dialing bootnode: {}", bootnode), + Err(err) => debug!( + log, + "Could not connect to bootnode: {} error: {:?}", bootnode, err + ), + }; + } Service { local_peer_id,