fix(gossip): chunk the digest + fail-soft obfuscate — no panic at large mesh scale (#44)#98
Open
vxfemboy wants to merge 1 commit into
Open
fix(gossip): chunk the digest + fail-soft obfuscate — no panic at large mesh scale (#44)#98vxfemboy wants to merge 1 commit into
vxfemboy wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #44.
The bug
Membership::tick_digestbuilt oneGossipMsg::Digestfrom the entire directory with no per-datagram cap. AtNodeId(16)+seq(8)=24bytes/entry, a directory of ≥~2731 members produced an encoded body >65535 bytes; when that gossip datagram was obfuscated (obf_pskset),yip_obf::obfuscate'su16::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)
Chunk the digest —
tick_digestnow returnsVec<GossipMsg>, splitting the directory into chunks of at mostMAX_GOSSIP_DIGEST_ENTRIES = 40entries each (40 × 24 B = 960 B + framing/obf/IP-UDP overhead stays underOBF_MTU_BUDGET = 1200, and 40 ≪ 2731 so the u16 length can never overflow again). This mirrors the existingRecordsreply 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.obfuscateis now fail-soft — returnsOption<Vec<u8>>(Nonewhen the body can't fit the u16 length field) instead of panicking. A wire-facing daemon function should never crash the process; every caller handlesNone(the egress obf-wrap drops an unshippable datagram viaretain_mutrather 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 returnsNone, a normal body returnsSome(RED before the fix).tick_digest_chunks_large_directory: a directory > the cap yields multipleDigests, 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 warningsclean; tests green: yip-obf 10, yipd 239, yip-rendezvous 21.The
obfuscatesignature change rippled tobin/yip-rendezvous's own RDV-envelope callers (small fixed bodies), updated to match.