iroh-gossip-rendezvous
Zero-configuration peer rendezvous for iroh-gossip swarms. Two nodes that share a passphrase and an application label find each other over the public Mainline DHT and join the same gossip topic — no bootstrap server, no prior knowledge of peer addresses.
use iroh_gossip_rendezvous::Rendezvous;
# async fn run() -> anyhow::Result<()> {
let rendezvous = Rendezvous::join("my-shared-passphrase", "my-app/v1").await?;
// Send to the swarm.
rendezvous.broadcast(bytes::Bytes::from_static(b"hello")).await?;
// Receive swarm events.
let mut events = rendezvous.subscribe();
while let Ok(event) = events.recv().await {
println!("{event:?}");
}
# Ok(()) }
How it works
The crate implements a clock-free variant of HyParView-style partition
healing on top of BEP 44 mutable items. Every (passphrase, app_salt) pair
deterministically derives:
- A gossip
TopicId(via HKDF-SHA256). Kindependent DHT slot keys (defaultK=3), each with its own Ed25519 signing key and a per-slot AEAD wrapper key.
Nodes publish their endpoint ID to one of the K slots and read from a
changing subset of slots to discover peers. Records age out naturally, so
crashed or silently-departed nodes don't clutter the DHT indefinitely. A
two-layer AEAD envelope (per-record one-time key wrapped under a
seq-ratcheted per-epoch key) ensures content confidentiality against DHT
observers.
See PROTOCOL.md for the full algorithm specification. See ARCHITECTURE.md for a module map.
Correctness
The crate ships with a test suite that goes beyond unit tests:
- Property tests (proptest) for wire format, merge invariants, and AEAD roundtrips.
- Integration tests driving multi-node scenarios over an in-memory DHT: cold start, partition healing, asymmetric minority visibility.
- Mutation testing (cargo-mutants) on the algorithmic core.
- Fuzz harnesses (cargo-fuzz) for
decode_entries,crypto::open, merge, and wire-format roundtrip. - Bounded model checking (Kani) of absence of undefined behavior
on pure algorithmic entry points:
crypto::epoch_ofnever panics / overflows for any(i64 seq, u64 epoch_size ≥ 1);wire::decode_entriesnever panics on arbitrary byte input. Structural invariants (merge size bound, age bound, roundtrip) are covered by the stronger proptest + Stateright combination — Kani's niche here is UB-absence at the slice/iterator boundary. - Distributed-system model checking (Stateright): bounded safety +
liveness witness for
N ≤ 6, K ≤ 3under weak fairness; randomized exploration of 10⁷ states forN = 20. - Miri UB checks on the synchronous modules (keys, wire, crypto, merge).
The precise claim: the record-size and age invariants always hold across all explored reachable states up to N=6, K=3; under a weak-fairness assumption on action scheduling, any bipartite-partitioned initial state eventually reaches a state where both components overlap. For larger N, randomized exploration has found no counterexample. This is not a proof for unbounded deployments — it is the strongest tractable evidence available short of a hand proof.
Security
See SECURITY.md for the threat model and known limitations. Short version: the design protects against DHT observers and passive eavesdroppers, but not against a compromise of the passphrase (no forward secrecy) or a malicious member (no post-compromise security). For threat models requiring those properties, layer MLS / RFC 9420 on top.
Features
| Feature | Default | Purpose |
|---|---|---|
sim |
off | Discrete-event simulator (examples/simulator.rs) + test-support exports |
kani |
off | Build Kani proof harnesses (#[kani::proof] functions) |
miri-compat |
off | Skip Miri-incompatible tests (#[cfg_attr(miri, ignore)]) |
mainline-live |
off | Tests against the real public Mainline DHT (flaky, nightly-only) |
test-support |
off | Exposes Builder::dht_backend for injecting an in-memory DHT in integration tests |
MSRV
Minimum Supported Rust Version: 1.93.0. Enforced in CI. Bumps are minor releases; we don't raise MSRV without releasing a new minor version.
Pinned iroh / iroh-gossip major versions: 0.98.x. Bumping the iroh major
will be a minor version of this crate.
Contributing
See CONTRIBUTING.md. Local testing via just:
just check # fmt + clippy + nextest + doctests (fast CI lane)
just all # everything including miri, kani, stateright
See the CHANGELOG for release history.
License
MIT. See LICENSE.