//! Example of how to use the network with a proxy for eth requests handling. //! //! This connects two peers: //! - first peer installs a channel for incoming eth request //! - second peer connects to first peer and sends a header request //! //! Run with //! //! ```not_rust //! cargo run --release -p example-network-proxy //! ``` use futures::StreamExt; use reth_chainspec::DEV; use reth_network::{ config::rng_secret_key, eth_requests::IncomingEthRequest, p2p::HeadersClient, transactions::NetworkTransactionEvent, types::{BlockHashOrNumber, NewPooledTransactionHashes68}, BlockDownloaderProvider, FetchClient, NetworkConfig, NetworkEventListenerProvider, NetworkHandle, NetworkInfo, NetworkManager, Peers, }; #[tokio::main] async fn main() -> eyre::Result<()> { reth_tracing::init_test_tracing(); // The key that's used for encrypting sessions and to identify our node. let local_key = rng_secret_key(); // Configure the network let config = NetworkConfig::builder(local_key).build_with_noop_provider(DEV.clone()); let (requests_tx, mut requests_rx) = tokio::sync::mpsc::channel(1000); let (transactions_tx, mut transactions_rx) = tokio::sync::mpsc::unbounded_channel(); // create the network instance let network = NetworkManager::eth(config) .await? // install the channel through which the network sends incoming eth requests .with_eth_request_handler(requests_tx) // install the channel through which the network sends incoming transaction messages .with_transactions(transactions_tx); // get a handle to the network to interact with it let handle = network.handle().clone(); tokio::task::spawn(async move { // print network events let mut events = handle.event_listener(); while let Some(event) = events.next().await { println!("Received event: {:?}", event); } }); let handle = network.handle().clone(); // spawn the network tokio::task::spawn(network); // spawn task to fetch a header using another peer/network tokio::task::spawn(async move { run_peer(handle).await.unwrap(); }); loop { // receive incoming eth requests and transaction messages from the second peer tokio::select! { eth_request = requests_rx.recv() => { let Some(eth_request) = eth_request else {break}; match eth_request { IncomingEthRequest::GetBlockHeaders { peer_id, request, response } => { println!("Received block headers request: {peer_id:?}, {request:?}"); response.send(Ok(vec![DEV.genesis_header().clone()].into())).unwrap(); } IncomingEthRequest::GetBlockBodies { .. } => {} IncomingEthRequest::GetNodeData { .. } => {} IncomingEthRequest::GetReceipts { .. } => {} } } transaction_message = transactions_rx.recv() => { let Some(transaction_message) = transaction_message else {break}; match transaction_message { NetworkTransactionEvent::IncomingTransactions { .. } => {} NetworkTransactionEvent::IncomingPooledTransactionHashes { peer_id, msg } => { println!("Received incoming tx hashes broadcast: {peer_id:?}, {msg:?}"); } NetworkTransactionEvent::GetPooledTransactions { .. } => {} NetworkTransactionEvent::GetTransactionsHandle(_) => {} } } } } Ok(()) } /// Launches another network/peer, connects to the first peer and sends requests/messages to the /// first peer. async fn run_peer(handle: NetworkHandle) -> eyre::Result<()> { // create another peer let config = NetworkConfig::builder(rng_secret_key()) // use random ports .with_unused_ports() .build_with_noop_provider(DEV.clone()); let network = NetworkManager::eth(config).await?; let peer = network.handle().clone(); // spawn additional peer tokio::task::spawn(network); // add the other peer as trusted // this will establish a connection to the first peer peer.add_trusted_peer(*handle.peer_id(), handle.local_addr()); // obtain the client that can emit requests let client: FetchClient = peer.fetch_client().await?; let header = client.get_header(BlockHashOrNumber::Number(0)).await.unwrap(); println!("Got header: {:?}", header); // send a (bogus) hashes message let hashes = NewPooledTransactionHashes68 { types: vec![1], sizes: vec![2], hashes: vec![Default::default()], }; peer.send_transactions_hashes(*handle.peer_id(), hashes.into()); Ok(()) }