Skip to content

Commit

Permalink
Move resolve func to DNSNodeRecord::
Browse files Browse the repository at this point in the history
  • Loading branch information
sergerad committed May 24, 2024
1 parent 0eb49c9 commit d8cc0c3
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 125 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions bin/reth/src/commands/p2p/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ impl Command {

let mut config: Config = confy::load_path(&config_path).unwrap_or_default();

for &peer in &self.network.trusted_peers {
config.peers.trusted_nodes.insert(peer);
for peer in &self.network.trusted_peers {
config.peers.trusted_nodes.insert(peer.resolve(None).await?);
}

if config.peers.trusted_nodes.is_empty() && self.network.trusted_only {
Expand Down
3 changes: 1 addition & 2 deletions bin/reth/src/commands/stage/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ use reth_config::{
use reth_db::init_db;
use reth_downloaders::bodies::bodies::BodiesDownloaderBuilder;
use reth_exex::ExExManagerHandle;
use reth_net_common::dns_node_record_resolve::resolve_dns_node_record;
use reth_primitives::ChainSpec;
use reth_provider::{
ProviderFactory, StageCheckpointReader, StageCheckpointWriter, StaticFileProviderFactory,
Expand Down Expand Up @@ -180,7 +179,7 @@ impl Command {
config.peers.trusted_nodes_only = self.network.trusted_only;
if !self.network.trusted_peers.is_empty() {
for peer in &self.network.trusted_peers {
let peer = resolve_dns_node_record(peer.clone(), None).await?;
let peer = peer.resolve(None).await?;
config.peers.trusted_nodes.insert(peer);
}
}
Expand Down
1 change: 0 additions & 1 deletion crates/net/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,3 @@ alloy-primitives = { workspace = true, features = ["rand"] }
pin-project.workspace = true
url.workspace = true
tokio = { workspace = true, features = ["full"] }
tokio-retry = { workspace = true }
110 changes: 0 additions & 110 deletions crates/net/common/src/dns_node_record_resolve.rs

This file was deleted.

2 changes: 0 additions & 2 deletions crates/net/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,4 @@ pub mod bandwidth_meter;
/// Traits related to tokio streams
pub mod stream;

pub mod dns_node_record_resolve;

pub mod ratelimit;
6 changes: 2 additions & 4 deletions crates/net/network/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ use reth_eth_wire::{
DisconnectReason, EthVersion, Status,
};
use reth_metrics::common::mpsc::UnboundedMeteredSender;
use reth_net_common::{
bandwidth_meter::BandwidthMeter, dns_node_record_resolve::resolve_dns_node_record,
};
use reth_net_common::bandwidth_meter::BandwidthMeter;
use reth_network_api::ReputationChangeKind;
use reth_network_types::PeerId;
use reth_primitives::{ForkId, NodeRecord};
Expand Down Expand Up @@ -211,7 +209,7 @@ where
// resolve boot nodes
let mut resolved_boot_nodes = vec![];
for record in boot_nodes.iter() {
let resolved = resolve_dns_node_record(record.clone(), None).await?;
let resolved = record.resolve(None).await?;
resolved_boot_nodes.push(resolved);
}

Expand Down
2 changes: 2 additions & 0 deletions crates/net/types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ secp256k1.workspace = true
serde_with.workspace = true
thiserror.workspace = true
url.workspace = true
tokio = { workspace = true, features = ["full"] }
tokio-retry = { workspace = true }

[dev-dependencies]
alloy-primitives = { workspace = true, features = ["rand"] }
Expand Down
96 changes: 96 additions & 0 deletions crates/net/types/src/dns_node_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use std::{
fmt::{self, Write},
io::Error,
net::IpAddr,
num::ParseIntError,
str::FromStr,
Expand All @@ -27,6 +28,15 @@ pub struct DNSNodeRecord {
pub id: PeerId,
}

/// Retry strategy for DNS lookups.
#[derive(Debug)]
pub struct RetryStrategy {
/// The amount of time between retries.
interval: u64,
/// The number of retries.
retries: usize,
}

impl DNSNodeRecord {
/// Derive the [`NodeRecord`] from the secret key and addr
pub fn from_secret_key(host: Host, port: u16, sk: &SecretKey) -> Self {
Expand All @@ -39,6 +49,66 @@ impl DNSNodeRecord {
pub fn new(host: Host, port: u16, id: PeerId) -> Self {
Self { host, tcp_port: port, udp_port: port, id }
}

/// Resolves the host in a [DNSNodeRecord] to an IP address, returning a [NodeRecord].
/// This function is provided instead of From<DNSNodeRecord> to allow for a retry strategy and async.
pub async fn resolve(
&self,
retry_strategy: Option<RetryStrategy>,
) -> Result<NodeRecord, Error> {
let domain = match self.host.to_owned() {
Host::Ipv4(ip) => {
let id = self.id;
let tcp_port = self.tcp_port;
let udp_port = self.udp_port;

return Ok(NodeRecord { address: ip.into(), id, tcp_port, udp_port })
}
Host::Ipv6(ip) => {
let id = self.id;
let tcp_port = self.tcp_port;
let udp_port = self.udp_port;

return Ok(NodeRecord { address: ip.into(), id, tcp_port, udp_port })
}
Host::Domain(domain) => domain,
};

// Lookip ipaddr from domain
match Self::lookup_host(&domain).await {
Ok(ip) => Ok(NodeRecord {
address: ip,
id: self.id,
tcp_port: self.tcp_port,
udp_port: self.udp_port,
}),
Err(e) => {
// Retry if strategy is provided
if let Some(strat) = retry_strategy {
let lookup = || async { Self::lookup_host(&domain).await };
let strat = tokio_retry::strategy::FixedInterval::from_millis(strat.interval)
.take(strat.retries);
let ip = tokio_retry::Retry::spawn(strat, lookup).await?;
Ok(NodeRecord {
address: ip,
id: self.id,
tcp_port: self.tcp_port,
udp_port: self.udp_port,
})
} else {
Err(e)
}
}
}
}

async fn lookup_host(domain: &str) -> Result<std::net::IpAddr, Error> {
let mut ips = tokio::net::lookup_host(format!("{domain}:0")).await?;
let ip = ips
.next()
.ok_or_else(|| Error::new(std::io::ErrorKind::AddrNotAvailable, "No IP found"))?;
Ok(ip.ip())
}
}

impl fmt::Display for DNSNodeRecord {
Expand Down Expand Up @@ -234,4 +304,30 @@ mod tests {
assert_eq!(node, expected);
}
}

#[tokio::test]
async fn test_resolve_dns_node_record() {
use super::*;

// Set up tests
let tests = vec![
("localhost", None),
("localhost", Some(RetryStrategy { interval: 1000, retries: 3 })),
];

// Run tests
for (domain, retry_strategy) in tests {
// Construct record
let rec =
DNSNodeRecord::new(url::Host::Domain(domain.to_owned()), 30300, PeerId::random());

// Resolve domain and validate
let rec = rec.resolve(retry_strategy).await.unwrap();
if let std::net::IpAddr::V4(addr) = rec.address {
assert_eq!(addr, std::net::Ipv4Addr::new(127, 0, 0, 1))
} else {
panic!("Expected IPv4 address");
}
}
}
}
4 changes: 2 additions & 2 deletions crates/node/builder/src/launch/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use reth_auto_seal_consensus::MiningMode;
use reth_config::{config::EtlConfig, PruneConfig};
use reth_db::{database::Database, database_metrics::DatabaseMetrics};
use reth_interfaces::p2p::headers::client::HeadersClient;
use reth_net_common::dns_node_record_resolve::resolve_dns_node_record;
use reth_node_core::{
cli::config::RethRpcConfig,
dirs::{ChainPath, DataDirPath},
Expand Down Expand Up @@ -81,7 +80,8 @@ impl LaunchContext {

// resolve trusted peers if they use a domain instead of dns
for peer in &config.network.trusted_peers {
let resolved = resolve_dns_node_record(peer.clone(), None)
let resolved = peer
.resolve(None)
.await
.wrap_err_with(|| format!("Could not resolve trusted peer {peer}"))?;
toml_config.peers.trusted_nodes.insert(resolved);
Expand Down

0 comments on commit d8cc0c3

Please sign in to comment.