From 95af19096416c08b28fce4b5fd6142e73a09087d Mon Sep 17 00:00:00 2001 From: xdustinface Date: Thu, 5 Feb 2026 03:36:29 +0100 Subject: [PATCH 1/2] refactor to return `AddrV2Message` in `get_known_addresses` --- dash-spv/src/network/addrv2.rs | 6 +++--- dash-spv/src/network/reputation.rs | 17 +++++++++++------ dash-spv/src/network/reputation_tests.rs | 16 ++++++++-------- dash-spv/tests/peer_test.rs | 2 +- dash/src/test_utils/mod.rs | 1 + dash/src/test_utils/network.rs | 14 ++++++++++++++ 6 files changed, 38 insertions(+), 18 deletions(-) create mode 100644 dash/src/test_utils/network.rs diff --git a/dash-spv/src/network/addrv2.rs b/dash-spv/src/network/addrv2.rs index 6c57dc6d7..896b24596 100644 --- a/dash-spv/src/network/addrv2.rs +++ b/dash-spv/src/network/addrv2.rs @@ -114,8 +114,8 @@ impl AddrV2Handler { } /// Get all known socket addresses - pub async fn get_known_addresses(&self) -> Vec { - self.known_peers.read().await.iter().filter_map(|addr| addr.socket_addr().ok()).collect() + pub async fn get_known_addresses(&self) -> Vec { + self.known_peers.read().await.clone() } /// Add a known peer address @@ -183,7 +183,7 @@ mod tests { let known = handler.get_known_addresses().await; assert_eq!(known.len(), 1); - assert_eq!(known[0], addr); + assert_eq!(known[0].socket_addr().unwrap(), addr); } #[tokio::test] diff --git a/dash-spv/src/network/reputation.rs b/dash-spv/src/network/reputation.rs index 9b6e72622..518b6c2c7 100644 --- a/dash-spv/src/network/reputation.rs +++ b/dash-spv/src/network/reputation.rs @@ -5,6 +5,8 @@ //! implements automatic banning for excessive misbehavior, and provides reputation //! decay over time for recovery. +use crate::storage::PeerStorage; +use dashcore::network::address::AddrV2Message; use serde::{Deserialize, Deserializer, Serialize}; use std::collections::HashMap; use std::net::SocketAddr; @@ -12,8 +14,6 @@ use std::sync::Arc; use std::time::{Duration, Instant}; use tokio::sync::RwLock; -use crate::storage::PeerStorage; - /// Misbehavior score thresholds for different violations pub mod misbehavior_scores { /// Invalid message format or protocol violation @@ -498,7 +498,7 @@ pub trait ReputationAware { /// Select best peers based on reputation fn select_best_peers( &self, - available_peers: Vec, + available_peers: Vec, count: usize, ) -> impl std::future::Future> + Send; @@ -512,18 +512,23 @@ pub trait ReputationAware { impl ReputationAware for PeerReputationManager { async fn select_best_peers( &self, - available_peers: Vec, + available_peers: Vec, count: usize, ) -> Vec { let mut peer_scores = Vec::new(); let mut reputations = self.reputations.write().await; for peer in available_peers { - let reputation = reputations.entry(peer).or_default(); + let Ok(socket_addr) = peer.socket_addr() else { + log::warn!("Skip invalid peer address: {:?}", peer); + continue; + }; + + let reputation = reputations.entry(socket_addr).or_default(); reputation.apply_decay(); if !reputation.is_banned() { - peer_scores.push((peer, reputation.score)); + peer_scores.push((socket_addr, reputation.score)); } } diff --git a/dash-spv/src/network/reputation_tests.rs b/dash-spv/src/network/reputation_tests.rs index e3403646f..b8b140057 100644 --- a/dash-spv/src/network/reputation_tests.rs +++ b/dash-spv/src/network/reputation_tests.rs @@ -81,22 +81,22 @@ mod tests { async fn test_peer_selection() { let manager = PeerReputationManager::new(); - let good_peer: SocketAddr = "1.1.1.1:8333".parse().unwrap(); - let neutral_peer: SocketAddr = "2.2.2.2:8333".parse().unwrap(); - let bad_peer: SocketAddr = "3.3.3.3:8333".parse().unwrap(); + let good_peer = AddrV2Message::dummy(0, "1.1.1.1".parse().unwrap(), 8333); + let neutral_peer = AddrV2Message::dummy(0, "2.2.2.2".parse().unwrap(), 8333); + let bad_peer = AddrV2Message::dummy(0, "3.3.3.3".parse().unwrap(), 8333); // Set different reputations - manager.update_reputation(good_peer, -20, "Very good").await; - manager.update_reputation(bad_peer, 80, "Very bad").await; + manager.update_reputation(good_peer.socket_addr().unwrap(), -20, "Very good").await; + manager.update_reputation(bad_peer.socket_addr().unwrap(), 80, "Very bad").await; // neutral_peer has default score of 0 - let all_peers = vec![good_peer, neutral_peer, bad_peer]; + let all_peers = vec![good_peer.clone(), neutral_peer.clone(), bad_peer.clone()]; let selected = manager.select_best_peers(all_peers, 2).await; // Should select good_peer first, then neutral_peer assert_eq!(selected.len(), 2); - assert_eq!(selected[0], good_peer); - assert_eq!(selected[1], neutral_peer); + assert_eq!(selected[0], good_peer.socket_addr().unwrap()); + assert_eq!(selected[1], neutral_peer.socket_addr().unwrap()); } #[tokio::test] diff --git a/dash-spv/tests/peer_test.rs b/dash-spv/tests/peer_test.rs index ebf0067f6..c15e7f50e 100644 --- a/dash-spv/tests/peer_test.rs +++ b/dash-spv/tests/peer_test.rs @@ -223,7 +223,7 @@ mod unit_tests { handler.add_known_address(peer, ServiceFlags::from(1)).await; let known = handler.get_known_addresses().await; assert_eq!(known.len(), 1); - assert_eq!(known[0], peer); + assert_eq!(known[0].socket_addr().unwrap(), peer); // Test getting addresses for sharing let to_share = handler.get_addresses_for_peer(10).await; diff --git a/dash/src/test_utils/mod.rs b/dash/src/test_utils/mod.rs index ef5388c35..287757dfc 100644 --- a/dash/src/test_utils/mod.rs +++ b/dash/src/test_utils/mod.rs @@ -3,4 +3,5 @@ mod block; mod chainlock; mod filter; mod instantlock; +mod network; mod transaction; diff --git a/dash/src/test_utils/network.rs b/dash/src/test_utils/network.rs new file mode 100644 index 000000000..5a5996f28 --- /dev/null +++ b/dash/src/test_utils/network.rs @@ -0,0 +1,14 @@ +use crate::network::address::{AddrV2, AddrV2Message}; +use crate::network::constants::ServiceFlags; +use std::net::Ipv4Addr; + +impl AddrV2Message { + pub fn dummy(time: u32, addr: Ipv4Addr, port: u16) -> Self { + Self { + time, + services: ServiceFlags::NONE, + addr: AddrV2::Ipv4(addr), + port, + } + } +} From d6e042d7403dbc575a08d1dd21ec6adbd9bfe5c8 Mon Sep 17 00:00:00 2001 From: xdustinface Date: Fri, 6 Feb 2026 15:50:46 +0100 Subject: [PATCH 2/2] save all known peers --- dash-spv/src/network/manager.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash-spv/src/network/manager.rs b/dash-spv/src/network/manager.rs index 1f4232cc6..60f41b5b7 100644 --- a/dash-spv/src/network/manager.rs +++ b/dash-spv/src/network/manager.rs @@ -886,7 +886,7 @@ impl PeerNetworkManager { // Only save known peers if not in exclusive mode if !exclusive_mode { - let addresses = addrv2_handler.get_addresses_for_peer(MAX_ADDR_TO_STORE).await; + let addresses = addrv2_handler.get_known_addresses().await; if !addresses.is_empty() { if let Err(e) = peer_store.save_peers(&addresses).await { log::warn!("Failed to save peers: {}", e);