Skip to content

Commit fe8384e

Browse files
committed
bad rebase fixed
1 parent e3621de commit fe8384e

7 files changed

Lines changed: 57 additions & 172 deletions

File tree

dash-spv/src/client/chainlock.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ impl<W: WalletInterface, N: NetworkManager, S: StorageManager> DashSpvClient<W,
4141
.await
4242
{
4343
// Penalize the peer that relayed the invalid ChainLock
44-
let reason = format!("Invalid ChainLock: {}", e);
45-
self.network.penalize_peer_invalid_chainlock(peer_address, &reason).await;
44+
self.network.penalize_peer_invalid_chainlock(peer_address).await;
4645
return Err(SpvError::Validation(e));
4746
}
4847
}
@@ -110,7 +109,7 @@ impl<W: WalletInterface, N: NetworkManager, S: StorageManager> DashSpvClient<W,
110109
tracing::warn!("{}", reason);
111110

112111
// Ban the peer using the reputation system
113-
self.network.penalize_peer_invalid_instantlock(peer_address, &reason).await;
112+
self.network.penalize_peer_invalid_instantlock(peer_address).await;
114113

115114
return Err(SpvError::Validation(e));
116115
}

dash-spv/src/network/manager.rs

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ use crate::network::addrv2::AddrV2Handler;
1717
use crate::network::constants::*;
1818
use crate::network::discovery::DnsDiscovery;
1919
use crate::network::pool::PeerPool;
20-
use crate::network::reputation::{
21-
misbehavior_scores, positive_scores, PeerReputationManager, ReputationAware,
22-
};
20+
use crate::network::reputation::{ChangeReason, PeerReputationManager};
2321
use crate::network::{
2422
HandshakeManager, Message, MessageDispatcher, MessageType, NetworkManager, Peer,
2523
};
@@ -446,11 +444,9 @@ impl PeerNetworkManager {
446444
headers2_disabled.lock().await.insert(addr);
447445
// Apply reputation penalty
448446
reputation_manager
449-
.update_reputation(
450-
addr,
451-
misbehavior_scores::INVALID_MESSAGE,
452-
"Headers2 decompression failed",
453-
)
447+
.lock()
448+
.await
449+
.update_reputation(addr, ChangeReason::InvalidHeaders2)
454450
.await;
455451
continue; // Don't forward corrupted message
456452
}
@@ -759,7 +755,7 @@ impl PeerNetworkManager {
759755
}
760756

761757
// Save reputation data periodically
762-
if let Err(e) = reputation_manager.save_to_storage(&*peer_store).await {
758+
if let Err(e) = reputation_manager.lock().await.save_to_storage(&*peer_store).await {
763759
log::warn!("Failed to save reputation data: {}", e);
764760
}
765761
}
@@ -978,17 +974,6 @@ impl PeerNetworkManager {
978974
Ok(())
979975
}
980976

981-
/// Get reputation information for all peers
982-
pub async fn get_peer_reputations(&self) -> HashMap<SocketAddr, (i32, bool)> {
983-
let reputations = self.reputation_manager.lock().await.get_all_reputations().await;
984-
reputations.into_iter().map(|(addr, rep)| (addr, (rep.score, rep.is_banned()))).collect()
985-
}
986-
987-
/// Unban a specific peer
988-
pub async fn unban_peer(&self, addr: &SocketAddr) {
989-
self.reputation_manager.lock().await.unban_peer(addr).await;
990-
}
991-
992977
/// Shutdown the network manager
993978
pub async fn shutdown(&self) {
994979
log::info!("Shutting down peer network manager");
@@ -1003,7 +988,9 @@ impl PeerNetworkManager {
1003988
}
1004989

1005990
// Save reputation data before shutdown
1006-
if let Err(e) = self.reputation_manager.save_to_storage(&*self.peer_store).await {
991+
if let Err(e) =
992+
self.reputation_manager.lock().await.save_to_storage(&*self.peer_store).await
993+
{
1007994
log::warn!("Failed to save reputation data on shutdown: {}", e);
1008995
}
1009996

@@ -1098,64 +1085,62 @@ impl NetworkManager for PeerNetworkManager {
10981085
} // end match
10991086
} // end send_message
11001087

1101-
async fn penalize_peer(&self, address: SocketAddr, score_change: i32, reason: &str) {
1102-
self.reputation_manager.update_reputation(address, score_change, reason).await;
1088+
async fn penalize_peer(&self, address: SocketAddr, reason: ChangeReason) {
1089+
self.reputation_manager.lock().await.update_reputation(address, reason).await;
11031090
}
11041091

1105-
async fn penalize_peer_invalid_chainlock(&self, address: SocketAddr, reason: &str) {
1106-
match self.disconnect_peer(&address, reason).await {
1092+
async fn penalize_peer_invalid_chainlock(&self, address: SocketAddr) {
1093+
match self.disconnect_peer(&address).await {
11071094
Ok(()) => {
1108-
log::warn!(
1109-
"Peer {} disconnected for invalid ChainLock enforcement: {}",
1110-
address,
1111-
reason
1112-
);
1095+
log::warn!("Peer {} disconnected for invalid ChainLock enforcement", address,);
11131096
}
11141097
Err(err) => {
11151098
log::error!(
1116-
"Failed to disconnect peer {} after invalid ChainLock enforcement ({}): {}",
1099+
"Failed to disconnect peer {} after invalid ChainLock enforcement: {}",
11171100
address,
1118-
reason,
11191101
err
11201102
);
11211103
}
11221104
}
11231105

11241106
// Apply misbehavior score and a short temporary ban
11251107
self.reputation_manager
1126-
.update_reputation(address, misbehavior_scores::INVALID_CHAINLOCK, reason)
1108+
.lock()
1109+
.await
1110+
.update_reputation(address, ChangeReason::InvalidChainLock)
11271111
.await;
11281112

11291113
// Short ban: 10 minutes for relaying invalid ChainLock
11301114
self.reputation_manager
1131-
.temporary_ban_peer(address, Duration::from_secs(10 * 60), reason)
1115+
.lock()
1116+
.await
1117+
.temporary_ban_peer(address, Duration::from_secs(10 * 60))
11321118
.await;
11331119
}
11341120

1135-
async fn penalize_peer_invalid_instantlock(&self, address: SocketAddr, reason: &str) {
1121+
async fn penalize_peer_invalid_instantlock(&self, address: SocketAddr) {
11361122
// Apply misbehavior score and a short temporary ban
11371123
self.reputation_manager
1138-
.update_reputation(address, misbehavior_scores::INVALID_INSTANTLOCK, reason)
1124+
.lock()
1125+
.await
1126+
.update_reputation(address, ChangeReason::InvalidInstantLock)
11391127
.await;
11401128

11411129
// Short ban: 10 minutes for relaying invalid InstantLock
11421130
self.reputation_manager
1143-
.temporary_ban_peer(address, Duration::from_secs(10 * 60), reason)
1131+
.lock()
1132+
.await
1133+
.temporary_ban_peer(address, Duration::from_secs(10 * 60))
11441134
.await;
11451135

1146-
match self.disconnect_peer(&address, reason).await {
1136+
match self.disconnect_peer(&address).await {
11471137
Ok(()) => {
1148-
log::warn!(
1149-
"Peer {} disconnected for invalid InstantLock enforcement: {}",
1150-
address,
1151-
reason
1152-
);
1138+
log::warn!("Peer {} disconnected for invalid InstantLock enforcement", address,);
11531139
}
11541140
Err(err) => {
11551141
log::error!(
1156-
"Failed to disconnect peer {} after invalid InstantLock enforcement ({}): {}",
1142+
"Failed to disconnect peer {} after invalid InstantLock enforcement: {}",
11571143
address,
1158-
reason,
11591144
err
11601145
);
11611146
}

dash-spv/src/network/mod.rs

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ mod message_type;
1414
#[cfg(test)]
1515
mod tests;
1616

17-
use crate::error::NetworkResult;
17+
use crate::{error::NetworkResult, network::reputation::ChangeReason};
1818
use async_trait::async_trait;
1919
use dashcore::network::message::NetworkMessage;
2020
use dashcore::BlockHash;
@@ -23,6 +23,7 @@ pub use manager::PeerNetworkManager;
2323
pub use message_dispatcher::{Message, MessageDispatcher};
2424
pub use message_type::MessageType;
2525
pub use peer::Peer;
26+
pub(crate) use reputation::PeerReputation;
2627
use std::net::SocketAddr;
2728
use tokio::sync::mpsc::UnboundedReceiver;
2829

@@ -95,25 +96,15 @@ pub trait NetworkManager: Send + Sync + 'static {
9596

9697
/// Penalize a peer by address by adjusting reputation.
9798
/// Default implementation is a no-op for managers without reputation.
98-
async fn penalize_peer(&self, _address: SocketAddr, _score_change: i32, _reason: &str) {}
99+
async fn penalize_peer(&self, _address: SocketAddr, _reason: ChangeReason) {}
99100

100101
/// Penalize a peer by address for an invalid ChainLock.
101-
async fn penalize_peer_invalid_chainlock(&self, address: SocketAddr, reason: &str) {
102-
self.penalize_peer(
103-
address,
104-
crate::network::reputation::misbehavior_scores::INVALID_CHAINLOCK,
105-
reason,
106-
)
107-
.await;
102+
async fn penalize_peer_invalid_chainlock(&self, address: SocketAddr) {
103+
self.penalize_peer(address, ChangeReason::InvalidChainLock).await;
108104
}
109105

110106
/// Penalize a peer by address for an invalid InstantLock.
111-
async fn penalize_peer_invalid_instantlock(&self, peer_address: SocketAddr, reason: &str) {
112-
self.penalize_peer(
113-
peer_address,
114-
crate::network::reputation::misbehavior_scores::INVALID_INSTANTLOCK,
115-
reason,
116-
)
117-
.await;
107+
async fn penalize_peer_invalid_instantlock(&self, peer_address: SocketAddr) {
108+
self.penalize_peer(peer_address, ChangeReason::InvalidInstantLock).await;
118109
}
119110
}

dash-spv/src/network/reputation.rs

Lines changed: 3 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ const MIN_MISBEHAVIOR_SCORE: i32 = -50;
8080

8181
const MAX_BAN_COUNT: u32 = 1000;
8282

83-
const MAX_ACTION_COUNT: u64 = 1_000_000;
84-
8583
fn clamp_peer_score<'de, D>(deserializer: D) -> Result<i32, D::Error>
8684
where
8785
D: Deserializer<'de>,
@@ -113,52 +111,10 @@ where
113111
Ok(v)
114112
}
115113

116-
fn clamp_peer_connection_attempts<'de, D>(deserializer: D) -> Result<u64, D::Error>
117-
where
118-
D: Deserializer<'de>,
119-
{
120-
let mut v = u64::deserialize(deserializer)?;
121-
122-
v = v.min(MAX_ACTION_COUNT);
123-
124-
Ok(v)
125-
}
126-
127114
fn default_instant() -> Instant {
128115
Instant::now()
129116
}
130117

131-
fn clamp_peer_score<'de, D>(deserializer: D) -> Result<i32, D::Error>
132-
where
133-
D: Deserializer<'de>,
134-
{
135-
let mut v = i32::deserialize(deserializer)?;
136-
137-
if v < MIN_MISBEHAVIOR_SCORE {
138-
log::warn!("Peer has invalid score {v}, clamping to min {MIN_MISBEHAVIOR_SCORE}");
139-
v = MIN_MISBEHAVIOR_SCORE
140-
} else if v > MAX_MISBEHAVIOR_SCORE {
141-
log::warn!("Peer has invalid score {v}, clamping to max {MAX_MISBEHAVIOR_SCORE}");
142-
v = MAX_MISBEHAVIOR_SCORE
143-
}
144-
145-
Ok(v)
146-
}
147-
148-
fn clamp_peer_ban_count<'de, D>(deserializer: D) -> Result<u32, D::Error>
149-
where
150-
D: Deserializer<'de>,
151-
{
152-
let mut v = u32::deserialize(deserializer)?;
153-
154-
if v > MAX_BAN_COUNT {
155-
log::warn!("Peer has excessive ban count {v}, clamping to {MAX_BAN_COUNT}");
156-
v = MAX_BAN_COUNT
157-
}
158-
159-
Ok(v)
160-
}
161-
162118
/// Peer reputation entry
163119
#[derive(Debug, Clone, Serialize, Deserialize)]
164120
pub struct PeerReputation {
@@ -239,7 +195,7 @@ pub struct PeerReputationManager {
239195
}
240196

241197
impl PeerReputationManager {
242-
pub async fn load_or_new(storage: &PersistentPeerStorage) -> Self {
198+
pub async fn load_or_new(storage: &impl PeerStorage) -> Self {
243199
let mut reputations =
244200
storage.load_peers_reputation().await.unwrap_or_else(|_| HashMap::new());
245201

@@ -332,16 +288,6 @@ impl PeerReputationManager {
332288
reputation.last_connection = Some(Instant::now());
333289
}
334290

335-
/// Clear banned status for a peer (admin function)
336-
pub async fn unban_peer(&mut self, peer: &SocketAddr) {
337-
let reputations = &mut self.reputations;
338-
if let Some(reputation) = reputations.get_mut(peer) {
339-
reputation.banned_until = None;
340-
reputation.score = reputation.score.min(MAX_MISBEHAVIOR_SCORE - 10);
341-
log::info!("Manually unbanned peer {}", peer);
342-
}
343-
}
344-
345291
pub async fn select_best_peers(
346292
&mut self,
347293
available_peers: Vec<SocketAddr>,
@@ -372,34 +318,13 @@ impl PeerReputationManager {
372318

373319
/// Save reputation data to persistent storage
374320
pub async fn save_to_storage(&self, storage: &impl PeerStorage) -> std::io::Result<()> {
375-
let reputations = self.reputations.read().await;
376-
377-
storage.save_peers_reputation(&reputations).await.map_err(std::io::Error::other)
378-
}
379-
380-
/// Load reputation data from persistent storage
381-
pub async fn load_from_storage(&self, storage: &impl PeerStorage) -> std::io::Result<()> {
382-
let data = storage.load_peers_reputation().await.map_err(std::io::Error::other)?;
383-
log::info!("Loaded reputation data for {} peers", data.len());
384-
385-
let reputations = &mut self.reputations;
386-
387-
for (addr, mut reputation) in data {
388-
// Apply initial decay based on ban count
389-
if reputation.ban_count > 0 {
390-
reputation.score = reputation.score.max(50); // Start with higher score for previously banned peers
391-
}
392-
393-
reputations.insert(addr, reputation);
394-
}
395-
396-
Ok(())
321+
storage.save_peers_reputation(&self.reputations).await.map_err(std::io::Error::other)
397322
}
398323
}
399324

400325
#[cfg(test)]
401326
mod tests {
402-
use crate::storage::PersistentStorage;
327+
use crate::storage::{PersistentPeerStorage, PersistentStorage};
403328

404329
use super::*;
405330
use std::net::SocketAddr;

dash-spv/src/storage/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ pub struct DiskStorageManager {
8787
metadata: Arc<RwLock<PersistentMetadataStorage>>,
8888
chainstate: Arc<RwLock<PersistentChainStateStorage>>,
8989
masternodestate: Arc<RwLock<PersistentMasternodeStateStorage>>,
90-
peers: Arc<RwLock<PersistentPeerStorage>>,
9190

9291
// Background worker
9392
worker_handle: Option<tokio::task::JoinHandle<()>>,
@@ -130,7 +129,6 @@ impl DiskStorageManager {
130129
masternodestate: Arc::new(RwLock::new(
131130
PersistentMasternodeStateStorage::open(&storage_path).await?,
132131
)),
133-
peers: Arc::new(RwLock::new(PersistentPeerStorage::open(&storage_path).await?)),
134132

135133
worker_handle: None,
136134

dash-spv/src/storage/peers.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -97,27 +97,25 @@ impl PeerStorage for PersistentPeerStorage {
9797
return Ok(Vec::new());
9898
};
9999

100-
let mut peers = Vec::new();
101-
102100
let peers = tokio::task::spawn_blocking(move || {
103101
let file = File::open(&peers_file)?;
104102
let mut reader = BufReader::new(file);
105103

106-
let file = File::open(&peers_file)?;
107-
let mut reader = BufReader::new(file);
108-
let mut peers = Vec::new();
109-
110-
loop {
111-
match AddrV2Message::consensus_decode(&mut reader) {
112-
Ok(peer) => peers.push(peer),
113-
Err(encode::Error::Io(ref e)) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
114-
break
115-
}
116-
Err(e) => {
117-
return Err(StorageError::ReadFailed(format!("Failed to decode peer: {e}")))
104+
let mut peers = Vec::new();
105+
106+
loop {
107+
match AddrV2Message::consensus_decode(&mut reader) {
108+
Ok(peer) => peers.push(peer),
109+
Err(encode::Error::Io(ref e))
110+
if e.kind() == std::io::ErrorKind::UnexpectedEof =>
111+
{
112+
break
113+
}
114+
Err(e) => {
115+
return Err(StorageError::ReadFailed(format!("Failed to decode peer: {e}")))
116+
}
118117
}
119118
}
120-
121119
Ok(peers)
122120
})
123121
.await

0 commit comments

Comments
 (0)