reth_cli_commands/p2p/
bootnode.rs1use clap::Parser;
4use reth_discv4::{DiscoveryUpdate, Discv4, Discv4Config};
5use reth_discv5::{discv5::Event, Config, Discv5};
6use reth_net_nat::NatResolver;
7use reth_network_peers::NodeRecord;
8use std::{net::SocketAddr, str::FromStr};
9use tokio::select;
10use tokio_stream::StreamExt;
11use tracing::info;
12
13#[derive(Parser, Debug)]
15pub struct Command {
16 #[arg(long, default_value = ":30301")]
18 pub addr: String,
19
20 #[arg(long, default_value = "")]
22 pub gen_key: String,
23
24 #[arg(long, default_value = "")]
26 pub node_key: String,
27
28 #[arg(long, default_value = "any")]
30 pub nat: NatResolver,
31
32 #[arg(long)]
34 pub v5: bool,
35}
36
37impl Command {
38 pub async fn execute(self) -> eyre::Result<()> {
40 info!("Bootnode started with config: {:?}", self);
41 let sk = reth_network::config::rng_secret_key();
42 let socket_addr = SocketAddr::from_str(&self.addr)?;
43 let local_enr = NodeRecord::from_secret_key(socket_addr, &sk);
44
45 let config = Discv4Config::builder().external_ip_resolver(Some(self.nat)).build();
46
47 let (_discv4, mut discv4_service) =
48 Discv4::bind(socket_addr, local_enr, sk, config).await?;
49
50 info!("Started discv4 at address:{:?}", socket_addr);
51
52 let mut discv4_updates = discv4_service.update_stream();
53 discv4_service.spawn();
54
55 let mut discv5_updates = None;
57
58 if self.v5 {
59 info!("Starting discv5");
60 let config = Config::builder(socket_addr).build();
61 let (_discv5, updates, _local_enr_discv5) = Discv5::start(&sk, config).await?;
62 discv5_updates = Some(updates);
63 };
64
65 loop {
67 select! {
68 update = discv4_updates.next() => {
70 if let Some(update) = update {
71 match update {
72 DiscoveryUpdate::Added(record) => {
73 info!("(Discv4) new peer added, peer_id={:?}", record.id);
74 }
75 DiscoveryUpdate::Removed(peer_id) => {
76 info!("(Discv4) peer with peer-id={:?} removed", peer_id);
77 }
78 _ => {}
79 }
80 } else {
81 info!("(Discv4) update stream ended.");
82 break;
83 }
84 }
85 update = async {
87 if let Some(updates) = &mut discv5_updates {
88 updates.recv().await
89 } else {
90 futures::future::pending().await
91 }
92 } => {
93 if let Some(update) = update {
94 if let Event::SessionEstablished(enr, _) = update {
95 info!("(Discv5) new peer added, peer_id={:?}", enr.id());
96 }
97 } else {
98 info!("(Discv5) update stream ended.");
99 break;
100 }
101 }
102 }
103 }
104
105 Ok(())
106 }
107}