Intermittent Gossip Data Propagation Issues in libp2p Network (Rust-libp2p 0.54)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 5.6k
- Forks
- 1.3k
- Avg merge
- 8h 47m
- Merged PRs (30d)
- 19
Description
Summary
We're experiencing intermittent issues with gossip data propagation in our libp2p network using Rust-libp2p 0.54. The problem occurs on both local development machines and test servers, where nodes sometimes fail to receive gossiped messages despite appearing to be connected.
Symptoms:
- Nodes sometimes fail to receive gossiped data
- Bootstrap connections occasionally fail with
HandshakeTimedOuterrors - Gossipsub mesh reports needing more peers even when nodes are connected
- Kademlia bootstrap queries complete but don't always result in stable connections
Configuration:
// Network setup
let mut config = libp2p::quic::Config::new(&keypair.unwrap().clone());
config.max_idle_timeout = 10*1000; // 10 seconds
config.keep_alive_interval = Duration::from_secs(5);
// Gossipsub config
let gossipsub_config = gossipsub::ConfigBuilder::default()
.heartbeat_interval(Duration::from_secs(HEARTBEAT_INTERVAL)) // 5 seconds
.validation_mode(gossipsub::ValidationMode::Strict)
.duplicate_cache_time(Duration::from_secs(DUPLICATE_CACHE_DURATION)) // 10 seconds
.max_transmit_size(1_000_000)
.message_id_fn(message_id_fn)
.max_messages_per_rpc(Some(MAX_MESSAGES_PER_RPC)) // 100
.mesh_n_low(4)
.mesh_n_high(10)
.mesh_n(8)
.build()?;
//Swarm setup
#[tracing::instrument(skip(keypair))]
pub async fn setup_swarm_network(
keypair: Option<Keypair>,
bootstrap_addresses: Option<Vec<(PeerId, Multiaddr)>>,
port: String,
) -> Result<Swarm<SwarmBehaviour>, Box<dyn Error>> {
// Set up the SwarmBuilder based on whether a keypair is provided or not.
let builder = if let Some(keypair) = keypair.clone() {
// Use the provided keypair for the swarm identity.
SwarmBuilder::with_existing_identity(keypair)
} else {
// Generate a new identity if no keypair is provided.
SwarmBuilder::with_new_identity()
};
let mut config = libp2p::quic::Config::new(&keypair.unwrap().clone());
// config.max_idle_timeout = 300;
config.max_idle_timeout = 10*1000;
//config.keep_alive_interval = Duration::from_millis(100);
config.keep_alive_interval=Duration::from_secs(5);
// Build the libp2p swarm with a specific transport (TCP and QUIC), and relay client.
let mut swarm = builder
.with_tokio() // Use Tokio for asynchronous execution.
.with_quic_config(|_| config)
.with_behaviour(|keypair| {
// If no bootstrap addresses are provided, print the peer ID for informational purposes.
if bootstrap_addresses.is_none() {
info!("Bootstrap Peer ID :{}", keypair.public().to_peer_id());
}
// Initialize the custom MyBehaviour which includes Gossipsub and Kademlia behaviors.
SwarmBehaviour::new(keypair.clone()).unwrap()
})?
.with_swarm_config(|c| {
// Configure idle connection timeout.
c.with_idle_connection_timeout(Duration::from_secs(60))
})
.build();
// If bootstrap nodes are provided, add them to the Kademlia behavior.
if let Some(ref bootstrap_addresses) = bootstrap_addresses {
for (peer_id, multi_addr) in bootstrap_addresses {
// Add each bootstrap node's address to the Kademlia DHT.
swarm
.behaviour_mut()
.kademlia
.add_address(peer_id, multi_addr.clone());
swarm.dial(multi_addr.clone())?;
// Trigger the Kademlia bootstrap process to find more peers.
}
swarm.behaviour_mut().kademlia.bootstrap()?;
}
// Subscribe to the primary Gossipsub topic for network-wide communication.
swarm
.behaviour_mut()
.gossipsub
.subscribe(&IdentTopic::new(NETWORK_TOPIC))?;
// Define the address to listen on for incoming connections (QUIC over UDP).
let listen_address = format!("/ip4/0.0.0.0/udp/{}/quic-v1", port);
swarm.listen_on(listen_address.parse()?)?;
// Return the initialized swarm.
Ok(swarm)
}
Logs:
From Node 1 (working):
[TRACE] Sending message to peer 16Uiu2HAmR6ogo4eHfXuz28HNS2XJUGcB1R9Wf4UzHh7go18LQX3v
[TRACE] Sending message to peer 16Uiu2HAmGjjk8mDH5F1Y3FVW68tenMNWMNkTcZXceLMnXUEJDoSx
[TRACE] Sending message to peer 16Uiu2HAmMwshLKvkHnMsgJ5MPxcLeVkkSxRK8Rm6cFRaCCTkhhEd
From Node 2 (failing):
[ERROR] Failed to establish outgoing connection. Connection ID: ConnectionId(8),
Peer ID: Some(PeerId("16Uiu2HAmT4FjyydhhSYgLoGjNJEFGHDexiaH6UxWM1VCW1LT5o1X")),
Error: Transport([(/ip4/127.0.0.1/udp/7070/quic-v1/p2p/16Uiu2HAmT4FjyydhhSYgLoGjNJEFGHDexiaH6UxWM1VCW1LT5o1X,
Other(Custom { kind: Other, error: Other(Right(HandshakeTimedOut)) }))]).
[DEBUG] HEARTBEAT: Mesh low. Topic contains: 0 needs: 4
[DEBUG] RANDOM PEERS: Got 0 peers
Expected behavior
- Stable connections between nodes
- Reliable gossip message propagation
- Healthy mesh network with sufficient peers
Actual behavior
- Intermittent connection failures
- Gossip messages sometimes not received
- Mesh peer count often below configured minimum
Relevant log output
Possible Solution
No response
Version
0.54
Would you like to work on fixing this bug?
Yes
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the setup_swarm_network entry point and the QUIC, Gossipsub, Kademlia, and swarm timeout settings shown in the report; then reproduce the failures using the attached logs. Trace HandshakeTimedOut events, mesh peer counts, and message delivery across nodes. Done means stable connections, a healthy mesh, and reliable gossip propagation under the reported configuration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- distributed-systems, networking
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100