1756 Commits

Author SHA1 Message Date
Sergi Delgado Segura
8b91883a23 Set the same best tip on restart if two candidates have the same work
Before this, if we had two (or more) same work tip candidates and restarted our node,
it could be the case that the block set as tip after bootstrap didn't match the one
before stopping. That's because the work and `nSequenceId` of both block will be the same
(the latter is only kept in memory), so the active chain after restart would have depended
on what tip candidate was loaded first.

This makes sure that we are consistent over reboots.
2025-07-28 10:15:14 -04:00
stickies-v
9ba1fff29e
kernel: refactor: ConnectTip to pass block pointer by value
By passing by value, we can remove the need to allocate a new pointer if
the callsite uses move semantics. In the process, simplify naming.
2025-07-28 13:45:15 +01:00
MarcoFalke
face8123fd
log: [refactor] Use info level for init logs
This refactor does not change behavior.
2025-07-25 09:50:50 +02:00
MarcoFalke
fa183761cb
log: Remove function name from init logs
It is redundant with -logsourcelocations and the log messages are
clearer without it.

Also, remove a double-space.

Also, add braces around `if` touched in the next commit.

This tiny behavior change requires a test fixup.
2025-07-25 09:50:24 +02:00
glozow
f24771af05 relax child-with-unconfirmed-parents rule
This rule was originally introduced along with a very early proposal for
package relay as a way to verify that the "correct"
child-with-unconfirmed-parents package was provided for a transaction,
where correctness was defined as all of the transactions unconfirmed
parents. However, we are not planning to introduce a protocol where
peers would be asked to send these packages.

This rule has downsides: if a transaction has multiple parents but only
1 that requires package CPFP to be accepted, the current rule prevents
us from accepting that package. Even if the other parents are already in
mempool, the p2p logic will only submit the 1p1c package, which fails
this check. See the test in p2p_1p1c_network.py
2025-07-24 09:44:48 -04:00
glozow
c3cd7fcb2c [doc] remove references to now-nonexistent Finalize() function 2025-07-14 14:48:26 -04:00
glozow
98ba2b1db2 [doc] MemPoolAccept coins views 2025-07-14 14:48:25 -04:00
glozow
ba02c30b8a [doc] always CleanupTemporaryCoins after a mempool trim 2025-07-14 14:43:11 -04:00
merge-script
23e15d40b9
Merge bitcoin/bitcoin#32631: refactor: Convert GenTxid to std::variant
a60f863d3e276534444571282f432b913d3967db scripted-diff: Replace GenTxidVariant with GenTxid (marcofleon)
c8ba1995986323cd9e76097acc1f15eed7c60943 Remove old GenTxid class (marcofleon)
072a198ea4bc9f1e8449cd31e55d397b75ce4ad5 Convert remaining instances of GenTxid to GenTxidVariant (marcofleon)
1b528391c79497ae19f7e481439e350533c7cd1a Convert `txrequest` to GenTxidVariant (marcofleon)
bde4579b0780aa3754af35beffbcfeb31f28045b Convert `txdownloadman_impl` to GenTxidVariant (marcofleon)
c876a892ec0b04851bea0a688d7681b6aaca4cb7 Replace GenTxid with Txid/Wtxid overloads in `txmempool` (marcofleon)
de858ce2bea83c53635dee9a49c8c273a12440dd move-only: make GetInfo a private CTxMemPool member (stickies-v)
eee473d9f3019a0ea4ebbc9c41781813ad574a86 Convert `CompareInvMempoolOrder` to GenTxidVariant (marcofleon)
243553d59071f3e43a42f3809706790495b17ffc refactor: replace get_iter_from_wtxid with GetIter(const Wtxid&) (stickies-v)
fcf92fd640eae60d1f601136a4e1c9de8ccb68b5 refactor: make CTxMemPool::GetIter strongly typed (marcofleon)
11d28f21bb8f0c3094934b3fef45871f73bb216a Implement GenTxid as a variant (marcofleon)

