Commit graph

307 commits

Author SHA1 Message Date
Olaoluwa Osuntokun
50f056f3c2
Merge pull request #2428 from kcalvinalvin/2025-09-16-new-parallel-block-downloads
blockchain, netsync: implement a complete headers-first download during ibd
2026-03-23 20:31:17 -04:00
Calvin Kim
28b6690ca9 blockchain: add BestChainHeaderForkHeight to return the fork point
between the best chain and the best header chain
2026-02-26 16:34:46 +09:00
Calvin Kim
eeb2d43a79 blockchain: add exports methods based on block header tip
The added exported methods on BlockChain provide access to the block
header tip like fetching block hashes and heights from the headers
chain.
2026-02-25 18:49:51 +09:00
Calvin Kim
e4b38e0cbf blockchain: change HaveBlock to also check for block data availability
In block processing and block downloading, HaveBlock is used to check if
the block data already exists.  It was ok to just check for the
existence of the blockNode but we now we also need to check if the data
exists as the blockNode may be present for just the block header.
2026-02-25 18:49:51 +09:00
Calvin Kim
9e45f60e9e blockchain: don't flush blockNodes that we don't have the data for
On flushes to the database, we check that the blockNodes we have for
the downloaded block headers are not flushed to the disk unless the
block data is stored as well for backwards compatibility.

With older btcd clients, they rely on the fact that the blockNode is
present to check if the block data is also present. Since we now
store blockNodes for just the block headers, this is no longer true.

Because of this, we don't flush the blockNodes if there's no
accompanying block data for it. This results in downloading and
verifying the headers again if the node were to restart but since the
header data is small and the verification is quick, it's not a big
downside.

As an optimization, flushToDB now skips opening a write transaction
entirely when every dirty node is header-only. This avoids a no-op
write transaction on every ProcessBlockHeader call during header sync.
2026-02-25 18:49:51 +09:00
Calvin Kim
f9645f07b5 blockchain: reuse existing header node in maybeAcceptBlock
maybeAcceptBlock unconditionally created a new blockNode, overwriting the
index entry.  If maybeAcceptBlockHeader had already processed the header,
the pointer held by bestHeader's chainView became orphaned, breaking
bestHeader.Contains and downstream checks like IsValidHeader.

Check for an existing node first and upgrade its status to
statusDataStored rather than replacing it.
2026-02-25 18:49:51 +09:00
Calvin Kim
c1a46122ca blockchain: add ProcessBlockHeader
ProcessBlockHeader performs chain selection and context-free &
contextual validation for the given block header.  The function allows
a header-first downloading of blocks even without checkpoints.
2026-02-25 18:49:51 +09:00
Calvin Kim
fd16786b1e blockchain: add maybeAcceptHeader
maybeAcceptHeader performs checks to accept block headers into the
header chain.  This function allows for a true headers-first download
where we only accept block headers for downloading new blocks.
2026-02-25 15:42:46 +09:00
Calvin Kim
743d0a2c40 blockchain: add ErrKnownInvalidBlock error code
Distinguish between a block that has itself failed validation
versus one that is only invalid due to an ancestor.
2026-02-25 15:42:46 +09:00
Calvin Kim
b60c2c3016 blockchain: add statusHeaderStored for blockNode status
Since we may now have blockNodes with just the block header stored
without the data, we add a new status to account for this.
2026-02-25 15:42:46 +09:00
Calvin Kim
5f25cf0d37 blockchain: add bestHeader to BlockChain
We add a chainview of bestHeaders so that we'll be able to keep track of
headers separately from the bestChain. This is needed as we're getting
headers for new block annoucements instead of invs.
2026-02-25 15:42:46 +09:00
Jameson Lopp
d3615dcc28
fix spelling error 2025-12-25 07:33:49 -05:00
Olaoluwa Osuntokun
a4f82f2540
blockchain: implement AlwaysActiveHeight for forced deployment activation
This commit introduces the concept of `AlwaysActiveHeight` to the
deployment mechanism, allowing a deployment to be forced into the active
state if the next block's height meets or exceeds this threshold.

