diff --git a/Cargo.lock b/Cargo.lock index 20aed5f8f..ec85c912c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7476,6 +7476,7 @@ dependencies = [ "reth-dns-discovery", "reth-ecies", "reth-eth-wire", + "reth-fs-util", "reth-metrics", "reth-net-banlist", "reth-network", @@ -7650,6 +7651,7 @@ dependencies = [ "tempfile", "tokio", "tokio-stream", + "tracing", ] [[package]] diff --git a/crates/net/network/Cargo.toml b/crates/net/network/Cargo.toml index 100114624..efadac80c 100644 --- a/crates/net/network/Cargo.toml +++ b/crates/net/network/Cargo.toml @@ -14,6 +14,7 @@ workspace = true [dependencies] # reth reth-chainspec.workspace = true +reth-fs-util.workspace = true reth-primitives.workspace = true reth-net-banlist.workspace = true reth-network-api.workspace = true diff --git a/crates/net/network/src/manager.rs b/crates/net/network/src/manager.rs index 2fea2cbc4..9d68bac3c 100644 --- a/crates/net/network/src/manager.rs +++ b/crates/net/network/src/manager.rs @@ -41,6 +41,7 @@ use reth_eth_wire::{ capability::{Capabilities, CapabilityMessage}, DisconnectReason, EthVersion, Status, }; +use reth_fs_util::{self as fs, FsPathError}; use reth_metrics::common::mpsc::UnboundedMeteredSender; use reth_network_api::{EthProtocolInfo, NetworkStatus, PeerInfo, ReputationChangeKind}; use reth_network_peers::{NodeRecord, PeerId}; @@ -51,6 +52,7 @@ use reth_tokio_util::EventSender; use secp256k1::SecretKey; use std::{ net::SocketAddr, + path::Path, pin::Pin, sync::{ atomic::{AtomicU64, AtomicUsize, Ordering}, @@ -336,6 +338,11 @@ where self.swarm.state().peers().iter_peers() } + /// Returns the number of peers in the peer set. + pub fn num_known_peers(&self) -> usize { + self.swarm.state().peers().num_known_peers() + } + /// Returns a new [`PeersHandle`] that can be cloned and shared. /// /// The [`PeersHandle`] can be used to interact with the network's peer set. @@ -343,6 +350,18 @@ where self.swarm.state().peers().handle() } + /// Collect the peers from the [`NetworkManager`] and write them to the given + /// `persistent_peers_file`. + pub fn write_peers_to_file(&self, persistent_peers_file: &Path) -> Result<(), FsPathError> { + let known_peers = self.all_peers().collect::>(); + let known_peers = serde_json::to_string_pretty(&known_peers).map_err(|e| { + FsPathError::WriteJson { source: e, path: persistent_peers_file.to_path_buf() } + })?; + persistent_peers_file.parent().map(fs::create_dir_all).transpose()?; + fs::write(persistent_peers_file, known_peers)?; + Ok(()) + } + /// Returns a new [`FetchClient`] that can be cloned and shared. /// /// The [`FetchClient`] is the entrypoint for sending requests to the network. diff --git a/crates/node/builder/Cargo.toml b/crates/node/builder/Cargo.toml index f83145b05..351dbc3d8 100644 --- a/crates/node/builder/Cargo.toml +++ b/crates/node/builder/Cargo.toml @@ -72,5 +72,8 @@ confy.workspace = true rayon.workspace = true backon.workspace = true +# tracing +tracing.workspace = true + [dev-dependencies] tempfile.workspace = true diff --git a/crates/node/builder/src/builder/mod.rs b/crates/node/builder/src/builder/mod.rs index 72e56b71a..dbdef2291 100644 --- a/crates/node/builder/src/builder/mod.rs +++ b/crates/node/builder/src/builder/mod.rs @@ -30,7 +30,6 @@ use reth_node_core::{ dirs::{ChainPath, DataDirPath, MaybePlatformPath}, node_config::NodeConfig, primitives::Head, - utils::write_peers_to_file, }; use reth_primitives::revm_primitives::EnvKzgSettings; use reth_provider::{providers::BlockchainProvider, ChainSpecProvider}; @@ -39,6 +38,7 @@ use reth_transaction_pool::{PoolConfig, TransactionPool}; use secp256k1::SecretKey; pub use states::*; use std::sync::Arc; +use tracing::{info, trace, warn}; mod states; @@ -509,7 +509,18 @@ impl BuilderContext { "p2p network task", |shutdown| { network.run_until_graceful_shutdown(shutdown, |network| { - write_peers_to_file(&network, known_peers_file) + if let Some(peers_file) = known_peers_file { + let num_known_peers = network.num_known_peers(); + trace!(target: "reth::cli", peers_file=?peers_file, num_peers=%num_known_peers, "Saving current peers"); + match network.write_peers_to_file(peers_file.as_path()) { + Ok(_) => { + info!(target: "reth::cli", peers_file=?peers_file, "Wrote network peers to file"); + } + Err(err) => { + warn!(target: "reth::cli", %err, "Failed to write network peers to file"); + } + } + } }) }, ); diff --git a/crates/node/core/src/utils.rs b/crates/node/core/src/utils.rs index 8393b50be..7bf3314f5 100644 --- a/crates/node/core/src/utils.rs +++ b/crates/node/core/src/utils.rs @@ -4,22 +4,19 @@ use eyre::Result; use reth_chainspec::ChainSpec; use reth_consensus_common::validation::validate_block_pre_execution; -use reth_fs_util as fs; -use reth_network::NetworkManager; use reth_network_p2p::{ bodies::client::BodiesClient, headers::client::{HeadersClient, HeadersRequest}, priority::Priority, }; use reth_primitives::{BlockHashOrNumber, HeadersDirection, SealedBlock, SealedHeader}; -use reth_provider::BlockReader; use reth_rpc_types::engine::{JwtError, JwtSecret}; use std::{ env::VarError, path::{Path, PathBuf}, sync::Arc, }; -use tracing::{debug, info, trace, warn}; +use tracing::{debug, info}; /// Parses a user-specified path with support for environment variables and common shorthands (e.g. /// ~ for the user's home directory). @@ -38,29 +35,6 @@ pub fn get_or_create_jwt_secret_from_path(path: &Path) -> Result(network: &NetworkManager, persistent_peers_file: Option) -where - C: BlockReader + Unpin, -{ - if let Some(file_path) = persistent_peers_file { - let known_peers = network.all_peers().collect::>(); - if let Ok(known_peers) = serde_json::to_string_pretty(&known_peers) { - trace!(target: "reth::cli", peers_file =?file_path, num_peers=%known_peers.len(), "Saving current peers"); - let parent_dir = file_path.parent().map(fs::create_dir_all).transpose(); - match parent_dir.and_then(|_| fs::write(&file_path, known_peers)) { - Ok(_) => { - info!(target: "reth::cli", peers_file=?file_path, "Wrote network peers to file"); - } - Err(err) => { - warn!(target: "reth::cli", %err, peers_file=?file_path, "Failed to write network peers to file"); - } - } - } - } -} - /// Get a single header from network pub async fn get_single_header( client: Client,