Skip to content

fix(gossip): chunk the digest + fail-soft obfuscate — no panic at large mesh scale (#44)#98

Open
vxfemboy wants to merge 1 commit into
mainfrom
fix/gossip-digest-chunk-44
Open

fix(gossip): chunk the digest + fail-soft obfuscate — no panic at large mesh scale (#44)#98
vxfemboy wants to merge 1 commit into
mainfrom
fix/gossip-digest-chunk-44

Conversation

@vxfemboy

Copy link
Copy Markdown
Member

Closes #44.

The bug

Membership::tick_digest built one GossipMsg::Digest from the entire directory with no per-datagram cap. At NodeId(16)+seq(8)=24 bytes/entry, a directory of ≥~2731 members produced an encoded body >65535 bytes; when that gossip datagram was obfuscated (obf_psk set), yip_obf::obfuscate's u16::try_from(body.len()).expect("body fits u16") panicked the daemon. (A full-directory digest also exceeds MTU well before that, so gossip couldn't converge past ~50 members anyway.)

The fix (both options the issue lists)

  1. Chunk the digesttick_digest now returns Vec<GossipMsg>, splitting the directory into chunks of at most MAX_GOSSIP_DIGEST_ENTRIES = 40 entries each (40 × 24 B = 960 B + framing/obf/IP-UDP overhead stays under OBF_MTU_BUDGET = 1200, and 40 ≪ 2731 so the u16 length can never overflow again). This mirrors the existing Records reply cap (MAX_GOSSIP_RECORDS_PER_REPLY). The sole caller loops, sending one datagram per chunk to every gossip target exactly as before. This fixes both the panic and convergence at scale. No wire-format change — a receiver can't distinguish a chunked series from N separate digests.

  2. obfuscate is now fail-soft — returns Option<Vec<u8>> (None when the body can't fit the u16 length field) instead of panicking. A wire-facing daemon function should never crash the process; every caller handles None (the egress obf-wrap drops an unshippable datagram via retain_mut rather than sending it empty). Defense-in-depth: after the chunking fix no gossip body approaches the limit, but the panic path is now closed for any caller.

Testing

  • obfuscate_is_fail_soft_on_oversized_body: a 65536-byte body returns None, a normal body returns Some (RED before the fix).
  • tick_digest_chunks_large_directory: a directory > the cap yields multiple Digests, each ≤ MAX_GOSSIP_DIGEST_ENTRIES, whose union is every node_id exactly once; the single-chunk / empty-directory / debounce cases are also covered.
  • cargo clippy --workspace -D warnings clean; tests green: yip-obf 10, yipd 239, yip-rendezvous 21.

The obfuscate signature change rippled to bin/yip-rendezvous's own RDV-envelope callers (small fixed bodies), updated to match.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gossip Digest can panic yip-obf obfuscate (u16) at large mesh scale

1 participant