Skip to content

bch(M5): HeaderChain back-off locator for IBD getheaders continuation - #208

Merged
frstrtr merged 2 commits into
masterfrom
bch/m5-ibd-robust-locator
Jun 19, 2026
Merged

bch(M5): HeaderChain back-off locator for IBD getheaders continuation#208
frstrtr merged 2 commits into
masterfrom
bch/m5-ibd-robust-locator

Conversation

@frstrtr

@frstrtr frstrtr commented Jun 19, 2026

Copy link
Copy Markdown
Owner

M5 embedded-daemon body, pure src/impl/bch/ SPV wire-sync.

PROBLEM: the headers-first IBD continuation (ContinueSync) re-issued getheaders with a single-hash locator anchored at the last learned header. A lone hash is not fork-resilient — if our tip sits on a minority fork the peer cannot anchor, the peer returns nothing and IBD stalls silently (no common-ancestor fallback).

FIX: route the continuation through the authoritative HeaderChain locator (get_locator(), exponential back-off) via an injected provider on NodeP2P, wired by EmbeddedDaemon after start_p2p(). HeaderChain has already ingested the batch (wire_chain_ingest) before ContinueSync fires, so the locator is anchored at the just-learned tip AND carries deep back-off references. Degraded single-hash fallback retained when no provider is wired.

Selection logic extracted to header_sync::choose_continue_locator (pure, templated) and unit-tested alongside classify policy — header_sync_test: ALL PASS. Both touched headers syntax-clean (-std=c++20).

SURFACE: p2pool-merged-v36 = NONE (no PoW/share/coinbase/AuxPoW/PPLNS). Per-coin isolation: src/impl/bch/ only; no prefix/identifier/consensus value; no bitcoin_family. Auto-merge-lane eligible; merge operator-gated.

frstrtr added 2 commits June 19, 2026 13:13
…tion

The headers-first IBD continuation (ContinueSync) re-issued getheaders with a
single-hash locator anchored at the last learned header. A lone hash is not
fork-resilient: if our latest header sits on a minority fork the peer cannot
anchor, the peer returns nothing and IBD stalls silently with no common-ancestor
fallback.

Route the continuation through the authoritative HeaderChain locator
(get_locator(), exponential back-off from the tip) via an injected provider on
NodeP2P, wired by EmbeddedDaemon after start_p2p(). The header chain has already
ingested the batch (wire_chain_ingest) before ContinueSync fires, so the locator
is anchored at the just-learned tip AND carries deep back-off references. Falls
back to the single-hash anchor only when no provider is wired (degraded).

Selection logic extracted to header_sync::choose_continue_locator (pure,
templated) and unit-tested alongside the classify policy. Pure SPV wire-sync:
no PoW/share/coinbase/AuxPoW/PPLNS surface; src/impl/bch/ only.
…e single-hash stalls

The progress soak drove cold-start IBD on a clean chain; header_sync_test
pinned choose_continue_locator as a pure function. Neither exercised the
COMPOSITIONAL property PR #208 actually buys: that the IBD *loop*, driven
through choose_continue_locator, CONVERGES to the peer tip when our latest
header sits on a minority fork -- the silent-stall case the back-off locator
fixes.

Add three loop-level invariants over a live-shaped cursor (anchor 955700 ->
peer tip 955822, the VM300 bchn-bch range), modeling the real BIP31 back-off
(get_locator_internal) and a peer that anchors only at a locator entry on its
main chain:
  inv.6 shallow fork: back-off locator anchors at the EXACT common ancestor,
        converges, re-walks ZERO already-held headers (false_evict analog == 0).
  inv.7 same fork, degraded single-hash fallback (no provider) STALLS and never
        converges -- proves the provider is load-bearing, not cosmetic.
  inv.8 deep 50-block fork still converges; re-walk bounded by one batch.

Header-only over coin/header_sync.hpp; src/impl/bch/test/ only; impl_bch stays
unregistered (bch skip-green). p2pool-merged-v36 surface: NONE.
@frstrtr
frstrtr merged commit bcfd21c into master Jun 19, 2026
19 checks passed
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.

1 participant