Commit graph

45 commits

Author SHA1 Message Date
Boris Nagaev
0860e42dcf
netsync: avoid clock tick race in sync state test
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.
2026-07-02 01:18:38 -05:00
Oli
a7e980dd34
netsync: require block-serving services on regtest/simnet sync peers
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.
2026-06-17 13:45:43 +02:00
Calvin Kim
bfb36e52e7 netsync: process inv announcements when no syncPeer is set
handleInvMsg early-returned for any inv from a non-syncPeer whenever
sm.current() was false, with the comment that it prevents fetching a
mass of orphans. That guard assumes a syncPeer is already fetching
blocks; when syncPeer is nil, the assumption breaks down and the
early return becomes a deadlock.

The deadlock is reachable whenever two nodes connect at equal heights:
startSync exits without picking a syncPeer (no peer is "higher"), and
nothing later promotes the freshly-mined blocks the peer announces via
inv. The pre-verack disconnect and sync-race regression tests in
integration/sync_race_test.go fail consistently because of this.

Only skip the inv when we actually have a syncPeer. When syncPeer is
nil, fall through and let the normal request path queue the block --
the inv is the only signal that there are blocks to fetch.
2026-05-30 17:25:51 +09:00
Oliver Gugger
dccea8feba multi: use new v2 modules everywhere 2026-05-14 18:05:33 -07:00
Boris Nagaev
74f48480e0
tests: fix stale regtest assumptions after #2467
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.
2026-05-06 17:16:25 -05:00
Olaoluwa Osuntokun
7f47da83bb netsync: add TestIsSyncCandidateRegtest
Add a test verifying that isSyncCandidate accepts peers from any
address on regtest, including Docker bridge IPs, remote IPs, and IPv6.
2026-03-23 21:13:59 -04:00
Abdullahi Yunus
26124d2754 netsync: allow sync with non-localhost peers on regtest/simnet
In this commit, we remove the localhost-only restriction for sync peer
candidates on regtest and simnet. Previously, isSyncCandidate rejected
any regtest peer not on 127.0.0.1 or localhost, which prevented IBD
when nodes run in Docker containers on bridge networks (e.g. 172.18.0.x).

We also replace fragile pointer-equality checks against global chaincfg
params with value-based Name field comparisons, and extend the exception
to simnet since it has the same local-only usage pattern.
2026-03-23 21:13:48 -04:00
Calvin Kim
2aae8a6d68 netsync: add TestStartSyncChainCurrent for chain-current noop path
Verify that startSync does not set syncPeer or ibdMode when the
chain tip is recent and no peer advertises a height above ours.
2026-02-26 23:08:01 +09:00
Calvin Kim
570d3c8da3 netsync: add TestStallNoDisconnectAtSameHeight for stall handler 2026-02-26 22:22:51 +09:00
Calvin Kim
ce094262ff netsync: add TestStartSyncBlockFallback for block-only sync path
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.
2026-02-26 22:05:57 +09:00
Calvin Kim
dc6e096cd3 netsync: add TestSyncStateMachine for end-to-end IBD sync flow
Tests the full IBD state machine: startSync → fetchHeaders →
handleHeadersMsg → fetchHeaderBlocks → handleBlockMsg → IBD complete.

Three sub-cases exercise different paths:
- fresh IBD from genesis
- node restart with partially synced blocks
- stalled sync peer recovery via handleStallSample
2026-02-26 21:57:54 +09:00
Calvin Kim
0b1c7b7acd netsync: rename headersFirstMode to ibdMode
ibdMode is a more fitting name than headersFirstMode since all blocks
are downloaded headers-first during the initial block download.
2026-02-26 18:10:29 +09:00
Calvin Kim
5af7680b2b netsync: remove unused headerList and checkpoint code
Since we no longer utilize the headerList for doing headers-first
download and checkpoint tracking, we remove related code.
2026-02-26 18:10:29 +09:00
Calvin Kim
9530eda3ee netsync: update handleBlockMsg
handleBlockMsg is updated to not be based off of the headerList and
sm.nextCheckpoint when doing operations related to checkpoints and
headers.
2026-02-26 18:10:29 +09:00
Calvin Kim
46574cc746 netsync: change startSync to be based off of processed headers
ince we now utilize ProcessBlockHeaders, we change the startSync
function to utilize the block index for downloading blocks/headers
instead of using the headerList in SyncManager.
2026-02-26 18:10:29 +09:00
Calvin Kim
8588a25129 netsync: require peer argument in fetchHeaderBlocks
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.
2026-02-26 16:40:01 +09:00
Calvin Kim
dc90f8ca2a netsync: change fetchHeaderBlocks to be based on the processed block
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.
2026-02-26 16:39:55 +09:00
Calvin Kim
26c24592d2 netsync: use ProcessBlockHeader in handleBlockHeader
Instead of the old headerList based header processing, we make use of
the new ProcessBlockHeader function.
2026-02-26 16:34:46 +09:00
Calvin Kim
2f2364db66 netsync: add fetchHeaders
fetchHeaders picks a random peer at a higher advertised block and
requests headers from them.
2026-02-26 16:34:46 +09:00
Calvin Kim
51576a44cc netsync: add isInIBDMode
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.
2026-02-26 16:34:46 +09:00
Calvin Kim
ddf80b87ef netsync: add fetchHigherPeers
fetchHigherPeers provides a convenient function to get peers that are
sync candidates and are at a higher advertised height than the passed in
height.
2026-02-26 16:34:44 +09:00
Calvin Kim
b1aef3ad21 netsync: add checkHeadersList
checkHeadersList takes in a blockhash and returns if it's a checkpointed
block and the correct behavior flags for the verification of the block.
2026-02-26 16:33:47 +09:00
Calvin Kim
aace7a9d0f netsync: don't ask for blocks from peers on the same block height
When we're all caught up and we have a new peer, we'll ask for blocks
from peers that we're on the same height. Since these peers don't have
any blocks to send us, they don't reply and we disconnect from them as
they timeout.

