reth_cli_commands/p2p/
enode.rs1use clap::Parser;
4use eyre::WrapErr;
5use reth_network_peers::NodeRecord;
6use secp256k1::SecretKey;
7use std::{
8 net::{IpAddr, Ipv4Addr, SocketAddr},
9 path::PathBuf,
10};
11
12#[derive(Parser, Debug)]
14pub struct Command {
15 pub discovery_secret: PathBuf,
17
18 #[arg(long)]
22 pub ip: Option<IpAddr>,
23
24 #[arg(long, default_value_t = 30303)]
26 pub port: u16,
27}
28
29impl Command {
30 pub fn execute(self) -> eyre::Result<()> {
32 let contents = reth_fs_util::read_to_string(&self.discovery_secret)?;
33 let sk = contents.parse::<SecretKey>().wrap_err_with(|| {
35 format!("Invalid secret key in {}", self.discovery_secret.display())
36 })?;
37 let ip = self.ip.unwrap_or(IpAddr::V4(Ipv4Addr::UNSPECIFIED));
38 let addr = SocketAddr::new(ip, self.port);
39 let enr = NodeRecord::from_secret_key(addr, &sk);
40 println!("{enr}");
41 Ok(())
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn missing_secret_key_is_not_generated() {
51 let dir = tempfile::tempdir().unwrap();
52 let path = dir.path().join("key");
53 let cmd = Command::parse_from(["enode", path.to_str().unwrap()]);
54 assert!(cmd.execute().is_err());
55 assert!(!path.exists());
56 }
57}