1use crate::{
4 cache::LruMap,
5 error::SessionError,
6 session::{Direction, PendingSessionHandshakeError},
7 swarm::NetworkConnectionState,
8 trusted_peers_resolver::TrustedPeersResolver,
9};
10use alloy_primitives::map::{hash_map::Entry, FbBuildHasher, HashMap, HashSet};
11use futures::StreamExt;
12
13use rand::Rng;
14use reth_eth_wire::{
15 errors::{EthStreamError, P2PHandshakeError, P2PStreamError},
16 DisconnectReason,
17};
18use reth_ethereum_forks::ForkId;
19use reth_net_banlist::{is_global, BanList};
20use reth_network_api::test_utils::{PeerCommand, PeersHandle};
21use reth_network_peers::{NodeRecord, PeerId, TrustedPeer};
22use reth_network_types::{
23 is_connection_failed_reputation,
24 peers::{
25 config::{PeerBackoffDurations, PEER_ROTATION_MIN_UPTIME},
26 reputation::{DEFAULT_REPUTATION, MAX_TRUSTED_PEER_REPUTATION_CHANGE},
27 },
28 BackoffKind, ConnectionsConfig, Peer, PeerAddr, PeerConnectionState, PeerKind, PeersConfig,
29 PersistedPeerInfo, ReputationChangeKind, ReputationChangeOutcome, ReputationChangeWeights,
30};
31use std::{
32 collections::VecDeque,
33 fmt::Display,
34 io,
35 net::{IpAddr, SocketAddr},
36 pin::Pin,
37 task::{Context, Poll},
38 time::Duration,
39};
40use thiserror::Error;
41use tokio::{
42 sync::mpsc,
43 time::{Instant, Interval, Sleep},
44};
45use tokio_stream::wrappers::UnboundedReceiverStream;
46use tracing::{trace, warn};
47
48const MAX_INCOMING_IP_THROTTLE_ENTRIES: u32 = 16_384;
50
51#[derive(Debug)]
58pub struct PeersManager {
59 peers: HashMap<PeerId, Peer, FbBuildHasher<64>>,
61 trusted_peer_ids: HashSet<PeerId, FbBuildHasher<64>>,
66 trusted_peers_resolver: TrustedPeersResolver,
69 manager_tx: mpsc::UnboundedSender<PeerCommand>,
71 handle_rx: UnboundedReceiverStream<PeerCommand>,
73 queued_actions: VecDeque<PeerAction>,
75 refill_slots_interval: Interval,
77 reputation_weights: ReputationChangeWeights,
79 connection_info: ConnectionInfo,
81 ban_list: BanList,
83 incoming_ip_throttle: LruMap<IpAddr, std::time::Instant>,
85 backed_off_peers: HashMap<PeerId, std::time::Instant, FbBuildHasher<64>>,
87 release_interval: Interval,
89 ban_duration: Duration,
91 backoff_durations: PeerBackoffDurations,
94 trusted_nodes_only: bool,
97 last_tick: Instant,
99 max_backoff_count: u8,
101 net_connection_state: NetworkConnectionState,
103 incoming_ip_throttle_duration: Duration,
105 ip_filter: reth_net_banlist::IpFilter,
107 enforce_enr_fork_id: bool,
110 peer_rotation_sleep: Option<Pin<Box<Sleep>>>,
113 peer_rotation_mean: Option<Duration>,
115}
116
117impl PeersManager {
118 pub fn new(config: PeersConfig) -> Self {
120 let PeersConfig {
121 refill_slots_interval,
122 connection_info,
123 reputation_weights,
124 ban_list,
125 ban_duration,
126 backoff_durations,
127 trusted_nodes,
128 trusted_nodes_only,
129 trusted_nodes_resolution_interval,
130 basic_nodes,
131 persisted_peers,
132 max_backoff_count,
133 incoming_ip_throttle_duration,
134 ip_filter,
135 enforce_enr_fork_id,
136 peer_rotation_interval,
137 } = config;
138 let (manager_tx, handle_rx) = mpsc::unbounded_channel();
139 let now = Instant::now();
140
141 let unban_interval = ban_duration.min(backoff_durations.low) / 2;
143
144 let mut peers: HashMap<PeerId, Peer, FbBuildHasher<64>> = HashMap::with_capacity_and_hasher(
145 trusted_nodes.len() + basic_nodes.len() + persisted_peers.len(),
146 Default::default(),
147 );
148 let mut trusted_peer_ids: HashSet<PeerId, FbBuildHasher<64>> =
149 HashSet::with_capacity_and_hasher(trusted_nodes.len(), Default::default());
150
151 for trusted_peer in &trusted_nodes {
152 trusted_peer_ids.insert(trusted_peer.id);
155 match trusted_peer.resolve_blocking() {
156 Ok(NodeRecord { address, tcp_port, udp_port, id }) => {
157 if !ip_filter.is_allowed(&address) {
158 trace!(target: "net::peers", ?id, ?address, "Skipping trusted peer address not in allowed ranges");
159 continue
160 }
161 peers.entry(id).or_insert_with(|| {
162 Peer::trusted(PeerAddr::new_with_ports(address, tcp_port, Some(udp_port)))
163 });
164 }
165 Err(err) => {
166 warn!(target: "net::peers", ?err, "Failed to resolve trusted peer");
167 }
168 }
169 }
170
171 for PersistedPeerInfo { record, kind, fork_id, reputation } in persisted_peers {
172 if enforce_enr_fork_id && fork_id.is_none() {
176 continue
177 }
178 let NodeRecord { address, tcp_port, udp_port, id } = record;
179 if kind.is_trusted() {
181 trusted_peer_ids.insert(id);
182 }
183 if !ip_filter.is_allowed(&address) {
184 trace!(target: "net::peers", ?id, ?address, "Skipping persisted peer from IP not in allowed ranges");
185 continue
186 }
187 peers.entry(id).or_insert_with(|| {
188 let mut peer = Peer::with_kind(
189 PeerAddr::new_with_ports(address, tcp_port, Some(udp_port)),
190 kind,
191 );
192 peer.fork_id = fork_id.map(Box::new);
193 peer.reputation = reputation;
194 peer
195 });
196 }
197
198 for NodeRecord { address, tcp_port, udp_port, id } in basic_nodes {
199 if !ip_filter.is_allowed(&address) {
200 trace!(target: "net::peers", ?id, ?address, "Skipping basic peer from IP not in allowed ranges");
201 continue
202 }
203 peers.entry(id).or_insert_with(|| {
204 Peer::new(PeerAddr::new_with_ports(address, tcp_port, Some(udp_port)))
205 });
206 }
207
208 for id in &trusted_peer_ids {
211 if let Some(peer) = peers.get_mut(id) {
212 peer.kind = PeerKind::Trusted;
213 }
214 }
215
216 trace!(target: "net::peers", trusted_peers=?trusted_peer_ids, "Initialized peers manager");
217
218 Self {
219 peers,
220 trusted_peer_ids,
221 trusted_peers_resolver: TrustedPeersResolver::new(
222 trusted_nodes,
223 tokio::time::interval(trusted_nodes_resolution_interval), ),
225 manager_tx,
226 handle_rx: UnboundedReceiverStream::new(handle_rx),
227 queued_actions: Default::default(),
228 reputation_weights,
229 refill_slots_interval: tokio::time::interval(refill_slots_interval),
230 release_interval: tokio::time::interval_at(now + unban_interval, unban_interval),
231 connection_info: ConnectionInfo::new(connection_info),
232 ban_list,
233 incoming_ip_throttle: LruMap::new(MAX_INCOMING_IP_THROTTLE_ENTRIES),
234 backed_off_peers: Default::default(),
235 ban_duration,
236 backoff_durations,
237 trusted_nodes_only,
238 last_tick: Instant::now(),
239 max_backoff_count,
240 net_connection_state: NetworkConnectionState::default(),
241 incoming_ip_throttle_duration,
242 ip_filter,
243 enforce_enr_fork_id,
244 peer_rotation_sleep: peer_rotation_interval
245 .map(|mean| Box::pin(tokio::time::sleep(jitter_rotation_interval(mean)))),
246 peer_rotation_mean: peer_rotation_interval,
247 }
248 }
249
250 pub(crate) fn handle(&self) -> PeersHandle {
252 PeersHandle::new(self.manager_tx.clone())
253 }
254
255 pub(crate) const fn enforce_enr_fork_id(&self) -> bool {
257 self.enforce_enr_fork_id
258 }
259
260 #[inline]
262 pub(crate) fn num_known_peers(&self) -> usize {
263 self.peers.len()
264 }
265
266 pub(crate) fn iter_peers(&self) -> impl Iterator<Item = NodeRecord> + '_ {
268 self.peers.iter().map(|(peer_id, v)| {
269 NodeRecord::new_with_ports(
270 v.addr.tcp().ip(),
271 v.addr.tcp().port(),
272 v.addr.udp().map(|addr| addr.port()),
273 *peer_id,
274 )
275 })
276 }
277
278 pub(crate) fn persistable_peers(&self) -> impl Iterator<Item = PersistedPeerInfo> + '_ {
283 self.peers.iter().filter(|(_, peer)| !peer.is_backed_off() && !peer.is_banned()).map(
284 |(peer_id, peer)| PersistedPeerInfo {
285 record: NodeRecord::new_with_ports(
286 peer.addr.tcp().ip(),
287 peer.addr.tcp().port(),
288 peer.addr.udp().map(|addr| addr.port()),
289 *peer_id,
290 ),
291 kind: peer.kind,
292 fork_id: peer.fork_id.as_deref().copied(),
293 reputation: peer.reputation,
294 },
295 )
296 }
297
298 pub(crate) fn peer_by_id(&self, peer_id: PeerId) -> Option<(NodeRecord, PeerKind)> {
300 self.peers.get(&peer_id).map(|v| {
301 (
302 NodeRecord::new_with_ports(
303 v.addr.tcp().ip(),
304 v.addr.tcp().port(),
305 v.addr.udp().map(|addr| addr.port()),
306 peer_id,
307 ),
308 v.kind,
309 )
310 })
311 }
312
313 pub(crate) fn is_inbound_peer(&self, peer_id: &PeerId) -> bool {
315 self.peers.get(peer_id).is_some_and(|p| {
316 matches!(p.state, PeerConnectionState::In | PeerConnectionState::DisconnectingIn)
317 })
318 }
319
320 pub(crate) fn peers_by_kind(&self, kind: PeerKind) -> impl Iterator<Item = PeerId> + '_ {
322 self.peers.iter().filter_map(move |(peer_id, peer)| (peer.kind == kind).then_some(*peer_id))
323 }
324
325 #[inline]
327 pub(crate) const fn num_inbound_connections(&self) -> usize {
328 self.connection_info.num_inbound
329 }
330
331 #[inline]
333 pub(crate) const fn num_outbound_connections(&self) -> usize {
334 self.connection_info.num_outbound
335 }
336
337 #[inline]
339 pub(crate) const fn num_pending_outbound_connections(&self) -> usize {
340 self.connection_info.num_pending_out
341 }
342
343 #[inline]
345 pub(crate) fn num_backed_off_peers(&self) -> usize {
346 self.backed_off_peers.len()
347 }
348
349 fn num_idle_trusted_peers(&self) -> usize {
351 self.peers.iter().filter(|(_, peer)| peer.kind.is_trusted() && peer.state.is_idle()).count()
352 }
353
354 pub(crate) fn on_incoming_pending_session(
358 &mut self,
359 addr: IpAddr,
360 ) -> Result<(), InboundConnectionError> {
361 if !self.ip_filter.is_allowed(&addr) {
363 trace!(target: "net", ?addr, "Rejecting connection from IP not in allowed ranges");
364 return Err(InboundConnectionError::IpBanned)
365 }
366
367 if self.ban_list.is_banned_ip(&addr) ||
368 self.incoming_ip_throttle
369 .get(&addr)
370 .is_some_and(|until| *until > std::time::Instant::now())
371 {
372 return Err(InboundConnectionError::IpBanned)
373 }
374
375 if !self.connection_info.has_in_capacity() {
377 if self.trusted_peer_ids.is_empty() {
378 return Err(InboundConnectionError::ExceedsCapacity)
381 }
382
383 let num_idle_trusted_peers = self.num_idle_trusted_peers();
387 if num_idle_trusted_peers <= self.trusted_peer_ids.len() {
388 let max_inbound =
390 self.trusted_peer_ids.len().max(self.connection_info.config.max_inbound);
391 if self.connection_info.num_pending_in < max_inbound {
392 self.throttle_incoming_ip(addr);
395 self.connection_info.inc_pending_in();
396 return Ok(())
397 }
398 }
399
400 return Err(InboundConnectionError::ExceedsCapacity)
402 }
403
404 if !self.connection_info.has_in_pending_capacity() {
406 return Err(InboundConnectionError::ExceedsCapacity)
407 }
408
409 self.throttle_incoming_ip(addr);
411
412 self.connection_info.inc_pending_in();
413 Ok(())
414 }
415
416 pub(crate) const fn on_incoming_pending_session_rejected_internally(&mut self) {
419 self.connection_info.decr_pending_in();
420 }
421
422 pub(crate) const fn on_incoming_pending_session_gracefully_closed(&mut self) {
424 self.connection_info.decr_pending_in()
425 }
426
427 pub(crate) fn on_incoming_pending_session_dropped(
429 &mut self,
430 remote_addr: SocketAddr,
431 err: &PendingSessionHandshakeError,
432 ) {
433 if err.is_fatal_protocol_error() {
434 self.ban_ip(remote_addr.ip());
435
436 if err.merits_discovery_ban() {
437 self.queued_actions
438 .push_back(PeerAction::DiscoveryBanIp { ip_addr: remote_addr.ip() })
439 }
440 }
441
442 self.connection_info.decr_pending_in();
443 }
444
445 pub(crate) fn on_incoming_session_established(&mut self, peer_id: PeerId, addr: SocketAddr) {
452 self.connection_info.decr_pending_in();
453
454 if self.ban_list.is_banned_peer(&peer_id) {
457 self.queued_actions.push_back(PeerAction::DisconnectBannedIncoming { peer_id });
458 return
459 }
460
461 let is_trusted = self.trusted_peer_ids.contains(&peer_id);
463 if self.trusted_nodes_only && !is_trusted {
464 self.queued_actions.push_back(PeerAction::DisconnectUntrustedIncoming { peer_id });
465 return
466 }
467
468 self.tick();
470
471 match self.peers.entry(peer_id) {
472 Entry::Occupied(mut entry) => {
473 let peer = entry.get_mut();
474 if peer.is_banned() {
475 self.queued_actions.push_back(PeerAction::DisconnectBannedIncoming { peer_id });
476 return
477 }
478 if peer.state.is_pending_out() {
481 self.connection_info.decr_state(peer.state);
482 }
483
484 peer.state = PeerConnectionState::In;
485 peer.mark_connected();
486 }
487 Entry::Vacant(entry) => {
488 let mut peer = Peer::with_state(PeerAddr::from_tcp(addr), PeerConnectionState::In);
491 peer.mark_connected();
492 peer.remove_after_disconnect = true;
493 if is_trusted {
494 peer.kind = PeerKind::Trusted;
495 }
496 entry.insert(peer);
497 self.queued_actions.push_back(PeerAction::PeerAdded(peer_id));
498 }
499 }
500
501 let has_in_capacity = self.has_inbound_capacity(peer_id);
502 self.connection_info.inc_in();
504
505 if !has_in_capacity {
507 self.queued_actions.push_back(PeerAction::Disconnect {
508 peer_id,
509 reason: Some(DisconnectReason::TooManyPeers),
510 });
511 }
512 }
513
514 pub(crate) fn has_inbound_capacity(&self, peer_id: PeerId) -> bool {
516 self.connection_info.has_in_capacity() ||
517 self.trusted_peer_ids.contains(&peer_id) ||
518 self.peers.get(&peer_id).is_some_and(|peer| peer.is_trusted())
519 }
520
521 pub(crate) fn inbound_session_rejection(&self, peer_id: PeerId) -> Option<DisconnectReason> {
524 if self.ban_list.is_banned_peer(&peer_id) ||
525 self.peers.get(&peer_id).is_some_and(|peer| peer.is_banned()) ||
526 (self.trusted_nodes_only && !self.trusted_peer_ids.contains(&peer_id))
527 {
528 return Some(DisconnectReason::DisconnectRequested)
529 }
530 (!self.has_inbound_capacity(peer_id)).then_some(DisconnectReason::TooManyPeers)
531 }
532
533 fn ban_peer(&mut self, peer_id: PeerId) {
535 let ban_duration = if let Some(peer) = self.peers.get(&peer_id) &&
536 (peer.is_trusted() || peer.is_static())
537 {
538 self.backoff_durations.low / 2
541 } else {
542 self.ban_duration
543 };
544
545 self.ban_list.ban_peer_until(peer_id, std::time::Instant::now() + ban_duration);
546 self.queued_actions.push_back(PeerAction::BanPeer { peer_id });
547 }
548
549 fn ban_ip(&mut self, ip: IpAddr) {
551 self.ban_list.ban_ip_until(ip, std::time::Instant::now() + self.ban_duration);
552 }
553
554 fn throttle_incoming_ip(&mut self, ip: IpAddr) {
556 if is_global(&ip) {
557 self.incoming_ip_throttle
560 .insert(ip, std::time::Instant::now() + self.incoming_ip_throttle_duration);
561 }
562 }
563
564 fn backoff_peer_until(&mut self, peer_id: PeerId, until: std::time::Instant) {
566 trace!(target: "net::peers", ?peer_id, "backing off");
567
568 if let Some(peer) = self.peers.get_mut(&peer_id) {
569 peer.backed_off = true;
570 self.backed_off_peers.insert(peer_id, until);
571 }
572 }
573
574 fn unban_peer(&mut self, peer_id: PeerId) {
576 self.ban_list.unban_peer(&peer_id);
577 self.queued_actions.push_back(PeerAction::UnBanPeer { peer_id });
578 }
579
580 fn tick(&mut self) {
585 let now = Instant::now();
586 let secs_since_last_tick =
590 if self.last_tick > now { 0 } else { (now - self.last_tick).as_secs() as i32 };
591 self.last_tick = now;
592
593 for peer in self.peers.iter_mut().filter(|(_, peer)| peer.state.is_connected()) {
595 if peer.1.reputation < DEFAULT_REPUTATION {
598 peer.1.reputation =
599 peer.1.reputation.saturating_add(secs_since_last_tick).min(DEFAULT_REPUTATION);
600 }
601 }
602 }
603
604 pub(crate) fn get_reputation(&self, peer_id: &PeerId) -> Option<i32> {
606 self.peers.get(peer_id).map(|peer| peer.reputation)
607 }
608
609 pub(crate) fn apply_reputation_change(&mut self, peer_id: &PeerId, rep: ReputationChangeKind) {
615 trace!(target: "net::peers", ?peer_id, reputation=?rep, "applying reputation change");
616
617 let reputation_change = if rep.is_reset() {
618 None
619 } else {
620 let reputation_change = self.reputation_weights.change(rep).as_i32();
621 if reputation_change == 0 {
622 return
623 }
624 Some(reputation_change)
625 };
626
627 let outcome = if let Some(peer) = self.peers.get_mut(peer_id) {
628 if let Some(mut reputation_change) = reputation_change {
629 if peer.is_trusted() || peer.is_static() {
630 if matches!(
632 rep,
633 ReputationChangeKind::Dropped |
634 ReputationChangeKind::BadAnnouncement |
635 ReputationChangeKind::Timeout |
636 ReputationChangeKind::AlreadySeenTransaction
637 ) {
638 return
639 }
640
641 if reputation_change < MAX_TRUSTED_PEER_REPUTATION_CHANGE {
643 reputation_change = MAX_TRUSTED_PEER_REPUTATION_CHANGE;
645 }
646 }
647 peer.apply_reputation(reputation_change, rep)
648 } else {
649 peer.reset_reputation()
650 }
651 } else {
652 return
653 };
654
655 match outcome {
656 ReputationChangeOutcome::None => {}
657 ReputationChangeOutcome::Ban => {
658 self.ban_peer(*peer_id);
659 }
660 ReputationChangeOutcome::Unban => self.unban_peer(*peer_id),
661 ReputationChangeOutcome::DisconnectAndBan => {
662 self.queued_actions.push_back(PeerAction::Disconnect {
663 peer_id: *peer_id,
664 reason: Some(DisconnectReason::DisconnectRequested),
665 });
666 self.ban_peer(*peer_id);
667 }
668 }
669 }
670
671 pub(crate) fn on_outgoing_pending_session_gracefully_closed(&mut self, peer_id: &PeerId) {
673 if let Some(peer) = self.peers.get_mut(peer_id) &&
674 peer.state.is_pending_out()
675 {
676 self.connection_info.decr_state(peer.state);
677 peer.state = PeerConnectionState::Idle;
678 peer.mark_disconnected();
679 }
680 }
681
682 pub(crate) fn on_outgoing_pending_session_dropped(
685 &mut self,
686 remote_addr: &SocketAddr,
687 peer_id: &PeerId,
688 err: &PendingSessionHandshakeError,
689 ) {
690 if matches!(
691 err,
692 PendingSessionHandshakeError::Ecies(_) | PendingSessionHandshakeError::Timeout
693 ) || matches!(
694 err,
695 PendingSessionHandshakeError::Eth(EthStreamError::P2PStreamError(
696 P2PStreamError::HandshakeError(
697 P2PHandshakeError::Timeout | P2PHandshakeError::NoResponse
698 )
699 ))
700 ) || matches!(err, PendingSessionHandshakeError::Eth(error) if error.as_io().is_some())
701 {
702 if self.peers.get(peer_id).is_some_and(|peer| peer.state.is_pending_out()) {
706 self.on_outgoing_pending_session_gracefully_closed(peer_id);
707 self.backoff_peer_until(
708 *peer_id,
709 self.backoff_durations.backoff_until(BackoffKind::Low, 0),
710 );
711 self.fill_outbound_slots();
712 }
713 return
714 }
715 self.on_connection_failure(remote_addr, peer_id, err, ReputationChangeKind::FailedToConnect)
716 }
717
718 pub(crate) fn on_active_session_gracefully_closed(&mut self, peer_id: PeerId) {
720 match self.peers.entry(peer_id) {
721 Entry::Occupied(mut entry) => {
722 trace!(target: "net::peers", ?peer_id, direction=?entry.get().state, "active session gracefully closed");
723 self.connection_info.decr_state(entry.get().state);
724
725 if entry.get().remove_after_disconnect && !entry.get().is_trusted() {
726 entry.remove();
728 self.queued_actions.push_back(PeerAction::PeerRemoved(peer_id));
729 } else {
730 let peer = entry.get_mut();
731 peer.severe_backoff_counter = 0;
735 peer.state = PeerConnectionState::Idle;
736 peer.mark_disconnected();
737
738 peer.backed_off = true;
743 self.backed_off_peers.insert(
744 peer_id,
745 std::time::Instant::now() + self.incoming_ip_throttle_duration,
746 );
747 trace!(target: "net::peers", ?peer_id, kind=?peer.kind, duration=?self.incoming_ip_throttle_duration, "backing off on gracefully closed session");
748 }
749 }
750 Entry::Vacant(_) => return,
751 }
752
753 self.fill_outbound_slots();
754 }
755
756 pub(crate) fn on_active_outgoing_established(&mut self, peer_id: PeerId) {
758 let at_capacity = self.connection_info.is_outbound_at_capacity();
759 if let Some(peer) = self.peers.get_mut(&peer_id) {
760 trace!(target: "net::peers", ?peer_id, "established active outgoing connection");
761 self.connection_info.decr_state(peer.state);
762 self.connection_info.inc_out();
763 peer.state = PeerConnectionState::Out;
764 peer.mark_connected();
765 if at_capacity &&
766 !peer.is_trusted() &&
767 !peer.is_static() &&
768 !self.trusted_peer_ids.contains(&peer_id)
769 {
770 self.queued_actions.push_back(PeerAction::Disconnect {
771 peer_id,
772 reason: Some(DisconnectReason::TooManyPeers),
773 });
774 }
775 }
776 }
777
778 pub(crate) fn on_active_session_dropped(
784 &mut self,
785 remote_addr: &SocketAddr,
786 peer_id: &PeerId,
787 err: &EthStreamError,
788 ) {
789 self.on_connection_failure(remote_addr, peer_id, err, ReputationChangeKind::Dropped)
790 }
791
792 pub(crate) fn on_outgoing_connection_failure(
795 &mut self,
796 remote_addr: &SocketAddr,
797 peer_id: &PeerId,
798 err: &io::Error,
799 ) {
800 if let Some(peer) = self.peers.get(peer_id) {
804 if peer.state.is_incoming() {
805 return
807 }
808
809 if peer.is_trusted() && is_connection_failed_reputation(peer.reputation) {
810 self.trusted_peers_resolver.interval.reset_immediately();
813 }
814 }
815
816 self.on_connection_failure(remote_addr, peer_id, err, ReputationChangeKind::FailedToConnect)
817 }
818
819 fn on_connection_failure(
820 &mut self,
821 remote_addr: &SocketAddr,
822 peer_id: &PeerId,
823 err: impl SessionError,
824 reputation_change: ReputationChangeKind,
825 ) {
826 trace!(target: "net::peers", ?remote_addr, ?peer_id, %err, "handling failed connection");
827
828 if err.is_fatal_protocol_error() {
829 trace!(target: "net::peers", ?remote_addr, ?peer_id, %err, "fatal connection error");
830 if let Entry::Occupied(mut entry) = self.peers.entry(*peer_id) {
833 self.connection_info.decr_state(entry.get().state);
834 if entry.get().is_trusted() {
836 let peer = entry.get_mut();
837 peer.state = PeerConnectionState::Idle;
838 peer.mark_disconnected();
839 } else {
840 entry.remove();
841 self.queued_actions.push_back(PeerAction::PeerRemoved(*peer_id));
842 if err.merits_discovery_ban() {
844 self.queued_actions.push_back(PeerAction::DiscoveryBanPeerId {
845 peer_id: *peer_id,
846 ip_addr: remote_addr.ip(),
847 })
848 }
849 }
850 }
851
852 self.ban_peer(*peer_id);
854 } else {
855 let mut backoff_until = None;
856 let mut remove_peer = false;
857
858 if let Some(peer) = self.peers.get_mut(peer_id) {
859 if let Some(kind) = err.should_backoff() {
860 if peer.is_trusted() || peer.is_static() {
861 let backoff = self.backoff_durations.low;
867 backoff_until = Some(std::time::Instant::now() + backoff);
868 trace!(target: "net::peers", ?peer_id, ?backoff, "backing off trusted peer");
869 } else {
870 if kind.is_severe() {
872 peer.severe_backoff_counter =
873 peer.severe_backoff_counter.saturating_add(1);
874 }
875 trace!(target: "net::peers", ?peer_id, ?kind, severe_backoff_counter=peer.severe_backoff_counter, "backing off basic peer");
876
877 let backoff_time =
878 self.backoff_durations.backoff_until(kind, peer.severe_backoff_counter);
879
880 backoff_until = Some(backoff_time);
884 }
885 } else {
886 let reputation_change = self.reputation_weights.change(reputation_change);
888 peer.reputation = peer.reputation.saturating_add(reputation_change.as_i32());
889 };
890
891 remove_peer = peer.remove_after_disconnect &&
895 matches!(
896 peer.state,
897 PeerConnectionState::DisconnectingIn |
898 PeerConnectionState::DisconnectingOut
899 ) &&
900 !peer.is_trusted();
901
902 self.connection_info.decr_state(peer.state);
903 peer.state = PeerConnectionState::Idle;
904 peer.mark_disconnected();
905
906 if peer.severe_backoff_counter > self.max_backoff_count &&
907 !peer.is_trusted() &&
908 !peer.is_static()
909 {
910 remove_peer = true;
913 }
914 }
915
916 if remove_peer {
918 trace!(target: "net", ?peer_id, "removed peer after failed connection");
919 let (peer_id, _) = self.peers.remove_entry(peer_id).expect("peer must exist");
920 self.queued_actions.push_back(PeerAction::PeerRemoved(peer_id));
921 } else if let Some(backoff_until) = backoff_until {
922 self.backoff_peer_until(*peer_id, backoff_until);
924 }
925 }
926
927 self.fill_outbound_slots();
928 }
929
930 pub(crate) const fn on_already_connected(&mut self, direction: Direction) {
936 match direction {
937 Direction::Incoming => {
938 self.connection_info.decr_pending_in();
940 }
941 Direction::Outgoing(_) => {
942 }
945 }
946 }
947
948 pub(crate) fn add_peer(&mut self, peer_id: PeerId, addr: PeerAddr, fork_id: Option<ForkId>) {
952 self.add_peer_kind(peer_id, None, addr, fork_id)
953 }
954
955 pub(crate) fn add_trusted_peer_id(&mut self, peer_id: PeerId) {
957 self.trusted_peer_ids.insert(peer_id);
958 if let Some(peer) = self.peers.get_mut(&peer_id) {
959 peer.kind = PeerKind::Trusted;
960 }
961 }
962
963 #[cfg_attr(not(test), expect(dead_code))]
967 pub(crate) fn add_trusted_peer(&mut self, peer_id: PeerId, addr: PeerAddr) {
968 self.add_peer_kind(peer_id, Some(PeerKind::Trusted), addr, None)
969 }
970
971 pub(crate) fn add_trusted_peer_node(&mut self, trusted: TrustedPeer) {
975 let peer_id = trusted.id;
976 self.add_trusted_peer_id(peer_id);
977 self.trusted_peers_resolver.remove(peer_id);
978 self.trusted_peers_resolver.trusted_peers.push(trusted);
979 self.trusted_peers_resolver.interval.reset_immediately();
980 }
981
982 pub(crate) fn add_peer_kind(
988 &mut self,
989 peer_id: PeerId,
990 kind: Option<PeerKind>,
991 addr: PeerAddr,
992 fork_id: Option<ForkId>,
993 ) {
994 let ip_addr = addr.tcp().ip();
995
996 if !self.ip_filter.is_allowed(&ip_addr) {
998 trace!(target: "net", ?peer_id, ?ip_addr, "Skipping peer from IP not in allowed ranges");
999 return
1000 }
1001
1002 if self.ban_list.is_banned(&peer_id, &ip_addr) {
1003 return
1004 }
1005
1006 match self.peers.entry(peer_id) {
1007 Entry::Occupied(mut entry) => {
1008 let peer = entry.get_mut();
1009 peer.fork_id = fork_id.map(Box::new);
1010 peer.addr = addr;
1011
1012 if let Some(kind) = kind {
1013 peer.kind = kind;
1014 }
1015
1016 if peer.state.is_incoming() {
1017 peer.remove_after_disconnect = false;
1021 }
1022 }
1023 Entry::Vacant(entry) => {
1024 trace!(target: "net::peers", ?peer_id, addr=?addr.tcp(), "discovered new node");
1025 let kind = kind.unwrap_or_else(|| {
1026 if self.trusted_peer_ids.contains(&peer_id) {
1027 PeerKind::Trusted
1028 } else {
1029 PeerKind::Basic
1030 }
1031 });
1032 let mut peer = Peer::with_kind(addr, kind);
1033 peer.fork_id = fork_id.map(Box::new);
1034 entry.insert(peer);
1035 self.queued_actions.push_back(PeerAction::PeerAdded(peer_id));
1036 }
1037 }
1038
1039 if kind.is_some_and(|kind| kind.is_trusted()) {
1040 self.trusted_peer_ids.insert(peer_id);
1042 }
1043 }
1044
1045 pub(crate) fn add_requested_peer(
1050 &mut self,
1051 peer_id: PeerId,
1052 kind: Option<PeerKind>,
1053 addr: PeerAddr,
1054 ) {
1055 self.add_peer_kind(peer_id, kind, addr, None);
1056 self.fill_outbound_slots();
1057 }
1058
1059 pub(crate) fn remove_peer(&mut self, peer_id: PeerId) {
1061 let Entry::Occupied(mut entry) = self.peers.entry(peer_id) else { return };
1062 if entry.get().is_trusted() {
1063 return
1064 }
1065 if matches!(
1066 entry.get().state,
1067 PeerConnectionState::DisconnectingIn | PeerConnectionState::DisconnectingOut
1068 ) {
1069 entry.get_mut().remove_after_disconnect = true;
1072 return
1073 }
1074 let mut peer = entry.remove();
1075
1076 trace!(target: "net::peers", ?peer_id, "remove discovered node");
1077 self.queued_actions.push_back(PeerAction::PeerRemoved(peer_id));
1078
1079 if peer.state.is_connected() {
1080 trace!(target: "net::peers", ?peer_id, "disconnecting on remove from discovery");
1081 peer.remove_after_disconnect = true;
1086 peer.state.disconnect();
1087 self.peers.insert(peer_id, peer);
1088 self.queued_actions.push_back(PeerAction::Disconnect {
1089 peer_id,
1090 reason: Some(DisconnectReason::DisconnectRequested),
1091 })
1092 }
1093 }
1094
1095 pub(crate) fn ban_peer_by_admin(&mut self, peer_id: PeerId) {
1100 if self.trusted_peer_ids.contains(&peer_id) ||
1101 self.peers.get(&peer_id).is_some_and(Peer::is_trusted)
1102 {
1103 return
1104 }
1105
1106 self.remove_peer(peer_id);
1107 self.ban_list.ban_peer(peer_id);
1108 }
1109
1110 pub(crate) fn unban_peer_by_admin(&mut self, peer_id: PeerId) {
1112 self.ban_list.unban_peer(&peer_id);
1113 if let Some(peer) = self.peers.get_mut(&peer_id) &&
1114 peer.is_banned()
1115 {
1116 peer.unban();
1117 self.queued_actions.push_back(PeerAction::UnBanPeer { peer_id });
1118 }
1119 }
1120
1121 #[cfg_attr(not(test), expect(dead_code))]
1124 pub(crate) fn add_and_connect(
1125 &mut self,
1126 peer_id: PeerId,
1127 addr: PeerAddr,
1128 fork_id: Option<ForkId>,
1129 ) {
1130 self.add_and_connect_kind(peer_id, PeerKind::Basic, addr, fork_id)
1131 }
1132
1133 pub(crate) fn add_and_connect_kind(
1137 &mut self,
1138 peer_id: PeerId,
1139 kind: PeerKind,
1140 addr: PeerAddr,
1141 fork_id: Option<ForkId>,
1142 ) {
1143 let ip_addr = addr.tcp().ip();
1144
1145 if !self.ip_filter.is_allowed(&ip_addr) {
1147 trace!(target: "net", ?peer_id, ?ip_addr, "Skipping outbound connection to IP not in allowed ranges");
1148 return
1149 }
1150
1151 if self.ban_list.is_banned(&peer_id, &ip_addr) {
1152 return
1153 }
1154
1155 match self.peers.entry(peer_id) {
1156 Entry::Occupied(mut entry) => {
1157 let peer = entry.get_mut();
1158 peer.kind = kind;
1159 peer.fork_id = fork_id.map(Box::new);
1160 peer.addr = addr;
1161
1162 if peer.state.is_idle() {
1163 peer.state = PeerConnectionState::PendingOut;
1165 self.connection_info.inc_pending_out();
1166 self.queued_actions
1167 .push_back(PeerAction::Connect { peer_id, remote_addr: addr.tcp() });
1168 }
1169 }
1170 Entry::Vacant(entry) => {
1171 trace!(target: "net::peers", ?peer_id, addr=?addr.tcp(), "connects new node");
1172 let mut peer = Peer::with_kind(addr, kind);
1173 peer.state = PeerConnectionState::PendingOut;
1174 peer.fork_id = fork_id.map(Box::new);
1175 entry.insert(peer);
1176 self.connection_info.inc_pending_out();
1177 self.queued_actions
1178 .push_back(PeerAction::Connect { peer_id, remote_addr: addr.tcp() });
1179 }
1180 }
1181
1182 if kind.is_trusted() {
1183 self.trusted_peer_ids.insert(peer_id);
1184 }
1185 }
1186
1187 pub(crate) fn remove_peer_from_trusted_set(&mut self, peer_id: PeerId) {
1189 self.trusted_peers_resolver.remove(peer_id);
1190 self.trusted_peer_ids.remove(&peer_id);
1191 if let Some(peer) = self.peers.get_mut(&peer_id) &&
1192 peer.is_trusted()
1193 {
1194 peer.kind = PeerKind::Basic;
1195 }
1196 }
1197
1198 fn best_unconnected(&mut self, trusted_only: bool) -> Option<(PeerId, &mut Peer)> {
1212 let mut unconnected = self.peers.iter_mut().filter(|(peer_id, peer)| {
1213 !peer.is_backed_off() &&
1214 !peer.is_banned() &&
1215 peer.state.is_unconnected() &&
1216 (!(self.trusted_nodes_only || trusted_only) ||
1217 peer.is_trusted() ||
1218 self.trusted_peer_ids.contains(*peer_id))
1219 });
1220
1221 let mut best_peer = unconnected.next()?;
1223
1224 if best_peer.1.is_trusted() ||
1225 best_peer.1.is_static() ||
1226 self.trusted_peer_ids.contains(best_peer.0)
1227 {
1228 return Some((*best_peer.0, best_peer.1))
1229 }
1230
1231 for maybe_better in unconnected {
1232 if maybe_better.1.is_trusted() ||
1234 maybe_better.1.is_static() ||
1235 self.trusted_peer_ids.contains(maybe_better.0)
1236 {
1237 return Some((*maybe_better.0, maybe_better.1))
1238 }
1239
1240 match maybe_better.1.reputation.cmp(&best_peer.1.reputation) {
1242 std::cmp::Ordering::Greater => best_peer = maybe_better,
1243 std::cmp::Ordering::Equal
1244 if maybe_better.1.fork_id.is_some() && best_peer.1.fork_id.is_none() =>
1245 {
1246 best_peer = maybe_better
1247 }
1248 _ => {}
1249 }
1250 }
1251 Some((*best_peer.0, best_peer.1))
1252 }
1253
1254 fn try_rotate_peer(&mut self) {
1261 let outbound_at_capacity = self.connection_info.is_outbound_at_capacity();
1262 let inbound_at_capacity = self.connection_info.is_inbound_at_capacity();
1263
1264 if !outbound_at_capacity && !inbound_at_capacity {
1265 return
1266 }
1267
1268 let now = std::time::Instant::now();
1269
1270 let candidates = self
1271 .peers
1272 .iter()
1273 .filter_map(|(peer_id, peer)| {
1274 let eligible = match peer.state {
1275 PeerConnectionState::Out => outbound_at_capacity,
1276 PeerConnectionState::In => inbound_at_capacity,
1277 _ => false,
1278 };
1279 (eligible &&
1280 !peer.is_trusted() &&
1281 !peer.is_static() &&
1282 !self.trusted_peer_ids.contains(peer_id) &&
1283 peer.connected_for_at_least(now, PEER_ROTATION_MIN_UPTIME))
1284 .then_some(*peer_id)
1285 })
1286 .collect::<Vec<_>>();
1287
1288 if candidates.is_empty() {
1289 return
1290 }
1291 let peer_id = candidates[rand::rng().random_range(0..candidates.len())];
1292
1293 trace!(target: "net::peers", ?peer_id, "rotating peer to open slot for new nodes");
1294
1295 self.queued_actions.push_back(PeerAction::Disconnect {
1296 peer_id,
1297 reason: Some(DisconnectReason::UselessPeer),
1298 });
1299 }
1300
1301 fn fill_outbound_slots(&mut self) {
1307 self.tick();
1308
1309 if !self.net_connection_state.is_active() {
1310 return
1312 }
1313
1314 while self.connection_info.has_out_dial_capacity() {
1316 let has_out_capacity = self.connection_info.has_out_capacity();
1319 let action = {
1320 let Some((peer_id, peer)) = self.best_unconnected(!has_out_capacity) else { break };
1321
1322 trace!(target: "net::peers", ?peer_id, addr=?peer.addr, "schedule outbound connection");
1323
1324 peer.state = PeerConnectionState::PendingOut;
1325 PeerAction::Connect { peer_id, remote_addr: peer.addr.tcp() }
1326 };
1327
1328 self.connection_info.inc_pending_out();
1329
1330 self.queued_actions.push_back(action);
1331 }
1332 }
1333
1334 fn on_resolved_peer(&mut self, peer_id: PeerId, new_record: NodeRecord) {
1335 if !self.trusted_peer_ids.contains(&peer_id) {
1336 trace!(target: "net::peers", ?peer_id, "Ignoring resolved trusted peer after removal");
1337 return
1338 }
1339
1340 if !self.ip_filter.is_allowed(&new_record.address) {
1341 trace!(target: "net::peers", ?peer_id, address=?new_record.address, "Ignoring resolved trusted peer address not in allowed ranges");
1342 return
1343 }
1344
1345 let new_addr = PeerAddr::new_with_ports(
1346 new_record.address,
1347 new_record.tcp_port,
1348 Some(new_record.udp_port),
1349 );
1350
1351 if let Some(peer) = self.peers.get_mut(&peer_id) {
1352 peer.kind = PeerKind::Trusted;
1355 if peer.state.is_incoming() {
1356 peer.remove_after_disconnect = false;
1358 }
1359 if peer.addr != new_addr {
1360 peer.addr = new_addr;
1361 trace!(target: "net::peers", ?peer_id, addr=?peer.addr, "Updated resolved trusted peer address");
1362 }
1363 } else {
1364 trace!(target: "net::peers", ?peer_id, ?new_addr, "Adding trusted peer after first successful resolution");
1365 self.add_peer_kind(peer_id, Some(PeerKind::Trusted), new_addr, None);
1366 }
1367 }
1368
1369 pub const fn on_network_state_change(&mut self, state: NetworkConnectionState) {
1371 self.net_connection_state = state;
1372 }
1373
1374 pub const fn connection_state(&self) -> &NetworkConnectionState {
1376 &self.net_connection_state
1377 }
1378
1379 pub const fn on_shutdown(&mut self) {
1381 self.net_connection_state = NetworkConnectionState::ShuttingDown;
1382 }
1383
1384 pub fn poll(&mut self, cx: &mut Context<'_>) -> Poll<PeerAction> {
1389 loop {
1390 if let Some(action) = self.queued_actions.pop_front() {
1392 return Poll::Ready(action)
1393 }
1394
1395 while let Poll::Ready(Some(cmd)) = self.handle_rx.poll_next_unpin(cx) {
1396 match cmd {
1397 PeerCommand::Add(peer_id, addr) => {
1398 self.add_requested_peer(peer_id, None, PeerAddr::from_tcp(addr));
1399 }
1400 PeerCommand::Remove(peer) => self.remove_peer(peer),
1401 PeerCommand::ReputationChange(peer_id, rep) => {
1402 self.apply_reputation_change(&peer_id, rep)
1403 }
1404 PeerCommand::GetPeer(peer, tx) => {
1405 let _ = tx.send(self.peers.get(&peer).cloned());
1406 }
1407 PeerCommand::GetPeers(tx) => {
1408 let _ = tx.send(self.iter_peers().collect());
1409 }
1410 }
1411 }
1412
1413 if self.release_interval.poll_tick(cx).is_ready() {
1414 let now = std::time::Instant::now();
1415 let (_, unbanned_peers) = self.ban_list.evict(now);
1416
1417 for peer_id in unbanned_peers {
1418 if let Some(peer) = self.peers.get_mut(&peer_id) {
1419 peer.unban();
1420 self.queued_actions.push_back(PeerAction::UnBanPeer { peer_id });
1421 }
1422 }
1423
1424 self.backed_off_peers.retain(|peer_id, until| {
1427 if now > *until {
1428 if let Some(peer) = self.peers.get_mut(peer_id) {
1429 peer.backed_off = false;
1430 }
1431 return false
1432 }
1433 true
1434 })
1435 }
1436
1437 while self.refill_slots_interval.poll_tick(cx).is_ready() {
1438 self.fill_outbound_slots();
1439 }
1440
1441 if let Poll::Ready((peer_id, new_record)) = self.trusted_peers_resolver.poll(cx) {
1442 self.on_resolved_peer(peer_id, new_record);
1443 }
1444
1445 let rotation_ready = self
1447 .peer_rotation_sleep
1448 .as_mut()
1449 .is_some_and(|sleep| sleep.as_mut().poll(cx).is_ready());
1450 if rotation_ready {
1451 self.try_rotate_peer();
1452 if let Some((mean, sleep)) =
1453 self.peer_rotation_mean.zip(self.peer_rotation_sleep.as_mut())
1454 {
1455 sleep
1456 .as_mut()
1457 .reset(tokio::time::Instant::now() + jitter_rotation_interval(mean));
1458 }
1459 }
1460
1461 if self.queued_actions.is_empty() {
1462 return Poll::Pending
1463 }
1464 }
1465 }
1466}
1467
1468impl Default for PeersManager {
1469 fn default() -> Self {
1470 Self::new(Default::default())
1471 }
1472}
1473
1474#[derive(Debug, Clone, PartialEq, Eq, Default)]
1476pub struct ConnectionInfo {
1477 num_outbound: usize,
1479 num_pending_out: usize,
1481 num_inbound: usize,
1483 num_pending_in: usize,
1485 config: ConnectionsConfig,
1487}
1488
1489impl ConnectionInfo {
1492 const fn new(config: ConnectionsConfig) -> Self {
1494 Self { config, num_outbound: 0, num_pending_out: 0, num_inbound: 0, num_pending_in: 0 }
1495 }
1496
1497 const fn has_out_capacity(&self) -> bool {
1499 self.has_out_dial_capacity() &&
1500 self.num_pending_out < self.config.max_outbound.saturating_sub(self.num_outbound)
1501 }
1502
1503 const fn is_outbound_at_capacity(&self) -> bool {
1505 self.num_outbound >= self.config.max_outbound
1506 }
1507
1508 const fn is_inbound_at_capacity(&self) -> bool {
1510 self.num_inbound >= self.config.max_inbound
1511 }
1512
1513 const fn has_in_capacity(&self) -> bool {
1515 self.num_inbound < self.config.max_inbound
1516 }
1517
1518 const fn has_in_pending_capacity(&self) -> bool {
1520 self.num_pending_in < self.config.max_inbound
1521 }
1522
1523 const fn has_out_dial_capacity(&self) -> bool {
1526 self.num_pending_out < self.config.max_concurrent_outbound_dials
1527 }
1528
1529 const fn decr_state(&mut self, state: PeerConnectionState) {
1530 match state {
1531 PeerConnectionState::Idle => {}
1532 PeerConnectionState::DisconnectingIn | PeerConnectionState::In => self.decr_in(),
1533 PeerConnectionState::DisconnectingOut | PeerConnectionState::Out => self.decr_out(),
1534 PeerConnectionState::PendingOut => self.decr_pending_out(),
1535 }
1536 }
1537
1538 const fn decr_out(&mut self) {
1539 self.num_outbound -= 1;
1540 }
1541
1542 const fn inc_out(&mut self) {
1543 self.num_outbound += 1;
1544 }
1545
1546 const fn inc_pending_out(&mut self) {
1547 self.num_pending_out += 1;
1548 }
1549
1550 const fn inc_in(&mut self) {
1551 self.num_inbound += 1;
1552 }
1553
1554 const fn inc_pending_in(&mut self) {
1555 self.num_pending_in += 1;
1556 }
1557
1558 const fn decr_in(&mut self) {
1559 self.num_inbound -= 1;
1560 }
1561
1562 const fn decr_pending_out(&mut self) {
1563 self.num_pending_out -= 1;
1564 }
1565
1566 const fn decr_pending_in(&mut self) {
1567 self.num_pending_in -= 1;
1568 }
1569}
1570
1571#[derive(Debug)]
1573pub enum PeerAction {
1574 Connect {
1576 peer_id: PeerId,
1578 remote_addr: SocketAddr,
1580 },
1581 Disconnect {
1583 peer_id: PeerId,
1585 reason: Option<DisconnectReason>,
1587 },
1588 DisconnectBannedIncoming {
1591 peer_id: PeerId,
1593 },
1594 DisconnectUntrustedIncoming {
1596 peer_id: PeerId,
1598 },
1599 DiscoveryBanPeerId {
1601 peer_id: PeerId,
1603 ip_addr: IpAddr,
1605 },
1606 DiscoveryBanIp {
1608 ip_addr: IpAddr,
1610 },
1611 BanPeer {
1613 peer_id: PeerId,
1615 },
1616 UnBanPeer {
1618 peer_id: PeerId,
1620 },
1621 PeerAdded(PeerId),
1623 PeerRemoved(PeerId),
1625}
1626
1627#[derive(Debug, Error, PartialEq, Eq)]
1629pub enum InboundConnectionError {
1630 IpBanned,
1632 ExceedsCapacity,
1634}
1635
1636impl Display for InboundConnectionError {
1637 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1638 write!(f, "{self:?}")
1639 }
1640}
1641
1642#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1644pub enum BackoffReason {
1645 TooManyPeers,
1647 GracefulClose,
1649 ConnectionError,
1651}
1652
1653impl BackoffReason {
1654 pub const fn from_disconnect(reason: Option<DisconnectReason>) -> Self {
1656 match reason {
1657 Some(DisconnectReason::TooManyPeers) => Self::TooManyPeers,
1658 _ => Self::ConnectionError,
1659 }
1660 }
1661}
1662
1663fn jitter_rotation_interval(mean: Duration) -> Duration {
1668 let min_nanos = (mean * 3 / 5).as_nanos() as u64;
1669 let max_nanos = (mean * 7 / 5).as_nanos() as u64;
1670 Duration::from_nanos(rand::rng().random_range(min_nanos..=max_nanos))
1671}
1672
1673#[cfg(test)]
1674mod tests {
1675 use super::*;
1676 use alloy_primitives::B512;
1677 use reth_ecies::ECIESErrorImpl;
1678 use reth_eth_wire::{
1679 errors::{EthHandshakeError, EthStreamError, P2PHandshakeError, P2PStreamError},
1680 DisconnectReason,
1681 };
1682 use reth_ethereum_forks::{ForkHash, ForkId};
1683 use reth_net_banlist::BanList;
1684 use reth_network_api::Direction;
1685 use reth_network_peers::{NodeRecord, PeerId, TrustedPeer};
1686 use reth_network_types::{
1687 peers::reputation::{BANNED_REPUTATION, DEFAULT_REPUTATION},
1688 BackoffKind, Peer, PeerKind, ReputationChangeKind,
1689 };
1690 use std::{
1691 future::{poll_fn, Future},
1692 io,
1693 net::{IpAddr, Ipv4Addr, SocketAddr},
1694 pin::Pin,
1695 task::{Context, Poll, Waker},
1696 time::Duration,
1697 };
1698 use url::Host;
1699
1700 use crate::{
1701 error::SessionError,
1702 peers::{
1703 ConnectionInfo, InboundConnectionError, PeerAction, PeerAddr, PeerBackoffDurations,
1704 PeerConnectionState, MAX_INCOMING_IP_THROTTLE_ENTRIES,
1705 },
1706 session::PendingSessionHandshakeError,
1707 PeersConfig,
1708 };
1709 use reth_net_banlist::IpFilter;
1710
1711 struct PeerActionFuture<'a> {
1712 peers: &'a mut PeersManager,
1713 }
1714
1715 impl Future for PeerActionFuture<'_> {
1716 type Output = PeerAction;
1717
1718 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1719 self.get_mut().peers.poll(cx)
1720 }
1721 }
1722
1723 macro_rules! event {
1724 ($peers:expr) => {
1725 PeerActionFuture { peers: &mut $peers }.await
1726 };
1727 }
1728
1729 fn set_connected_at(
1730 peers: &mut PeersManager,
1731 peer_id: PeerId,
1732 connected_at: std::time::Instant,
1733 ) {
1734 peers.peers.get_mut(&peer_id).expect("peer exists").connected_at = Some(connected_at);
1735 }
1736
1737 fn poll_now(peers: &mut PeersManager) -> Poll<PeerAction> {
1739 peers.poll(&mut Context::from_waker(Waker::noop()))
1740 }
1741
1742 #[tokio::test]
1743 async fn test_insert() {
1744 let peer = PeerId::random();
1745 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
1746 let mut peers = PeersManager::default();
1747 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
1748
1749 match event!(peers) {
1750 PeerAction::PeerAdded(peer_id) => {
1751 assert_eq!(peer_id, peer);
1752 }
1753 _ => unreachable!(),
1754 }
1755 match event!(peers) {
1756 PeerAction::Connect { peer_id, remote_addr } => {
1757 assert_eq!(peer_id, peer);
1758 assert_eq!(remote_addr, socket_addr);
1759 }
1760 _ => unreachable!(),
1761 }
1762
1763 let (record, _) = peers.peer_by_id(peer).unwrap();
1764 assert_eq!(record.tcp_addr(), socket_addr);
1765 assert_eq!(record.udp_addr(), socket_addr);
1766 }
1767
1768 #[tokio::test]
1769 async fn test_insert_udp() {
1770 let peer = PeerId::random();
1771 let tcp_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
1772 let udp_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
1773 let mut peers = PeersManager::default();
1774 peers.add_peer(peer, PeerAddr::new(tcp_addr, Some(udp_addr)), None);
1775
1776 match event!(peers) {
1777 PeerAction::PeerAdded(peer_id) => {
1778 assert_eq!(peer_id, peer);
1779 }
1780 _ => unreachable!(),
1781 }
1782 match event!(peers) {
1783 PeerAction::Connect { peer_id, remote_addr } => {
1784 assert_eq!(peer_id, peer);
1785 assert_eq!(remote_addr, tcp_addr);
1786 }
1787 _ => unreachable!(),
1788 }
1789
1790 let (record, _) = peers.peer_by_id(peer).unwrap();
1791 assert_eq!(record.tcp_addr(), tcp_addr);
1792 assert_eq!(record.udp_addr(), udp_addr);
1793 }
1794
1795 #[tokio::test]
1796 async fn test_ban() {
1797 let peer = PeerId::random();
1798 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
1799 let mut peers = PeersManager::default();
1800 peers.ban_peer(peer);
1801 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
1802
1803 match event!(peers) {
1804 PeerAction::BanPeer { peer_id } => {
1805 assert_eq!(peer_id, peer);
1806 }
1807 _ => unreachable!(),
1808 }
1809
1810 poll_fn(|cx| {
1811 assert!(peers.poll(cx).is_pending());
1812 Poll::Ready(())
1813 })
1814 .await;
1815 }
1816
1817 #[tokio::test]
1818 async fn test_unban() {
1819 let peer = PeerId::random();
1820 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
1821 let mut peers = PeersManager::default();
1822 peers.ban_peer(peer);
1823 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
1824
1825 match event!(peers) {
1826 PeerAction::BanPeer { peer_id } => {
1827 assert_eq!(peer_id, peer);
1828 }
1829 _ => unreachable!(),
1830 }
1831
1832 poll_fn(|cx| {
1833 assert!(peers.poll(cx).is_pending());
1834 Poll::Ready(())
1835 })
1836 .await;
1837
1838 peers.unban_peer(peer);
1839
1840 match event!(peers) {
1841 PeerAction::UnBanPeer { peer_id } => {
1842 assert_eq!(peer_id, peer);
1843 }
1844 _ => unreachable!(),
1845 }
1846
1847 poll_fn(|cx| {
1848 assert!(peers.poll(cx).is_pending());
1849 Poll::Ready(())
1850 })
1851 .await;
1852 }
1853
1854 #[tokio::test]
1855 async fn test_admin_ban_removes_peer_and_bans_indefinitely() {
1856 let peer = PeerId::random();
1857 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
1858 let mut peers = PeersManager::default();
1859 peers.peers.insert(peer, Peer::new(PeerAddr::from_tcp(socket_addr)));
1860
1861 peers.ban_peer_by_admin(peer);
1862
1863 assert!(peers.ban_list.is_banned_peer(&peer));
1864 assert!(peers.peer_by_id(peer).is_none());
1865
1866 match peers.queued_actions.pop_front() {
1867 Some(PeerAction::PeerRemoved(peer_id)) => assert_eq!(peer_id, peer),
1868 other => panic!("unexpected action: {other:?}"),
1869 }
1870
1871 let (_, unbanned_peers) =
1872 peers.ban_list.evict(std::time::Instant::now() + Duration::from_secs(1));
1873 assert!(unbanned_peers.is_empty());
1874 }
1875
1876 #[tokio::test]
1877 async fn test_admin_ban_does_not_override_trusted_peer() {
1878 let peer = PeerId::random();
1879 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
1880 let mut peers = PeersManager::default();
1881 peers.peers.insert(peer, Peer::trusted(PeerAddr::from_tcp(socket_addr)));
1882
1883 peers.ban_peer_by_admin(peer);
1884
1885 assert!(!peers.ban_list.is_banned_peer(&peer));
1886 assert!(peers.peer_by_id(peer).is_some());
1887 assert!(peers.queued_actions.is_empty());
1888 }
1889
1890 #[tokio::test]
1891 async fn test_admin_unban_resets_reputation() {
1892 let peer = PeerId::random();
1893 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
1894 let mut peers = PeersManager::default();
1895 let mut peer_info = Peer::new(PeerAddr::from_tcp(socket_addr));
1896 peer_info.reputation = i32::MIN;
1897 peers.peers.insert(peer, peer_info);
1898 peers.ban_list.ban_peer(peer);
1899 assert!(peers.peers.get(&peer).is_some_and(Peer::is_banned));
1900
1901 peers.unban_peer_by_admin(peer);
1902
1903 assert!(!peers.ban_list.is_banned_peer(&peer));
1904 assert!(!peers.peers.get(&peer).is_some_and(Peer::is_banned));
1905 assert!(matches!(
1906 peers.queued_actions.pop_front(),
1907 Some(PeerAction::UnBanPeer { peer_id }) if peer_id == peer
1908 ));
1909 }
1910
1911 #[tokio::test]
1912 async fn test_backoff_on_busy() {
1913 let peer = PeerId::random();
1914 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
1915
1916 let mut peers = PeersManager::new(PeersConfig::test());
1917 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
1918
1919 match event!(peers) {
1920 PeerAction::PeerAdded(peer_id) => {
1921 assert_eq!(peer_id, peer);
1922 }
1923 _ => unreachable!(),
1924 }
1925 match event!(peers) {
1926 PeerAction::Connect { peer_id, .. } => {
1927 assert_eq!(peer_id, peer);
1928 }
1929 _ => unreachable!(),
1930 }
1931
1932 poll_fn(|cx| {
1933 assert!(peers.poll(cx).is_pending());
1934 Poll::Ready(())
1935 })
1936 .await;
1937
1938 peers.on_active_session_dropped(
1939 &socket_addr,
1940 &peer,
1941 &EthStreamError::P2PStreamError(P2PStreamError::Disconnected(
1942 DisconnectReason::TooManyPeers,
1943 )),
1944 );
1945
1946 poll_fn(|cx| {
1947 assert!(peers.poll(cx).is_pending());
1948 Poll::Ready(())
1949 })
1950 .await;
1951
1952 assert!(peers.backed_off_peers.contains_key(&peer));
1953 assert!(peers.peers.get(&peer).unwrap().is_backed_off());
1954
1955 tokio::time::sleep(peers.backoff_durations.low).await;
1956
1957 match event!(peers) {
1958 PeerAction::Connect { peer_id, .. } => {
1959 assert_eq!(peer_id, peer);
1960 }
1961 _ => unreachable!(),
1962 }
1963
1964 assert!(!peers.backed_off_peers.contains_key(&peer));
1965 assert!(!peers.peers.get(&peer).unwrap().is_backed_off());
1966 }
1967
1968 #[tokio::test]
1969 async fn test_backoff_on_no_response() {
1970 let peer = PeerId::random();
1971 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
1972
1973 let backoff_durations = PeerBackoffDurations::test();
1974 let config = PeersConfig { backoff_durations, ..PeersConfig::test() };
1975 let mut peers = PeersManager::new(config);
1976 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
1977
1978 match event!(peers) {
1979 PeerAction::PeerAdded(peer_id) => {
1980 assert_eq!(peer_id, peer);
1981 }
1982 _ => unreachable!(),
1983 }
1984 match event!(peers) {
1985 PeerAction::Connect { peer_id, .. } => {
1986 assert_eq!(peer_id, peer);
1987 }
1988 _ => unreachable!(),
1989 }
1990
1991 poll_fn(|cx| {
1992 assert!(peers.poll(cx).is_pending());
1993 Poll::Ready(())
1994 })
1995 .await;
1996
1997 peers.on_outgoing_pending_session_dropped(
1998 &socket_addr,
1999 &peer,
2000 &PendingSessionHandshakeError::Eth(EthStreamError::EthHandshakeError(
2001 EthHandshakeError::NoResponse,
2002 )),
2003 );
2004
2005 poll_fn(|cx| {
2006 assert!(peers.poll(cx).is_pending());
2007 Poll::Ready(())
2008 })
2009 .await;
2010
2011 assert!(peers.backed_off_peers.contains_key(&peer));
2012 assert!(peers.peers.get(&peer).unwrap().is_backed_off());
2013
2014 tokio::time::sleep(backoff_durations.high).await;
2015
2016 match event!(peers) {
2017 PeerAction::Connect { peer_id, .. } => {
2018 assert_eq!(peer_id, peer);
2019 }
2020 _ => unreachable!(),
2021 }
2022
2023 assert!(!peers.backed_off_peers.contains_key(&peer));
2024 assert!(!peers.peers.get(&peer).unwrap().is_backed_off());
2025 }
2026
2027 #[tokio::test]
2028 async fn test_low_backoff() {
2029 let peer = PeerId::random();
2030 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2031 let config = PeersConfig::test();
2032 let mut peers = PeersManager::new(config);
2033 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
2034 let peer_struct = peers.peers.get_mut(&peer).unwrap();
2035
2036 let backoff_timestamp = peers
2037 .backoff_durations
2038 .backoff_until(BackoffKind::Low, peer_struct.severe_backoff_counter);
2039
2040 let expected = std::time::Instant::now() + peers.backoff_durations.low;
2041 assert!(backoff_timestamp <= expected);
2042 }
2043
2044 #[tokio::test]
2045 async fn test_multiple_backoff_calculations() {
2046 let peer = PeerId::random();
2047 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2048 let config = PeersConfig::default();
2049 let mut peers = PeersManager::new(config);
2050 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
2051 let peer_struct = peers.peers.get_mut(&peer).unwrap();
2052
2053 peer_struct.severe_backoff_counter = 1;
2055
2056 let now = std::time::Instant::now();
2057
2058 peer_struct.severe_backoff_counter += 1;
2060 let backoff_time = peers
2062 .backoff_durations
2063 .backoff_until(BackoffKind::High, peer_struct.severe_backoff_counter);
2064
2065 let backoff_duration = std::time::Duration::new(30 * 60, 0);
2067
2068 assert!(backoff_time.duration_since(now) > backoff_duration);
2071 }
2072
2073 #[tokio::test]
2074 async fn test_ban_on_active_drop() {
2075 let peer = PeerId::random();
2076 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2077 let mut peers = PeersManager::default();
2078 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
2079
2080 match event!(peers) {
2081 PeerAction::PeerAdded(peer_id) => {
2082 assert_eq!(peer_id, peer);
2083 }
2084 _ => unreachable!(),
2085 }
2086 match event!(peers) {
2087 PeerAction::Connect { peer_id, .. } => {
2088 assert_eq!(peer_id, peer);
2089 }
2090 _ => unreachable!(),
2091 }
2092
2093 poll_fn(|cx| {
2094 assert!(peers.poll(cx).is_pending());
2095 Poll::Ready(())
2096 })
2097 .await;
2098
2099 peers.on_active_session_dropped(
2100 &socket_addr,
2101 &peer,
2102 &EthStreamError::P2PStreamError(P2PStreamError::Disconnected(
2103 DisconnectReason::UselessPeer,
2104 )),
2105 );
2106
2107 match event!(peers) {
2108 PeerAction::PeerRemoved(peer_id) => {
2109 assert_eq!(peer_id, peer);
2110 }
2111 _ => unreachable!(),
2112 }
2113 match event!(peers) {
2114 PeerAction::BanPeer { peer_id } => {
2115 assert_eq!(peer_id, peer);
2116 }
2117 _ => unreachable!(),
2118 }
2119
2120 poll_fn(|cx| {
2121 assert!(peers.poll(cx).is_pending());
2122 Poll::Ready(())
2123 })
2124 .await;
2125
2126 assert!(!peers.peers.contains_key(&peer));
2127 }
2128
2129 #[tokio::test]
2130 async fn test_remove_on_max_backoff_count() {
2131 let peer = PeerId::random();
2132 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2133 let config = PeersConfig::test();
2134 let mut peers = PeersManager::new(config.clone());
2135 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
2136 let peer_struct = peers.peers.get_mut(&peer).unwrap();
2137
2138 peer_struct.severe_backoff_counter = config.max_backoff_count;
2140
2141 match event!(peers) {
2142 PeerAction::PeerAdded(peer_id) => {
2143 assert_eq!(peer_id, peer);
2144 }
2145 _ => unreachable!(),
2146 }
2147 match event!(peers) {
2148 PeerAction::Connect { peer_id, .. } => {
2149 assert_eq!(peer_id, peer);
2150 }
2151 _ => unreachable!(),
2152 }
2153
2154 poll_fn(|cx| {
2155 assert!(peers.poll(cx).is_pending());
2156 Poll::Ready(())
2157 })
2158 .await;
2159
2160 peers.on_outgoing_connection_failure(
2161 &socket_addr,
2162 &peer,
2163 &io::Error::new(io::ErrorKind::ConnectionRefused, "peer unreachable"),
2164 );
2165
2166 match event!(peers) {
2167 PeerAction::PeerRemoved(peer_id) => {
2168 assert_eq!(peer_id, peer);
2169 }
2170 _ => unreachable!(),
2171 }
2172
2173 poll_fn(|cx| {
2174 assert!(peers.poll(cx).is_pending());
2175 Poll::Ready(())
2176 })
2177 .await;
2178
2179 assert!(!peers.peers.contains_key(&peer));
2180 }
2181
2182 #[tokio::test]
2183 async fn test_remove_disconnecting_peer_on_active_drop() {
2184 let peer = PeerId::random();
2185 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2186 let mut peers = PeersManager::default();
2187 peers.add_and_connect(peer, PeerAddr::from_tcp(socket_addr), None);
2188 peers.on_active_outgoing_established(peer);
2189
2190 peers.remove_peer(peer);
2191 assert_eq!(peers.peers.get(&peer).unwrap().state, PeerConnectionState::DisconnectingOut);
2192
2193 peers.on_active_session_dropped(
2194 &socket_addr,
2195 &peer,
2196 &EthStreamError::P2PStreamError(P2PStreamError::Disconnected(
2197 DisconnectReason::TooManyPeers,
2198 )),
2199 );
2200
2201 assert!(!peers.peers.contains_key(&peer));
2202 assert_eq!(peers.connection_info.num_outbound, 0);
2203 }
2204
2205 #[tokio::test]
2206 async fn test_keep_banned_static_peer_on_active_drop() {
2207 let peer = PeerId::random();
2208 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2209 let mut peers = PeersManager::default();
2210 peers.add_and_connect_kind(peer, PeerKind::Static, PeerAddr::from_tcp(socket_addr), None);
2211 peers.on_active_outgoing_established(peer);
2212
2213 peers.peers.get_mut(&peer).unwrap().reputation = BANNED_REPUTATION;
2214 peers.apply_reputation_change(&peer, ReputationChangeKind::BadMessage);
2215 assert_eq!(peers.peers.get(&peer).unwrap().state, PeerConnectionState::DisconnectingOut);
2216
2217 peers.on_active_session_dropped(
2218 &socket_addr,
2219 &peer,
2220 &EthStreamError::P2PStreamError(P2PStreamError::Disconnected(
2221 DisconnectReason::TooManyPeers,
2222 )),
2223 );
2224
2225 assert_eq!(peers.peers.get(&peer).unwrap().state, PeerConnectionState::Idle);
2226 assert_eq!(peers.connection_info.num_outbound, 0);
2227 }
2228
2229 #[tokio::test]
2230 async fn test_ban_on_pending_drop() {
2231 let peer = PeerId::random();
2232 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2233 let mut peers = PeersManager::default();
2234 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
2235
2236 match event!(peers) {
2237 PeerAction::PeerAdded(peer_id) => {
2238 assert_eq!(peer_id, peer);
2239 }
2240 _ => unreachable!(),
2241 }
2242 match event!(peers) {
2243 PeerAction::Connect { peer_id, .. } => {
2244 assert_eq!(peer_id, peer);
2245 }
2246 _ => unreachable!(),
2247 }
2248
2249 poll_fn(|cx| {
2250 assert!(peers.poll(cx).is_pending());
2251 Poll::Ready(())
2252 })
2253 .await;
2254
2255 peers.on_outgoing_pending_session_dropped(
2256 &socket_addr,
2257 &peer,
2258 &PendingSessionHandshakeError::Eth(EthStreamError::P2PStreamError(
2259 P2PStreamError::Disconnected(DisconnectReason::UselessPeer),
2260 )),
2261 );
2262
2263 match event!(peers) {
2264 PeerAction::PeerRemoved(peer_id) => {
2265 assert_eq!(peer_id, peer);
2266 }
2267 _ => unreachable!(),
2268 }
2269 match event!(peers) {
2270 PeerAction::BanPeer { peer_id } => {
2271 assert_eq!(peer_id, peer);
2272 }
2273 _ => unreachable!(),
2274 }
2275
2276 poll_fn(|cx| {
2277 assert!(peers.poll(cx).is_pending());
2278 Poll::Ready(())
2279 })
2280 .await;
2281
2282 assert!(!peers.peers.contains_key(&peer));
2283 }
2284
2285 #[tokio::test]
2286 async fn test_internally_closed_incoming() {
2287 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2288 let mut peers = PeersManager::default();
2289
2290 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
2291 assert_eq!(peers.connection_info.num_pending_in, 1);
2292 peers.on_incoming_pending_session_rejected_internally();
2293 assert_eq!(peers.connection_info.num_pending_in, 0);
2294 }
2295
2296 #[tokio::test]
2297 async fn test_reject_incoming_at_pending_capacity() {
2298 let mut peers = PeersManager::default();
2299
2300 for count in 1..=peers.connection_info.config.max_inbound {
2301 let socket_addr =
2302 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, count as u8)), 8008);
2303 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
2304 assert_eq!(peers.connection_info.num_pending_in, count);
2305 }
2306 assert!(peers.connection_info.has_in_capacity());
2307 assert!(!peers.connection_info.has_in_pending_capacity());
2308
2309 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 100)), 8008);
2310 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_err());
2311 }
2312
2313 #[tokio::test]
2314 async fn test_reject_incoming_at_pending_capacity_trusted_peers() {
2315 let mut peers = PeersManager::new(PeersConfig::test().with_max_inbound(2));
2316 let trusted = PeerId::random();
2317 peers.add_trusted_peer_id(trusted);
2318
2319 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 0)), 8008);
2321 assert!(peers.on_incoming_pending_session(addr.ip()).is_ok());
2322 peers.on_incoming_session_established(trusted, addr);
2323
2324 match event!(peers) {
2325 PeerAction::PeerAdded(id) => {
2326 assert_eq!(id, trusted);
2327 }
2328 _ => unreachable!(),
2329 }
2330
2331 let mut connected_untrusted_peer_ids = Vec::new();
2333 for i in 0..(peers.connection_info.config.max_inbound - 1) {
2334 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, (i + 1) as u8)), 8008);
2335 assert!(peers.on_incoming_pending_session(addr.ip()).is_ok());
2336 let peer_id = PeerId::random();
2337 peers.on_incoming_session_established(peer_id, addr);
2338 connected_untrusted_peer_ids.push(peer_id);
2339
2340 match event!(peers) {
2341 PeerAction::PeerAdded(id) => {
2342 assert_eq!(id, peer_id);
2343 }
2344 _ => unreachable!(),
2345 }
2346 }
2347
2348 let mut pending_addrs = Vec::new();
2349
2350 for i in 0..2 {
2352 let socket_addr =
2353 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, (i + 10) as u8)), 8008);
2354 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
2355
2356 pending_addrs.push(socket_addr);
2357 }
2358
2359 assert_eq!(peers.connection_info.num_pending_in, 2);
2360
2361 for i in 0..2 {
2363 let socket_addr =
2364 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, (i + 20) as u8)), 8008);
2365 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_err());
2366 }
2367
2368 let err = PendingSessionHandshakeError::Eth(EthStreamError::P2PStreamError(
2369 P2PStreamError::HandshakeError(P2PHandshakeError::Disconnected(
2370 DisconnectReason::UselessPeer,
2371 )),
2372 ));
2373
2374 for pending_addr in pending_addrs {
2376 peers.on_incoming_pending_session_dropped(pending_addr, &err);
2377 }
2378
2379 println!("num_pending_in: {}", peers.connection_info.num_pending_in);
2380
2381 println!(
2382 "num_inbound: {}, has_in_capacity: {}",
2383 peers.connection_info.num_inbound,
2384 peers.connection_info.has_in_capacity()
2385 );
2386
2387 peers.on_active_session_gracefully_closed(connected_untrusted_peer_ids[0]);
2389
2390 println!(
2391 "num_inbound: {}, has_in_capacity: {}",
2392 peers.connection_info.num_inbound,
2393 peers.connection_info.has_in_capacity()
2394 );
2395
2396 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 99)), 8008);
2397 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
2398 }
2399
2400 #[tokio::test]
2401 async fn test_closed_incoming() {
2402 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2403 let mut peers = PeersManager::default();
2404
2405 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
2406 assert_eq!(peers.connection_info.num_pending_in, 1);
2407 peers.on_incoming_pending_session_gracefully_closed();
2408 assert_eq!(peers.connection_info.num_pending_in, 0);
2409 }
2410
2411 #[tokio::test]
2412 async fn test_dropped_incoming() {
2413 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(1, 0, 1, 2)), 8008);
2414 let ban_duration = Duration::from_millis(500);
2415 let config = PeersConfig {
2416 ban_duration,
2417 incoming_ip_throttle_duration: ban_duration,
2418 ..PeersConfig::test()
2419 };
2420 let mut peers = PeersManager::new(config);
2421
2422 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
2423 assert_eq!(peers.connection_info.num_pending_in, 1);
2424 let err = PendingSessionHandshakeError::Eth(EthStreamError::P2PStreamError(
2425 P2PStreamError::HandshakeError(P2PHandshakeError::Disconnected(
2426 DisconnectReason::UselessPeer,
2427 )),
2428 ));
2429
2430 peers.on_incoming_pending_session_dropped(socket_addr, &err);
2431 assert_eq!(peers.connection_info.num_pending_in, 0);
2432 assert!(peers.ban_list.is_banned_ip(&socket_addr.ip()));
2433
2434 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_err());
2435
2436 tokio::time::sleep(ban_duration).await;
2438
2439 poll_fn(|cx| {
2440 let _ = peers.poll(cx);
2441 Poll::Ready(())
2442 })
2443 .await;
2444
2445 assert!(!peers.ban_list.is_banned_ip(&socket_addr.ip()));
2446 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
2447 }
2448
2449 #[tokio::test]
2450 async fn test_reputation_change_connected() {
2451 let peer = PeerId::random();
2452 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2453 let mut peers = PeersManager::default();
2454 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
2455
2456 match event!(peers) {
2457 PeerAction::PeerAdded(peer_id) => {
2458 assert_eq!(peer_id, peer);
2459 }
2460 _ => unreachable!(),
2461 }
2462 match event!(peers) {
2463 PeerAction::Connect { peer_id, remote_addr } => {
2464 assert_eq!(peer_id, peer);
2465 assert_eq!(remote_addr, socket_addr);
2466 }
2467 _ => unreachable!(),
2468 }
2469
2470 let p = peers.peers.get_mut(&peer).unwrap();
2471 assert_eq!(p.state, PeerConnectionState::PendingOut);
2472
2473 peers.apply_reputation_change(&peer, ReputationChangeKind::BadProtocol);
2474
2475 let p = peers.peers.get(&peer).unwrap();
2476 assert_eq!(p.state, PeerConnectionState::PendingOut);
2477 assert!(p.is_banned());
2478
2479 peers.on_active_session_gracefully_closed(peer);
2480
2481 let p = peers.peers.get(&peer).unwrap();
2482 assert_eq!(p.state, PeerConnectionState::Idle);
2483 assert!(p.is_banned());
2484
2485 match event!(peers) {
2486 PeerAction::Disconnect { peer_id, .. } => {
2487 assert_eq!(peer_id, peer);
2488 }
2489 _ => unreachable!(),
2490 }
2491 }
2492
2493 #[tokio::test]
2494 async fn retain_trusted_status() {
2495 let _socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 99)), 8008);
2496 let trusted = PeerId::random();
2497 let mut peers =
2498 PeersManager::new(PeersConfig::test().with_trusted_nodes(vec![TrustedPeer {
2499 host: Host::Ipv4(Ipv4Addr::new(127, 0, 1, 2)),
2500 tcp_port: 8008,
2501 udp_port: 8008,
2502 id: trusted,
2503 }]));
2504 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2505 peers.add_peer(trusted, PeerAddr::from_tcp(socket_addr), None);
2506 assert!(peers.peers.get(&trusted).unwrap().is_trusted());
2507 }
2508
2509 #[tokio::test]
2510 async fn accept_incoming_trusted_unknown_peer_address() {
2511 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 99)), 8008);
2512 let mut peers = PeersManager::new(PeersConfig::test().with_max_inbound(2));
2513 let trusted = PeerId::random();
2515 peers.add_trusted_peer_id(trusted);
2516
2517 for i in 0..peers.connection_info.config.max_inbound {
2519 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, i as u8)), 8008);
2520 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
2521 let peer_id = PeerId::random();
2522 peers.on_incoming_session_established(peer_id, addr);
2523
2524 match event!(peers) {
2525 PeerAction::PeerAdded(id) => {
2526 assert_eq!(id, peer_id);
2527 }
2528 _ => unreachable!(),
2529 }
2530 }
2531
2532 let untrusted = PeerId::random();
2534 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 99)), 8008);
2535 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
2536 peers.on_incoming_session_established(untrusted, socket_addr);
2537
2538 match event!(peers) {
2539 PeerAction::PeerAdded(id) => {
2540 assert_eq!(id, untrusted);
2541 }
2542 _ => unreachable!(),
2543 }
2544
2545 match event!(peers) {
2546 PeerAction::Disconnect { peer_id, reason } => {
2547 assert_eq!(peer_id, untrusted);
2548 assert_eq!(reason, Some(DisconnectReason::TooManyPeers));
2549 }
2550 _ => unreachable!(),
2551 }
2552
2553 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 100)), 8008);
2554 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
2555 peers.on_incoming_session_established(trusted, socket_addr);
2556
2557 match event!(peers) {
2558 PeerAction::PeerAdded(id) => {
2559 assert_eq!(id, trusted);
2560 }
2561 _ => unreachable!(),
2562 }
2563
2564 poll_fn(|cx| {
2565 assert!(peers.poll(cx).is_pending());
2566 Poll::Ready(())
2567 })
2568 .await;
2569
2570 let peer = peers.peers.get(&trusted).unwrap();
2571 assert_eq!(peer.state, PeerConnectionState::In);
2572 }
2573
2574 #[tokio::test]
2575 async fn test_already_connected() {
2576 let peer = PeerId::random();
2577 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2578 let mut peers = PeersManager::default();
2579
2580 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
2582 assert_eq!(peers.connection_info.num_pending_in, 1);
2583
2584 peers.on_incoming_session_established(peer, socket_addr);
2587 let p = peers.peers.get_mut(&peer).expect("peer not found");
2588 assert_eq!(p.addr.tcp(), socket_addr);
2589 assert_eq!(peers.connection_info.num_pending_in, 0);
2590 assert_eq!(peers.connection_info.num_inbound, 1);
2591
2592 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
2595 assert_eq!(peers.connection_info.num_pending_in, 1);
2596
2597 peers.on_already_connected(Direction::Incoming);
2601
2602 let p = peers.peers.get_mut(&peer).expect("peer not found");
2603 assert_eq!(p.addr.tcp(), socket_addr);
2604 assert_eq!(peers.connection_info.num_pending_in, 0);
2605 assert_eq!(peers.connection_info.num_inbound, 1);
2606 }
2607
2608 #[tokio::test]
2609 async fn test_reputation_change_trusted_peer() {
2610 let peer = PeerId::random();
2611 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2612 let mut peers = PeersManager::default();
2613 peers.add_trusted_peer(peer, PeerAddr::from_tcp(socket_addr));
2614
2615 match event!(peers) {
2616 PeerAction::PeerAdded(peer_id) => {
2617 assert_eq!(peer_id, peer);
2618 }
2619 _ => unreachable!(),
2620 }
2621 match event!(peers) {
2622 PeerAction::Connect { peer_id, remote_addr } => {
2623 assert_eq!(peer_id, peer);
2624 assert_eq!(remote_addr, socket_addr);
2625 }
2626 _ => unreachable!(),
2627 }
2628
2629 assert_eq!(peers.peers.get_mut(&peer).unwrap().state, PeerConnectionState::PendingOut);
2630 peers.on_active_outgoing_established(peer);
2631 assert_eq!(peers.peers.get_mut(&peer).unwrap().state, PeerConnectionState::Out);
2632
2633 peers.apply_reputation_change(&peer, ReputationChangeKind::BadMessage);
2634
2635 {
2636 let p = peers.peers.get(&peer).unwrap();
2637 assert_eq!(p.state, PeerConnectionState::Out);
2638 assert!(!p.is_banned());
2640 }
2641
2642 loop {
2644 peers.apply_reputation_change(&peer, ReputationChangeKind::BadMessage);
2645
2646 let p = peers.peers.get(&peer).unwrap();
2647 if p.is_banned() {
2648 break
2649 }
2650 }
2651
2652 match event!(peers) {
2653 PeerAction::Disconnect { peer_id, .. } => {
2654 assert_eq!(peer_id, peer);
2655 }
2656 _ => unreachable!(),
2657 }
2658 }
2659
2660 #[tokio::test]
2661 async fn test_reputation_management() {
2662 let peer = PeerId::random();
2663 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2664 let mut peers = PeersManager::default();
2665 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
2666 assert_eq!(peers.get_reputation(&peer), Some(0));
2667
2668 peers.apply_reputation_change(&peer, ReputationChangeKind::Other(1024));
2669 assert_eq!(peers.get_reputation(&peer), Some(1024));
2670
2671 peers.apply_reputation_change(&peer, ReputationChangeKind::Reset);
2672 assert_eq!(peers.get_reputation(&peer), Some(0));
2673 }
2674
2675 #[tokio::test]
2676 async fn test_remove_discovered_active() {
2677 let peer = PeerId::random();
2678 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2679 let mut peers = PeersManager::default();
2680 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
2681
2682 match event!(peers) {
2683 PeerAction::PeerAdded(peer_id) => {
2684 assert_eq!(peer_id, peer);
2685 }
2686 _ => unreachable!(),
2687 }
2688 match event!(peers) {
2689 PeerAction::Connect { peer_id, remote_addr } => {
2690 assert_eq!(peer_id, peer);
2691 assert_eq!(remote_addr, socket_addr);
2692 }
2693 _ => unreachable!(),
2694 }
2695
2696 let p = peers.peers.get(&peer).unwrap();
2697 assert_eq!(p.state, PeerConnectionState::PendingOut);
2698
2699 peers.remove_peer(peer);
2700
2701 match event!(peers) {
2702 PeerAction::PeerRemoved(peer_id) => {
2703 assert_eq!(peer_id, peer);
2704 }
2705 _ => unreachable!(),
2706 }
2707 match event!(peers) {
2708 PeerAction::Disconnect { peer_id, .. } => {
2709 assert_eq!(peer_id, peer);
2710 }
2711 _ => unreachable!(),
2712 }
2713
2714 let p = peers.peers.get(&peer).unwrap();
2715 assert_eq!(p.state, PeerConnectionState::PendingOut);
2716
2717 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
2718 let p = peers.peers.get(&peer).unwrap();
2719 assert_eq!(p.state, PeerConnectionState::PendingOut);
2720
2721 peers.on_active_session_gracefully_closed(peer);
2722 assert!(!peers.peers.contains_key(&peer));
2723 }
2724
2725 #[tokio::test]
2726 async fn test_fatal_outgoing_connection_error_trusted() {
2727 let peer = PeerId::random();
2728 let config = PeersConfig::test()
2729 .with_trusted_nodes(vec![TrustedPeer {
2730 host: Host::Ipv4(Ipv4Addr::new(127, 0, 1, 2)),
2731 tcp_port: 8008,
2732 udp_port: 8008,
2733 id: peer,
2734 }])
2735 .with_trusted_nodes_only(true);
2736 let mut peers = PeersManager::new(config);
2737 let socket_addr = peers.peers.get(&peer).unwrap().addr.tcp();
2738
2739 match event!(peers) {
2740 PeerAction::Connect { peer_id, remote_addr } => {
2741 assert_eq!(peer_id, peer);
2742 assert_eq!(remote_addr, socket_addr);
2743 }
2744 _ => unreachable!(),
2745 }
2746
2747 let p = peers.peers.get(&peer).unwrap();
2748 assert_eq!(p.state, PeerConnectionState::PendingOut);
2749
2750 assert_eq!(peers.num_outbound_connections(), 0);
2751
2752 let err = PendingSessionHandshakeError::Eth(EthStreamError::EthHandshakeError(
2753 EthHandshakeError::NonStatusMessageInHandshake,
2754 ));
2755 assert!(err.is_fatal_protocol_error());
2756
2757 peers.on_outgoing_pending_session_dropped(&socket_addr, &peer, &err);
2758 assert_eq!(peers.num_outbound_connections(), 0);
2759
2760 match event!(peers) {
2762 PeerAction::BanPeer { peer_id } => {
2763 assert_eq!(peer_id, peer);
2764 }
2765 err => unreachable!("{err:?}"),
2766 }
2767
2768 assert!(peers.peers.contains_key(&peer));
2770
2771 tokio::time::sleep(peers.backoff_durations.medium).await;
2773
2774 match event!(peers) {
2775 PeerAction::Connect { peer_id, remote_addr } => {
2776 assert_eq!(peer_id, peer);
2777 assert_eq!(remote_addr, socket_addr);
2778 }
2779 err => unreachable!("{err:?}"),
2780 }
2781 }
2782
2783 #[tokio::test]
2784 async fn test_outgoing_connection_error() {
2785 let peer = PeerId::random();
2786 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2787 let mut peers = PeersManager::default();
2788 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
2789
2790 match event!(peers) {
2791 PeerAction::PeerAdded(peer_id) => {
2792 assert_eq!(peer_id, peer);
2793 }
2794 _ => unreachable!(),
2795 }
2796 match event!(peers) {
2797 PeerAction::Connect { peer_id, remote_addr } => {
2798 assert_eq!(peer_id, peer);
2799 assert_eq!(remote_addr, socket_addr);
2800 }
2801 _ => unreachable!(),
2802 }
2803
2804 let p = peers.peers.get(&peer).unwrap();
2805 assert_eq!(p.state, PeerConnectionState::PendingOut);
2806
2807 assert_eq!(peers.num_outbound_connections(), 0);
2808
2809 peers.on_outgoing_connection_failure(
2810 &socket_addr,
2811 &peer,
2812 &io::Error::new(io::ErrorKind::ConnectionRefused, ""),
2813 );
2814
2815 assert_eq!(peers.num_outbound_connections(), 0);
2816 }
2817
2818 #[tokio::test]
2819 async fn test_outgoing_connection_gracefully_closed() {
2820 let peer = PeerId::random();
2821 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2822 let mut peers = PeersManager::default();
2823 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
2824
2825 match event!(peers) {
2826 PeerAction::PeerAdded(peer_id) => {
2827 assert_eq!(peer_id, peer);
2828 }
2829 _ => unreachable!(),
2830 }
2831 match event!(peers) {
2832 PeerAction::Connect { peer_id, remote_addr } => {
2833 assert_eq!(peer_id, peer);
2834 assert_eq!(remote_addr, socket_addr);
2835 }
2836 _ => unreachable!(),
2837 }
2838
2839 let p = peers.peers.get(&peer).unwrap();
2840 assert_eq!(p.state, PeerConnectionState::PendingOut);
2841
2842 assert_eq!(peers.num_outbound_connections(), 0);
2843
2844 peers.on_outgoing_pending_session_gracefully_closed(&peer);
2845
2846 assert_eq!(peers.num_outbound_connections(), 0);
2847 assert_eq!(peers.connection_info.num_pending_out, 0);
2848 }
2849
2850 #[tokio::test]
2851 async fn test_discovery_ban_list() {
2852 let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2));
2853 let socket_addr = SocketAddr::new(ip, 8008);
2854 let ban_list = BanList::new(vec![], vec![ip]);
2855 let config = PeersConfig::default().with_ban_list(ban_list);
2856 let mut peer_manager = PeersManager::new(config);
2857 peer_manager.add_peer(B512::default(), PeerAddr::from_tcp(socket_addr), None);
2858
2859 assert!(peer_manager.peers.is_empty());
2860 }
2861
2862 #[tokio::test]
2863 async fn test_on_pending_ban_list() {
2864 let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2));
2865 let socket_addr = SocketAddr::new(ip, 8008);
2866 let ban_list = BanList::new(vec![], vec![ip]);
2867 let config = PeersConfig::test().with_ban_list(ban_list);
2868 let mut peer_manager = PeersManager::new(config);
2869 let a = peer_manager.on_incoming_pending_session(socket_addr.ip());
2870 match a {
2872 Ok(_) => panic!(),
2873 Err(err) => match err {
2874 InboundConnectionError::IpBanned => {
2875 assert_eq!(peer_manager.connection_info.num_pending_in, 0)
2876 }
2877 _ => unreachable!(),
2878 },
2879 }
2880 }
2881
2882 #[tokio::test]
2883 async fn test_on_active_inbound_ban_list() {
2884 let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2));
2885 let socket_addr = SocketAddr::new(ip, 8008);
2886 let given_peer_id = PeerId::random();
2887 let ban_list = BanList::new(vec![given_peer_id], vec![]);
2888 let config = PeersConfig::test().with_ban_list(ban_list);
2889 let mut peer_manager = PeersManager::new(config);
2890 assert!(peer_manager.on_incoming_pending_session(socket_addr.ip()).is_ok());
2891 assert_eq!(peer_manager.connection_info.num_pending_in, 1);
2893 assert_eq!(
2894 peer_manager.inbound_session_rejection(given_peer_id),
2895 Some(DisconnectReason::DisconnectRequested)
2896 );
2897 peer_manager.on_incoming_session_established(given_peer_id, socket_addr);
2898 assert_eq!(peer_manager.connection_info.num_pending_in, 0);
2901 assert_eq!(peer_manager.connection_info.num_inbound, 0);
2902
2903 let Some(PeerAction::DisconnectBannedIncoming { peer_id }) =
2904 peer_manager.queued_actions.pop_front()
2905 else {
2906 panic!()
2907 };
2908
2909 assert_eq!(peer_id, given_peer_id)
2910 }
2911
2912 #[test]
2913 fn test_connection_limits() {
2914 let mut info = ConnectionInfo::default();
2915 info.inc_in();
2916 assert_eq!(info.num_inbound, 1);
2917 assert_eq!(info.num_outbound, 0);
2918 assert!(info.has_in_capacity());
2919
2920 info.decr_in();
2921 assert_eq!(info.num_inbound, 0);
2922 assert_eq!(info.num_outbound, 0);
2923
2924 info.inc_out();
2925 assert_eq!(info.num_inbound, 0);
2926 assert_eq!(info.num_outbound, 1);
2927 assert!(info.has_out_capacity());
2928
2929 info.decr_out();
2930 assert_eq!(info.num_inbound, 0);
2931 assert_eq!(info.num_outbound, 0);
2932 }
2933
2934 #[test]
2935 fn test_connection_peer_state() {
2936 let mut info = ConnectionInfo::default();
2937 info.inc_in();
2938
2939 info.decr_state(PeerConnectionState::In);
2940 assert_eq!(info.num_inbound, 0);
2941 assert_eq!(info.num_outbound, 0);
2942
2943 info.inc_out();
2944
2945 info.decr_state(PeerConnectionState::Out);
2946 assert_eq!(info.num_inbound, 0);
2947 assert_eq!(info.num_outbound, 0);
2948 }
2949
2950 #[tokio::test]
2951 async fn test_trusted_peers_are_prioritized() {
2952 let trusted_peer = PeerId::random();
2953 let trusted_sock = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2954 let config = PeersConfig::test().with_trusted_nodes(vec![TrustedPeer {
2955 host: Host::Ipv4(Ipv4Addr::new(127, 0, 1, 2)),
2956 tcp_port: 8008,
2957 udp_port: 8008,
2958 id: trusted_peer,
2959 }]);
2960 let mut peers = PeersManager::new(config);
2961
2962 let basic_peer = PeerId::random();
2963 let basic_sock = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
2964 peers.add_peer(basic_peer, PeerAddr::from_tcp(basic_sock), None);
2965
2966 match event!(peers) {
2967 PeerAction::PeerAdded(peer_id) => {
2968 assert_eq!(peer_id, basic_peer);
2969 }
2970 _ => unreachable!(),
2971 }
2972 match event!(peers) {
2973 PeerAction::Connect { peer_id, remote_addr } => {
2974 assert_eq!(peer_id, trusted_peer);
2975 assert_eq!(remote_addr, trusted_sock);
2976 }
2977 _ => unreachable!(),
2978 }
2979 match event!(peers) {
2980 PeerAction::Connect { peer_id, remote_addr } => {
2981 assert_eq!(peer_id, basic_peer);
2982 assert_eq!(remote_addr, basic_sock);
2983 }
2984 _ => unreachable!(),
2985 }
2986 }
2987
2988 #[tokio::test]
2989 async fn test_trusted_peers_bypass_outbound_capacity() {
2990 let mut peers = PeersManager::new(PeersConfig::test().with_max_outbound(1));
2991
2992 let basic_peer = PeerId::random();
2994 let basic_sock = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
2995 peers.add_peer(basic_peer, PeerAddr::from_tcp(basic_sock), None);
2996 peers.fill_outbound_slots();
2997 peers.on_active_outgoing_established(basic_peer);
2998 assert!(!peers.connection_info.has_out_capacity());
2999 peers.queued_actions.clear();
3000
3001 let static_peer = PeerId::random();
3002 peers.add_peer_kind(
3003 static_peer,
3004 Some(PeerKind::Static),
3005 PeerAddr::from_tcp(basic_sock),
3006 None,
3007 );
3008 assert!(peers.best_unconnected(true).is_none());
3009 peers.queued_actions.clear();
3010
3011 let trusted_peer = PeerId::random();
3013 let trusted_sock = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 3)), 8008);
3014 peers.add_trusted_peer(trusted_peer, PeerAddr::from_tcp(trusted_sock));
3015 peers.queued_actions.clear();
3016 peers.fill_outbound_slots();
3017 match peers.queued_actions.pop_front() {
3018 Some(PeerAction::Connect { peer_id, remote_addr }) => {
3019 assert_eq!(peer_id, trusted_peer);
3020 assert_eq!(remote_addr, trusted_sock);
3021 }
3022 action => panic!("expected the trusted peer to be dialed, got {action:?}"),
3023 }
3024 assert!(peers.queued_actions.is_empty());
3025 peers.on_active_outgoing_established(trusted_peer);
3026
3027 let other_peer = PeerId::random();
3029 let other_sock = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 4)), 8008);
3030 peers.add_peer(other_peer, PeerAddr::from_tcp(other_sock), None);
3031 peers.queued_actions.clear();
3032 peers.fill_outbound_slots();
3033 assert!(peers.queued_actions.is_empty());
3034 assert!(peers.peers[&other_peer].state.is_idle());
3035 }
3036
3037 #[tokio::test]
3038 async fn test_connect_trusted_nodes_only() {
3039 let trusted_peer = PeerId::random();
3040 let trusted_sock = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
3041 let config = PeersConfig::test()
3042 .with_trusted_nodes(vec![TrustedPeer {
3043 host: Host::Ipv4(Ipv4Addr::new(127, 0, 1, 2)),
3044 tcp_port: 8008,
3045 udp_port: 8008,
3046 id: trusted_peer,
3047 }])
3048 .with_trusted_nodes_only(true);
3049 let mut peers = PeersManager::new(config);
3050
3051 let basic_peer = PeerId::random();
3052 let basic_sock = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
3053 peers.add_peer(basic_peer, PeerAddr::from_tcp(basic_sock), None);
3054
3055 match event!(peers) {
3056 PeerAction::PeerAdded(peer_id) => {
3057 assert_eq!(peer_id, basic_peer);
3058 }
3059 _ => unreachable!(),
3060 }
3061 match event!(peers) {
3062 PeerAction::Connect { peer_id, remote_addr } => {
3063 assert_eq!(peer_id, trusted_peer);
3064 assert_eq!(remote_addr, trusted_sock);
3065 }
3066 _ => unreachable!(),
3067 }
3068 poll_fn(|cx| {
3069 assert!(peers.poll(cx).is_pending());
3070 Poll::Ready(())
3071 })
3072 .await;
3073 }
3074
3075 #[tokio::test]
3076 async fn test_incoming_with_trusted_nodes_only() {
3077 let trusted_peer = PeerId::random();
3078 let config = PeersConfig::test()
3079 .with_trusted_nodes(vec![TrustedPeer {
3080 host: Host::Ipv4(Ipv4Addr::new(127, 0, 1, 2)),
3081 tcp_port: 8008,
3082 udp_port: 8008,
3083 id: trusted_peer,
3084 }])
3085 .with_trusted_nodes_only(true);
3086 let mut peers = PeersManager::new(config);
3087
3088 let basic_peer = PeerId::random();
3089 let basic_sock = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
3090 assert!(peers.on_incoming_pending_session(basic_sock.ip()).is_ok());
3091 assert_eq!(peers.connection_info.num_pending_in, 1);
3093 assert_eq!(
3094 peers.inbound_session_rejection(basic_peer),
3095 Some(DisconnectReason::DisconnectRequested)
3096 );
3097 assert_eq!(peers.inbound_session_rejection(trusted_peer), None);
3098 peers.on_incoming_session_established(basic_peer, basic_sock);
3099 assert_eq!(peers.connection_info.num_pending_in, 0);
3102 assert_eq!(peers.connection_info.num_inbound, 0);
3103
3104 let Some(PeerAction::DisconnectUntrustedIncoming { peer_id }) =
3105 peers.queued_actions.pop_front()
3106 else {
3107 panic!()
3108 };
3109 assert_eq!(basic_peer, peer_id);
3110 assert!(!peers.peers.contains_key(&basic_peer));
3111 }
3112
3113 #[tokio::test]
3114 async fn test_incoming_without_trusted_nodes_only() {
3115 let trusted_peer = PeerId::random();
3116 let config = PeersConfig::test()
3117 .with_trusted_nodes(vec![TrustedPeer {
3118 host: Host::Ipv4(Ipv4Addr::new(127, 0, 1, 2)),
3119 tcp_port: 8008,
3120 udp_port: 8008,
3121 id: trusted_peer,
3122 }])
3123 .with_trusted_nodes_only(false);
3124 let mut peers = PeersManager::new(config);
3125
3126 let basic_peer = PeerId::random();
3127 let basic_sock = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
3128 assert!(peers.on_incoming_pending_session(basic_sock.ip()).is_ok());
3129
3130 assert_eq!(peers.connection_info.num_pending_in, 1);
3132 peers.on_incoming_session_established(basic_peer, basic_sock);
3133 assert_eq!(peers.connection_info.num_pending_in, 0);
3136 assert_eq!(peers.connection_info.num_inbound, 1);
3137 assert!(peers.peers.contains_key(&basic_peer));
3138 }
3139
3140 #[tokio::test]
3141 async fn test_incoming_at_capacity() {
3142 let mut config = PeersConfig::test();
3143 config.connection_info.max_inbound = 1;
3144 let mut peers = PeersManager::new(config);
3145
3146 let peer = PeerId::random();
3147 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
3148 assert!(peers.on_incoming_pending_session(addr.ip()).is_ok());
3149
3150 peers.on_incoming_session_established(peer, addr);
3151
3152 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
3153 assert_eq!(
3154 peers.on_incoming_pending_session(addr.ip()).unwrap_err(),
3155 InboundConnectionError::ExceedsCapacity
3156 );
3157 }
3158
3159 #[tokio::test]
3160 async fn test_incoming_rate_limit() {
3161 for max_inbound in [0, 1] {
3162 let config = PeersConfig {
3163 incoming_ip_throttle_duration: Duration::from_millis(100),
3164 ..PeersConfig::test().with_max_inbound(max_inbound)
3165 };
3166 let mut peers = PeersManager::new(config);
3167 peers.add_trusted_peer_id(PeerId::random());
3168
3169 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(168, 0, 1, 2)), 8009);
3170 peers.on_incoming_pending_session(addr.ip()).unwrap();
3171 peers.on_incoming_pending_session_gracefully_closed();
3172 assert_eq!(
3173 peers.on_incoming_pending_session(addr.ip()).unwrap_err(),
3174 InboundConnectionError::IpBanned
3175 );
3176
3177 peers.release_interval.reset_immediately();
3178 tokio::time::sleep(peers.incoming_ip_throttle_duration).await;
3179
3180 poll_fn(|cx| loop {
3182 if peers.poll(cx).is_pending() {
3183 return Poll::Ready(());
3184 }
3185 })
3186 .await;
3187
3188 peers.on_incoming_pending_session(addr.ip()).unwrap();
3189 peers.on_incoming_pending_session_gracefully_closed();
3190 assert_eq!(
3191 peers.on_incoming_pending_session(addr.ip()).unwrap_err(),
3192 InboundConnectionError::IpBanned
3193 );
3194 }
3195 }
3196
3197 #[tokio::test]
3198 async fn test_incoming_throttle_capacity() {
3199 for max_inbound in [0, 1] {
3200 let mut peers = PeersManager::new(PeersConfig::test().with_max_inbound(max_inbound));
3201 peers.add_trusted_peer_id(PeerId::random());
3202 peers.ban_list = BanList::new(
3203 [],
3204 (0..MAX_INCOMING_IP_THROTTLE_ENTRIES)
3205 .map(|i| IpAddr::V4(Ipv4Addr::from(0x0800_0000 + i))),
3206 );
3207 for i in 0..MAX_INCOMING_IP_THROTTLE_ENTRIES {
3208 peers.throttle_incoming_ip(IpAddr::V4(Ipv4Addr::from(0x0900_0000 + i)));
3209 }
3210 let ip = IpAddr::from([1, 1, 1, 1]);
3211 assert!(peers.on_incoming_pending_session(ip).is_ok());
3212 assert_eq!(peers.connection_info.num_pending_in, 1);
3213 assert_eq!(
3214 peers.incoming_ip_throttle.len(),
3215 usize::try_from(MAX_INCOMING_IP_THROTTLE_ENTRIES).unwrap()
3216 );
3217 peers.on_incoming_pending_session_gracefully_closed();
3218 assert_eq!(peers.connection_info.num_pending_in, 0);
3219 assert_eq!(
3220 peers.on_incoming_pending_session(ip),
3221 Err(InboundConnectionError::IpBanned)
3222 );
3223
3224 assert_eq!(
3226 peers.on_incoming_pending_session(IpAddr::from([8, 0, 0, 1])),
3227 Err(InboundConnectionError::IpBanned)
3228 );
3229 }
3230 }
3231
3232 #[tokio::test]
3233 async fn test_tick() {
3234 let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2));
3235 let socket_addr = SocketAddr::new(ip, 8008);
3236 let config = PeersConfig::test();
3237 let mut peer_manager = PeersManager::new(config);
3238 let peer_id = PeerId::random();
3239 peer_manager.add_peer(peer_id, PeerAddr::from_tcp(socket_addr), None);
3240
3241 peer_manager.last_tick -= Duration::from_secs(1);
3243 peer_manager.tick();
3244
3245 assert_eq!(peer_manager.peers.get_mut(&peer_id).unwrap().reputation, DEFAULT_REPUTATION);
3247
3248 peer_manager.peers.get_mut(&peer_id).unwrap().state = PeerConnectionState::Out;
3250
3251 peer_manager.last_tick -= Duration::from_secs(1);
3252 peer_manager.tick();
3253
3254 assert_eq!(peer_manager.peers.get_mut(&peer_id).unwrap().reputation, DEFAULT_REPUTATION);
3256
3257 peer_manager.peers.get_mut(&peer_id).unwrap().reputation -= 1;
3258
3259 peer_manager.last_tick -= Duration::from_secs(5);
3261 peer_manager.tick();
3262
3263 assert_eq!(peer_manager.peers.get_mut(&peer_id).unwrap().reputation, DEFAULT_REPUTATION);
3265 }
3266
3267 #[tokio::test]
3268 async fn test_remove_incoming_after_disconnect() {
3269 let peer_id = PeerId::random();
3270 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
3271 let mut peers = PeersManager::default();
3272
3273 peers.on_incoming_pending_session(addr.ip()).unwrap();
3274 peers.on_incoming_session_established(peer_id, addr);
3275 let peer = peers.peers.get(&peer_id).unwrap();
3276 assert_eq!(peer.state, PeerConnectionState::In);
3277 assert!(peer.remove_after_disconnect);
3278
3279 peers.on_active_session_gracefully_closed(peer_id);
3280 assert!(!peers.peers.contains_key(&peer_id))
3281 }
3282
3283 #[tokio::test]
3284 async fn test_repeated_remove_while_disconnecting_releases_slot() {
3285 let peer_id = PeerId::random();
3286 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
3287 let mut peers = PeersManager::default();
3288
3289 peers.on_incoming_pending_session(addr.ip()).unwrap();
3290 peers.on_incoming_session_established(peer_id, addr);
3291 assert_eq!(peers.connection_info.num_inbound, 1);
3292
3293 peers.remove_peer(peer_id);
3294 peers.remove_peer(peer_id);
3295
3296 let peer = peers.peers.get(&peer_id).unwrap();
3297 assert_eq!(peer.state, PeerConnectionState::DisconnectingIn);
3298 assert!(peer.remove_after_disconnect);
3299 assert_eq!(peers.connection_info.num_inbound, 1);
3300
3301 peers.on_active_session_gracefully_closed(peer_id);
3302 assert_eq!(peers.connection_info.num_inbound, 0);
3303 assert!(!peers.peers.contains_key(&peer_id));
3304 }
3305
3306 #[tokio::test]
3307 async fn test_keep_incoming_after_disconnect_if_discovered() {
3308 let peer_id = PeerId::random();
3309 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
3310 let mut peers = PeersManager::default();
3311
3312 peers.on_incoming_pending_session(addr.ip()).unwrap();
3313 peers.on_incoming_session_established(peer_id, addr);
3314 let peer = peers.peers.get(&peer_id).unwrap();
3315 assert_eq!(peer.state, PeerConnectionState::In);
3316 assert!(peer.remove_after_disconnect);
3317
3318 peers.add_peer(peer_id, PeerAddr::from_tcp(addr), None);
3320
3321 peers.on_active_session_gracefully_closed(peer_id);
3322
3323 let peer = peers.peers.get(&peer_id).unwrap();
3324 assert_eq!(peer.state, PeerConnectionState::Idle);
3325 assert!(!peer.remove_after_disconnect);
3326 }
3327
3328 #[tokio::test]
3329 async fn test_peer_reconnect_after_graceful_close_respects_throttle() {
3330 let throttle_duration = Duration::from_millis(100);
3331 let config =
3332 PeersConfig { incoming_ip_throttle_duration: throttle_duration, ..PeersConfig::test() };
3333 let mut peers = PeersManager::new(config);
3334
3335 let peer_id = PeerId::random();
3336 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
3337
3338 peers.add_peer(peer_id, PeerAddr::from_tcp(addr), None);
3340
3341 match event!(peers) {
3342 PeerAction::PeerAdded(id) => assert_eq!(id, peer_id),
3343 _ => unreachable!(),
3344 }
3345
3346 match event!(peers) {
3347 PeerAction::Connect { .. } => {}
3348 _ => unreachable!(),
3349 }
3350
3351 peers.on_active_outgoing_established(peer_id);
3353 assert_eq!(peers.peers.get(&peer_id).unwrap().state, PeerConnectionState::Out);
3354
3355 peers.on_active_session_gracefully_closed(peer_id);
3357
3358 let peer = peers.peers.get(&peer_id).unwrap();
3359 assert_eq!(peer.state, PeerConnectionState::Idle);
3360 assert!(peer.backed_off);
3361
3362 assert!(peers.backed_off_peers.contains_key(&peer_id));
3364
3365 poll_fn(|cx| {
3367 assert!(peers.poll(cx).is_pending());
3368 Poll::Ready(())
3369 })
3370 .await;
3371
3372 assert!(peers.backed_off_peers.contains_key(&peer_id));
3374 assert!(peers.peers.get(&peer_id).unwrap().backed_off);
3375
3376 tokio::time::sleep(throttle_duration).await;
3378
3379 match event!(peers) {
3381 PeerAction::Connect { peer_id: id, .. } => assert_eq!(id, peer_id),
3382 _ => unreachable!(),
3383 }
3384
3385 assert!(!peers.backed_off_peers.contains_key(&peer_id));
3387 assert!(!peers.peers.get(&peer_id).unwrap().backed_off);
3388 }
3389
3390 #[tokio::test]
3391 async fn test_backed_off_peer_can_accept_incoming_connection() {
3392 let throttle_duration = Duration::from_millis(100);
3393 let config =
3394 PeersConfig { incoming_ip_throttle_duration: throttle_duration, ..PeersConfig::test() };
3395 let mut peers = PeersManager::new(config);
3396
3397 let peer_id = PeerId::random();
3398 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
3399
3400 peers.add_peer(peer_id, PeerAddr::from_tcp(addr), None);
3402
3403 match event!(peers) {
3404 PeerAction::PeerAdded(id) => assert_eq!(id, peer_id),
3405 _ => unreachable!(),
3406 }
3407
3408 match event!(peers) {
3409 PeerAction::Connect { .. } => {}
3410 _ => unreachable!(),
3411 }
3412
3413 peers.on_active_outgoing_established(peer_id);
3415 assert_eq!(peers.peers.get(&peer_id).unwrap().state, PeerConnectionState::Out);
3416
3417 peers.on_active_session_gracefully_closed(peer_id);
3419
3420 let peer = peers.peers.get(&peer_id).unwrap();
3421 assert_eq!(peer.state, PeerConnectionState::Idle);
3422 assert!(peer.backed_off);
3423 assert!(peers.backed_off_peers.contains_key(&peer_id));
3424
3425 assert!(peers.on_incoming_pending_session(addr.ip()).is_ok());
3428 assert_eq!(peers.connection_info.num_pending_in, 1);
3429
3430 peers.on_incoming_session_established(peer_id, addr);
3432
3433 assert_eq!(peers.peers.get(&peer_id).unwrap().state, PeerConnectionState::In);
3435 assert_eq!(peers.connection_info.num_inbound, 1);
3436
3437 assert!(peers.backed_off_peers.contains_key(&peer_id));
3439 assert!(peers.peers.get(&peer_id).unwrap().backed_off);
3440
3441 poll_fn(|cx| {
3443 assert!(peers.poll(cx).is_pending());
3444 Poll::Ready(())
3445 })
3446 .await;
3447
3448 assert_eq!(peers.peers.get(&peer_id).unwrap().state, PeerConnectionState::In);
3450
3451 tokio::time::sleep(throttle_duration).await;
3453
3454 poll_fn(|cx| {
3455 let _ = peers.poll(cx);
3456 Poll::Ready(())
3457 })
3458 .await;
3459
3460 assert!(!peers.backed_off_peers.contains_key(&peer_id));
3462 assert!(!peers.peers.get(&peer_id).unwrap().backed_off);
3463
3464 assert_eq!(peers.peers.get(&peer_id).unwrap().state, PeerConnectionState::In);
3466 }
3467
3468 #[tokio::test]
3469 async fn test_incoming_outgoing_already_connected() {
3470 let peer_id = PeerId::random();
3471 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
3472 let mut peers = PeersManager::default();
3473
3474 peers.on_incoming_pending_session(addr.ip()).unwrap();
3475 peers.add_peer(peer_id, PeerAddr::from_tcp(addr), None);
3476
3477 match event!(peers) {
3478 PeerAction::PeerAdded(_) => {}
3479 _ => unreachable!(),
3480 }
3481
3482 match event!(peers) {
3483 PeerAction::Connect { .. } => {}
3484 _ => unreachable!(),
3485 }
3486
3487 peers.on_incoming_session_established(peer_id, addr);
3488 peers.on_already_connected(Direction::Outgoing(peer_id));
3489 assert_eq!(peers.peers.get(&peer_id).unwrap().state, PeerConnectionState::In);
3490 assert_eq!(peers.connection_info.num_inbound, 1);
3491 assert_eq!(peers.connection_info.num_pending_out, 0);
3492 assert_eq!(peers.connection_info.num_pending_in, 0);
3493 assert_eq!(peers.connection_info.num_outbound, 0);
3494 }
3495
3496 #[tokio::test]
3497 async fn test_already_connected_incoming_outgoing_connection_error() {
3498 let peer_id = PeerId::random();
3499 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8009);
3500 let mut peers = PeersManager::default();
3501
3502 peers.on_incoming_pending_session(addr.ip()).unwrap();
3503 peers.add_peer(peer_id, PeerAddr::from_tcp(addr), None);
3504
3505 match event!(peers) {
3506 PeerAction::PeerAdded(_) => {}
3507 _ => unreachable!(),
3508 }
3509
3510 match event!(peers) {
3511 PeerAction::Connect { .. } => {}
3512 _ => unreachable!(),
3513 }
3514
3515 peers.on_incoming_session_established(peer_id, addr);
3516
3517 peers.on_outgoing_connection_failure(
3518 &addr,
3519 &peer_id,
3520 &io::Error::new(io::ErrorKind::ConnectionRefused, ""),
3521 );
3522 assert_eq!(peers.peers.get(&peer_id).unwrap().state, PeerConnectionState::In);
3523 assert_eq!(peers.connection_info.num_inbound, 1);
3524 assert_eq!(peers.connection_info.num_pending_out, 0);
3525 assert_eq!(peers.connection_info.num_pending_in, 0);
3526 assert_eq!(peers.connection_info.num_outbound, 0);
3527 }
3528
3529 #[tokio::test]
3530 async fn test_max_concurrent_dials() {
3531 let config = PeersConfig::default();
3532 let mut peer_manager = PeersManager::new(config);
3533 let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2));
3534 let peer_addr = PeerAddr::from_tcp(SocketAddr::new(ip, 8008));
3535 for _ in 0..peer_manager.connection_info.config.max_concurrent_outbound_dials * 2 {
3536 peer_manager.add_peer(PeerId::random(), peer_addr, None);
3537 }
3538
3539 peer_manager.fill_outbound_slots();
3540 let dials = peer_manager
3541 .queued_actions
3542 .iter()
3543 .filter(|ev| matches!(ev, PeerAction::Connect { .. }))
3544 .count();
3545 assert_eq!(dials, peer_manager.connection_info.config.max_concurrent_outbound_dials);
3546 }
3547
3548 #[tokio::test]
3549 async fn test_max_num_of_pending_dials() {
3550 let config = PeersConfig::default();
3551 let mut peer_manager = PeersManager::new(config);
3552 let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2));
3553 let peer_addr = PeerAddr::from_tcp(SocketAddr::new(ip, 8008));
3554
3555 for _ in 0..peer_manager.connection_info.config.max_concurrent_outbound_dials * 2 {
3557 peer_manager.add_peer(PeerId::random(), peer_addr, None);
3558 }
3559
3560 for _ in 0..peer_manager.connection_info.config.max_concurrent_outbound_dials * 2 {
3561 match event!(peer_manager) {
3562 PeerAction::PeerAdded(_) => {}
3563 _ => unreachable!(),
3564 }
3565 }
3566
3567 for _ in 0..peer_manager.connection_info.config.max_concurrent_outbound_dials {
3568 match event!(peer_manager) {
3569 PeerAction::Connect { .. } => {}
3570 _ => unreachable!(),
3571 }
3572 }
3573
3574 peer_manager.fill_outbound_slots();
3576
3577 let dials = peer_manager.connection_info.num_pending_out;
3579 assert_eq!(dials, peer_manager.connection_info.config.max_concurrent_outbound_dials);
3580
3581 let num_pendingout_states = peer_manager
3582 .peers
3583 .iter()
3584 .filter(|(_, peer)| peer.state.is_pending_out())
3585 .map(|(peer_id, _)| *peer_id)
3586 .collect::<Vec<PeerId>>();
3587 assert_eq!(
3588 num_pendingout_states.len(),
3589 peer_manager.connection_info.config.max_concurrent_outbound_dials
3590 );
3591
3592 for peer_id in &num_pendingout_states {
3594 peer_manager.on_active_outgoing_established(*peer_id);
3595 }
3596
3597 for peer_id in &num_pendingout_states {
3599 assert_eq!(peer_manager.peers.get(peer_id).unwrap().state, PeerConnectionState::Out);
3600 }
3601
3602 assert_eq!(peer_manager.connection_info.num_pending_out, 0);
3604 }
3605
3606 #[tokio::test]
3607 async fn test_connect() {
3608 let peer = PeerId::random();
3609 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
3610 let mut peers = PeersManager::default();
3611 peers.add_and_connect(peer, PeerAddr::from_tcp(socket_addr), None);
3612 assert_eq!(peers.peers.get(&peer).unwrap().state, PeerConnectionState::PendingOut);
3613
3614 match event!(peers) {
3615 PeerAction::Connect { peer_id, remote_addr } => {
3616 assert_eq!(peer_id, peer);
3617 assert_eq!(remote_addr, socket_addr);
3618 }
3619 _ => unreachable!(),
3620 }
3621
3622 let (record, _) = peers.peer_by_id(peer).unwrap();
3623 assert_eq!(record.tcp_addr(), socket_addr);
3624 assert_eq!(record.udp_addr(), socket_addr);
3625
3626 peers.add_and_connect(peer, PeerAddr::from_tcp(socket_addr), None);
3628
3629 let (record, _) = peers.peer_by_id(peer).unwrap();
3630 assert_eq!(record.tcp_addr(), socket_addr);
3631 assert_eq!(record.udp_addr(), socket_addr);
3632 }
3633
3634 #[tokio::test]
3635 async fn test_incoming_connection_from_banned() {
3636 let peer = PeerId::random();
3637 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
3638 let config = PeersConfig::test().with_max_inbound(3);
3639 let mut peers = PeersManager::new(config);
3640 peers.add_peer(peer, PeerAddr::from_tcp(socket_addr), None);
3641
3642 match event!(peers) {
3643 PeerAction::PeerAdded(peer_id) => {
3644 assert_eq!(peer_id, peer);
3645 }
3646 _ => unreachable!(),
3647 }
3648 match event!(peers) {
3649 PeerAction::Connect { peer_id, .. } => {
3650 assert_eq!(peer_id, peer);
3651 }
3652 _ => unreachable!(),
3653 }
3654
3655 poll_fn(|cx| {
3656 assert!(peers.poll(cx).is_pending());
3657 Poll::Ready(())
3658 })
3659 .await;
3660
3661 loop {
3663 peers.on_active_session_dropped(
3664 &socket_addr,
3665 &peer,
3666 &EthStreamError::InvalidMessage(reth_eth_wire::message::MessageError::Invalid(
3667 reth_eth_wire::EthVersion::Eth68,
3668 reth_eth_wire::EthMessageID::Status,
3669 )),
3670 );
3671
3672 if peers.peers.get(&peer).unwrap().is_banned() {
3673 break;
3674 }
3675
3676 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
3677 peers.on_incoming_session_established(peer, socket_addr);
3678
3679 match event!(peers) {
3680 PeerAction::Connect { peer_id, .. } => {
3681 assert_eq!(peer_id, peer);
3682 }
3683 _ => unreachable!(),
3684 }
3685 }
3686
3687 assert!(peers.peers.get(&peer).unwrap().is_banned());
3688
3689 for _ in 0..peers.connection_info.config.max_inbound {
3691 assert!(peers.on_incoming_pending_session(socket_addr.ip()).is_ok());
3692 peers.on_incoming_session_established(peer, socket_addr);
3693
3694 match event!(peers) {
3695 PeerAction::DisconnectBannedIncoming { peer_id } => {
3696 assert_eq!(peer_id, peer);
3697 }
3698 _ => unreachable!(),
3699 }
3700 }
3701
3702 poll_fn(|cx| {
3703 assert!(peers.poll(cx).is_pending());
3704 Poll::Ready(())
3705 })
3706 .await;
3707
3708 assert_eq!(peers.connection_info.num_inbound, 0);
3709
3710 let new_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 3)), 8008);
3711
3712 assert!(peers.on_incoming_pending_session(new_addr.ip()).is_ok());
3714 assert_eq!(peers.connection_info.num_pending_in, 1);
3715
3716 peers.on_active_session_gracefully_closed(peer);
3720 assert_eq!(peers.connection_info.num_inbound, 0);
3721 }
3722
3723 #[tokio::test]
3724 async fn test_add_pending_connect() {
3725 let peer = PeerId::random();
3726 let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
3727 let mut peers = PeersManager::default();
3728 peers.add_and_connect(peer, PeerAddr::from_tcp(socket_addr), None);
3729 assert_eq!(peers.peers.get(&peer).unwrap().state, PeerConnectionState::PendingOut);
3730 assert_eq!(peers.connection_info.num_pending_out, 1);
3731 }
3732
3733 #[tokio::test]
3734 async fn test_dns_updates_peer_address() {
3735 let peer_id = PeerId::random();
3736 let initial_socket = SocketAddr::new("1.1.1.1".parse::<IpAddr>().unwrap(), 8008);
3737 let updated_ip = "2.2.2.2".parse::<IpAddr>().unwrap();
3738
3739 let trusted = TrustedPeer {
3740 host: url::Host::Ipv4("2.2.2.2".parse().unwrap()),
3741 tcp_port: 8008,
3742 udp_port: 8008,
3743 id: peer_id,
3744 };
3745
3746 let config = PeersConfig::test().with_trusted_nodes(vec![trusted.clone()]);
3747 let mut manager = PeersManager::new(config);
3748 manager
3749 .trusted_peers_resolver
3750 .set_interval(tokio::time::interval(Duration::from_millis(1)));
3751
3752 manager.peers.insert(
3753 peer_id,
3754 Peer::trusted(PeerAddr::new_with_ports(initial_socket.ip(), 8008, Some(8008))),
3755 );
3756
3757 for _ in 0..100 {
3758 let _ = event!(manager);
3759 if manager.peers.get(&peer_id).unwrap().addr.tcp().ip() == updated_ip {
3760 break;
3761 }
3762 tokio::time::sleep(Duration::from_millis(10)).await;
3763 }
3764
3765 let updated_peer = manager.peers.get(&peer_id).unwrap();
3766 assert_eq!(updated_peer.addr.tcp().ip(), updated_ip);
3767 }
3768
3769 #[tokio::test]
3770 async fn test_ip_filter_blocks_inbound_connection() {
3771 use std::net::IpAddr;
3772
3773 let ip_filter = IpFilter::from_cidr_string("192.168.0.0/16").unwrap();
3775 let config = PeersConfig::test().with_ip_filter(ip_filter);
3776 let mut peers = PeersManager::new(config);
3777
3778 let allowed_ip: IpAddr = "192.168.1.100".parse().unwrap();
3780 assert!(peers.on_incoming_pending_session(allowed_ip).is_ok());
3781
3782 let disallowed_ip: IpAddr = "10.0.0.1".parse().unwrap();
3784 assert!(peers.on_incoming_pending_session(disallowed_ip).is_err());
3785 }
3786
3787 #[tokio::test]
3788 async fn test_ip_filter_blocks_outbound_connection() {
3789 use std::net::SocketAddr;
3790
3791 let ip_filter = IpFilter::from_cidr_string("192.168.0.0/16").unwrap();
3793 let config = PeersConfig::test().with_ip_filter(ip_filter);
3794 let mut peers = PeersManager::new(config);
3795
3796 let peer_id = PeerId::repeat_byte(1);
3797
3798 let allowed_addr: SocketAddr = "192.168.1.100:30303".parse().unwrap();
3800 peers.add_peer(peer_id, PeerAddr::from_tcp(allowed_addr), None);
3801 assert!(peers.peers.contains_key(&peer_id));
3802
3803 let peer_id2 = PeerId::repeat_byte(2);
3805 let disallowed_addr: SocketAddr = "10.0.0.1:30303".parse().unwrap();
3806 peers.add_peer(peer_id2, PeerAddr::from_tcp(disallowed_addr), None);
3807 assert!(!peers.peers.contains_key(&peer_id2));
3808 }
3809
3810 #[tokio::test]
3811 async fn test_ip_filter_ipv6() {
3812 use std::net::IpAddr;
3813
3814 let ip_filter = IpFilter::from_cidr_string("2001:db8::/32").unwrap();
3816 let config = PeersConfig::test().with_ip_filter(ip_filter);
3817 let mut peers = PeersManager::new(config);
3818
3819 let allowed_ip: IpAddr = "2001:db8::1".parse().unwrap();
3821 assert!(peers.on_incoming_pending_session(allowed_ip).is_ok());
3822
3823 let disallowed_ip: IpAddr = "2001:db9::1".parse().unwrap();
3825 assert!(peers.on_incoming_pending_session(disallowed_ip).is_err());
3826 }
3827
3828 #[tokio::test]
3829 async fn test_ip_filter_multiple_ranges() {
3830 use std::net::IpAddr;
3831
3832 let ip_filter = IpFilter::from_cidr_string("192.168.0.0/16,10.0.0.0/8").unwrap();
3834 let config = PeersConfig::test().with_ip_filter(ip_filter);
3835 let mut peers = PeersManager::new(config);
3836
3837 let ip1: IpAddr = "192.168.1.1".parse().unwrap();
3839 let ip2: IpAddr = "10.5.10.20".parse().unwrap();
3840 assert!(peers.on_incoming_pending_session(ip1).is_ok());
3841 assert!(peers.on_incoming_pending_session(ip2).is_ok());
3842
3843 let disallowed_ip: IpAddr = "172.16.0.1".parse().unwrap();
3845 assert!(peers.on_incoming_pending_session(disallowed_ip).is_err());
3846 }
3847
3848 #[tokio::test]
3849 async fn test_ip_filter_no_restriction() {
3850 use std::net::IpAddr;
3851
3852 let ip_filter = IpFilter::allow_all();
3854 let config = PeersConfig::test().with_ip_filter(ip_filter);
3855 let mut peers = PeersManager::new(config);
3856
3857 let ip1: IpAddr = "192.168.1.1".parse().unwrap();
3859 let ip2: IpAddr = "10.0.0.1".parse().unwrap();
3860 let ip3: IpAddr = "8.8.8.8".parse().unwrap();
3861 assert!(peers.on_incoming_pending_session(ip1).is_ok());
3862 assert!(peers.on_incoming_pending_session(ip2).is_ok());
3863 assert!(peers.on_incoming_pending_session(ip3).is_ok());
3864 }
3865
3866 #[tokio::test]
3867 async fn test_ip_filter_skips_configured_peers() {
3868 let allowed = NodeRecord::new("192.168.1.1:30303".parse().unwrap(), PeerId::random());
3869 let trusted = NodeRecord::new("10.0.0.1:30303".parse().unwrap(), PeerId::random());
3870 let persisted = NodeRecord::new("10.0.0.2:30303".parse().unwrap(), PeerId::random());
3871 let basic = NodeRecord::new("10.0.0.3:30303".parse().unwrap(), PeerId::random());
3872
3873 let mut config = PeersConfig::test()
3874 .with_ip_filter(IpFilter::from_cidr_string("192.168.0.0/16").unwrap())
3875 .with_trusted_nodes(vec![trusted.into()])
3876 .with_basic_nodes(std::iter::once(basic).collect());
3877 config.persisted_peers =
3878 [allowed, persisted].into_iter().map(PersistedPeerInfo::from_node_record).collect();
3879 let mut peers = PeersManager::new(config);
3880
3881 assert_eq!(peers.peers.keys().collect::<Vec<_>>(), [&allowed.id]);
3882 assert!(peers.trusted_peer_ids.contains(&trusted.id));
3883 assert_eq!(
3884 peers.persistable_peers().map(|peer| peer.record).collect::<Vec<_>>(),
3885 [allowed]
3886 );
3887 peers.fill_outbound_slots();
3888 assert!(
3889 matches!(peers.queued_actions.pop_front(), Some(PeerAction::Connect { peer_id, remote_addr })
3890 if peer_id == allowed.id && remote_addr == allowed.tcp_addr())
3891 );
3892 assert!(peers.queued_actions.is_empty());
3893
3894 peers.on_resolved_peer(trusted.id, trusted);
3895 assert!(!peers.peers.contains_key(&trusted.id));
3896 let resolved = NodeRecord::new("192.168.1.2:30303".parse().unwrap(), trusted.id);
3897 peers.on_resolved_peer(trusted.id, resolved);
3898 peers.on_resolved_peer(trusted.id, trusted);
3899 assert_eq!(peers.peers[&trusted.id].addr.tcp(), resolved.tcp_addr());
3900 }
3901
3902 #[tokio::test]
3903 async fn test_best_unconnected_prefers_fork_id_as_tiebreaker() {
3904 let mut peers = PeersManager::default();
3905 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8008);
3906
3907 let fork_id = ForkId { hash: ForkHash([0xaa, 0xbb, 0xcc, 0xdd]), next: 0 };
3908
3909 let no_fork = PeerId::random();
3911 peers.add_peer(no_fork, PeerAddr::from_tcp(addr), None);
3912
3913 let with_fork = PeerId::random();
3914 peers.add_peer(with_fork, PeerAddr::from_tcp(addr), None);
3915 peers.peers.get_mut(&with_fork).unwrap().fork_id = Some(Box::new(fork_id));
3916
3917 let (best_id, _) = peers.best_unconnected(false).unwrap();
3918 assert_eq!(best_id, with_fork, "fork_id should break tie when reputation is equal");
3919 }
3920
3921 #[tokio::test]
3922 async fn test_add_trusted_peer_node_resolves_absent_peer() {
3923 let peer_id = PeerId::random();
3924 let trusted = TrustedPeer {
3925 host: url::Host::Domain("example.invalid".to_string()),
3926 tcp_port: 30303,
3927 udp_port: 30303,
3928 id: peer_id,
3929 };
3930
3931 let mut manager = PeersManager::default();
3932 manager.add_trusted_peer_node(trusted);
3933
3934 assert!(manager.trusted_peer_ids.contains(&peer_id));
3935 assert_eq!(manager.trusted_peers_resolver.trusted_peers.len(), 1);
3936 assert!(!manager.peers.contains_key(&peer_id));
3937
3938 let resolved = NodeRecord {
3939 address: "10.0.0.1".parse::<IpAddr>().unwrap(),
3940 tcp_port: 30303,
3941 udp_port: 30303,
3942 id: peer_id,
3943 };
3944 manager.on_resolved_peer(peer_id, resolved);
3945
3946 let peer = manager.peers.get(&peer_id).expect("peer should be added after resolution");
3947 assert!(peer.kind.is_trusted());
3948 assert_eq!(peer.addr.tcp().ip(), "10.0.0.1".parse::<IpAddr>().unwrap());
3949 }
3950
3951 #[tokio::test]
3952 async fn test_configured_trusted_peer_resolves_after_startup_failure() {
3953 let peer_id = PeerId::random();
3954 let trusted = TrustedPeer::new(Host::Domain("example.invalid".into()), 30303, peer_id);
3955 let mut manager = PeersManager::new(PeersConfig::test().with_trusted_nodes(vec![trusted]));
3956 assert!(!manager.peers.contains_key(&peer_id));
3957
3958 let addr = "10.0.0.1:30303".parse::<SocketAddr>().unwrap();
3959 manager.on_resolved_peer(peer_id, NodeRecord::new(addr, peer_id));
3960 let peer = manager.peers.get(&peer_id).expect("peer should be added after resolution");
3961 assert!(peer.is_trusted());
3962 assert_eq!(peer.addr.tcp(), addr);
3963 }
3964
3965 #[tokio::test]
3966 async fn test_unresolved_trusted_peer_promotes_persisted_entry() {
3967 let peer_id = PeerId::random();
3968 let trusted = TrustedPeer::new(Host::Domain("example.invalid".into()), 30303, peer_id);
3969 let mut config = PeersConfig::test().with_trusted_nodes(vec![trusted]);
3970 config.persisted_peers.push(PersistedPeerInfo {
3971 record: NodeRecord::new("10.0.0.1:30303".parse().unwrap(), peer_id),
3972 kind: PeerKind::Basic,
3973 fork_id: None,
3974 reputation: 0,
3975 });
3976 let manager = PeersManager::new(config);
3977 assert!(manager.trusted_peer_ids.contains(&peer_id));
3978 assert!(manager.peers.get(&peer_id).unwrap().is_trusted());
3979 }
3980
3981 #[tokio::test]
3982 async fn test_unresolved_trusted_peer_inbound_then_resolved() {
3983 let peer_id = PeerId::random();
3984 let trusted = TrustedPeer::new(Host::Domain("example.invalid".into()), 30303, peer_id);
3985 let mut manager = PeersManager::new(
3986 PeersConfig::test().with_trusted_nodes(vec![trusted]).with_trusted_nodes_only(true),
3987 );
3988
3989 let inbound = "10.0.0.1:41234".parse::<SocketAddr>().unwrap();
3990 assert!(manager.on_incoming_pending_session(inbound.ip()).is_ok());
3991 manager.on_incoming_session_established(peer_id, inbound);
3992 assert!(manager.peers.get(&peer_id).unwrap().is_trusted());
3993
3994 let addr = "10.0.0.1:30303".parse::<SocketAddr>().unwrap();
3995 manager.on_resolved_peer(peer_id, NodeRecord::new(addr, peer_id));
3996 let peer = manager.peers.get(&peer_id).unwrap();
3997 assert!(peer.is_trusted());
3998 assert!(!peer.remove_after_disconnect);
3999 assert_eq!(peer.addr.tcp(), addr);
4000 }
4001
4002 #[tokio::test]
4003 async fn test_removed_trusted_peer_ignores_late_resolution() {
4004 let peer_id = PeerId::random();
4005 let trusted = TrustedPeer {
4006 host: url::Host::Domain("example.invalid".to_string()),
4007 tcp_port: 30303,
4008 udp_port: 30303,
4009 id: peer_id,
4010 };
4011
4012 let mut manager = PeersManager::default();
4013 manager.add_trusted_peer_node(trusted);
4014 manager.remove_peer_from_trusted_set(peer_id);
4015
4016 let resolved = NodeRecord {
4017 address: "10.0.0.1".parse::<IpAddr>().unwrap(),
4018 tcp_port: 30303,
4019 udp_port: 30303,
4020 id: peer_id,
4021 };
4022 manager.on_resolved_peer(peer_id, resolved);
4023
4024 assert!(!manager.peers.contains_key(&peer_id));
4025 assert!(!manager.trusted_peer_ids.contains(&peer_id));
4026 }
4027
4028 #[tokio::test]
4029 async fn test_resolution_promotes_basic_trusted_peer() {
4030 let peer_id = PeerId::random();
4031 let trusted = TrustedPeer {
4032 host: url::Host::Domain("example.invalid".to_string()),
4033 tcp_port: 30303,
4034 udp_port: 30303,
4035 id: peer_id,
4036 };
4037 let addr = "10.0.0.1:30303".parse::<SocketAddr>().unwrap();
4038
4039 let mut manager = PeersManager::default();
4040 manager.add_trusted_peer_node(trusted);
4041 manager.add_peer_kind(peer_id, Some(PeerKind::Basic), PeerAddr::from_tcp(addr), None);
4042 assert_eq!(manager.peers[&peer_id].kind, PeerKind::Basic);
4043 manager.on_resolved_peer(peer_id, NodeRecord::new(addr, peer_id));
4044 assert!(manager.peers[&peer_id].is_trusted());
4045 }
4046
4047 #[tokio::test]
4048 async fn test_rotation_disconnects_eligible_peer() {
4049 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
4050 let peer = PeerId::random();
4051 let mut peers = PeersManager::new(
4052 PeersConfig::test()
4053 .with_max_outbound(1)
4054 .with_peer_rotation_interval(Some(Duration::from_millis(50))),
4055 );
4056
4057 peers.add_peer(peer, PeerAddr::from_tcp(addr), None);
4058 match event!(peers) {
4059 PeerAction::PeerAdded(_) => {}
4060 _ => unreachable!(),
4061 }
4062 match event!(peers) {
4063 PeerAction::Connect { .. } => {}
4064 _ => unreachable!(),
4065 }
4066 peers.on_active_outgoing_established(peer);
4067
4068 set_connected_at(
4069 &mut peers,
4070 peer,
4071 std::time::Instant::now() - Duration::from_secs(11 * 60),
4072 );
4073
4074 tokio::time::sleep(Duration::from_millis(100)).await;
4075
4076 match event!(peers) {
4077 PeerAction::Disconnect { peer_id, reason } => {
4078 assert_eq!(peer_id, peer);
4079 assert_eq!(reason, Some(DisconnectReason::UselessPeer));
4080 }
4081 _ => unreachable!(),
4082 }
4083 }
4084
4085 #[tokio::test]
4086 async fn test_rotation_then_remove_uses_active_session_removal() {
4087 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 7)), 8008);
4088 let peer = PeerId::random();
4089 let mut peers = PeersManager::new(
4090 PeersConfig::test()
4091 .with_max_outbound(1)
4092 .with_peer_rotation_interval(Some(Duration::from_millis(50))),
4093 );
4094
4095 peers.add_peer(peer, PeerAddr::from_tcp(addr), None);
4096 match event!(peers) {
4097 PeerAction::PeerAdded(_) => {}
4098 _ => unreachable!(),
4099 }
4100 match event!(peers) {
4101 PeerAction::Connect { .. } => {}
4102 _ => unreachable!(),
4103 }
4104 peers.on_active_outgoing_established(peer);
4105 set_connected_at(
4106 &mut peers,
4107 peer,
4108 std::time::Instant::now() - Duration::from_secs(11 * 60),
4109 );
4110
4111 tokio::time::sleep(Duration::from_millis(100)).await;
4112
4113 match event!(peers) {
4114 PeerAction::Disconnect { peer_id, reason } => {
4115 assert_eq!(peer_id, peer);
4116 assert_eq!(reason, Some(DisconnectReason::UselessPeer));
4117 }
4118 _ => unreachable!(),
4119 }
4120 assert_eq!(peers.peers.get(&peer).unwrap().state, PeerConnectionState::Out);
4121 assert_eq!(peers.connection_info.num_outbound, 1);
4122
4123 peers.remove_peer(peer);
4124 match event!(peers) {
4125 PeerAction::PeerRemoved(peer_id) => assert_eq!(peer_id, peer),
4126 _ => unreachable!(),
4127 }
4128 match event!(peers) {
4129 PeerAction::Disconnect { peer_id, reason } => {
4130 assert_eq!(peer_id, peer);
4131 assert_eq!(reason, Some(DisconnectReason::DisconnectRequested));
4132 }
4133 _ => unreachable!(),
4134 }
4135
4136 let p = peers.peers.get(&peer).unwrap();
4137 assert_eq!(p.state, PeerConnectionState::DisconnectingOut);
4138 assert!(p.remove_after_disconnect);
4139 assert_eq!(peers.connection_info.num_outbound, 1);
4140
4141 peers.on_active_session_gracefully_closed(peer);
4142 assert_eq!(peers.connection_info.num_outbound, 0);
4143 assert!(!peers.peers.contains_key(&peer));
4144 }
4145
4146 #[tokio::test]
4147 async fn test_rotation_skips_trusted_peers() {
4148 let _addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 3)), 8008);
4149 let peer = PeerId::random();
4150 let trusted = TrustedPeer {
4151 host: Host::Ipv4(Ipv4Addr::new(127, 0, 1, 3)),
4152 tcp_port: 8008,
4153 udp_port: 8008,
4154 id: peer,
4155 };
4156 let mut peers = PeersManager::new(
4157 PeersConfig::test()
4158 .with_max_outbound(1)
4159 .with_trusted_nodes(vec![trusted])
4160 .with_peer_rotation_interval(Some(Duration::from_millis(50))),
4161 );
4162
4163 match event!(peers) {
4164 PeerAction::Connect { .. } => {}
4165 _ => unreachable!(),
4166 }
4167 peers.on_active_outgoing_established(peer);
4168 set_connected_at(
4169 &mut peers,
4170 peer,
4171 std::time::Instant::now() - Duration::from_secs(11 * 60),
4172 );
4173
4174 tokio::time::sleep(Duration::from_millis(100)).await;
4175
4176 poll_fn(|cx| {
4177 assert!(peers.poll(cx).is_pending(), "trusted peer must not be rotated");
4178 Poll::Ready(())
4179 })
4180 .await;
4181 }
4182
4183 #[tokio::test]
4184 async fn test_rotation_skips_recently_connected_peers() {
4185 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 4)), 8008);
4186 let peer = PeerId::random();
4187 let mut peers = PeersManager::new(
4188 PeersConfig::test()
4189 .with_max_outbound(1)
4190 .with_peer_rotation_interval(Some(Duration::from_millis(50))),
4191 );
4192
4193 peers.add_peer(peer, PeerAddr::from_tcp(addr), None);
4194 match event!(peers) {
4195 PeerAction::PeerAdded(_) => {}
4196 _ => unreachable!(),
4197 }
4198 match event!(peers) {
4199 PeerAction::Connect { .. } => {}
4200 _ => unreachable!(),
4201 }
4202 peers.on_active_outgoing_established(peer);
4203
4204 tokio::time::sleep(Duration::from_millis(100)).await;
4205
4206 poll_fn(|cx| {
4207 assert!(peers.poll(cx).is_pending(), "recently connected peer must not be rotated");
4208 Poll::Ready(())
4209 })
4210 .await;
4211 }
4212
4213 #[tokio::test]
4214 async fn test_rotation_skips_when_slots_available() {
4215 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 5)), 8008);
4216 let peer = PeerId::random();
4217 let mut peers = PeersManager::new(
4218 PeersConfig::test()
4219 .with_max_outbound(2)
4220 .with_peer_rotation_interval(Some(Duration::from_millis(50))),
4221 );
4222
4223 peers.add_peer(peer, PeerAddr::from_tcp(addr), None);
4224 match event!(peers) {
4225 PeerAction::PeerAdded(_) => {}
4226 _ => unreachable!(),
4227 }
4228 match event!(peers) {
4229 PeerAction::Connect { .. } => {}
4230 _ => unreachable!(),
4231 }
4232 peers.on_active_outgoing_established(peer);
4233 set_connected_at(
4234 &mut peers,
4235 peer,
4236 std::time::Instant::now() - Duration::from_secs(11 * 60),
4237 );
4238
4239 tokio::time::sleep(Duration::from_millis(100)).await;
4240
4241 poll_fn(|cx| {
4242 assert!(
4243 peers.poll(cx).is_pending(),
4244 "rotation must not fire when outbound slots are available"
4245 );
4246 Poll::Ready(())
4247 })
4248 .await;
4249 }
4250
4251 #[tokio::test]
4252 async fn test_rotation_disconnects_inbound_peer() {
4253 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 6)), 8008);
4254 let peer = PeerId::random();
4255 let mut peers = PeersManager::new(
4256 PeersConfig::test()
4257 .with_max_inbound(1)
4258 .with_peer_rotation_interval(Some(Duration::from_millis(50))),
4259 );
4260
4261 assert!(peers.on_incoming_pending_session(addr.ip()).is_ok());
4262 peers.on_incoming_session_established(peer, addr);
4263
4264 match event!(peers) {
4265 PeerAction::PeerAdded(_) => {}
4266 _ => unreachable!(),
4267 }
4268
4269 set_connected_at(
4270 &mut peers,
4271 peer,
4272 std::time::Instant::now() - Duration::from_secs(11 * 60),
4273 );
4274
4275 tokio::time::sleep(Duration::from_millis(100)).await;
4276
4277 match event!(peers) {
4278 PeerAction::Disconnect { peer_id, reason } => {
4279 assert_eq!(peer_id, peer);
4280 assert_eq!(reason, Some(DisconnectReason::UselessPeer));
4281 }
4282 _ => unreachable!(),
4283 }
4284 }
4285
4286 #[tokio::test]
4289 async fn test_requested_peer_is_dialed_before_refill_tick() {
4290 let mut peers = PeersManager::new(PeersConfig {
4291 refill_slots_interval: Duration::from_secs(60),
4292 ..PeersConfig::test()
4293 });
4294 assert!(poll_now(&mut peers).is_pending());
4296
4297 let discovered = PeerId::random();
4298 let discovered_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 1)), 8008);
4299 peers.add_peer(discovered, PeerAddr::from_tcp(discovered_addr), None);
4300 assert!(
4301 matches!(poll_now(&mut peers), Poll::Ready(PeerAction::PeerAdded(id)) if id == discovered)
4302 );
4303 assert!(poll_now(&mut peers).is_pending());
4304
4305 let requested = PeerId::random();
4306 let requested_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 1, 2)), 8008);
4307 peers.handle().add_peer(requested, requested_addr);
4308 assert!(
4309 matches!(poll_now(&mut peers), Poll::Ready(PeerAction::PeerAdded(id)) if id == requested)
4310 );
4311
4312 let mut dialed = Vec::new();
4314 while let Poll::Ready(PeerAction::Connect { peer_id, .. }) = poll_now(&mut peers) {
4315 dialed.push(peer_id);
4316 }
4317 dialed.sort();
4318 let mut expected = vec![discovered, requested];
4319 expected.sort();
4320 assert_eq!(dialed, expected);
4321 }
4322
4323 #[tokio::test]
4324 async fn test_revoke_trust_independent_of_peer_kind() {
4325 for kind in [None, Some(PeerKind::Basic), Some(PeerKind::Static), Some(PeerKind::Trusted)] {
4326 let mut peers = PeersManager::new(PeersConfig::test());
4327 let peer_id = PeerId::random();
4328 peers.add_trusted_peer_id(peer_id);
4329 if let Some(kind) = kind {
4330 peers.add_peer_kind(
4331 peer_id,
4332 Some(kind),
4333 PeerAddr::from_tcp("127.0.0.1:8008".parse().unwrap()),
4334 None,
4335 );
4336 }
4337 peers.remove_peer_from_trusted_set(peer_id);
4338 assert!(!peers.trusted_peer_ids.contains(&peer_id));
4339 assert_eq!(
4340 peers.peers.get(&peer_id).map(|peer| peer.kind),
4341 kind.map(|kind| if kind == PeerKind::Trusted { PeerKind::Basic } else { kind })
4342 );
4343 peers.ban_peer_by_admin(peer_id);
4345 assert!(peers.ban_list.is_banned_peer(&peer_id));
4346 }
4347 }
4348
4349 #[tokio::test]
4350 async fn test_persisted_trust_controls_inbound_admission() {
4351 for kind in [PeerKind::Basic, PeerKind::Static, PeerKind::Trusted] {
4352 for trusted_only in [false, true] {
4353 let peer_id = PeerId::random();
4354 let addr = "127.0.0.1:8008".parse::<SocketAddr>().unwrap();
4355 let mut config = PeersConfig::test().with_trusted_nodes_only(trusted_only);
4356 config.connection_info.max_inbound = 0;
4357 config.persisted_peers.push(PersistedPeerInfo {
4358 record: NodeRecord::new(addr, peer_id),
4359 kind,
4360 fork_id: None,
4361 reputation: 0,
4362 });
4363 let mut peers = PeersManager::new(config);
4364 assert_eq!(peers.trusted_peer_ids.contains(&peer_id), kind.is_trusted());
4365 peers.connection_info.inc_pending_in();
4366 peers.on_incoming_session_established(peer_id, addr);
4367 if kind.is_trusted() {
4368 assert!(peers.queued_actions.is_empty());
4369 assert_eq!(peers.connection_info.num_inbound, 1);
4370 } else if trusted_only {
4371 assert!(matches!(peers.queued_actions.pop_front(),
4372 Some(PeerAction::DisconnectUntrustedIncoming { peer_id: id }) if id == peer_id));
4373 } else {
4374 assert!(matches!(peers.queued_actions.pop_front(),
4375 Some(PeerAction::Disconnect { peer_id: id, reason: Some(DisconnectReason::TooManyPeers) }) if id == peer_id));
4376 }
4377 }
4378 }
4379 }
4380
4381 #[tokio::test]
4382 async fn test_filtered_persisted_peer_does_not_restore_trust() {
4383 let peer_id = PeerId::random();
4384 let mut config = PeersConfig::test();
4385 config.enforce_enr_fork_id = true;
4386 config.persisted_peers.push(PersistedPeerInfo {
4387 record: NodeRecord::new("127.0.0.1:8008".parse().unwrap(), peer_id),
4388 kind: PeerKind::Trusted,
4389 fork_id: None,
4390 reputation: 0,
4391 });
4392 let peers = PeersManager::new(config);
4393 assert!(!peers.trusted_peer_ids.contains(&peer_id));
4394 assert!(!peers.peers.contains_key(&peer_id));
4395 }
4396 #[tokio::test]
4397 async fn test_pending_dials_reserve_outbound_capacity() {
4398 for max_outbound in [0, 1, 3] {
4399 let mut peers = PeersManager::new(PeersConfig::test().with_max_outbound(max_outbound));
4400 let addr = PeerAddr::from_tcp("127.0.0.1:8008".parse().unwrap());
4401 for _ in 0..30 {
4402 peers.add_peer(PeerId::random(), addr, None);
4403 }
4404 peers.fill_outbound_slots();
4405 let dialed = peers
4406 .queued_actions
4407 .iter()
4408 .filter_map(|action| match action {
4409 PeerAction::Connect { peer_id, .. } => Some(*peer_id),
4410 _ => None,
4411 })
4412 .collect::<Vec<_>>();
4413 assert_eq!(dialed.len(), max_outbound);
4414 peers.queued_actions.clear();
4415 for peer in dialed {
4416 peers.on_active_outgoing_established(peer);
4417 peers.fill_outbound_slots();
4418 assert!(peers.queued_actions.is_empty());
4419 }
4420 assert_eq!(peers.connection_info.num_outbound, max_outbound);
4421 assert_eq!(peers.connection_info.num_pending_out, 0);
4422 }
4423 }
4424
4425 #[tokio::test]
4426 async fn test_surplus_outbound_completion() {
4427 for kind in [PeerKind::Basic, PeerKind::Trusted, PeerKind::Static] {
4428 let mut peers = PeersManager::new(PeersConfig::test().with_max_outbound(0));
4429 let peer = PeerId::random();
4430 let addr = PeerAddr::from_tcp("127.0.0.1:8008".parse().unwrap());
4431 peers.add_and_connect_kind(peer, kind, addr, None);
4432 peers.queued_actions.clear();
4433 peers.on_active_outgoing_established(peer);
4434 if kind == PeerKind::Basic {
4435 assert!(matches!(
4436 peers.queued_actions.pop_front(),
4437 Some(PeerAction::Disconnect {
4438 peer_id,
4439 reason: Some(DisconnectReason::TooManyPeers),
4440 }) if peer_id == peer
4441 ));
4442 } else {
4443 assert!(peers.queued_actions.is_empty());
4444 }
4445 peers.on_active_session_gracefully_closed(peer);
4447 assert_eq!(peers.connection_info.num_outbound, 0);
4448 assert_eq!(peers.connection_info.num_pending_out, 0);
4449 }
4450 }
4451
4452 #[tokio::test]
4453 async fn test_surplus_outbound_preserves_id_trusted_peers() {
4454 for hostname in [false, true] {
4455 let mut peers = PeersManager::new(PeersConfig::test().with_max_outbound(0));
4456 let peer_id = PeerId::random();
4457 let addr = PeerAddr::from_tcp("127.0.0.1:8008".parse().unwrap());
4458 if hostname {
4459 peers.add_peer(peer_id, addr, None);
4460 peers.add_trusted_peer_node(TrustedPeer {
4461 host: Host::Domain("example.invalid".to_string()),
4462 tcp_port: 8008,
4463 udp_port: 8008,
4464 id: peer_id,
4465 });
4466 } else {
4467 peers.add_trusted_peer_id(peer_id);
4468 }
4469 peers.add_and_connect_kind(peer_id, PeerKind::Basic, addr, None);
4470 assert_eq!(peers.peers[&peer_id].kind, PeerKind::Basic);
4471 peers.queued_actions.clear();
4472
4473 peers.on_active_outgoing_established(peer_id);
4474
4475 assert!(peers.queued_actions.is_empty());
4476 assert_eq!(peers.num_outbound_connections(), 1);
4477 peers.on_active_session_gracefully_closed(peer_id);
4478 assert_eq!(peers.num_outbound_connections(), 0);
4479 assert_eq!(peers.num_pending_outbound_connections(), 0);
4480 }
4481 }
4482
4483 #[tokio::test]
4484 async fn test_pending_outbound_cleanup_preserves_incoming_session() {
4485 let mut peers = PeersManager::new(PeersConfig::test());
4486 let peer_id = PeerId::random();
4487 let addr = "127.0.0.1:8008".parse::<SocketAddr>().unwrap();
4488 peers.add_and_connect_kind(peer_id, PeerKind::Basic, PeerAddr::from_tcp(addr), None);
4489 peers.on_incoming_pending_session(addr.ip()).unwrap();
4490 peers.on_incoming_session_established(peer_id, addr);
4491 let connected_at = peers.peers[&peer_id].connected_at;
4492
4493 peers.on_outgoing_pending_session_gracefully_closed(&peer_id);
4494
4495 assert_eq!(peers.peers[&peer_id].state, PeerConnectionState::In);
4496 assert_eq!(peers.peers[&peer_id].connected_at, connected_at);
4497 assert_eq!(peers.connection_info.num_inbound, 1);
4498 assert_eq!(peers.num_pending_outbound_connections(), 0);
4499 }
4500
4501 #[tokio::test]
4502 async fn test_inbound_capacity_preserves_pending_outbound_and_trusted_exemption() {
4503 for trusted in [false, true] {
4504 let mut peers = PeersManager::new(PeersConfig::test().with_max_inbound(0));
4505 let peer_id = PeerId::random();
4506 let addr = "127.0.0.1:8008".parse().unwrap();
4507 peers.add_and_connect_kind(peer_id, PeerKind::Basic, PeerAddr::from_tcp(addr), None);
4508 if trusted {
4509 peers.add_trusted_peer_id(peer_id);
4510 }
4511 assert_eq!(peers.has_inbound_capacity(peer_id), trusted);
4512 assert_eq!(peers.peers[&peer_id].state, PeerConnectionState::PendingOut);
4513 assert_eq!(peers.connection_info.num_pending_out, 1);
4514 }
4515 }
4516
4517 #[tokio::test]
4518 async fn test_unauthenticated_outbound_errors_do_not_ban_identity() {
4519 for error in [
4520 PendingSessionHandshakeError::Timeout,
4521 PendingSessionHandshakeError::Eth(EthStreamError::P2PStreamError(
4522 P2PStreamError::HandshakeError(P2PHandshakeError::Timeout),
4523 )),
4524 PendingSessionHandshakeError::Eth(EthStreamError::P2PStreamError(
4525 P2PStreamError::HandshakeError(P2PHandshakeError::NoResponse),
4526 )),
4527 PendingSessionHandshakeError::Ecies(ECIESErrorImpl::InvalidAckData.into()),
4528 PendingSessionHandshakeError::Ecies(ECIESErrorImpl::TagCheckDecryptFailed.into()),
4529 PendingSessionHandshakeError::Eth(EthStreamError::P2PStreamError(P2PStreamError::Io(
4530 io::Error::other("invalid frame MAC"),
4531 ))),
4532 ] {
4533 let mut peers = PeersManager::new(PeersConfig::test());
4534 let peer_id = PeerId::random();
4535 let addr = "8.8.8.8:30303".parse::<SocketAddr>().unwrap();
4536 peers.add_and_connect_kind(peer_id, PeerKind::Basic, PeerAddr::from_tcp(addr), None);
4537 peers.queued_actions.clear();
4538 let reputation = peers.peers[&peer_id].reputation;
4539 for _ in 0..=peers.max_backoff_count + 1 {
4540 peers.add_and_connect_kind(
4541 peer_id,
4542 PeerKind::Basic,
4543 PeerAddr::from_tcp(addr),
4544 None,
4545 );
4546 peers.queued_actions.clear();
4547 peers.on_outgoing_pending_session_dropped(&addr, &peer_id, &error);
4548 assert_eq!(peers.peers[&peer_id].reputation, reputation);
4549 }
4550 let peer = &peers.peers[&peer_id];
4551 assert_eq!(peer.state, PeerConnectionState::Idle);
4552 assert_eq!(peer.reputation, reputation);
4553 assert_eq!(peer.severe_backoff_counter, 0);
4554 assert!(peer.backed_off);
4555 assert!(!peers.ban_list.is_banned_peer(&peer_id));
4556 assert!(peers.queued_actions.is_empty());
4557 assert_eq!(peers.connection_info.num_pending_out, 0);
4558
4559 if matches!(&error, PendingSessionHandshakeError::Ecies(_)) {
4561 peers.connection_info.inc_pending_in();
4562 peers.on_incoming_pending_session_dropped(addr, &error);
4563 assert!(peers.ban_list.is_banned_ip(&addr.ip()));
4564 }
4565 }
4566 }
4567
4568 #[tokio::test]
4569 async fn test_unattributable_backoff_respects_maximum() {
4570 let mut config = PeersConfig::test();
4571 config.backoff_durations.low = Duration::from_secs(60);
4572 config.backoff_durations.max = Duration::from_secs(1);
4573 let mut peers = PeersManager::new(config);
4574 let peer_id = PeerId::random();
4575 let addr = "8.8.8.8:30303".parse::<SocketAddr>().unwrap();
4576 peers.add_and_connect_kind(peer_id, PeerKind::Basic, PeerAddr::from_tcp(addr), None);
4577 peers.peers.get_mut(&peer_id).unwrap().severe_backoff_counter = 3;
4578 let before = std::time::Instant::now();
4579 peers.on_outgoing_pending_session_dropped(
4580 &addr,
4581 &peer_id,
4582 &PendingSessionHandshakeError::Timeout,
4583 );
4584 let after = std::time::Instant::now();
4585 let until = peers.backed_off_peers[&peer_id];
4586 assert!(until >= before + Duration::from_secs(1));
4587 assert!(until <= after + Duration::from_secs(1));
4588 assert_eq!(peers.peers[&peer_id].severe_backoff_counter, 3);
4589 }
4590
4591 #[tokio::test]
4592 async fn test_dns_trusted_ids_bypass_outbound_capacity() {
4593 for register_first in [false, true] {
4594 let mut peers = PeersManager::new(PeersConfig::test().with_max_outbound(0));
4595 let peer_id = PeerId::random();
4596 let addr = "127.0.0.1:30303".parse::<SocketAddr>().unwrap();
4597 let trusted =
4598 TrustedPeer::new(Host::Domain("trusted.invalid".into()), addr.port(), peer_id);
4599 if register_first {
4600 peers.add_trusted_peer_node(trusted.clone());
4601 }
4602 peers.add_peer(peer_id, PeerAddr::from_tcp(addr), None);
4603 if !register_first {
4604 peers.add_trusted_peer_node(trusted);
4605 }
4606 assert_eq!(peers.peers[&peer_id].kind, PeerKind::Trusted);
4607 peers.queued_actions.clear();
4608 peers.fill_outbound_slots();
4609 assert!(
4610 matches!(peers.queued_actions.pop_front(), Some(PeerAction::Connect { peer_id: id, remote_addr }) if id == peer_id && remote_addr == addr)
4611 );
4612 assert!(peers.queued_actions.is_empty());
4613 }
4614 }
4615
4616 #[tokio::test]
4617 async fn test_trusted_bypass_respects_shared_dial_limit() {
4618 let mut peers = PeersManager::new(
4619 PeersConfig::test().with_max_outbound(1).with_max_concurrent_dials(1),
4620 );
4621 let addr = "127.0.0.1:30303".parse().unwrap();
4622 let basic = PeerId::random();
4623 peers.add_peer(basic, PeerAddr::from_tcp(addr), None);
4624 peers.fill_outbound_slots();
4625 assert_eq!(peers.connection_info.num_pending_out, 1);
4626 for _ in 0..2 {
4627 peers.add_trusted_peer(PeerId::random(), PeerAddr::from_tcp(addr));
4628 }
4629 peers.queued_actions.clear();
4630 peers.fill_outbound_slots();
4631 assert!(peers.queued_actions.is_empty());
4632 peers.on_active_outgoing_established(basic);
4633 peers.fill_outbound_slots();
4634 assert!(
4635 matches!(peers.queued_actions.pop_front(), Some(PeerAction::Connect { peer_id, .. }) if peers.peers[&peer_id].is_trusted())
4636 );
4637 assert!(peers.queued_actions.is_empty());
4638 assert_eq!(peers.connection_info.num_pending_out, 1);
4639 assert_eq!(peers.connection_info.num_outbound, 1);
4640 }
4641
4642 #[tokio::test]
4643 async fn test_ip_filter_preserves_trust_on_rediscovery() {
4644 for persisted in [false, true] {
4645 let blocked = NodeRecord::new("10.0.0.1:30303".parse().unwrap(), PeerId::random());
4646 let allowed = NodeRecord::new("192.168.1.1:30303".parse().unwrap(), blocked.id);
4647 let mut config = PeersConfig::test()
4648 .with_ip_filter(IpFilter::from_cidr_string("192.168.0.0/16").unwrap());
4649 if persisted {
4650 config.persisted_peers.push(PersistedPeerInfo {
4651 kind: PeerKind::Trusted,
4652 ..PersistedPeerInfo::from_node_record(blocked)
4653 });
4654 } else {
4655 config.trusted_nodes.push(blocked.into());
4656 }
4657 let mut peers = PeersManager::new(config);
4658 assert!(peers.peers.is_empty());
4659 assert!(peers.trusted_peer_ids.contains(&blocked.id));
4660 peers.add_peer(blocked.id, PeerAddr::from_tcp(blocked.tcp_addr()), None);
4661 assert!(peers.peers.is_empty());
4662
4663 peers.add_peer(allowed.id, PeerAddr::from_tcp(allowed.tcp_addr()), None);
4664 assert_eq!(peers.peers[&allowed.id].kind, PeerKind::Trusted);
4665 peers.apply_reputation_change(&allowed.id, ReputationChangeKind::Timeout);
4666 assert_eq!(peers.peers[&allowed.id].reputation, DEFAULT_REPUTATION);
4667 peers.remove_peer(allowed.id);
4668 assert!(peers.peers.contains_key(&allowed.id));
4669 assert_eq!(peers.persistable_peers().next().unwrap().kind, PeerKind::Trusted);
4670
4671 peers.remove_peer_from_trusted_set(allowed.id);
4672 peers.remove_peer(allowed.id);
4673 peers.add_peer(allowed.id, PeerAddr::from_tcp(allowed.tcp_addr()), None);
4674 assert_eq!(peers.peers[&allowed.id].kind, PeerKind::Basic);
4675 }
4676 }
4677
4678 #[tokio::test]
4679 async fn test_ip_filter_preserves_trust_with_startup_fallback() {
4680 for persisted_trust in [false, true] {
4681 for persisted_fallback in [false, true] {
4682 let blocked = NodeRecord::new("10.0.0.1:30303".parse().unwrap(), PeerId::random());
4683 let allowed = NodeRecord::new("192.168.1.1:30303".parse().unwrap(), blocked.id);
4684 let mut config = PeersConfig::test()
4685 .with_ip_filter(IpFilter::from_cidr_string("192.168.0.0/16").unwrap());
4686 if persisted_trust {
4687 config.persisted_peers.push(PersistedPeerInfo {
4688 kind: PeerKind::Trusted,
4689 ..PersistedPeerInfo::from_node_record(blocked)
4690 });
4691 } else {
4692 config.trusted_nodes.push(blocked.into());
4693 }
4694 if persisted_fallback {
4695 config.persisted_peers.push(PersistedPeerInfo::from_node_record(allowed));
4696 } else {
4697 config.basic_nodes.insert(allowed);
4698 }
4699 let peers = PeersManager::new(config);
4700 assert_eq!(peers.peers.len(), 1);
4701 assert!(peers.trusted_peer_ids.contains(&allowed.id));
4702 assert_eq!(peers.peers[&allowed.id].kind, PeerKind::Trusted);
4703 assert_eq!(peers.peers[&allowed.id].addr.tcp(), allowed.tcp_addr());
4704 }
4705 }
4706 }
4707
4708 #[tokio::test]
4709 async fn test_ip_filter_startup_ipv6_and_allowed_metadata() {
4710 for kind in [PeerKind::Basic, PeerKind::Static, PeerKind::Trusted] {
4711 let allowed = NodeRecord::new("[2001:db8::1]:30303".parse().unwrap(), PeerId::random());
4712 let blocked = NodeRecord::new("[2001:db9::1]:30303".parse().unwrap(), PeerId::random());
4713 let fork_id = ForkId { hash: ForkHash([1, 2, 3, 4]), next: 0 };
4714 let mut config = PeersConfig::test()
4715 .with_ip_filter(IpFilter::from_cidr_string("2001:db8::/32").unwrap());
4716 config.persisted_peers = [allowed, blocked]
4717 .into_iter()
4718 .map(|record| PersistedPeerInfo {
4719 record,
4720 kind,
4721 fork_id: Some(fork_id),
4722 reputation: 10,
4723 })
4724 .collect();
4725 let mut peers = PeersManager::new(config);
4726 assert_eq!(peers.peers.len(), 1);
4727 assert_eq!(peers.trusted_peer_ids.contains(&blocked.id), kind.is_trusted());
4728 assert_eq!(
4729 peers.persistable_peers().collect::<Vec<_>>(),
4730 [PersistedPeerInfo {
4731 record: allowed,
4732 kind,
4733 fork_id: Some(fork_id),
4734 reputation: 10,
4735 }]
4736 );
4737 peers.fill_outbound_slots();
4738 assert!(
4739 matches!(peers.queued_actions.pop_front(), Some(PeerAction::Connect { peer_id, remote_addr })
4740 if peer_id == allowed.id && remote_addr == allowed.tcp_addr())
4741 );
4742 assert!(peers.queued_actions.is_empty());
4743 }
4744 }
4745}