94 lines
3.5 KiB
Rust
94 lines
3.5 KiB
Rust
//! Shared test checks for MetaAddr
|
|
|
|
use std::net::SocketAddr;
|
|
|
|
use super::super::MetaAddr;
|
|
|
|
use crate::{constants::TIMESTAMP_TRUNCATION_SECONDS, types::PeerServices};
|
|
|
|
/// Check that:
|
|
/// - the only times that are included in serialized `MetaAddr`s are the last
|
|
/// responded time, and the untrusted last seen time, and
|
|
/// - `sanitized_addr` has less time and state metadata than `original_addr`.
|
|
///
|
|
/// Also checks that the time hasn't changed too much.
|
|
pub(crate) fn sanitize_avoids_leaks(original: &MetaAddr, sanitized: &MetaAddr) {
|
|
// check that irrelevant times are cleared by sanitization
|
|
assert_eq!(sanitized.last_attempt, None);
|
|
assert_eq!(sanitized.last_failure, None);
|
|
|
|
// check that the last seen and responded times end up in the untrusted field
|
|
// (but ignore their values for now - those checks are next)
|
|
assert_eq!(sanitized.last_response, None);
|
|
assert_eq!(
|
|
sanitized.untrusted_last_seen.is_some(),
|
|
original
|
|
.last_response
|
|
.or(original.untrusted_last_seen)
|
|
.is_some()
|
|
);
|
|
// Check the responded field overrides the untrusted field
|
|
assert_eq!(
|
|
original.last_seen(),
|
|
original.last_response.or(original.untrusted_last_seen)
|
|
);
|
|
|
|
// check for time truncation
|
|
if let Some(sanitized_last_seen) = sanitized.last_seen() {
|
|
// We want the sanitized timestamp to:
|
|
// - be a multiple of the truncation interval,
|
|
// - have a zero nanoseconds component, and
|
|
// - be within the truncation interval of the original timestamp.
|
|
assert_eq!(
|
|
sanitized_last_seen.timestamp() % TIMESTAMP_TRUNCATION_SECONDS,
|
|
0
|
|
);
|
|
|
|
// check that the times haven't changed too much
|
|
let original_last_seen = original
|
|
.last_seen()
|
|
.expect("unexpected missing original last seen when sanitized last seen is Some");
|
|
|
|
// handle underflow and overflow by skipping the check
|
|
// the other check will ensure correctness
|
|
let lowest_time = original_last_seen
|
|
.timestamp()
|
|
.checked_sub(TIMESTAMP_TRUNCATION_SECONDS);
|
|
let highest_time = original_last_seen
|
|
.timestamp()
|
|
.checked_add(TIMESTAMP_TRUNCATION_SECONDS);
|
|
if let Some(lowest_time) = lowest_time {
|
|
assert!(sanitized_last_seen.timestamp() > lowest_time);
|
|
}
|
|
if let Some(highest_time) = highest_time {
|
|
assert!(sanitized_last_seen.timestamp() < highest_time);
|
|
}
|
|
}
|
|
|
|
// check the other fields
|
|
|
|
// Sanitize to the the default state, even though it's not serialized
|
|
assert_eq!(sanitized.last_connection_state, Default::default());
|
|
// Sanitize to known flags
|
|
let sanitized_peer_services = original.services & PeerServices::all();
|
|
assert_eq!(sanitized.services, sanitized_peer_services);
|
|
|
|
// Remove IPv6 scope ID and flow information
|
|
let sanitized_socket_addr = SocketAddr::new(original.addr.ip(), original.addr.port());
|
|
assert_eq!(sanitized.addr.ip(), original.addr.ip());
|
|
assert_eq!(sanitized.addr.port(), original.addr.port());
|
|
assert_eq!(sanitized.addr, sanitized_socket_addr);
|
|
|
|
// We want any other fields to be their defaults
|
|
assert_eq!(
|
|
sanitized,
|
|
&MetaAddr::new_gossiped_meta_addr(
|
|
sanitized_socket_addr,
|
|
sanitized_peer_services,
|
|
sanitized
|
|
.last_seen()
|
|
.expect("unexpected missing last seen time in sanitized MetaAddr")
|
|
),
|
|
);
|
|
}
|