4040 gossip_error:: GossipError ,
4141 ping_pong:: { self , PingCache , Pong } ,
4242 restart_crds_values:: { RestartLastVotedForkSlots , RestartLastVotedForkSlotsError } ,
43- socketaddr, socketaddr_any,
4443 weighted_shuffle:: WeightedShuffle ,
4544 } ,
4645 bincode:: { serialize, serialized_size} ,
@@ -127,7 +126,7 @@ pub const MAX_INCREMENTAL_SNAPSHOT_HASHES: usize = 25;
127126const MAX_PRUNE_DATA_NODES : usize = 32 ;
128127/// Number of bytes in the randomly generated token sent with ping messages.
129128const GOSSIP_PING_TOKEN_SIZE : usize = 32 ;
130- const GOSSIP_PING_CACHE_CAPACITY : usize = 65536 ;
129+ const GOSSIP_PING_CACHE_CAPACITY : usize = 126976 ;
131130const GOSSIP_PING_CACHE_TTL : Duration = Duration :: from_secs ( 1280 ) ;
132131const GOSSIP_PING_CACHE_RATE_LIMIT_DELAY : Duration = Duration :: from_secs ( 1280 / 64 ) ;
133132pub const DEFAULT_CONTACT_DEBUG_INTERVAL_MILLIS : u64 = 10_000 ;
@@ -2422,6 +2421,20 @@ impl ClusterInfo {
24222421 }
24232422 Ok ( ( ) )
24242423 } ;
2424+ let mut pings = Vec :: new ( ) ;
2425+ let mut rng = rand:: thread_rng ( ) ;
2426+ let keypair: Arc < Keypair > = self . keypair ( ) . clone ( ) ;
2427+ let mut verify_gossip_addr = |value : & CrdsValue | {
2428+ verify_gossip_addr (
2429+ & mut rng,
2430+ & keypair,
2431+ value,
2432+ stakes,
2433+ & self . socket_addr_space ,
2434+ & self . ping_cache ,
2435+ & mut pings,
2436+ )
2437+ } ;
24252438 // Split packets based on their types.
24262439 let mut pull_requests = vec ! [ ] ;
24272440 let mut pull_responses = vec ! [ ] ;
@@ -2432,15 +2445,23 @@ impl ClusterInfo {
24322445 for ( from_addr, packet) in packets {
24332446 match packet {
24342447 Protocol :: PullRequest ( filter, caller) => {
2435- pull_requests. push ( ( from_addr, filter, caller) )
2448+ if verify_gossip_addr ( & caller) {
2449+ pull_requests. push ( ( from_addr, filter, caller) )
2450+ }
24362451 }
24372452 Protocol :: PullResponse ( _, mut data) => {
24382453 check_duplicate_instance ( & data) ?;
2439- pull_responses. append ( & mut data) ;
2454+ data. retain ( & mut verify_gossip_addr) ;
2455+ if !data. is_empty ( ) {
2456+ pull_responses. append ( & mut data) ;
2457+ }
24402458 }
2441- Protocol :: PushMessage ( from, data) => {
2459+ Protocol :: PushMessage ( from, mut data) => {
24422460 check_duplicate_instance ( & data) ?;
2443- push_messages. push ( ( from, data) ) ;
2461+ data. retain ( & mut verify_gossip_addr) ;
2462+ if !data. is_empty ( ) {
2463+ push_messages. push ( ( from, data) ) ;
2464+ }
24442465 }
24452466 Protocol :: PruneMessage ( _from, data) => prune_messages. push ( data) ,
24462467 Protocol :: PingMessage ( ping) => ping_messages. push ( ( from_addr, ping) ) ,
@@ -2454,6 +2475,17 @@ impl ClusterInfo {
24542475 }
24552476 push_messages. retain ( |( _, data) | !data. is_empty ( ) ) ;
24562477 }
2478+ if !pings. is_empty ( ) {
2479+ self . stats
2480+ . packets_sent_gossip_requests_count
2481+ . add_relaxed ( pings. len ( ) as u64 ) ;
2482+ let packet_batch = PacketBatch :: new_unpinned_with_recycler_data_and_dests (
2483+ recycler,
2484+ "ping_contact_infos" ,
2485+ & pings,
2486+ ) ;
2487+ let _ = response_sender. send ( packet_batch) ;
2488+ }
24572489 self . handle_batch_ping_messages ( ping_messages, recycler, response_sender) ;
24582490 self . handle_batch_prune_messages ( prune_messages, stakes) ;
24592491 self . handle_batch_push_messages (
@@ -2722,9 +2754,12 @@ impl ClusterInfo {
27222754 shred_version : u16 ,
27232755 ) -> ( ContactInfo , UdpSocket , Option < TcpListener > ) {
27242756 let bind_ip_addr = IpAddr :: V4 ( Ipv4Addr :: UNSPECIFIED ) ;
2725- let ( _, gossip_socket) = bind_in_range ( bind_ip_addr, VALIDATOR_PORT_RANGE ) . unwrap ( ) ;
2726- let contact_info = Self :: gossip_contact_info ( id, socketaddr_any ! ( ) , shred_version) ;
2727-
2757+ let ( port, gossip_socket) = bind_in_range ( bind_ip_addr, VALIDATOR_PORT_RANGE ) . unwrap ( ) ;
2758+ let contact_info = Self :: gossip_contact_info (
2759+ id,
2760+ SocketAddr :: new ( IpAddr :: V4 ( Ipv4Addr :: LOCALHOST ) , port) ,
2761+ shred_version,
2762+ ) ;
27282763 ( contact_info, gossip_socket, None )
27292764 }
27302765}
@@ -3145,6 +3180,44 @@ fn filter_on_shred_version(
31453180 }
31463181}
31473182
3183+ // If the CRDS value is an unstaked contact-info, verifies if
3184+ // it has responded to ping on its gossip socket address.
3185+ // Returns false if the CRDS value should be discarded.
3186+ #[ must_use]
3187+ fn verify_gossip_addr < R : Rng + CryptoRng > (
3188+ rng : & mut R ,
3189+ keypair : & Keypair ,
3190+ value : & CrdsValue ,
3191+ stakes : & HashMap < Pubkey , u64 > ,
3192+ socket_addr_space : & SocketAddrSpace ,
3193+ ping_cache : & Mutex < PingCache > ,
3194+ pings : & mut Vec < ( SocketAddr , Protocol /* ::PingMessage */ ) > ,
3195+ ) -> bool {
3196+ let ( pubkey, addr) = match & value. data {
3197+ CrdsData :: ContactInfo ( node) => ( node. pubkey ( ) , node. gossip ( ) ) ,
3198+ CrdsData :: LegacyContactInfo ( node) => ( node. pubkey ( ) , node. gossip ( ) ) ,
3199+ _ => return true , // If not a contact-info, nothing to verify.
3200+ } ;
3201+ // For (sufficiently) staked nodes, don't bother with ping/pong.
3202+ if stakes. get ( pubkey) >= Some ( & MIN_STAKE_FOR_GOSSIP ) {
3203+ return true ;
3204+ }
3205+ // Invalid addresses are not verifiable.
3206+ let Some ( addr) = addr. ok ( ) . filter ( |addr| socket_addr_space. check ( addr) ) else {
3207+ return false ;
3208+ } ;
3209+ let ( out, ping) = {
3210+ let node = ( * pubkey, addr) ;
3211+ let mut pingf = move || Ping :: new_rand ( rng, keypair) . ok ( ) ;
3212+ let mut ping_cache = ping_cache. lock ( ) . unwrap ( ) ;
3213+ ping_cache. check ( Instant :: now ( ) , node, & mut pingf)
3214+ } ;
3215+ if let Some ( ping) = ping {
3216+ pings. push ( ( addr, Protocol :: PingMessage ( ping) ) ) ;
3217+ }
3218+ out
3219+ }
3220+
31483221#[ cfg( test) ]
31493222mod tests {
31503223 use {
@@ -3153,6 +3226,7 @@ mod tests {
31533226 crds_gossip_pull:: tests:: MIN_NUM_BLOOM_FILTERS ,
31543227 crds_value:: { CrdsValue , CrdsValueLabel , Vote as CrdsVote } ,
31553228 duplicate_shred:: { self , tests:: new_rand_shred, MAX_DUPLICATE_SHREDS } ,
3229+ socketaddr,
31563230 } ,
31573231 itertools:: izip,
31583232 solana_ledger:: shred:: Shredder ,
0 commit comments