Passphrase-based peer rendezvous for iroh-gossip swarms over the public Mainline DHT. Two nodes that share a passphrase + application salt find each other and join the same gossip topic — no bootstrap server, no prior knowledge of peer addresses. The algorithm is a clock-free variant of HyParView-style partition healing on BEP 44 mutable items, with K-sharded slots, logical aging with random-tie eviction, vouching of up to V neighbors at age 1, and a two-layer AEAD record envelope. Full spec in PROTOCOL.md. Ships with: * 119 tests (unit / property / integration / doctest) all green * 100% mutation-testing catch rate (cargo-mutants) * cargo-fuzz harnesses for the parse surface * Kani proofs of no-UB / no-panic on crypto::epoch_of and wire::decode_entries across their full symbolic input spaces * Stateright distributed-system model: safety invariants S1 + S2 proved exhaustively for N ≤ 6, K ≤ 3; liveness witness under weak fairness * Miri green on the synchronous modules * cargo-deny + cargo-audit clean * criterion benches * Full-matrix CI (Linux + macOS + Windows × stable + MSRV 1.93.0) * Dedicated nightly lane for Miri / mutation / fuzz / Kani / Stateright Pinned iroh 0.98.x. License MIT. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
29 lines
908 B
Rust
29 lines
908 B
Rust
//! Fuzz the wire-roundtrip path with structure-aware input. The `merge()`
|
|
//! function itself is crate-internal; we exercise it indirectly by
|
|
//! constructing random entry lists and checking encode→decode is
|
|
//! idempotent. Direct coverage of `merge` comes from the property tests
|
|
//! in `src/merge.rs`.
|
|
|
|
#![no_main]
|
|
|
|
use arbitrary::Arbitrary;
|
|
use iroh_gossip_rendezvous::sim::{decode_entries, encode_entries, Entry, MAX_ENTRIES};
|
|
use libfuzzer_sys::fuzz_target;
|
|
|
|
#[derive(Arbitrary, Debug)]
|
|
struct FuzzInput {
|
|
entries: Vec<([u8; 32], u8)>,
|
|
}
|
|
|
|
fuzz_target!(|input: FuzzInput| {
|
|
let entries: Vec<Entry> = input
|
|
.entries
|
|
.into_iter()
|
|
.take(MAX_ENTRIES)
|
|
.map(|(id, age)| Entry { id, age })
|
|
.collect();
|
|
let encoded = encode_entries(&entries);
|
|
let decoded = decode_entries(&encoded).expect("roundtrip");
|
|
assert_eq!(decoded.len(), entries.len());
|
|
});
|