mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(cli): add persistent peers (#1167)
Co-authored-by: lambdaclass-user <github@lambdaclass.com> Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de> Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
This commit is contained in:
@ -14,8 +14,9 @@ use reth_primitives::{ForkId, NodeRecord, PeerId};
|
||||
use std::{
|
||||
collections::{hash_map::Entry, HashMap, HashSet, VecDeque},
|
||||
fmt::Display,
|
||||
io,
|
||||
io::{self, ErrorKind},
|
||||
net::{IpAddr, SocketAddr},
|
||||
path::Path,
|
||||
task::{Context, Poll},
|
||||
time::Duration,
|
||||
};
|
||||
@ -25,7 +26,7 @@ use tokio::{
|
||||
time::{Instant, Interval},
|
||||
};
|
||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||
use tracing::{debug, trace};
|
||||
use tracing::{debug, info, trace};
|
||||
|
||||
/// A communication channel to the [`PeersManager`] to apply manual changes to the peer set.
|
||||
#[derive(Clone, Debug)]
|
||||
@ -63,6 +64,14 @@ impl PeersHandle {
|
||||
|
||||
rx.await.unwrap_or(None)
|
||||
}
|
||||
|
||||
/// Returns all peers in the peerset.
|
||||
pub async fn all_peers(&self) -> Vec<NodeRecord> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.send(PeerCommand::GetPeers(tx));
|
||||
|
||||
rx.await.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Maintains the state of _all_ the peers known to the network.
|
||||
@ -111,6 +120,7 @@ impl PeersManager {
|
||||
backoff_durations,
|
||||
trusted_nodes,
|
||||
connect_trusted_nodes_only,
|
||||
basic_nodes,
|
||||
..
|
||||
} = config;
|
||||
let (manager_tx, handle_rx) = mpsc::unbounded_channel();
|
||||
@ -119,12 +129,16 @@ impl PeersManager {
|
||||
// We use half of the interval to decrease the max duration to `150%` in worst case
|
||||
let unban_interval = ban_duration.min(backoff_durations.low) / 2;
|
||||
|
||||
let mut peers = HashMap::with_capacity(trusted_nodes.len());
|
||||
let mut peers = HashMap::with_capacity(trusted_nodes.len() + basic_nodes.len());
|
||||
|
||||
for NodeRecord { address, tcp_port, udp_port: _, id } in trusted_nodes {
|
||||
peers.entry(id).or_insert_with(|| Peer::trusted(SocketAddr::from((address, tcp_port))));
|
||||
}
|
||||
|
||||
for NodeRecord { address, tcp_port, udp_port: _, id } in basic_nodes {
|
||||
peers.entry(id).or_insert_with(|| Peer::new(SocketAddr::from((address, tcp_port))));
|
||||
}
|
||||
|
||||
Self {
|
||||
peers,
|
||||
manager_tx,
|
||||
@ -623,6 +637,11 @@ impl PeersManager {
|
||||
PeerCommand::GetPeer(peer, tx) => {
|
||||
let _ = tx.send(self.peers.get(&peer).cloned());
|
||||
}
|
||||
PeerCommand::GetPeers(tx) => {
|
||||
let _ = tx.send(
|
||||
self.peers.iter().map(|(k, v)| NodeRecord::new(v.addr, *k)).collect(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -876,6 +895,8 @@ pub(crate) enum PeerCommand {
|
||||
ReputationChange(PeerId, ReputationChangeKind),
|
||||
/// Get information about a peer
|
||||
GetPeer(PeerId, oneshot::Sender<Option<Peer>>),
|
||||
/// Get node information on all peers
|
||||
GetPeers(oneshot::Sender<Vec<NodeRecord>>),
|
||||
}
|
||||
|
||||
/// Actions the peer manager can trigger.
|
||||
@ -921,6 +942,9 @@ pub struct PeersConfig {
|
||||
pub trusted_nodes: HashSet<NodeRecord>,
|
||||
/// Connect to trusted nodes only?
|
||||
pub connect_trusted_nodes_only: bool,
|
||||
/// Basic nodes to connect to.
|
||||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
pub basic_nodes: HashSet<NodeRecord>,
|
||||
/// How long to ban bad peers.
|
||||
#[cfg_attr(feature = "serde", serde(with = "humantime_serde"))]
|
||||
pub ban_duration: Duration,
|
||||
@ -948,6 +972,7 @@ impl Default for PeersConfig {
|
||||
backoff_durations: Default::default(),
|
||||
trusted_nodes: Default::default(),
|
||||
connect_trusted_nodes_only: false,
|
||||
basic_nodes: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -992,6 +1017,30 @@ impl PeersConfig {
|
||||
self.connect_trusted_nodes_only = trusted_only;
|
||||
self
|
||||
}
|
||||
|
||||
/// Nodes available at launch.
|
||||
pub fn with_basic_nodes(mut self, nodes: HashSet<NodeRecord>) -> Self {
|
||||
self.basic_nodes = nodes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Read from file nodes available at launch. Ignored if None.
|
||||
pub fn with_basic_nodes_from_file(
|
||||
self,
|
||||
optional_file: Option<impl AsRef<Path>>,
|
||||
) -> Result<Self, io::Error> {
|
||||
let Some(file_path) = optional_file else {
|
||||
return Ok(self)
|
||||
};
|
||||
let reader = match std::fs::File::open(file_path.as_ref()) {
|
||||
Ok(file) => std::io::BufReader::new(file),
|
||||
Err(e) if e.kind() == ErrorKind::NotFound => return Ok(self),
|
||||
Err(e) => Err(e)?,
|
||||
};
|
||||
info!(target: "net::peers", file = %file_path.as_ref().display(), "Loading saved peers");
|
||||
let nodes: HashSet<NodeRecord> = serde_json::from_reader(reader)?;
|
||||
Ok(self.with_basic_nodes(nodes))
|
||||
}
|
||||
}
|
||||
|
||||
/// The durations to use when a backoff should be applied to a peer.
|
||||
|
||||
Reference in New Issue
Block a user