Uh oh!
There was an error while loading. Please reload this page.
fix(peer): keep a later source's novel reach-hint when an earlier source fills the cap - #130
Merged
Merged
Conversation
MichaelTaylor3dforce-pushed
the
fix/1620/union-locator-cap-order
branch
from
August 2, 2026 02:08
d1937d9 to
e742122Compare…rce fills the cap union_locator merges the address hints of the same peer_id named by multiple sources (#836/#97), then caps the combined set at MAX_ADDRS_PER_PROVIDER. But the cap ran AFTER the merge and kept the FIRST MAX, so an earlier source that had already filled the cap with unreachable hints (a stale DHT record) silently dropped a later source's novel REACHABLE hint (the live pool connection) for the same peer (#1620). The node then dialed only stale hints and missed a dialable holder. Masked in production only by wiring the reachable pool source first — any reorder reintroduced it. merge_address_hints now reserves the cap's slots for the later source's NOVEL hints first, then leads with as many of the earlier source's hints as still fit — so the earlier HEAD keeps its lead position (#836: best_address breaks ties by list order) while only the earlier SURPLUS TAIL is displaced, never a later reachable hint. When everything fits, the order is unchanged (earlier-then-later). The shared order- preserving dedup is factored into dedup_hints; sanitize_address_hints (first-seen ingest) dedups-then-caps through it. Regression test: an earlier source filling the cap + a later source's one reachable hint -> the reachable hint survives and the earlier head still leads. The existing #836 merge/order tests stay green. union_locator suite 6/6; fmt + clippy -D warnings clean. Closes #1620 Co-Authored-By: Claude <noreply@anthropic.com>
MichaelTaylor3dforce-pushed
the
fix/1620/union-locator-cap-order
branch
from
August 2, 2026 02:29
e742122 to
4b4e64aCompareUh oh!
There was an error while loading. Please reload this page.
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 freeto 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 #1620.
Problem
union_locatormerges the address hints of the samepeer_idnamed by multiple sources (#836/#97), then caps the combined set atMAX_ADDRS_PER_PROVIDER. But the cap ran after the merge (existing.addresses.extend(record.addresses)→sanitize_address_hints) and kept the firstMAX. So an earlier source that had already filled the cap with unreachable hints (a stale DHT record) silently dropped a later source's novel reachable hint (the live connected pool) for the same peer — the node then dialed only stale hints and missed a dialable holder. Masked in production only by wiring the reachable pool source first; any reorder reintroduced it (verified still-real against currentmain, per the ticket's "reproduce RED first" note).Fix — reconciles #1620 with #836
merge_address_hintsreserves the cap's slots for the later source's novel hints first, then leads with as many of the earlier source's hints as still fit:best_addressbreaks ties by list order, and the pool source is wired first).combined ≤ MAX), the order is unchanged (earlier-then-later), so the existing #836 behaviour is byte-identical.The shared order-preserving dedup is factored into
dedup_hints;sanitize_address_hints(first-seen ingest) dedups-then-caps through it.Blast radius (checked)
union_locator.rsonly.merge_address_hintsis called from the oneSome(i)merge branch; theNone(first-seen ingest) branch keeps itssanitize_address_hintscap. The dial consumer selectsbest_address()(dig-dht preference + list-order tie-break), which is unaffected — the earlier head still leads; the fix only guarantees the reachable hint is present to be chosen.Tests
a_later_sources_novel_hint_survives_when_an_earlier_source_fills_the_cap— earlier source fills the cap + later source's one reachable hint → reachable survives, earlier head still leads. (Fails against the old code, which kept 8 earlier + dropped the reachable.)same_peer_across_sources_merges_address_hintsasserts first-seen leads;provider_address_hints_are_capped_and_deduped).cargo test -p dig-node-core --lib union_locator→ 6 passed, 0 failed. fmt clean;clippy -D warningsclean.Version
0.72.1→0.72.2(patch —fix:, behaviour-correcting within the existing contract), re-locked.🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com
Generated by Claude Code