Skip to content

Commit 375ce2e

Browse files
committed
fix(gossipsub): resolve empty mesh issue by removing add_explicit_peer calls
- Remove all add_explicit_peer calls that were converting peers to 'direct peers' which bypass the gossipsub mesh entirely (caused 'GRAFT: ignoring request from direct peer' errors) - Adjust gossipsub config: mesh_n_low=1, mesh_outbound_min=0 to support hub-and-spoke topology where bootnode has only inbound connections - Mesh now forms correctly via standard GRAFT/PRUNE protocol
1 parent 81524af commit 375ce2e

File tree

2 files changed

+14
-20
lines changed

2 files changed

+14
-20
lines changed

crates/network/src/behaviour.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ impl MiniChainBehaviour {
4545
let gossipsub_config = gossipsub::ConfigBuilder::default()
4646
.heartbeat_interval(Duration::from_secs(1))
4747
.validation_mode(ValidationMode::Strict)
48-
.mesh_n(8) // Target mesh size (good for networks up to 64 nodes)
49-
.mesh_n_low(2) // Minimum mesh size before adding peers
50-
.mesh_n_high(16) // Maximum mesh size before pruning
51-
.mesh_outbound_min(2) // Require outbound peers for proper bidirectional mesh
48+
.mesh_n(6) // Target mesh size
49+
.mesh_n_low(1) // Allow mesh with just 1 peer (important for small networks)
50+
.mesh_n_high(12) // Maximum mesh size before pruning
51+
.mesh_outbound_min(0) // No outbound requirement (bootnode has only inbound connections)
5252
.gossip_lazy(6) // Peers to gossip to outside mesh
5353
.gossip_factor(0.25) // Fraction of peers to gossip to
5454
.do_px() // Enable peer exchange on PRUNE for discovery

crates/network/src/node.rs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -425,11 +425,9 @@ impl NetworkNode {
425425
peer_id,
426426
topic.as_str()
427427
);
428-
// Now that the peer has subscribed, add them as explicit peer to ensure mesh membership
429-
self.swarm
430-
.behaviour_mut()
431-
.gossipsub
432-
.add_explicit_peer(&peer_id);
428+
// NOTE: Do NOT call add_explicit_peer here!
429+
// Explicit peers become "direct peers" that bypass the mesh entirely.
430+
// Let gossipsub handle mesh formation automatically via GRAFT/PRUNE.
433431
}
434432
MiniChainBehaviourEvent::Gossipsub(gossipsub::Event::Unsubscribed { peer_id, topic }) => {
435433
info!(
@@ -449,20 +447,13 @@ impl NetworkNode {
449447
MiniChainBehaviourEvent::Mdns(mdns::Event::Discovered(list)) => {
450448
for (peer_id, addr) in list {
451449
info!("mDNS discovered peer: {} at {}", peer_id, addr);
452-
self.swarm
453-
.behaviour_mut()
454-
.gossipsub
455-
.add_explicit_peer(&peer_id);
450+
// Just dial the peer - gossipsub will handle mesh formation
456451
let _ = self.swarm.dial(addr);
457452
}
458453
}
459454
MiniChainBehaviourEvent::Mdns(mdns::Event::Expired(list)) => {
460455
for (peer_id, _) in list {
461456
debug!("mDNS peer expired: {}", peer_id);
462-
self.swarm
463-
.behaviour_mut()
464-
.gossipsub
465-
.remove_explicit_peer(&peer_id);
466457
}
467458
}
468459
MiniChainBehaviourEvent::RequestResponse(request_response::Event::Message {
@@ -510,9 +501,12 @@ impl NetworkNode {
510501
})
511502
.await;
512503

513-
// Note: Mesh membership is handled in Gossipsub::Event::Subscribed
514-
// which fires when the peer subscribes to our topic via gossipsub protocol.
515-
// add_explicit_peer is called there, not here, to avoid duplicate calls.
504+
// NOTE: Do NOT call add_explicit_peer here!
505+
// Explicit peers become "direct peers" that bypass the gossipsub mesh.
506+
// The mesh should form automatically via the gossipsub protocol:
507+
// 1. Connection established -> gossipsub protocol negotiated
508+
// 2. SUBSCRIBE messages exchanged -> peers know each other's topics
509+
// 3. GRAFT/PRUNE in heartbeats -> mesh forms naturally
516510

517511
// Also connect to other peers they know about through their observed addr
518512
// This helps with peer discovery in small networks

0 commit comments

Comments
 (0)