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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions dash-spv/src/network/addrv2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ impl AddrV2Handler {
}

/// Get all known socket addresses
pub async fn get_known_addresses(&self) -> Vec<SocketAddr> {
self.known_peers.read().await.iter().filter_map(|addr| addr.socket_addr().ok()).collect()
pub async fn get_known_addresses(&self) -> Vec<AddrV2Message> {
self.known_peers.read().await.clone()
}

/// Add a known peer address
Expand Down Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion dash-spv/src/network/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
17 changes: 11 additions & 6 deletions dash-spv/src/network/reputation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
//! 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;
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
Expand Down Expand Up @@ -498,7 +498,7 @@ pub trait ReputationAware {
/// Select best peers based on reputation
fn select_best_peers(
&self,
available_peers: Vec<SocketAddr>,
available_peers: Vec<AddrV2Message>,
count: usize,
) -> impl std::future::Future<Output = Vec<SocketAddr>> + Send;

Expand All @@ -512,18 +512,23 @@ pub trait ReputationAware {
impl ReputationAware for PeerReputationManager {
async fn select_best_peers(
&self,
available_peers: Vec<SocketAddr>,
available_peers: Vec<AddrV2Message>,
count: usize,
) -> Vec<SocketAddr> {
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));
}
}

Expand Down
16 changes: 8 additions & 8 deletions dash-spv/src/network/reputation_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion dash-spv/tests/peer_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions dash/src/test_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ mod block;
mod chainlock;
mod filter;
mod instantlock;
mod network;
mod transaction;
14 changes: 14 additions & 0 deletions dash/src/test_utils/network.rs
Original file line number Diff line number Diff line change
@@ -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,
}
}
}
Loading