discovery: account for future gossip memory - #11158
moscowchill wants to merge 2 commits into
Conversation
Future gossip entries currently have a constant cache cost even when a decoded channel announcement retains a dense feature map. Charge a maximum wire body per message plus each decoded feature-map entry, preserving the ordinary message count while bounding dense retained state. Signed-off-by: moscowchill <gasgeverij@proton.me>
Signed-off-by: moscowchill <gasgeverij@proton.me>
🟠 PR Severity: HIGH
🟠 High (1 file)
🟢 Low (2 files)
AnalysisThe core change is in To override, add a |
Lrifton92
left a comment
There was a problem hiding this comment.
Reviewed the retained-memory accounting and reproduced the bounds independently — the approach looks correct and the constants are safe. A few notes:
Bounds check out. With lnwire.MaxMsgBody = 65533 and futureFeatureEntrySize = 16, a maximally dense ChannelAnnouncement1 (65,536 feature bits) is charged 65533 + 65536*16 = 1,114,109 bytes, and the cache budget 1000 * 65533 = 65,533,000 retains floor(65,533,000 / 1,114,109) = 58 such objects. Both figures in the description are exact.
futureFeatureEntrySize = 16 is a genuine upper bound. RawFeatureVector.features is a map[FeatureBit]struct{} with a uint16 key and zero-size value, so a full bucket retains 8 tophash + 8*2 key + 0 value + 8 overflow = 32 bytes for 8 entries, i.e. ~4 bytes/entry amortized (a few more with Go's load-factor slack and overflow buckets). Charging 16 per entry comfortably over-approximates the real retained cost, which is the safe direction for a memory budget. The comment on the constant matches the runtime layout.
Coverage. Of the three isPremature call sites (handleChanAnnouncement, handleChanUpdate, handleAnnSig), only handleChanAnnouncement carries a decoded feature map — ChannelUpdate1 and AnnounceSignatures1 have no RawFeatureVector — so restricting the per-entry charge to *lnwire.ChannelAnnouncement1 covers every dense object that can currently enter the cache.
One forward-looking note (not blocking): ChannelAnnouncement2 also carries a RawFeatureVector (tlv.TlvType2). It doesn't reach this cache today since v2 gossip isn't wired into isPremature, but if/when it is, futureMsgSize's type switch would charge it only futureMsgMinSize and reopen the same under-accounting. A short comment next to the ChannelAnnouncement1 assertion flagging that assumption would make the extension point explicit for whoever adds v2 gossip.
|
Thanks for the PR, @moscowchill. Our contribution guidelines note that PRs from new contributors aren't prioritized for review at the moment. With the backlog we have, that means closing this instead of leaving it in limbo. If there is a genuine bug behind this, please open an issue instead with:
That gives us something concrete to evaluate, and if it checks out we may fix it ourselves or invite you to reopen. If you'd like to contribute going forward, reviewing open PRs and helping triage issues is the path we recommend. It's a stronger signal of understanding than a first patch, and it makes it a lot easier for us to prioritize your PRs later. |
Change Description
The future gossip cache currently charges each decoded message as one unit. A
ChannelAnnouncement1feature vector can decode into 65,536 map entries, so the existing 1,000-message limit does not bound the memory retained by the cache.This PR converts the cache to a retained-memory budget while preserving the existing upper bound of 1,000 ordinary messages. Every future message receives a conservative maximum-wire-body charge, and decoded channel-announcement feature entries receive an additional per-entry charge. A maximally dense announcement therefore consumes 1,114,109 cache bytes and the production cache retains at most 58 such objects.
Validation order, replay behavior, and monotonic cache keys remain unchanged. The change is scoped to bounding retained cache state; transient decoding work remains subject to the existing gossip processing limits.
Steps to Test
Pull Request Checklist
Testing
Code Style and Documentation