diff --git a/Cargo.lock b/Cargo.lock index 5ca8146287..2b6aef52fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,6 +217,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +[[package]] +name = "base64" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3" + [[package]] name = "beacon_chain" version = "0.2.0" @@ -1082,20 +1088,21 @@ dependencies = [ [[package]] name = "enr" -version = "0.1.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +version = "0.1.0-alpha.3" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ - "base64 0.10.1", + "base64 0.12.0", "bs58 0.3.0", - "clap", + "ed25519-dalek", "hex 0.4.2", "libp2p-core", - "libsecp256k1 0.3.5", + "libsecp256k1", "log 0.4.8", "rand 0.7.3", "rlp", "serde", "sha3", + "zeroize 1.1.0", ] [[package]] @@ -1199,7 +1206,6 @@ version = "0.2.0" dependencies = [ "base64 0.11.0", "dirs", - "enr", "error-chain", "eth2_ssz", "eth2_ssz_derive", @@ -2044,10 +2050,9 @@ dependencies = [ [[package]] name = "libp2p" version = "0.13.2" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "bytes", - "enr", "futures", "lazy_static", "libp2p-core", @@ -2084,7 +2089,7 @@ dependencies = [ [[package]] name = "libp2p-core" version = "0.13.2" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "asn1_der", "bs58 0.3.0", @@ -2094,7 +2099,7 @@ dependencies = [ "fnv", "futures", "lazy_static", - "libsecp256k1 0.3.5", + "libsecp256k1", "log 0.4.8", "multistream-select", "parity-multiaddr", @@ -2119,7 +2124,7 @@ dependencies = [ [[package]] name = "libp2p-core-derive" version = "0.13.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "quote 1.0.3", "syn 1.0.16", @@ -2128,7 +2133,7 @@ dependencies = [ [[package]] name = "libp2p-deflate" version = "0.5.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "flate2", "futures", @@ -2139,7 +2144,7 @@ dependencies = [ [[package]] name = "libp2p-discv5" version = "0.1.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "arrayvec 0.4.12", "bigint", @@ -2151,12 +2156,12 @@ dependencies = [ "hkdf", "libp2p-core", "libp2p-swarm", - "libsecp256k1 0.3.1", + "libsecp256k1", "log 0.4.8", "openssl", "parity-multiaddr", "parity-multihash", - "rand 0.6.5", + "rand 0.7.3", "rlp", "sha2", "smallvec 0.6.13", @@ -2170,7 +2175,7 @@ dependencies = [ [[package]] name = "libp2p-dns" version = "0.13.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "futures", "libp2p-core", @@ -2181,7 +2186,7 @@ dependencies = [ [[package]] name = "libp2p-floodsub" version = "0.13.1" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "bs58 0.3.0", "bytes", @@ -2199,7 +2204,7 @@ dependencies = [ [[package]] name = "libp2p-gossipsub" version = "0.1.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "base64 0.10.1", "bs58 0.2.5", @@ -2224,7 +2229,7 @@ dependencies = [ [[package]] name = "libp2p-identify" version = "0.13.2" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "bytes", "futures", @@ -2243,7 +2248,7 @@ dependencies = [ [[package]] name = "libp2p-kad" version = "0.13.2" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "arrayvec 0.5.1", "bytes", @@ -2270,7 +2275,7 @@ dependencies = [ [[package]] name = "libp2p-mdns" version = "0.13.1" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "data-encoding", "dns-parser", @@ -2292,7 +2297,7 @@ dependencies = [ [[package]] name = "libp2p-mplex" version = "0.13.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "bytes", "fnv", @@ -2308,7 +2313,7 @@ dependencies = [ [[package]] name = "libp2p-noise" version = "0.11.1" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "bytes", "curve25519-dalek 1.2.3", @@ -2328,7 +2333,7 @@ dependencies = [ [[package]] name = "libp2p-ping" version = "0.13.1" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "bytes", "futures", @@ -2345,7 +2350,7 @@ dependencies = [ [[package]] name = "libp2p-plaintext" version = "0.13.1" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "bytes", "futures", @@ -2360,7 +2365,7 @@ dependencies = [ [[package]] name = "libp2p-secio" version = "0.13.1" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "aes-ctr", "bytes", @@ -2389,7 +2394,7 @@ dependencies = [ [[package]] name = "libp2p-swarm" version = "0.3.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "futures", "libp2p-core", @@ -2402,7 +2407,7 @@ dependencies = [ [[package]] name = "libp2p-tcp" version = "0.13.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "bytes", "futures", @@ -2418,7 +2423,7 @@ dependencies = [ [[package]] name = "libp2p-uds" version = "0.13.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "futures", "libp2p-core", @@ -2429,7 +2434,7 @@ dependencies = [ [[package]] name = "libp2p-wasm-ext" version = "0.6.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "futures", "js-sys", @@ -2443,7 +2448,7 @@ dependencies = [ [[package]] name = "libp2p-websocket" version = "0.13.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "bytes", "futures", @@ -2461,7 +2466,7 @@ dependencies = [ [[package]] name = "libp2p-yamux" version = "0.13.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "futures", "libp2p-core", @@ -2470,20 +2475,6 @@ dependencies = [ "yamux", ] -[[package]] -name = "libsecp256k1" -version = "0.3.1" -source = "git+https://github.com/SigP/libsecp256k1?branch=ecdh_generalise#5858db8d1b280417f5866582df2cd0c63983d928" -dependencies = [ - "arrayref", - "digest", - "hmac-drbg", - "rand 0.6.5", - "sha2", - "subtle 2.2.2", - "typenum", -] - [[package]] name = "libsecp256k1" version = "0.3.5" @@ -2775,7 +2766,7 @@ dependencies = [ [[package]] name = "multistream-select" version = "0.6.1" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "bytes", "futures", @@ -3008,7 +2999,7 @@ dependencies = [ [[package]] name = "parity-multiaddr" version = "0.6.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "arrayref", "bs58 0.3.0", @@ -3025,7 +3016,7 @@ dependencies = [ [[package]] name = "parity-multihash" version = "0.2.0" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "blake2", "bytes", @@ -3801,7 +3792,7 @@ dependencies = [ [[package]] name = "rw-stream-sink" version = "0.1.2" -source = "git+https://github.com/SigP/rust-libp2p/?rev=49c95c4c4242f1c9f08558a3daac5e9ecac290d5#49c95c4c4242f1c9f08558a3daac5e9ecac290d5" +source = "git+https://github.com/SigP/rust-libp2p?rev=0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6#0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" dependencies = [ "bytes", "futures", diff --git a/beacon_node/eth1/src/service.rs b/beacon_node/eth1/src/service.rs index 9890ec6b05..1d54c09ea0 100644 --- a/beacon_node/eth1/src/service.rs +++ b/beacon_node/eth1/src/service.rs @@ -410,7 +410,7 @@ impl Service { .map(|vec| { let first = vec.first().cloned().unwrap_or_else(|| 0); let last = vec.last().map(|n| n + 1).unwrap_or_else(|| 0); - (first..last) + first..last }) .collect::>>() }) diff --git a/beacon_node/eth2-libp2p/Cargo.toml b/beacon_node/eth2-libp2p/Cargo.toml index 1232dcda65..546a31fd82 100644 --- a/beacon_node/eth2-libp2p/Cargo.toml +++ b/beacon_node/eth2-libp2p/Cargo.toml @@ -8,8 +8,7 @@ edition = "2018" hex = "0.3" # rust-libp2p is presently being sourced from a Sigma Prime fork of the # `libp2p/rust-libp2p` repository. -libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "49c95c4c4242f1c9f08558a3daac5e9ecac290d5" } -enr = { git = "https://github.com/SigP/rust-libp2p/", rev = "49c95c4c4242f1c9f08558a3daac5e9ecac290d5", features = ["serde"] } +libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "0cb9d504c7be6a7bcfc87feeafdb6847d8083fc6" } types = { path = "../../eth2/types" } serde = "1.0.102" serde_derive = "1.0.102" diff --git a/beacon_node/eth2-libp2p/src/behaviour.rs b/beacon_node/eth2-libp2p/src/behaviour.rs index 7c2294d8a9..5349772fa2 100644 --- a/beacon_node/eth2-libp2p/src/behaviour.rs +++ b/beacon_node/eth2-libp2p/src/behaviour.rs @@ -1,7 +1,7 @@ use crate::discovery::Discovery; use crate::rpc::{RPCEvent, RPCMessage, RPC}; +use crate::Enr; use crate::{error, GossipTopic, NetworkConfig, NetworkGlobals, PubsubMessage, TopicHash}; -use enr::Enr; use futures::prelude::*; use libp2p::{ core::identity::Keypair, diff --git a/beacon_node/eth2-libp2p/src/config.rs b/beacon_node/eth2-libp2p/src/config.rs index 5941da3d7c..57c90cc9a6 100644 --- a/beacon_node/eth2-libp2p/src/config.rs +++ b/beacon_node/eth2-libp2p/src/config.rs @@ -1,5 +1,6 @@ use crate::types::{GossipEncoding, GossipKind, GossipTopic}; -use enr::Enr; +use crate::Enr; +use libp2p::discv5::{Discv5Config, Discv5ConfigBuilder}; use libp2p::gossipsub::{GossipsubConfig, GossipsubConfigBuilder, GossipsubMessage, MessageId}; use libp2p::Multiaddr; use serde_derive::{Deserialize, Serialize}; @@ -20,13 +21,19 @@ pub struct Config { /// The TCP port that libp2p listens on. pub libp2p_port: u16, - /// The address to broadcast to peers about which address we are listening on. None indicates - /// that no discovery address has been set in the CLI args. - pub discovery_address: Option, - /// UDP port that discovery listens on. pub discovery_port: u16, + /// The address to broadcast to peers about which address we are listening on. None indicates + /// that no discovery address has been set in the CLI args. + pub enr_address: Option, + + /// The udp port to broadcast to peers in order to reach back for discovery. + pub enr_udp_port: Option, + + /// The tcp port to broadcast to peers in order to reach back for libp2p services. + pub enr_tcp_port: Option, + /// Target number of connected peers. pub max_peers: usize, @@ -40,6 +47,10 @@ pub struct Config { #[serde(skip)] pub gs_config: GossipsubConfig, + /// Discv5 configuration parameters. + #[serde(skip)] + pub discv5_config: Discv5Config, + /// List of nodes to initially connect to. pub boot_nodes: Vec, @@ -83,23 +94,40 @@ impl Default for Config { )) }; + // gossipsub configuration + // Note: The topics by default are sent as plain strings. Hashes are an optional + // parameter. + let gs_config = GossipsubConfigBuilder::new() + .max_transmit_size(1_048_576) + .heartbeat_interval(Duration::from_secs(20)) // TODO: Reduce for mainnet + .manual_propagation() // require validation before propagation + .no_source_id() + .message_id_fn(gossip_message_id) + .build(); + + // discv5 configuration + let discv5_config = Discv5ConfigBuilder::new() + .request_timeout(Duration::from_secs(4)) + .request_retries(1) + .enr_update(true) // update IP based on PONG responses + .enr_peer_update_min(2) // prevents NAT's should be raised for mainnet + .query_parallelism(5) + .ip_limit(false) // limits /24 IP's in buckets. Enable for mainnet + .ping_interval(Duration::from_secs(300)) + .build(); + Config { network_dir, listen_address: "127.0.0.1".parse().expect("valid ip address"), libp2p_port: 9000, - discovery_address: None, discovery_port: 9000, + enr_address: None, + enr_udp_port: None, + enr_tcp_port: None, max_peers: 10, secret_key_hex: None, - // Note: The topics by default are sent as plain strings. Hashes are an optional - // parameter. - gs_config: GossipsubConfigBuilder::new() - .max_transmit_size(1_048_576) - .heartbeat_interval(Duration::from_secs(20)) // TODO: Reduce for mainnet - .manual_propagation() // require validation before propagation - .no_source_id() - .message_id_fn(gossip_message_id) - .build(), + gs_config, + discv5_config, boot_nodes: vec![], libp2p_nodes: vec![], client_version: version::version(), diff --git a/beacon_node/eth2-libp2p/src/discovery.rs b/beacon_node/eth2-libp2p/src/discovery.rs index 733b14c840..2023d7cb3a 100644 --- a/beacon_node/eth2-libp2p/src/discovery.rs +++ b/beacon_node/eth2-libp2p/src/discovery.rs @@ -1,4 +1,5 @@ use crate::metrics; +use crate::Enr; use crate::{error, NetworkConfig, NetworkGlobals, PeerInfo}; /// This manages the discovery and management of peers. /// @@ -6,14 +7,16 @@ use crate::{error, NetworkConfig, NetworkGlobals, PeerInfo}; /// use futures::prelude::*; use libp2p::core::{identity::Keypair, ConnectedPoint, Multiaddr, PeerId}; +use libp2p::discv5::enr::{CombinedKey, EnrBuilder, NodeId}; use libp2p::discv5::{Discv5, Discv5Event}; -use libp2p::enr::{Enr, EnrBuilder, NodeId}; use libp2p::multiaddr::Protocol; use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters, ProtocolsHandler}; use slog::{debug, info, warn}; use std::collections::HashSet; +use std::convert::TryInto; use std::fs::File; use std::io::prelude::*; +use std::net::SocketAddr; use std::path::Path; use std::str::FromStr; use std::sync::Arc; @@ -73,7 +76,7 @@ impl Discovery { let log = log.clone(); // checks if current ENR matches that found on disk - let local_enr = load_enr(local_key, config, &log)?; + let local_enr = load_enr(local_key.clone(), config, &log)?; *network_globals.local_enr.write() = Some(local_enr.clone()); @@ -82,21 +85,25 @@ impl Discovery { None => String::from(""), }; - info!(log, "ENR Initialised"; "enr" => local_enr.to_base64(), "seq" => local_enr.seq(), "id"=> format!("{}",local_enr.node_id()), "ip" => format!("{:?}", local_enr.ip()), "udp"=> local_enr.udp().unwrap_or_else(|| 0), "tcp" => local_enr.tcp().unwrap_or_else(|| 0)); + info!(log, "ENR Initialised"; "enr" => local_enr.to_base64(), "seq" => local_enr.seq(), "id"=> format!("{}",local_enr.node_id()), "ip" => format!("{:?}", local_enr.ip()), "udp"=> format!("{:?}", local_enr.udp()), "tcp" => format!("{:?}", local_enr.tcp())); - // the last parameter enables IP limiting. 2 Nodes on the same /24 subnet per bucket and 10 - // nodes on the same /24 subnet per table. - // TODO: IP filtering is currently disabled for the DHT. Enable for production - let mut discovery = Discv5::new(local_enr, local_key.clone(), config.listen_address, false) - .map_err(|e| format!("Discv5 service failed. Error: {:?}", e))?; + let listen_socket = SocketAddr::new(config.listen_address, config.discovery_port); + + let mut discovery = Discv5::new( + local_enr, + local_key.clone(), + config.discv5_config.clone(), + listen_socket, + ) + .map_err(|e| format!("Discv5 service failed. Error: {:?}", e))?; // Add bootnodes to routing table for bootnode_enr in config.boot_nodes.clone() { debug!( log, "Adding node to routing table"; - "node_id" => format!("{}", - bootnode_enr.node_id()) + "node_id" => format!("{}", bootnode_enr.node_id()), + "peer_id" => format!("{}", bootnode_enr.peer_id()) ); discovery.add_enr(bootnode_enr); } @@ -319,22 +326,32 @@ where /// /// If an ENR exists, with the same NodeId and IP address, we use the disk-generated one as its /// ENR sequence will be equal or higher than a newly generated one. -fn load_enr( - local_key: &Keypair, - config: &NetworkConfig, - log: &slog::Logger, -) -> Result { +fn load_enr(local_key: Keypair, config: &NetworkConfig, log: &slog::Logger) -> Result { // Build the local ENR. // Note: Discovery should update the ENR record's IP to the external IP as seen by the - // majority of our peers. - let mut local_enr = EnrBuilder::new("v4") - .ip(config - .discovery_address - .unwrap_or_else(|| "127.0.0.1".parse().expect("valid ip"))) - .tcp(config.libp2p_port) - .udp(config.discovery_port) - .build(&local_key) - .map_err(|e| format!("Could not build Local ENR: {:?}", e))?; + // majority of our peers, if the CLI doesn't expressly forbid it. + let enr_key: CombinedKey = local_key + .try_into() + .map_err(|_| "Invalid key type for ENR records")?; + + let mut local_enr = { + let mut builder = EnrBuilder::new("v4"); + if let Some(enr_address) = config.enr_address { + builder.ip(enr_address); + } + if let Some(udp_port) = config.enr_udp_port { + builder.udp(udp_port); + } + // we always give it our listening tcp port + // TODO: Add uPnP support to map udp and tcp ports + let tcp_port = config.enr_tcp_port.unwrap_or_else(|| config.libp2p_port); + builder.tcp(tcp_port); + + builder + .tcp(config.libp2p_port) + .build(&enr_key) + .map_err(|e| format!("Could not build Local ENR: {:?}", e))? + }; let enr_f = config.network_dir.join(ENR_FILENAME); if let Ok(mut enr_file) = File::open(enr_f.clone()) { @@ -344,11 +361,13 @@ fn load_enr( Ok(_) => { match Enr::from_str(&enr_string) { Ok(enr) => { + let tcp_port = config.enr_tcp_port.unwrap_or_else(|| config.libp2p_port); if enr.node_id() == local_enr.node_id() { - if (config.discovery_address.is_none() - || enr.ip().map(Into::into) == config.discovery_address) - && enr.tcp() == Some(config.libp2p_port) - && enr.udp() == Some(config.discovery_port) + if (config.enr_address.is_none() + || enr.ip().map(Into::into) == config.enr_address) + && enr.tcp() == Some(tcp_port) + && (config.enr_udp_port.is_none() + || enr.udp() == config.enr_udp_port) { debug!(log, "ENR loaded from file"; "file" => format!("{:?}", enr_f)); // the stored ENR has the same configuration, use it @@ -357,7 +376,7 @@ fn load_enr( // same node id, different configuration - update the sequence number let new_seq_no = enr.seq().checked_add(1).ok_or_else(|| "ENR sequence number on file is too large. Remove it to generate a new NodeId")?; - local_enr.set_seq(new_seq_no, local_key).map_err(|e| { + local_enr.set_seq(new_seq_no, &enr_key).map_err(|e| { format!("Could not update ENR sequence number: {:?}", e) })?; debug!(log, "ENR sequence number increased"; "seq" => new_seq_no); diff --git a/beacon_node/eth2-libp2p/src/lib.rs b/beacon_node/eth2-libp2p/src/lib.rs index 49e5715671..c630152b31 100644 --- a/beacon_node/eth2-libp2p/src/lib.rs +++ b/beacon_node/eth2-libp2p/src/lib.rs @@ -13,9 +13,11 @@ pub mod rpc; mod service; pub mod types; +// shift this type into discv5 +pub type Enr = libp2p::discv5::enr::Enr; + pub use crate::types::{error, GossipTopic, NetworkGlobals, PeerInfo, PubsubData, PubsubMessage}; pub use config::Config as NetworkConfig; -pub use libp2p::enr::Enr; pub use libp2p::gossipsub::{MessageId, Topic, TopicHash}; pub use libp2p::{multiaddr, Multiaddr}; pub use libp2p::{PeerId, Swarm}; diff --git a/beacon_node/eth2-libp2p/tests/common/mod.rs b/beacon_node/eth2-libp2p/tests/common/mod.rs index ea075ff559..c6e8054c83 100644 --- a/beacon_node/eth2-libp2p/tests/common/mod.rs +++ b/beacon_node/eth2-libp2p/tests/common/mod.rs @@ -1,5 +1,5 @@ #![cfg(test)] -use enr::Enr; +use eth2_libp2p::Enr; use eth2_libp2p::Multiaddr; use eth2_libp2p::NetworkConfig; use eth2_libp2p::Service as LibP2PService; @@ -32,6 +32,9 @@ pub fn build_config( config.libp2p_port = port; // tcp port config.discovery_port = port; // udp port + config.enr_tcp_port = Some(port); + config.enr_udp_port = Some(port); + config.enr_address = Some("127.0.0.1".parse().unwrap()); config.boot_nodes.append(&mut boot_nodes); config.secret_key_hex = secret_key; config.network_dir = path.into_path(); @@ -56,7 +59,9 @@ pub fn build_libp2p_instance( #[allow(dead_code)] pub fn get_enr(node: &LibP2PService) -> Enr { - node.swarm.discovery().local_enr().clone() + let enr = node.swarm.discovery().local_enr().clone(); + dbg!(enr.multiaddr()); + enr } // Returns `n` libp2p peers in fully connected topology. @@ -66,7 +71,7 @@ pub fn build_full_mesh( n: usize, start_port: Option, ) -> Vec> { - let base_port = start_port.unwrap_or(9000); + let base_port = start_port.unwrap_or(10000); let mut nodes: Vec> = (base_port..base_port + n as u16) .map(|p| build_libp2p_instance(p, vec![], None, log.clone())) .collect(); diff --git a/beacon_node/eth2-libp2p/tests/gossipsub_tests.rs b/beacon_node/eth2-libp2p/tests/gossipsub_tests.rs index 09f8d351dd..f2f765b773 100644 --- a/beacon_node/eth2-libp2p/tests/gossipsub_tests.rs +++ b/beacon_node/eth2-libp2p/tests/gossipsub_tests.rs @@ -89,7 +89,7 @@ fn test_gossipsub_forward() { #[test] fn test_gossipsub_full_mesh_publish() { // set up the logging. The level and enabled or not - let log = common::build_log(Level::Info, false); + let log = common::build_log(Level::Debug, false); // Note: This test does not propagate gossipsub messages. // Having `num_nodes` > `mesh_n_high` may give inconsistent results diff --git a/beacon_node/src/cli.rs b/beacon_node/src/cli.rs index 0a32e864fd..a38d00f1ae 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -62,6 +62,14 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .default_value("9000") .takes_value(true), ) + .arg( + Arg::with_name("discovery-port") + .long("discovery-port") + .value_name("PORT") + .help("The UDP port that discovery will listen on.") + .default_value("9000") + .takes_value(true), + ) .arg( Arg::with_name("maxpeers") .long("maxpeers") @@ -78,20 +86,43 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .takes_value(true), ) .arg( - Arg::with_name("discovery-port") - .long("disc-port") + Arg::with_name("enr-udp-port") + .long("enr-udp-port") .value_name("PORT") - .help("The discovery UDP port.") - .default_value("9000") + .help("The UDP port of the local ENR. Set this only if you are sure other nodes can connect to your local node on this port.") .takes_value(true), ) .arg( - Arg::with_name("discovery-address") - .long("discovery-address") + Arg::with_name("enr-tcp-port") + .long("enr-tcp-port") + .value_name("PORT") + .help("The TCP port of the local ENR. Set this only if you are sure other nodes can connect to your local node on this port.\ + The --port flag is used if this is not set.") + .takes_value(true), + ) + .arg( + 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. \ - Default will load previous values from disk failing this it is set to 127.0.0.1 \ - and will be updated when connecting to other nodes on the network.") + 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. + ") + .takes_value(true), + ) + .arg( + Arg::with_name("enr-match") + .short("e") + .long("enr-match") + .help("Sets the local ENR IP address and port to match those set for lighthouse. \ + Specifically, the IP address will be the value of --listen-address and the UDP port will be --discovery-port.") + ) + .arg( + Arg::with_name("disable-enr-auto-update") + .short("s") + .long("disable-enr-auto-update") + .help("Discovery automatically updates the nodes local ENR with an external IP address and port as seen by other peers on the network. \ + This disables this feature, fixing the ENR's IP/PORT to those specified on boot.") .takes_value(true), ) .arg( diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index 4bad6d9d52..3fa8339f20 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -5,7 +5,7 @@ use eth2_libp2p::{Enr, GossipTopic, Multiaddr}; use eth2_testnet_config::Eth2TestnetConfig; use genesis::recent_genesis_time; use rand::{distributions::Alphanumeric, Rng}; -use slog::{crit, info, warn, Logger}; +use slog::{crit, info, Logger}; use ssz::Encode; use std::fs; use std::net::{IpAddr, Ipv4Addr}; @@ -116,6 +116,13 @@ pub fn get_configs( client_config.network.discovery_port = port; } + if let Some(port_str) = cli_args.value_of("discovery-port") { + let port = port_str + .parse::() + .map_err(|_| format!("Invalid port: {}", port_str))?; + client_config.network.discovery_port = port; + } + if let Some(boot_enr_str) = cli_args.value_of("boot-nodes") { client_config.network.boot_nodes = boot_enr_str .split(',') @@ -143,18 +150,37 @@ pub fn get_configs( client_config.network.topics = topics; } - if let Some(discovery_address_str) = cli_args.value_of("discovery-address") { - client_config.network.discovery_address = Some( - discovery_address_str + 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: {:?}", discovery_address_str))?, + .map_err(|_| format!("Invalid discovery address: {:?}", enr_address_str))?, ) } - if let Some(disc_port_str) = cli_args.value_of("disc-port") { - client_config.network.discovery_port = disc_port_str - .parse::() - .map_err(|_| format!("Invalid discovery port: {}", disc_port_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 + .parse::() + .map_err(|_| format!("Invalid discovery port: {}", enr_udp_port_str))?, + ); + } + + if let Some(enr_tcp_port_str) = cli_args.value_of("enr-tcp-port") { + client_config.network.enr_tcp_port = Some( + enr_tcp_port_str + .parse::() + .map_err(|_| format!("Invalid ENR TCP port: {}", enr_tcp_port_str))?, + ); + } + + if cli_args.is_present("enr-match") { + client_config.network.enr_address = Some(client_config.network.listen_address); + client_config.network.enr_udp_port = Some(client_config.network.discovery_port); + } + + if cli_args.is_present("disable_enr_auto_update") { + client_config.network.discv5_config.enr_update = false; } if let Some(p2p_priv_key) = cli_args.value_of("p2p-priv-key") { @@ -301,8 +327,8 @@ pub fn get_configs( * Discovery address is set to localhost by default. */ if cli_args.is_present("zero-ports") { - if client_config.network.discovery_address == Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))) { - client_config.network.discovery_address = None + if client_config.network.enr_address == Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))) { + client_config.network.enr_address = None } client_config.network.libp2p_port = unused_port("tcp").map_err(|e| format!("Failed to get port for libp2p: {}", e))?; @@ -312,15 +338,6 @@ pub fn get_configs( client_config.websocket_server.port = 0; } - // ENR IP needs to be explicit for node to be discoverable - if client_config.network.discovery_address == Some(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))) { - warn!( - log, - "Discovery address cannot be 0.0.0.0, Setting to to 127.0.0.1" - ); - client_config.network.discovery_address = - Some("127.0.0.1".parse().expect("Valid IP address")) - } Ok((client_config, eth2_config, log)) }