To prevent this, we don't ask for blocks if the chain thinks we're
current and do not have a peer that reports having a higher block.
2025-01-16 16:09:26 +09:00
xiaoxiangxianzi
95330bc1bb
chore: fix some comments (#2146)
Signed-off-by: xiaoxiangxianzi <zhaoyizheng@outlook.com>
2024-03-27 09:45:48 -04:00
Calvin Kim
c17cf800dc netsync: don't update mempool/fee estimator unless we're synced up
Noticed during ibd that there's a slight overhead for
handleBlockchainNotification on mempool/fee estimator updates. Since
there's no reason to be looking at this while we're not caught up,
return early and avoid the calls.
2024-01-22 13:35:55 +09:00
Calvin Kim
16cd44f0e6 blockchain, netsync, main, cmd/addblock: Use utxocache
This change is part of the effort to add utxocache support to btcd.

utxo cache is now used by the BlockChain struct.  By default it's used
and the minimum cache is set to 250MiB.  The change made helps speed up
block/tx validation as the cache allows for much faster lookup of utxos.
The initial block download in particular is improved as the db i/o
bottleneck is remedied by the cache.
2023-12-16 16:53:17 +09:00
Calvin Kim
b4992febff netsync: change isSyncCandidate behavior to include pruned nodes
isSyncCandidate is now changed to return true even if the peer is a
pruned node if and only if our chaintip is within 288 blocks of the
peer.

Rationale:
Pruned nodes that signal NODE_NETWORK_LIMITED MUST serve 288 blocks from
their chaintip.  If our chaintip is within that range, this peer can be
a sync candidate even if they aren't an archival node.
2023-11-07 11:04:34 +09:00
Calvin Kim
ba5407615d multi: Run gofmt on the entire repository
The doc formatting changes introduced in the recent go version is
increasing the diff for all of the new commits.  Formatting it all in
this commit will help the readability of future PRs by reducing the
diff.
2023-06-21 22:31:09 +09:00
Olaoluwa Osuntokun
caac0f821a
multi: update btcutil imports to point to new sub-module
In this commit, we update all the btcutil imports to point to the new
sub-module.

In the same commit, we also modify the recently added `btcutil/go.mod`
file as we need to continue pointing to the _old_ version of btcd, until
we merge this PR and push a new tag.
2022-01-10 18:44:58 -08:00
Jake Sylvestre
d08785547a docs: update shields 2021-03-05 07:45:19 -05:00
yyforyongyu
61634447e7
btcd+netsync: support witness tx and block in notfound msg 2020-09-03 18:53:16 +08:00
Javed Khan
24db7d7c0c netsync: handle notfound messages from peers
backport from https://github.com/decred/dcrd/pull/2253

When a peer sends a notfound message, remove the hash from requested
map.  Also increase notfound ban score and return early if it
disconnects the peer.
2020-07-28 09:23:35 -04:00
Javed Khan
875b51c9fb peer: knownInventory, sentNonces - use generic lru
While here, also rename and generalize limitMap and apply to
other maps which need to be bounded.
2020-07-08 16:44:04 -04:00
Conner Fromknecht
e7f9935099
netsync/manager: add syncPeer stall detector
Adds stall detection when no blocks have been received from the sync
peer for at least 3 minutes.

The change backports parts of https://github.com/gcash/bchd/pull/105,
though has different behavior, such as:
 - Rotating the sync peer at tip.
 - Only disconnecting the sync peer if they're height exceeds our own.
   Since we will instead rotate the sync peer at tip, this prevents us
   from disconnecting good peers while waiting for new blocks.
 - Not resetting the progress time when blocks are submitted via rpc.
2019-04-26 17:20:57 -07:00
Conner Fromknecht
a015d8231e
netsync/manager: split out handlePeerDone helpers
Preemptively splits out portions of the handlePeerDone method so that
they can be used in the stall detection logic added in the next commit.
2019-04-26 17:20:57 -07:00
Conner Fromknecht
a9f23321d9
netsync/manager: prioritize higher height peers for sync peer
This commit modifies the sync peer selection to prefer peers with a
higher advertised height than our currently known best height. If no
peers are known with a higher height, we will fall back to selecting a
random peer with the same best height as our own.

The current algorithm currently selects a random peer from the union of
these two sets, while this approach will favor trying to make progress.
This will likely help in selecting a good peer once already at tip, such
as after a restart.

Backport of https://github.com/gcash/bchd/pull/96
2019-04-16 21:09:18 -07:00
Shuai Qi
5bda5314ca netsync+blockchain: fix typos 2019-01-08 20:07:09 -08:00
Dave Collins
a59ac5b18f
multi: Rework utxoset/view to use outpoints.
This modifies the utxoset in the database and related UtxoViewpoint to
store and work with unspent transaction outputs on a per-output basis
instead of at a transaction level.  This was inspired by similar recent
changes in Bitcoin Core.

The primary motivation is to simplify the code, pave the way for a
utxo cache, and generally focus on optimizing runtime performance.

The tradeoff is that this approach does somewhat increase the size of
the serialized utxoset since it means that the transaction hash is
duplicated for each output as a part of the key and some additional
details such as whether the containing transaction is a coinbase and the
block height it was a part of are duplicated in each output.

However, in practice, the size difference isn't all that large, disk
space is relatively cheap, certainly cheaper than memory, and it is much
more important to provide more efficient runtime operation since that is
the ultimate purpose of the daemon.

While performing this conversion, it also simplifies the code to remove
the transaction version information from the utxoset as well as the
spend journal.  The logic for only serializing it under certain
circumstances is complicated and it isn't actually used anywhere aside
from the gettxout RPC where it also isn't used by anything important
either.  Consequently, this also removes the version field of the
gettxout RPC result.

The utxos in the database are automatically migrated to the new format
with this commit and it is possible to interrupt and resume the
migration process.

Finally, it also updates the tests for the new format and adds a new
function to the tests to convert the old test data to the new format for
convenience.  The data has already been converted and updated in the
commit.

An overview of the changes are as follows:

- Remove transaction version from both spent and unspent output entries
  - Update utxo serialization format to exclude the version
  - Modify the spend journal serialization format
    - The old version field is now reserved and always stores zero and
      ignores it when reading
    - This allows old entries to be used by new code without having to
      migrate the entire spend journal
  - Remove version field from gettxout RPC result
- Convert UtxoEntry to represent a specific utxo instead of a
  transaction with all remaining utxos
  - Optimize for memory usage with an eye towards a utxo cache
    - Combine details such as whether the txout was contained in a
      coinbase, is spent, and is modified into a single packed field of
      bit flags
    - Align entry fields to eliminate extra padding since ultimately
      there will be a lot of these in memory
    - Introduce a free list for serializing an outpoint to the database
      key format to significantly reduce pressure on the GC
  - Update all related functions that previously dealt with transaction
    hashes to accept outpoints instead
  - Update all callers accordingly
  - Only add individually requested outputs from the mempool when
    constructing a mempool view
- Modify the spend journal to always store the block height and coinbase
  information with every spent txout
  - Introduce code to handle fetching the missing information from
    another utxo from the same transaction in the event an old style
    entry is encountered
    - Make use of a database cursor with seek to do this much more
      efficiently than testing every possible output
- Always decompress data loaded from the database now that a utxo entry
  only consists of a specific output
- Introduce upgrade code to migrate the utxo set to the new format
  - Store versions of the utxoset and spend journal buckets
  - Allow migration process to be interrupted and resumed
- Update all tests to expect the correct encodings, remove tests that no
  longer apply, and add new ones for the new expected behavior
  - Convert old tests for the legacy utxo format deserialization code to
    test the new function that is used during upgrade
  - Update the utxostore test data and add function that was used to
    convert it
- Introduce a few new functions on UtxoViewpoint
  - AddTxOut for adding an individual txout versus all of them
  - addTxOut to handle the common code between the new AddTxOut and
    existing AddTxOuts
  - RemoveEntry for removing an individual txout
  - fetchEntryByHash for fetching any remaining utxo for a given
    transaction hash
2018-05-27 03:07:41 -05:00
Olaoluwa Osuntokun
b72e16f0d6 multi: correct all import paths 2018-05-23 16:46:15 -07:00
Daniel Krawisz
1333ad7f78 FeeEstimator added to server. Mempool alerts the fee estimator of
new txs that it observes. The block manager alerts the fee estimator
of new and orphaned blocks.

Check for invalid state and recreate FeeEstimator if necessary.
2018-05-23 16:46:15 -07:00
Olaoluwa Osuntokun
10432160d5 multi: rebase to upstream, update API's 2018-05-23 16:46:15 -07:00
Jim Posen
46fd4ec358 netsync: Change name of blockManager to syncManager. 2017-08-25 13:41:22 -05:00
Jim Posen
f2fc24d0fc netsync: Use package-local logger. 2017-08-25 13:41:22 -05:00
Jim Posen
1cf7e233e5 netsync: Initialize netsync package.
Create doc.go, interface.go, and README for new package.
2017-08-25 13:41:22 -05:00
Jim Posen
3135a40371 MOVEONLY: Move blockmanager and blocklogger to netsync directory. 2017-08-25 13:41:22 -05:00