TestSyncStateMachine checked that handleHeadersMsg advanced
lastProgressTime by comparing it against the timestamp written by
startSync. Those two writes can happen within the same clock tick, so
the handler can update the field while time.After still reports false.
Reset lastProgressTime to the zero value before delivering headers and
assert that the handler writes a non-zero value. This keeps the test
focused on the behavior under test without depending on adjacent
time.Now calls producing distinct timestamps.
Commit 26124d275 made every peer a sync candidate on regtest and
simnet so that nodes on non-localhost networks (e.g. Docker bridge
networks) can be synced from. Dropping the address requirement was
the intent, but the change also dropped the service-flag requirement,
so light clients became eligible sync peers.
A light client (e.g. neutrino) advertises a recent best height but
can serve neither headers nor blocks. Electing one as the sync peer
stalls the sync until the stall handler disconnects it, and with
other light client connections present the next one is elected and
stalls again, livelocking the sync indefinitely. This surfaced in
neutrino's sync tests, where a btcd simnet node connected to both a
neutrino instance and other btcd nodes never synced.
Keep accepting any peer address on regtest/simnet, but require the
peer to signal SFNodeNetwork or SFNodeNetworkLimited like on any
other network.
PR #2467 changed regtest to match Core's BIP34/65/66 activation rules, and
the merged stack carries that (commit cd4e5426 "regtest: align activations
with Bitcoin Core"). Height-1 regtest blocks now need a BIP34-compliant
coinbase height and a post-BIP66 block version.
The failing tests came from commits added after PR #2467 was opened on
December 25, 2025 but before it merged on April 30, 2026:
- c1a46122 ("blockchain: add ProcessBlockHeader")
- f9645f07 ("blockchain: reuse existing header node in maybeAcceptBlock")
- dc6e096c ("netsync: add TestSyncStateMachine for end-to-end IBD sync flow")
- ce094262 ("netsync: add TestStartSyncBlockFallback for block-only sync path")
- 2aae8a6d ("netsync: add TestStartSyncChainCurrent for chain-current noop path")
Because those tests landed later, they kept the old regtest assumptions even
though #2467 had already been authored and tested against the older tree.
Once #2467 finally merged, these newer tests started building invalid regtest
blocks and headers.
Fix them by setting the genesis tip height to 0 before generating descendants,
using Version 4 in the regtest block/header helpers, and encoding the test
coinbase height with a minimal BIP34 push plus padding for the generic coinbase
script-length rule.
Verify that startSync skips header download and directly requests
blocks when the header chain is already caught up to the peer's
height but the block chain lags behind.
Refactor fetchHeaderBlocks and buildBlockRequest to take an explicit
peer parameter instead of implicitly using sm.syncPeer. This makes the
caller responsible for choosing which peer to fetch from and adds a nil
guard to prevent a panic if the sync peer has been cleared.
headers
We introduce buildBlockRequest that'll create a getdata message based
off of the block index instead of the headerList in SyncManager.
The new fetchHeaderBlocks utilizes buildBlockRequest and now will create
fetch requests based on the processed block headers.
isInIBDMode returns if the SyncManager needs to download blocks and sync
to the latest chain tip.
It determines if it's in ibd mode by checking if the blockchain thinks
we're current and if we don't have peers that are at higher advertised
blocks.