mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(net): IP resolution in docker (#10681)
Co-authored-by: Cody Wang <cody.wang@coinbase.com>
This commit is contained in:
11
Cargo.lock
generated
11
Cargo.lock
generated
@ -3845,6 +3845,16 @@ dependencies = [
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "if-addrs"
|
||||
version = "0.13.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a78a89907582615b19f6f0da1af18abf6ff08be259395669b834b057a7ee92d8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "impl-codec"
|
||||
version = "0.6.0"
|
||||
@ -7435,6 +7445,7 @@ name = "reth-net-nat"
|
||||
version = "1.0.6"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"if-addrs",
|
||||
"reqwest",
|
||||
"reth-tracing",
|
||||
"serde_with",
|
||||
|
||||
@ -536,6 +536,7 @@ tower-http = "0.5"
|
||||
|
||||
# p2p
|
||||
discv5 = "0.7.0"
|
||||
if-addrs = "0.13"
|
||||
|
||||
# rpc
|
||||
jsonrpsee = "0.24"
|
||||
|
||||
5
book/cli/reth/debug/execution.md
vendored
5
book/cli/reth/debug/execution.md
vendored
@ -228,6 +228,11 @@ Networking:
|
||||
|
||||
[default: 25600]
|
||||
|
||||
--net-if.experimental <IF_NAME>
|
||||
Name of network interface used to communicate with peers.
|
||||
|
||||
If flag is set, but no value is passed, the default interface for docker `eth0` is tried.
|
||||
|
||||
--to <TO>
|
||||
The maximum block height
|
||||
|
||||
|
||||
5
book/cli/reth/debug/in-memory-merkle.md
vendored
5
book/cli/reth/debug/in-memory-merkle.md
vendored
@ -228,6 +228,11 @@ Networking:
|
||||
|
||||
[default: 25600]
|
||||
|
||||
--net-if.experimental <IF_NAME>
|
||||
Name of network interface used to communicate with peers.
|
||||
|
||||
If flag is set, but no value is passed, the default interface for docker `eth0` is tried.
|
||||
|
||||
--retries <RETRIES>
|
||||
The number of retries per request
|
||||
|
||||
|
||||
5
book/cli/reth/debug/merkle.md
vendored
5
book/cli/reth/debug/merkle.md
vendored
@ -228,6 +228,11 @@ Networking:
|
||||
|
||||
[default: 25600]
|
||||
|
||||
--net-if.experimental <IF_NAME>
|
||||
Name of network interface used to communicate with peers.
|
||||
|
||||
If flag is set, but no value is passed, the default interface for docker `eth0` is tried.
|
||||
|
||||
--retries <RETRIES>
|
||||
The number of retries per request
|
||||
|
||||
|
||||
5
book/cli/reth/debug/replay-engine.md
vendored
5
book/cli/reth/debug/replay-engine.md
vendored
@ -228,6 +228,11 @@ Networking:
|
||||
|
||||
[default: 25600]
|
||||
|
||||
--net-if.experimental <IF_NAME>
|
||||
Name of network interface used to communicate with peers.
|
||||
|
||||
If flag is set, but no value is passed, the default interface for docker `eth0` is tried.
|
||||
|
||||
--engine-api-store <PATH>
|
||||
The path to read engine API messages from
|
||||
|
||||
|
||||
5
book/cli/reth/node.md
vendored
5
book/cli/reth/node.md
vendored
@ -220,6 +220,11 @@ Networking:
|
||||
|
||||
[default: 25600]
|
||||
|
||||
--net-if.experimental <IF_NAME>
|
||||
Name of network interface used to communicate with peers.
|
||||
|
||||
If flag is set, but no value is passed, the default interface for docker `eth0` is tried.
|
||||
|
||||
RPC:
|
||||
--http
|
||||
Enable the HTTP-RPC server
|
||||
|
||||
5
book/cli/reth/p2p.md
vendored
5
book/cli/reth/p2p.md
vendored
@ -205,6 +205,11 @@ Networking:
|
||||
|
||||
[default: 25600]
|
||||
|
||||
--net-if.experimental <IF_NAME>
|
||||
Name of network interface used to communicate with peers.
|
||||
|
||||
If flag is set, but no value is passed, the default interface for docker `eth0` is tried.
|
||||
|
||||
Datadir:
|
||||
--datadir <DATA_DIR>
|
||||
The path to the data dir for all reth files and subdirectories.
|
||||
|
||||
5
book/cli/reth/stage/run.md
vendored
5
book/cli/reth/stage/run.md
vendored
@ -271,6 +271,11 @@ Networking:
|
||||
|
||||
[default: 25600]
|
||||
|
||||
--net-if.experimental <IF_NAME>
|
||||
Name of network interface used to communicate with peers.
|
||||
|
||||
If flag is set, but no value is passed, the default interface for docker `eth0` is tried.
|
||||
|
||||
Logging:
|
||||
--log.stdout.format <FORMAT>
|
||||
The format to use for logs written to stdout
|
||||
|
||||
5
book/cli/reth/stage/unwind.md
vendored
5
book/cli/reth/stage/unwind.md
vendored
@ -233,6 +233,11 @@ Networking:
|
||||
|
||||
[default: 25600]
|
||||
|
||||
--net-if.experimental <IF_NAME>
|
||||
Name of network interface used to communicate with peers.
|
||||
|
||||
If flag is set, but no value is passed, the default interface for docker `eth0` is tried.
|
||||
|
||||
--offline
|
||||
If this is enabled, then all stages except headers, bodies, and sender recovery will be unwound
|
||||
|
||||
|
||||
@ -17,6 +17,7 @@ reqwest.workspace = true
|
||||
serde_with = { workspace = true, optional = true }
|
||||
thiserror.workspace = true
|
||||
tokio = { workspace = true, features = ["time"] }
|
||||
if-addrs.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
reth-tracing.workspace = true
|
||||
|
||||
@ -12,6 +12,10 @@
|
||||
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||
|
||||
pub mod net_if;
|
||||
|
||||
pub use net_if::{NetInterfaceError, DEFAULT_NET_IF_NAME};
|
||||
|
||||
use std::{
|
||||
fmt,
|
||||
future::{poll_fn, Future},
|
||||
|
||||
55
crates/net/nat/src/net_if.rs
Normal file
55
crates/net/nat/src/net_if.rs
Normal file
@ -0,0 +1,55 @@
|
||||
//! IP resolution on non-host Docker network.
|
||||
|
||||
#![cfg(not(target_os = "windows"))]
|
||||
|
||||
use std::{io, net::IpAddr};
|
||||
|
||||
/// The 'eth0' interface tends to be the default interface that docker containers use to
|
||||
/// communicate with each other.
|
||||
pub const DEFAULT_NET_IF_NAME: &str = "eth0";
|
||||
|
||||
/// Errors resolving network interface IP.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum NetInterfaceError {
|
||||
/// Error reading OS interfaces.
|
||||
#[error("failed to read OS interfaces: {0}")]
|
||||
Io(io::Error),
|
||||
/// No interface found with given name.
|
||||
#[error("interface not found: {0}, found other interfaces: {1:?}")]
|
||||
IFNotFound(String, Vec<String>),
|
||||
}
|
||||
|
||||
/// Reads IP of OS interface with given name, if exists.
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn resolve_net_if_ip(if_name: &str) -> Result<IpAddr, NetInterfaceError> {
|
||||
match if_addrs::get_if_addrs() {
|
||||
Ok(ifs) => {
|
||||
let ip = ifs.iter().find(|i| i.name == if_name).map(|i| i.ip());
|
||||
match ip {
|
||||
Some(ip) => Ok(ip),
|
||||
None => {
|
||||
let ifs = ifs.into_iter().map(|i| i.name.as_str().into()).collect();
|
||||
Err(NetInterfaceError::IFNotFound(if_name.into(), ifs))
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => Err(NetInterfaceError::Io(err)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn read_docker_if_addr() {
|
||||
const LOCALHOST_IF: [&str; 2] = ["lo0", "lo"];
|
||||
|
||||
let ip = resolve_net_if_ip(LOCALHOST_IF[0])
|
||||
.unwrap_or_else(|_| resolve_net_if_ip(LOCALHOST_IF[1]).unwrap());
|
||||
|
||||
assert_eq!(ip, Ipv4Addr::LOCALHOST);
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,7 @@ use reth_discv5::{
|
||||
discv5::ListenConfig, DEFAULT_COUNT_BOOTSTRAP_LOOKUPS, DEFAULT_DISCOVERY_V5_PORT,
|
||||
DEFAULT_SECONDS_BOOTSTRAP_LOOKUP_INTERVAL, DEFAULT_SECONDS_LOOKUP_INTERVAL,
|
||||
};
|
||||
use reth_net_nat::NatResolver;
|
||||
use reth_net_nat::{NatResolver, DEFAULT_NET_IF_NAME};
|
||||
use reth_network::{
|
||||
transactions::{
|
||||
constants::{
|
||||
@ -35,6 +35,7 @@ use reth_network::{
|
||||
};
|
||||
use reth_network_peers::{mainnet_nodes, TrustedPeer};
|
||||
use secp256k1::SecretKey;
|
||||
use tracing::error;
|
||||
|
||||
use crate::version::P2P_CLIENT_VERSION;
|
||||
|
||||
@ -148,9 +149,38 @@ pub struct NetworkArgs {
|
||||
/// Max capacity of cache of hashes for transactions pending fetch.
|
||||
#[arg(long = "max-tx-pending-fetch", value_name = "COUNT", default_value_t = DEFAULT_MAX_CAPACITY_CACHE_PENDING_FETCH, verbatim_doc_comment)]
|
||||
pub max_capacity_cache_txns_pending_fetch: u32,
|
||||
|
||||
/// Name of network interface used to communicate with peers.
|
||||
///
|
||||
/// If flag is set, but no value is passed, the default interface for docker `eth0` is tried.
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[arg(long = "net-if.experimental", conflicts_with = "addr", value_name = "IF_NAME")]
|
||||
pub net_if: Option<String>,
|
||||
}
|
||||
|
||||
impl NetworkArgs {
|
||||
/// Returns the resolved IP address.
|
||||
pub fn resolved_addr(&self) -> IpAddr {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
if let Some(ref if_name) = self.net_if {
|
||||
let if_name = if if_name.is_empty() { DEFAULT_NET_IF_NAME } else { if_name };
|
||||
return match reth_net_nat::net_if::resolve_net_if_ip(if_name) {
|
||||
Ok(addr) => addr,
|
||||
Err(err) => {
|
||||
error!(target: "reth::cli",
|
||||
if_name,
|
||||
%err,
|
||||
"Failed to read network interface IP"
|
||||
);
|
||||
|
||||
DEFAULT_DISCOVERY_ADDR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.addr
|
||||
}
|
||||
|
||||
/// Returns the resolved bootnodes if any are provided.
|
||||
pub fn resolved_bootnodes(&self) -> Option<Vec<NodeRecord>> {
|
||||
self.bootnodes.clone().map(|bootnodes| {
|
||||
@ -176,6 +206,7 @@ impl NetworkArgs {
|
||||
secret_key: SecretKey,
|
||||
default_peers_file: PathBuf,
|
||||
) -> NetworkConfigBuilder {
|
||||
let addr = self.resolved_addr();
|
||||
let chain_bootnodes = self
|
||||
.resolved_bootnodes()
|
||||
.unwrap_or_else(|| chain_spec.bootnodes().unwrap_or_else(mainnet_nodes));
|
||||
@ -224,11 +255,11 @@ impl NetworkArgs {
|
||||
})
|
||||
// apply discovery settings
|
||||
.apply(|builder| {
|
||||
let rlpx_socket = (self.addr, self.port).into();
|
||||
let rlpx_socket = (addr, self.port).into();
|
||||
self.discovery.apply_to_builder(builder, rlpx_socket, chain_bootnodes)
|
||||
})
|
||||
.listener_addr(SocketAddr::new(
|
||||
self.addr, // set discovery port based on instance number
|
||||
addr, // set discovery port based on instance number
|
||||
self.port,
|
||||
))
|
||||
.discovery_addr(SocketAddr::new(
|
||||
@ -303,6 +334,7 @@ impl Default for NetworkArgs {
|
||||
max_pending_pool_imports: DEFAULT_MAX_COUNT_PENDING_POOL_IMPORTS,
|
||||
max_seen_tx_history: DEFAULT_MAX_COUNT_TRANSACTIONS_SEEN_BY_PEER,
|
||||
max_capacity_cache_txns_pending_fetch: DEFAULT_MAX_CAPACITY_CACHE_PENDING_FETCH,
|
||||
net_if: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user