From 821e4bd06ea93fd09082847f8010e854c03e5a4f Mon Sep 17 00:00:00 2001 From: Bo QIU <35757521+boqiu@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:39:14 +0800 Subject: [PATCH] Use public ip address to broadcast file announcement (#115) * Use public ip address to broadcast file announcement * auto detect public ip address for ENR address * add more log --- Cargo.lock | 215 +++++++++++++++++++++++- node/Cargo.toml | 1 + node/router/Cargo.toml | 1 + node/router/src/libp2p_event_handler.rs | 38 ++++- node/src/config/convert.rs | 21 ++- node/src/main.rs | 2 +- run/config.toml | 5 +- 7 files changed, 264 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4daacb0..38caad8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -939,7 +939,7 @@ dependencies = [ "clap_lex", "indexmap 1.9.3", "once_cell", - "strsim", + "strsim 0.10.0", "termcolor", "textwrap", ] @@ -1326,14 +1326,38 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core 0.10.2", + "darling_macro 0.10.2", +] + [[package]] name = "darling" version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.13.4", + "darling_macro 0.13.4", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.9.3", + "syn 1.0.109", ] [[package]] @@ -1346,7 +1370,18 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core 0.10.2", + "quote", "syn 1.0.109", ] @@ -1356,7 +1391,7 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ - "darling_core", + "darling_core 0.13.4", "quote", "syn 1.0.109", ] @@ -1396,6 +1431,31 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_builder" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0" +dependencies = [ + "darling 0.10.2", + "derive_builder_core", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef" +dependencies = [ + "darling 0.10.2", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.18" @@ -1531,6 +1591,18 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" +[[package]] +name = "dns-lookup" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53ecafc952c4528d9b51a458d1a8904b81783feff9fde08ab6ed2545ff396872" +dependencies = [ + "cfg-if", + "libc", + "socket2 0.4.10", + "winapi", +] + [[package]] name = "dns-parser" version = "0.8.0" @@ -1679,6 +1751,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + [[package]] name = "enr" version = "0.6.2" @@ -1715,6 +1793,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "enum-as-inner" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "enum-as-inner" version = "0.4.0" @@ -1812,7 +1902,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "635b86d2c941bb71e7419a571e1763d65c93e51a1bafc400352e3bef6ff59fc9" dependencies = [ - "darling", + "darling 0.13.4", "proc-macro2", "quote", "syn 1.0.109", @@ -2975,6 +3065,20 @@ dependencies = [ "tokio-rustls 0.24.1", ] +[[package]] +name = "hyper-system-resolver" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eea26c5d0b6ab9d72219f65000af310f042a740926f7b2fa3553e774036e2e7" +dependencies = [ + "derive_builder", + "dns-lookup", + "hyper", + "tokio", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -4707,6 +4811,15 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + [[package]] name = "nix" version = "0.24.3" @@ -5718,6 +5831,27 @@ dependencies = [ "tracing", ] +[[package]] +name = "public-ip" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4c40db5262d93298c363a299f8bc1b3a956a78eecddba3bc0e58b76e2f419a" +dependencies = [ + "dns-lookup", + "futures-core", + "futures-util", + "http", + "hyper", + "hyper-system-resolver", + "pin-project-lite 0.2.14", + "thiserror", + "tokio", + "tracing", + "tracing-futures", + "trust-dns-client", + "trust-dns-proto 0.20.4", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -5756,6 +5890,16 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + [[package]] name = "rand" version = "0.4.6" @@ -6144,6 +6288,7 @@ dependencies = [ "miner", "network", "pruner", + "public-ip", "rand 0.8.5", "serde", "shared_types", @@ -6898,6 +7043,12 @@ dependencies = [ "precomputed-hash", ] +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + [[package]] name = "strsim" version = "0.10.0" @@ -7465,6 +7616,8 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ + "futures", + "futures-task", "pin-project 1.1.5", "tracing", ] @@ -7530,6 +7683,51 @@ dependencies = [ "smallvec", ] +[[package]] +name = "trust-dns-client" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b4ef9b9bde0559b78a4abb00339143750085f05e5a453efb7b8bef1061f09dc" +dependencies = [ + "cfg-if", + "data-encoding", + "futures-channel", + "futures-util", + "lazy_static", + "log", + "radix_trie", + "rand 0.8.5", + "thiserror", + "time", + "tokio", + "trust-dns-proto 0.20.4", +] + +[[package]] +name = "trust-dns-proto" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner 0.3.4", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.2.3", + "ipnet", + "lazy_static", + "log", + "rand 0.8.5", + "smallvec", + "thiserror", + "tinyvec", + "tokio", + "url", +] + [[package]] name = "trust-dns-proto" version = "0.21.2" @@ -7539,7 +7737,7 @@ dependencies = [ "async-trait", "cfg-if", "data-encoding", - "enum-as-inner", + "enum-as-inner 0.4.0", "futures-channel", "futures-io", "futures-util", @@ -7572,7 +7770,7 @@ dependencies = [ "smallvec", "thiserror", "tokio", - "trust-dns-proto", + "trust-dns-proto 0.21.2", ] [[package]] @@ -8356,6 +8554,7 @@ dependencies = [ "miner", "network", "pruner", + "public-ip", "router", "rpc", "serde", diff --git a/node/Cargo.toml b/node/Cargo.toml index b790f19..b2865b7 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -36,6 +36,7 @@ itertools = "0.10.5" serde = { version = "1.0.137", features = ["derive"] } duration-str = "0.5.1" config = "0.13.1" +public-ip = "0.2" [dependencies.libp2p] version = "0.45.1" diff --git a/node/router/Cargo.toml b/node/router/Cargo.toml index 575cf5d..2289e08 100644 --- a/node/router/Cargo.toml +++ b/node/router/Cargo.toml @@ -23,6 +23,7 @@ tracing = "0.1.35" rand = "0.8.5" serde = { version = "1.0.137", features = ["derive"] } duration-str = "0.5.1" +public-ip = "0.2" [dev-dependencies] channel = { path = "../../common/channel" } diff --git a/node/router/src/libp2p_event_handler.rs b/node/router/src/libp2p_event_handler.rs index 01a449c..ea0d244 100644 --- a/node/router/src/libp2p_event_handler.rs +++ b/node/router/src/libp2p_event_handler.rs @@ -263,6 +263,31 @@ impl Libp2pEventHandler { } } + async fn get_listen_addr_or_add(&self) -> Option { + if let Some(addr) = self.get_listen_addr() { + return Some(addr); + } + + let ipv4_addr = public_ip::addr_v4().await?; + + let mut addr = Multiaddr::empty(); + addr.push(Protocol::Ip4(ipv4_addr)); + addr.push(Protocol::Tcp(self.network_globals.listen_port_tcp())); + addr.push(Protocol::P2p(self.network_globals.local_peer_id().into())); + + self.network_globals + .listen_multiaddrs + .write() + .insert(0, addr.clone()); + + info!( + ?addr, + "Create public ip address to broadcase file announcement" + ); + + Some(addr) + } + fn get_listen_addr(&self) -> Option { let listen_addrs = self.network_globals.listen_multiaddrs.read(); @@ -303,7 +328,7 @@ impl Libp2pEventHandler { pub async fn construct_announce_file_message(&self, tx_id: TxID) -> Option { let peer_id = *self.network_globals.peer_id.read(); - let addr = self.get_listen_addr()?; + let addr = self.get_listen_addr_or_add().await?; let timestamp = timestamp_now(); let shard_config = self.store.get_store().flow().get_shard_config(); @@ -335,7 +360,7 @@ impl Libp2pEventHandler { shard_config: ShardConfig, ) -> Option { let peer_id = *self.network_globals.peer_id.read(); - let addr = self.get_listen_addr()?; + let addr = self.get_listen_addr_or_add().await?; let timestamp = timestamp_now(); let msg = AnnounceShardConfig { @@ -401,14 +426,14 @@ impl Libp2pEventHandler { MessageAcceptance::Accept } - pub fn construct_announce_chunks_message( + pub async fn construct_announce_chunks_message( &self, tx_id: TxID, index_start: u64, index_end: u64, ) -> Option { let peer_id = *self.network_globals.peer_id.read(); - let addr = self.get_listen_addr()?; + let addr = self.get_listen_addr_or_add().await?; let timestamp = timestamp_now(); let msg = AnnounceChunks { @@ -479,7 +504,10 @@ impl Libp2pEventHandler { debug!(?msg, "Found chunks to respond FindChunks message"); - match self.construct_announce_chunks_message(msg.tx_id, msg.index_start, msg.index_end) { + match self + .construct_announce_chunks_message(msg.tx_id, msg.index_start, msg.index_end) + .await + { Some(msg) => { self.publish(msg); MessageAcceptance::Ignore diff --git a/node/src/config/convert.rs b/node/src/config/convert.rs index 8659ad3..3f9cb36 100644 --- a/node/src/config/convert.rs +++ b/node/src/config/convert.rs @@ -7,12 +7,13 @@ use miner::MinerConfig; use network::NetworkConfig; use pruner::PrunerConfig; use rpc::RPCConfig; +use std::net::IpAddr; use std::time::Duration; use storage::config::ShardConfig; use storage::StorageConfig; impl ZgsConfig { - pub fn network_config(&self) -> Result { + pub async fn network_config(&self) -> Result { let mut network_config = NetworkConfig::default(); network_config.listen_address = self @@ -25,10 +26,24 @@ impl ZgsConfig { network_config.disable_discovery = self.network_disable_discovery; network_config.discovery_port = self.network_discovery_port; - if let Some(addr) = &self.network_enr_address { + if !self.network_disable_discovery { network_config.enr_tcp_port = Some(self.network_enr_tcp_port); network_config.enr_udp_port = Some(self.network_enr_udp_port); - network_config.enr_address = Some(addr.parse().unwrap()); + network_config.enr_address = match &self.network_enr_address { + Some(addr) => Some(addr.parse().unwrap()), + None => match public_ip::addr_v4().await { + Some(ipv4_addr) => { + info!(?ipv4_addr, "Auto detect public IP as ENR address"); + Some(IpAddr::V4(ipv4_addr)) + } + None => { + return Err( + "ENR address not configured and failed to detect public IP address" + .into(), + ) + } + }, + }; } network_config.boot_nodes_multiaddr = self diff --git a/node/src/main.rs b/node/src/main.rs index ddf8929..bec892e 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -11,7 +11,7 @@ use client::{Client, ClientBuilder, RuntimeContext}; use std::error::Error; async fn start_node(context: RuntimeContext, config: ZgsConfig) -> Result { - let network_config = config.network_config()?; + let network_config = config.network_config().await?; let storage_config = config.storage_config()?; let rpc_config = config.rpc_config()?; let log_sync_config = config.log_sync_config()?; diff --git a/run/config.toml b/run/config.toml index 71ea6d4..e9142b9 100644 --- a/run/config.toml +++ b/run/config.toml @@ -11,8 +11,9 @@ # IP address to listen on. # network_listen_address = "0.0.0.0" -# The address to broadcast to peers about which address we are listening on. Empty indicates that -# no discovery address has been set. Generally, configure public IP address to enable UDP discovery. +# The address to broadcast to peers about which address we are listening on. Generally, +# configure public IP address for UDP discovery. If not specified, program will try to +# detect public IP address automatically. # network_enr_address = "" # The tcp port to broadcast to peers in order to reach back for libp2p services.