Skip to content

Commit 4c21ac9

Browse files
more aggressive deprecated CRDS filter (solana-labs#6048)
* more aggressive deprecated CRDS filter Also split off into separate file as we are not backporting this. --------- Co-authored-by: Greg Cusack <[email protected]>
1 parent c16dcb3 commit 4c21ac9

File tree

3 files changed

+79
-49
lines changed

3 files changed

+79
-49
lines changed

gossip/src/cluster_info.rs

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use {
1919
contact_info::{self, ContactInfo, ContactInfoQuery, Error as ContactInfoError},
2020
crds::{Crds, Cursor, GossipRoute},
2121
crds_data::{self, CrdsData, EpochSlotsIndex, LowestSlot, SnapshotHashes, Vote, MAX_VOTES},
22+
crds_filter::{should_retain_crds_value, GossipFilterDirection, MIN_STAKE_FOR_GOSSIP},
2223
crds_gossip::CrdsGossip,
2324
crds_gossip_error::CrdsGossipError,
2425
crds_gossip_pull::{
@@ -133,11 +134,6 @@ pub const DEFAULT_CONTACT_DEBUG_INTERVAL_MILLIS: u64 = 10_000;
133134
pub const DEFAULT_CONTACT_SAVE_INTERVAL_MILLIS: u64 = 60_000;
134135
// Limit number of unique pubkeys in the crds table.
135136
pub(crate) const CRDS_UNIQUE_PUBKEY_CAPACITY: usize = 8192;
136-
/// Minimum stake that a node should have so that its CRDS values are
137-
/// propagated through gossip (few types are exempted).
138-
const MIN_STAKE_FOR_GOSSIP: u64 = solana_native_token::LAMPORTS_PER_SOL;
139-
/// Minimum number of staked nodes for enforcing stakes in gossip.
140-
const MIN_NUM_STAKED_NODES: usize = 500;
141137

142138
// Must have at least one socket to monitor the TVU port
143139
pub const MINIMUM_NUM_TVU_RECEIVE_SOCKETS: NonZeroUsize = NonZeroUsize::new(1).unwrap();
@@ -177,42 +173,6 @@ pub struct ClusterInfo {
177173
socket_addr_space: SocketAddrSpace,
178174
}
179175

180-
// Returns false if the CRDS value should be discarded.
181-
#[inline]
182-
#[must_use]
183-
fn should_retain_crds_value(
184-
value: &CrdsValue,
185-
stakes: &HashMap<Pubkey, u64>,
186-
drop_unstaked_node_instance: bool,
187-
) -> bool {
188-
match value.data() {
189-
CrdsData::ContactInfo(_) => true,
190-
CrdsData::LegacyContactInfo(_) => true,
191-
// May Impact new validators starting up without any stake yet.
192-
CrdsData::Vote(_, _) => true,
193-
// Unstaked nodes can still help repair.
194-
CrdsData::EpochSlots(_, _) => true,
195-
// Unstaked nodes can still serve snapshots.
196-
CrdsData::LegacySnapshotHashes(_) | CrdsData::SnapshotHashes(_) => true,
197-
// Otherwise unstaked voting nodes will show up with no version in
198-
// the various dashboards.
199-
CrdsData::Version(_) => true,
200-
CrdsData::AccountsHashes(_) => true,
201-
CrdsData::NodeInstance(_) if !drop_unstaked_node_instance => true,
202-
CrdsData::LowestSlot(_, _)
203-
| CrdsData::LegacyVersion(_)
204-
| CrdsData::DuplicateShred(_, _)
205-
| CrdsData::RestartHeaviestFork(_)
206-
| CrdsData::RestartLastVotedForkSlots(_)
207-
| CrdsData::NodeInstance(_) => {
208-
stakes.len() < MIN_NUM_STAKED_NODES || {
209-
let stake = stakes.get(&value.pubkey()).copied();
210-
stake.unwrap_or_default() >= MIN_STAKE_FOR_GOSSIP
211-
}
212-
}
213-
}
214-
}
215-
216176
impl ClusterInfo {
217177
pub fn new(
218178
contact_info: ContactInfo,
@@ -1282,9 +1242,7 @@ impl ClusterInfo {
12821242
self.flush_push_queue();
12831243
self.gossip
12841244
.new_push_messages(&self_id, timestamp(), stakes, |value| {
1285-
should_retain_crds_value(
1286-
value, stakes, /*drop_unstaked_node_instance:*/ false,
1287-
)
1245+
should_retain_crds_value(value, stakes, GossipFilterDirection::EgressPush)
12881246
})
12891247
};
12901248
self.stats
@@ -1692,7 +1650,9 @@ impl ClusterInfo {
16921650
now,
16931651
|value| {
16941652
should_retain_crds_value(
1695-
value, stakes, /*drop_unstaked_node_instance:*/ true,
1653+
value,
1654+
stakes,
1655+
GossipFilterDirection::EgressPullResponse,
16961656
)
16971657
},
16981658
self.my_shred_version(),
@@ -2132,9 +2092,7 @@ impl ClusterInfo {
21322092
&mut protocol
21332093
{
21342094
values.retain(|value| {
2135-
should_retain_crds_value(
2136-
value, stakes, /*drop_unstaked_node_instance:*/ false,
2137-
)
2095+
should_retain_crds_value(value, stakes, GossipFilterDirection::Ingress)
21382096
});
21392097
if values.is_empty() {
21402098
return None;
@@ -3003,7 +2961,7 @@ fn verify_gossip_addr<R: Rng + CryptoRng>(
30032961
_ => return true, // If not a contact-info, nothing to verify.
30042962
};
30052963
// For (sufficiently) staked nodes, don't bother with ping/pong.
3006-
if stakes.get(pubkey) >= Some(&MIN_STAKE_FOR_GOSSIP) {
2964+
if stakes.get(pubkey).copied() >= Some(MIN_STAKE_FOR_GOSSIP) {
30072965
return true;
30082966
}
30092967
// Invalid addresses are not verifiable.

gossip/src/crds_filter.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use {
2+
crate::{crds_data::CrdsData, crds_value::CrdsValue},
3+
solana_pubkey::Pubkey,
4+
std::collections::HashMap,
5+
};
6+
7+
pub(crate) enum GossipFilterDirection {
8+
Ingress,
9+
EgressPush,
10+
EgressPullResponse,
11+
}
12+
13+
/// Minimum number of staked nodes for enforcing stakes in gossip.
14+
const MIN_NUM_STAKED_NODES: usize = 500;
15+
16+
/// Minimum stake that a node should have so that all its CRDS values are
17+
/// propagated through gossip (below this only subset of CRDS is propagated).
18+
pub(crate) const MIN_STAKE_FOR_GOSSIP: u64 = solana_native_token::LAMPORTS_PER_SOL;
19+
20+
/// Returns false if the CRDS value should be discarded.
21+
/// `direction` controls whether we are looking at
22+
/// incoming packet (via Push or PullResponse) or
23+
/// we are about to make a packet
24+
#[inline]
25+
#[must_use]
26+
pub(crate) fn should_retain_crds_value(
27+
value: &CrdsValue,
28+
stakes: &HashMap<Pubkey, u64>,
29+
direction: GossipFilterDirection,
30+
) -> bool {
31+
let retain_if_staked = || {
32+
stakes.len() < MIN_NUM_STAKED_NODES || {
33+
let stake = stakes.get(&value.pubkey()).copied();
34+
stake.unwrap_or_default() >= MIN_STAKE_FOR_GOSSIP
35+
}
36+
};
37+
38+
use GossipFilterDirection::*;
39+
match value.data() {
40+
// All nodes can send ContactInfo
41+
CrdsData::ContactInfo(_) => true,
42+
// Unstaked nodes can still serve snapshots.
43+
CrdsData::SnapshotHashes(_) => true,
44+
// Consensus related messages only allowed for staked nodes
45+
CrdsData::DuplicateShred(_, _)
46+
| CrdsData::LowestSlot(0, _)
47+
| CrdsData::RestartHeaviestFork(_)
48+
| CrdsData::RestartLastVotedForkSlots(_) => retain_if_staked(),
49+
// Unstaked nodes can technically send EpochSlots, but we do not want them
50+
// eating gossip bandwidth
51+
CrdsData::EpochSlots(_, _) => match direction {
52+
// always store if we have received them
53+
// to avoid getting them again in PullResponses
54+
Ingress => true,
55+
// only forward if the origin is staked
56+
EgressPush | EgressPullResponse => retain_if_staked(),
57+
},
58+
CrdsData::Vote(_, _) => match direction {
59+
Ingress | EgressPush => true,
60+
EgressPullResponse => retain_if_staked(),
61+
},
62+
// Fully deprecated messages
63+
CrdsData::AccountsHashes(_) => false,
64+
CrdsData::LegacyContactInfo(_) => false,
65+
CrdsData::LegacySnapshotHashes(_) => false,
66+
CrdsData::LegacyVersion(_) => false,
67+
CrdsData::LowestSlot(1.., _) => false,
68+
CrdsData::NodeInstance(_) => false,
69+
CrdsData::Version(_) => false,
70+
}
71+
}

gossip/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub mod contact_info;
77
pub mod crds;
88
pub mod crds_data;
99
pub mod crds_entry;
10+
mod crds_filter;
1011
pub mod crds_gossip;
1112
pub mod crds_gossip_error;
1213
pub mod crds_gossip_pull;

0 commit comments

Comments
 (0)