Skip to main content

reth_cli_commands/p2p/
rlpx.rs

1//! RLPx subcommand of P2P Debugging tool.
2
3use clap::{Parser, Subcommand};
4use reth_ecies::stream::ECIESStream;
5use reth_eth_wire::{HelloMessage, UnauthedP2PStream};
6use reth_network::config::rng_secret_key;
7use reth_network_peers::{pk2id, AnyNode};
8use tokio::net::TcpStream;
9
10/// RLPx commands
11#[derive(Parser, Debug)]
12pub struct Command {
13    #[command(subcommand)]
14    subcommand: Subcommands,
15}
16
17impl Command {
18    // Execute `p2p rlpx` command.
19    pub async fn execute(self) -> eyre::Result<()> {
20        match self.subcommand {
21            Subcommands::Ping { node } => {
22                let key = rng_secret_key();
23                let node_record = node
24                    .node_record()
25                    .ok_or_else(|| eyre::eyre!("failed to parse node {}", node))?;
26                let outgoing =
27                    TcpStream::connect((node_record.address, node_record.tcp_port)).await?;
28                let ecies_stream = ECIESStream::connect(outgoing, key, node_record.id).await?;
29
30                let peer_id = pk2id(&key.public_key());
31                let hello = HelloMessage::builder(peer_id).build();
32
33                let (_, their_hello) =
34                    UnauthedP2PStream::new(ecies_stream).handshake(hello).await?;
35
36                println!("{their_hello:#?}");
37            }
38        }
39        Ok(())
40    }
41}
42
43#[derive(Subcommand, Debug)]
44enum Subcommands {
45    /// ping node
46    Ping {
47        /// The node to ping.
48        node: AnyNode,
49    },
50}