Bridge the node from IBD validator (syncs to a height and stops) to a live node that follows the chain and survives reorgs.
What it does (_follow.mjs)
- Bootstrap the UTXO set from the saved snapshot (load the chainstate as a live coin view, ~20 s).
- Catch up to the live testnet4 tip block-by-block: fetch the next block, verify it links to our tip, validate it forward (structure + scripts/sigs/fees/maturity),
connect it (apply + record undo data), advance.
- Follow at the tip: poll for new blocks and connect them as they're mined.
- Handle reorgs in place: when a block doesn't link, walk down to the fork point, disconnect the orphaned blocks (restore their spent coins + remove their created ones, using the per-block undo data), then reconnect the canonical chain forward. Reorg-aware down to the snapshot height (undo buffer 1000 blocks; deeper → re-bootstrap).
Undo data is kept per connected block (the spent coins' records + created keys), since a block only references the coins it spends. Disconnect restores spent first, then removes created, so a coin created-and-spent within one block nets to correctly absent.
Verified
- Connect/disconnect round-trip is exact (connect N blocks, disconnect them → UTXO set returns bit-for-bit).
- Live on testnet4: bootstrapped → caught up 140,503 → tip → handled a real 2-block reorg (forked at 140,835, disconnected 2 orphans, reconnected) → now following at the live tip, in consensus with the network.
Gaps (follow-ups, not this PR)
- Key-path taproot (BIP 341) signature verification still skipped.
- P2P block source (uses the mempool.space REST API for now; the node's own P2P is the real path).
- Persistence/crash-recovery of the live UTXO set.
Bridge the node from IBD validator (syncs to a height and stops) to a live node that follows the chain and survives reorgs.
What it does (
_follow.mjs)connectit (apply + record undo data), advance.Undo data is kept per connected block (the spent coins' records + created keys), since a block only references the coins it spends. Disconnect restores spent first, then removes created, so a coin created-and-spent within one block nets to correctly absent.
Verified
Gaps (follow-ups, not this PR)