Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 11 additions & 12 deletions core/src/repair/serve_repair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub const MAX_ANCESTOR_RESPONSES: usize =
const REPAIR_PING_TOKEN_SIZE: usize = HASH_BYTES;
pub const REPAIR_PING_CACHE_CAPACITY: usize = 65536;
pub const REPAIR_PING_CACHE_TTL: Duration = Duration::from_secs(1280);
const REPAIR_PING_CACHE_RATE_LIMIT_DELAY: Duration = Duration::from_secs(2);
const REPAIR_PING_CACHE_OUTSTANDING_PING_TIMEOUT: Duration = Duration::from_secs(2);
pub(crate) const REPAIR_RESPONSE_SERIALIZED_PING_BYTES: usize =
4 /*enum discriminator*/ + PUBKEY_BYTES + REPAIR_PING_TOKEN_SIZE + SIGNATURE_BYTES;
const SIGNED_REPAIR_TIME_WINDOW: Duration = Duration::from_secs(60 * 10); // 10 min
Expand Down Expand Up @@ -1338,12 +1338,12 @@ impl ServeRepair {
) -> JoinHandle<()> {
const MAX_BYTES_PER_SECOND: u64 = 12_000_000;

// rate limit delay should be greater than the repair request iteration delay
assert!(REPAIR_PING_CACHE_RATE_LIMIT_DELAY > Duration::from_millis(REPAIR_MS));
// ping timeout should be greater than the repair request iteration delay
assert!(REPAIR_PING_CACHE_OUTSTANDING_PING_TIMEOUT > Duration::from_millis(REPAIR_MS));

let mut ping_cache = PingCache::new(
REPAIR_PING_CACHE_TTL,
REPAIR_PING_CACHE_RATE_LIMIT_DELAY,
REPAIR_PING_CACHE_OUTSTANDING_PING_TIMEOUT,
REPAIR_PING_CACHE_CAPACITY,
);

Expand Down Expand Up @@ -2003,7 +2003,7 @@ mod tests {
let from_addr = socketaddr!(Ipv4Addr::LOCALHOST, 1234);
let mut ping_cache = PingCache::new(
REPAIR_PING_CACHE_TTL,
REPAIR_PING_CACHE_RATE_LIMIT_DELAY,
REPAIR_PING_CACHE_OUTSTANDING_PING_TIMEOUT,
REPAIR_PING_CACHE_CAPACITY,
);
let slot = 42;
Expand Down Expand Up @@ -3176,33 +3176,32 @@ mod tests {
assert!(!repair.verify_response(&AncestorHashesResponse::Hashes(response)));
}

// A second check() within REPAIR_PING_CACHE_RATE_LIMIT_DELAY must not generate
// A second check() within REPAIR_PING_CACHE_OUTSTANDING_PING_TIMEOUT must not generate
// a new ping. If it did, it would overwrite the stored token and invalidate the Pong,
// making Ping fail for no reason.
#[test]
fn test_repair_no_ping_overwrite_within_rate_limit_delay() {
fn test_repair_no_ping_overwrite_while_already_probing() {
let mut rng = rand::rng();
let this_node = Keypair::new();
let remote_socket = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 8001));
let remote_keypair = Keypair::new();
let remote_node = (remote_keypair.pubkey(), remote_socket);
let mut cache = PingCache::new(
REPAIR_PING_CACHE_TTL,
REPAIR_PING_CACHE_RATE_LIMIT_DELAY,
REPAIR_PING_CACHE_OUTSTANDING_PING_TIMEOUT,
REPAIR_PING_CACHE_CAPACITY,
);
let now = Instant::now();

let (_, ping1) = cache.check(&mut rng, &this_node, now, remote_node);
let ping1 = ping1.expect("should generate ping for unknown node");

// Second check within REPAIR_PING_CACHE_RATE_LIMIT_DELAY must not generate
// a new ping — that would overwrite the stored hash and invalidate the in-flight pong.
let within_delay = now + REPAIR_PING_CACHE_RATE_LIMIT_DELAY - Duration::from_millis(1);
let within_delay =
now + REPAIR_PING_CACHE_OUTSTANDING_PING_TIMEOUT - Duration::from_millis(1);
let (_, ping2) = cache.check(&mut rng, &this_node, within_delay, remote_node);
assert!(
ping2.is_none(),
"must not generate a second ping within REPAIR_PING_CACHE_RATE_LIMIT_DELAY"
"must not generate a second ping within REPAIR_PING_CACHE_OUTSTANDING_PING_TIMEOUT"
);

// Pong for ping1 must still be valid — token was not overwritten.
Expand Down
7 changes: 4 additions & 3 deletions gossip/src/cluster_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,9 @@ const CHANNEL_CONSUME_CAPACITY: usize = 1024;
/// of `MAX_GOSSIP_TRAFFIC` (103,896).
pub(crate) const GOSSIP_CHANNEL_CAPACITY: usize = 4096; // 2^12
const GOSSIP_PING_CACHE_CAPACITY: usize = 126976;
const GOSSIP_PING_CACHE_TTL: Duration = Duration::from_secs(1280);
const GOSSIP_PING_CACHE_RATE_LIMIT_DELAY: Duration = Duration::from_secs(1280 / 64);
pub(crate) const GOSSIP_PING_CACHE_TTL: Duration = Duration::from_secs(1280);
// max amount of time we wait for a Pong before pinging again
pub(crate) const GOSSIP_PING_CACHE_OUTSTANDING_PING_TIMEOUT: Duration = Duration::from_secs(2);
pub const DEFAULT_CONTACT_DEBUG_INTERVAL_MILLIS: u64 = 10_000;
pub const DEFAULT_CONTACT_SAVE_INTERVAL_MILLIS: u64 = 60_000;
// Limit number of unique pubkeys in the crds table.
Expand Down Expand Up @@ -188,7 +189,7 @@ impl ClusterInfo {
my_contact_info: RwLock::new(contact_info),
ping_cache: Mutex::new(PingCache::new(
GOSSIP_PING_CACHE_TTL,
GOSSIP_PING_CACHE_RATE_LIMIT_DELAY,
GOSSIP_PING_CACHE_OUTSTANDING_PING_TIMEOUT,
GOSSIP_PING_CACHE_CAPACITY,
)),
stats: GossipStats::default(),
Expand Down
13 changes: 9 additions & 4 deletions gossip/src/crds_gossip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,12 @@ pub(crate) fn maybe_ping_gossip_addresses<R: Rng + CryptoRng>(
#[cfg(test)]
mod test {
use {
super::*, crate::contact_info::ContactInfo, solana_sha256_hasher::hash,
super::*,
crate::{
cluster_info::{GOSSIP_PING_CACHE_OUTSTANDING_PING_TIMEOUT, GOSSIP_PING_CACHE_TTL},
contact_info::ContactInfo,
},
solana_sha256_hasher::hash,
solana_time_utils::timestamp,
};

Expand All @@ -414,9 +419,9 @@ mod test {
)
.unwrap();
let ping_cache = PingCache::new(
Duration::from_secs(20 * 60), // ttl
Duration::from_secs(20 * 60) / 64, // rate_limit_delay
128, // capacity
GOSSIP_PING_CACHE_TTL,
GOSSIP_PING_CACHE_OUTSTANDING_PING_TIMEOUT,
128, // capacity (small for tests)
);
let ping_cache = Mutex::new(ping_cache);
crds_gossip.refresh_push_active_set(
Expand Down
12 changes: 8 additions & 4 deletions gossip/src/crds_gossip_pull.rs
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,11 @@ pub(crate) fn get_max_bloom_filter_bytes(caller: &CrdsValue) -> usize {
pub(crate) mod tests {
use {
super::*,
crate::{crds_data::CrdsData, protocol::Protocol},
crate::{
cluster_info::{GOSSIP_PING_CACHE_OUTSTANDING_PING_TIMEOUT, GOSSIP_PING_CACHE_TTL},
crds_data::CrdsData,
protocol::Protocol,
},
itertools::Itertools,
rand::{SeedableRng, prelude::IndexedRandom as _},
rand_chacha::ChaChaRng,
Expand Down Expand Up @@ -730,9 +734,9 @@ pub(crate) mod tests {

fn new_ping_cache() -> PingCache {
PingCache::new(
Duration::from_secs(20 * 60), // ttl
Duration::from_secs(20 * 60) / 64, // rate_limit_delay
128, // capacity
GOSSIP_PING_CACHE_TTL,
GOSSIP_PING_CACHE_OUTSTANDING_PING_TIMEOUT,
128, // capacity (small for tests)
)
}

Expand Down
14 changes: 9 additions & 5 deletions gossip/src/crds_gossip_push.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,15 +288,19 @@ impl CrdsGossipPush {
mod tests {
use {
super::*,
crate::{contact_info::ContactInfo, crds_data::CrdsData},
std::time::{Duration, Instant},
crate::{
cluster_info::{GOSSIP_PING_CACHE_OUTSTANDING_PING_TIMEOUT, GOSSIP_PING_CACHE_TTL},
contact_info::ContactInfo,
crds_data::CrdsData,
},
std::time::Instant,
};

fn new_ping_cache() -> PingCache {
PingCache::new(
Duration::from_secs(20 * 60), // ttl
Duration::from_secs(20 * 60) / 64, // rate_limit_delay
128, // capacity
GOSSIP_PING_CACHE_TTL,
GOSSIP_PING_CACHE_OUTSTANDING_PING_TIMEOUT,
128, // capacity (small for tests)
)
}

Expand Down
Loading