From be37f46f59f127bd3dd9c4278cb160ad348b29c3 Mon Sep 17 00:00:00 2001 From: ardocrat Date: Thu, 14 May 2026 11:26:22 +0300 Subject: [PATCH 1/5] fix: add segment to request if not exists --- chain/src/txhashset/desegmenter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain/src/txhashset/desegmenter.rs b/chain/src/txhashset/desegmenter.rs index d8c41fe2..b20c486e 100644 --- a/chain/src/txhashset/desegmenter.rs +++ b/chain/src/txhashset/desegmenter.rs @@ -585,7 +585,7 @@ impl Desegmenter { // Explicitly add segment identifier to request if not exists. let mut maybe_add_to_request = |seg_id: SegmentTypeIdentifier| { - if return_vec.iter().any(|i| i == &seg_id) { + if !return_vec.iter().any(|i| i == &seg_id) { if return_vec.len() >= max_elements { return_vec.pop(); } From 0321bf5b1451b849a6adedb414e5d0bb339877c4 Mon Sep 17 00:00:00 2001 From: ardocrat Date: Thu, 14 May 2026 11:54:54 +0300 Subject: [PATCH 2/5] fix: peers iterator to unblock blocked --- p2p/src/peers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/p2p/src/peers.rs b/p2p/src/peers.rs index fdf10ace..cdfe134b 100644 --- a/p2p/src/peers.rs +++ b/p2p/src/peers.rs @@ -475,7 +475,7 @@ impl Peers { let peers = peers.iter().into_iter(); let _ = peers .filter(|(_, peer)| peer.is_blocked()) - .map(|(_, peer)| peer.unblock()); + .for_each(|(_, peer)| peer.unblock()); Ok(()) } From 048453f989802e97ddbdc41bc54d13024caf8ad8 Mon Sep 17 00:00:00 2001 From: ardocrat Date: Thu, 14 May 2026 22:32:01 +0300 Subject: [PATCH 3/5] peers: keep blocked list into memory till restart or pibd finish --- p2p/src/peer.rs | 41 --------------------------- p2p/src/peers.rs | 72 ++++++++++++++++++++++++++++++------------------ 2 files changed, 45 insertions(+), 68 deletions(-) diff --git a/p2p/src/peer.rs b/p2p/src/peer.rs index e61e2115..69f073cc 100644 --- a/p2p/src/peer.rs +++ b/p2p/src/peer.rs @@ -13,7 +13,6 @@ // limitations under the License. use crate::util::{Mutex, RwLock}; -use chrono::Duration; use lru_cache::LruCache; use std::fmt; use std::fs::File; @@ -52,7 +51,6 @@ const MAX_PEER_MSG_PER_MIN: u64 = 500; enum State { Connected, Banned, - Blocked(DateTime, u32), } pub struct Peer { @@ -194,45 +192,6 @@ impl Peer { State::Banned == *self.state.read() } - /// Whether this peer has been blocked. - pub fn is_blocked(&self) -> bool { - match *self.state.read() { - State::Blocked(expiry, _) => expiry > Utc::now(), - _ => false, - } - } - - /// Set this peer status to blocked. - pub fn set_blocked(&self) { - if self.is_blocked() { - return; - } - let times = { - match *self.state.read() { - State::Blocked(_, times) => times + 1, - _ => 1, - } - }; - let duration = match times { - 1 => 60, // 1m - 2 => 180, // 3m - _ => 600, // 10m - }; - let expiry = Utc::now() + Duration::seconds(duration); - *self.state.write() = State::Blocked(expiry, times); - debug!( - "state_sync: block peer {} for {} times: {}", - self.info.addr, duration, times - ); - } - - /// Unblock blocked peer. - pub fn unblock(&self) { - if self.is_blocked() { - *self.state.write() = State::Connected; - } - } - /// Whether this peer is stuck on sync. pub fn is_stuck(&self) -> (bool, Difficulty) { let peer_live_info = self.info.live_info.read(); diff --git a/p2p/src/peers.rs b/p2p/src/peers.rs index cdfe134b..77431a5e 100644 --- a/p2p/src/peers.rs +++ b/p2p/src/peers.rs @@ -45,6 +45,7 @@ pub struct Peers { pub adapter: Arc, store: PeerStore, peers: RwLock>>, + blocked: RwLock, u32)>>, config: P2PConfig, } @@ -55,6 +56,7 @@ impl Peers { store, config, peers: RwLock::new(HashMap::new()), + blocked: RwLock::new(HashMap::new()), } } @@ -450,32 +452,55 @@ impl Peers { } } - /// Temporary block a peer without banning it. - pub fn block_peer(&self, peer_addr: PeerAddr, reason: &str) -> Result<(), Error> { - let peers = self.peers.try_read_for(LOCK_TIMEOUT).ok_or_else(|| { - error!("block_peer: failed to get peers lock"); - Error::PeerException - })?; - match peers.get(&peer_addr) { - None => Err(Error::PeerNotFound), - Some(peer) => { - warn!("blocking peer {} ({})", peer_addr, reason); - peer.set_blocked(); - Ok(()) + /// Whether this peer has been blocked. + pub fn is_blocked(&self, peer_addr: PeerAddr) -> bool { + match self.blocked.try_read_for(LOCK_TIMEOUT) { + Some(peers) => match peers.get(&peer_addr) { + None => false, + Some((expiry, _)) => expiry > &Utc::now(), + }, + None => { + error!("is_blocked: failed to get peers lock"); + false } } } - /// Unblock blocked peers. - pub fn unblock_peers(&self) -> Result<(), Error> { - let peers = self.peers.try_read_for(LOCK_TIMEOUT).ok_or_else(|| { - error!("unblock_peers: failed to get peers lock"); + /// Temporary block a peer without banning it. + pub fn block_peer(&self, peer_addr: PeerAddr, reason: &str) -> Result<(), Error> { + let mut blocked = self.blocked.try_write_for(LOCK_TIMEOUT).ok_or_else(|| { + error!("block_peer: failed to get blocked lock"); Error::PeerException })?; - let peers = peers.iter().into_iter(); - let _ = peers - .filter(|(_, peer)| peer.is_blocked()) - .for_each(|(_, peer)| peer.unblock()); + + let times = { + match blocked.get(&peer_addr) { + Some((_, times)) => times + 1, + None => 1, + } + }; + let duration = match times { + 1 => 60, // 1m + 2 => 180, // 3m + _ => 600, // 10m + }; + let expiry = Utc::now() + Duration::seconds(duration); + blocked.insert(peer_addr, (expiry, times)); + + warn!( + "state_sync: block peer {} ({}) for {} times: {}", + peer_addr, reason, duration, times + ); + Ok(()) + } + + /// Unblock all blocked peers. + pub fn unblock_peers(&self) -> Result<(), Error> { + let mut blocked = self.blocked.try_write_for(LOCK_TIMEOUT).ok_or_else(|| { + error!("unblock_peers: failed to get blocked lock"); + Error::PeerException + })?; + blocked.clear(); Ok(()) } @@ -839,13 +864,6 @@ impl>> PeersIter { } } - /// Filter non-blocked peers. - pub fn non_blocked(self) -> PeersIter>> { - PeersIter { - iter: self.iter.filter(|p| !p.is_blocked()), - } - } - /// Filter peers with the provided difficulty comparison fn. /// /// with_difficulty(|x| x > diff) From c4f054ab514e198d27b6fb6df272a14de2413b61 Mon Sep 17 00:00:00 2001 From: ardocrat Date: Thu, 14 May 2026 22:34:22 +0300 Subject: [PATCH 4/5] sync: blocked filter --- servers/src/grin/sync/state_sync.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/servers/src/grin/sync/state_sync.rs b/servers/src/grin/sync/state_sync.rs index 07faaf8b..19fc07fe 100644 --- a/servers/src/grin/sync/state_sync.rs +++ b/servers/src/grin/sync/state_sync.rs @@ -413,13 +413,13 @@ impl StateSync { .and_then(|(_, addr)| *addr); let peer = available_pibd_peers() .outbound() - .non_blocked() + .with_filter(|p| !peers.is_blocked(p.info.addr)) .exclude(excluded_peer) .choose_random() .or_else(|| { available_pibd_peers() .inbound() - .non_blocked() + .with_filter(|p| !peers.is_blocked(p.info.addr)) .exclude(excluded_peer) .choose_random() .or_else(|| { From a81f59926c8558ba90e7cc00322deb3ffe6b7bce Mon Sep 17 00:00:00 2001 From: ardocrat Date: Fri, 15 May 2026 15:14:47 +0300 Subject: [PATCH 5/5] lmdb: do not include blocked peers in selection of peer, count also blocked peers to use fallback .zip download --- servers/src/grin/sync/state_sync.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/servers/src/grin/sync/state_sync.rs b/servers/src/grin/sync/state_sync.rs index 19fc07fe..5b11da5e 100644 --- a/servers/src/grin/sync/state_sync.rs +++ b/servers/src/grin/sync/state_sync.rs @@ -377,7 +377,10 @@ impl StateSync { // abort PIBD and fall back to txhashset download // Waiting a minute helps ensures that the cancellation isn't simply due to a single non-PIBD enabled // peer having the max difficulty - if available_pibd_peers().count() == 0 { + if available_pibd_peers() + .with_filter(|p| !peers.is_blocked(p.info.addr)) + .count() == 0 + { if let None = self.earliest_zero_pibd_peer_time { self.set_earliest_zero_pibd_peer_time(Some(Utc::now())); } @@ -422,12 +425,6 @@ impl StateSync { .with_filter(|p| !peers.is_blocked(p.info.addr)) .exclude(excluded_peer) .choose_random() - .or_else(|| { - // Select from blocked if we have no peers (could be network issue). - available_pibd_peers() - .exclude(excluded_peer) - .choose_random() - }) }); trace!("Chosen peer is {:?}", peer);