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>
This commit is contained in:
parent
989c5979fb
commit
b0d9471214
|
@ -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<SocketAddr, MetaAddr, Reverse<MetaAddr>>,
|
||||
by_addr: OrderedMap<PeerSocketAddr, MetaAddr, Reverse<MetaAddr>>,
|
||||
|
||||
/// 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<Utc>) -> Vec<MetaAddr> {
|
||||
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<MetaAddr> {
|
||||
let addr = canonical_socket_addr(*addr);
|
||||
pub fn get(&mut self, addr: PeerSocketAddr) -> Option<MetaAddr> {
|
||||
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<MetaAddr> {
|
||||
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<MetaAddr> {
|
||||
fn take(&mut self, removed_addr: PeerSocketAddr) -> Option<MetaAddr> {
|
||||
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();
|
||||
|
|
|
@ -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<SocketAddr> {
|
||||
pub async fn initial_peers(&self) -> HashSet<PeerSocketAddr> {
|
||||
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<String>) -> HashSet<SocketAddr> {
|
||||
async fn resolve_peers(peers: &HashSet<String>) -> HashSet<PeerSocketAddr> {
|
||||
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<SocketAddr> {
|
||||
async fn resolve_host(host: &str, max_retries: usize) -> HashSet<PeerSocketAddr> {
|
||||
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<HashSet<SocketAddr>, BoxError> {
|
||||
async fn resolve_host_once(host: &str) -> Result<HashSet<PeerSocketAddr>, 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<SocketAddr> = ip_addrs.map(canonical_socket_addr).collect();
|
||||
let ip_addrs: Vec<PeerSocketAddr> = 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
|
||||
|
|
|
@ -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<PeerSocketAddr>,
|
||||
user_agent: String,
|
||||
) -> impl Future<Output = Result<Client, BoxError>> {
|
||||
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<InboundService>(
|
||||
network: Network,
|
||||
addr: SocketAddr,
|
||||
addr: impl Into<PeerSocketAddr>,
|
||||
user_agent: String,
|
||||
inbound_service: InboundService,
|
||||
) -> impl Future<Output = Result<Client, BoxError>>
|
||||
|
@ -155,7 +155,9 @@ where
|
|||
Service<Request, Response = Response, Error = BoxError> + 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)
|
||||
|
|
|
@ -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<PeerTransport>(
|
|||
//
|
||||
// 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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<PeerServices>,
|
||||
},
|
||||
}
|
||||
|
@ -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<PeerSocketAddr>) -> 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<Option<PeerServices>>,
|
||||
) -> 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<Option<PeerServices>>,
|
||||
) -> 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, &'static str> {
|
||||
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, .. }
|
||||
|
|
|
@ -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<Self> {
|
||||
(
|
||||
canonical_socket_addr_strategy(),
|
||||
canonical_peer_addr_strategy(),
|
||||
any::<PeerServices>(),
|
||||
any::<DateTime32>(),
|
||||
)
|
||||
|
@ -51,9 +49,9 @@ impl MetaAddr {
|
|||
///
|
||||
/// [1]: super::PeerAddrState::NeverAttemptedAlternate
|
||||
pub fn alternate_strategy() -> BoxedStrategy<Self> {
|
||||
(canonical_socket_addr_strategy(), any::<PeerServices>())
|
||||
(canonical_peer_addr_strategy(), any::<PeerServices>())
|
||||
.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<Self> {
|
||||
/// `addr` is typically generated by the `canonical_peer_addr` strategy.
|
||||
pub fn addr_strategy(addr: PeerSocketAddr) -> BoxedStrategy<Self> {
|
||||
any::<MetaAddrChange>()
|
||||
.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<MetaAddrChange>)> {
|
||||
|
@ -101,12 +98,12 @@ impl MetaAddrChange {
|
|||
///
|
||||
/// [1]: super::NewAlternate
|
||||
pub fn ready_outbound_strategy() -> BoxedStrategy<Self> {
|
||||
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")
|
||||
|
|
|
@ -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 = <SocketAddr as FromStr>::Err;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(Self(s.parse()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<S> for PeerSocketAddr
|
||||
where
|
||||
S: Into<SocketAddr>,
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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<SocketAddr, u32> = HashMap::new();
|
||||
let mut attempt_counts: HashMap<PeerSocketAddr, u32> = HashMap::new();
|
||||
|
||||
// The most recent address info for each peer
|
||||
let mut addrs: HashMap<SocketAddr, MetaAddr> = HashMap::new();
|
||||
let mut addrs: HashMap<PeerSocketAddr, MetaAddr> = 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");
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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<SocketAddr>,
|
||||
pub transient_addr: Option<PeerSocketAddr>,
|
||||
|
||||
/// 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<InventoryChange>,
|
||||
|
||||
/// 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<Result<Response, SharedPeerError>>,
|
||||
request: &Request,
|
||||
inv_collector: Option<broadcast::Sender<InventoryChange>>,
|
||||
transient_addr: Option<SocketAddr>,
|
||||
transient_addr: Option<PeerSocketAddr>,
|
||||
) -> Self {
|
||||
Self {
|
||||
tx: Some(tx),
|
||||
|
@ -341,7 +340,7 @@ impl MissingInventoryCollector {
|
|||
pub fn new(
|
||||
request: &Request,
|
||||
inv_collector: Option<broadcast::Sender<InventoryChange>>,
|
||||
transient_addr: Option<SocketAddr>,
|
||||
transient_addr: Option<PeerSocketAddr>,
|
||||
) -> Option<Box<MissingInventoryCollector>> {
|
||||
if !request.is_inventory_download() {
|
||||
return None;
|
||||
|
|
|
@ -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<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + 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::<TcpStream> {
|
||||
data_stream: tcp_stream,
|
||||
|
|
|
@ -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<SocketAddr> {
|
||||
pub fn get_address_book_addr(&self) -> Option<PeerSocketAddr> {
|
||||
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<SocketAddr> {
|
||||
pub fn get_transient_addr(&self) -> Option<PeerSocketAddr> {
|
||||
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<Item = SocketAddr> {
|
||||
mut canonical_remote: PeerSocketAddr,
|
||||
) -> impl Iterator<Item = PeerSocketAddr> {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<PeerSocketAddr>,
|
||||
network: impl Into<Option<Network>>,
|
||||
) -> Result<PeerPreference, &'static str> {
|
||||
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<Option<Network>>,
|
||||
) -> 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<Option<Network>>,
|
||||
) -> Result<(), &'static str> {
|
||||
// TODO: make private IP addresses an error unless a debug config is set (#3117)
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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<Item = DateTime<Utc>>)
|
|||
.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,
|
||||
)
|
||||
|
|
|
@ -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<S>(
|
|||
address_book_updater: tokio::sync::mpsc::Sender<MetaAddrChange>,
|
||||
) -> Result<ActiveConnectionCounter, BoxError>
|
||||
where
|
||||
S: Service<OutboundConnectorRequest, Response = (SocketAddr, peer::Client), Error = BoxError>
|
||||
+ 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<MetaAddrChange>,
|
||||
) -> HashSet<SocketAddr> {
|
||||
let all_peers: HashSet<SocketAddr> = config.initial_peers().await;
|
||||
let mut preferred_peers: BTreeMap<PeerPreference, Vec<SocketAddr>> = BTreeMap::new();
|
||||
) -> HashSet<PeerSocketAddr> {
|
||||
let all_peers: HashSet<PeerSocketAddr> = config.initial_peers().await;
|
||||
let mut preferred_peers: BTreeMap<PeerPreference, Vec<PeerSocketAddr>> = 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<SocketAddr> = HashSet::new();
|
||||
let mut initial_peers: HashSet<PeerSocketAddr> = 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<C, S>(
|
|||
mut active_outbound_connections: ActiveConnectionCounter,
|
||||
) -> Result<(), BoxError>
|
||||
where
|
||||
C: Service<OutboundConnectorRequest, Response = (SocketAddr, peer::Client), Error = BoxError>
|
||||
+ Clone
|
||||
C: Service<
|
||||
OutboundConnectorRequest,
|
||||
Response = (PeerSocketAddr, peer::Client),
|
||||
Error = BoxError,
|
||||
> + Clone
|
||||
+ Send
|
||||
+ 'static,
|
||||
C::Future: Send + 'static,
|
||||
|
@ -865,8 +873,11 @@ async fn dial<C>(
|
|||
outbound_connection_tracker: ConnectionTracker,
|
||||
) -> CrawlerAction
|
||||
where
|
||||
C: Service<OutboundConnectorRequest, Response = (SocketAddr, peer::Client), Error = BoxError>
|
||||
+ 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<Result<(SocketAddr, peer::Client), (MetaAddr, BoxError)>> for CrawlerAction {
|
||||
fn from(dial_result: Result<(SocketAddr, peer::Client), (MetaAddr, BoxError)>) -> Self {
|
||||
impl From<Result<(PeerSocketAddr, peer::Client), (MetaAddr, BoxError)>> for CrawlerAction {
|
||||
fn from(dial_result: Result<(PeerSocketAddr, peer::Client), (MetaAddr, BoxError)>) -> Self {
|
||||
use CrawlerAction::*;
|
||||
match dial_result {
|
||||
Ok((address, client)) => HandshakeConnected { address, client },
|
||||
|
|
|
@ -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<C>(
|
|||
outbound_connector: C,
|
||||
) -> (Config, mpsc::Receiver<DiscoveredPeer>)
|
||||
where
|
||||
C: Service<OutboundConnectorRequest, Response = (SocketAddr, peer::Client), Error = BoxError>
|
||||
+ 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<C>(
|
|||
JoinHandle<Result<(), BoxError>>,
|
||||
)
|
||||
where
|
||||
C: Service<OutboundConnectorRequest, Response = (SocketAddr, peer::Client), Error = BoxError>
|
||||
+ Clone
|
||||
C: Service<
|
||||
OutboundConnectorRequest,
|
||||
Response = (PeerSocketAddr, peer::Client),
|
||||
Error = BoxError,
|
||||
> + Clone
|
||||
+ Send
|
||||
+ 'static,
|
||||
C::Future: Send + 'static,
|
||||
|
|
|
@ -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<T> = InventoryResponse<T, T>;
|
|||
///
|
||||
/// 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<InventoryHash>, SocketAddr)>;
|
||||
pub type InventoryChange = InventoryStatus<(AtLeastOne<InventoryHash>, 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<InventoryHash, IndexMap<SocketAddr, InventoryMarker>>,
|
||||
current: IndexMap<InventoryHash, IndexMap<PeerSocketAddr, InventoryMarker>>,
|
||||
|
||||
/// Map tracking inventory statuses from the previous interval period.
|
||||
prev: IndexMap<InventoryHash, IndexMap<SocketAddr, InventoryMarker>>,
|
||||
prev: IndexMap<InventoryHash, IndexMap<PeerSocketAddr, InventoryMarker>>,
|
||||
|
||||
/// 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<Item = &'a InventoryHash>,
|
||||
peer: SocketAddr,
|
||||
peer: PeerSocketAddr,
|
||||
) -> Option<Self> {
|
||||
let mut hashes: Vec<InventoryHash> = 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<Item = &'a InventoryHash>,
|
||||
peer: SocketAddr,
|
||||
peer: PeerSocketAddr,
|
||||
) -> Option<Self> {
|
||||
let mut hashes: Vec<InventoryHash> = 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<Item = &SocketAddr> {
|
||||
pub fn advertising_peers(&self, hash: InventoryHash) -> impl Iterator<Item = &PeerSocketAddr> {
|
||||
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<Item = &SocketAddr> {
|
||||
pub fn missing_peers(&self, hash: InventoryHash) -> impl Iterator<Item = &PeerSocketAddr> {
|
||||
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<Item = InventoryStatus<&SocketAddr>> {
|
||||
) -> impl Iterator<Item = InventoryStatus<&PeerSocketAddr>> {
|
||||
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<Item = (&InventoryHash, &IndexMap<SocketAddr, InventoryMarker>)> {
|
||||
) -> impl Iterator<Item = (&InventoryHash, &IndexMap<PeerSocketAddr, InventoryMarker>)> {
|
||||
self.current.iter().chain(self.prev.iter())
|
||||
}
|
||||
|
||||
|
|
|
@ -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<InventoryHash>,
|
||||
) {
|
||||
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);
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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<D, C>
|
||||
where
|
||||
D: Discover<Key = SocketAddr, Service = LoadTrackedClient> + Unpin,
|
||||
D: Discover<Key = PeerSocketAddr, Service = LoadTrackedClient> + Unpin,
|
||||
D::Error: Into<BoxError>,
|
||||
C: ChainTip,
|
||||
{
|
||||
|
@ -252,7 +251,7 @@ where
|
|||
|
||||
impl<D, C> Drop for PeerSet<D, C>
|
||||
where
|
||||
D: Discover<Key = SocketAddr, Service = LoadTrackedClient> + Unpin,
|
||||
D: Discover<Key = PeerSocketAddr, Service = LoadTrackedClient> + Unpin,
|
||||
D::Error: Into<BoxError>,
|
||||
C: ChainTip,
|
||||
{
|
||||
|
@ -263,7 +262,7 @@ where
|
|||
|
||||
impl<D, C> PeerSet<D, C>
|
||||
where
|
||||
D: Discover<Key = SocketAddr, Service = LoadTrackedClient> + Unpin,
|
||||
D: Discover<Key = PeerSocketAddr, Service = LoadTrackedClient> + Unpin,
|
||||
D::Error: Into<BoxError>,
|
||||
C: ChainTip,
|
||||
{
|
||||
|
@ -711,7 +710,7 @@ where
|
|||
return fut.map_err(Into::into).boxed();
|
||||
}
|
||||
|
||||
let missing_peer_list: HashSet<SocketAddr> = self
|
||||
let missing_peer_list: HashSet<PeerSocketAddr> = self
|
||||
.inventory_registry
|
||||
.missing_peers(hash)
|
||||
.copied()
|
||||
|
@ -883,7 +882,7 @@ where
|
|||
|
||||
impl<D, C> Service<Request> for PeerSet<D, C>
|
||||
where
|
||||
D: Discover<Key = SocketAddr, Service = LoadTrackedClient> + Unpin,
|
||||
D: Discover<Key = PeerSocketAddr, Service = LoadTrackedClient> + Unpin,
|
||||
D::Error: Into<BoxError>,
|
||||
C: ChainTip,
|
||||
{
|
||||
|
|
|
@ -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<Item = Result<Change<SocketAddr, LoadTrackedClient>, BoxError>>,
|
||||
impl Stream<Item = Result<Change<PeerSocketAddr, LoadTrackedClient>, BoxError>>,
|
||||
Vec<ClientTestHarness>,
|
||||
) {
|
||||
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<D, C> PeerSetBuilder<D, C> {
|
|||
|
||||
impl<D, C> PeerSetBuilder<D, C>
|
||||
where
|
||||
D: Discover<Key = SocketAddr, Service = LoadTrackedClient> + Unpin,
|
||||
D: Discover<Key = PeerSocketAddr, Service = LoadTrackedClient> + Unpin,
|
||||
D::Error: Into<BoxError>,
|
||||
C: ChainTip,
|
||||
{
|
||||
|
|
|
@ -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<D, C>(
|
|||
minimum_version: Version,
|
||||
) -> Result<usize, TestCaseError>
|
||||
where
|
||||
D: Discover<Key = SocketAddr, Service = LoadTrackedClient> + Unpin,
|
||||
D: Discover<Key = PeerSocketAddr, Service = LoadTrackedClient> + Unpin,
|
||||
D::Error: Into<BoxError>,
|
||||
C: ChainTip,
|
||||
{
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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>) -> SocketAddr {
|
||||
use SocketAddr::*;
|
||||
|
@ -42,3 +45,13 @@ pub fn canonical_socket_addr(socket_addr: impl Into<SocketAddr>) -> 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>) -> PeerSocketAddr {
|
||||
let peer_socket_addr = peer_socket_addr.into();
|
||||
|
||||
canonical_socket_addr(*peer_socket_addr).into()
|
||||
}
|
||||
|
|
|
@ -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<SocketAddr>, untrusted_services: PeerServices) -> Self {
|
||||
pub fn new(socket_addr: impl Into<PeerSocketAddr>, 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<W: Write>(&self, mut writer: W) -> Result<(), std::io::Error> {
|
||||
writer.write_u64::<LittleEndian>(self.untrusted_services.bits())?;
|
||||
|
||||
self.ipv6_addr.ip().zcash_serialize(&mut writer)?;
|
||||
writer.write_u16::<BigEndian>(self.ipv6_addr.port())?;
|
||||
let ipv6_addr = ipv6_mapped_ip_addr(self.addr.ip());
|
||||
ipv6_addr.zcash_serialize(&mut writer)?;
|
||||
writer.write_u16::<BigEndian>(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,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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<MetaAddr> 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<MetaAddr> for AddrV1 {
|
|||
AddrV1 {
|
||||
untrusted_last_seen,
|
||||
untrusted_services,
|
||||
ipv6_addr,
|
||||
addr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +91,7 @@ impl From<MetaAddr> for AddrV1 {
|
|||
impl From<AddrV1> 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::<LittleEndian>(self.untrusted_services.bits())?;
|
||||
|
||||
self.ipv6_addr.ip().zcash_serialize(&mut writer)?;
|
||||
writer.write_u16::<BigEndian>(self.ipv6_addr.port())?;
|
||||
let ipv6_addr = ipv6_mapped_ip_addr(self.addr.ip());
|
||||
ipv6_addr.zcash_serialize(&mut writer)?;
|
||||
writer.write_u16::<BigEndian>(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<SocketAddr>,
|
||||
) -> 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)
|
||||
}
|
||||
|
|
|
@ -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<MetaAddr> 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<AddrV2> 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::<BigEndian>(*port)?;
|
||||
writer.write_u16::<BigEndian>(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::<BigEndian>(*port)?;
|
||||
writer.write_u16::<BigEndian>(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)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Self>;
|
||||
}
|
||||
|
||||
/// 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<Value = SocketAddr> {
|
||||
any::<SocketAddr>().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<Value = SocketAddrV6> {
|
||||
any::<SocketAddr>().prop_map(ipv6_mapped_socket_addr)
|
||||
pub fn canonical_peer_addr_strategy() -> impl Strategy<Value = PeerSocketAddr> {
|
||||
any::<SocketAddr>().prop_map(canonical_peer_addr)
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ pub enum Response {
|
|||
///
|
||||
/// The list contains `0..=MAX_META_ADDR` peers.
|
||||
//
|
||||
// TODO: make this into a HashMap<SocketAddr, MetaAddr> - a unique list of peer addresses (#2244)
|
||||
// TODO: make this into a HashMap<PeerSocketAddr, MetaAddr> - a unique list of peer addresses (#2244)
|
||||
Peers(Vec<MetaAddr>),
|
||||
|
||||
/// An ordered list of block hashes.
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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<MetaAddr> for PeerInfo {
|
||||
|
|
|
@ -125,13 +125,15 @@ pub async fn test_responses<State, ReadState>(
|
|||
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(
|
||||
|
|
|
@ -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]);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue