11//! Peer network manager for SPV client
22
3- use std:: collections:: HashSet ;
3+ use std:: collections:: { HashMap , HashSet } ;
44use std:: net:: SocketAddr ;
55use std:: path:: PathBuf ;
66use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
@@ -17,9 +17,7 @@ use crate::network::addrv2::AddrV2Handler;
1717use crate :: network:: constants:: * ;
1818use crate :: network:: discovery:: DnsDiscovery ;
1919use crate :: network:: pool:: PeerPool ;
20- use crate :: network:: reputation:: {
21- misbehavior_scores, positive_scores, PeerReputationManager , ReputationAware ,
22- } ;
20+ use crate :: network:: reputation:: { ChangeReason , PeerReputationManager } ;
2321use 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 }
@@ -972,16 +968,37 @@ impl PeerNetworkManager {
972968 }
973969
974970 /// Disconnect a specific peer
975- pub async fn disconnect_peer ( & self , addr : & SocketAddr ) -> Result < ( ) , Error > {
971+ pub async fn disconnect_peer ( & self , addr : & SocketAddr , reason : & str ) -> Result < ( ) , Error > {
972+ log:: info!( "Disconnecting peer {} - reason: {}" , addr, reason) ;
973+
974+ // Remove the peer
976975 self . pool . remove_peer ( addr) . await ;
977976
978977 Ok ( ( ) )
979978 }
980979
981980 /// Get reputation information for all peers
982981 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 ( )
982+ let mut lock = self . reputation_manager . lock ( ) . await ;
983+ let reputations = lock. get_all_reputations ( ) . await ;
984+ reputations. iter ( ) . map ( |( addr, rep) | ( * addr, ( rep. score ( ) , rep. is_banned ( ) ) ) ) . collect ( )
985+ }
986+
987+ /// Ban a specific peer manually
988+ pub async fn ban_peer ( & self , addr : & SocketAddr , reason : & str ) -> Result < ( ) , Error > {
989+ log:: info!( "Manually banning peer {} - reason: {}" , addr, reason) ;
990+
991+ // Disconnect the peer first
992+ self . disconnect_peer ( addr, reason) . await ?;
993+
994+ // Update reputation to trigger ban
995+ self . reputation_manager
996+ . lock ( )
997+ . await
998+ . update_reputation ( * addr, ChangeReason :: ManuallyBanned )
999+ . await ;
1000+
1001+ Ok ( ( ) )
9851002 }
9861003
9871004 /// Unban a specific peer
@@ -1003,7 +1020,9 @@ impl PeerNetworkManager {
10031020 }
10041021
10051022 // Save reputation data before shutdown
1006- if let Err ( e) = self . reputation_manager . save_to_storage ( & * self . peer_store ) . await {
1023+ if let Err ( e) =
1024+ self . reputation_manager . lock ( ) . await . save_to_storage ( & * self . peer_store ) . await
1025+ {
10071026 log:: warn!( "Failed to save reputation data on shutdown: {}" , e) ;
10081027 }
10091028
@@ -1098,64 +1117,62 @@ impl NetworkManager for PeerNetworkManager {
10981117 } // end match
10991118 } // end send_message
11001119
1101- async fn penalize_peer ( & self , address : SocketAddr , score_change : i32 , reason : & str ) {
1102- self . reputation_manager . update_reputation ( address, score_change , reason) . await ;
1120+ async fn penalize_peer ( & self , address : SocketAddr , reason : ChangeReason ) {
1121+ self . reputation_manager . lock ( ) . await . update_reputation ( address, reason) . await ;
11031122 }
11041123
1105- async fn penalize_peer_invalid_chainlock ( & self , address : SocketAddr , reason : & str ) {
1106- match self . disconnect_peer ( & address, reason ) . await {
1124+ async fn penalize_peer_invalid_chainlock ( & self , address : SocketAddr ) {
1125+ match self . disconnect_peer ( & address, & ChangeReason :: InvalidChainLock . to_string ( ) ) . await {
11071126 Ok ( ( ) ) => {
1108- log:: warn!(
1109- "Peer {} disconnected for invalid ChainLock enforcement: {}" ,
1110- address,
1111- reason
1112- ) ;
1127+ log:: warn!( "Peer {} disconnected for invalid ChainLock enforcement" , address, ) ;
11131128 }
11141129 Err ( err) => {
11151130 log:: error!(
1116- "Failed to disconnect peer {} after invalid ChainLock enforcement ({}) : {}" ,
1131+ "Failed to disconnect peer {} after invalid ChainLock enforcement: {}" ,
11171132 address,
1118- reason,
11191133 err
11201134 ) ;
11211135 }
11221136 }
11231137
11241138 // Apply misbehavior score and a short temporary ban
11251139 self . reputation_manager
1126- . update_reputation ( address, misbehavior_scores:: INVALID_CHAINLOCK , reason)
1140+ . lock ( )
1141+ . await
1142+ . update_reputation ( address, ChangeReason :: InvalidChainLock )
11271143 . await ;
11281144
11291145 // Short ban: 10 minutes for relaying invalid ChainLock
11301146 self . reputation_manager
1131- . temporary_ban_peer ( address, Duration :: from_secs ( 10 * 60 ) , reason)
1147+ . lock ( )
1148+ . await
1149+ . temporary_ban_peer ( address, Duration :: from_secs ( 10 * 60 ) )
11321150 . await ;
11331151 }
11341152
1135- async fn penalize_peer_invalid_instantlock ( & self , address : SocketAddr , reason : & str ) {
1153+ async fn penalize_peer_invalid_instantlock ( & self , address : SocketAddr ) {
11361154 // Apply misbehavior score and a short temporary ban
11371155 self . reputation_manager
1138- . update_reputation ( address, misbehavior_scores:: INVALID_INSTANTLOCK , reason)
1156+ . lock ( )
1157+ . await
1158+ . update_reputation ( address, ChangeReason :: InvalidInstantLock )
11391159 . await ;
11401160
11411161 // Short ban: 10 minutes for relaying invalid InstantLock
11421162 self . reputation_manager
1143- . temporary_ban_peer ( address, Duration :: from_secs ( 10 * 60 ) , reason)
1163+ . lock ( )
1164+ . await
1165+ . temporary_ban_peer ( address, Duration :: from_secs ( 10 * 60 ) )
11441166 . await ;
11451167
1146- match self . disconnect_peer ( & address, reason ) . await {
1168+ match self . disconnect_peer ( & address, & ChangeReason :: InvalidInstantLock . to_string ( ) ) . await {
11471169 Ok ( ( ) ) => {
1148- log:: warn!(
1149- "Peer {} disconnected for invalid InstantLock enforcement: {}" ,
1150- address,
1151- reason
1152- ) ;
1170+ log:: warn!( "Peer {} disconnected for invalid InstantLock enforcement" , address, ) ;
11531171 }
11541172 Err ( err) => {
11551173 log:: error!(
1156- "Failed to disconnect peer {} after invalid InstantLock enforcement ({}) : {}" ,
1174+ "Failed to disconnect peer {} after invalid InstantLock enforcement: {}" ,
11571175 address,
1158- reason,
11591176 err
11601177 ) ;
11611178 }
0 commit comments