diff --git a/binaries/cuprated/src/rpc/other.rs b/binaries/cuprated/src/rpc/other.rs index a8a1bc0..29a5370 100644 --- a/binaries/cuprated/src/rpc/other.rs +++ b/binaries/cuprated/src/rpc/other.rs @@ -13,6 +13,7 @@ use cuprate_constants::rpc::{ }; use cuprate_helper::cast::usize_to_u64; use cuprate_hex::Hex; +use cuprate_p2p_core::{client::handshaker::builder::DummyAddressBook, ClearNet}; use cuprate_rpc_interface::RpcHandler; use cuprate_rpc_types::{ base::{AccessResponseBase, ResponseBase}, @@ -50,6 +51,8 @@ use crate::{ }, }; +use super::request::address_book; + /// Map a [`OtherRequest`] to the function that will lead to a [`OtherResponse`]. pub(super) async fn map_request( state: CupratedRpcHandler, @@ -483,9 +486,12 @@ async fn get_peer_list( state: CupratedRpcHandler, request: GetPeerListRequest, ) -> Result { + let (white_list, gray_list) = address_book::peerlist::(&mut DummyAddressBook).await?; + Ok(GetPeerListResponse { base: helper::response_base(false), - ..todo!() + white_list, + gray_list, }) } diff --git a/binaries/cuprated/src/rpc/request/address_book.rs b/binaries/cuprated/src/rpc/request/address_book.rs index 7fbb470..77841df 100644 --- a/binaries/cuprated/src/rpc/request/address_book.rs +++ b/binaries/cuprated/src/rpc/request/address_book.rs @@ -1,11 +1,14 @@ //! Functions to send [`AddressBookRequest`]s. +use std::net::SocketAddrV4; + use anyhow::{anyhow, Error}; +use cuprate_types::rpc::Peer; use tower::ServiceExt; -use cuprate_helper::cast::usize_to_u64; +use cuprate_helper::{cast::usize_to_u64, map::u32_from_ipv4}; use cuprate_p2p_core::{ - services::{AddressBookRequest, AddressBookResponse}, + services::{AddressBookRequest, AddressBookResponse, ZoneSpecificPeerListEntryBase}, types::{BanState, ConnectionId}, AddressBook, NetworkZone, }; @@ -161,3 +164,62 @@ pub(crate) async fn get_bans( Ok(bans) } + +/// [`AddressBookRequest::Peerlist`] +pub(crate) async fn peerlist( + address_book: &mut impl AddressBook, +) -> Result<(Vec, Vec), Error> { + let AddressBookResponse::Peerlist(peerlist) = address_book + .ready() + .await + .map_err(|e| anyhow!(e))? + .call(AddressBookRequest::Peerlist) + .await + .map_err(|e| anyhow!(e))? + else { + unreachable!(); + }; + + fn map(peers: Vec>) -> Vec { + peers + .into_iter() + .map(|peer| { + let ZoneSpecificPeerListEntryBase { + adr, + id, + last_seen, + pruning_seed, + rpc_port, + rpc_credits_per_hash, + } = peer; + + let host = adr.to_string(); + + let (ip, port) = if let Ok(socket_addr) = host.parse::() { + (u32_from_ipv4(*socket_addr.ip()), socket_addr.port()) + } else { + (0, 0) + }; + + let last_seen = last_seen.try_into().unwrap_or(0); + let pruning_seed = pruning_seed.compress(); + + Peer { + id, + host, + ip, + port, + rpc_port, + rpc_credits_per_hash, + last_seen, + pruning_seed, + } + }) + .collect() + } + + let white = map::(peerlist.white); + let grey = map::(peerlist.grey); + + Ok((white, grey)) +} diff --git a/p2p/address-book/src/book.rs b/p2p/address-book/src/book.rs index 3e5269f..6f80214 100644 --- a/p2p/address-book/src/book.rs +++ b/p2p/address-book/src/book.rs @@ -420,7 +420,8 @@ impl Service> for AddressBook { AddressBookRequest::GetBan(addr) => Ok(AddressBookResponse::GetBan { unban_instant: self.peer_unban_instant(&addr).map(Instant::into_std), }), - AddressBookRequest::PeerlistSize + AddressBookRequest::Peerlist + | AddressBookRequest::PeerlistSize | AddressBookRequest::ConnectionCount | AddressBookRequest::SetBan(_) | AddressBookRequest::GetBans diff --git a/p2p/p2p-core/src/client/handshaker/builder/dummy.rs b/p2p/p2p-core/src/client/handshaker/builder/dummy.rs index 48b3daf..404f7a2 100644 --- a/p2p/p2p-core/src/client/handshaker/builder/dummy.rs +++ b/p2p/p2p-core/src/client/handshaker/builder/dummy.rs @@ -108,7 +108,8 @@ impl Service> for DummyAddressBook { AddressBookRequest::GetBan(_) => AddressBookResponse::GetBan { unban_instant: None, }, - AddressBookRequest::PeerlistSize + AddressBookRequest::Peerlist + | AddressBookRequest::PeerlistSize | AddressBookRequest::ConnectionCount | AddressBookRequest::SetBan(_) | AddressBookRequest::GetBans diff --git a/p2p/p2p-core/src/services.rs b/p2p/p2p-core/src/services.rs index 6d1089c..a9aee45 100644 --- a/p2p/p2p-core/src/services.rs +++ b/p2p/p2p-core/src/services.rs @@ -6,7 +6,7 @@ use cuprate_wire::{CoreSyncData, PeerListEntryBase}; use crate::{ client::InternalPeerID, handles::ConnectionHandle, - types::{BanState, ConnectionInfo, SetBan}, + types::{BanState, ConnectionInfo, Peerlist, SetBan}, NetZoneAddress, NetworkAddressIncorrectZone, NetworkZone, }; @@ -115,6 +115,9 @@ pub enum AddressBookRequest { /// Gets the specified number of white peers, or less if we don't have enough. GetWhitePeers(usize), + /// Get info on all peers, white & grey. + Peerlist, + /// Get the amount of white & grey peers. PeerlistSize, @@ -152,6 +155,9 @@ pub enum AddressBookResponse { /// Response to [`AddressBookRequest::GetWhitePeers`]. Peers(Vec>), + /// Response to [`AddressBookRequest::Peerlist`]. + Peerlist(Peerlist), + /// Response to [`AddressBookRequest::PeerlistSize`]. PeerlistSize { white: usize, grey: usize }, diff --git a/p2p/p2p-core/src/types.rs b/p2p/p2p-core/src/types.rs index ca56055..35cd883 100644 --- a/p2p/p2p-core/src/types.rs +++ b/p2p/p2p-core/src/types.rs @@ -5,7 +5,7 @@ use std::time::{Duration, Instant}; use cuprate_pruning::PruningSeed; use cuprate_types::{AddressType, ConnectionState}; -use crate::NetZoneAddress; +use crate::{NetZoneAddress, ZoneSpecificPeerListEntryBase}; /// Data within [`crate::services::AddressBookRequest::SetBan`]. pub struct SetBan { @@ -94,3 +94,10 @@ pub struct Span { pub speed: u32, pub start_block_height: u64, } + +/// Used in RPC's `/get_peer_list`. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct Peerlist { + pub white: Vec>, + pub grey: Vec>, +}