Skip to content

Commit 9eec9ec

Browse files
committed
try to fix undersized/empty broadcast bug
1 parent fcafa33 commit 9eec9ec

2 files changed

Lines changed: 49 additions & 16 deletions

File tree

overlay/src/libp2p_overlay.rs

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ pub enum OverlayCommand {
172172
RequestScpState { ledger_seq: u32 },
173173
/// Send SCP envelope to a specific peer
174174
SendScpToPeer { peer_id: PeerId, envelope: Vec<u8> },
175+
/// Update the number of known peers used to size eager flooding trees.
176+
SetKnownPeerCount(usize),
175177
/// Shutdown
176178
Shutdown,
177179
/// Query the number of connected peers (responds via oneshot)
@@ -333,6 +335,19 @@ impl OverlayHandle {
333335
Ok(())
334336
}
335337

338+
pub async fn set_known_peer_count(&self, count: usize) {
339+
if let Err(e) = self
340+
.cmd_tx
341+
.send(OverlayCommand::SetKnownPeerCount(count))
342+
.await
343+
{
344+
warn!(
345+
"Overlay command channel closed, failed to send SetKnownPeerCount: {}",
346+
e
347+
);
348+
}
349+
}
350+
336351
pub async fn shutdown(&self) {
337352
if let Err(e) = self.cmd_tx.send(OverlayCommand::Shutdown).await {
338353
warn!(
@@ -391,8 +406,11 @@ struct SharedState {
391406
pending_getdata: RwLock<PendingRequests>,
392407
/// TX buffer for responding to GETDATA requests
393408
tx_buffer: RwLock<TxBuffer>,
394-
/// Current eager flooding TTL depth derived from the connected peer count.
409+
/// Current eager flooding TTL depth derived from known and connected peer counts.
395410
overlay_eager_depth: AtomicU64,
411+
/// Number of peers known by configuration/peer discovery, whether currently
412+
/// connected or not. Used to size eager flooding trees.
413+
overlay_known_peer_count: AtomicU64,
396414
/// Overlay metrics (shared with App for IPC reporting)
397415
metrics: Arc<OverlayMetrics>,
398416
}
@@ -426,6 +444,7 @@ impl SharedState {
426444
pending_getdata: RwLock::new(PendingRequests::new()),
427445
tx_buffer: RwLock::new(TxBuffer::new()),
428446
overlay_eager_depth: AtomicU64::new(0),
447+
overlay_known_peer_count: AtomicU64::new(0),
429448
metrics,
430449
}
431450
}
@@ -642,6 +661,9 @@ impl StellarOverlay {
642661
warn!("Failed to send SCP to {}: {:?}", peer_id, e);
643662
}
644663
}
664+
OverlayCommand::SetKnownPeerCount(count) => {
665+
update_known_peer_count(&self.state, count);
666+
}
645667
OverlayCommand::Shutdown => {
646668
info!("Overlay shutting down");
647669
break;
@@ -826,21 +848,6 @@ impl StellarOverlay {
826848
}
827849
};
828850

829-
// Dedup check. Received SCP messages are relayed directly by the overlay
830-
// according to their TTL, so a later rebroadcast request from Core should
831-
// not restart flooding from this node.
832-
{
833-
let mut seen = self.state.scp_seen.write().await;
834-
if seen.contains(&hash) {
835-
trace!(
836-
"SCP_BROADCAST_SKIP: SCP {:02x?}... already seen",
837-
&hash[..4]
838-
);
839-
return;
840-
}
841-
seen.put(hash, ());
842-
}
843-
844851
let streams = self.state.peer_streams.read().await;
845852
let peers: Vec<_> = streams.keys().cloned().collect();
846853
drop(streams);
@@ -856,6 +863,14 @@ impl StellarOverlay {
856863
let initial_fanout = overlay_eager_fanout().saturating_mul(overlay_eager_redundancy());
857864
let peers_to_send = select_eager_peers(peers, None, initial_fanout);
858865

866+
if peers_to_send.is_empty() {
867+
trace!(
868+
"SCP_BROADCAST_SKIP: SCP {:02x?}... has no eligible peers",
869+
&hash[..4]
870+
);
871+
return;
872+
}
873+
859874
info!(
860875
"SCP_BROADCAST: Broadcasting SCP {:02x?}... ({} bytes, ttl={}) to {} peers",
861876
&hash[..4],
@@ -2028,11 +2043,25 @@ async fn relay_tx_inv(state: &Arc<SharedState>, peer_id: &PeerId, hash: [u8; 32]
20282043
}
20292044

20302045
fn update_eager_depth(state: &SharedState, peer_count: usize) {
2046+
let peer_count =
2047+
peer_count.max(state.overlay_known_peer_count.load(Ordering::Relaxed) as usize);
20312048
state
20322049
.overlay_eager_depth
20332050
.store(calculate_eager_depth(peer_count), Ordering::Relaxed);
20342051
}
20352052

2053+
fn update_known_peer_count(state: &SharedState, peer_count: usize) {
2054+
state
2055+
.overlay_known_peer_count
2056+
.store(peer_count as u64, Ordering::Relaxed);
2057+
let connected_peer_count = state
2058+
.peer_streams
2059+
.try_read()
2060+
.map(|streams| streams.len())
2061+
.unwrap_or(0);
2062+
update_eager_depth(state, connected_peer_count);
2063+
}
2064+
20362065
fn calculate_eager_depth(peer_count: usize) -> u64 {
20372066
calculate_eager_depth_for_fanout(peer_count, overlay_eager_fanout())
20382067
}

overlay/src/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,10 @@ impl App {
13131313
cp.resolved.clear();
13141314
}
13151315

1316+
self.libp2p_handle
1317+
.set_known_peer_count(all_peers.len().saturating_sub(1))
1318+
.await;
1319+
13161320
// Prune known_peers and peer_hostnames for peers whose
13171321
// hostnames are no longer in the config. Prevents stale
13181322
// entries from re-dialing removed peers.

0 commit comments

Comments
 (0)