Skip to content

Commit

Permalink
feat: support DNS in reth.toml for trusted_nodes (#9864)
Browse files Browse the repository at this point in the history
  • Loading branch information
loocapro authored Jul 31, 2024
1 parent f9ed57d commit fcbdbf3
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 53 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion crates/cli/commands/src/p2p.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ impl Command {

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

config.peers.trusted_nodes.extend(self.network.resolve_trusted_peers().await?);
config.peers.trusted_nodes.extend(self.network.trusted_peers.clone());

if config.peers.trusted_nodes.is_empty() && self.network.trusted_only {
eyre::bail!("No trusted nodes. Set trusted peer with `--trusted-peer <enode record>` or set `--trusted-only` to `false`")
Expand Down
2 changes: 1 addition & 1 deletion crates/cli/commands/src/stage/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ impl Command {

let mut config = config;
config.peers.trusted_nodes_only = self.network.trusted_only;
config.peers.trusted_nodes.extend(self.network.resolve_trusted_peers().await?);
config.peers.trusted_nodes.extend(self.network.trusted_peers.clone());

let network_secret_path = self
.network
Expand Down
1 change: 1 addition & 0 deletions crates/config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ confy.workspace = true
[dev-dependencies]
tempfile.workspace = true
toml.workspace = true
reth-network-peers.workspace = true
27 changes: 26 additions & 1 deletion crates/config/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,8 @@ where
#[cfg(test)]
mod tests {
use super::{Config, EXTENSION};
use std::time::Duration;
use reth_network_peers::TrustedPeer;
use std::{str::FromStr, time::Duration};

fn with_tempdir(filename: &str, proc: fn(&std::path::Path)) {
let temp_dir = tempfile::tempdir().unwrap();
Expand Down Expand Up @@ -751,4 +752,28 @@ connect_trusted_nodes_only = true
let conf: Config = toml::from_str(trusted_nodes_only).unwrap();
assert!(conf.peers.trusted_nodes_only);
}

#[test]
fn test_can_support_dns_in_trusted_nodes() {
let reth_toml = r#"
[peers]
trusted_nodes = [
"enode://0401e494dbd0c84c5c0f72adac5985d2f2525e08b68d448958aae218f5ac8198a80d1498e0ebec2ce38b1b18d6750f6e61a56b4614c5a6c6cf0981c39aed47dc@34.159.32.127:30303",
"enode://e9675164b5e17b9d9edf0cc2bd79e6b6f487200c74d1331c220abb5b8ee80c2eefbf18213989585e9d0960683e819542e11d4eefb5f2b4019e1e49f9fd8fff18@berav2-bootnode.staketab.org:30303"
]
"#;

let conf: Config = toml::from_str(reth_toml).unwrap();
assert_eq!(conf.peers.trusted_nodes.len(), 2);

let expected_enodes = vec![
"enode://0401e494dbd0c84c5c0f72adac5985d2f2525e08b68d448958aae218f5ac8198a80d1498e0ebec2ce38b1b18d6750f6e61a56b4614c5a6c6cf0981c39aed47dc@34.159.32.127:30303",
"enode://e9675164b5e17b9d9edf0cc2bd79e6b6f487200c74d1331c220abb5b8ee80c2eefbf18213989585e9d0960683e819542e11d4eefb5f2b4019e1e49f9fd8fff18@berav2-bootnode.staketab.org:30303",
];

for enode in expected_enodes {
let node = TrustedPeer::from_str(enode).unwrap();
assert!(conf.peers.trusted_nodes.contains(&node));
}
}
}
6 changes: 3 additions & 3 deletions crates/net/network-types/src/peers/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::{BackoffKind, ReputationChangeWeights};
use reth_net_banlist::BanList;
use reth_network_peers::NodeRecord;
use reth_network_peers::{NodeRecord, TrustedPeer};
use std::{
collections::HashSet,
io::{self, ErrorKind},
Expand Down Expand Up @@ -122,7 +122,7 @@ pub struct PeersConfig {
#[cfg_attr(feature = "serde", serde(with = "humantime_serde"))]
pub refill_slots_interval: Duration,
/// Trusted nodes to connect to or accept from
pub trusted_nodes: HashSet<NodeRecord>,
pub trusted_nodes: Vec<TrustedPeer>,
/// Connect to or accept from trusted nodes only?
#[cfg_attr(feature = "serde", serde(alias = "connect_trusted_nodes_only"))]
pub trusted_nodes_only: bool,
Expand Down Expand Up @@ -221,7 +221,7 @@ impl PeersConfig {
}

/// Nodes to always connect to.
pub fn with_trusted_nodes(mut self, nodes: HashSet<NodeRecord>) -> Self {
pub fn with_trusted_nodes(mut self, nodes: Vec<TrustedPeer>) -> Self {
self.trusted_nodes = nodes;
self
}
Expand Down
1 change: 1 addition & 0 deletions crates/net/network/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ alloy-provider= { workspace = true, features = ["admin-api"] }
# misc
serial_test.workspace = true
tempfile.workspace = true
url.workspace = true

## Benchmarks
pprof = { workspace = true, features = ["criterion", "flamegraph"] }
Expand Down
47 changes: 27 additions & 20 deletions crates/net/network/src/peers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use tokio::{
time::{Instant, Interval},
};
use tokio_stream::wrappers::UnboundedReceiverStream;
use tracing::trace;
use tracing::{trace, warn};

/// A communication channel to the [`PeersManager`] to apply manual changes to the peer set.
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -155,11 +155,18 @@ impl PeersManager {
let mut peers = HashMap::with_capacity(trusted_nodes.len() + basic_nodes.len());
let mut trusted_peer_ids = HashSet::with_capacity(trusted_nodes.len());

for NodeRecord { address, tcp_port, udp_port, id } in trusted_nodes {
trusted_peer_ids.insert(id);
peers.entry(id).or_insert_with(|| {
Peer::trusted(PeerAddr::new_with_ports(address, tcp_port, Some(udp_port)))
});
for trusted_peer in trusted_nodes {
match trusted_peer.resolve_blocking() {
Ok(NodeRecord { address, tcp_port, udp_port, id }) => {
trusted_peer_ids.insert(id);
peers.entry(id).or_insert_with(|| {
Peer::trusted(PeerAddr::new_with_ports(address, tcp_port, Some(udp_port)))
});
}
Err(err) => {
warn!(target: "net::peers", ?err, "Failed to resolve trusted peer");
}
}
}

for NodeRecord { address, tcp_port, udp_port, id } in basic_nodes {
Expand Down Expand Up @@ -1328,14 +1335,13 @@ mod tests {
session::PendingSessionHandshakeError,
PeersConfig,
};
use reth_discv4::NodeRecord;
use reth_eth_wire::{
errors::{EthHandshakeError, EthStreamError, P2PHandshakeError, P2PStreamError},
DisconnectReason,
};
use reth_net_banlist::BanList;
use reth_network_api::{Direction, ReputationChangeKind};
use reth_network_peers::PeerId;
use reth_network_peers::{PeerId, TrustedPeer};
use reth_network_types::{peers::reputation::DEFAULT_REPUTATION, BackoffKind};
use reth_primitives::B512;
use std::{
Expand All @@ -1347,6 +1353,7 @@ mod tests {
task::{Context, Poll},
time::Duration,
};
use url::Host;

struct PeerActionFuture<'a> {
peers: &'a mut PeersManager,
Expand Down Expand Up @@ -2290,12 +2297,12 @@ mod tests {
async fn test_trusted_peers_are_prioritized() {
let trusted_peer = PeerId::random();
let trusted_sock = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
let config = PeersConfig::test().with_trusted_nodes(HashSet::from([NodeRecord {
address: IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)),
let config = PeersConfig::test().with_trusted_nodes(vec![TrustedPeer {
host: Host::Ipv4(Ipv4Addr::new(127, 0, 1, 2)),
tcp_port: 8008,
udp_port: 8008,
id: trusted_peer,
}]));
}]);
let mut peers = PeersManager::new(config);

let basic_peer = PeerId::random();
Expand Down Expand Up @@ -2329,12 +2336,12 @@ mod tests {
let trusted_peer = PeerId::random();
let trusted_sock = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
let config = PeersConfig::test()
.with_trusted_nodes(HashSet::from([NodeRecord {
address: IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)),
.with_trusted_nodes(vec![TrustedPeer {
host: Host::Ipv4(Ipv4Addr::new(127, 0, 1, 2)),
tcp_port: 8008,
udp_port: 8008,
id: trusted_peer,
}]))
}])
.with_trusted_nodes_only(true);
let mut peers = PeersManager::new(config);

Expand Down Expand Up @@ -2366,12 +2373,12 @@ mod tests {
async fn test_incoming_with_trusted_nodes_only() {
let trusted_peer = PeerId::random();
let config = PeersConfig::test()
.with_trusted_nodes(HashSet::from([NodeRecord {
address: IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)),
.with_trusted_nodes(vec![TrustedPeer {
host: Host::Ipv4(Ipv4Addr::new(127, 0, 1, 2)),
tcp_port: 8008,
udp_port: 8008,
id: trusted_peer,
}]))
}])
.with_trusted_nodes_only(true);
let mut peers = PeersManager::new(config);

Expand Down Expand Up @@ -2399,12 +2406,12 @@ mod tests {
async fn test_incoming_without_trusted_nodes_only() {
let trusted_peer = PeerId::random();
let config = PeersConfig::test()
.with_trusted_nodes(HashSet::from([NodeRecord {
address: IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)),
.with_trusted_nodes(vec![TrustedPeer {
host: Host::Ipv4(Ipv4Addr::new(127, 0, 1, 2)),
tcp_port: 8008,
udp_port: 8008,
id: trusted_peer,
}]))
}])
.with_trusted_nodes_only(false);
let mut peers = PeersManager::new(config);

Expand Down
29 changes: 16 additions & 13 deletions crates/net/network/tests/it/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ use reth_network_p2p::{
headers::client::{HeadersClient, HeadersRequest},
sync::{NetworkSyncUpdater, SyncState},
};
use reth_network_peers::{mainnet_nodes, NodeRecord};
use reth_network_peers::{mainnet_nodes, NodeRecord, TrustedPeer};
use reth_provider::test_utils::NoopProvider;
use reth_transaction_pool::test_utils::testing_pool;
use secp256k1::SecretKey;
use std::{collections::HashSet, net::SocketAddr, time::Duration};
use tokio::task;
use url::Host;

#[tokio::test(flavor = "multi_thread")]
async fn test_establish_connections() {
Expand Down Expand Up @@ -594,13 +595,18 @@ async fn test_disconnect_incoming_when_exceeded_incoming_connections() {
#[tokio::test(flavor = "multi_thread")]
async fn test_always_accept_incoming_connections_from_trusted_peers() {
reth_tracing::init_test_tracing();
let peer1 = new_random_peer(10, HashSet::new()).await;
let peer2 = new_random_peer(0, HashSet::new()).await;
let peer1 = new_random_peer(10, vec![]).await;
let peer2 = new_random_peer(0, vec![]).await;

// setup the peer with max_inbound = 1, and add other_peer_3 as trust nodes
let peer =
new_random_peer(0, HashSet::from([NodeRecord::new(peer2.local_addr(), *peer2.peer_id())]))
.await;
let trusted_peer2 = TrustedPeer {
host: Host::Ipv4(peer2.local_addr().ip().to_string().parse().unwrap()),
tcp_port: peer2.local_addr().port(),
udp_port: peer2.local_addr().port(),
id: *peer2.peer_id(),
};

let peer = new_random_peer(0, vec![trusted_peer2.clone()]).await;

let handle = peer.handle().clone();
let peer1_handle = peer1.handle().clone();
Expand Down Expand Up @@ -634,11 +640,11 @@ async fn test_always_accept_incoming_connections_from_trusted_peers() {
#[tokio::test(flavor = "multi_thread")]
async fn test_rejected_by_already_connect() {
reth_tracing::init_test_tracing();
let other_peer1 = new_random_peer(10, HashSet::new()).await;
let other_peer2 = new_random_peer(10, HashSet::new()).await;
let other_peer1 = new_random_peer(10, vec![]).await;
let other_peer2 = new_random_peer(10, vec![]).await;

// setup the peer with max_inbound = 2
let peer = new_random_peer(2, HashSet::new()).await;
let peer = new_random_peer(2, vec![]).await;

let handle = peer.handle().clone();
let other_peer_handle1 = other_peer1.handle().clone();
Expand Down Expand Up @@ -671,10 +677,7 @@ async fn test_rejected_by_already_connect() {
assert_eq!(handle.num_connected_peers(), 2);
}

async fn new_random_peer(
max_in_bound: usize,
trusted_nodes: HashSet<NodeRecord>,
) -> NetworkManager {
async fn new_random_peer(max_in_bound: usize, trusted_nodes: Vec<TrustedPeer>) -> NetworkManager {
let secret_key = SecretKey::new(&mut rand::thread_rng());
let peers_config =
PeersConfig::default().with_max_inbound(max_in_bound).with_trusted_nodes(trusted_nodes);
Expand Down
1 change: 0 additions & 1 deletion crates/node/builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ eyre.workspace = true
fdlimit.workspace = true
confy.workspace = true
rayon.workspace = true
backon.workspace = true

# tracing
tracing.workspace = true
Expand Down
17 changes: 5 additions & 12 deletions crates/node/builder/src/launch/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::{
hooks::OnComponentInitializedHook,
BuilderContext, NodeAdapter,
};
use backon::{ConstantBuilder, Retryable};
use eyre::Context;
use rayon::ThreadPoolBuilder;
use reth_auto_seal_consensus::MiningMode;
Expand Down Expand Up @@ -238,17 +237,11 @@ impl LaunchContextWith<WithConfigs> {
if !self.attachment.config.network.trusted_peers.is_empty() {
info!(target: "reth::cli", "Adding trusted nodes");

// resolve trusted peers if they use a domain instead of dns
let resolved = futures::future::try_join_all(
self.attachment.config.network.trusted_peers.iter().map(|peer| async move {
let backoff = ConstantBuilder::default()
.with_max_times(self.attachment.config.network.dns_retries);
(move || { peer.resolve() })
.retry(&backoff)
.notify(|err, _| warn!(target: "reth::cli", "Error resolving peer domain: {err}. Retrying..."))
.await
})).await?;
self.attachment.toml_config.peers.trusted_nodes.extend(resolved);
self.attachment
.toml_config
.peers
.trusted_nodes
.extend(self.attachment.config.network.trusted_peers.clone());
}
Ok(self)
}
Expand Down

0 comments on commit fcbdbf3

Please sign in to comment.