From b0d9471214450b8389890295f51480eec44b5dab Mon Sep 17 00:00:00 2001 From: teor Date: Mon, 15 May 2023 01:06:07 +1000 Subject: [PATCH] fix(log): Stop logging peer IP addresses, to protect user privacy (#6662) * Add a PeerSocketAddr type which hides its IP address, but shows the port * Manually replace SocketAddr with PeerSocketAddr where needed ```sh fastmod SocketAddr PeerSocketAddr zebra-network ``` * Add missing imports * Make converting into PeerSocketAddr easier * Fix some unused imports * Add a canonical_peer_addr() function * Fix connection handling for PeerSocketAddr * Fix serialization for PeerSocketAddr * Fix tests for PeerSocketAddr * Remove some unused imports * Fix address book listener handling * Remove redundant imports and conversions * Update outdated IPv4-mapped IPv6 address code * Make addresses canonical when deserializing * Stop logging peer addresses in RPC code * Update zebrad tests with new PeerSocketAddr type * Update zebra-rpc tests with new PeerSocketAddr type --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- zebra-network/src/address_book.rs | 35 ++++--- zebra-network/src/config.rs | 14 +-- zebra-network/src/isolated.rs | 12 ++- zebra-network/src/isolated/tests/vectors.rs | 4 +- zebra-network/src/lib.rs | 7 +- zebra-network/src/meta_addr.rs | 92 ++++++++++--------- zebra-network/src/meta_addr/arbitrary.rs | 25 +++-- zebra-network/src/meta_addr/peer_addr.rs | 66 +++++++++++++ zebra-network/src/meta_addr/tests/check.rs | 2 +- zebra-network/src/meta_addr/tests/prop.rs | 19 ++-- zebra-network/src/meta_addr/tests/vectors.rs | 36 ++++---- zebra-network/src/peer/client.rs | 11 +-- zebra-network/src/peer/connector.rs | 9 +- zebra-network/src/peer/handshake.rs | 63 ++++++------- zebra-network/src/peer/priority.rs | 18 ++-- zebra-network/src/peer_set/candidate_set.rs | 4 +- .../peer_set/candidate_set/tests/vectors.rs | 3 +- zebra-network/src/peer_set/initialize.rs | 45 +++++---- .../src/peer_set/initialize/tests/vectors.rs | 27 ++++-- .../src/peer_set/inventory_registry.rs | 27 +++--- .../peer_set/inventory_registry/tests/prop.rs | 5 +- .../inventory_registry/tests/vectors.rs | 6 +- zebra-network/src/peer_set/set.rs | 13 ++- zebra-network/src/peer_set/set/tests.rs | 8 +- zebra-network/src/peer_set/set/tests/prop.rs | 11 ++- zebra-network/src/protocol/external.rs | 2 +- zebra-network/src/protocol/external/addr.rs | 4 +- .../src/protocol/external/addr/canonical.rs | 35 ++++--- .../src/protocol/external/addr/in_version.rs | 33 +++---- .../src/protocol/external/addr/v1.rs | 56 ++++------- .../src/protocol/external/addr/v2.rs | 33 +++---- .../src/protocol/external/arbitrary.rs | 27 ++---- .../src/protocol/internal/response.rs | 2 +- zebra-network/tests/acceptance.rs | 6 +- .../types/peer_info.rs | 6 +- .../tests/snapshot/get_block_template_rpcs.rs | 12 ++- zebra-rpc/src/methods/tests/vectors.rs | 12 ++- .../components/inbound/tests/real_peer_set.rs | 21 +++-- 38 files changed, 447 insertions(+), 364 deletions(-) create mode 100644 zebra-network/src/meta_addr/peer_addr.rs diff --git a/zebra-network/src/address_book.rs b/zebra-network/src/address_book.rs index b5c9e973..703eadf8 100644 --- a/zebra-network/src/address_book.rs +++ b/zebra-network/src/address_book.rs @@ -17,9 +17,13 @@ use tracing::Span; use zebra_chain::parameters::Network; use crate::{ - constants, meta_addr::MetaAddrChange, protocol::external::canonical_socket_addr, - types::MetaAddr, AddressBookPeers, PeerAddrState, + constants, + meta_addr::MetaAddrChange, + protocol::external::{canonical_peer_addr, canonical_socket_addr}, + types::MetaAddr, + AddressBookPeers, PeerAddrState, PeerSocketAddr, }; + #[cfg(test)] mod tests; @@ -66,7 +70,7 @@ pub struct AddressBook { /// We reverse the comparison order, because the standard library /// ([`BTreeMap`](std::collections::BTreeMap)) sorts in ascending order, but /// [`OrderedMap`] sorts in descending order. - by_addr: OrderedMap>, + by_addr: OrderedMap>, /// The local listener address. local_listener: SocketAddr, @@ -182,7 +186,7 @@ impl AddressBook { let addrs = addrs .into_iter() .map(|mut meta_addr| { - meta_addr.addr = canonical_socket_addr(meta_addr.addr); + meta_addr.addr = canonical_peer_addr(meta_addr.addr); meta_addr }) .filter(|meta_addr| meta_addr.address_is_valid_for_outbound(network)) @@ -219,11 +223,16 @@ impl AddressBook { /// /// This address contains minimal state, but it is not sanitized. pub fn local_listener_meta_addr(&self) -> MetaAddr { - MetaAddr::new_local_listener_change(&self.local_listener) + MetaAddr::new_local_listener_change(self.local_listener) .into_new_meta_addr() .expect("unexpected invalid new local listener addr") } + /// Get the local listener [`SocketAddr`]. + pub fn local_listener_socket_addr(&self) -> SocketAddr { + self.local_listener + } + /// Get the contents of `self` in random order with sanitized timestamps. pub fn sanitized(&self, now: chrono::DateTime) -> Vec { use rand::seq::SliceRandom; @@ -257,8 +266,8 @@ impl AddressBook { /// Look up `addr` in the address book, and return its [`MetaAddr`]. /// /// Converts `addr` to a canonical address before looking it up. - pub fn get(&mut self, addr: &SocketAddr) -> Option { - let addr = canonical_socket_addr(*addr); + pub fn get(&mut self, addr: PeerSocketAddr) -> Option { + let addr = canonical_peer_addr(*addr); // Unfortunately, `OrderedMap` doesn't implement `get`. let meta_addr = self.by_addr.remove(&addr); @@ -278,7 +287,7 @@ impl AddressBook { /// All changes should go through `update`, so that the address book /// only contains valid outbound addresses. /// - /// Change addresses must be canonical `SocketAddr`s. This makes sure that + /// Change addresses must be canonical `PeerSocketAddr`s. This makes sure that /// each address book entry has a unique IP address. /// /// # Security @@ -287,11 +296,11 @@ impl AddressBook { /// to the address book. This prevents rapid reconnections to the same peer. /// /// As an exception, this function can ignore all changes for specific - /// [`SocketAddr`]s. Ignored addresses will never be used to connect to + /// [`PeerSocketAddr`]s. Ignored addresses will never be used to connect to /// peers. #[allow(clippy::unwrap_in_result)] pub fn update(&mut self, change: MetaAddrChange) -> Option { - let previous = self.get(&change.addr()); + let previous = self.get(change.addr()); let _guard = self.span.enter(); @@ -378,7 +387,7 @@ impl AddressBook { /// All address removals should go through `take`, so that the address /// book metrics are accurate. #[allow(dead_code)] - fn take(&mut self, removed_addr: SocketAddr) -> Option { + fn take(&mut self, removed_addr: PeerSocketAddr) -> Option { let _guard = self.span.enter(); let instant_now = Instant::now(); @@ -399,9 +408,9 @@ impl AddressBook { } } - /// Returns true if the given [`SocketAddr`] is pending a reconnection + /// Returns true if the given [`PeerSocketAddr`] is pending a reconnection /// attempt. - pub fn pending_reconnection_addr(&mut self, addr: &SocketAddr) -> bool { + pub fn pending_reconnection_addr(&mut self, addr: PeerSocketAddr) -> bool { let meta_addr = self.get(addr); let _guard = self.span.enter(); diff --git a/zebra-network/src/config.rs b/zebra-network/src/config.rs index 3d4ae503..14f46ec4 100644 --- a/zebra-network/src/config.rs +++ b/zebra-network/src/config.rs @@ -17,8 +17,8 @@ use crate::{ DEFAULT_CRAWL_NEW_PEER_INTERVAL, DNS_LOOKUP_TIMEOUT, INBOUND_PEER_LIMIT_MULTIPLIER, OUTBOUND_PEER_LIMIT_MULTIPLIER, }, - protocol::external::canonical_socket_addr, - BoxError, + protocol::external::{canonical_peer_addr, canonical_socket_addr}, + BoxError, PeerSocketAddr, }; #[cfg(test)] @@ -145,7 +145,7 @@ impl Config { } /// Resolve initial seed peer IP addresses, based on the configured network. - pub async fn initial_peers(&self) -> HashSet { + pub async fn initial_peers(&self) -> HashSet { Config::resolve_peers(&self.initial_peer_hostnames().iter().cloned().collect()).await } @@ -154,7 +154,7 @@ impl Config { /// /// If DNS resolution fails or times out for all peers, continues retrying /// until at least one peer is found. - async fn resolve_peers(peers: &HashSet) -> HashSet { + async fn resolve_peers(peers: &HashSet) -> HashSet { use futures::stream::StreamExt; if peers.is_empty() { @@ -196,7 +196,7 @@ impl Config { /// `max_retries` times. /// /// If DNS continues to fail, returns an empty list of addresses. - async fn resolve_host(host: &str, max_retries: usize) -> HashSet { + async fn resolve_host(host: &str, max_retries: usize) -> HashSet { for retries in 0..=max_retries { if let Ok(addresses) = Config::resolve_host_once(host).await { return addresses; @@ -225,13 +225,13 @@ impl Config { /// /// If `host` is a DNS name, performs DNS resolution with a timeout of a few seconds. /// If DNS resolution fails or times out, returns an error. - async fn resolve_host_once(host: &str) -> Result, BoxError> { + async fn resolve_host_once(host: &str) -> Result, BoxError> { let fut = tokio::net::lookup_host(host); let fut = tokio::time::timeout(DNS_LOOKUP_TIMEOUT, fut); match fut.await { Ok(Ok(ip_addrs)) => { - let ip_addrs: Vec = ip_addrs.map(canonical_socket_addr).collect(); + let ip_addrs: Vec = ip_addrs.map(canonical_peer_addr).collect(); // if we're logging at debug level, // the full list of IP addresses will be shown in the log message diff --git a/zebra-network/src/isolated.rs b/zebra-network/src/isolated.rs index 65991e69..403b5102 100644 --- a/zebra-network/src/isolated.rs +++ b/zebra-network/src/isolated.rs @@ -1,6 +1,6 @@ //! Creating isolated connections to specific peers. -use std::{future::Future, net::SocketAddr}; +use std::future::Future; use futures::future::TryFutureExt; use tokio::io::{AsyncRead, AsyncWrite}; @@ -11,7 +11,7 @@ use zebra_chain::{chain_tip::NoChainTip, parameters::Network}; use crate::{ peer::{self, Client, ConnectedAddr, HandshakeRequest}, peer_set::ActiveConnectionCounter, - BoxError, Config, Request, Response, + BoxError, Config, PeerSocketAddr, Request, Response, }; // Wait until `arti-client`'s dependency `x25519-dalek v1.2.0` is updated to a higher version. (#5492) @@ -126,7 +126,7 @@ where /// Prefer `connect_isolated_tor` if available. pub fn connect_isolated_tcp_direct( network: Network, - addr: SocketAddr, + addr: impl Into, user_agent: String, ) -> impl Future> { let nil_inbound_service = @@ -146,7 +146,7 @@ pub fn connect_isolated_tcp_direct( /// which makes it stand out from other isolated connections from other peers. pub fn connect_isolated_tcp_direct_with_inbound( network: Network, - addr: SocketAddr, + addr: impl Into, user_agent: String, inbound_service: InboundService, ) -> impl Future> @@ -155,7 +155,9 @@ where Service + Clone + Send + 'static, InboundService::Future: Send, { - tokio::net::TcpStream::connect(addr) + let addr = addr.into(); + + tokio::net::TcpStream::connect(*addr) .err_into() .and_then(move |tcp_stream| { connect_isolated_with_inbound(network, tcp_stream, user_agent, inbound_service) diff --git a/zebra-network/src/isolated/tests/vectors.rs b/zebra-network/src/isolated/tests/vectors.rs index d6e0f815..aa13b65e 100644 --- a/zebra-network/src/isolated/tests/vectors.rs +++ b/zebra-network/src/isolated/tests/vectors.rs @@ -1,6 +1,6 @@ //! Fixed test vectors for isolated Zebra connections. -use std::{net::SocketAddr, task::Poll, time::Duration}; +use std::{task::Poll, time::Duration}; use futures::stream::StreamExt; use tokio_util::codec::Framed; @@ -151,7 +151,7 @@ async fn check_version_message( // // SECURITY TODO: check if the timestamp field can be zeroed, to remove another distinguisher (#3300) - let mut fixed_isolated_addr: SocketAddr = "0.0.0.0:0".parse().unwrap(); + let mut fixed_isolated_addr: PeerSocketAddr = "0.0.0.0:0".parse().unwrap(); fixed_isolated_addr.set_port(network.default_port()); // Required fields should be accurate and match most other peers. diff --git a/zebra-network/src/lib.rs b/zebra-network/src/lib.rs index 5e5f884f..13901f03 100644 --- a/zebra-network/src/lib.rs +++ b/zebra-network/src/lib.rs @@ -166,8 +166,9 @@ pub use crate::isolated::tor::connect_isolated_tor; pub use crate::isolated::tor::connect_isolated_tor_with_inbound; #[cfg(any(test, feature = "proptest-impl"))] -pub use crate::isolated::{ - connect_isolated_tcp_direct_with_inbound, connect_isolated_with_inbound, +pub use crate::{ + isolated::{connect_isolated_tcp_direct_with_inbound, connect_isolated_with_inbound}, + protocol::external::canonical_peer_addr, }; pub use crate::{ @@ -175,7 +176,7 @@ pub use crate::{ address_book_peers::AddressBookPeers, config::Config, isolated::{connect_isolated, connect_isolated_tcp_direct}, - meta_addr::PeerAddrState, + meta_addr::{PeerAddrState, PeerSocketAddr}, peer::{Client, ConnectedAddr, ConnectionInfo, HandshakeError, PeerError, SharedPeerError}, peer_set::init, policies::RetryLimit, diff --git a/zebra-network/src/meta_addr.rs b/zebra-network/src/meta_addr.rs index 6b0b1f46..3d9657fc 100644 --- a/zebra-network/src/meta_addr.rs +++ b/zebra-network/src/meta_addr.rs @@ -2,7 +2,6 @@ use std::{ cmp::{Ord, Ordering}, - net::SocketAddr, time::Instant, }; @@ -12,18 +11,22 @@ use zebra_chain::{parameters::Network, serialization::DateTime32}; use crate::{ constants, - peer::PeerPreference, - protocol::{external::canonical_socket_addr, types::PeerServices}, + peer::{address_is_valid_for_outbound_connections, PeerPreference}, + protocol::{external::canonical_peer_addr, types::PeerServices}, }; use MetaAddrChange::*; use PeerAddrState::*; +pub mod peer_addr; + +pub use peer_addr::PeerSocketAddr; + #[cfg(any(test, feature = "proptest-impl"))] use proptest_derive::Arbitrary; #[cfg(any(test, feature = "proptest-impl"))] -use crate::protocol::external::arbitrary::canonical_socket_addr_strategy; +use crate::protocol::external::arbitrary::canonical_peer_addr_strategy; #[cfg(any(test, feature = "proptest-impl"))] pub(crate) mod arbitrary; @@ -134,12 +137,12 @@ pub struct MetaAddr { /// The peer's canonical socket address. #[cfg_attr( any(test, feature = "proptest-impl"), - proptest(strategy = "canonical_socket_addr_strategy()") + proptest(strategy = "canonical_peer_addr_strategy()") )] // // TODO: make addr private, so the constructors can make sure it is a // canonical SocketAddr (#2357) - pub(crate) addr: SocketAddr, + pub(crate) addr: PeerSocketAddr, /// The services advertised by the peer. /// @@ -196,18 +199,18 @@ pub enum MetaAddrChange { NewInitial { #[cfg_attr( any(test, feature = "proptest-impl"), - proptest(strategy = "canonical_socket_addr_strategy()") + proptest(strategy = "canonical_peer_addr_strategy()") )] - addr: SocketAddr, + addr: PeerSocketAddr, }, /// Creates a new gossiped `MetaAddr`. NewGossiped { #[cfg_attr( any(test, feature = "proptest-impl"), - proptest(strategy = "canonical_socket_addr_strategy()") + proptest(strategy = "canonical_peer_addr_strategy()") )] - addr: SocketAddr, + addr: PeerSocketAddr, untrusted_services: PeerServices, untrusted_last_seen: DateTime32, }, @@ -218,9 +221,9 @@ pub enum MetaAddrChange { NewAlternate { #[cfg_attr( any(test, feature = "proptest-impl"), - proptest(strategy = "canonical_socket_addr_strategy()") + proptest(strategy = "canonical_peer_addr_strategy()") )] - addr: SocketAddr, + addr: PeerSocketAddr, untrusted_services: PeerServices, }, @@ -228,9 +231,9 @@ pub enum MetaAddrChange { NewLocal { #[cfg_attr( any(test, feature = "proptest-impl"), - proptest(strategy = "canonical_socket_addr_strategy()") + proptest(strategy = "canonical_peer_addr_strategy()") )] - addr: SocketAddr, + addr: PeerSocketAddr, }, /// Updates an existing `MetaAddr` when an outbound connection attempt @@ -238,18 +241,18 @@ pub enum MetaAddrChange { UpdateAttempt { #[cfg_attr( any(test, feature = "proptest-impl"), - proptest(strategy = "canonical_socket_addr_strategy()") + proptest(strategy = "canonical_peer_addr_strategy()") )] - addr: SocketAddr, + addr: PeerSocketAddr, }, /// Updates an existing `MetaAddr` when a peer responds with a message. UpdateResponded { #[cfg_attr( any(test, feature = "proptest-impl"), - proptest(strategy = "canonical_socket_addr_strategy()") + proptest(strategy = "canonical_peer_addr_strategy()") )] - addr: SocketAddr, + addr: PeerSocketAddr, services: PeerServices, }, @@ -257,9 +260,9 @@ pub enum MetaAddrChange { UpdateFailed { #[cfg_attr( any(test, feature = "proptest-impl"), - proptest(strategy = "canonical_socket_addr_strategy()") + proptest(strategy = "canonical_peer_addr_strategy()") )] - addr: SocketAddr, + addr: PeerSocketAddr, services: Option, }, } @@ -267,21 +270,21 @@ pub enum MetaAddrChange { impl MetaAddr { /// Returns a [`MetaAddrChange::NewInitial`] for a peer that was excluded from /// the list of the initial peers. - pub fn new_initial_peer(addr: SocketAddr) -> MetaAddrChange { + pub fn new_initial_peer(addr: PeerSocketAddr) -> MetaAddrChange { NewInitial { - addr: canonical_socket_addr(addr), + addr: canonical_peer_addr(addr), } } /// Returns a new `MetaAddr`, based on the deserialized fields from a /// gossiped peer [`Addr`][crate::protocol::external::Message::Addr] message. pub fn new_gossiped_meta_addr( - addr: SocketAddr, + addr: PeerSocketAddr, untrusted_services: PeerServices, untrusted_last_seen: DateTime32, ) -> MetaAddr { MetaAddr { - addr: canonical_socket_addr(addr), + addr: canonical_peer_addr(addr), services: Some(untrusted_services), untrusted_last_seen: Some(untrusted_last_seen), last_response: None, @@ -300,7 +303,7 @@ impl MetaAddr { let untrusted_services = self.services?; Some(NewGossiped { - addr: canonical_socket_addr(self.addr), + addr: canonical_peer_addr(self.addr), untrusted_services, untrusted_last_seen: self .untrusted_last_seen @@ -320,52 +323,55 @@ impl MetaAddr { /// - malicious peers could interfere with other peers' [`AddressBook`](crate::AddressBook) state, /// or /// - Zebra could advertise unreachable addresses to its own peers. - pub fn new_responded(addr: &SocketAddr, services: &PeerServices) -> MetaAddrChange { + pub fn new_responded(addr: PeerSocketAddr, services: &PeerServices) -> MetaAddrChange { UpdateResponded { - addr: canonical_socket_addr(*addr), + addr: canonical_peer_addr(*addr), services: *services, } } /// Returns a [`MetaAddrChange::UpdateAttempt`] for a peer that we /// want to make an outbound connection to. - pub fn new_reconnect(addr: &SocketAddr) -> MetaAddrChange { + pub fn new_reconnect(addr: PeerSocketAddr) -> MetaAddrChange { UpdateAttempt { - addr: canonical_socket_addr(*addr), + addr: canonical_peer_addr(*addr), } } /// Returns a [`MetaAddrChange::NewAlternate`] for a peer's alternate address, /// received via a `Version` message. - pub fn new_alternate(addr: &SocketAddr, untrusted_services: &PeerServices) -> MetaAddrChange { + pub fn new_alternate( + addr: PeerSocketAddr, + untrusted_services: &PeerServices, + ) -> MetaAddrChange { NewAlternate { - addr: canonical_socket_addr(*addr), + addr: canonical_peer_addr(*addr), untrusted_services: *untrusted_services, } } /// Returns a [`MetaAddrChange::NewLocal`] for our own listener address. - pub fn new_local_listener_change(addr: &SocketAddr) -> MetaAddrChange { + pub fn new_local_listener_change(addr: impl Into) -> MetaAddrChange { NewLocal { - addr: canonical_socket_addr(*addr), + addr: canonical_peer_addr(addr), } } /// Returns a [`MetaAddrChange::UpdateFailed`] for a peer that has just had /// an error. pub fn new_errored( - addr: &SocketAddr, + addr: PeerSocketAddr, services: impl Into>, ) -> MetaAddrChange { UpdateFailed { - addr: canonical_socket_addr(*addr), + addr: canonical_peer_addr(*addr), services: services.into(), } } /// Create a new `MetaAddr` for a peer that has just shut down. pub fn new_shutdown( - addr: &SocketAddr, + addr: PeerSocketAddr, services: impl Into>, ) -> MetaAddrChange { // TODO: if the peer shut down in the Responded state, preserve that @@ -374,13 +380,13 @@ impl MetaAddr { } /// Return the address for this `MetaAddr`. - pub fn addr(&self) -> SocketAddr { + pub fn addr(&self) -> PeerSocketAddr { self.addr } /// Return the address preference level for this `MetaAddr`. pub fn peer_preference(&self) -> Result { - PeerPreference::new(&self.addr, None) + PeerPreference::new(self.addr, None) } /// Returns the time of the last successful interaction with this peer. @@ -535,13 +541,13 @@ impl MetaAddr { && self.is_probably_reachable(chrono_now) } - /// Is the [`SocketAddr`] we have for this peer valid for outbound + /// Is the [`PeerSocketAddr`] we have for this peer valid for outbound /// connections? /// /// Since the addresses in the address book are unique, this check can be /// used to permanently reject entire [`MetaAddr`]s. pub fn address_is_valid_for_outbound(&self, network: Network) -> bool { - PeerPreference::new(&self.addr, network).is_ok() + address_is_valid_for_outbound_connections(self.addr, network).is_ok() } /// Is the last known information for this peer valid for outbound @@ -611,7 +617,7 @@ impl MetaAddr { .expect("unexpected underflow: rem_euclid is strictly less than timestamp"); Some(MetaAddr { - addr: canonical_socket_addr(self.addr), + addr: canonical_peer_addr(self.addr), // initial peers are sanitized assuming they are `NODE_NETWORK` // TODO: split untrusted and direct services // consider sanitizing untrusted services to NODE_NETWORK (#2324) @@ -640,7 +646,7 @@ impl MetaAddr { impl MetaAddrChange { /// Return the address for this change. - pub fn addr(&self) -> SocketAddr { + pub fn addr(&self) -> PeerSocketAddr { match self { NewInitial { addr } | NewGossiped { addr, .. } @@ -656,7 +662,7 @@ impl MetaAddrChange { /// Set the address for this change to `new_addr`. /// /// This method should only be used in tests. - pub fn set_addr(&mut self, new_addr: SocketAddr) { + pub fn set_addr(&mut self, new_addr: PeerSocketAddr) { match self { NewInitial { addr } | NewGossiped { addr, .. } diff --git a/zebra-network/src/meta_addr/arbitrary.rs b/zebra-network/src/meta_addr/arbitrary.rs index 91235530..955607e7 100644 --- a/zebra-network/src/meta_addr/arbitrary.rs +++ b/zebra-network/src/meta_addr/arbitrary.rs @@ -1,14 +1,12 @@ //! Randomised test data generation for MetaAddr. -use std::net::SocketAddr; - use proptest::{arbitrary::any, collection::vec, prelude::*}; use zebra_chain::{parameters::Network::*, serialization::DateTime32}; -use crate::protocol::external::arbitrary::canonical_socket_addr_strategy; +use crate::protocol::external::arbitrary::canonical_peer_addr_strategy; -use super::{MetaAddr, MetaAddrChange, PeerServices}; +use super::{MetaAddr, MetaAddrChange, PeerServices, PeerSocketAddr}; /// The largest number of random changes we want to apply to a [`MetaAddr`]. /// @@ -36,7 +34,7 @@ impl MetaAddr { /// [1]: super::PeerAddrState::NeverAttemptedGossiped pub fn gossiped_strategy() -> BoxedStrategy { ( - canonical_socket_addr_strategy(), + canonical_peer_addr_strategy(), any::(), any::(), ) @@ -51,9 +49,9 @@ impl MetaAddr { /// /// [1]: super::PeerAddrState::NeverAttemptedAlternate pub fn alternate_strategy() -> BoxedStrategy { - (canonical_socket_addr_strategy(), any::()) + (canonical_peer_addr_strategy(), any::()) .prop_map(|(socket_addr, untrusted_services)| { - MetaAddr::new_alternate(&socket_addr, &untrusted_services) + MetaAddr::new_alternate(socket_addr, &untrusted_services) .into_new_meta_addr() .expect("unexpected invalid alternate change") }) @@ -62,11 +60,10 @@ impl MetaAddr { } impl MetaAddrChange { - /// Returns a strategy which generates changes for `socket_addr`. + /// Returns a strategy which generates changes for `addr`. /// - /// `socket_addr` is typically generated by the `canonical_socket_addr` - /// strategy. - pub fn addr_strategy(addr: SocketAddr) -> BoxedStrategy { + /// `addr` is typically generated by the `canonical_peer_addr` strategy. + pub fn addr_strategy(addr: PeerSocketAddr) -> BoxedStrategy { any::() .prop_map(move |mut change| { change.set_addr(addr); @@ -78,7 +75,7 @@ impl MetaAddrChange { /// Returns a strategy which generates a `MetaAddr`, and a vector of up to /// `max_addr_change` changes. /// - /// The address and the changes all have matching `SocketAddr`s. + /// The address and the changes all have matching `PeerSocketAddr`s. pub fn addr_changes_strategy( max_addr_change: usize, ) -> BoxedStrategy<(MetaAddr, Vec)> { @@ -101,12 +98,12 @@ impl MetaAddrChange { /// /// [1]: super::NewAlternate pub fn ready_outbound_strategy() -> BoxedStrategy { - canonical_socket_addr_strategy() + canonical_peer_addr_strategy() .prop_filter_map("failed MetaAddr::is_valid_for_outbound", |addr| { // Alternate nodes use the current time, so they're always ready // // TODO: create a "Zebra supported services" constant - let change = MetaAddr::new_alternate(&addr, &PeerServices::NODE_NETWORK); + let change = MetaAddr::new_alternate(addr, &PeerServices::NODE_NETWORK); if change .into_new_meta_addr() .expect("unexpected invalid alternate change") diff --git a/zebra-network/src/meta_addr/peer_addr.rs b/zebra-network/src/meta_addr/peer_addr.rs new file mode 100644 index 00000000..09876a08 --- /dev/null +++ b/zebra-network/src/meta_addr/peer_addr.rs @@ -0,0 +1,66 @@ +//! Wrappers for peer addresses which hide sensitive user and node operator details in logs and +//! metrics. + +use std::{ + fmt, + net::SocketAddr, + ops::{Deref, DerefMut}, + str::FromStr, +}; + +#[cfg(any(test, feature = "proptest-impl"))] +use proptest_derive::Arbitrary; + +/// A thin wrapper for [`SocketAddr`] which hides peer IP addresses in logs and metrics. +#[derive( + Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize, +)] +#[serde(transparent)] +#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))] +pub struct PeerSocketAddr(SocketAddr); + +impl fmt::Debug for PeerSocketAddr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl fmt::Display for PeerSocketAddr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let ip_version = if self.is_ipv4() { "v4" } else { "v6" }; + + // The port is usually not sensitive, and it's useful for debugging. + f.pad(&format!("{}redacted:{}", ip_version, self.port())) + } +} + +impl FromStr for PeerSocketAddr { + type Err = ::Err; + + fn from_str(s: &str) -> Result { + Ok(Self(s.parse()?)) + } +} + +impl From for PeerSocketAddr +where + S: Into, +{ + fn from(value: S) -> Self { + Self(value.into()) + } +} + +impl Deref for PeerSocketAddr { + type Target = SocketAddr; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for PeerSocketAddr { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} diff --git a/zebra-network/src/meta_addr/tests/check.rs b/zebra-network/src/meta_addr/tests/check.rs index 5a65ab0c..234a2352 100644 --- a/zebra-network/src/meta_addr/tests/check.rs +++ b/zebra-network/src/meta_addr/tests/check.rs @@ -75,7 +75,7 @@ pub(crate) fn sanitize_avoids_leaks(original: &MetaAddr, sanitized: &MetaAddr) { assert_eq!(sanitized.services, Some(sanitized_peer_services)); // Remove IPv6 scope ID and flow information - let sanitized_socket_addr = SocketAddr::new(original.addr.ip(), original.addr.port()); + let sanitized_socket_addr = SocketAddr::new(original.addr.ip(), original.addr.port()).into(); assert_eq!(sanitized.addr.ip(), original.addr.ip()); assert_eq!(sanitized.addr.port(), original.addr.port()); assert_eq!(sanitized.addr, sanitized_socket_addr); diff --git a/zebra-network/src/meta_addr/tests/prop.rs b/zebra-network/src/meta_addr/tests/prop.rs index f737aef4..0b5f968a 100644 --- a/zebra-network/src/meta_addr/tests/prop.rs +++ b/zebra-network/src/meta_addr/tests/prop.rs @@ -1,9 +1,6 @@ //! Randomised property tests for MetaAddr and MetaAddrChange. -use std::{ - collections::HashMap, convert::TryFrom, env, net::SocketAddr, str::FromStr, sync::Arc, - time::Duration, -}; +use std::{collections::HashMap, env, net::SocketAddr, str::FromStr, sync::Arc, time::Duration}; use chrono::Utc; use proptest::{collection::vec, prelude::*}; @@ -21,8 +18,8 @@ use crate::{ PeerAddrState::*, }, peer_set::candidate_set::CandidateSet, - protocol::{external::canonical_socket_addr, types::PeerServices}, - AddressBook, + protocol::{external::canonical_peer_addr, types::PeerServices}, + AddressBook, PeerSocketAddr, }; use super::check; @@ -120,7 +117,7 @@ proptest! { prop_assert!(attempt_count <= 1); // Simulate an attempt - addr = MetaAddr::new_reconnect(&addr.addr) + addr = MetaAddr::new_reconnect(addr.addr) .apply_to_meta_addr(addr) .expect("unexpected invalid attempt"); } @@ -159,7 +156,7 @@ proptest! { let sanitized_addrs = address_book.sanitized(chrono_now); let expected_local_listener = address_book.local_listener_meta_addr(); - let canonical_local_listener = canonical_socket_addr(local_listener); + let canonical_local_listener = canonical_peer_addr(local_listener); let book_sanitized_local_listener = sanitized_addrs .iter() .find(|meta_addr| meta_addr.addr == canonical_local_listener); @@ -415,10 +412,10 @@ proptest! { tokio::time::pause(); // The current attempt counts for each peer in this interval - let mut attempt_counts: HashMap = HashMap::new(); + let mut attempt_counts: HashMap = HashMap::new(); // The most recent address info for each peer - let mut addrs: HashMap = HashMap::new(); + let mut addrs: HashMap = HashMap::new(); for change_index in 0..MAX_ADDR_CHANGE { for (addr, changes) in addr_changes_lists.iter() { @@ -432,7 +429,7 @@ proptest! { ); // Simulate an attempt - *addr = MetaAddr::new_reconnect(&addr.addr) + *addr = MetaAddr::new_reconnect(addr.addr) .apply_to_meta_addr(*addr) .expect("unexpected invalid attempt"); } diff --git a/zebra-network/src/meta_addr/tests/vectors.rs b/zebra-network/src/meta_addr/tests/vectors.rs index 19b21276..187f7077 100644 --- a/zebra-network/src/meta_addr/tests/vectors.rs +++ b/zebra-network/src/meta_addr/tests/vectors.rs @@ -1,7 +1,5 @@ //! Fixed test cases for MetaAddr and MetaAddrChange. -use std::net::SocketAddr; - use chrono::Utc; use zebra_chain::{ @@ -9,7 +7,7 @@ use zebra_chain::{ serialization::{DateTime32, Duration32}, }; -use crate::{constants::MAX_PEER_ACTIVE_FOR_GOSSIP, protocol::types::PeerServices}; +use crate::{constants::MAX_PEER_ACTIVE_FOR_GOSSIP, protocol::types::PeerServices, PeerSocketAddr}; use super::{super::MetaAddr, check}; @@ -61,8 +59,8 @@ fn new_local_listener_is_gossipable() { let chrono_now = Utc::now(); - let address = SocketAddr::from(([192, 168, 180, 9], 10_000)); - let peer = MetaAddr::new_local_listener_change(&address) + let address = PeerSocketAddr::from(([192, 168, 180, 9], 10_000)); + let peer = MetaAddr::new_local_listener_change(address) .into_new_meta_addr() .expect("MetaAddrChange can't create a new MetaAddr"); @@ -79,8 +77,8 @@ fn new_alternate_peer_address_is_not_gossipable() { let chrono_now = Utc::now(); - let address = SocketAddr::from(([192, 168, 180, 9], 10_000)); - let peer = MetaAddr::new_alternate(&address, &PeerServices::NODE_NETWORK) + let address = PeerSocketAddr::from(([192, 168, 180, 9], 10_000)); + let peer = MetaAddr::new_alternate(address, &PeerServices::NODE_NETWORK) .into_new_meta_addr() .expect("MetaAddrChange can't create a new MetaAddr"); @@ -94,7 +92,7 @@ fn gossiped_peer_reportedly_to_be_seen_recently_is_gossipable() { let chrono_now = Utc::now(); - let address = SocketAddr::from(([192, 168, 180, 9], 10_000)); + let address = PeerSocketAddr::from(([192, 168, 180, 9], 10_000)); // Report last seen within the reachable interval. let offset = MAX_PEER_ACTIVE_FOR_GOSSIP @@ -116,7 +114,7 @@ fn gossiped_peer_reportedly_seen_in_the_future_is_gossipable() { let chrono_now = Utc::now(); - let address = SocketAddr::from(([192, 168, 180, 9], 10_000)); + let address = PeerSocketAddr::from(([192, 168, 180, 9], 10_000)); // Report last seen in the future let last_seen = DateTime32::now() @@ -135,7 +133,7 @@ fn gossiped_peer_reportedly_seen_long_ago_is_not_gossipable() { let chrono_now = Utc::now(); - let address = SocketAddr::from(([192, 168, 180, 9], 10_000)); + let address = PeerSocketAddr::from(([192, 168, 180, 9], 10_000)); // Report last seen just outside the reachable interval. let offset = MAX_PEER_ACTIVE_FOR_GOSSIP @@ -157,13 +155,13 @@ fn recently_responded_peer_is_gossipable() { let chrono_now = Utc::now(); - let address = SocketAddr::from(([192, 168, 180, 9], 10_000)); - let peer_seed = MetaAddr::new_alternate(&address, &PeerServices::NODE_NETWORK) + let address = PeerSocketAddr::from(([192, 168, 180, 9], 10_000)); + let peer_seed = MetaAddr::new_alternate(address, &PeerServices::NODE_NETWORK) .into_new_meta_addr() .expect("MetaAddrChange can't create a new MetaAddr"); // Create a peer that has responded - let peer = MetaAddr::new_responded(&address, &PeerServices::NODE_NETWORK) + let peer = MetaAddr::new_responded(address, &PeerServices::NODE_NETWORK) .apply_to_meta_addr(peer_seed) .expect("Failed to create MetaAddr for responded peer"); @@ -177,13 +175,13 @@ fn not_so_recently_responded_peer_is_still_gossipable() { let chrono_now = Utc::now(); - let address = SocketAddr::from(([192, 168, 180, 9], 10_000)); - let peer_seed = MetaAddr::new_alternate(&address, &PeerServices::NODE_NETWORK) + let address = PeerSocketAddr::from(([192, 168, 180, 9], 10_000)); + let peer_seed = MetaAddr::new_alternate(address, &PeerServices::NODE_NETWORK) .into_new_meta_addr() .expect("MetaAddrChange can't create a new MetaAddr"); // Create a peer that has responded - let mut peer = MetaAddr::new_responded(&address, &PeerServices::NODE_NETWORK) + let mut peer = MetaAddr::new_responded(address, &PeerServices::NODE_NETWORK) .apply_to_meta_addr(peer_seed) .expect("Failed to create MetaAddr for responded peer"); @@ -207,13 +205,13 @@ fn responded_long_ago_peer_is_not_gossipable() { let chrono_now = Utc::now(); - let address = SocketAddr::from(([192, 168, 180, 9], 10_000)); - let peer_seed = MetaAddr::new_alternate(&address, &PeerServices::NODE_NETWORK) + let address = PeerSocketAddr::from(([192, 168, 180, 9], 10_000)); + let peer_seed = MetaAddr::new_alternate(address, &PeerServices::NODE_NETWORK) .into_new_meta_addr() .expect("MetaAddrChange can't create a new MetaAddr"); // Create a peer that has responded - let mut peer = MetaAddr::new_responded(&address, &PeerServices::NODE_NETWORK) + let mut peer = MetaAddr::new_responded(address, &PeerServices::NODE_NETWORK) .apply_to_meta_addr(peer_seed) .expect("Failed to create MetaAddr for responded peer"); diff --git a/zebra-network/src/peer/client.rs b/zebra-network/src/peer/client.rs index 3b6e0fcd..f264cc5f 100644 --- a/zebra-network/src/peer/client.rs +++ b/zebra-network/src/peer/client.rs @@ -4,7 +4,6 @@ use std::{ collections::HashSet, future::Future, iter, - net::SocketAddr, pin::Pin, sync::Arc, task::{Context, Poll}, @@ -29,7 +28,7 @@ use crate::{ external::InventoryHash, internal::{Request, Response}, }, - BoxError, + BoxError, PeerSocketAddr, }; #[cfg(any(test, feature = "proptest-impl"))] @@ -87,7 +86,7 @@ pub(crate) struct ClientRequest { /// The peer address for registering missing inventory. /// /// TODO: replace this with `ConnectedAddr`? - pub transient_addr: Option, + pub transient_addr: Option, /// The tracing context for the request, so that work the connection task does /// processing messages in the context of this request will have correct context. @@ -166,7 +165,7 @@ pub(super) struct MissingInventoryCollector { collector: broadcast::Sender, /// The peer address for registering missing inventory. - transient_addr: SocketAddr, + transient_addr: PeerSocketAddr, } impl std::fmt::Debug for Client { @@ -263,7 +262,7 @@ impl MustUseClientResponseSender { tx: oneshot::Sender>, request: &Request, inv_collector: Option>, - transient_addr: Option, + transient_addr: Option, ) -> Self { Self { tx: Some(tx), @@ -341,7 +340,7 @@ impl MissingInventoryCollector { pub fn new( request: &Request, inv_collector: Option>, - transient_addr: Option, + transient_addr: Option, ) -> Option> { if !request.is_inventory_download() { return None; diff --git a/zebra-network/src/peer/connector.rs b/zebra-network/src/peer/connector.rs index 7c774d25..dd2342c7 100644 --- a/zebra-network/src/peer/connector.rs +++ b/zebra-network/src/peer/connector.rs @@ -2,7 +2,6 @@ use std::{ future::Future, - net::SocketAddr, pin::Pin, task::{Context, Poll}, }; @@ -17,7 +16,7 @@ use zebra_chain::chain_tip::{ChainTip, NoChainTip}; use crate::{ peer::{Client, ConnectedAddr, Handshake, HandshakeRequest}, peer_set::ConnectionTracker, - BoxError, Request, Response, + BoxError, PeerSocketAddr, Request, Response, }; /// A wrapper around [`Handshake`] that opens a TCP connection before @@ -60,7 +59,7 @@ where /// Contains the information needed to make an outbound connection to the peer. pub struct OutboundConnectorRequest { /// The Zcash listener address of the peer. - pub addr: SocketAddr, + pub addr: PeerSocketAddr, /// A connection tracker that reduces the open connection count when dropped. /// @@ -74,7 +73,7 @@ where S::Future: Send, C: ChainTip + Clone + Send + 'static, { - type Response = (SocketAddr, Client); + type Response = (PeerSocketAddr, Client); type Error = BoxError; type Future = Pin> + Send + 'static>>; @@ -94,7 +93,7 @@ where let connector_span = info_span!("connector", peer = ?connected_addr); async move { - let tcp_stream = TcpStream::connect(addr).await?; + let tcp_stream = TcpStream::connect(*addr).await?; let client = hs .oneshot(HandshakeRequest:: { data_stream: tcp_stream, diff --git a/zebra-network/src/peer/handshake.rs b/zebra-network/src/peer/handshake.rs index 9dd338ae..40c07493 100644 --- a/zebra-network/src/peer/handshake.rs +++ b/zebra-network/src/peer/handshake.rs @@ -4,7 +4,7 @@ use std::{ cmp::min, fmt, future::Future, - net::{IpAddr, Ipv4Addr, SocketAddr}, + net::{Ipv4Addr, SocketAddr}, panic, pin::Pin, sync::Arc, @@ -45,7 +45,7 @@ use crate::{ internal::{Request, Response}, }, types::MetaAddr, - BoxError, Config, VersionMessage, + BoxError, Config, PeerSocketAddr, VersionMessage, }; #[cfg(test)] @@ -152,7 +152,7 @@ pub enum ConnectedAddr { /// and port. OutboundDirect { /// The connected outbound remote address and port. - addr: SocketAddr, + addr: PeerSocketAddr, }, /// The address we received from the OS, when a remote peer directly @@ -162,11 +162,10 @@ pub enum ConnectedAddr { /// if its outbound address is the same as its listener address. But the port /// is an ephemeral outbound TCP port, not a listener port. InboundDirect { - /// The connected inbound remote address. - maybe_ip: IpAddr, - - /// The connected inbound transient remote port. - transient_port: u16, + /// The connected inbound remote address and ephemeral port. + /// + /// The IP address might be the address of a Zcash peer, but the port is an ephemeral port. + addr: PeerSocketAddr, }, /// The proxy address we used to make an outbound connection. @@ -207,16 +206,13 @@ use ConnectedAddr::*; impl ConnectedAddr { /// Returns a new outbound directly connected addr. - pub fn new_outbound_direct(addr: SocketAddr) -> ConnectedAddr { + pub fn new_outbound_direct(addr: PeerSocketAddr) -> ConnectedAddr { OutboundDirect { addr } } /// Returns a new inbound directly connected addr. - pub fn new_inbound_direct(addr: SocketAddr) -> ConnectedAddr { - InboundDirect { - maybe_ip: addr.ip(), - transient_port: addr.port(), - } + pub fn new_inbound_direct(addr: PeerSocketAddr) -> ConnectedAddr { + InboundDirect { addr } } /// Returns a new outbound connected addr via `proxy`. @@ -246,7 +242,7 @@ impl ConnectedAddr { Isolated } - /// Returns a `SocketAddr` that can be used to track this connection in the + /// Returns a `PeerSocketAddr` that can be used to track this connection in the /// `AddressBook`. /// /// `None` for inbound connections, proxy connections, and isolated @@ -264,7 +260,7 @@ impl ConnectedAddr { /// `AddressBook` state. /// /// TODO: remove the `get_` from these methods (Rust style avoids `get` prefixes) - pub fn get_address_book_addr(&self) -> Option { + pub fn get_address_book_addr(&self) -> Option { match self { OutboundDirect { addr } => Some(*addr), // TODO: consider using the canonical address of the peer to track @@ -273,7 +269,7 @@ impl ConnectedAddr { } } - /// Returns a `SocketAddr` that can be used to temporarily identify a + /// Returns a `PeerSocketAddr` that can be used to temporarily identify a /// connection. /// /// Isolated connections must not change Zebra's peer set or address book @@ -290,18 +286,15 @@ impl ConnectedAddr { /// This address must not depend on the canonical address from the `Version` /// message. Otherwise, malicious peers could interfere with other peers' /// `PeerSet` state. - pub fn get_transient_addr(&self) -> Option { + pub fn get_transient_addr(&self) -> Option { match self { OutboundDirect { addr } => Some(*addr), - InboundDirect { - maybe_ip, - transient_port, - } => Some(SocketAddr::new(*maybe_ip, *transient_port)), + InboundDirect { addr } => Some(*addr), OutboundProxy { transient_local_addr, .. - } => Some(*transient_local_addr), - InboundProxy { transient_addr } => Some(*transient_addr), + } => Some(PeerSocketAddr::from(*transient_local_addr)), + InboundProxy { transient_addr } => Some(PeerSocketAddr::from(*transient_addr)), Isolated => None, } } @@ -332,8 +325,8 @@ impl ConnectedAddr { /// remote address that we're currently connected to. pub fn get_alternate_addrs( &self, - mut canonical_remote: SocketAddr, - ) -> impl Iterator { + mut canonical_remote: PeerSocketAddr, + ) -> impl Iterator { let addrs = match self { OutboundDirect { addr } => { // Fixup unspecified addresses and ports using known good data @@ -355,9 +348,9 @@ impl ConnectedAddr { } } - InboundDirect { maybe_ip, .. } => { + InboundDirect { addr } => { // Use the IP from the TCP connection, and the port the peer told us - let maybe_addr = SocketAddr::new(*maybe_ip, canonical_remote.port()); + let maybe_addr = SocketAddr::new(addr.ip(), canonical_remote.port()).into(); // Try both addresses, but remove one duplicate if they match if canonical_remote != maybe_addr { @@ -654,7 +647,7 @@ where // an unspecified address for Isolated connections Isolated => { let unspec_ipv4 = get_unspecified_ipv4_addr(config.network); - (unspec_ipv4, PeerServices::empty(), unspec_ipv4) + (unspec_ipv4.into(), PeerServices::empty(), unspec_ipv4) } _ => { let their_addr = connected_addr @@ -923,7 +916,7 @@ where // `Version` messages. let alternate_addrs = connected_addr.get_alternate_addrs(remote_canonical_addr); for alt_addr in alternate_addrs { - let alt_addr = MetaAddr::new_alternate(&alt_addr, &remote_services); + let alt_addr = MetaAddr::new_alternate(alt_addr, &remote_services); // awaiting a local task won't hang let _ = address_book_updater.send(alt_addr).await; } @@ -933,7 +926,7 @@ where // the collector doesn't depend on network activity, // so this await should not hang let _ = address_book_updater - .send(MetaAddr::new_responded(&book_addr, &remote_services)) + .send(MetaAddr::new_responded(book_addr, &remote_services)) .await; } @@ -1023,7 +1016,7 @@ where // so this await should not hang let _ = inbound_ts_collector .send(MetaAddr::new_responded( - &book_addr, + book_addr, &remote_services, )) .await; @@ -1040,7 +1033,7 @@ where if let Some(book_addr) = connected_addr.get_address_book_addr() { let _ = inbound_ts_collector - .send(MetaAddr::new_errored(&book_addr, remote_services)) + .send(MetaAddr::new_errored(book_addr, remote_services)) .await; } } @@ -1408,7 +1401,7 @@ where if let Some(book_addr) = connected_addr.get_address_book_addr() { let _ = address_book_updater - .send(MetaAddr::new_errored(&book_addr, *remote_services)) + .send(MetaAddr::new_errored(book_addr, *remote_services)) .await; } Err(err) @@ -1427,7 +1420,7 @@ async fn handle_heartbeat_shutdown( if let Some(book_addr) = connected_addr.get_address_book_addr() { let _ = address_book_updater - .send(MetaAddr::new_shutdown(&book_addr, *remote_services)) + .send(MetaAddr::new_shutdown(book_addr, *remote_services)) .await; } diff --git a/zebra-network/src/peer/priority.rs b/zebra-network/src/peer/priority.rs index f754c8bb..1b9d3c05 100644 --- a/zebra-network/src/peer/priority.rs +++ b/zebra-network/src/peer/priority.rs @@ -4,6 +4,8 @@ use std::net::SocketAddr; use zebra_chain::parameters::Network; +use crate::PeerSocketAddr; + use AttributePreference::*; /// A level of preference for a peer attribute. @@ -67,13 +69,15 @@ impl PeerPreference { /// /// Use the [`PeerPreference`] [`Ord`] implementation to sort preferred peers first. pub fn new( - peer_addr: &SocketAddr, + peer_addr: impl Into, network: impl Into>, ) -> Result { + let peer_addr = peer_addr.into(); + address_is_valid_for_outbound_connections(peer_addr, network)?; - // This check only prefers the configured network, - // because the address book and initial peer connections reject the port used by the other network. + // This check only prefers the configured network, because + // address_is_valid_for_outbound_connections() rejects the port used by the other network. let canonical_port = AttributePreference::preferred_from([8232, 18232].contains(&peer_addr.port())); @@ -81,7 +85,7 @@ impl PeerPreference { } } -/// Is the [`SocketAddr`] we have for this peer valid for outbound +/// Is the [`PeerSocketAddr`] we have for this peer valid for outbound /// connections? /// /// Since the addresses in the address book are unique, this check can be @@ -89,7 +93,7 @@ impl PeerPreference { /// /// [`MetaAddr`]: crate::meta_addr::MetaAddr pub fn address_is_valid_for_outbound_connections( - peer_addr: &SocketAddr, + peer_addr: PeerSocketAddr, network: impl Into>, ) -> Result<(), &'static str> { // TODO: make private IP addresses an error unless a debug config is set (#3117) @@ -105,14 +109,14 @@ pub fn address_is_valid_for_outbound_connections( ); } - address_is_valid_for_inbound_listeners(peer_addr, network) + address_is_valid_for_inbound_listeners(*peer_addr, network) } /// Is the supplied [`SocketAddr`] valid for inbound listeners on `network`? /// /// This is used to check Zebra's configured Zcash listener port. pub fn address_is_valid_for_inbound_listeners( - listener_addr: &SocketAddr, + listener_addr: SocketAddr, network: impl Into>, ) -> Result<(), &'static str> { // TODO: make private IP addresses an error unless a debug config is set (#3117) diff --git a/zebra-network/src/peer_set/candidate_set.rs b/zebra-network/src/peer_set/candidate_set.rs index 3a3d8933..042a92b2 100644 --- a/zebra-network/src/peer_set/candidate_set.rs +++ b/zebra-network/src/peer_set/candidate_set.rs @@ -388,7 +388,7 @@ where // // We could send a reconnect change to the AddressBookUpdater when the peer is actually used, // but channel order is not guaranteed, so we could accidentally re-use the same peer. - let next_peer = MetaAddr::new_reconnect(&next_peer.addr); + let next_peer = MetaAddr::new_reconnect(next_peer.addr); guard.update(next_peer) }; @@ -407,7 +407,7 @@ where /// Mark `addr` as a failed peer. pub async fn report_failed(&mut self, addr: &MetaAddr) { - let addr = MetaAddr::new_errored(&addr.addr, addr.services); + let addr = MetaAddr::new_errored(addr.addr, addr.services); // # Correctness // diff --git a/zebra-network/src/peer_set/candidate_set/tests/vectors.rs b/zebra-network/src/peer_set/candidate_set/tests/vectors.rs index cfbac8ad..71811a75 100644 --- a/zebra-network/src/peer_set/candidate_set/tests/vectors.rs +++ b/zebra-network/src/peer_set/candidate_set/tests/vectors.rs @@ -1,7 +1,6 @@ //! Fixed test vectors for CandidateSet. use std::{ - convert::TryInto, net::{IpAddr, SocketAddr}, str::FromStr, sync::Arc, @@ -245,7 +244,7 @@ fn mock_gossiped_peers(last_seen_times: impl IntoIterator>) .expect("`last_seen` time doesn't fit in a `DateTime32`"); MetaAddr::new_gossiped_meta_addr( - SocketAddr::new(IpAddr::from([192, 168, 1, index as u8]), 20_000), + SocketAddr::new(IpAddr::from([192, 168, 1, index as u8]), 20_000).into(), PeerServices::NODE_NETWORK, last_seen, ) diff --git a/zebra-network/src/peer_set/initialize.rs b/zebra-network/src/peer_set/initialize.rs index 664e483d..f9b002f9 100644 --- a/zebra-network/src/peer_set/initialize.rs +++ b/zebra-network/src/peer_set/initialize.rs @@ -39,7 +39,7 @@ use crate::{ OutboundConnectorRequest, PeerPreference, }, peer_set::{set::MorePeers, ActiveConnectionCounter, CandidateSet, ConnectionTracker, PeerSet}, - AddressBook, BoxError, Config, Request, Response, + AddressBook, BoxError, Config, PeerSocketAddr, Request, Response, }; #[cfg(test)] @@ -49,7 +49,7 @@ mod tests; /// handshake. /// /// This result comes from the `Handshaker`. -type DiscoveredPeer = Result<(SocketAddr, peer::Client), BoxError>; +type DiscoveredPeer = Result<(PeerSocketAddr, peer::Client), BoxError>; /// Initialize a peer set, using a network `config`, `inbound_service`, /// and `latest_chain_tip`. @@ -254,8 +254,11 @@ async fn add_initial_peers( address_book_updater: tokio::sync::mpsc::Sender, ) -> Result where - S: Service - + Clone + S: Service< + OutboundConnectorRequest, + Response = (PeerSocketAddr, peer::Client), + Error = BoxError, + > + Clone + Send + 'static, S::Future: Send + 'static, @@ -398,9 +401,9 @@ where async fn limit_initial_peers( config: &Config, address_book_updater: tokio::sync::mpsc::Sender, -) -> HashSet { - let all_peers: HashSet = config.initial_peers().await; - let mut preferred_peers: BTreeMap> = BTreeMap::new(); +) -> HashSet { + let all_peers: HashSet = config.initial_peers().await; + let mut preferred_peers: BTreeMap> = BTreeMap::new(); let all_peers_count = all_peers.len(); if all_peers_count > config.peerset_initial_target_size { @@ -413,7 +416,7 @@ async fn limit_initial_peers( // Filter out invalid initial peers, and prioritise valid peers for initial connections. // (This treats initial peers the same way we treat gossiped peers.) for peer_addr in all_peers { - let preference = PeerPreference::new(&peer_addr, config.network); + let preference = PeerPreference::new(peer_addr, config.network); match preference { Ok(preference) => preferred_peers @@ -439,7 +442,7 @@ async fn limit_initial_peers( // Split out the `initial_peers` that will be shuffled and returned, // choosing preferred peers first. - let mut initial_peers: HashSet = HashSet::new(); + let mut initial_peers: HashSet = HashSet::new(); for better_peers in preferred_peers.values() { let mut better_peers = better_peers.clone(); let (chosen_peers, _unused_peers) = better_peers.partial_shuffle( @@ -470,7 +473,7 @@ async fn limit_initial_peers( pub(crate) async fn open_listener(config: &Config) -> (TcpListener, SocketAddr) { // Warn if we're configured using the wrong network port. if let Err(wrong_addr) = - address_is_valid_for_inbound_listeners(&config.listen_addr, config.network) + address_is_valid_for_inbound_listeners(config.listen_addr, config.network) { warn!( "We are configured with address {} on {:?}, but it could cause network issues. \ @@ -551,6 +554,8 @@ where }; if let Ok((tcp_stream, addr)) = inbound_result { + let addr: PeerSocketAddr = addr.into(); + if active_inbound_connections.update_count() >= config.peerset_inbound_connection_limit() { @@ -644,7 +649,7 @@ enum CrawlerAction { TimerCrawl { tick: Instant }, /// Handle a successfully connected handshake `peer_set_change`. HandshakeConnected { - address: SocketAddr, + address: PeerSocketAddr, client: peer::Client, }, /// Handle a handshake failure to `failed_addr`. @@ -692,8 +697,11 @@ async fn crawl_and_dial( mut active_outbound_connections: ActiveConnectionCounter, ) -> Result<(), BoxError> where - C: Service - + Clone + C: Service< + OutboundConnectorRequest, + Response = (PeerSocketAddr, peer::Client), + Error = BoxError, + > + Clone + Send + 'static, C::Future: Send + 'static, @@ -865,8 +873,11 @@ async fn dial( outbound_connection_tracker: ConnectionTracker, ) -> CrawlerAction where - C: Service - + Clone + C: Service< + OutboundConnectorRequest, + Response = (PeerSocketAddr, peer::Client), + Error = BoxError, + > + Clone + Send + 'static, C::Future: Send + 'static, @@ -898,8 +909,8 @@ where .await } -impl From> for CrawlerAction { - fn from(dial_result: Result<(SocketAddr, peer::Client), (MetaAddr, BoxError)>) -> Self { +impl From> for CrawlerAction { + fn from(dial_result: Result<(PeerSocketAddr, peer::Client), (MetaAddr, BoxError)>) -> Self { use CrawlerAction::*; match dial_result { Ok((address, client)) => HandshakeConnected { address, client }, diff --git a/zebra-network/src/peer_set/initialize/tests/vectors.rs b/zebra-network/src/peer_set/initialize/tests/vectors.rs index 8bab47c0..4ef69cb5 100644 --- a/zebra-network/src/peer_set/initialize/tests/vectors.rs +++ b/zebra-network/src/peer_set/initialize/tests/vectors.rs @@ -43,7 +43,7 @@ use crate::{ ActiveConnectionCounter, CandidateSet, }, protocol::types::PeerServices, - AddressBook, BoxError, Config, Request, Response, + AddressBook, BoxError, Config, PeerSocketAddr, Request, Response, }; use Network::*; @@ -1192,7 +1192,7 @@ async fn self_connections_should_fail() { .expect("unexpected panic in address book"); let self_connection_status = unlocked_address_book - .get(&real_self_listener.addr()) + .get(real_self_listener.addr()) .expect("unexpected dropped listener address in address book"); std::mem::drop(unlocked_address_book); @@ -1283,7 +1283,7 @@ async fn remnant_nonces_from_outbound_connections_are_limited() { let connection_tracker = active_outbound_connections.track_connection(); let req = OutboundConnectorRequest { - addr, + addr: addr.into(), connection_tracker, }; @@ -1462,8 +1462,11 @@ async fn spawn_crawler_with_peer_limit( outbound_connector: C, ) -> (Config, mpsc::Receiver) where - C: Service - + Clone + C: Service< + OutboundConnectorRequest, + Response = (PeerSocketAddr, peer::Client), + Error = BoxError, + > + Clone + Send + 'static, C::Future: Send + 'static, @@ -1482,8 +1485,11 @@ where let mut fake_peer = None; for address_number in 0..over_limit_peers { let addr = SocketAddr::new(Ipv4Addr::new(127, 1, 1, address_number as _).into(), 1); - let addr = - MetaAddr::new_gossiped_meta_addr(addr, PeerServices::NODE_NETWORK, DateTime32::now()); + let addr = MetaAddr::new_gossiped_meta_addr( + addr.into(), + PeerServices::NODE_NETWORK, + DateTime32::now(), + ); fake_peer = Some(addr); let addr = addr .new_gossiped_change() @@ -1674,8 +1680,11 @@ async fn spawn_add_initial_peers( JoinHandle>, ) where - C: Service - + Clone + C: Service< + OutboundConnectorRequest, + Response = (PeerSocketAddr, peer::Client), + Error = BoxError, + > + Clone + Send + 'static, C::Future: Send + 'static, diff --git a/zebra-network/src/peer_set/inventory_registry.rs b/zebra-network/src/peer_set/inventory_registry.rs index 4b19a72c..b3de4cce 100644 --- a/zebra-network/src/peer_set/inventory_registry.rs +++ b/zebra-network/src/peer_set/inventory_registry.rs @@ -3,7 +3,6 @@ //! [RFC]: https://zebra.zfnd.org/dev/rfcs/0003-inventory-tracking.html use std::{ - net::SocketAddr, pin::Pin, task::{Context, Poll}, }; @@ -21,7 +20,7 @@ use zebra_chain::serialization::AtLeastOne; use crate::{ constants::INVENTORY_ROTATION_INTERVAL, protocol::{external::InventoryHash, internal::InventoryResponse}, - BoxError, + BoxError, PeerSocketAddr, }; use self::update::Update; @@ -79,7 +78,7 @@ pub type InventoryStatus = InventoryResponse; /// /// For security reasons, all `notfound` rejections should be tracked. /// This also helps with performance, if the hash is rare on the network. -pub type InventoryChange = InventoryStatus<(AtLeastOne, SocketAddr)>; +pub type InventoryChange = InventoryStatus<(AtLeastOne, PeerSocketAddr)>; /// An internal marker used in inventory status hash maps. type InventoryMarker = InventoryStatus<()>; @@ -94,10 +93,10 @@ pub struct InventoryRegistry { /// period. // // TODO: split maps into available and missing, so we can limit them separately. - current: IndexMap>, + current: IndexMap>, /// Map tracking inventory statuses from the previous interval period. - prev: IndexMap>, + prev: IndexMap>, /// Stream of incoming inventory statuses to register. inv_stream: Pin< @@ -119,20 +118,20 @@ impl std::fmt::Debug for InventoryRegistry { impl InventoryChange { /// Returns a new available inventory change from a single hash. - pub fn new_available(hash: InventoryHash, peer: SocketAddr) -> Self { + pub fn new_available(hash: InventoryHash, peer: PeerSocketAddr) -> Self { InventoryStatus::Available((AtLeastOne::from_one(hash), peer)) } /// Returns a new missing inventory change from a single hash. #[allow(dead_code)] - pub fn new_missing(hash: InventoryHash, peer: SocketAddr) -> Self { + pub fn new_missing(hash: InventoryHash, peer: PeerSocketAddr) -> Self { InventoryStatus::Missing((AtLeastOne::from_one(hash), peer)) } /// Returns a new available multiple inventory change, if `hashes` contains at least one change. pub fn new_available_multi<'a>( hashes: impl IntoIterator, - peer: SocketAddr, + peer: PeerSocketAddr, ) -> Option { let mut hashes: Vec = hashes.into_iter().copied().collect(); @@ -153,7 +152,7 @@ impl InventoryChange { /// Returns a new missing multiple inventory change, if `hashes` contains at least one change. pub fn new_missing_multi<'a>( hashes: impl IntoIterator, - peer: SocketAddr, + peer: PeerSocketAddr, ) -> Option { let mut hashes: Vec = hashes.into_iter().copied().collect(); @@ -220,14 +219,14 @@ impl InventoryRegistry { } /// Returns an iterator over addrs of peers that have recently advertised `hash` in their inventory. - pub fn advertising_peers(&self, hash: InventoryHash) -> impl Iterator { + pub fn advertising_peers(&self, hash: InventoryHash) -> impl Iterator { self.status_peers(hash) .filter_map(|addr_status| addr_status.available()) } /// Returns an iterator over addrs of peers that have recently missed `hash` in their inventory. #[allow(dead_code)] - pub fn missing_peers(&self, hash: InventoryHash) -> impl Iterator { + pub fn missing_peers(&self, hash: InventoryHash) -> impl Iterator { self.status_peers(hash) .filter_map(|addr_status| addr_status.missing()) } @@ -238,7 +237,7 @@ impl InventoryRegistry { pub fn status_peers( &self, hash: InventoryHash, - ) -> impl Iterator> { + ) -> impl Iterator> { let prev = self.prev.get(&hash); let current = self.current.get(&hash); @@ -258,7 +257,7 @@ impl InventoryRegistry { } /// Returns true if there is a current status entry for `hash` and `addr`. - pub fn has_current_status(&self, hash: InventoryHash, addr: SocketAddr) -> bool { + pub fn has_current_status(&self, hash: InventoryHash, addr: PeerSocketAddr) -> bool { self.current .get(&hash) .and_then(|current| current.get(&addr)) @@ -272,7 +271,7 @@ impl InventoryRegistry { #[allow(dead_code)] pub fn status_hashes( &self, - ) -> impl Iterator)> { + ) -> impl Iterator)> { self.current.iter().chain(self.prev.iter()) } diff --git a/zebra-network/src/peer_set/inventory_registry/tests/prop.rs b/zebra-network/src/peer_set/inventory_registry/tests/prop.rs index 10dcc34f..959d7b91 100644 --- a/zebra-network/src/peer_set/inventory_registry/tests/prop.rs +++ b/zebra-network/src/peer_set/inventory_registry/tests/prop.rs @@ -1,6 +1,6 @@ //! Randomised property tests for the inventory registry. -use std::{collections::HashSet, net::SocketAddr}; +use std::collections::HashSet; use proptest::prelude::*; @@ -11,6 +11,7 @@ use crate::{ InventoryMarker, }, protocol::external::{InventoryHash, Message}, + PeerSocketAddr, }; use InventoryHash::*; @@ -59,7 +60,7 @@ async fn inv_registry_inbound_wrapper_with( status: InventoryMarker, test_hashes: HashSet, ) { - let test_peer: SocketAddr = "1.1.1.1:1" + let test_peer: PeerSocketAddr = "1.1.1.1:1" .parse() .expect("unexpected invalid peer address"); let test_peer = ConnectedAddr::new_inbound_direct(test_peer); diff --git a/zebra-network/src/peer_set/inventory_registry/tests/vectors.rs b/zebra-network/src/peer_set/inventory_registry/tests/vectors.rs index 2aafc96d..0116f3b0 100644 --- a/zebra-network/src/peer_set/inventory_registry/tests/vectors.rs +++ b/zebra-network/src/peer_set/inventory_registry/tests/vectors.rs @@ -10,6 +10,7 @@ use crate::{ MAX_PEERS_PER_INV, }, protocol::external::InventoryHash, + PeerSocketAddr, }; /// Check an empty inventory registry works as expected. @@ -242,10 +243,11 @@ async fn inv_registry_limit_for(status: InventoryMarker) { let (mut inv_registry, inv_stream_tx) = new_inv_registry(); for peer_count in 0..(MAX_PEERS_PER_INV + 10) { - let test_peer = SocketAddr::new( + let test_peer: PeerSocketAddr = SocketAddr::new( "2.2.2.2".parse().unwrap(), peer_count.try_into().expect("fits in u16"), - ); + ) + .into(); let test_change = status.map(|()| (AtLeastOne::from_one(single_test_hash), test_peer)); diff --git a/zebra-network/src/peer_set/set.rs b/zebra-network/src/peer_set/set.rs index de641ace..88d53b54 100644 --- a/zebra-network/src/peer_set/set.rs +++ b/zebra-network/src/peer_set/set.rs @@ -98,7 +98,6 @@ use std::{ fmt::Debug, future::Future, marker::PhantomData, - net::SocketAddr, pin::Pin, task::{Context, Poll}, time::Instant, @@ -133,7 +132,7 @@ use crate::{ external::InventoryHash, internal::{Request, Response}, }, - BoxError, Config, PeerError, SharedPeerError, + BoxError, Config, PeerError, PeerSocketAddr, SharedPeerError, }; #[cfg(test)] @@ -166,7 +165,7 @@ pub struct CancelClientWork; /// Otherwise, malicious peers could interfere with other peers' `PeerSet` state. pub struct PeerSet where - D: Discover + Unpin, + D: Discover + Unpin, D::Error: Into, C: ChainTip, { @@ -252,7 +251,7 @@ where impl Drop for PeerSet where - D: Discover + Unpin, + D: Discover + Unpin, D::Error: Into, C: ChainTip, { @@ -263,7 +262,7 @@ where impl PeerSet where - D: Discover + Unpin, + D: Discover + Unpin, D::Error: Into, C: ChainTip, { @@ -711,7 +710,7 @@ where return fut.map_err(Into::into).boxed(); } - let missing_peer_list: HashSet = self + let missing_peer_list: HashSet = self .inventory_registry .missing_peers(hash) .copied() @@ -883,7 +882,7 @@ where impl Service for PeerSet where - D: Discover + Unpin, + D: Discover + Unpin, D::Error: Into, C: ChainTip, { diff --git a/zebra-network/src/peer_set/set/tests.rs b/zebra-network/src/peer_set/set/tests.rs index bc01d978..a24330f9 100644 --- a/zebra-network/src/peer_set/set/tests.rs +++ b/zebra-network/src/peer_set/set/tests.rs @@ -26,7 +26,7 @@ use crate::{ peer::{ClientTestHarness, LoadTrackedClient, MinimumPeerVersion}, peer_set::{set::MorePeers, InventoryChange, PeerSet}, protocol::external::types::Version, - AddressBook, Config, + AddressBook, Config, PeerSocketAddr, }; #[cfg(test)] @@ -86,14 +86,14 @@ impl PeerVersions { pub fn mock_peer_discovery( &self, ) -> ( - impl Stream, BoxError>>, + impl Stream, BoxError>>, Vec, ) { let (clients, harnesses) = self.mock_peers(); let fake_ports = 1_u16..; let discovered_peers_iterator = fake_ports.zip(clients).map(|(port, client)| { - let peer_address = SocketAddr::new([127, 0, 0, 1].into(), port); + let peer_address: PeerSocketAddr = SocketAddr::new([127, 0, 0, 1].into(), port).into(); Ok(Change::Insert(peer_address, client)) }); @@ -159,7 +159,7 @@ impl PeerSetBuilder { impl PeerSetBuilder where - D: Discover + Unpin, + D: Discover + Unpin, D::Error: Into, C: ChainTip, { diff --git a/zebra-network/src/peer_set/set/tests/prop.rs b/zebra-network/src/peer_set/set/tests/prop.rs index 24b3c9ab..1a95f31e 100644 --- a/zebra-network/src/peer_set/set/tests/prop.rs +++ b/zebra-network/src/peer_set/set/tests/prop.rs @@ -10,15 +10,16 @@ use zebra_chain::{ block, chain_tip::ChainTip, parameters::Network, serialization::ZcashDeserializeInto, }; -use super::{BlockHeightPairAcrossNetworkUpgrades, PeerSetBuilder, PeerVersions}; use crate::{ constants::CURRENT_NETWORK_PROTOCOL_VERSION, peer::{ClientTestHarness, LoadTrackedClient, MinimumPeerVersion, ReceiveRequestAttempt}, peer_set::PeerSet, protocol::external::types::Version, - Request, + PeerSocketAddr, Request, }; +use super::{BlockHeightPairAcrossNetworkUpgrades, PeerSetBuilder, PeerVersions}; + proptest! { /// Check if discovered outdated peers are immediately dropped by the [`PeerSet`]. #[test] @@ -200,7 +201,7 @@ proptest! { // Remove peers, test broadcast until there is only 1 peer left in the peerset for port in 1u16..total_number_of_peers as u16 { - peer_set.remove(&SocketAddr::new([127, 0, 0, 1].into(), port)); + peer_set.remove(&SocketAddr::new([127, 0, 0, 1].into(), port).into()); handles.remove(0); // poll the peers @@ -270,7 +271,7 @@ proptest! { // Remove peers for port in 1u16..=total_number_of_peers as u16 { - peer_set.remove(&SocketAddr::new([127, 0, 0, 1].into(), port)); + peer_set.remove(&SocketAddr::new([127, 0, 0, 1].into(), port).into()); handles.remove(0); } @@ -294,7 +295,7 @@ fn check_if_only_up_to_date_peers_are_live( minimum_version: Version, ) -> Result where - D: Discover + Unpin, + D: Discover + Unpin, D::Error: Into, C: ChainTip, { diff --git a/zebra-network/src/protocol/external.rs b/zebra-network/src/protocol/external.rs index abecdc05..b060d646 100644 --- a/zebra-network/src/protocol/external.rs +++ b/zebra-network/src/protocol/external.rs @@ -16,7 +16,7 @@ pub mod arbitrary; #[cfg(test)] mod tests; -pub use addr::{canonical_socket_addr, AddrInVersion}; +pub use addr::{canonical_peer_addr, canonical_socket_addr, AddrInVersion}; pub use codec::Codec; pub use inv::InventoryHash; pub use message::{Message, VersionMessage}; diff --git a/zebra-network/src/protocol/external/addr.rs b/zebra-network/src/protocol/external/addr.rs index 111100ec..53281157 100644 --- a/zebra-network/src/protocol/external/addr.rs +++ b/zebra-network/src/protocol/external/addr.rs @@ -11,7 +11,7 @@ pub mod in_version; pub(crate) mod v1; pub(crate) mod v2; -pub use canonical::canonical_socket_addr; +pub use canonical::{canonical_peer_addr, canonical_socket_addr}; pub use in_version::AddrInVersion; // These types and functions should only be visible in the `external` module, @@ -22,7 +22,7 @@ pub(super) use v2::AddrV2; #[allow(unused_imports)] #[cfg(any(test, feature = "proptest-impl"))] -pub(super) use v1::{ipv6_mapped_socket_addr, ADDR_V1_SIZE}; +pub(super) use v1::{ipv6_mapped_ip_addr, ADDR_V1_SIZE}; // TODO: write tests for addrv2 deserialization #[allow(unused_imports)] diff --git a/zebra-network/src/protocol/external/addr/canonical.rs b/zebra-network/src/protocol/external/addr/canonical.rs index 3e0f003a..91bb20ad 100644 --- a/zebra-network/src/protocol/external/addr/canonical.rs +++ b/zebra-network/src/protocol/external/addr/canonical.rs @@ -1,34 +1,37 @@ //! Zebra's canonical node address format. //! -//! Zebra canonicalises all received addresses into Rust [`SocketAddr`]s. +//! Zebra canonicalises all received addresses into Rust [`PeerSocketAddr`]s. //! If the address is an [IPv4-mapped IPv6 address], it becomes a [`SocketAddr::V4`] //! //! [IPv4-mapped IPv6 address]: https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses use std::net::{IpAddr, Ipv6Addr, SocketAddr}; -/// Transform a Zcash-deserialized IPv6 address into a canonical Zebra IP address. +use crate::PeerSocketAddr; + +/// Transform a Zcash-deserialized [`Ipv6Addr`] into a canonical Zebra [`IpAddr`]. /// /// Zcash uses IPv6-mapped IPv4 addresses in its `addr` (v1) network messages. /// Zebra converts those addresses to `Ipv4Addr`s, for maximum compatibility /// with systems that don't understand IPv6. /// /// Zebra also uses this canonical format for addresses from other sources. -pub fn canonical_ip_addr(v6_addr: &Ipv6Addr) -> IpAddr { +pub(in super::super) fn canonical_ip_addr(v6_addr: &Ipv6Addr) -> IpAddr { use IpAddr::*; - // TODO: replace with `to_ipv4_mapped` when that stabilizes - // https://github.com/rust-lang/rust/issues/27709 - match v6_addr.to_ipv4() { - // workaround for unstable `to_ipv4_mapped` - Some(v4_addr) if v4_addr.to_ipv6_mapped() == *v6_addr => V4(v4_addr), - Some(_) | None => V6(*v6_addr), - } + // if it is an IPv4-mapped address, convert to V4, otherwise leave it as V6 + v6_addr + .to_ipv4_mapped() + .map(V4) + .unwrap_or_else(|| V6(*v6_addr)) } -/// Transform a `SocketAddr` into a canonical Zebra `SocketAddr`, converting +/// Transform a [`SocketAddr`] into a canonical Zebra [`SocketAddr`], converting /// IPv6-mapped IPv4 addresses, and removing IPv6 scope IDs and flow information. /// +/// Use [`canonical_peer_addr()`] and [`PeerSocketAddr`] for remote peer addresses, +/// so that Zebra doesn't log sensitive information about peers. +/// /// See [`canonical_ip_addr`] for detailed info on IPv6-mapped IPv4 addresses. pub fn canonical_socket_addr(socket_addr: impl Into) -> SocketAddr { use SocketAddr::*; @@ -42,3 +45,13 @@ pub fn canonical_socket_addr(socket_addr: impl Into) -> SocketAddr { socket_addr } + +/// Transform a [`PeerSocketAddr`] into a canonical Zebra [`PeerSocketAddr`], converting +/// IPv6-mapped IPv4 addresses, and removing IPv6 scope IDs and flow information. +/// +/// See [`canonical_ip_addr`] for detailed info on IPv6-mapped IPv4 addresses. +pub fn canonical_peer_addr(peer_socket_addr: impl Into) -> PeerSocketAddr { + let peer_socket_addr = peer_socket_addr.into(); + + canonical_socket_addr(*peer_socket_addr).into() +} diff --git a/zebra-network/src/protocol/external/addr/in_version.rs b/zebra-network/src/protocol/external/addr/in_version.rs index 5305c943..bdaf4509 100644 --- a/zebra-network/src/protocol/external/addr/in_version.rs +++ b/zebra-network/src/protocol/external/addr/in_version.rs @@ -5,7 +5,7 @@ use std::{ io::{Read, Write}, - net::{SocketAddr, SocketAddrV6}, + net::SocketAddrV6, }; use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt}; @@ -14,15 +14,15 @@ use zebra_chain::serialization::{ SerializationError, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize, }; -use crate::protocol::external::types::PeerServices; +use crate::{protocol::external::types::PeerServices, PeerSocketAddr}; #[cfg(any(test, feature = "proptest-impl"))] use proptest_derive::Arbitrary; #[cfg(any(test, feature = "proptest-impl"))] -use crate::protocol::external::arbitrary::addr_v1_ipv6_mapped_socket_addr_strategy; +use crate::protocol::external::arbitrary::canonical_peer_addr_strategy; -use super::{canonical_socket_addr, v1::ipv6_mapped_socket_addr}; +use super::{canonical_peer_addr, v1::ipv6_mapped_ip_addr}; /// The format used for Bitcoin node addresses in `version` messages. /// Contains a node address and services, without a last-seen time. @@ -31,9 +31,9 @@ use super::{canonical_socket_addr, v1::ipv6_mapped_socket_addr}; #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))] pub struct AddrInVersion { - /// The unverified services for the peer at `ipv6_addr`. + /// The unverified services for the peer at `addr`. /// - /// These services were advertised by the peer at `ipv6_addr`, + /// These services were advertised by the peer at `addr`, /// then gossiped via another peer. /// /// ## Security @@ -42,29 +42,29 @@ pub struct AddrInVersion { /// records, older peer versions, or buggy or malicious peers. untrusted_services: PeerServices, - /// The peer's IPv6 socket address. + /// The peer's canonical socket address. /// IPv4 addresses are serialized as an [IPv4-mapped IPv6 address]. /// /// [IPv4-mapped IPv6 address]: https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses #[cfg_attr( any(test, feature = "proptest-impl"), - proptest(strategy = "addr_v1_ipv6_mapped_socket_addr_strategy()") + proptest(strategy = "canonical_peer_addr_strategy()") )] - ipv6_addr: SocketAddrV6, + addr: PeerSocketAddr, } impl AddrInVersion { /// Returns a new `version` message address based on its fields. - pub fn new(socket_addr: impl Into, untrusted_services: PeerServices) -> Self { + pub fn new(socket_addr: impl Into, untrusted_services: PeerServices) -> Self { Self { untrusted_services, - ipv6_addr: ipv6_mapped_socket_addr(socket_addr), + addr: canonical_peer_addr(socket_addr), } } /// Returns the canonical address for this peer. - pub fn addr(&self) -> SocketAddr { - canonical_socket_addr(self.ipv6_addr) + pub fn addr(&self) -> PeerSocketAddr { + self.addr } /// Returns the services for this peer. @@ -77,8 +77,9 @@ impl ZcashSerialize for AddrInVersion { fn zcash_serialize(&self, mut writer: W) -> Result<(), std::io::Error> { writer.write_u64::(self.untrusted_services.bits())?; - self.ipv6_addr.ip().zcash_serialize(&mut writer)?; - writer.write_u16::(self.ipv6_addr.port())?; + let ipv6_addr = ipv6_mapped_ip_addr(self.addr.ip()); + ipv6_addr.zcash_serialize(&mut writer)?; + writer.write_u16::(self.addr.port())?; Ok(()) } @@ -96,7 +97,7 @@ impl ZcashDeserialize for AddrInVersion { let ipv6_addr = SocketAddrV6::new(ipv6_addr, port, 0, 0); Ok(AddrInVersion { - ipv6_addr, + addr: canonical_peer_addr(ipv6_addr), untrusted_services, }) } diff --git a/zebra-network/src/protocol/external/addr/v1.rs b/zebra-network/src/protocol/external/addr/v1.rs index efdd8245..a8be5a33 100644 --- a/zebra-network/src/protocol/external/addr/v1.rs +++ b/zebra-network/src/protocol/external/addr/v1.rs @@ -7,7 +7,7 @@ use std::{ io::{Read, Write}, - net::{IpAddr, Ipv6Addr, SocketAddr, SocketAddrV6}, + net::{IpAddr, Ipv6Addr, SocketAddrV6}, }; use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt}; @@ -20,13 +20,16 @@ use zebra_chain::serialization::{ use crate::{ meta_addr::MetaAddr, protocol::external::{types::PeerServices, MAX_PROTOCOL_MESSAGE_LEN}, + PeerSocketAddr, }; +use super::canonical_peer_addr; + #[cfg(any(test, feature = "proptest-impl"))] use proptest_derive::Arbitrary; #[cfg(any(test, feature = "proptest-impl"))] -use crate::protocol::external::arbitrary::addr_v1_ipv6_mapped_socket_addr_strategy; +use crate::protocol::external::arbitrary::canonical_peer_addr_strategy; /// The first format used for Bitcoin node addresses. /// Contains a node address, its advertised services, and last-seen time. @@ -42,9 +45,9 @@ pub(in super::super) struct AddrV1 { /// See the [`MetaAddr::last_seen`] method for details. untrusted_last_seen: DateTime32, - /// The unverified services for the peer at `ipv6_addr`. + /// The unverified services for the peer at `addr`. /// - /// These services were advertised by the peer at `ipv6_addr`, + /// These services were advertised by the peer at `addr`, /// then gossiped via another peer. /// /// ## Security @@ -53,20 +56,20 @@ pub(in super::super) struct AddrV1 { /// records, older peer versions, or buggy or malicious peers. untrusted_services: PeerServices, - /// The peer's IPv6 socket address. + /// The peer's canonical socket address. /// IPv4 addresses are serialized as an [IPv4-mapped IPv6 address]. /// /// [IPv4-mapped IPv6 address]: https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses #[cfg_attr( any(test, feature = "proptest-impl"), - proptest(strategy = "addr_v1_ipv6_mapped_socket_addr_strategy()") + proptest(strategy = "canonical_peer_addr_strategy()") )] - ipv6_addr: SocketAddrV6, + addr: PeerSocketAddr, } impl From for AddrV1 { fn from(meta_addr: MetaAddr) -> Self { - let ipv6_addr = ipv6_mapped_socket_addr(meta_addr.addr); + let addr = canonical_peer_addr(meta_addr.addr); let untrusted_services = meta_addr.services.expect( "unexpected MetaAddr with missing peer services: \ @@ -80,7 +83,7 @@ impl From for AddrV1 { AddrV1 { untrusted_last_seen, untrusted_services, - ipv6_addr, + addr, } } } @@ -88,7 +91,7 @@ impl From for AddrV1 { impl From for MetaAddr { fn from(addr: AddrV1) -> Self { MetaAddr::new_gossiped_meta_addr( - addr.ipv6_addr.into(), + addr.addr, addr.untrusted_services, addr.untrusted_last_seen, ) @@ -100,8 +103,9 @@ impl ZcashSerialize for AddrV1 { self.untrusted_last_seen.zcash_serialize(&mut writer)?; writer.write_u64::(self.untrusted_services.bits())?; - self.ipv6_addr.ip().zcash_serialize(&mut writer)?; - writer.write_u16::(self.ipv6_addr.port())?; + let ipv6_addr = ipv6_mapped_ip_addr(self.addr.ip()); + ipv6_addr.zcash_serialize(&mut writer)?; + writer.write_u16::(self.addr.port())?; Ok(()) } @@ -120,7 +124,7 @@ impl ZcashDeserialize for AddrV1 { let ipv6_addr = SocketAddrV6::new(ipv6_addr, port, 0, 0); Ok(AddrV1 { - ipv6_addr, + addr: canonical_peer_addr(ipv6_addr), untrusted_services, untrusted_last_seen, }) @@ -137,36 +141,16 @@ impl TrustedPreallocate for AddrV1 { } } -/// Transform a `SocketAddr` into an IPv6-mapped IPv4 addresses. +/// Transform an `IpAddr` into an IPv6-mapped IPv4 addresses. /// /// See [`canonical_ip_addr`] for detailed info on IPv6-mapped IPv4 addresses. /// /// [`canonical_ip_addr`]: super::canonical::canonical_ip_addr -pub(in super::super) fn ipv6_mapped_ip_addr(ip_addr: &IpAddr) -> Ipv6Addr { +pub(in super::super) fn ipv6_mapped_ip_addr(ip_addr: IpAddr) -> Ipv6Addr { use IpAddr::*; match ip_addr { V4(v4_addr) => v4_addr.to_ipv6_mapped(), - V6(v6_addr) => *v6_addr, + V6(v6_addr) => v6_addr, } } - -/// Transform a `SocketAddr` into an IPv6-mapped IPv4 addresses, -/// for `addr` (v1) Zcash network messages. -/// -/// Also remove IPv6 scope IDs and flow information. -/// -/// See [`canonical_ip_addr`] for detailed info on IPv6-mapped IPv4 addresses. -/// -/// [`canonical_ip_addr`]: super::canonical::canonical_ip_addr -pub(in super::super) fn ipv6_mapped_socket_addr( - socket_addr: impl Into, -) -> SocketAddrV6 { - let socket_addr = socket_addr.into(); - - let ipv6_mapped_ip = ipv6_mapped_ip_addr(&socket_addr.ip()); - - // Remove scope IDs and flow information. - // `0` is the default unspecified value for these fields. - SocketAddrV6::new(ipv6_mapped_ip, socket_addr.port(), 0, 0) -} diff --git a/zebra-network/src/protocol/external/addr/v2.rs b/zebra-network/src/protocol/external/addr/v2.rs index 9e6a266f..d7fc14a7 100644 --- a/zebra-network/src/protocol/external/addr/v2.rs +++ b/zebra-network/src/protocol/external/addr/v2.rs @@ -21,8 +21,11 @@ use zebra_chain::serialization::{ use crate::{ meta_addr::MetaAddr, protocol::external::{types::PeerServices, MAX_PROTOCOL_MESSAGE_LEN}, + PeerSocketAddr, }; +use super::canonical_peer_addr; + #[cfg(any(test, feature = "proptest-impl"))] use proptest_derive::Arbitrary; @@ -100,18 +103,18 @@ pub(in super::super) enum AddrV2 { /// records, older peer versions, or buggy or malicious peers. untrusted_services: PeerServices, - /// The peer's IP address. + /// The peer's canonical IP address and port. /// /// Unlike [`AddrV1`], this can be an IPv4 or IPv6 address. /// /// [`AddrV1`]: super::v1::AddrV1 - ip: IpAddr, - - /// The peer's TCP port. - port: u16, + addr: PeerSocketAddr, }, /// A node address with an unsupported `networkID`, in `addrv2` format. + // + // TODO: when we add more address types, make sure their addresses aren't logged, + // in a similar way to `PeerSocketAddr` Unsupported, } @@ -138,8 +141,7 @@ impl From for AddrV2 { AddrV2::IpAddr { untrusted_last_seen, untrusted_services, - ip: meta_addr.addr.ip(), - port: meta_addr.addr.port(), + addr: canonical_peer_addr(meta_addr.addr()), } } } @@ -157,12 +159,9 @@ impl TryFrom for MetaAddr { if let AddrV2::IpAddr { untrusted_last_seen, untrusted_services, - ip, - port, + addr, } = addr { - let addr = SocketAddr::new(ip, port); - Ok(MetaAddr::new_gossiped_meta_addr( addr, untrusted_services, @@ -219,8 +218,7 @@ impl ZcashSerialize for AddrV2 { if let AddrV2::IpAddr { untrusted_last_seen, untrusted_services, - ip, - port, + addr, } = self { // > uint32 Time that this node was last seen as connected to the network. @@ -230,7 +228,7 @@ impl ZcashSerialize for AddrV2 { let untrusted_services: CompactSize64 = untrusted_services.bits().into(); untrusted_services.zcash_serialize(&mut writer)?; - match ip { + match addr.ip() { IpAddr::V4(ip) => { // > Network identifier. An 8-bit value that specifies which network is addressed. writer.write_u8(ADDR_V2_IPV4_NETWORK_ID)?; @@ -243,7 +241,7 @@ impl ZcashSerialize for AddrV2 { zcash_serialize_bytes(&ip.to_vec(), &mut writer)?; // > uint16 Network port. If not relevant for the network this MUST be 0. - writer.write_u16::(*port)?; + writer.write_u16::(addr.port())?; } IpAddr::V6(ip) => { writer.write_u8(ADDR_V2_IPV6_NETWORK_ID)?; @@ -251,7 +249,7 @@ impl ZcashSerialize for AddrV2 { let ip: [u8; ADDR_V2_IPV6_ADDR_SIZE] = ip.octets(); zcash_serialize_bytes(&ip.to_vec(), &mut writer)?; - writer.write_u16::(*port)?; + writer.write_u16::(addr.port())?; } } } else { @@ -313,8 +311,7 @@ impl ZcashDeserialize for AddrV2 { Ok(AddrV2::IpAddr { untrusted_last_seen, untrusted_services, - ip, - port, + addr: canonical_peer_addr(SocketAddr::new(ip, port)), }) } } diff --git a/zebra-network/src/protocol/external/arbitrary.rs b/zebra-network/src/protocol/external/arbitrary.rs index de536928..a8706aa4 100644 --- a/zebra-network/src/protocol/external/arbitrary.rs +++ b/zebra-network/src/protocol/external/arbitrary.rs @@ -1,14 +1,15 @@ -use std::{ - convert::TryInto, - net::{SocketAddr, SocketAddrV6}, -}; +//! Randomised test data generation for external protocol types. + +use std::net::SocketAddr; use proptest::{arbitrary::any, arbitrary::Arbitrary, collection::vec, prelude::*}; use zebra_chain::{block, transaction}; +use crate::PeerSocketAddr; + use super::{ - addr::{canonical_socket_addr, ipv6_mapped_socket_addr}, + addr::canonical_peer_addr, types::{PeerServices, Version}, InventoryHash, Message, }; @@ -124,21 +125,11 @@ impl Arbitrary for Version { type Strategy = BoxedStrategy; } -/// Returns a random canonical Zebra `SocketAddr`. +/// Returns a random canonical Zebra [`PeerSocketAddr`]. /// /// See [`canonical_ip_addr`] for details. /// /// [`canonical_ip_addr`]: super::addr::canonical::canonical_ip_addr -pub fn canonical_socket_addr_strategy() -> impl Strategy { - any::().prop_map(canonical_socket_addr) -} - -/// Returns a random `SocketAddrV6` for use in `addr` (v1) Zcash network -/// messages. -/// -/// See [`canonical_ip_addr`] for details. -/// -/// [`canonical_ip_addr`]: super::addr::canonical::canonical_ip_addr -pub fn addr_v1_ipv6_mapped_socket_addr_strategy() -> impl Strategy { - any::().prop_map(ipv6_mapped_socket_addr) +pub fn canonical_peer_addr_strategy() -> impl Strategy { + any::().prop_map(canonical_peer_addr) } diff --git a/zebra-network/src/protocol/internal/response.rs b/zebra-network/src/protocol/internal/response.rs index eedc40e0..379517bb 100644 --- a/zebra-network/src/protocol/internal/response.rs +++ b/zebra-network/src/protocol/internal/response.rs @@ -32,7 +32,7 @@ pub enum Response { /// /// The list contains `0..=MAX_META_ADDR` peers. // - // TODO: make this into a HashMap - a unique list of peer addresses (#2244) + // TODO: make this into a HashMap - a unique list of peer addresses (#2244) Peers(Vec), /// An ordered list of block hashes. diff --git a/zebra-network/tests/acceptance.rs b/zebra-network/tests/acceptance.rs index c301b900..cb09fd1d 100644 --- a/zebra-network/tests/acceptance.rs +++ b/zebra-network/tests/acceptance.rs @@ -1,7 +1,7 @@ //! Acceptance tests for zebra-network APIs. use std::{ - net::{Ipv4Addr, SocketAddr, SocketAddrV4}, + net::{Ipv4Addr, SocketAddrV4}, sync::Arc, }; @@ -10,14 +10,14 @@ use chrono::Utc; use zebra_chain::block::Height; use zebra_network::{ types::{AddrInVersion, Nonce, PeerServices}, - ConnectedAddr, ConnectionInfo, Version, VersionMessage, + ConnectedAddr, ConnectionInfo, PeerSocketAddr, Version, VersionMessage, }; /// Test that the types used in [`ConnectionInfo`] are public, /// by compiling code that explicitly uses those types. #[test] fn connection_info_types_are_public() { - let fake_addr: SocketAddr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 3).into(); + let fake_addr: PeerSocketAddr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 3).into(); let fake_version = Version(3); let fake_services = PeerServices::default(); diff --git a/zebra-rpc/src/methods/get_block_template_rpcs/types/peer_info.rs b/zebra-rpc/src/methods/get_block_template_rpcs/types/peer_info.rs index 681f5f32..65ae9df6 100644 --- a/zebra-rpc/src/methods/get_block_template_rpcs/types/peer_info.rs +++ b/zebra-rpc/src/methods/get_block_template_rpcs/types/peer_info.rs @@ -1,14 +1,12 @@ //! An array of [`PeerInfo`] is the output of the `getpeerinfo` RPC method. -use std::net::SocketAddr; - -use zebra_network::types::MetaAddr; +use zebra_network::{types::MetaAddr, PeerSocketAddr}; /// Item of the `getpeerinfo` response #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct PeerInfo { /// The IP address and port of the peer - pub addr: SocketAddr, + pub addr: PeerSocketAddr, } impl From for PeerInfo { diff --git a/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs b/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs index 9ae6d70f..5f7e0476 100644 --- a/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs +++ b/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs @@ -125,13 +125,15 @@ pub async fn test_responses( mock_chain_tip_sender.send_best_tip_hash(fake_tip_hash); mock_chain_tip_sender.send_estimated_distance_to_network_chain_tip(Some(0)); - let mock_address_book = - MockAddressBookPeers::new(vec![MetaAddr::new_initial_peer(SocketAddr::new( + let mock_address_book = MockAddressBookPeers::new(vec![MetaAddr::new_initial_peer( + SocketAddr::new( IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), network.default_port(), - )) - .into_new_meta_addr() - .unwrap()]); + ) + .into(), + ) + .into_new_meta_addr() + .unwrap()]); // get an rpc instance with continuous blockchain state let get_block_template_rpc = GetBlockTemplateRpcImpl::new( diff --git a/zebra-rpc/src/methods/tests/vectors.rs b/zebra-rpc/src/methods/tests/vectors.rs index eb495918..02ccd9bc 100644 --- a/zebra-rpc/src/methods/tests/vectors.rs +++ b/zebra-rpc/src/methods/tests/vectors.rs @@ -944,13 +944,15 @@ async fn rpc_getpeerinfo() { ) .await; - let mock_peer_address = - zebra_network::types::MetaAddr::new_initial_peer(std::net::SocketAddr::new( + let mock_peer_address = zebra_network::types::MetaAddr::new_initial_peer( + std::net::SocketAddr::new( std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1)), network.default_port(), - )) - .into_new_meta_addr() - .unwrap(); + ) + .into(), + ) + .into_new_meta_addr() + .unwrap(); let mock_address_book = MockAddressBookPeers::new(vec![mock_peer_address]); diff --git a/zebrad/src/components/inbound/tests/real_peer_set.rs b/zebrad/src/components/inbound/tests/real_peer_set.rs index 6e176cf3..6f9df6aa 100644 --- a/zebrad/src/components/inbound/tests/real_peer_set.rs +++ b/zebrad/src/components/inbound/tests/real_peer_set.rs @@ -20,8 +20,8 @@ use zebra_chain::{ }; use zebra_consensus::{chain::VerifyChainError, error::TransactionError, transaction}; use zebra_network::{ - connect_isolated_tcp_direct_with_inbound, types::InventoryHash, Config as NetworkConfig, - InventoryResponse, PeerError, Request, Response, SharedPeerError, + canonical_peer_addr, connect_isolated_tcp_direct_with_inbound, types::InventoryHash, + Config as NetworkConfig, InventoryResponse, PeerError, Request, Response, SharedPeerError, }; use zebra_node_services::mempool; use zebra_state::Config as StateConfig; @@ -67,7 +67,10 @@ async fn inbound_peers_empty_address_book() -> Result<(), crate::BoxError> { let response = request.await; match response.as_ref() { Ok(Response::Peers(single_peer)) if single_peer.len() == 1 => { - assert_eq!(single_peer.first().unwrap().addr(), listen_addr) + assert_eq!( + single_peer.first().unwrap().addr(), + canonical_peer_addr(listen_addr) + ) } Ok(Response::Peers(_peer_list)) => unreachable!( "`Peers` response should contain a single peer, \ @@ -86,7 +89,10 @@ async fn inbound_peers_empty_address_book() -> Result<(), crate::BoxError> { let response = request.await; match response.as_ref() { Ok(Response::Peers(single_peer)) if single_peer.len() == 1 => { - assert_eq!(single_peer.first().unwrap().addr(), listen_addr) + assert_eq!( + single_peer.first().unwrap().addr(), + canonical_peer_addr(listen_addr) + ) } Ok(Response::Peers(_peer_list)) => unreachable!( "`Peers` response should contain a single peer, \ @@ -653,11 +659,8 @@ async fn setup( .await; // Inbound listener - let listen_addr = address_book - .lock() - .unwrap() - .local_listener_meta_addr() - .addr(); + let listen_addr = address_book.lock().unwrap().local_listener_socket_addr(); + assert_ne!( listen_addr.port(), 0,