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