47019 Commits

Author SHA1 Message Date
merge-script
938d7aacab Merge bitcoin/bitcoin#33657: rest: allow reading partial block data from storage
07135290c1 rest: allow reading partial block data from storage (Roman Zeyde)
4e2af1c065 blockstorage: allow reading partial block data from storage (Roman Zeyde)
f2fd1aa21c blockstorage: return an error code from `ReadRawBlock()` (Roman Zeyde)

Pull request description:

  It allows fetching specific transactions using an external index, following https://github.com/bitcoin/bitcoin/pull/32541#issuecomment-3267485313.

  Currently, electrs and other indexers map between an address/scripthash to the list of the relevant transactions.

  However, in order to fetch those transactions from bitcoind, electrs relies on reading the whole block and post-filtering for a specific transaction[^1]. Other indexers use a `txindex` to fetch a transaction using its txid [^2][^3][^4].

  The above approach has significant storage and CPU overhead, since the `txid` is a pseudo-random 32-byte value. Also, mainnet `txindex` takes ~60GB today.

  This PR is adding support for using the transaction's position within its block to be able to fetch it directly using [REST API](https://github.com/bitcoin/bitcoin/blob/master/doc/REST-interface.md), using the following HTTP request:

  ```
  GET /rest/blockpart/BLOCKHASH.bin?offset=OFFSET&size=SIZE
  ```

  - The offsets' index can be encoded much more efficiently ([~1.3GB today](https://github.com/romanz/bindex-rs/pull/66#issuecomment-3508476436)).

  - Address history query performance can be tested on mainnet using [1BitcoinEaterAddressDontSendf59kuE](https://mempool.space/address/1BitcoinEaterAddressDontSendf59kuE) - assuming warm OS block cache, [it takes <1s to fetch 5200 txs, i.e. <0.2ms per tx](https://github.com/romanz/bindex-rs/pull/66#issuecomment-3508476436) with [bindex](https://github.com/romanz/bindex-rs).

  - Only binary and hex response formats are supported.

  [^1]: https://github.com/romanz/electrs/blob/master/doc/schema.md
  [^2]: https://github.com/Blockstream/electrs/blob/new-index/doc/schema.md#txstore
  [^3]: https://github.com/spesmilo/electrumx/blob/master/docs/HOWTO.rst#prerequisites
  [^4]: https://github.com/cculianu/Fulcrum/blob/master/README.md#requirements

ACKs for top commit:
  maflcko:
    review ACK 07135290c1 🏪
  l0rinc:
    ACK 07135290c1
  hodlinator:
    re-ACK 07135290c1

Tree-SHA512: bcce7bf4b9a3e5e920ab5a83e656f50d5d7840cdde6b7147d329cf578f8a2db555fc1aa5334e8ee64d5630d25839ece77a2cf421c6c3ac1fa379bb453163bd4f
2025-12-12 13:22:00 +00:00
merge-script
597b8be223 Merge bitcoin/bitcoin#34025: net: Waste less time in socket handling
5f5c1ea019 net: Cache -capturemessages setting (Anthony Towns)
cea443e246 net: Pass time to InactivityChecks fuctions (Anthony Towns)

Pull request description:

  Cuts out some wasted time in net socket handling. First, only calculates the current time once every 50ms, rather than once for each peer, which given we only care about second-level precision seems more than adequate. Second, caches the value of the `-capturemessages` setting in `CConnman` rather than re-evaluating it every time we invoke `PushMessaage`.

ACKs for top commit:
  maflcko:
    review ACK 5f5c1ea019 🏣
  vasild:
    ACK 5f5c1ea019
  sedited:
    ACK 5f5c1ea019
  mzumsande:
    ACK 5f5c1ea019

Tree-SHA512: 0194143a3a4481c6355ac9eab27ce6ae4bed5db1d483ba5d06288dd92f195ccb9f0f055a9eb9d7e16e9bbf72f145eca1ff17c6700ee9aa42730103a8f047b32c
2025-12-12 10:49:59 +00:00
Ava Chow
d155fc12a0 Merge bitcoin/bitcoin#32414: validation: periodically flush dbcache during reindex-chainstate
c1e554d3e5 refactor: consolidate 3 separate locks into one block (Andrew Toth)
41479ed1d2 test: add test for periodic flush inside ActivateBestChain (Andrew Toth)
84820561dc validation: periodically flush dbcache during reindex-chainstate (Andrew Toth)

Pull request description:

  After #30611 we periodically do a non-erasing flush of the dbcache to disk roughly every hour during IBD.
  The intention was to also do this periodic flush during reindex-chainstate, so we would not risk losing progress during a system failure when reindexing with a high dbcache value.

  It was discovered that reindex-chainstate does not perform a PERIODIC flush until it has already reached the tip. Since reindexing to tip usually happens within 24 hours, this behaviour was unnoticed with the previous periodic flush interval. Note that reindex-chainstate still does IF_NEEDED flushes during `ConnectBlock`, so this also would not be noticed when running with a lower dbcache value.

  This patch moves the PERIODIC flush from after the outer loop in `ActivateBestChain` to inside the outer loop after we release `cs_main`. This will periodically flush during IBD, reindex-chainstate, and steady state.

ACKs for top commit:
  l0rinc:
    ACK c1e554d3e5
  achow101:
    ACK c1e554d3e5
  sipa:
    utACK c1e554d3e5

Tree-SHA512: c447ad03e16c9978b8ed2c285b38e1b4c56e7778ab93b6f64435116f47b8931017f5f56ab53eb61656693146aaced776f666af573a41ab28e8f2b6d8657fa756
2025-12-11 11:56:01 -08:00
Roman Zeyde
07135290c1 rest: allow reading partial block data from storage
It will allow fetching specific transactions using an external index,
following https://github.com/bitcoin/bitcoin/pull/32541#issuecomment-3267485313.

Co-authored-by: Hodlinator <172445034+hodlinator@users.noreply.github.com>
Co-authored-by: Lőrinc <pap.lorinc@gmail.com>
2025-12-11 19:02:56 +01:00
Roman Zeyde
4e2af1c065 blockstorage: allow reading partial block data from storage
It will allow fetching specific transactions using an external index,
following https://github.com/bitcoin/bitcoin/pull/32541#issuecomment-3267485313.

No logging takes place in case of an invalid offset/size (to avoid spamming the log),
by using a new `ReadRawError::BadPartRange` error variant.

Co-authored-by: Hodlinator <172445034+hodlinator@users.noreply.github.com>
Co-authored-by: Lőrinc <pap.lorinc@gmail.com>
2025-12-11 18:54:55 +01:00
Roman Zeyde
f2fd1aa21c blockstorage: return an error code from ReadRawBlock()
It will enable different error handling flows for different error types.

Also, `ReadRawBlockBench` performance has decreased due to no longer reusing a vector
with an unchanging capacity - mirroring our production code behavior.

Co-authored-by: Hodlinator <172445034+hodlinator@users.noreply.github.com>
Co-authored-by: Lőrinc <pap.lorinc@gmail.com>
2025-12-11 18:54:55 +01:00
merge-script
5be20c380d Merge bitcoin/bitcoin#34033: scripted-diff: Unify error and warning log formatting
fa89f60e31 scripted-diff: LogPrintLevel(*,BCLog::Level::*,*) -> LogError()/LogWarning() (MarcoFalke)
fa6c7a1954 scripted-diff: LogPrintLevel(*,BCLog::Level::Debug,*) -> LogDebug() (MarcoFalke)

Pull request description:

  Errors and warnings should normally not happen. However, if they do happen, it is easier to spot them, if they are all logged in the same format via `LogError` or `LogWarning`.

  So do that with a scripted-diff.

  This is a minimal behavior change and unifies the log output from:

      [net:error] Something bad happened
      [net:warning] Something problematic happened

  to either

      [error] Something bad happened
      [warning] Something problematic happened

  or, when `-loglevelalways=1` is enabled:

      [all:error] Something bad happened
      [all:warning] Something problematic happened

  Such a behavior change is desired, because all warning and error logs are written in the same style in the source code and they are logged in the same format for log consumers.

  Removing the category should be harmless, because warning and error messages should be descriptive and unique anyway.

ACKs for top commit:
  ajtowns:
    ACK fa89f60e31
  stickies-v:
    ACK fa89f60e31
  rkrux:
    lgtm code review ACK fa89f60e31

Tree-SHA512: dafa47ab561609a79005faf008fe188dd714f6e07bb2dfbe4db49290d6636b12eb7ac4a18ed32bcc5526641a9f258dbc37c08e10c223ec068b97976590ff0b52
2025-12-11 09:00:18 -08:00
merge-script
b31f786695 Merge bitcoin/bitcoin#34045: test: Log IP of download server in get_previous_releases.py
cdaf25f9c3 test: Log IP of download server in get_previous_releases.py (Ava Chow)

Pull request description:

  In order to help debug issues with previous release downloads from our web server, we need to know which IP the downloader connected to.

ACKs for top commit:
  fjahr:
    utACK cdaf25f9c3
  l0rinc:
    untested ACK cdaf25f9c3
  janb84:
    ACK cdaf25f9c3
  rkrux:
    tACK cdaf25f9c3
  glozow:
    ACK cdaf25f9c3

Tree-SHA512: 38b1ad5fe91b12fe5c4b71b35e3d66effb327c4515598b721a163f64a8efdd1e6237ff9f86c4897394d2c69c6e3a28ae4ba7ed9567a0e27ab6a6e90df8688b39
2025-12-11 08:36:05 -08:00
Ava Chow
b26762bdcb Merge bitcoin/bitcoin#33805: merkle: migrate path arg to reference and drop unused args
24ed820d4f merkle: remove unused `mutated` arg from `BlockWitnessMerkleRoot` (Lőrinc)
63d640fa6a merkle: remove unused `proot` and `pmutated` args from `MerkleComputation` (Lőrinc)
be270551df merkle: migrate `path` arg of `MerkleComputation` to a reference (Lőrinc)

Pull request description:

  ### Summary
  Simplifies merkle tree computation by removing dead code found through coverage analysis (following up on #33768 and #33786).

  ### History

  #### BlockWitnessMerkleRoot
  Original `MerkleComputation` was added in ee60e5625b (diff-706988c23877f8a557484053887f932b2cafb3b5998b50497ce7ff8118ac85a3R131) where it was called for either `&hash, mutated` or `position, &ret` args.
  In 1f0e7ca09c (diff-706988c23877f8a557484053887f932b2cafb3b5998b50497ce7ff8118ac85a3L135-L165) the first usage was inlined in `ComputeMerkleRoot`, leaving the `proot` and , `pmutated` values unused in `MerkleComputation`.
  Later in 4defdfab94 the method was moved to test and in 63d6ad7c89 (diff-706988c23877f8a557484053887f932b2cafb3b5998b50497ce7ff8118ac85a3R87-R95) was restored to the code, though with unused parameters again.

  #### BlockWitnessMerkleRoot
  `BlockWitnessMerkleRoot` was introduced in 8b49040854 where it was already called with `NULL` 8b49040854 (diff-34d21af3c614ea3cee120df276c9c4ae95053830d7f1d3deaf009a4625409ad2R3509) or an unused dummy 8b49040854 (diff-34d21af3c614ea3cee120df276c9c4ae95053830d7f1d3deaf009a4625409ad2R3598-R3599) for the `mutated` parameter.

  ### Fixes

  #### BlockWitnessMerkleRoot
  - Converts `path` parameter from pointer to reference (always non-null at call site)
  - Removes `proot` and `pmutated` parameters (always `nullptr` at call site)

  #### BlockWitnessMerkleRoot
  - Removes unused `mutated` output parameter (always passed as `nullptr`)

  The change is a refactor that shouldn't introduce *any* behavioral change, only remove dead code, leftovers from previous refactors.

  ### Coverage proof
  https://maflcko.github.io/b-c-cov/total.coverage/src/consensus/merkle.cpp.gcov.html

ACKs for top commit:
  optout21:
    utACK 24ed820d4f
  Sjors:
    utACK 24ed820d4f
  achow101:
    ACK 24ed820d4f
  sedited:
    ACK 24ed820d4f
  hodlinator:
    ACK 24ed820d4f

Tree-SHA512: 6960411304631bc381a3db7a682f6b6ba51bd58936ca85aa237c69a9109265b736b22ec4d891875bddfcbe8517bd3f014c44a4b387942eee4b01029c91ec93e1
2025-12-10 15:28:50 -08:00
Ava Chow
0f6d8a347a Merge bitcoin/bitcoin#30442: precalculate SipHash constant salt XORs
6eb5ba5691 refactor: extract shared `SipHash` state into `SipHashState` (Lőrinc)
118d22ddb4 optimization: cache `PresaltedSipHasher` in `CBlockHeaderAndShortTxIDs` (Lőrinc)
9ca52a4cbe optimization: migrate `SipHashUint256` to `PresaltedSipHasher` (Lőrinc)
ec11b9fede optimization: introduce `PresaltedSipHasher` for repeated hashing (Lőrinc)
20330548cf refactor: extract `SipHash` C0-C3 constants to class scope (Lőrinc)
9f9eb7fbc0 test: rename k1/k2 to k0/k1 in `SipHash` consistency tests (Lőrinc)

Pull request description:

  This change is part of [[IBD] - Tracking PR for speeding up Initial Block Download](https://github.com/bitcoin/bitcoin/pull/32043)

  ### Summary

  The in-memory representation of the UTXO set uses (salted) [SipHash](https://github.com/bitcoin/bitcoin/blob/master/src/coins.h#L226) to avoid key collision attacks.

  Hashing `uint256` keys is performed frequently throughout the codebase. Previously, specialized optimizations existed as standalone functions (`SipHashUint256` and `SipHashUint256Extra`), but the constant salting operations (C0-C3 XOR with keys) were recomputed on every call.

  This PR introduces `PresaltedSipHasher`, a class that caches the initial SipHash state (v0-v3 after XORing constants with keys), eliminating redundant constant computations when hashing multiple values with the same keys. The optimization is applied uniformly across:
  - All `Salted*Hasher` classes (`SaltedUint256Hasher`, `SaltedTxidHasher`, `SaltedWtxidHasher`, `SaltedOutpointHasher`)
  - `CBlockHeaderAndShortTxIDs` for compact block short ID computation

  ### Details

  The change replaces the standalone `SipHashUint256` and `SipHashUint256Extra` functions with `PresaltedSipHasher` class methods that cache the constant-salted state. This is particularly beneficial for hash map operations where the same salt is used repeatedly (as suggested by Sipa in https://github.com/bitcoin/bitcoin/pull/30442#issuecomment-2628994530).

  `CSipHasher` behavior remains unchanged; only the specialized `uint256` paths and callers now reuse the cached state instead of recomputing it.

  ### Measurements

  Benchmarks were run using local `SaltedOutpointHasherBench_*` microbenchmarks (not included in this PR) that exercise `SaltedOutpointHasher` in realistic `std::unordered_set` scenarios.

  <details>
  <summary>Benchmarks</summary>

  ```C++
  diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp
  --- a/src/bench/crypto_hash.cpp(revision 9b1a7c3e8d)
  +++ b/src/bench/crypto_hash.cpp(revision e1b4f056b3097e7e34b0eda31f57826d81c9d810)
  @@ -2,7 +2,6 @@
   // Distributed under the MIT software license, see the accompanying
   // file COPYING or http://www.opensource.org/licenses/mit-license.php.

  -
   #include <bench/bench.h>
   #include <crypto/muhash.h>
   #include <crypto/ripemd160.h>
  @@ -12,9 +11,11 @@
   #include <crypto/sha512.h>
   #include <crypto/siphash.h>
   #include <random.h>
  -#include <span.h>
   #include <tinyformat.h>
   #include <uint256.h>
  +#include <primitives/transaction.h>
  +#include <util/hasher.h>
  +#include <unordered_set>

   #include <cstdint>
   #include <vector>
  @@ -205,6 +206,98 @@
       });
   }

  +static void SaltedOutpointHasherBench_hash(benchmark::Bench& bench)
  +{
  +    FastRandomContext rng{/*fDeterministic=*/true};
  +    constexpr size_t size{1000};
  +
  +    std::vector<COutPoint> outpoints(size);
  +    for (auto& outpoint : outpoints) {
  +        outpoint = {Txid::FromUint256(rng.rand256()), rng.rand32()};
  +    }
  +
  +    const SaltedOutpointHasher hasher;
  +    bench.batch(size).run([&] {
  +        size_t result{0};
  +        for (const auto& outpoint : outpoints) {
  +            result ^= hasher(outpoint);
  +        }
  +        ankerl::nanobench::doNotOptimizeAway(result);
  +    });
  +}
  +
  +static void SaltedOutpointHasherBench_match(benchmark::Bench& bench)
  +{
  +    FastRandomContext rng{/*fDeterministic=*/true};
  +    constexpr size_t size{1000};
  +
  +    std::unordered_set<COutPoint, SaltedOutpointHasher> values;
  +    std::vector<COutPoint> value_vector;
  +    values.reserve(size);
  +    value_vector.reserve(size);
  +
  +    for (size_t i{0}; i < size; ++i) {
  +        COutPoint outpoint{Txid::FromUint256(rng.rand256()), rng.rand32()};
  +        values.emplace(outpoint);
  +        value_vector.push_back(outpoint);
  +        assert(values.contains(outpoint));
  +    }
  +
  +    bench.batch(size).run([&] {
  +        bool result{true};
  +        for (const auto& outpoint : value_vector) {
  +            result ^= values.contains(outpoint);
  +        }
  +        ankerl::nanobench::doNotOptimizeAway(result);
  +    });
  +}
  +
  +static void SaltedOutpointHasherBench_mismatch(benchmark::Bench& bench)
  +{
  +    FastRandomContext rng{/*fDeterministic=*/true};
  +    constexpr size_t size{1000};
  +
  +    std::unordered_set<COutPoint, SaltedOutpointHasher> values;
  +    std::vector<COutPoint> missing_value_vector;
  +    values.reserve(size);
  +    missing_value_vector.reserve(size);
  +
  +    for (size_t i{0}; i < size; ++i) {
  +        values.emplace(Txid::FromUint256(rng.rand256()), rng.rand32());
  +        COutPoint missing_outpoint{Txid::FromUint256(rng.rand256()), rng.rand32()};
  +        missing_value_vector.push_back(missing_outpoint);
  +        assert(!values.contains(missing_outpoint));
  +    }
  +
  +    bench.batch(size).run([&] {
  +        bool result{false};
  +        for (const auto& outpoint : missing_value_vector) {
  +            result ^= values.contains(outpoint);
  +        }
  +        ankerl::nanobench::doNotOptimizeAway(result);
  +    });
  +}
  +
  +static void SaltedOutpointHasherBench_create_set(benchmark::Bench& bench)
  +{
  +    FastRandomContext rng{/*fDeterministic=*/true};
  +    constexpr size_t size{1000};
  +
  +    std::vector<COutPoint> outpoints(size);
  +    for (auto& outpoint : outpoints) {
  +        outpoint = {Txid::FromUint256(rng.rand256()), rng.rand32()};
  +    }
  +
  +    bench.batch(size).run([&] {
  +        std::unordered_set<COutPoint, SaltedOutpointHasher> set;
  +        set.reserve(size);
  +        for (const auto& outpoint : outpoints) {
  +            set.emplace(outpoint);
  +        }
  +        ankerl::nanobench::doNotOptimizeAway(set.size());
  +    });
  +}
  +
   static void MuHash(benchmark::Bench& bench)
   {
       MuHash3072 acc;
  @@ -276,6 +369,10 @@
   BENCHMARK(SHA256_32b_AVX2, benchmark::PriorityLevel::HIGH);
   BENCHMARK(SHA256_32b_SHANI, benchmark::PriorityLevel::HIGH);
   BENCHMARK(SipHash_32b, benchmark::PriorityLevel::HIGH);
  +BENCHMARK(SaltedOutpointHasherBench_hash, benchmark::PriorityLevel::HIGH);
  +BENCHMARK(SaltedOutpointHasherBench_match, benchmark::PriorityLevel::HIGH);
  +BENCHMARK(SaltedOutpointHasherBench_mismatch, benchmark::PriorityLevel::HIGH);
  +BENCHMARK(SaltedOutpointHasherBench_create_set, benchmark::PriorityLevel::HIGH);
   BENCHMARK(SHA256D64_1024_STANDARD, benchmark::PriorityLevel::HIGH);
   BENCHMARK(SHA256D64_1024_SSE4, benchmark::PriorityLevel::HIGH);
   BENCHMARK(SHA256D64_1024_AVX2, benchmark::PriorityLevel::HIGH);

  ```

  </details>

  > cmake -B build -DBUILD_BENCH=ON -DCMAKE_BUILD_TYPE=Release && cmake --build build -j$(nproc) && build/bin/bench_bitcoin -filter='SaltedOutpointHasherBench' -min-time=10000

  > Before:

  |               ns/op |                op/s |    err% |     total | benchmark
  |--------------------:|--------------------:|--------:|----------:|:----------
  |               58.60 |       17,065,922.04 |    0.3% |     11.02 | `SaltedOutpointHasherBench_create_set`
  |               11.97 |       83,576,684.83 |    0.1% |     11.01 | `SaltedOutpointHasherBench_hash`
  |               14.50 |       68,985,850.12 |    0.3% |     10.96 | `SaltedOutpointHasherBench_match`
  |               13.90 |       71,942,033.47 |    0.4% |     11.03 | `SaltedOutpointHasherBench_mismatch`

  > After:

  |               ns/op |                op/s |    err% |     total | benchmark
  |--------------------:|--------------------:|--------:|----------:|:----------
  |               57.27 |       17,462,299.19 |    0.1% |     11.02 | `SaltedOutpointHasherBench_create_set`
  |               11.24 |       88,997,888.48 |    0.3% |     11.04 | `SaltedOutpointHasherBench_hash`
  |               13.91 |       71,902,014.20 |    0.2% |     11.01 | `SaltedOutpointHasherBench_match`
  |               13.29 |       75,230,390.31 |    0.1% |     11.00 | `SaltedOutpointHasherBench_mismatch`

  compared to master:
  ```python
  create_set - 17,462,299.19 / 17,065,922.04 - 2.3% faster
  hash       - 88,997,888.48 / 83,576,684.83 - 6.4% faster
  match      - 71,902,014.20 / 68,985,850.12 - 4.2% faster
  mismatch   - 75,230,390.31 / 71,942,033.47 - 4.5% faster
  ```

  > C++ compiler .......................... GNU 13.3.0

  > Before:

  |               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark
  |--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
  |              136.76 |        7,312,133.16 |    0.0% |        1,086.67 |          491.12 |  2.213 |         119.54 |    1.1% |     11.01 | `SaltedOutpointHasherBench_create_set`
  |               23.82 |       41,978,882.62 |    0.0% |          252.01 |           85.57 |  2.945 |           4.00 |    0.0% |     11.00 | `SaltedOutpointHasherBench_hash`
  |               60.42 |       16,549,695.42 |    0.1% |          460.51 |          217.04 |  2.122 |          21.00 |    1.4% |     10.99 | `SaltedOutpointHasherBench_match`
  |               78.66 |       12,713,595.35 |    0.1% |          555.59 |          282.52 |  1.967 |          20.19 |    2.2% |     10.74 | `SaltedOutpointHasherBench_mismatch`

  > After:

  |               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark
  |--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
  |              135.38 |        7,386,349.49 |    0.0% |        1,078.19 |          486.16 |  2.218 |         119.56 |    1.1% |     11.00 | `SaltedOutpointHasherBench_create_set`
  |               23.67 |       42,254,558.08 |    0.0% |          247.01 |           85.01 |  2.906 |           4.00 |    0.0% |     11.00 | `SaltedOutpointHasherBench_hash`
  |               58.95 |       16,962,220.14 |    0.1% |          446.55 |          211.74 |  2.109 |          20.86 |    1.4% |     11.01 | `SaltedOutpointHasherBench_match`
  |               76.98 |       12,991,047.69 |    0.1% |          548.93 |          276.50 |  1.985 |          20.25 |    2.3% |     10.72 | `SaltedOutpointHasherBench_mismatch`

  ```python
  compared to master:
  create_set -  7,386,349.49 / 7,312,133.16  - 1.0% faster
  hash       - 42,254,558.08 / 41,978,882.62 - 0.6% faster
  match      - 16,962,220.14 / 16,549,695.42 - 2.4% faster
  mismatch   - 12,991,047.69 / 12,713,595.35 - 2.1% faster
  ```

ACKs for top commit:
  achow101:
    ACK 6eb5ba5691
  vasild:
    ACK 6eb5ba5691
  sipa:
    ACK 6eb5ba5691

Tree-SHA512: 9688b87e1d79f8af9efc18a8487922c5f1735487a9c5b78029dd46abc1d94f05d499cd1036bd615849aa7d6b17d11653c968086050dd7d04300403ebd0e81210
2025-12-10 15:22:34 -08:00
Ava Chow
c2975f26d6 Merge bitcoin/bitcoin#33602: [IBD] coins: reduce lookups in dbcache layer propagation
0ac969cddf validation: don't reallocate cache for short-lived CCoinsViewCache (Lőrinc)
c8f5e446dc coins: reduce lookups in dbcache layer propagation (Lőrinc)

Pull request description:

  This change is part of [[IBD] - Tracking PR for speeding up Initial Block Download](https://github.com/bitcoin/bitcoin/pull/32043)

  ### Summary

  Previously, when the parent coins cache had no entry and the child did, `BatchWrite` performed a find followed by `try_emplace`, which resulted in multiple `SipHash` computations and bucket traversals on the common insert path.
  On a different path, these caches were recreated needlessly for every block connection.

  ### Fix for double fetch

  This change uses a single leading `try_emplace` and branches on the returned `inserted` flag. In the `FRESH && SPENT` case (not used in production, only exercised by tests), we erase the just-inserted placeholder (which is constant time with no rehash anyway). Semantics are unchanged for all valid parent/child state combinations.

  This change is a minimal version of [bitcoin/bitcoin@`723c49b` (#32128)](723c49b63b) and draws simplification ideas [bitcoin/bitcoin@`ae76ec7` (#30673)](ae76ec7bcf) and https://github.com/bitcoin/bitcoin/pull/30326.

  ### Fix for temporary cache recreation

  Related to parent cache propagation, the second commit makes it possible to avoid destructuring-recreating-destructuring of these short-live parent caches created for each new block.
  A few temporary `CCoinsViewCache`'s are destructed right after the `Flush()`, therefore it is not necessary to call `ReallocateCache` to recreate them right before they're killed anyway.

  This change was based on a subset of https://github.com/bitcoin/bitcoin/pull/28945, the original authors and relevant commenters were added as coauthors to this version.

  -----

  Reindex-chainstate indicates ~1% speedup.
  <details>
  <summary>Details</summary>

  ```python
  COMMITS="647cdb4f7e8041affed887e2325ee03a91078bb1 0b0c3293ffd75afb27dadc0b28426b40132a8c6b"; \
  STOP=909090; DBCACHE=4500; \
  CC=gcc; CXX=g++; \
  BASE_DIR="/mnt/my_storage"; DATA_DIR="$BASE_DIR/BitcoinData"; LOG_DIR="$BASE_DIR/logs"; \
  (echo ""; for c in $COMMITS; do git fetch -q origin $c && git log -1 --pretty='%h %s' $c || exit 1; done; echo "") && \
  hyperfine \
    --sort command \
    --runs 2 \
    --export-json "$BASE_DIR/rdx-$(sed -E 's/(\w{8})\w+ ?/\1-/g;s/-$//'<<<"$COMMITS")-$STOP-$DBCACHE-$CC.json" \
    --parameter-list COMMIT ${COMMITS// /,} \
    --prepare "killall bitcoind 2>/dev/null; rm -f $DATA_DIR/debug.log; git checkout {COMMIT}; git clean -fxd; git reset --hard && \
      cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DENABLE_IPC=OFF && ninja -C build bitcoind && \
      ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=1000 -printtoconsole=0; sleep 20" \
    --cleanup "cp $DATA_DIR/debug.log $LOG_DIR/debug-{COMMIT}-$(date +%s).log" \
    "COMPILER=$CC ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=$DBCACHE -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0"

  647cdb4f7e Merge bitcoin/bitcoin#33311: net: Quiet down logging when router doesn't support natpmp/pcp
  0b0c3293ff validation: don't reallocate cache for short-lived CCoinsViewCache

  Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=909090 -dbcache=4500 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 647cdb4f7e)
    Time (mean ± σ):     16233.508 s ±  9.501 s    [User: 19064.578 s, System: 951.672 s]
    Range (min … max):   16226.790 s … 16240.226 s    2 runs

  Benchmark 2: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=909090 -dbcache=4500 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 0b0c3293ffd75afb27dadc0b28426b40132a8c6b)
    Time (mean ± σ):     16039.626 s ± 17.284 s    [User: 18870.130 s, System: 950.722 s]
    Range (min … max):   16027.405 s … 16051.848 s    2 runs

  Relative speed comparison
          1.01 ±  0.00  COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=909090 -dbcache=4500 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 647cdb4f7e)
          1.00          COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=909090 -dbcache=4500 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 0b0c3293ffd75afb27dadc0b28426b40132a8c6b)
  ```

  </details>

ACKs for top commit:
  optout21:
    utACK 0ac969cddf
  achow101:
    ACK 0ac969cddf
  andrewtoth:
    utACK 0ac969cddf
  sedited:
    ACK 0ac969cddf

Tree-SHA512: 9fcc3f1a8314368576a4fba96ca72665527eaa3a97964ab5b39491757f3527147d134f79a5c3456f76c1330c7ef862989d23f764236c5e2563be89a81c1cee47
2025-12-10 15:02:25 -08:00
Ava Chow
cdaf25f9c3 test: Log IP of download server in get_previous_releases.py 2025-12-10 13:49:11 -08:00
merge-script
c1f0a89d9c Merge bitcoin/bitcoin#34040: test: Detect truncated download in get_previous_releases.py
fa75480c84 test: Detect truncated download in get_previous_releases.py (MarcoFalke)

Pull request description:

  Without this, and end-of-stream is not detected and will just lead to an immediate exit, instead of a re-try.

  E.g. https://github.com/bitcoin/bitcoin/actions/runs/20089133013/job/57633839315?pr=34038#step:12:201:

  ```
  ...
  Downloading: [##--------------------------------------] 5.4%
  Downloading: [##--------------------------------------] 5.4%
  Downloading: [##--------------------------------------] 5.5%
  Downloading: [##--------------------------------------] 5.6%
  Checksum dd02eab18f9154604e38135ef3f98fd310ba3c748074aeb83a71118cd2cd1367 did not match
  Error: Process completed with exit code 1.
  ```

  Also, remove the `0` fallback value, because if the fallback was ever hit, the program would fail anyway with `division by zero` error.

ACKs for top commit:
  Sjors:
    utACK fa75480c84
  rkrux:
    Looks fine, ACK fa75480c84
  l0rinc:
    code review ACK fa75480c84

Tree-SHA512: 230eaf155701ed833636b401118f11ff5c6521c61bf4f3a01fcf390a71a508ba6a570eea855ef659134e118b74f75e3d5772ec8a261db23ebfe4ac7ec87cab5a
2025-12-10 16:40:54 +00:00
MarcoFalke
fa75480c84 test: Detect truncated download in get_previous_releases.py 2025-12-10 13:35:22 +01:00
merge-script
56ce78d5f6 Merge bitcoin/bitcoin#34031: net: Remove "tor" as a network specification
e7ac5a133c doc: add release note for 34031 (fanquake)
c4c70a256e netbase: Remove "tor" as a network specification (Carl Dong)

Pull request description:

  "tor" as a network specification was deprecated in 60dc8e4208 in favor of "onion"
  and this commit removes it and updates the relevant test.

  Previously #16029. This has been warning as being deprecated since `v0.17.0`.

  This PR only removes the already deprecated usage of tor as a network specification, the use of tor throughout the codebase, is not deprecated.

ACKs for top commit:
  davidgumberg:
    crACK e7ac5a133c
  laanwj:
    Code review ACK e7ac5a133c
  janb84:
    ACK e7ac5a133c
  stickies-v:
    ACK e7ac5a133c

Tree-SHA512: f211dec151c21728b4cd2b1716ee68907871beaa85d8c89e2bc17576e701d03c03e5455593de94970d787aa3264fab60d8c6debeeff908e00d8feb48804692e9
2025-12-10 11:51:01 +00:00
merge-script
500862b2d4 Merge bitcoin/bitcoin#33423: qa: Improvements to debug_assert_log + busy_wait_for_debug_log
a1f7623020 qa: Only complain about expected messages that were not found (Hodlinator)
1e54125e2e refactor(qa): Avoid unnecessary string operations (Hodlinator)
a9021101dc qa: Replace always-escaped regexps with "X in Y" (Hodlinator)
5c16e4631c doc: Remove no longer correct comment (Hodlinator)

Pull request description:

  * Remove incorrect docstring in `busy_wait_for_debug_log()`.
  * Replace nerfed regex searches with `X in Y` expressions.
  * Only compute the log string to be printed on failure *when we actually fail* instead of every 0.05s.
  * As we find each needle (expected message) in the haystack (log output), stop searching for it. **If we fail and time out, we will only complain about the needles (expected messages) we didn't find. On master we also include found needles, which is less helpful.**

  Found while developing a new test case in https://github.com/bitcoin/bitcoin/pull/33336#discussion_r2351892330

ACKs for top commit:
  l0rinc:
    Code review ACK a1f7623020
  maflcko:
    review ACK a1f7623020 💨

Tree-SHA512: 191ea7647b0ea8b4220e37c62d176861c2fd0e3737aee3641b262915d9118f48953cf1204767c93a93a8fc78a44c2c29206fb390b44c59d99fc2aa7d12bf4889
2025-12-10 11:40:59 +00:00
Anthony Towns
5f5c1ea019 net: Cache -capturemessages setting 2025-12-10 06:51:47 +10:00
merge-script
cca113f5b0 Merge bitcoin/bitcoin#34008: log: don't rate-limit "new peer" with -debug=net
d4d184eda9 log: don't rate-limit "new peer" with -debug=net (0xb10c)

Pull request description:

  Previously, when `debug=net` is enabled, we log "New [..] peer connected" for new inbound peers with `LogInfo`. However, `LogInfo` will get rate-limited since https://github.com/bitcoin/bitcoin/pull/32604. When we specifically turn on `debug=net`, we don't want these log messages to be rate-limited.

  To fix this, use `LogDebug(BCLog::NET, ...)` for potentially high-rate inbound connections. Otherwise use `LogInfo`. This means we don't rate-limit the messages for inbound peers when `debug=net` is turned on but will rate-limit if we created outbound at a high rate as these are logged via `LogInfo`.

  The new log messages look similar to:
  ```
  2025-12-08T00:00:00Z [net] New inbound peer connected: transport=v2 version=70016 blocks=0 peer=1
  2025-12-08T00:00:00Z New outbound-full-relay peer connected: transport=v2 version=70016 blocks=281738 peer=5
  ```

  --

  I ran into this message getting rate-limited on one of my monitoring nodes with `-logsourcelocations=1`: With logsourcelocations, one of these lines is about 338 chars (or 338 bytes) long. We rate-limit after more than 1048576 bytes per hour, which results in about 3100 in- and outbound connections per hour. With evicted and instantly reconnecting connections from an entity like LinkingLion, this can be reached fairly quickly.

ACKs for top commit:
  stickies-v:
    utACK d4d184eda9
  Crypt-iQ:
    tACK d4d184eda9
  maflcko:
    review ACK d4d184eda9 🚲
  rkrux:
    lgtm code review ACK d4d184eda9
  glozow:
    lgtm ACK d4d184eda9

Tree-SHA512: 14dbf693fa44a74c9822590e7a08167d2deeb1bc6f4b8aeb00c1b035c0df7101087d5c80a3c0d637879d5c52f88b30f0cb4c0577cff6f647d2eb3300f49d8ea3
2025-12-09 11:16:12 -08:00
merge-script
2c44c41984 Merge bitcoin/bitcoin#33553: validation: Improve warnings in case of chain corruption
4b47113698 validation: Reword CheckForkWarningConditions and call it also during IBD and at startup (Martin Zumsande)
2f51951d03 p2p: Add warning message when receiving headers for blocks cached as invalid (Martin Zumsande)

Pull request description:

  In case of corruption that leads to a block being marked as invalid that is seen as valid by the rest of the network, the user currently doesn't receive good error messages, but will often be stuck in an endless headers-sync loop with no explanation (#26391).

  This PR improves warnings in two ways:
  - When we receive a header that is already saved in our disk, but invalid, add a warning. This will happen repeatedly during the headerssync loop (see https://github.com/bitcoin/bitcoin/issues/26391#issuecomment-1291765534 on how to trigger it artificially).
  - Removes the IBD check from `CheckForkWarningConditions` and adds a call to the function during init (`LoadChainTip()`). The existing check was added in 55ed3f1475 a long time ago when we had more sophisticated fork detection that could lead to false positives during IBD, but that  logic was removed in fa62304c97 so that I don't see a reason to suppress the warning anymore.

  Fixes #26391 (We'll still do the endless looping, trying to find a peer with a headers that we can use, but will now repeatedly log warnings while doing so).

ACKs for top commit:
  glozow:
    ACK `git range-diff 6d2c8ea9dbd77c71051935b5ab59224487509559...4b4711369880369729893ba7baef11ba2a36cf4b`
  theStack:
    re-ACK 4b47113698
  sedited:
    ACK 4b47113698

Tree-SHA512: 78bc53606374636d616ee10fdce0324adcc9bcee2806a7e13c9471e4c02ef00925ce6daef303bc153b7fcf5a8528fb4263c875b71d2e965f7c4332304bc4d922
2025-12-09 08:25:17 -08:00
Lőrinc
6eb5ba5691 refactor: extract shared SipHash state into SipHashState
Split the repeated `SipHash` v[0..3] initialization into a small `SipHashState` helper that is used by both `CSipHasher` and `PresaltedSipHasher`.

Added explanatory comments to clarify behavior, documenting the equivalence of `PresaltedSipHasher` `operator()` overloads to `CSipHasher` usage.

Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
2025-12-09 17:17:47 +01:00
Lőrinc
118d22ddb4 optimization: cache PresaltedSipHasher in CBlockHeaderAndShortTxIDs
Replaces separate `shorttxidk0`/`shorttxidk1` members with a cached `PresaltedSipHasher`, so `GetShortID()` reuses the precomputed `SipHash` state instead of rebuilding it on every call.

`CBlockHeaderAndShortTxIDs` was never intended to be used before `FillShortTxIDSelector()` runs; doing so already relied on indeterminate salt values.
The new `Assert(m_hasher)` just makes this invariant explicit and fails fast if the object is used in an uninitialized state.
2025-12-09 17:16:17 +01:00
Lőrinc
9ca52a4cbe optimization: migrate SipHashUint256 to PresaltedSipHasher
Replaces standalone `SipHashUint256` with an `operator()` overload in `PresaltedSipHasher`.
Updates all hasher classes (`SaltedUint256Hasher`, `SaltedTxidHasher`, `SaltedWtxidHasher`) to use `PresaltedSipHasher` internally, enabling the same constant-state caching optimization while keeping behavior unchanged.

Benchmark was also adjusted to cache the salting part.
2025-12-09 17:16:15 +01:00
Lőrinc
ec11b9fede optimization: introduce PresaltedSipHasher for repeated hashing
Replaces the `SipHashUint256Extra` function with the `PresaltedSipHasher` class that caches the constant-salted state (v[0-3] after XORing with keys).
This avoids redundant XOR operations when hashing multiple values with the same keys, benefiting use cases like `SaltedOutpointHasher`.

This essentially brings the precalculations in the `CSipHasher` constructor to the `uint256`-specialized SipHash implementation.

> cmake -B build -DBUILD_BENCH=ON -DCMAKE_BUILD_TYPE=Release && cmake --build build -j$(nproc) && build/src/bench/bench_bitcoin -filter='SaltedOutpointHasherBench.*' -min-time=10000

> C++ compiler .......................... AppleClang 16.0.0.16000026

|               ns/op |                op/s |    err% |     total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
|               57.27 |       17,462,299.19 |    0.1% |     11.02 | `SaltedOutpointHasherBench_create_set`
|               11.24 |       88,997,888.48 |    0.3% |     11.04 | `SaltedOutpointHasherBench_hash`
|               13.91 |       71,902,014.20 |    0.2% |     11.01 | `SaltedOutpointHasherBench_match`
|               13.29 |       75,230,390.31 |    0.1% |     11.00 | `SaltedOutpointHasherBench_mismatch`

compared to master:
create_set - 17,462,299.19/17,065,922.04 - 2.3% faster
hash       - 88,997,888.48/83,576,684.83 - 6.4% faster
match      - 71,902,014.20/68,985,850.12 - 4.2% faster
mismatch   - 75,230,390.31/71,942,033.47 - 4.5% faster

> C++ compiler .......................... GNU 13.3.0

|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
|              135.38 |        7,386,349.49 |    0.0% |        1,078.19 |          486.16 |  2.218 |         119.56 |    1.1% |     11.00 | `SaltedOutpointHasherBench_create_set`
|               23.67 |       42,254,558.08 |    0.0% |          247.01 |           85.01 |  2.906 |           4.00 |    0.0% |     11.00 | `SaltedOutpointHasherBench_hash`
|               58.95 |       16,962,220.14 |    0.1% |          446.55 |          211.74 |  2.109 |          20.86 |    1.4% |     11.01 | `SaltedOutpointHasherBench_match`
|               76.98 |       12,991,047.69 |    0.1% |          548.93 |          276.50 |  1.985 |          20.25 |    2.3% |     10.72 | `SaltedOutpointHasherBench_mismatch`

compared to master:
create_set -  7,386,349.49/7,312,133.16  - 1% faster
hash       - 42,254,558.08/41,978,882.62 - 0.6% faster
match      - 16,962,220.14/16,549,695.42 - 2.4% faster
mismatch   - 12,991,047.69/12,713,595.35 - 2% faster

Co-authored-by: sipa <pieter@wuille.net>
2025-12-09 17:13:44 +01:00
merge-script
d23d49ee3f Merge bitcoin/bitcoin#31823: tests: Add witness commitment if we have a witness transaction in FullBlockTest.update_block()
a7c96f874d tests: Add witness commitment if we have a witness transaction in FullBlockTest.update_block() (Chris Stewart)

Pull request description:

  This is useful for test cases where we want to test logic invalid blocks that contain witness transactions. If we don't add the witness commitment as per [BIP141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#user-content-Commitment_structure), blocks will be rejected with the error [`Block mutated`](fb0ada982a/src/validation.cpp (L4180)).

  This change was needed in https://github.com/ajtowns/bitcoin/pull/13 which is a soft fork proposal to disallow 64 byte transactions. We want to test that 64 byte transactions serialized without the witness are invalid. If we do not have this change, we cannot directly test the logic that rejects 64 byte transactions.

  I decided to PR this upstream as many soft fork proposals may not see the light of day, but this functionality seems strictly additive to the test framework.

ACKs for top commit:
  theStack:
    ACK a7c96f874d
  sedited:
    ACK a7c96f874d
  glozow:
    ACK a7c96f874d

Tree-SHA512: 7c185838abaf068bc96b425c3c971b73f75dfcb41dacc8b2f2543c7602f23f19d908633278b93738f18049e6bd8c845c152cfb93b289bef501c7e86ed8dae0ab
2025-12-09 08:11:13 -08:00
Lőrinc
20330548cf refactor: extract SipHash C0-C3 constants to class scope
Moves the `SipHash` initialization constants (C0-C3) from magic numbers to named static constexpr members of `CSipHasher`.
2025-12-09 17:03:18 +01:00
Lőrinc
9f9eb7fbc0 test: rename k1/k2 to k0/k1 in SipHash consistency tests
Aligns test variable naming with the `k0`/`k1` convention used consistently throughout the codebase for `SipHash` keys.
Also splits the single-param `SipHash` test from the one with extra, for clarity.
2025-12-09 17:03:18 +01:00
merge-script
29ed608dc7 Merge bitcoin/bitcoin#33961: script: Add a separate ScriptError for empty pubkeys encountered in Tapscript
9d5021a05b script: add SCRIPT_ERR_TAPSCRIPT_EMPTY_PUBKEY (billymcbip)

Pull request description:

  We currently have two callsites for `SCRIPT_ERR_PUBKEYTYPE`:
  - A pre-tapscript policy error behind the `SCRIPT_VERIFY_STRICTENC` flag: 4de26b111f/src/script/interpreter.cpp (L220)
  - A [consensus error](https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki?plain=1#L93) in Tapscript: 4de26b111f/src/script/interpreter.cpp (L368)

  It would be good for readability and testability to have separate errors for both cases, as they are quite distinct (policy vs. consensus, format vs. emptiness).

  **This PR adds `SCRIPT_ERR_TAPSCRIPT_EMPTY_PUBKEY` for the consensus error path.**

  This change would make our error handling more consistent. We have more granular errors for other pubkey error paths already: `SCRIPT_ERR_WITNESS_PUBKEYTYPE`,  `SCRIPT_ERR_DISCOURAGE_UPGRADABLE_PUBKEYTYPE`. We also have separate errors for MINIMAL_IF: `SCRIPT_ERR_MINIMALIF` for the policy error pre-tapscript, and `SCRIPT_ERR_TAPSCRIPT_MINIMALIF` for the consensus error post-tapscript.

  Tests:

  Added a test case to `script_tests` and ran `build/bin/test_bitcoin --run_test=script_tests --log_level=success`.
  ```
  test/script_tests.cpp:144: info: check '[["aa","#SCRIPT# 0 CHECKSIG","#CONTROLBLOCK#",0.00000001],"","0x51 0x20 #TAPROOTOUTPUT#","P2SH,WITNESS,TAPROOT","TAPSCRIPT_EMPTY_PUBKEY","TAPSCRIPT: OP_CHECKSIG with empty pubkey must fail"] (with flags 165d5d)' has passed
  ...
  ```

  Ran `DIR_UNIT_TEST_DATA="$(pwd)/../qa-assets/unit_test_data" build/bin/test_bitcoin --run_test=script_assets_tests --log_level=success`.

  Updated `feature_taproot.py` and ran `build/test/functional/feature_taproot.py`.

  Looking forward to your feedback.

ACKs for top commit:
  sedited:
    ACK 9d5021a05b
  darosior:
    utACK 9d5021a05b
  sipa:
    ACK 9d5021a05b

Tree-SHA512: bc0b7f64454313fe392ffb2d23aa4eca3deadc5ea1d10b3fba0b3ab4cb0575a5ddcb002dc27b4fa7aa3c180840a83d1b3e5c89351009ce7ffe684d58e1980ace
2025-12-09 08:01:49 -08:00
merge-script
d2a199bca7 Merge bitcoin/bitcoin#33909: doc, ci: Make the max number of commits tested explicit
b5a7a685bb ci: Make the max number of commits tested explicit (Hodlinator)

Pull request description:

  Gives less of a false sense of security.

ACKs for top commit:
  maflcko:
    lgtm ACK b5a7a685bb
  rkrux:
    crACK b5a7a685bb
  janb84:
    ACK b5a7a685bb
  glozow:
    lgtm ACK b5a7a685bb

Tree-SHA512: 9f50a86f440d6a551a0c1ff547e61b61b829e98cd0cd2d5ca65966af0b48d40582f698bcb039a7467c4b71166920413c334eac0e9e4f0141c3e02cd68555865b
2025-12-09 07:51:44 -08:00
merge-script
dbc8928069 Merge bitcoin/bitcoin#33993: init: point out -stopatheight may be imprecise
ff06e2468a init: point out -stopatheight may be imprecise (brunoerg)

Pull request description:

  `-stopatheight` is used to stop running bitcoind after reaching a given height. However, this feature is imprecise since some blocks can still be processed during the shutdown.

  There are some previous discussions around it in https://github.com/bitcoin/bitcoin/pull/13713, https://github.com/bitcoin/bitcoin/pull/13490 and https://github.com/bitcoin/bitcoin/issues/13477. However, I'm not sure if it will get fixed since it's undesirable to burden the validation code further with this and we can bypass this behavior by using `invalidateblock` to wind back. Anyway, since at this moment its behavior is imprecise I think worth mentioning it in documentation.

ACKs for top commit:
  rkrux:
    re-ACK ff06e2468a
  stickies-v:
    ACK ff06e2468a
  pablomartin4btc:
    ACK ff06e2468a
  jaonoctus:
    re-ACK ff06e2468a

Tree-SHA512: 222d5e89021d5f9a7ce0edca44c4ce20b13f71832413dccea78ad40a01f2a615a061f8cf446d7290ed911023922adbc6fa22f0c88cff306dcd8b4ae14194e9b8
2025-12-09 07:39:46 -08:00
0xb10c
d4d184eda9 log: don't rate-limit "new peer" with -debug=net
Previously, when `debug=net` is enabled, we log "New [..] peer connected"
for new inbound peers with `LogInfo`. However, `LogInfo` will get
rate-limited since https://github.com/bitcoin/bitcoin/pull/32604.
When we specifically turn on `debug=net`, we don't want these log
messages to be rate-limited.

To fix this, use `LogDebug(BCLog::NET, ...)` for potentially high-
rate inbound connections. Otherwise use `LogInfo`. This means we
don't rate-limit the messages for inbound peers when `debug=net`
is turned on but will rate-limit if we created outbound at a high
rate as these are logged via `LogInfo`.

--

I ran into this message getting rate-limited on one of my monitoring
nodes with `-logsourcelocations=1`: With logsourcelocations, one of
these lines is about 338 chars (or 338 bytes) long. We rate-limit
after more than 1048576 bytes per hour, which results in about
3100 in- and outbound connections per hour. With evicted and
instantly reconnecting connections from an entity like LinkingLion,
this can be reached fairly quickly.

Co-Authored-By: Eugene Siegel <elzeigel@gmail.com>
Co-Authored-By: Anthony Towns <aj@erisian.com.au>
2025-12-09 13:05:16 +01:00
fanquake
e7ac5a133c doc: add release note for 34031 2025-12-09 10:13:07 +00:00
Carl Dong
c4c70a256e netbase: Remove "tor" as a network specification
"tor" as a network specification was deprecated in 60dc8e4208 in favor
of "onion" and this commit removes it and updates the relevant test.

Co-authored-by: Mara van der Laan <126646+laanwj@users.noreply.github.com>
2025-12-09 10:12:32 +00:00
MarcoFalke
fa89f60e31 scripted-diff: LogPrintLevel(*,BCLog::Level::*,*) -> LogError()/LogWarning()
This is a minimal behavior change and changes log output from:

  [net:error] Something bad happened
  [net:warning] Something problematic happened

to either

  [error] Something bad happened
  [warning] Something problematic happened

or, when -loglevelalways=1 is enabled:

  [all:error] Something bad happened
  [all:warning] Something problematic happened

Such a behavior change is desired, because all warning and error logs
are written in the same style in the source code and they are logged in
the same format for log consumers.

-BEGIN VERIFY SCRIPT-

 sed --regexp-extended --in-place \
   's/LogPrintLevel\((BCLog::[^,]*), BCLog::Level::(Error|Warning), */Log\2(/g' \
   $( git grep -l LogPrintLevel ':(exclude)src/test/logging_tests.cpp' )

-END VERIFY SCRIPT-
2025-12-09 10:44:33 +01:00
MarcoFalke
fa6c7a1954 scripted-diff: LogPrintLevel(*,BCLog::Level::Debug,*) -> LogDebug()
This refactor does not change behavior.

-BEGIN VERIFY SCRIPT-

 sed --regexp-extended --in-place \
   's/LogPrintLevel\((BCLog::[^,]*), BCLog::Level::Debug,/LogDebug(\1,/g' \
   $( git grep -l LogPrintLevel ':(exclude)src/test/logging_tests.cpp' )

-END VERIFY SCRIPT-
2025-12-09 10:44:29 +01:00
Ryan Ofsky
d5c8199b79 Merge bitcoin/bitcoin#34006: Add util::Expected (std::expected)
faa23738fc refactor: Enable clang-tidy bugprone-unused-return-value (MarcoFalke)
fa114be27b Add util::Expected (std::expected) (MarcoFalke)

Pull request description:

  Some low-level code could benefit from being able to use `std::expected` from C++23:

  * Currently, some code is using `std::optional<E>` to denote an optional error. This is fine, but a bit confusing, because `std::optional` is normally used for values, not errors. Using `std::expected<void, E>` is clearer.
  * Currently, some code is using `std::variant<V, E>` to denote either a value or an error. This is fine, but a bit verbose, because `std::variant` requires a visitor or get_if/holds_alternative instead of a simple call of the `operator bool` for `std::expected`.

  In theory, `util::Result` could be taught to behave similar to `std::expected` (see https://github.com/bitcoin/bitcoin/pull/34005). However, it is unclear if this is the right approach:

  * `util::Result` is mostly meant for higher level code, where errors come with translated error messages.
  * `std::expected` is mostly meant for lower level code, where errors could be an enum, or any other type.
  * https://github.com/bitcoin/bitcoin/pull/25665 aims to minimize the memory footprint of the error by wrapping it in a unique_ptr internally. `std::expected` requires the value and error to be "nested within it" (https://cplusplus.github.io/LWG/issue4141). So from a memory-layout perspective, the two are not compatible.
  * `std::expected` also comes with `std::unexpected`, which also does not map cleanly to `util::Result`.

  So just add a minimal drop-in port of `std::expected`.

ACKs for top commit:
  romanz:
    tACK faa23738fc
  sedited:
    Re-ACK faa23738fc
  hodlinator:
    ACK faa23738fc
  rkrux:
    light Code Review ACK faa23738fc
  ryanofsky:
    Code review ACK faa23738fc, only adding `value_or` implementation and `CheckedReturnTypes` clang-tidy commit since last review.
  stickies-v:
    ACK faa23738fc

Tree-SHA512: fdbd0f6bf439738ffe6a68da5522f1051537f8df9c308eb90bef6bd2e06931d79f1c5da22d5500765e9cb1d801d5be39e11e10d47c9659fec1a8c8804cb7c872
2025-12-08 20:11:51 -05:00
merge-script
77248e8496 Merge bitcoin/bitcoin#33771: refactor: C++20 operators
48840bfc2d refactor: Prefer `<=>` over multiple relational operators (Daniel Pfeifer)
5a0f49bd26 refactor: Remove all `operator!=` definitions (Daniel Pfeifer)

Pull request description:

  Remove all `operator!=` definitions and provide `operator<=>` as a replacement where all relational comparison operators were defined before.

  The compiler is able to deduce missing comparison operators from `operator!=` and `operator<=>`. The compiler provided operators have the following advantages:

  1. less code
  2. guaranteed consistency

  Refactoring that changes the implementation, or replaces it with `= default` is left for a separate PR.

ACKs for top commit:
  optout21:
    utACK 48840bfc2d
  Chand-ra:
    tACK [`48840bf`](48840bfc2d). Built the PR and ran unit tests; everything passes.
  maflcko:
    review ACK 48840bfc2d 🌖
  stickies-v:
    utACK 48840bfc2d. Pretty straightforward cleanup taking advantage of C++20 improvements, nice.
  janb84:
    ACK 48840bfc2d
  sipa:
    ACK 48840bfc2d

Tree-SHA512: 7fedc4abc451c7ad611e3a960ff939a35580667222009cb30ca546e564dc9161e3e8d4d1d7d44c538d961cc8f7adba6e6dbcebcd1be370bf33aef294d06f236b
2025-12-08 16:46:03 +00:00
merge-script
36073d56db Merge bitcoin/bitcoin#33952: depends: update freetype and document remaining bitcoin-qt runtime libs
41e657aacf guix: add bitcoin-qt runtime libs doc in symbol-check (fanquake)
ef4ce19a15 depends: freetype 2.11.1 (fanquake)

Pull request description:

  Update freetype to `2.11.1`.
  Updating fontconfig (currently `2.12.6`) to `2.13.1` requires what looks like a hard dep on gperf; leaving that as-is for now.
  Document expectations in `symbol-check.py`.
  Closes #29977 (changes are based on discussion there).

ACKs for top commit:
  sedited:
    ACK 41e657aacf

Tree-SHA512: 71c4ccc442df0b90bebc475003eb325564111b8312c42bc7d7a9c81a2fc166fdc0814c9ddde3cfe562c3c835556e7f97107458b02a07b981b1a199bf65d5ac1d
2025-12-08 10:10:23 +00:00
merge-script
f09ae5f96f Merge bitcoin/bitcoin#33950: guix: reduce allowed exported symbols
7b90b4f5bb guix: reduce allowed exported symbols (fanquake)

Pull request description:

  Need to double-check, but pretty sure this is atleast partly from #33181.

ACKs for top commit:
  sedited:
    Nice, ACK 7b90b4f5bb

Tree-SHA512: 538c03dc32aab9b3e18100e8ffa0d664aea5ceba6aafee9e8e0894c2d02eea3b3fb09733cf7b5bd0aefb6b56d0ac3b92f28da932e135b23f55404efd8f43664a
2025-12-08 09:40:30 +00:00
Anthony Towns
cea443e246 net: Pass time to InactivityChecks fuctions
We run InactivityChecks() for each node everytime poll()/select() every
50ms or so. Rather than calculating the current time once for each node,
just calculate it once and reuse it.
2025-12-07 00:36:24 +10:00
merge-script
89dc82295e Merge bitcoin/bitcoin#29641: scripted-diff: Use LogInfo over LogPrintf
fa4395dffd refactor: Remove unused LogPrintf (MarcoFalke)
fa05181d90 scripted-diff: LogPrintf -> LogInfo (MarcoFalke)

Pull request description:

  `LogPrintf` has many issues:

  * It does not mention the log severity (info).
  * It is a deprecated alias for `LogInfo`, according to the dev notes.
  * It wastes review cycles, because reviewers sometimes point out that it is deprecated.
  * It makes the code inconsistent, when both versions of the alias are used.

  Fix all issues by removing the deprecated alias.

ACKs for top commit:
  ajtowns:
    ACK fa4395dffd
  stickies-v:
    ACK fa4395dffd
  rkrux:
    lgtm ACK fa4395dffd

Tree-SHA512: de95d56df27b9ee33548cc7ee7595e2d253474094473089ee67787ddb171384383c683142672c3e2c1984e19eee629b2c469dc85713640a73391610581edbdbe
2025-12-06 13:47:44 +00:00
merge-script
eb19a2dac5 Merge bitcoin/bitcoin#34017: fuzz: Add a test case for ParseByteUnits()
57b888ce0e fuzz: Add a test case for `ParseByteUnits()` (Chandra Pratap)

Pull request description:

  `ParseByteUnits()` is the only parsing function in `strencodings.cpp` lacking a fuzz test. Add a test case to check the function against arbitrary strings and randomized `default_multiplier`.

ACKs for top commit:
  maflcko:
    lgtm ACK 57b888ce0e
  dergoegge:
    utACK 57b888ce0e
  marcofleon:
    crACK 57b888ce0e

Tree-SHA512: c16557442987437e5e0c9d9a8b016df93e513e34acb78242a1f73dabc4482632ec57eb35cb4c84f9a1ea838fa6bda2094f2a8b52ace431f8064a79fad96e9a52
2025-12-06 13:41:13 +00:00
MarcoFalke
faa23738fc refactor: Enable clang-tidy bugprone-unused-return-value
This requires some small refactors to silence false-positive warnings.

Also, expand the bugprone-unused-return-value.CheckedReturnTypes option
to include util::Result, and util::Expected.
2025-12-06 13:06:28 +01:00
MarcoFalke
fa114be27b Add util::Expected (std::expected) 2025-12-06 13:06:21 +01:00
merge-script
e68517208b Merge bitcoin/bitcoin#33995: depends: Propagate native C compiler to sqlite package
710031ebef Revert "guix: sqlite wants tcl" (Hennadii Stepanov)
4cf5ea6c3d depends: Propagate native C compiler to `sqlite` package (Hennadii Stepanov)

Pull request description:

  This PR:

  1. Ensures that autosetup can build the local bootstrap `jimsh0` when neither `jimsh` nor `tclsh` is available on the system.

  2. Removes the `tcl` package from the Guix manifest.

  This is an alternative to https://github.com/bitcoin/bitcoin/pull/33975.

ACKs for top commit:
  fanquake:
    ACK 710031ebef
  sedited:
    ACK 710031ebef

Tree-SHA512: bdaa29af977799669bfc2aa3a8d0a4a688263b99c5f06b1582fbefb71ef77be0ee6223903e8357e51a9e0a7744807174b94262c2f4a3afd9f39737b61b00863e
2025-12-05 17:24:52 +00:00
merge-script
091cae6fdf Merge bitcoin/bitcoin#33939: contrib: Count entry differences in asmap-tool diff summary
fd4ce55121 contrib: Count entry differences in asmap-tool diff summary (Fabian Jahr)

Pull request description:

  Currently the output of `asmap-tool.py diff` returns the total number of addresses that has changed at the end of the list.

  Example output currently:

  ```
  2602:feda:c0::/48 AS1029 # was AS43126
  2604:7c00:100::/40 AS29802 # was AS40244
  # 0 IPv4 addresses changed; 79552154633921058212365205504 (2^96.01) IPv6 addresses changed
  ```

  This is good indicator but in case of a longer list I would like the number of changed entries as well, since that is an easier number to parse and for debugging of certain issues also the more relevant value. This PR adds the count of changed entries to this summary output at the end. There as also a bit more structure so it's easier to parse as well.

  Example new output:

  ```
  2602:feda:c0::/48 AS1029 # was AS43126
  2604:7c00:100::/40 AS29802 # was AS40244
  # Summary
  IPv4: 0 entries with 0 addresses changed
  IPv6: 12 entries with 79552154633921058212365205504 (2^96.01) addresses changed
  ```

ACKs for top commit:
  jurraca:
    utACK [`fd4ce55121`](fd4ce55121)
  janb84:
    utACK fd4ce55121
  hodlinator:
    ACK fd4ce55121

Tree-SHA512: 97cc543eaba80a33f0291b20630411bda869d3b8d1b35ed7f36792064cb1edccc8fe4740b7229b5451a88b7bd8d68c42f96829ce4255ecac3e29d70b68061608
2025-12-05 15:27:01 +00:00
Chandra Pratap
57b888ce0e fuzz: Add a test case for ParseByteUnits()
`ParseByteUnits()` is the only parsing function in `strencodings.cpp`
lacking a fuzz test. Add a test case to check the function against
arbitrary strings and randomized default_multiplier's.
2025-12-05 15:23:54 +00:00
merge-script
b8e66b901d Merge bitcoin/bitcoin#33858: test: add unit test coverage for the empty leaves path in MerkleComputation
ffcae82a68 test: exercise TransactionMerklePath with empty block; targets the MerkleComputation empty-leaves path that was only reached by fuzz tests (frankomosh)

Pull request description:

  As noted in [#32243 (comment)](https://github.com/bitcoin/bitcoin/pull/32243#issuecomment-2988854482), the early return inside `MerkleComputation` when `leaves.size() == 0` was only exercised by fuzz tests.

  The existing `merkle_test_empty_block` calls `BlockMerkleRoot`, which uses `ComputeMerkleRoot`, but does not exercise the `TransactionMerklePath` → `ComputeMerklePath` → `MerkleComputation` code path.

  Coverage before adding test:
  <img width="2459" height="66" alt="before" src="https://github.com/user-attachments/assets/ca94015a-d7c2-4281-ac60-13b22f177b67" />

  Coverage after adding test:
  <img width="2459" height="66" alt="after" src="https://github.com/user-attachments/assets/b1d4e1bb-af72-46ab-8898-f18db39dd2fb" />

ACKs for top commit:
  kevkevinpal:
    ACK [ffcae82](ffcae82a68)
  maflcko:
    lgtm ACK ffcae82a68
  brunoerg:
    code review ACK ffcae82a68
  sedited:
    ACK ffcae82a68

Tree-SHA512: d2499d91269c4f4f9a86011f7ad13f675834662a5bd37b0e7cbe887a7d9acf4170e53f0bdc528011fc82866b9c1dec34f4e7e9cd64cc3100591c1580a4df5d00
2025-12-05 13:05:07 +00:00
merge-script
0c9ab0f8f8 Merge bitcoin/bitcoin#33956: net: fix use-after-free with v2->v1 reconnection logic
167df7a98c net: fix use-after-free with v2->v1 reconnection logic (Eugene Siegel)

Pull request description:

  `CConnman::Stop()` resets `semOutbound`, yet `m_reconnections` is not cleared in `Stop`. Each `ReconnectionInfo` contains a `grant` member that points to the memory that `semOutbound` pointed to and `~CConnman` will attempt to access the grant field (memory that was already freed) when destroying `m_reconnections`. Fix this by calling `m_reconnections.clear()` in `CConnman::Stop()` and add appropriate annotations.

  I was able to reproduce the original issue https://github.com/bitcoin/bitcoin/issues/33615 with the following diff by randomly stopping my node while it was attempting to reconnect (and verified that this patch fixes the issue, at least in my ~40-50 runs):
  <details>
  <summary> diff </summary>

  ```diff
  diff --git a/src/net.cpp b/src/net.cpp
  index ef1c63044a..9c1d161d8b 100644
  --- a/src/net.cpp
  +++ b/src/net.cpp
  @@ -1918,8 +1918,8 @@ void CConnman::DisconnectNodes()
       {
           LOCK(m_nodes_mutex);

  -        const bool network_active{fNetworkActive};
  -        if (!network_active) {
  +//        const bool network_active{fNetworkActive};
  +//        if (!network_active) {
               // Disconnect any connected nodes
               for (CNode* pnode : m_nodes) {
                   if (!pnode->fDisconnect) {
  @@ -1927,7 +1927,7 @@ void CConnman::DisconnectNodes()
                       pnode->fDisconnect = true;
                   }
               }
  -        }
  +//        }

           // Disconnect unused nodes
           std::vector<CNode*> nodes_copy = m_nodes;
  @@ -1941,7 +1941,7 @@ void CConnman::DisconnectNodes()
                   // Add to reconnection list if appropriate. We don't reconnect right here, because
                   // the creation of a connection is a blocking operation (up to several seconds),
                   // and we don't want to hold up the socket handler thread for that long.
  -                if (network_active && pnode->m_transport->ShouldReconnectV1()) {
  +                if (true) {
                       reconnections_to_add.push_back({
                           .addr_connect = pnode->addr,
                           .grant = std::move(pnode->grantOutbound),
  ```
  </details>

  I'm curious to see if others can reproduce as well.

ACKs for top commit:
  dergoegge:
    Code review ACK 167df7a98c
  darosior:
    utACK 167df7a98c
  mzumsande:
    ACK 167df7a98c

Tree-SHA512: 33fdfb110a7cdae182b5cd5400eea8a271308a62dd56491e0aef8865eff24a9ea908be74e4e2e2ee00ac1cb698e46f270f56dffffe34cf2cfd79e9b1079d6531
2025-12-05 10:23:45 +00:00
MarcoFalke
fa4395dffd refactor: Remove unused LogPrintf 2025-12-04 19:53:06 +01:00
MarcoFalke
fa05181d90 scripted-diff: LogPrintf -> LogInfo
This refactor does not change behavior.

-BEGIN VERIFY SCRIPT-

 sed --in-place 's/\<LogPrintf\>/LogInfo/g' \
   $( git grep -l '\<LogPrintf\>' -- ./contrib/ ./src/ ./test/ ':(exclude)src/logging.h' )

-END VERIFY SCRIPT-
2025-12-04 19:52:49 +01:00