Pull request description:

  Part of the [type safety refactor](https://github.com/bitcoin/bitcoin/pull/32189).

  This PR changes the GenTxid class to a variant, which holds both Txids and Wtxids. This provides compile-time type safety and eliminates the manual type check (bool m_is_wtxid). Variables that can be either a Txid or a Wtxid are now using the new GenTxid variant, instead of uint256.

ACKs for top commit:
  w0xlt:
    ACK a60f863d3e
  dergoegge:
    Code review ACK a60f863d3e276534444571282f432b913d3967db
  maflcko:
    review ACK a60f863d3e276534444571282f432b913d3967db 🎽
  theStack:
    Code-review ACK a60f863d3e276534444571282f432b913d3967db

Tree-SHA512: da9b73b7bdffee2eb9281a409205519ac330d3336094d17681896703fbca8099608782c9c85801e388e4d90af5af8abf1f34931f57bbbe6e9674d802d6066047
2025-07-11 13:47:19 -04:00
Ava Chow
a40e953658
Merge bitcoin/bitcoin#30479: validation: Add eligible ancestors of reconsidered block to setBlockIndexCandidates
8cc3ac6c2328873e57c31f237d194c5f22b6748a validation: Don't use IsValid() to filter for invalid blocks (Martin Zumsande)
86d98b94e5469e6476dc87f54b8ac25074603f0c test: verify that ancestors of a reconsidered block can become the chain tip (stratospher)
3c39a55e64bedfc384f6a7b9de1410bc8b46a9bb validation: Add ancestors of reconsiderblock to setBlockIndexCandidates (Martin Zumsande)

Pull request description:

  When we call `reconsiderblock` for some block,  `Chainstate::ResetBlockFailureFlags` puts the descendants of that block into `setBlockIndexCandidates` (if they meet the criteria, i.e. have more work than the tip etc.), but never put any ancestors into the set even though we do clear their failure flags.

  I think that this is wrong, because `setBlockIndexCandidates` should always contain all eligible indexes that have at least as much work as the current tip, which can include ancestors of the reconsidered block. This is being checked by `CheckBlockIndex()`, which could fail if it was invoked after `ActivateBestChain` connects a block and releases `cs_main`:
  ``` diff
  diff --git a/src/validation.cpp b/src/validation.cpp
  index 7b04bd9a5b..ff0c3c9f58 100644
  --- a/src/validation.cpp
  +++ b/src/validation.cpp
  @@ -3551,6 +3551,7 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
               }
           }
           // When we reach this point, we switched to a new tip (stored in pindexNewTip).
  +        m_chainman.CheckBlockIndex();
   
           if (exited_ibd) {
               // If a background chainstate is in use, we may need to rebalance our
  ```
  makes `rpc_invalidateblock.py` fail on master.

  Even though we don't currently have a `CheckBlockIndex()` in that place, after `cs_main` is released other threads could invoke it, which is happening in the rare failures of #16444 where an invalid header received from another peer could trigger a `CheckBlockIndex()` call that would fail.

  Fix this by adding eligible ancestors to `setBlockIndexCandidates` in `Chainstate::ResetBlockFailureFlags` (also simplifying that function a bit).

  Fixes #16444

ACKs for top commit:
  achow101:
    ACK 8cc3ac6c2328873e57c31f237d194c5f22b6748a
  TheCharlatan:
    Re-ACK 8cc3ac6c2328873e57c31f237d194c5f22b6748a
  stratospher:
    reACK 8cc3ac6.

Tree-SHA512: 53f27591916246be4093d64b86a0494e55094abd8c586026b1247e4a36747bc3d6dbe46dc26ee4a22f47b8eb0d9699d13e577dee0e7198145f3c9b11ab2a30b7
2025-07-09 16:55:43 -07:00
Eugene Siegel
d541409a64
log: Add rate limiting to LogPrintf, LogInfo, LogWarning, LogError, LogPrintLevel
To mitigate disk-filling attacks caused by unsafe usages of LogPrintf and
friends, we rate-limit them by passing a should_ratelimit bool that
eventually makes its way to LogPrintStr which may call
LogRateLimiter::Consume. The rate limiting is accomplished by
adding a LogRateLimiter member to BCLog::Logger which tracks source
code locations for the given logging window.

Every hour, a source location can log up to 1MiB of data. Source
locations that exceed the limit will have their logs suppressed for the
rest of the window determined by m_limiter.

This change affects the public LogPrintLevel function if called with
a level >= BCLog::Level::Info.

The UpdateTipLog function has been changed to use the private LogPrintLevel_
macro with should_ratelimit set to false. This allows UpdateTipLog to log
during IBD without hitting the rate limit.

Note that on restart, a source location that was rate limited before the
restart will be able to log until it hits the rate limit again.

Co-Authored-By: Niklas Gogge <n.goeggi@gmail.com>
Co-Authored-By: stickies-v <stickies-v@protonmail.com>
2025-07-09 09:13:00 -04:00
marcofleon
c876a892ec Replace GenTxid with Txid/Wtxid overloads in txmempool
Co-authored-by: stickies-v <stickies-v@protonmail.com>
2025-07-08 19:31:02 +01:00
Pol Espinasa
d3b8a54a81
Refactor CFeeRate to use FeeFrac internally
Co-authored-by: Abubakar Sadiq Ismail <48946461+ismaelsadeeq@users.noreply.github.com>
2025-07-07 10:39:45 +02:00
Ava Chow
319ff58bbd
Merge bitcoin/bitcoin#32638: blocks: force hash validations on disk read
9341b5333ad54ccdb7c16802ff06c51b956948e7 blockstorage: make block read hash checks explicit (Lőrinc)
2371b9f4ee0b108ebbb8afedc47d73ce0f97d272 test/bench: verify hash in `ComputeFilter` reads (Lőrinc)
5d235d50d6dd0cc23175a1484e8ebb6cdc6e2183 net: assert block hash in `ProcessGetBlockData` and `ProcessMessage` (Lőrinc)

Pull request description:

  A follow-up to https://github.com/bitcoin/bitcoin/pull/32487#discussion_r2094072165, after which validating the hash of a read block from disk doesn't incur the cost of calculating its hash anymore.

  ### Summary

  This PR adds explicit checks that the read block header's hash matches the one we were expecting.

  ### Context

  After the previous PR, validating a block's hash during read operations became essentially free. This PR leverages that by requiring callers to provide a block's expected hash (or `std::nullopt`), preventing silent failures caused by corrupted or mismatched data. Most `ReadBlock` usages were updated with expected hashes and now fail on mismatch.

  ### Changes

  * added hash assertions in `ProcessGetBlockData` and `ProcessMessage` to validate that the block read from disk matches the expected hash;
  * updated tests and benchmark to pass the correct block hash to `ReadBlock()`, ensuring the hash validation is tested - or none if we already expect PoW failure;
  * removed the default value for `expected_hash`, requiring an explicit hash for all block reads.

  ### Why is the hash still optional (but no longer has a default value)

  * for header-error tests, where the goal is to trigger failures early in the parsing process;
  * for out-of-order orphan blocks, where the child hash isn't available before the initial disk read.

ACKs for top commit:
  maflcko:
    review ACK 9341b5333ad54ccdb7c16802ff06c51b956948e7 🕙
  achow101:
    ACK 9341b5333ad54ccdb7c16802ff06c51b956948e7
  hodlinator:
    ACK 9341b5333ad54ccdb7c16802ff06c51b956948e7
  janb84:
    re ACK 9341b5333ad54ccdb7c16802ff06c51b956948e7

Tree-SHA512: cf1d4fff4c15e3f8898ec284929cb83d7e747125d4ee759e77d369f1716728e843ef98030be32c8d608956a96ae2fbefa0e801200c333b9eefd6c086ec032e1f
2025-06-27 13:28:26 -07:00
Ava Chow
9a7eece5a4
Merge bitcoin/bitcoin#31981: Add checkBlock() to Mining interface
a18e57232867d946bc35769632fed49e1bf1464f test: more template verification tests (Sjors Provoost)
10c908808fb80cd4fbde9d377079951b91944755 test: move gbt proposal mode tests to new file (Sjors Provoost)
94959b8deedcff98a55c87b5e473890b2e7a3b16 Add checkBlock to Mining interface (Sjors Provoost)
6077157531c1cec6dea8e6f90b4df8ef7b5cec4e ipc: drop BlockValidationState special handling (Sjors Provoost)
74690f4ed82b1584abb07c0387db0d924c4c0cab validation: refactor TestBlockValidity (Sjors Provoost)

Pull request description:

  This PR adds the IPC equivalent of the `getblocktemplate` RPC in `proposal` mode.

  In order to do so it has `TestBlockValidity` return error reasons as a string instead of `BlockValidationState`. This avoids complexity in IPC code for handling the latter struct.

  The new Mining interface method is used in `miner_tests`.

  It's not used by the `getblocktemplate` and `generateblock` RPC calls, see https://github.com/bitcoin/bitcoin/pull/31981#discussion_r2096473337

  The `inconclusive-not-best-prevblk` check is moved from RPC
  code to `TestBlockValidity`.

  Test coverage is increased by `mining_template_verification.py`.

  Superseedes #31564

  ## Background

  ### Verifying block templates (no PoW)

  Stratum v2 allows miners to generate their own block template. Pools may wish (or need) to verify these templates. This typically involves comparing mempools, asking miners to providing missing transactions and then reconstructing the proposed block.[^0] This is not sufficient to ensure a proposed block is actually valid. In some schemes miners could take advantage of incomplete validation[^1].

  The Stratum Reference Implementation (SRI), currently the only Stratum v2 implementation, collects all missing mempool transactions, but does not yet fully verify the block.[^2]. It could use the `getblocktemplate` RPC in `proposal` mode, but using IPC is more performant, as it avoids serialising up to 4 MB of transaction data as JSON.

  (although SRI could use this PR, the Template Provider role doesn't need it, so this is _not_ part of #31098)

  [^0]: https://github.com/stratum-mining/sv2-spec/blob/main/06-Job-Declaration-Protocol.md
  [^1]: https://delvingbitcoin.org/t/pplns-with-job-declaration/1099/45?u=sjors
  [^2]: https://github.com/stratum-mining/stratum/blob/v1.1.0/roles/jd-server/src/lib/job_declarator/message_handler.rs#L196

ACKs for top commit:
  davidgumberg:
    reACK a18e572328
  achow101:
    ACK a18e57232867d946bc35769632fed49e1bf1464f
  TheCharlatan:
    ACK a18e57232867d946bc35769632fed49e1bf1464f
  ryanofsky:
    Code review ACK a18e57232867d946bc35769632fed49e1bf1464f just adding another NONFATAL_UNREACHABLE since last review

Tree-SHA512: 1a6c29f45a1666114f10f55aed155980b90104db27761c78aada4727ce3129e6ae7a522d90a56314bd767bd7944dfa46e85fb9f714370fc83e6a585be7b044f1
2025-06-18 17:07:21 -07:00
Sjors Provoost
74690f4ed8
validation: refactor TestBlockValidity
Comments are expanded.

Return BlockValidationState instead of passing a reference.
Lock Chainman mutex instead of cs_main.
Remove redundant chainparams and pindexPrev arguments.
Drop defaults for checking proof-of-work and merkle root.

The ContextualCheckBlockHeader check is moved to after CheckBlock,
which is more similar to normal validation where context-free checks
are done first.

Validation failure reasons are no longer printed through LogError(),
since it depends on the caller whether this implies an actual bug
in the node, or an externally sourced block that happens to be invalid.
When called from getblocktemplate, via BlockAssembler::CreateNewBlock(),
this method already throws an std::runtime_error if validation fails.

Additionally it moves the inconclusive-not-best-prevblk check from RPC
code to TestBlockValidity.

There is no behavior change when callling getblocktemplate with proposal.
Previously this would return a BIP22ValidationResult which can throw for
state.IsError(). But CheckBlock() and the functions it calls only use
state.IsValid().

The final assert is changed into Assume, with a LogError.

Co-authored-by: <Ryan Ofsky <ryan@ofsky.org>
2025-06-14 14:32:45 +02:00
Lőrinc
9341b5333a blockstorage: make block read hash checks explicit
Dropped the default expected_hash parameter from `ReadBlock()`.

In `blockmanager_flush_block_file` tests, we pass {} since the tests would already fail at PoW validation for corrupted blocks.

In `ChainstateManager::LoadExternalBlockFile`, we pass {} when processing child blocks because their hashes aren't known beforehand.
2025-06-13 12:32:56 +02:00
Ava Chow
19765dca19
Merge bitcoin/bitcoin#32694: index: move disk read lookups to base class
029ba1a21d570f7db6c4366ec9a30a381b56d6fb index: remove CBlockIndex access from CustomAppend() (furszy)
91b7ab6c69264a46f70825546a1574478d9e824a refactor: index, simplify CopyHeightIndexToHashIndex to process single block (furszy)
6f1392cc42cde638773f2b697d7d2c58abcdc860 indexes, refactor: Remove remaining CBlockIndex* uses in index Rewind methods (Ryan Ofsky)
0a248708dc9d465db09168c39b3f12cb4c9465b7 indexes, refactor: Stop requiring CBlockIndex type to call IsBIP30Unspendable (Ryan Ofsky)
331a25cb16632042dd6782a9b62fcc5c8aa6da3b test: indexes, avoid creating threads when sync runs synchronously (furszy)

Pull request description:

  Combining common refactors from #24230 and #26966, aiming to move both efforts forward while reducing their size and review burden.

  Broadly, #24230 focuses on enabling indexes to run in a separate process, and #26966 aims to parallelize the indexes initial synchronization process. A shared prerequisite for both is ensuring that only the base index class interacts with the node’s chain internals - child index classes should instead operate solely through chain events.

  This PR moves disk read lookups from child index classes to the base index class. It also includes a few documentation improvements and a test-only code cleanup.

ACKs for top commit:
  maflcko:
    review ACK 029ba1a21d570f7db6c4366ec9a30a381b56d6fb 👡
  achow101:
    ACK 029ba1a21d570f7db6c4366ec9a30a381b56d6fb
  TheCharlatan:
    Re-ACK 029ba1a21d570f7db6c4366ec9a30a381b56d6fb
  davidgumberg:
    ACK 029ba1a21d570f7db6c
  mzumsande:
    Code Review ACK 029ba1a21d570f7db6c4366ec9a30a381b56d6fb

Tree-SHA512: f073af407fc86f228cb47a32c7bcf2241551cc89ff32059317eb81d5b86fd5fda35f228d2567e0aedbc9fd6826291f5fee05619db35ba44108421ae04d11e6fb
2025-06-12 16:01:04 -07:00
Martin Zumsande
8cc3ac6c23 validation: Don't use IsValid() to filter for invalid blocks
IsValid() also returns false for blocks that have not been
validated yet up to the default validity level of BLOCK_VALID_TRANSACTIONS but
are not marked as invalid - e.g. if we only know the header.
Here, we specifically want to filter for invalid blocks.

Also removes the default arg from IsValid() which is now unused outside
of tests, to prevent this kind of misuse for the future.

Co-authored-by: TheCharlatan <seb.kung@gmail.com>
2025-06-12 14:40:59 -04:00
Martin Zumsande
3c39a55e64 validation: Add ancestors of reconsiderblock to setBlockIndexCandidates
When we call reconsiderblock for some block, ResetBlockFailureFlags puts the descendants of that block
into setBlockIndexCandidates (if they meet the criteria, i.e. have more work than the tip etc.)
We also clear the failure flags of the ancestors, but we never put any of those into setBlockIndexCandidates
this is wrong and could lead to failures in CheckBlockIndex().
2025-06-12 14:40:57 -04:00
Ryan Ofsky
7c0cfce20d
Merge bitcoin/bitcoin#31405: validation: stricter internal handling of invalid blocks
f6b782f3aad4a6bcf823a9a0fabb4418bca1eea1 doc: Improve m_best_header documentation (Martin Zumsande)
ee673b9aa0157d94220722491f135aef23142521 validation: remove m_failed_blocks (Martin Zumsande)
ed764ea2b4edb3cf1925a4bff5f39567a8be54ac validation: Add more checks to CheckBlockIndex() (Martin Zumsande)
9a70883002e1fee76c24810808af4fb43f2c8cf5 validation: in invalidateblock, calculate m_best_header right away (Martin Zumsande)
8e39f2d20d09592035ae048d0cfe955c733310d9 validation: in invalidateblock, mark children as invalid right away (Martin Zumsande)
4c29326183ba3c9d0b198cb2cec37c3119862c19 validation: cache all headers with enough PoW in invalidateblock (Martin Zumsande)
15fa5b5a908d1019fc1b3042901b42bee0a1bd95 validation: call InvalidBlockFound also from AcceptBlock (Martin Zumsande)

Pull request description:

  Some fields in validation are set opportunistically by "best effort":
  - The `BLOCK_FAILED_CHILD` status (which means that the block index has an invalid predecessor)
  - `m_best_header` (the most-work header not known to be invalid).

  This means that there are known situations in which these fields are not set when they should be, or set to wrong values. This is tolerated because the fields are not used for anything consensus-critical and triggering these situations involved creating invalid blocks with valid PoW header, so would have a cost attached. Also, having stricter guarantees for these fields requires iterating over the entire block index, which has some DoS potential, especially with any header above the checkpoint being accepted int he past (see e.g. #11531).

  However, there are reasons to change this now:
  - RPCs use these fields and can report wrong results
  - There is the constant possibility that someone could add code that expects these fields to be correct, especially because it is not well documented that these fields cannot always be relied upon.
  - DoS concerns have become less of an issue after #25717 - now an attacker would need to invest much more work because they can't fork off the last checkpoint anymore

  This PR continues the work from #30666 to ensure that `BLOCK_FAILED_CHILD` status and `m_best_header` are always correct:
  - it adds a call to `InvalidChainFound()` in `AcceptBlock()`.
  - it adds checks for `BLOCK_FAILED_CHILD` and `m_best_header`  to `CheckBlockIndex()`. In order to be able to do this, the existing cache in the RPC-only `InvalidateBlock()` is adjusted to handle these as well. These are performance optimizations with the goal of avoiding having a call of `InvalidChainFound()` / looping over the block index after each disconnected block.
  I also wrote a fuzz test to find possible edge cases violating `CheckBlockIndex`, which I will PR separately soon.
  - it removes the `m_failed_blocks` set, which was a heuristic necessary when we couldn't be sure if a given block index had an invalid predecessor or not. Now that we have that guarantee, the set is no longer needed.

ACKs for top commit:
  stickies-v:
    re-ACK f6b782f3aad4a6bcf823a9a0fabb4418bca1eea1
  achow101:
    reACK f6b782f3aad4a6bcf823a9a0fabb4418bca1eea1
  ryanofsky:
    Code review ACK f6b782f3aad4a6bcf823a9a0fabb4418bca1eea1 with only minor code & comment updates
  TheCharlatan:
    Re-ACK f6b782f3aad4a6bcf823a9a0fabb4418bca1eea1

Tree-SHA512: 1bee324216eeee6af401abdb683abd098b18212833f9600dbc0a46244e634cb0e6f2a320c937a5675a12af7ec4a7d10fabc1db9e9bc0d9d0712e6e6ca72d084f
2025-06-11 16:17:22 -04:00
Ryan Ofsky
0a248708dc
indexes, refactor: Stop requiring CBlockIndex type to call IsBIP30Unspendable
This commit does not change behavior in any way.
2025-06-10 12:57:15 -04:00
Martin Zumsande
ee673b9aa0 validation: remove m_failed_blocks
After changes in previous commits, we now mark all blocks that descend from an invalid block
immediately as the block is found invalid. This happens both in the AcceptBlock
and ConnectBlock stages of block validation.
As a result, the pindexPrev->nStatus check in AcceptBlockHeader is now sufficient to detect
invalid blocks and checking m_failed_blocks there is no longer necessary.
2025-06-06 11:23:44 -04:00
Martin Zumsande
ed764ea2b4 validation: Add more checks to CheckBlockIndex()
This adds checks that
1) Descendants of invalid block indexes are also marked invalid
2) m_best_header cannot be invalid, and there can be no valid
block with more work than it.
2025-06-06 11:23:44 -04:00
Martin Zumsande
9a70883002 validation: in invalidateblock, calculate m_best_header right away
Before, m_best_header would be calculated only after disconnecting
multiple blocks, letting go of cs_main in the meantime.
This is in preparation for adding checks to CheckBlockIndex()
requiring that m_best_header is the most-work header not known to be invalid.

Co-authored-by: stringintech <stringintech@gmail.com>
2025-06-06 11:23:44 -04:00
Martin Zumsande
8e39f2d20d validation: in invalidateblock, mark children as invalid right away
Before, they would be marked as invalid only after disconnecting
multiple blocks, letting go of cs_main in the meantime.
This is in preparation for adding a check to
CheckBlockIndex() requiring that descendants of invalid block indexes
are always marked as invalid.
Entries from highpow_outofchain_headers are now only removed if made invalid,
no longer after inserting into setBlockIndexCandidates, because they
might still become invalid later in the second case.
This means that blocks could be inserted multiple times now into
setBlockIndexCandidates - this won't have any effect, so
behavior isn't changed.
2025-06-06 11:23:44 -04:00
Martin Zumsande
4c29326183 validation: cache all headers with enough PoW in invalidateblock
We now include blocks without HaveNumChainTxs() / lower validation status
than BLOCK_VALID_TRANSACTIONS. These checks are still performed at the
spot where we use the cache to insert into setBlockIndexCandidates.

This is in preparation for using the cache for more things than
just setBlockIndexCandidates candidates in the following commits.

Co-authored-by: stickies-v <stickies-v@protonmail.com>
2025-06-06 11:23:44 -04:00
Martin Zumsande
15fa5b5a90 validation: call InvalidBlockFound also from AcceptBlock
When a block it found invalid during acceptance (but before connection)
we now mark its descendants with BLOCK_FAILED_CHILD and update
m_best_header when these things weren't done reliably before.

This does not fix a serious bug because the flags and m_best_header were being set on a best-effort basis before
and not used for anything critical.
Setting these reliably has a slight performance cost (iterating over the
entire block index) but leads to more consistency in validation and allows removing m_failed_blocks in a later commit.
This can only be triggered by providing a block with sufficient PoW
that is otherwise invalid, so it is not a DoS vector.
2025-06-06 11:23:44 -04:00
fanquake
ee4406c04a
doc: update URLs
Some are now redirecting, some are outdated, i.e qt5.
2025-06-03 08:09:21 +01:00
Ava Chow
88b22acc3d
Merge bitcoin/bitcoin#32528: rpc: Round verificationprogress to 1 for a recent tip
fab1e02086ceebd7d96417b7a386fe61158bfda9 refactor: Pass verification_progress into block tip notifications (MarcoFalke)
fa76b378e4b218fb4853088328b9b488de18dcd2 rpc: Round verificationprogress to exactly 1 for a recent tip (MarcoFalke)
faf6304bdfdf228354b4072b72f4c0ef90fdaade test: Use mockable time in GuessVerificationProgress (MarcoFalke)

Pull request description:

  Some users really seem to care about this. While it shouldn't matter much, the diff is so trivial that it is probably worth doing.

  Fixes #31127

  One could also consider to split the field into two dedicated ones (https://github.com/bitcoin/bitcoin/issues/28847#issuecomment-1807115357), but this is left for a more involved follow-up and may also be controversial.

ACKs for top commit:
  achow101:
    ACK fab1e02086ceebd7d96417b7a386fe61158bfda9
  pinheadmz:
    ACK fab1e02086ceebd7d96417b7a386fe61158bfda9
  sipa:
    utACK fab1e02086ceebd7d96417b7a386fe61158bfda9

Tree-SHA512: a3c24e3c446d38fbad9399c1e7f1ffa7904490a3a7d12623b44e583b435cc8b5f1ba83b84d29c7ffaf22028bc909c7cec07202b825480449c6419d2a190938f5
2025-05-27 16:45:23 -07:00
Ava Chow
aee7cec0db
Merge bitcoin/bitcoin#32364: refactor: validation: mark CheckBlockIndex as const
3e6ac5bf772751c66cdcd015dcb7e6ce4ea2cc77 refactor: validation: mark CheckBlockIndex as const (stickies-v)
61a51eccbba1e7ccbdaac2bb7c74503bcf6fc9a5 validation: don't use GetAll() in CheckBlockIndex() (stickies-v)
d05481df644cc958cb309f20758bec996b8cfcfa refactor: validation: mark SnapshotBase as const (stickies-v)

Pull request description:

  While reviewing another PR, I [noticed](https://github.com/bitcoin/bitcoin/pull/31405#discussion_r2056509235) that `ChainstateManager::CheckBlockIndex()`  is not a `const` method. To try and assert that this method was not causing any side-effects, I modified the method to make it `const`. It did not surface any errors, but I think it would be good to merge this change regardless, even if `CheckBlockIndex` is only used in regtest.

  This PR removes `CheckBlockIndex()`'s calls to non-const `ChainstateManager` methods by marking `SnapshotBase` `const` and ~inlining the `GetAll()` calls (thereby also performing consistency checks on invalid or fully validated `m_disabled==true` chainstates, as slight behaviour change), and finally marks `CheckBlockIndex()` as `const`.

ACKs for top commit:
  achow101:
    ACK 3e6ac5bf772751c66cdcd015dcb7e6ce4ea2cc77
  mzumsande:
    Code Review ACK 3e6ac5bf772751c66cdcd015dcb7e6ce4ea2cc77
  TheCharlatan:
    ACK 3e6ac5bf772751c66cdcd015dcb7e6ce4ea2cc77

Tree-SHA512: 3d3cd351f5af1fab9a9498218ec62dba6e397fc7b5f4868ae0a77dc2b7c813d12c4f53f253f209101a3f6523695014e20c82dfac27cf0035611d5dd29feb80b5
2025-05-27 15:33:09 -07:00
MarcoFalke
fab1e02086
refactor: Pass verification_progress into block tip notifications
It is cheap to calculate and the caller does not have to take a lock to
calculate it.

Also turn pointers that can never be null into references.
2025-05-24 13:49:32 +02:00
Lőrinc
53e9b71b2f log: print reason for why should_write was triggered in FlushStateToDisk
Co-authored-by: Jon Atack <jon@atack.com>
2025-05-23 21:18:00 +02:00
merge-script
0a8ab55951
Merge bitcoin/bitcoin#32467: checkqueue: make the queue non-optional for CCheckQueueControl and drop legacy locking macro usage
fd290730f530a8b76a9607392f49830697cdd7c5 validation: clean up and clarify CheckInputScripts logic (Cory Fields)
1a37507895402ee08b1f248262701d4f848647e1 validation: use a lock for CCheckQueueControl (Cory Fields)
c3b0e6c7f4828291cd136717fddf1df878f3ca20 validation: make CCheckQueueControl's CCheckQueue non-optional (Cory Fields)
4c8c90b5567a3f31444bf0b151c3109e85ac2329 validation: only create a CCheckQueueControl if it's actually going to be used (Cory Fields)
11fed833b3ed6d5c96957de5addc4f903b2cee6c threading: add LOCK_ARGS macro (Cory Fields)

Pull request description:

  As part of an effort to cleanup our threading primitives and add safe `SharedMutex`/`SharedLock` impls, I'd like to get rid of the last of our legacy `ENTER_CRITICAL_SECTION`/`LEAVE_CRITICAL_SECTION` usage. This, along with a follow-up [after fixing REVERSE_LOCK](https://github.com/bitcoin/bitcoin/pull/32465) will allow us to do that.

  This replaces the old macros with an RAII lock, while simplifying `CCheckQueueControl`. It now requires a `CCheckQueue`, and optionality is handled externally. In the case of validation, it is wrapped in a `std::optional`.

  It also adds an `LOCK_ARGS` macro for `UniqueLock` initialization which may be helpful elsewhere.

ACKs for top commit:
  fjahr:
    re-ACK fd290730f530a8b76a9607392f49830697cdd7c5
  ryanofsky:
    Code review ACK fd290730f530a8b76a9607392f49830697cdd7c5, just removing assert since last review. Thanks for considering all the comments and feedback!
  TheCharlatan:
    Re-ACK fd290730f530a8b76a9607392f49830697cdd7c5

Tree-SHA512: 54b9db604ee1bda7d11bce1653a88d3dcbc4f525eed6a85abdd4d6409138674af4bb8b00afa4e0d3d29dadd045a3a39de253a45f0ef9c05f56cba1aac5b59303
2025-05-22 17:57:33 +01:00
Cory Fields
fd290730f5 validation: clean up and clarify CheckInputScripts logic
CheckInputScripts behaves differently depending on whether or not it was called
with a vector for checks. Make this difference clear by calling it differently
depending on whether or not control exists. Though more verbose, it should be
more straightforward to understand what's happening this way.

Also remove parallel_script_checks, as `if(control)` is a better test.

Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
2025-05-20 18:24:34 +00:00
MarcoFalke
fa76b378e4
rpc: Round verificationprogress to exactly 1 for a recent tip
This requires a new lock annotation, but all relevant callers already
held the lock.
2025-05-20 11:17:29 +02:00
MarcoFalke
faf6304bdf
test: Use mockable time in GuessVerificationProgress
Also add a test.
2025-05-20 11:16:35 +02:00
Cory Fields
c3b0e6c7f4 validation: make CCheckQueueControl's CCheckQueue non-optional
This simplifies the construction logic and will allow the constructor and
destructor to lock and unlock uncondiationally.
2025-05-19 22:06:48 +00:00
Cory Fields
4c8c90b556 validation: only create a CCheckQueueControl if it's actually going to be used
This will allow CCheckQueueControl to require a CCheckQueue.
2025-05-19 22:06:48 +00:00
Ryan Ofsky
f1d78a3087
Merge bitcoin/bitcoin#31624: doc: warn that CheckBlock() underestimates sigops
a04f17a1882407db09b0a07338e12877ac1d9e92 doc: warn that CheckBlock() underestimates sigops (Sjors Provoost)

Pull request description:

  Counting sigops in the witness requires context that `CheckBlock()`  does not have, so it only counts sigops for non-segwit transactions.

  It's useful to document, but it should not be a problem.

  The commit message contains some historical context.

ACKs for top commit:
  ismaelsadeeq:
    ACK a04f17a1882407db09b0a07338e12877ac1d9e92
  ryanofsky:
    Code review ACK a04f17a1882407db09b0a07338e12877ac1d9e92

Tree-SHA512: 26528367a7f3cfa8540ef0b90f7aa912c8f0bc057428f20a1fd1d4e232dac77747bc20044f0fcb0ffab8a2e1fb3dbe3dab46be749553a917744ddc7a829025cb
2025-05-14 10:05:41 -04:00
Sjors Provoost
a04f17a188
doc: warn that CheckBlock() underestimates sigops
Counting sigops in the witness and for p2sh requires
context that CheckBlock()  does not have, so it only
counts a subset of sigops.

The check here was introduced by Satoshi as a "cleanup" in
f1e1fb4bdef878c8fc1564fa418d44e7541a7e83. With the attempted
introduction of OP_EVAL, it was replaced by the check in
ConnectBlock(). Commit e679ec969c8b22c676ebb10bea1038f6c8f13b33
marked this code as a placeholder for backward compatibility.

Then when P2SH replaced OP_EVAL in 922e8e2929a2e78270868385aa46f96002fbcff3
the phrase "compatibility-breaking" was replaced by a simple
observation that before v0.6 this is how sigops were counted.

It's unclear why the check was kept and there were no review comments
about it.
2025-05-08 18:37:49 +02:00
stickies-v
3e6ac5bf77
refactor: validation: mark CheckBlockIndex as const
As a check/test method, this function should not mutate logical
state. Mark it as const to better help ensure this.
2025-05-06 14:29:49 +01:00
stickies-v
61a51eccbb
validation: don't use GetAll() in CheckBlockIndex()
GetAll() is non-const, preventing CheckBlockIndex() from being
const. Rather than add a const GetAll() method, just iterate over
the chainstates directly.

Slight behaviour change by also subjecting non-`IsUsable()`
chainstates to consistency checks.
2025-05-06 14:29:48 +01:00
Andrew Toth
c1e554d3e5 refactor: consolidate 3 separate locks into one block
The main lock needs to be taken 3 separate times.
It simplifies readability to take it once, and is more efficient.
2025-05-04 15:00:50 -04:00
Andrew Toth
84820561dc validation: periodically flush dbcache during reindex-chainstate
Move the periodic flush inside the outer loop of ActivateBestChain.
For very long activations, such as with reindex-chainstate, this
calls periodic flushes so progress can be saved to disk.

Co-Authored-By: l0rinc <pap.lorinc@gmail.com>
2025-05-04 13:23:14 -04:00
Ava Chow
5b8046a6e8
Merge bitcoin/bitcoin#30611: validation: write chainstate to disk every hour
e976bd3045010ee217aa0f2dca4c962aabb789d5 validation: add randomness to periodic write interval (Andrew Toth)
2e2f41068128c38120a5b44d24ee30f71970455a refactor: replace m_last_write with m_next_write (Andrew Toth)
b557fa7a175f139614932fbb3a4ad0af8271c73c refactor: rename fDoFullFlush to should_write (Andrew Toth)
d73bd9fbe483ad1397f62dc1d580314202351ace validation: write chainstate to disk every hour (Andrew Toth)
0ad7d7abdbcffc11a46413545a214a716f56dc95 test: chainstate write test for periodic chainstate flush (Andrew Toth)

Pull request description:

  Since #28233, periodically writing the chainstate to disk every 24 hours does not clear the dbcache. Since #28280, periodically writing the chainstate to disk is proportional only to the amount of dirty entries in the cache. Due to these changes, it is no longer beneficial to only write the chainstate to disk every 24 hours. The periodic flush interval was necessary because every write of the chainstate would clear the dbcache. Now, we can get rid of the periodic flush interval and simply write the chainstate along with blocks and block index at least every hour.

  Three benefits of doing this:
  1. For IBD or reindex-chainstate with a combination of large dbcache setting, slow CPU, slow internet speed/unreliable peers, it could be up to 24 hours until the chainstate is persisted to disk. A power outage or crash could potentially lose up to 24 hours of progress. If there is a very large amount of dirty cache entries, writing to disk when a flush finally does occur will take a very long time. Crashing during this window of writing can cause https://github.com/bitcoin/bitcoin/issues/11600. By syncing every hour in unison with the block index we avoid this problem. Only a maximum of one hour of progress can be lost, and the window for crashing during writing is much smaller. For IBD with lower dbcache settings, faster CPU, or better internet speed/reliable peers, chainstate writes are already triggered more often than every hour so this change will have no effect on IBD.
  2. Based on discussion in #28280, writing only once every 24 hours during long running operation of a node causes IO spikes. Writing smaller chainstate changes every hour like we do with blocks and block index will reduce IO spikes.
  3. Faster shutdown speeds. All dirty chainstate entries must be persisted to disk on shutdown. If we have a lot of dirty entries, such as when close to 24 hours or if we sync with a large dbcache, it can take a long time to shutdown. By keeping the chainstate clean we avoid this problem.

  Inspired by [this comment](https://github.com/bitcoin/bitcoin/pull/28280#issuecomment-2121088705).

  Resolves https://github.com/bitcoin/bitcoin/issues/11600

ACKs for top commit:
  achow101:
    ACK e976bd3045010ee217aa0f2dca4c962aabb789d5
  davidgumberg:
    utACK e976bd3045
  sipa:
    utACK e976bd3045010ee217aa0f2dca4c962aabb789d5
  l0rinc:
    ACK  e976bd3045010ee217aa0f2dca4c962aabb789d5

Tree-SHA512: 5bccd8f1dea47f9820a3fd32fe3bb6841c0167b3d6870cc8f3f7e2368f124af1a914bca6acb06889cd7183638a8dbdbace54d3237c3683f2b567eb7355e015ee
2025-05-01 12:11:55 -07:00
Andrew Toth
e976bd3045
validation: add randomness to periodic write interval
Co-Authored-By: Pieter Wuille <pieter@wuille.net>
Co-Authored-By: l0rinc <pap.lorinc@gmail.com>
2025-04-30 18:35:03 -04:00
Andrew Toth
2e2f410681
refactor: replace m_last_write with m_next_write
Co-Authored-By: l0rinc <pap.lorinc@gmail.com>
2025-04-30 18:33:43 -04:00
Andrew Toth
b557fa7a17 refactor: rename fDoFullFlush to should_write 2025-04-30 18:32:51 -04:00
Andrew Toth
d73bd9fbe4
validation: write chainstate to disk every hour
Remove the 24 hour periodic flush interval and
write the chainstate along with blocks and block
index every hour
2025-04-30 18:32:41 -04:00