v1.3.4 — Auto-updater downgrade protection + bootnode sync fix
Auto-updater downgrade protection + bootnode sync fix
Auto-updater: refuse to downgrade
The auto-updater previously compared versions with latest != current and
happily downgraded nodes when the remote "latest" release was older than
the locally installed binary. Observed during the 2026-04-09 four-way fork
incident: a brand-new v1.3.1 hotfix was silently downgraded to v1.3.0
because v1.3.0 was still marked latest on GitHub at that moment,
overriding the manual hotfix.
compareSemver() is now used to only apply updates when
latest > current. If a newer local binary sees an older remote latest
(stale metadata, rollback, mis-tagged release), the updater logs:
Remote 'latest' release is OLDER than currently installed — refusing to downgrade
and leaves the binary alone. Regression test added:
TestCompareSemver_Regression.
Bootnode sync fix
Bootnodes stayed permanently 100-300 blocks behind validators because
handleBlockBodies deduplicated by gossip-seen-set instead of
chain-membership. The race:
- Bootnode receives a fresh block via gossip (
handleNewBlock). handleNewBlockmarks the block as seen BEFORE checking parent existence.- Parent is missing → triggers sync → returns without inserting.
- Sync response arrives later with the parent + the original block in a
batch of bodies. handleBlockBodiescheckshasSeen(block.Hash)— which returns true
because step 2 marked it — and silently drops the entire batch. The
bootnode stays stuck forever.
Fix: handleBlockBodies now uses blockchain.HasBlock(block.Hash) —
authoritative chain membership — for the dedup check. The seen set
remains for its original purpose (gossip dedup in handleNewBlock).
Testnet verification
- Consensus stable across all 4 validators, blocks in sync up to current tip
- Payment economy running
- Bootnode sync lag expected to close within ~1 minute of deploy
Upgrade notes
Drop-in upgrade. No chain data wipe needed.