libp2p / libp2p/rust-libp2p

Persistent peer identity during restart make it unable to publish message with gossipsub

Open
#5,097 15 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Rust
Stars
5.6k
Forks
1.3k
Avg merge
8h 47m
Merged PRs (30d)
19

Description

Summary

When using QUIC transport exclusively with a persistent identity, the restart of the client of one node would make that node unable to publish message and getting an InsufficientPeers error. However, both swarm and gossipsub would report that there is a connected peer.

For example:

Both PeerA and PeerB has a static identity(and peer id derived from that identity) and connected to each other using QUIC transport exclusively, and gossipsub is able to send messages to each other.

Now PeerA restarts, connect to PeerB with the same identity, PeerA will be unable to publish any message and will always get InsufficientPeers, but the swarm.connected_peers() and gossipsub.all_peers() are returning PeerB as connected peer. PeerB can publish message to PeerA.

To reproduce this, we can simply modify the chat example:

First we add ed25519_dalek as a direct dependency, then add the following to the chat example:

// in header
use ed25519_dalek::{pkcs8::DecodePrivateKey, SigningKey};
...
// in main function:
let pem = std::fs::read_to_string("private_key.pem")?;
let mut verifying_key_bytes = SigningKey::from_pkcs8_pem(&*pem).unwrap().to_bytes();
let keypair = libp2p::identity::Keypair::ed25519_from_bytes(&mut verifying_key_bytes)?;
...
// use keypair as exisiting identity:
let mut swarm = libp2p::SwarmBuilder::with_existing_identity(keypair)
...
// comment out the tcp listening so we use quic exclusively:
//swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;

Then change the private_key.pem for PeerA and PeerB, we can use openssl to generate the pem:

openssl genpkey -algorithm Ed25519 -out private_key.pem

Make sure PeerA and PeerB is using different private key, and restart one of the client, you will see Publish error: InsufficientPeers on the restarted node.

Expected behavior

The peer should be able to publish message even after restart

Actual behavior

The peer restarted will report InsufficientPeers, the peer not restarted is able to publish message to the peer restarted.

Relevant log output
Enter messages via STDIN and they will be sent to connected peers using Gossipsub
Local node is listening on /ip4/127.0.0.1/udp/62392/quic-v1
Local node is listening on /ip4/192.168.125.145/udp/62392/quic-v1
mDNS discovered a new peer: 12D3KooWC1tB5J6W7NWwzXVFHZBggNLU1T5etuTtmpnf9WBQaJCm
mDNS discovered a new peer: 12D3KooWC1tB5J6W7NWwzXVFHZBggNLU1T5etuTtmpnf9WBQaJCm
test
Publish error: InsufficientPeers
Possible Solution

Current workarounds including:

  • Use TCP based transports as fallback.
  • Don't reboot too fast. Shut down the node and wait for ~10 seconds until the remote node closed the connection, which can be detected with an swarm::ConnectionError::IO event, then start the node. Starting the node after remote closed the connection will not trigger InsufficientPeers
Version

I tried "0.53.2" as well as running the chat example directly on master with 3e57cf494792031459d7f831408af24dbedc1a0b.

Would you like to work on fixing this bug ?

Yes

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the chat example and its SwarmBuilder::with_existing_identity setup, then reproduce the QUIC-only restart scenario using the provided Ed25519 key steps. Compare the swarm and gossipsub peer state around restart and the InsufficientPeers publish error. Done means the restarted peer can publish messages to its connected peer without that error.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.