Skip to content

Commit

Permalink
feat: resolve domains in enode strings
Browse files Browse the repository at this point in the history
  • Loading branch information
Rjected committed May 23, 2024
1 parent a4933e7 commit f17b065
Show file tree
Hide file tree
Showing 18 changed files with 355 additions and 36 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions bin/reth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ reth-rpc-types.workspace = true
reth-rpc-types-compat.workspace = true
reth-rpc-api = { workspace = true, features = ["client"] }
reth-network = { workspace = true, features = ["serde"] }
reth-net-common.workspace = true
reth-network-api.workspace = true
reth-downloaders.workspace = true
reth-tracing.workspace = true
Expand Down
8 changes: 5 additions & 3 deletions bin/reth/src/commands/stage/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ 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 @@ -178,9 +179,10 @@ impl Command {
let mut config = config;
config.peers.trusted_nodes_only = self.network.trusted_only;
if !self.network.trusted_peers.is_empty() {
self.network.trusted_peers.iter().for_each(|peer| {
config.peers.trusted_nodes.insert(*peer);
});
for peer in &self.network.trusted_peers {
let peer = resolve_dns_node_record(peer.clone()).await?;
config.peers.trusted_nodes.insert(peer);
}
}

let network_secret_path = self
Expand Down
1 change: 1 addition & 0 deletions crates/net/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ alloy-primitives.workspace = true

# async
pin-project.workspace = true
url.workspace = true
tokio = { workspace = true, features = ["full"] }
41 changes: 41 additions & 0 deletions crates/net/common/src/dns_node_record_resolve.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//! Resolves a [DNSNodeRecord] to a [NodeRecord] by looking up the record in the DNS system.

use reth_network_types::{DNSNodeRecord, NodeRecord};
use std::io::Error;
use url::Host;

/// Resolves the host in a [DNSNodeRecord] to an IP address, returning a [NodeRecord]. If the domain
/// cannot be resolved, an error is returned.
///
/// If the host is already an IP address, the [NodeRecord] is returned immediately.
pub async fn resolve_dns_node_record(node_record: DNSNodeRecord) -> Result<NodeRecord, Error> {
let domain = match node_record.host {
Host::Ipv4(ip) => {
let id = node_record.id;
let tcp_port = node_record.tcp_port;
let udp_port = node_record.udp_port;

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

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

let mut ips = tokio::net::lookup_host(domain).await?;
let ip = ips
.next()
.ok_or_else(|| Error::new(std::io::ErrorKind::AddrNotAvailable, "No IP found"))?;

Ok(NodeRecord {
address: ip.ip(),
id: node_record.id,
tcp_port: node_record.tcp_port,
udp_port: node_record.udp_port,
})
}
3 changes: 3 additions & 0 deletions crates/net/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@

pub mod ban_list;
pub mod bandwidth_meter;

/// Traits related to tokio streams
pub mod stream;

pub mod dns_node_record_resolve;

pub mod ratelimit;
1 change: 1 addition & 0 deletions crates/net/discv5/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ futures.workspace = true

# io
rand.workspace = true
url.workspace = true

# misc
derive_more.workspace = true
Expand Down
25 changes: 16 additions & 9 deletions crates/net/discv5/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ use std::{
use derive_more::Display;
use discv5::ListenConfig;
use multiaddr::{Multiaddr, Protocol};
use reth_primitives::{Bytes, EnrForkIdEntry, ForkId, NodeRecord};
use reth_primitives::{Bytes, DNSNodeRecord, EnrForkIdEntry, ForkId};
use tracing::warn;
use url::Host;

use crate::{enr::discv4_id_to_multiaddr_id, filter::MustNotIncludeKeys, NetworkStackId};

Expand Down Expand Up @@ -129,9 +130,12 @@ impl ConfigBuilder {
}

/// Adds boot nodes in the form a list of [`NodeRecord`]s, parsed enodes.
pub fn add_unsigned_boot_nodes(mut self, enodes: impl Iterator<Item = NodeRecord>) -> Self {
pub fn add_unsigned_boot_nodes<T: Into<DNSNodeRecord>>(
mut self,
enodes: impl Iterator<Item = T>,
) -> Self {
for node in enodes {
if let Ok(node) = BootNode::from_unsigned(node) {
if let Ok(node) = BootNode::from_unsigned(node.into()) {
self.bootstrap_nodes.insert(node);
}
}
Expand Down Expand Up @@ -425,14 +429,17 @@ pub enum BootNode {
}

impl BootNode {
/// Parses a [`NodeRecord`] and serializes according to CL format. Note: [`discv5`] is
/// Parses a [`DNSNodeRecord`] and serializes according to CL format. Note: [`discv5`] is
/// originally a CL library hence needs this format to add the node.
pub fn from_unsigned(node_record: NodeRecord) -> Result<Self, secp256k1::Error> {
let NodeRecord { address, udp_port, id, .. } = node_record;
pub fn from_unsigned(node_record: DNSNodeRecord) -> Result<Self, secp256k1::Error> {
let DNSNodeRecord { host, udp_port, id, .. } = node_record;
let mut multi_address = Multiaddr::empty();
match address {
IpAddr::V4(ip) => multi_address.push(Protocol::Ip4(ip)),
IpAddr::V6(ip) => multi_address.push(Protocol::Ip6(ip)),
match host {
Host::Ipv4(ip) => multi_address.push(Protocol::Ip4(ip)),
Host::Ipv6(ip) => multi_address.push(Protocol::Ip6(ip)),
Host::Domain(domain) => {
multi_address.push(Protocol::Dns(domain.into()));
}
}

multi_address.push(Protocol::Udp(udp_port));
Expand Down
13 changes: 8 additions & 5 deletions crates/net/network/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use reth_dns_discovery::DnsDiscoveryConfig;
use reth_eth_wire::{HelloMessage, HelloMessageWithProtocols, Status};
use reth_network_types::{pk2id, PeerId};
use reth_primitives::{
mainnet_nodes, sepolia_nodes, ChainSpec, ForkFilter, Head, NodeRecord, MAINNET,
mainnet_nodes, sepolia_nodes, ChainSpec, DNSNodeRecord, ForkFilter, Head, MAINNET,
};
use reth_provider::{BlockReader, HeaderProvider};
use reth_tasks::{TaskSpawner, TokioTaskExecutor};
Expand All @@ -41,7 +41,7 @@ pub struct NetworkConfig<C> {
/// The node's secret key, from which the node's identity is derived.
pub secret_key: SecretKey,
/// All boot nodes to start network discovery with.
pub boot_nodes: HashSet<NodeRecord>,
pub boot_nodes: HashSet<DNSNodeRecord>,
/// How to set up discovery over DNS.
pub dns_discovery_config: Option<DnsDiscoveryConfig>,
/// Address to use for discovery v4.
Expand Down Expand Up @@ -147,7 +147,7 @@ pub struct NetworkConfigBuilder {
#[serde(skip)]
discovery_v5_builder: Option<reth_discv5::ConfigBuilder>,
/// All boot nodes to start network discovery with.
boot_nodes: HashSet<NodeRecord>,
boot_nodes: HashSet<DNSNodeRecord>,
/// Address to use for discovery
discovery_addr: Option<SocketAddr>,
/// Listener for incoming connections
Expand Down Expand Up @@ -356,8 +356,11 @@ impl NetworkConfigBuilder {
}

/// Sets the boot nodes.
pub fn boot_nodes(mut self, nodes: impl IntoIterator<Item = NodeRecord>) -> Self {
self.boot_nodes = nodes.into_iter().collect();
pub fn boot_nodes<T: Into<DNSNodeRecord>>(
mut self,
nodes: impl IntoIterator<Item = T>,
) -> Self {
self.boot_nodes = nodes.into_iter().map(Into::into).collect();
self
}

Expand Down
13 changes: 11 additions & 2 deletions crates/net/network/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ use reth_eth_wire::{
DisconnectReason, EthVersion, Status,
};
use reth_metrics::common::mpsc::UnboundedMeteredSender;
use reth_net_common::bandwidth_meter::BandwidthMeter;
use reth_net_common::{
bandwidth_meter::BandwidthMeter, dns_node_record_resolve::resolve_dns_node_record,
};
use reth_network_api::ReputationChangeKind;
use reth_network_types::PeerId;
use reth_primitives::{ForkId, NodeRecord};
Expand Down Expand Up @@ -206,9 +208,16 @@ where
})?;
let listener_address = Arc::new(Mutex::new(incoming.local_address()));

// resolve boot nodes
let mut resolved_boot_nodes = vec![];
for record in boot_nodes.iter() {
let resolved = resolve_dns_node_record(record.clone()).await?;
resolved_boot_nodes.push(resolved);
}

discovery_v4_config = discovery_v4_config.map(|mut disc_config| {
// merge configured boot nodes
disc_config.bootstrap_nodes.extend(boot_nodes.clone());
disc_config.bootstrap_nodes.extend(resolved_boot_nodes.clone());
disc_config.add_eip868_pair("eth", status.forkid);
disc_config
});
Expand Down
Loading

0 comments on commit f17b065

Please sign in to comment.