This is intended primarily to be used alongside the new Testnet4
deployment, as the past major soft forks are meant to be active from the
very first block height.
2025-03-18 11:18:39 -05:00
Olaoluwa Osuntokun
591d7e1609
blockchain: add property-based tests for assertNoTimeWarp
Add robust property-based tests for the assertNoTimeWarp function using
the rapid testing library. The tests verify the following scenarios:

- Basic property tests:
  - Only retarget blocks (block height divisible by blocksPerRetarget) are checked
  - Valid timestamps (within maxTimeWarp of previous block) pass validation
  - Invalid timestamps (too early) fail with appropriate ErrTimewarpAttack
  - Correct boundary behavior (exactly at maxTimeWarp limit)

- Invariant tests:
  - Function never panics with valid inputs
  - Non-retarget blocks always return nil regardless of timestamps

- Security tests:
  - All retarget blocks are protected from timewarp attacks
  - Non-retarget blocks are not affected by the timewarp check
2025-03-18 11:18:39 -05:00
Oleg Bondar
0ef589e8e3
blockchain: add BIP94 support 2025-03-18 11:18:38 -05:00
Oleg Bondar
b1ab1ded9c
multi: fix typos 2025-03-18 11:18:37 -05:00
Eugene Siegel
3eda1a58a2
blockchain: copy utxo status bytes to avoid UB
It is undefined behavior if we directly use the value from a Get
call after the transaction has completed.
2024-08-06 11:49:23 -04:00
Olaoluwa Osuntokun
cd5e5bab63
Merge pull request #2196 from Crypt-iQ/2181_eugene
blockchain: Add ReconsiderBlock()
2024-06-19 16:07:14 -07:00
veth
976cbebd09
chore: fix some comments (#2191) 2024-06-19 11:37:10 -04:00
Calvin Kim
52a8a2a06e blockchain: Add ReconsiderBlock to BlockChain
ReconsiderBlock reconsiders the validity of the block for the passed
in blockhash. The behavior of the function mimics that of Bitcoin Core.

The invalid status of the block nodes are reset and if the chaintip that
is being reconsidered has more cumulative work, then we'll validate the
blocks and reorganize to it. If the cumulative work is lesser than the
current active chain tip, then nothing else will be done.
2024-06-07 18:08:25 -04:00
Calvin Kim
eabc9bf50c blockchain: Refactor reorganizeChain to exclude verification
reorganizeChain() used to handle the following:
1: That the blocknodes being disconnected/connected indeed to connect
   properly without errors.
2: Perform the actual disconnect/connect of the blocknodes.

The functionality of 1, the validation that the disconnects/connects can
happen without errors are now refactored out into
verifyReorganizationValidity.

This is an effort made so that ReconsiderBlock() can call
verifyReorganizationValidity and set the block status of the
reconsidered chain and return nil even when an error returns as it's ok
to get an error when reconsidering an invalid branch.
2024-06-07 18:08:25 -04:00
Olaoluwa Osuntokun
c4677255bd
Merge pull request #2155 from kcalvinalvin/2024-04-02-invalidate-block
blockchain, fullblocktests, workmath, testhelper: add InvalidateBlock() method to BlockChain
2024-05-22 13:15:47 -07:00
Calvin Kim
689ac6b6de blockchain: remove trailing ":" and space on utxocache log 2024-05-01 17:59:02 +09:00
Calvin Kim
635ae68957 blockchain: Add InvalidateBlock() method to BlockChain
InvalidateBlock() invalidates a given block and marks all its
descendents as invalid as well. The active chain tip changes if the
invalidated block is part of the best chain.
2024-04-30 17:13:32 +09:00
oftenoccur
126b0ecff1
chore: fix some typos in comments (#2164)
Signed-off-by: oftenoccur <ezc5@sina.com>
2024-04-26 08:08:05 -04:00
Calvin Kim
ea39fe090d blockchain: add block generating functions in test code
The block generating functions here allow for a test to create mock
blocks.  This is useful for testing invalidateblock and reconsiderblock
methods on blockchain that will be added in later commits.
2024-04-23 02:52:13 +09:00
Calvin Kim
5df14376c1 fullblocktests, testhelper: move createSpendTx to testhelper
createSpendTx is moved to testhelper so that the function can be used
for callers in package blockchain without introducing import cycles.
The test code for invalidateblock and reconsiderblock that are going to
be added in later commits make use of this code.
2024-04-23 02:48:28 +09:00
Calvin Kim
8ab27b9245 fullblocktests, testhelper: move createCoinbaseTx to testhelper
createCoinbaseTx's code is refactored out and placed in testhelper
package and is exported so that callers in package blockchain can reuse
the code without introducing import cycles.  The test code for
invalidateblock and reconsiderblock that'll be added in later commits
make use of this code.
2024-04-23 02:48:28 +09:00
Calvin Kim
59c7d10507 fullblocktests, testhelper: move standardCoinbaseScript to testhelper
standardCoinbaseScript is moved to testhelper and is exported.  This
allows test code in package blockchain to reuse the code without
introducing an import cycle.  This code is used in the testing code
for invalidateblock and reconsiderblock that's added in the later
commits.
2024-04-23 02:48:28 +09:00
Calvin Kim
9093243d8b fullblocktests, testhelper: move uniqueOpReturnScript to testhelper
uniqueOpReturnScript is moved to testhelper and is exported so that the
code and be reused in package blockchain without introducing import
cycles.  The test code for invalidateblock and reconsiderblock that are
gonna be added in later commits uses the functions.
2024-04-23 02:48:28 +09:00
Calvin Kim
62790ac065 fullblocktests, testhelper: move opTrueScript and lowFee to testhelper
The variables are moved to testhelper so that they can be reused in the
blockchain package without introducing an import cycle.  The testing
code for invalidateblock and reconsiderblock that will be added in later
commits will be using these variables.
2024-04-23 02:48:28 +09:00
Calvin Kim
d4644dff10 fullblocktests, testhelper: move solveBlock to testhelper
solveBlock is moved to testhelper and is exported.  This is done so that
the code can be reused without introducing import cycles.  The testing
code to be added in alter commits for invalidateblock and reconsider
block will use SolveBlock.
2024-04-23 02:48:19 +09:00
Calvin Kim
337d7f6be8 fullblocktests, testhelper: refactor out spendableOut
spendableOut and the functions related to it are is moved to package
testhelper and are exported.  This is done to make the code reusable
without introducing an import cycle when the testing code for
invalidateblock and reconsiderblock are added in follow up commits.
2024-04-23 02:42:35 +09:00
Calvin Kim
597b68c79e blockchain, workmath: refactor functions to workmath package
Some of the functions in difficulty.go are not dependent on any external
functions and they are needed to introduce testing code for the
invalidateblock and reconsiderblock methods that are to be added on in
later commits. Having the workmath package let's us reuse the code and
avoid dependency cycles.

The existing functions that were exported already (HashToBig,
CompactToBig, BigToCompact, CalcWork) are still kept in difficulty.go
to avoid breaking external code that depends on those exported
functions.
2024-04-23 02:35:36 +09:00
Calvin Kim
bc6396ddfd blockchain: Add IsAncestor method to blockNode
IsAncestor() provides functionality for testing if a block node is
an ancestor of anther block node.
2024-04-08 17:47:26 +09:00
Calvin Kim
c9c8795160 blockchain: add Equals method to blockNode
Helper function for the added IsAncestor in the follow up commit.
Returns true if all the fields (except for parent and ancestor) are
equal.
2024-04-08 17:47:08 +09:00
xiaoxiangxianzi
95330bc1bb
chore: fix some comments (#2146)
Signed-off-by: xiaoxiangxianzi <zhaoyizheng@outlook.com>
2024-03-27 09:45:48 -04:00
mattn
3cb9f602e8
fix typos (#2100) 2024-03-25 09:44:25 -04:00
Olaoluwa Osuntokun
f0ec9fbcce
Merge pull request #2128 from kcalvinalvin/2024-02-27-no-panic-for-subscription-callback-errors
blockchain: always relock chainLock for subscription callbacks
2024-03-08 17:56:14 -08:00
Olaoluwa Osuntokun
8ed234b9f5
Merge pull request #2134 from kcalvinalvin/2024-03-07-make-duplicate-entries-on-mapslice-impossible
blockchain: fix a bug where a duplicate entry is possible in the mapslice
2024-03-08 17:54:08 -08:00
Olaoluwa Osuntokun
e63bf03d2a
Merge pull request #2123 from kcalvinalvin/2024-02-15-no-utxocache-loading-on-reorgs
blockchain: fix inconsistent utxocache and database on reorg
2024-03-08 17:52:57 -08:00
Calvin Kim
078815bcbc blockchain: remove utxoview from the argument in connectBlock
Since no code is now depending on accepting new blocks without the
cache, we get rid of the option to do so.
2024-03-07 15:43:48 +09:00
Calvin Kim
059a668e88 blockchain: check all the maps first before adding an entry
When attempting to insert an entry to the mapslice, we check all the
underlying maps to ensure that the entry doesn't exist.
2024-03-07 15:27:44 +09:00
Calvin Kim
8d1aa01c69 blockchain: add another mapslice duplicate entry case
Duplicate entries are currently possible in the following scenario:

1: Add entries to the mapslice.
2: 1st map is full. Move onto the 2nd map.
3: Delete any entry in the first map.
4: Attempt to add an entry in the 2nd map.

When attempting (4), the entry should just be overwritten but a
duplicate gets added.
2024-03-07 15:24:00 +09:00
Calvin Kim
99846b0805 blockchain: remove unused fetchUtxosMain() 2024-03-06 02:44:51 +09:00
Calvin Kim
78b158dc56 blockchain: get rid of database as an argument in fetchInputUtxos
Allowing the caller to fetch from either the database or the cache
resulted in inconsistencies if the cache were ever to be dirty.
Removing this option eliminates this problem.
2024-03-06 02:42:33 +09:00
Calvin Kim
a254998bc5 blockchain: change reorg utxo cache behavior
The assumption in the previous code was incorrect in that we were
assuming that the chainLock is held throughout the entire chain reorg.
This is not the case since the chainLock is let go of during the
callback to the subscribers.

Because of this, we need to ensure that the utxo set is consistent on
each block disconnect. To achieve this, additional flushes are added
during block disconnects.

Also the utxocache is no longer avoided during block connects and when
we're checking for the validity of the block connects and disconnects as
we can just use the cache instead of trying to avoid it.
2024-03-06 02:40:24 +09:00
Calvin Kim
f2caa8fadc blockchain: don't rely on BlockHeightByHash for prune height
calculations

Since BlockHeightByHash only returns the heights for blocks that are in
the main chain, when a block that is stale gets pruned, this will cause
an error in the block height lookup and cause an error in block
processing.

Look up the node directly from the index and if the node isn't found,
just skip that node. For utxoCache.lastFlushHash, if that isn't found,
just force a flush.
2024-03-06 02:15:39 +09:00
Calvin Kim
3d1150a1a8 blockchain: always relock chainLock for subscription callbacks
For various b.sendNotifcation() callbacks, if a runtime panic happens,
we don't get any useful debugging information since the error that
happens first is the "unlock of unlocked mutex" error.

This is because we temporarily unlock the chainLock for callbacks and
then relock them.  However, since the relocking code is executed after
the completion of the callback, if an error happens during that
callback, we never relock the chainLock.

Switching to an anonymous function and having the unlock code as a
defer will ensure that the lock always relocks.
2024-02-27 14:32:42 +09:00
Calvin Kim
5a91ea23ca blockchain_test, fullblocktests: add test to check for utxo
existance/non-existance

New test instance BlockDisconnectExpectUTXO tests that a utxo
exists/doesn't exist after a specific block has been disconnected.
2024-02-21 19:09:03 +09:00