2040 Commits

Author SHA1 Message Date
Ava Chow
4e4fa0199e
Merge bitcoin/bitcoin#33680: validation: do not wipe utxo cache for stats/scans/snapshots
c6ca2b85a3e6e73674e210aee4ed69c4af2848e4 validation: do not wipe utxo cache for stats/scans/snapshots (Pieter Wuille)
7099e93d0a80c65a547131d7bab977b09573310c refactor: rename `FlushStateMode::ALWAYS` to `FORCE_FLUSH` (Lőrinc)

Pull request description:

  Revival of https://github.com/bitcoin/bitcoin/pull/30610#issuecomment-3432564955 with the remaining comments applied on top

  > Since #28280, the cost of a non-wiping sync of the UTXO cache is only proportional to the number of dirty entries, rather than proportional to the size of the entire cache. Because of that, there is no reason to perform a wiping flush in case the contents of the cache is still useful.
  >
  > Split the `FlushStateMode::ALWAYS` mode into a FORCE_SYNC (non-wiping) and a FORCE_FLUSH (wiping), and then use the former in `scantxoutset`, `gettxoutsetinfo`, snapshot creation.

  (slightly updated after #30214)

ACKs for top commit:
  optout21:
    reACK c6ca2b85a3e6e73674e210aee4ed69c4af2848e4
  cedwies:
    reACK c6ca2b8 (trivial)
  achow101:
    ACK c6ca2b85a3e6e73674e210aee4ed69c4af2848e4
  sedited:
    ACK c6ca2b85a3e6e73674e210aee4ed69c4af2848e4

Tree-SHA512: f3525a85dc512db4a0a9c749ad47c0d3fa44085a121aa54cd77646260a719c71f754ec6570ae77779c0ed68a24799116f79c686e7a17ce57a26f6a598f7bf926
2026-01-29 14:43:27 -08:00
merge-script
1c2f164d34
Merge bitcoin/bitcoin#34253: validation: cache tip recency for lock-free IsInitialBlockDownload()
557b41a38ccf2929ca1e5271db1701e5fbe781af validation: make `IsInitialBlockDownload()` lock-free (Lőrinc)
b9c0ab3b75a19d7a1f7c01762374ce85f2d0d7be chain: add `CChain::IsTipRecent` helper (Lőrinc)
8d531c6210eb05bc424c971f621bb0b688ff70e6 validation: invert `m_cached_finished_ibd` to `m_cached_is_ibd` (Lőrinc)
8be54e3b19677b02e19d054a4a5b2f1968bb1c46 test: cover IBD exit conditions (Lőrinc)

Pull request description:

  This PR is a follow-up to the stale #32885.

  ### Problem
  `ChainstateManager::IsInitialBlockDownload()` currently acquires `cs_main` internally, even though most existing call sites already hold the lock. This becomes relevant for proposals like #34054, which would call `IsInitialBlockDownload()` from the scheduler thread without holding `cs_main`, potentially introducing lock contention.

  ### Fix
  Make `ChainstateManager::IsInitialBlockDownload()` lock-free by caching its result in a single atomic `m_cached_is_ibd` (true while in IBD, latched to false on exit).
  Move the IBD exit checks out of `IsInitialBlockDownload()` (reader-side) into a new `ChainstateManager::UpdateIBDStatus()` (writer-side, called under cs_main).

  Call UpdateIBDStatus() at strategic points where IBD exit conditions may change, after active chain tip updates in `ConnectTip()`, `DisconnectTip()`, and `LoadChainTip()`, and after `ImportBlocks()` returns.

  With this, `IsInitialBlockDownload()` becomes a lock-free atomic read, avoiding internal `cs_main` acquisition on hot paths.

  ### Testing and Benchmarks
  This isn't strictly an optimization (though some usecases might benefit from it), so rather as a sanity check I ran a reindex-chainstate and an `AssumeUTXO` load (without background validation).

  <details>
  <summary>assumeutxo load | 910000 blocks | dbcache 4500 | i9-ssd | x86_64 | Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 16 cores | 62Gi RAM | xfs | SSD</summary>

  ```
  COMMITS="595504a43209bead162da54a204df7d140a25f0e 63e822b637f67242e3689adedc0155b34100e651"; \
  CC=gcc; CXX=g++; \
  BASE_DIR="/mnt/my_storage"; DATA_DIR="$BASE_DIR/ShallowBitcoinData"; LOG_DIR="$BASE_DIR/logs"; UTXO_SNAPSHOT_PATH="$BASE_DIR/utxo-910000.dat"; \
  (echo ""; for c in $COMMITS; do git fetch -q origin $c && git log -1 --pretty='%h %s' $c || exit 1; done; echo "") && \
  for DBCACHE in 4500; do \
    (echo "assumeutxo load | 910000 blocks | dbcache ${DBCACHE} | $(hostname) | $(uname -m) | $(lscpu | grep 'Model name' | head -1 | cut -d: -f2 | xargs) | $(nproc) cores | $(free -h | awk '/^Mem:/{print $2}') RAM | $(df -T $BASE_DIR | awk 'NR==2{print $2}') | $(lsblk -no ROTA $(df --output=source $BASE_DIR | tail -1) | grep -q 0 && echo SSD || echo HDD)";) &&\
    hyperfine \
    --sort command \
    --runs 3 \
    --export-json "$BASE_DIR/assumeutxo-$(sed -E 's/(\w{8})\w+ ?/\1-/g;s/-$//'<<<"$COMMITS")-$DBCACHE-$CC-$(date +%s).json" \
    --parameter-list COMMIT ${COMMITS// /,} \
    --prepare "killall -9 bitcoind 2>/dev/null; rm -rf $DATA_DIR/blocks $DATA_DIR/chainstate $DATA_DIR/chainstate_snapshot $DATA_DIR/debug.log; git clean -fxd; git reset --hard {COMMIT} && \
               cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo && ninja -C build bitcoind bitcoin-cli -j2 && \
               ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=1 -printtoconsole=0; sleep 20 && \
               ./build/bin/bitcoind -datadir=$DATA_DIR -daemon -blocksonly -connect=0 -dbcache=$DBCACHE -printtoconsole=0; sleep 20" \
     --conclude "build/bin/bitcoin-cli -datadir=$DATA_DIR stop || true; killall bitcoind || true; sleep 10; \
                 echo '{COMMIT} | dbcache=$DBCACHE | chainstate: $(find $DATA_DIR/chainstate_snapshot -type f 2>/dev/null | wc -l) files, $(du -sb $DATA_DIR/chainstate_snapshot 2>/dev/null | cut -f1) bytes' >> $DATA_DIR/debug.log; \
                 cp $DATA_DIR/debug.log $LOG_DIR/debug-assumeutxo-{COMMIT}-dbcache-$DBCACHE-$(date +%s).log" \
      "COMPILER=$CC DBCACHE=$DBCACHE ./build/bin/bitcoin-cli -datadir=$DATA_DIR -rpcclienttimeout=0 loadtxoutset $UTXO_SNAPSHOT_PATH"; \
  done

  595504a432 Merge bitcoin/bitcoin#34236: Add sedited to trusted-keys
  63e822b637 validation: make `IsInitialBlockDownload()` lock-free

  assumeutxo load | 910000 blocks | dbcache 4500 | i9-ssd | x86_64 | Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 16 cores | 62Gi RAM | xfs | SSD

  Benchmark 1: COMPILER=gcc DBCACHE=4500 ./build/bin/bitcoin-cli -datadir=/mnt/my_storage/ShallowBitcoinData -rpcclienttimeout=0 loadtxoutset /mnt/my_storage/utxo-910000.dat (COMMIT = 595504a43209bead162da54a204df7d140a25f0e)
    Time (mean ± σ):     418.452 s ±  0.461 s    [User: 0.001 s, System: 0.001 s]
    Range (min … max):   418.070 s … 418.964 s    3 runs

  Benchmark 2: COMPILER=gcc DBCACHE=4500 ./build/bin/bitcoin-cli -datadir=/mnt/my_storage/ShallowBitcoinData -rpcclienttimeout=0 loadtxoutset /mnt/my_storage/utxo-910000.dat (COMMIT = 63e822b637f67242e3689adedc0155b34100e651)
    Time (mean ± σ):     415.994 s ±  0.294 s    [User: 0.001 s, System: 0.001 s]
    Range (min … max):   415.788 s … 416.330 s    3 runs

  Relative speed comparison
          1.01 ±  0.00  COMPILER=gcc DBCACHE=4500 ./build/bin/bitcoin-cli -datadir=/mnt/my_storage/ShallowBitcoinData -rpcclienttimeout=0 loadtxoutset /mnt/my_storage/utxo-910000.dat (COMMIT = 595504a43209bead162da54a204df7d140a25f0e)
          1.00          COMPILER=gcc DBCACHE=4500 ./build/bin/bitcoin-cli -datadir=/mnt/my_storage/ShallowBitcoinData -rpcclienttimeout=0 loadtxoutset /mnt/my_storage/utxo-910000.dat (COMMIT = 63e822b637f67242e3689adedc0155b34100e651)
  ```

  </details>

  <details>
  <summary>2026-01-12 | reindex-chainstate | 931139 blocks | dbcache 4500 | i9-ssd | x86_64 | Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 16 cores | 62Gi RAM | SSD</summary>

  ```
  for DBCACHE in 4500; do \
    COMMITS="595504a43209bead162da54a204df7d140a25f0e 63e822b637f67242e3689adedc0155b34100e651"; \
    STOP=931139; 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 "" && echo "$(date -I) | reindex-chainstate | ${STOP} blocks | dbcache ${DBCACHE} | $(hostname) | $(uname -m) | $(lscpu | grep 'Model name' | head -1 | cut -d: -f2 | xargs) | $(nproc) cores | $(free -h | awk '/^Mem:/{print $2}') RAM | SSD"; echo "") &&\
    hyperfine \
      --sort command \
      --runs 1 \
      --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 -9 bitcoind 2>/dev/null; rm -f $DATA_DIR/debug.log; git clean -fxd; git reset --hard {COMMIT} && \
        cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DENABLE_IPC=OFF && ninja -C build bitcoind -j1 && \
        ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=1000 -printtoconsole=0; sleep 20; rm -f $DATA_DIR/debug.log" \
      --conclude "killall bitcoind || true; sleep 5; grep -q 'height=0' $DATA_DIR/debug.log && grep -q 'Disabling script verification at block #1' $DATA_DIR/debug.log && grep -q 'height=$STOP' $DATA_DIR/debug.log; \
                  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";
  done

  595504a432 Merge bitcoin/bitcoin#34236: Add sedited to trusted-keys
  63e822b637 validation: make `IsInitialBlockDownload()` lock-free

  2026-01-12 | reindex-chainstate | 931139 blocks | dbcache 4500 | i9-ssd | x86_64 | Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 16 cores | 62Gi RAM | SSD

  Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=931139 -dbcache=4500 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 595504a43209bead162da54a204df7d140a25f0e)
    Time (abs ≡):        17187.310 s               [User: 33104.415 s, System: 937.548 s]

  Benchmark 2: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=931139 -dbcache=4500 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 63e822b637f67242e3689adedc0155b34100e651)
    Time (abs ≡):        17240.300 s               [User: 33164.803 s, System: 976.485 s]

  Relative speed comparison
          1.00          COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=931139 -dbcache=4500 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 595504a43209bead162da54a204df7d140a25f0e)
          1.00          COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=931139 -dbcache=4500 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 63e822b637f67242e3689adedc0155b34100e651)
  ```

  </details>

ACKs for top commit:
  sedited:
    ACK 557b41a38ccf2929ca1e5271db1701e5fbe781af
  sipa:
    utACK 557b41a38ccf2929ca1e5271db1701e5fbe781af
  mzumsande:
    Code Review ACK 557b41a38ccf2929ca1e5271db1701e5fbe781af

Tree-SHA512: 174015b9785846fc3375bd9d6e4ef91de47ffb659a94d645c49d333a33a32986d5c3cb2eb5a0a7245f96580ed6fea4ba5b7f93cac7e42e3b225f0a01538a2e5c
2026-01-29 11:51:41 +01:00
Ava Chow
75ec9001ce
Merge bitcoin/bitcoin#34207: coins/refactor: enforce GetCoin() returns only unspent coins
2ee7f9b259059d59e127852ea898b58183604b46 coins: assume `GetCoin` only returns unspent coins (Andrew Toth)
eec551aaf1dff4cccc15e486d5618a8a44d8314c fuzz: keep `coinscache_sim` backend free of spent coins (Andrew Toth)
3e4155fcefe0aafcc9cb84640e303e05477605a3 test: do not return spent coins from `CCoinsViewTest::GetCoin` (Andrew Toth)
ee1e40f58000921e95f08bcb199a452eb5c4d9b2 txdb: assert `CCoinsViewDB::GetCoin` only returns unspent coins (Lőrinc)

Pull request description:

  This PR is split out from #33018 to keep that PR focused on removing the `FRESH-but-not-DIRTY` cache state.

  ### Problem
  `::GetCoin()` is an interface for querying the UTXO set, so production implementations should only ever return unspent coins. Tests should mimic this to provide useful feedback.

  ### Fix:
  * Add a fail-fast assertion that `CCoinsViewDB::GetCoin()` never returns a spent coin.
  * Align unit tests and fuzz simulations with the production `GetCoin()` contract by never returning spent coins.
  * Replace the unreachable “spent coin returned by parent” handling in `CCoinsViewCache::FetchCoin()` with `Assert(!coin.IsSpent())`, drop outdated `spent+FRESH` docs, and tighten `SanityCheck()` invariants.

  Behavior is unchanged, it just aligns our tests to exercise valid states.

ACKs for top commit:
  andrewtoth:
    re-ACK 2ee7f9b259059d59e127852ea898b58183604b46
  optout21:
    crACK 2ee7f9b259059d59e127852ea898b58183604b46
  achow101:
    ACK 2ee7f9b259059d59e127852ea898b58183604b46
  w0xlt:
    reACK 2ee7f9b259059d59e127852ea898b58183604b46

Tree-SHA512: be21cc09690410fc04ca25e1ba47aae6186bc037e413b3bb1e6e9a04e6364cbfac5a2fcdc49b638fec848cd29243fab0cc0581b9923f34fafe8366828f690ed4
2026-01-28 14:29:17 -08:00
merge-script
2778eb4664
Merge bitcoin/bitcoin#34337: fuzz: Return chrono point from ConsumeTime(), Add ConsumeDuration()
eeee3755f8c415b227820479b5492261f3a8aa08 fuzz: Return chrono point from ConsumeTime(), Add ConsumeDuration() (MarcoFalke)
faa5a9ebad15fe41e8ddf45f11ad72bdc5aabf99 fuzz: Use min option in ConsumeTime (MarcoFalke)

Pull request description:

  Returning a raw i64 is a bit confusing when it comes to chrono types. For example, in the addrman fuzz tests, the `time_penalty` is not a time point, but a duration.

  Also, all call-sites assume second resolution right now, so document that better by returning `NodeSeconds` from `ConsumeTime(...)` and `std::chrono::seconds` from `ConsumeDuration(...)`.

ACKs for top commit:
  l0rinc:
    ACK eeee3755f8c415b227820479b5492261f3a8aa08
  Crypt-iQ:
    crACK eeee3755f8c415b227820479b5492261f3a8aa08

Tree-SHA512: 25dd779a1bf79fa42c6e69db0f0593ad4daa4c0d746e8e82a26bdd65391a27c38e484431056d4e2207b542c511a71cb536c259809728a7166b8d304c0490e321
2026-01-26 11:36:24 +00:00
MarcoFalke
eeee3755f8
fuzz: Return chrono point from ConsumeTime(), Add ConsumeDuration()
A chrono time point is a bit more type-safe than a raw i64.

Also, add a dedicated helper for plain chrono durations.
2026-01-23 15:59:07 +01:00
merge-script
1b079becf1
Merge bitcoin/bitcoin#34317: fuzz: Exclude too expensive inputs in descriptor_parse targets
fab2f3df4beb230eef63bdcf5042b6417c0012dc fuzz: Exclude too expensive inputs in descriptor_parse targets (MarcoFalke)

Pull request description:

  Accepting "expensive" fuzz inputs which have no real use-case is problematic, because it prevents the fuzz engine from spending time on the next useful fuzz input.

  For example, those will take several seconds (!) and the flamegraph shows that base58 encoding is the cause:

  ```
  curl -fLO 'f5abf41608'
  curl -fLO '78cb317546'

  FUZZ=mocked_descriptor_parse ./bld-cmake/bin/fuzz ./f5abf41608addcef3538da61d8096c2050235032
  FUZZ=descriptor_parse ./bld-cmake/bin/fuzz ./78cb3175467f53b467b949883ee6072e92dbb267
  ```

  This will also break 32-bit fuzzing, see https://github.com/bitcoin/bitcoin/issues/34110#issuecomment-3759461248.

  Fix all issues by checking for `HasTooLargeLeafSize`.

  Sorry for creating several pull requests to fix this class of issue, but I think this one should be the last one. 😅

ACKs for top commit:
  brunoerg:
    reACK fab2f3df4beb230eef63bdcf5042b6417c0012dc
  frankomosh:
    re-ACK fab2f3df4beb230eef63bdcf5042b6417c0012dc

Tree-SHA512: 4ecf98ec4adc39f6e014370945fb1598cdd3ceba60f7209b00789ac1164b6d20e82a69d71f8419d9a40d57ee3fea36ef593c47fe48b584b6e8344c44f20a15c1
2026-01-23 09:54:22 +00:00
MarcoFalke
fab2f3df4b
fuzz: Exclude too expensive inputs in descriptor_parse targets
Also, fixup iwyu warnings in the util module.

Also, fixup a typo.

The moved part can be reviewed with the git option:
--color-moved=dimmed-zebra
2026-01-22 21:01:55 +01:00
merge-script
d7fd8c6952
Merge bitcoin/bitcoin#34090: net: Fix -Wmissing-braces
f46e3ec0f9567a19ad9c111f264d395341327e4a net: Fix `-Wmissing-braces` (Hennadii Stepanov)

Pull request description:

  On some non-POSIX platforms, Clang emits `-Wmissing-braces` warnings for the `IN6ADDR_ANY_INIT` and `IN6ADDR_LOOPBACK_INIT` macros. For example, on OpenIndiana / illumos:
  ```
  $ uname -srv
  SunOS 5.11 illumos-325e0fc8bb
  $ clang --version
  clang version 21.1.7 (https://github.com/OpenIndiana/oi-userland.git 36a81bf5e5d307d4e85893422600678d46328010)
  Target: x86_64-pc-solaris2.11
  Thread model: posix
  InstalledDir: /usr/clang/21/bin
  $ cmake -B build -DCMAKE_GENERATOR=Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DENABLE_IPC=OFF -DAPPEND_CXXFLAGS='-Wno-unused-command-line-argument'
  $ cmake --build build
  [284/573] Building CXX object src/CMakeFiles/bitcoin_node.dir/net.cpp.o
  /export/home/hebasto/dev/bitcoin/src/net.cpp:3309:42: warning: suggest braces around initialization of subobject [-Wmissing-braces]
   3309 |         const CService ipv6_any{in6_addr(IN6ADDR_ANY_INIT), GetListenPort()}; // ::
        |                                          ^~~~~~~~~~~~~~~~
  /usr/include/netinet/in.h:479:32: note: expanded from macro 'IN6ADDR_ANY_INIT'
    479 | #define IN6ADDR_ANY_INIT            {   0, 0, 0, 0,     \
        |                                         ^~~~~~~~~~~~~~~~~
    480 |                                         0, 0, 0, 0,     \
        |                                         ~~~~~~~~~~~~~~~~~
    481 |                                         0, 0, 0, 0,     \
        |                                         ~~~~~~~~~~~~~~~~~
    482 |                                         0, 0, 0, 0 }
        |                                         ~~~~~~~~~~
  1 warning generated.
  [467/573] Building CXX object src/test/CMakeFiles/test_bitcoin.dir/i2p_tests.cpp.o
  /export/home/hebasto/dev/bitcoin/src/test/i2p_tests.cpp:116:34: warning: suggest braces around initialization of subobject [-Wmissing-braces]
    116 |     const CService addr{in6_addr(IN6ADDR_LOOPBACK_INIT), /*port=*/7656};
        |                                  ^~~~~~~~~~~~~~~~~~~~~
  /usr/include/netinet/in.h:484:37: note: expanded from macro 'IN6ADDR_LOOPBACK_INIT'
    484 | #define IN6ADDR_LOOPBACK_INIT       {   0, 0, 0, 0,     \
        |                                         ^~~~~~~~~~~~~~~~~
    485 |                                         0, 0, 0, 0,     \
        |                                         ~~~~~~~~~~~~~~~~~
    486 |                                         0, 0, 0, 0,     \
        |                                         ~~~~~~~~~~~~~~~~~
    487 |                                         0, 0, 0, 0x1U }
        |                                         ~~~~~~~~~~~~~
  /export/home/hebasto/dev/bitcoin/src/test/i2p_tests.cpp:159:38: warning: suggest braces around initialization of subobject [-Wmissing-braces]
    159 |         const CService addr{in6_addr(IN6ADDR_LOOPBACK_INIT), /*port=*/7656};
        |                                      ^~~~~~~~~~~~~~~~~~~~~
  /usr/include/netinet/in.h:484:37: note: expanded from macro 'IN6ADDR_LOOPBACK_INIT'
    484 | #define IN6ADDR_LOOPBACK_INIT       {   0, 0, 0, 0,     \
        |                                         ^~~~~~~~~~~~~~~~~
    485 |                                         0, 0, 0, 0,     \
        |                                         ~~~~~~~~~~~~~~~~~
    486 |                                         0, 0, 0, 0,     \
        |                                         ~~~~~~~~~~~~~~~~~
    487 |                                         0, 0, 0, 0x1U }
        |                                         ~~~~~~~~~~~~~
  2 warnings generated.
  [483/573] Building CXX object src/test/CMakeFiles/test_bitcoin.dir/netbase_tests.cpp.o
  /export/home/hebasto/dev/bitcoin/src/test/netbase_tests.cpp:505:36: warning: suggest braces around initialization of subobject [-Wmissing-braces]
    505 |         CService(CNetAddr(in6_addr(IN6ADDR_LOOPBACK_INIT)), 0 /* port */),
        |                                    ^~~~~~~~~~~~~~~~~~~~~
  /usr/include/netinet/in.h:484:37: note: expanded from macro 'IN6ADDR_LOOPBACK_INIT'
    484 | #define IN6ADDR_LOOPBACK_INIT       {   0, 0, 0, 0,     \
        |                                         ^~~~~~~~~~~~~~~~~
    485 |                                         0, 0, 0, 0,     \
        |                                         ~~~~~~~~~~~~~~~~~
    486 |                                         0, 0, 0, 0,     \
        |                                         ~~~~~~~~~~~~~~~~~
    487 |                                         0, 0, 0, 0x1U }
        |                                         ~~~~~~~~~~~~~
  /export/home/hebasto/dev/bitcoin/src/test/netbase_tests.cpp:510:36: warning: suggest braces around initialization of subobject [-Wmissing-braces]
    510 |         CService(CNetAddr(in6_addr(IN6ADDR_LOOPBACK_INIT)), 0x00f1 /* port */),
        |                                    ^~~~~~~~~~~~~~~~~~~~~
  /usr/include/netinet/in.h:484:37: note: expanded from macro 'IN6ADDR_LOOPBACK_INIT'
    484 | #define IN6ADDR_LOOPBACK_INIT       {   0, 0, 0, 0,     \
        |                                         ^~~~~~~~~~~~~~~~~
    485 |                                         0, 0, 0, 0,     \
        |                                         ~~~~~~~~~~~~~~~~~
    486 |                                         0, 0, 0, 0,     \
        |                                         ~~~~~~~~~~~~~~~~~
    487 |                                         0, 0, 0, 0x1U }
        |                                         ~~~~~~~~~~~~~
  /export/home/hebasto/dev/bitcoin/src/test/netbase_tests.cpp:515:36: warning: suggest braces around initialization of subobject [-Wmissing-braces]
    515 |         CService(CNetAddr(in6_addr(IN6ADDR_LOOPBACK_INIT)), 0xf1f2 /* port */),
        |                                    ^~~~~~~~~~~~~~~~~~~~~
  /usr/include/netinet/in.h:484:37: note: expanded from macro 'IN6ADDR_LOOPBACK_INIT'
    484 | #define IN6ADDR_LOOPBACK_INIT       {   0, 0, 0, 0,     \
        |                                         ^~~~~~~~~~~~~~~~~
    485 |                                         0, 0, 0, 0,     \
        |                                         ~~~~~~~~~~~~~~~~~
    486 |                                         0, 0, 0, 0,     \
        |                                         ~~~~~~~~~~~~~~~~~
    487 |                                         0, 0, 0, 0x1U }
        |                                         ~~~~~~~~~~~~~
  3 warnings generated.
  [573/573] Linking CXX executable bin/test_bitcoin
  ```

  The same issue is observed on Windows. For further details, see https://github.com/bitcoin/bitcoin/pull/31507.

ACKs for top commit:
  bensig:
    ACK f46e3ec0f9567a19ad9c111f264d395341327e4a
  maflcko:
    review ACK  f46e3ec0f9567a19ad9c111f264d395341327e4a 👭
  vasild:
    ACK f46e3ec0f9567a19ad9c111f264d395341327e4a
  sedited:
    utACK f46e3ec0f9567a19ad9c111f264d395341327e4a

Tree-SHA512: 9ad597d393ba04537b3aa728070ea7bbe1fc8796f6d8f3d90eb511242e5a61b0ab18123a6be3cca89aaa20ba7fb4dbe682c4d1c6bd3f6d883c459133e0c2861f
2026-01-22 12:39:52 +01:00
Ava Chow
8c07800b19
Merge bitcoin/bitcoin#32497: merkle: pre‑reserve leaves to prevent reallocs with odd vtx count
3dd815f048c80c9a35f01972e0537eb42531aec7 validation: pre-reserve leaves to prevent reallocs with odd vtx count (Lőrinc)
7fd47e0e56087cd3b5fd76a532bdc3ac331e832e bench: make `MerkleRoot` benchmark more representative (Lőrinc)
f0a21831087410687c4ca31ac00e44f380b859be test: adjust `ComputeMerkleRoot` tests (Lőrinc)

Pull request description:

  #### Summary

  `ComputeMerkleRoot` [duplicates the last hash](39b6c139bd/src/consensus/merkle.cpp (L54-L56)) when the input size is odd. If the caller provides a `std::vector` whose capacity equals its size, that extra `push_back` forces a reallocation, doubling its capacity (causing peak memory usage of 3x the necessary size).

  This affects roughly half of the created blocks (those with odd transaction counts), causing unnecessary memory fragmentation during every block validation.

  #### Fix

  * Pre-reserves vector capacity to account for the odd-count duplication using `(size + 1) & ~1ULL`.
      * This syntax produces [optimal assembly](https://github.com/bitcoin/bitcoin/pull/32497#discussion_r2553107836) across x86/ARM and 32/64-bit platforms for GCC & Clang.
  * Eliminates default construction of `uint256` objects that are immediately overwritten by switching from `resize` to `reserve` + `push_back`.

  #### Memory Impact

  [Memory profiling](https://github.com/bitcoin/bitcoin/pull/32497#issuecomment-3563724551) shows **50% reduction in peak allocation** (576KB → 288KB) and elimination of reallocation overhead.

  #### Validation

  The benchmark was updated to use an odd leaf count to demonstrate the real-world scenario where the reallocation occurs.

  A full `-reindex-chainstate` up to block **896 408** ran without triggering the asserts.

  <details>
  <summary>Validation asserts</summary>

  Temporary asserts (not included in this PR) confirm that `push_back` never reallocates and that the coinbase witness hash remains null:
  ```cpp
  if (hashes.size() & 1) {
      assert(hashes.size() < hashes.capacity()); // TODO remove
      hashes.push_back(hashes.back());
  }

  leaves.reserve((block.vtx.size() + 1) & ~1ULL); // capacity rounded up to even
  leaves.emplace_back();
  assert(leaves.back().IsNull()); // TODO remove
  ```

  </details>

  #### Benchmark Performance

  While the main purpose is to improve predictability, the reduced memory operations also improve hashing throughput slightly.

ACKs for top commit:
  achow101:
    ACK 3dd815f048c80c9a35f01972e0537eb42531aec7
  optout21:
    reACK 3dd815f048c80c9a35f01972e0537eb42531aec7
  hodlinator:
    re-ACK 3dd815f048c80c9a35f01972e0537eb42531aec7
  vasild:
    ACK 3dd815f048c80c9a35f01972e0537eb42531aec7
  w0xlt:
    ACK 3dd815f048c80c9a35f01972e0537eb42531aec7 with minor nits.
  danielabrozzoni:
    Code review ACK 3dd815f048

Tree-SHA512: e7b578f9deadc0de7d61c062c7f65c5e1d347548ead4a4bb74b056396ad7df3f1c564327edc219670e6e2b2cb51f4e1ccfd4f58dd414aeadf2008d427065c11f
2026-01-20 15:47:17 -08:00
Ava Chow
a365c9fe1f
Merge bitcoin/bitcoin#33738: log: avoid collecting GetSerializeSize data when compact block logging is disabled
969c840db52da796c319f84c9a9a20b1de902ccf log,blocks: avoid `ComputeTotalSize` and `GetHash` work when logging is disabled (Lőrinc)
babfda332b6aa41143eb694193358ef2c76ebefe log,net: avoid `ComputeTotalSize` when logging is disabled (Lőrinc)
1658b8f82b99f9ba3b42a50ba1f72b19a38c8e75 refactor: rename `CTransaction::GetTotalSize` to signal that it's not cached (Lőrinc)

Pull request description:

  ### Context

  The new accounting options introduced in https://github.com/bitcoin/bitcoin/pull/32582 can be quite heavy, and are not needed when debug logging is disabled.

  ### Problem
  `PartiallyDownloadedBlock::FillBlock()` and `PeerManagerImpl::SendBlockTransactions()` accumulate transaction sizes for debug logging by calling `ComputeTotalSize()` in loops, which invokes expensive `GetSerializeSize()` serializations.
  The block header hash is also only computed for the debug log.

  ### Fixes

  Guard the size and hash calculations with `LogAcceptCategory()` checks so the serialization and hashing work only occurs when compact block debug logging is enabled.

  Also modernized the surrounding code a bit since the change is quite trivial.

  ### Reproducer

  You can test the change by starting an up-to-date `bitcoind` node with `-debug=cmpctblock` and observing compact block log lines such as:

  > [cmpctblock] Successfully reconstructed block 00000000000000000001061eaa6c0fe79258e7f79606e67ac495765cb121a520 with 1 txn prefilled, 3122 txn from mempool (incl at least 3 from extra pool) and 641 txn (352126 bytes) requested

  <details>
  <summary>Test patch</summary>

  ```patch
  diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp
  index 58620c93cc..f16eb38fa5 100644
  --- a/src/blockencodings.cpp
  +++ b/src/blockencodings.cpp
  @@ -186,6 +186,7 @@ bool PartiallyDownloadedBlock::IsTxAvailable(size_t index) const

   ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing, bool segwit_active)
   {
  +    LogInfo("PartiallyDownloadedBlock::FillBlock called");
       if (header.IsNull()) return READ_STATUS_INVALID;

       block = header;
  @@ -218,6 +219,7 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<
       }

       if (LogAcceptCategory(BCLog::CMPCTBLOCK, BCLog::Level::Debug)) {
  +        LogInfo("debug log enabled");
           const uint256 hash{block.GetHash()}; // avoid cleared header
           uint32_t tx_missing_size{0};
           for (const auto& tx : vtx_missing) tx_missing_size += tx->ComputeTotalSize(); // avoid cleared txn_available
  diff --git a/src/net_processing.cpp b/src/net_processing.cpp
  index 5600c8d389..c081825f77 100644
  --- a/src/net_processing.cpp
  +++ b/src/net_processing.cpp
  @@ -2470,6 +2470,7 @@ uint32_t PeerManagerImpl::GetFetchFlags(const Peer& peer) const

   void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlock& block, const BlockTransactionsRequest& req)
   {
  +    LogInfo("PeerManagerImpl::SendBlockTransactions called");
       BlockTransactions resp(req);
       for (size_t i = 0; i < req.indexes.size(); i++) {
           if (req.indexes[i] >= block.vtx.size()) {
  @@ -2480,6 +2481,7 @@ void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlo
       }

       if (LogAcceptCategory(BCLog::CMPCTBLOCK, BCLog::Level::Debug)) {
  +        LogInfo("debug log enabled");
           uint32_t tx_requested_size{0};
           for (const auto i : req.indexes) tx_requested_size += block.vtx[i]->ComputeTotalSize();
           LogDebug(BCLog::CMPCTBLOCK, "Peer %d sent us a GETBLOCKTXN for block %s, sending a BLOCKTXN with %u txns. (%u bytes)\n", pfrom.GetId(), block.GetHash().ToString(), resp.txn.size(), tx_requested_size);
  ```

  </details>

ACKs for top commit:
  davidgumberg:
    reACK 969c840db5
  achow101:
    ACK 969c840db52da796c319f84c9a9a20b1de902ccf
  hodlinator:
    re-ACK 969c840db52da796c319f84c9a9a20b1de902ccf
  sedited:
    Re-ACK 969c840db52da796c319f84c9a9a20b1de902ccf
  danielabrozzoni:
    reACK 969c840db52da796c319f84c9a9a20b1de902ccf

Tree-SHA512: 9780102d29778165144e3602d934ed4cb96660fd7b9ff2581b223c619e419139b8348e60f226af448702ae527736a1806d169b44342c5a82795590f664e16efe
2026-01-20 15:41:30 -08:00
Ava Chow
f7e88e298a
Merge bitcoin/bitcoin#32471: wallet/rpc: fix listdescriptors RPC fails to return descriptors with private key information when wallet contains descriptors missing any key
9c7e4771b13d4729fd20ea08b7e2e3209b134fff test: Test listdescs with priv works even with missing priv keys (Novo)
ed945a685473712c1a822379effa42fd49223515 walletrpc: reject listdes with priv key on w-only wallets (Novo)
9e5e9824f11b1b0f9e2a4e28124edbb1616af519 descriptor: ToPrivateString() pass if  at least 1 priv key exists (Novo)
5c4db25b61d417a567f152169f4ab21a491afb95 descriptor: refactor ToPrivateString for providers (Novo)
2dc74e3f4e5e6f01c8810359b91041bc6865f1c7 wallet/migration: use HavePrivateKeys in place of ToPrivateString (Novo)
e842eb90bb6db39076a43b010c0c7898d50b8d92 descriptors: add HavePrivateKeys() (Novo)

Pull request description:

  _TLDR:
  Currently, `listdescriptors [private=true]` will fail for a non-watch-only wallet if any descriptor has a missing private key(e.g `tr()`, `multi()`, etc.). This PR changes that while making sure `listdescriptors [private=true]` still fails if there no private keys. Closes #32078_

  In non-watch-only wallets, it's possible to import descriptors as long as at least one private key is included. It's important that users can still view these descriptors when they need to create a backup—even if some private keys are missing ([#32078 (comment)](https://github.com/bitcoin/bitcoin/issues/32078#issuecomment-2781428475)). This change makes it possible to do so.

  This change also helps prevent `listdescriptors true` from failing completely, because one descriptor is missing some private keys.

  ### Notes
  - The new behaviour is applied to all descriptors including miniscript descriptors
  - `listdescriptors true` still fails for watch-only wallets to preserve existing behaviour https://github.com/bitcoin/bitcoin/pull/24361#discussion_r920801352
  - Wallet migration logic previously used `Descriptor::ToPrivateString()` to determine which descriptor was watchonly. This means that modifying the `ToPrivateString()` behaviour caused descriptors that were previously recognized as "watchonly" to be "non-watchonly". **In order to keep the scope of this PR limited to the RPC behaviour, this PR uses a different method to determine `watchonly` descriptors for the purpose of wallet migration.** A follow-up PR can be opened to update migration logic to exclude descriptors with some private keys from the `watchonly` migration wallet.

  ### Relevant PRs
  https://github.com/bitcoin/bitcoin/pull/24361
  https://github.com/bitcoin/bitcoin/pull/32186

  ### Testing
  Functional tests were added to test the new behaviour

  EDIT
  **`listdescriptors [private=true]` will still fail when there are no private keys because non-watchonly wallets must have private keys and calling `listdescriptors [private=true]` for watchonly wallet returns an error**

ACKs for top commit:
  Sjors:
    ACK 9c7e4771b13d4729fd20ea08b7e2e3209b134fff
  achow101:
    ACK 9c7e4771b13d4729fd20ea08b7e2e3209b134fff
  w0xlt:
    reACK 9c7e4771b1 with minor nits
  rkrux:
    re-ACK 9c7e4771b13d4729fd20ea08b7e2e3209b134fff

Tree-SHA512: f9b3b2c3e5425a26e158882e39e82e15b7cb13ffbfb6a5fa2868c79526e9b178fcc3cd88d3e2e286f64819d041f687353780bbcf5a355c63a136fb8179698b60
2026-01-20 12:17:19 -08:00
merge-script
7f5ebef56a
Merge bitcoin/bitcoin#34302: fuzz: Restore SendMessages coverage in process_message(s) fuzz targets
fabf8d1c5bdb6a944762792cdc762caa6c1a760b fuzz: Restore SendMessages coverage in process_message(s) fuzz targets (MarcoFalke)
fac7fed397f0fa3924600c1806a46d235a62ee5f refactor: Use std::reference_wrapper<AddrMan> in Connman (MarcoFalke)

Pull request description:

  *Found and reported by Crypt-iQ (thanks!)*

  Currently the process_message(s) fuzz targets do not have any meaningful `SendMessages` code coverage. This is not ideal.

  Fix the problem by adding back the coverage, and by hardening the code here, so that the problem hopefully does not happen again in the future.

  ### Historic context for this regression

  The regression was introduced in commit fa11eea4059a608f591db4469c07a341fd33a031, which built a new deterministic peerman object. However, the patch was incomplete, because it was missing one hunk to replace `g_setup->m_node.peerman->SendMessages(&p2p_node);` with `peerman->SendMessages(&p2p_node);`.

  This means the stale and empty peerman from the node context and not the freshly created and deterministic peerman was used.

  A simple fix would be to just submit the missing patch hunk. However, this still leaves the risk that the issue is re-introduced at any time in the future. So instead, I think the stale and empty peerman should be de-constructed, so that any call to it will lead to a hard sanitizer error and fuzz failure.

  Doing that also uncovered another issue: The connman was holding on to a reference to a stale and empty addrman.

  So fix all issues by:

  * Allowing the addrman reference in connman to be re-seatable
  * Clearing all stale objects, before creating new objects, and then using references to the new objects in all code

ACKs for top commit:
  Crypt-iQ:
    crACK fabf8d1c5bdb6a944762792cdc762caa6c1a760b
  frankomosh:
    ACK fabf8d1c5bdb6a944762792cdc762caa6c1a760b
  marcofleon:
    code review ACK fabf8d1c5bdb6a944762792cdc762caa6c1a760b
  sedited:
    ACK fabf8d1c5bdb6a944762792cdc762caa6c1a760b

Tree-SHA512: 2e478102b3e928dc7505f00c08d4b9e4f8368407b100bc88f3eb3b82aa6fea5a45bae736c211f5af1551ca0de1a5ffd4a5d196d9473d4c3b87cfed57c9a0b69d
2026-01-20 16:45:18 +01:00
Lőrinc
1658b8f82b
refactor: rename CTransaction::GetTotalSize to signal that it's not cached
Transaction hashes are cached, it may not be intuitive that their sizes are actually recalculated every time.
This is done before the other refactors to clarify why we want to avoid calling this method;

Co-authored-by: maflcko <6399679+maflcko@users.noreply.github.com>
2026-01-19 20:20:13 +01:00
merge-script
c57fbbe99d
Merge bitcoin/bitcoin#31650: refactor: Avoid copies by using const references or by move-construction
fa64d8424b8de49e219bffb842a33d484fb03212 refactor: Enforce readability-avoid-const-params-in-decls (MarcoFalke)
faf0c2d942c8de7868a3fd3afc7fc9ea700c91d4 refactor: Avoid copies by using const references or by move-construction (MarcoFalke)

Pull request description:

  Top level `const` in declarations is problematic for many reasons:

  * It is often a typo, where one wanted to denote a const reference. For example `bool PSBTInputSignedAndVerified(const PartiallySignedTransaction psbt, ...` is missing the `&`. This will create a redundant copy of the value.
  * In constructors it prevents move construction.
  * It can incorrectly imply some data is const, like in an imaginary example `std::span<int> Shuffle(const std::span<int>);`, where the `int`s are *not* const.
  * The compiler ignores the `const` from the declaration in the implementation.
  * It isn't used consistently anyway, not even on the same line.

  Fix some issues by:

  * Using a const reference to avoid a copy, where read-only of the value is intended. This is only done for values that may be expensive to copy.
  * Using move-construction to avoid a copy
  * Applying `readability-avoid-const-params-in-decls` via clang-tidy

ACKs for top commit:
  l0rinc:
    diff reACK fa64d8424b8de49e219bffb842a33d484fb03212
  hebasto:
    ACK fa64d8424b8de49e219bffb842a33d484fb03212, I have reviewed the code and it looks OK.
  sedited:
    ACK fa64d8424b8de49e219bffb842a33d484fb03212

Tree-SHA512: 293c000b4ebf8fdcc75259eb0283a2e4e7892c73facfb5c3182464d6cb6a868b7f4a6682d664426bf2edecd665cf839d790bef0bae43a8c3bf1ddfdd3d068d38
2026-01-19 11:44:04 +01:00
MarcoFalke
faa5a9ebad
fuzz: Use min option in ConsumeTime
This is less code and also required for the next commit.
2026-01-16 11:00:58 +01:00
MarcoFalke
fabf8d1c5b
fuzz: Restore SendMessages coverage in process_message(s) fuzz targets 2026-01-15 15:17:12 +01:00
merge-script
d08c1b3ed9
Merge bitcoin/bitcoin#34288: fuzz: Exclude too expensive inputs in miniscript_string target
fac70ea8b5bb33d05a47c36f2c5f1d79f119315c fuzz: Exclude too expensive inputs in miniscript_string target (MarcoFalke)
fa907864786056258302a611bf4df0319138a71b iwyu: Fix includes for test/fuzz/util/descriptor module (MarcoFalke)

Pull request description:

  Fixes https://github.com/bitcoin/bitcoin/issues/30498

  Accepting "expensive" fuzz inputs which have no real use-case is problematic, because it prevents the fuzz engine from spending time on the next useful fuzz input.

  For example this one will take several seconds (the flamegraph shows the time is spent in minscipt `NoDupCheck`):

  ```
  curl -fLO '41bae50cff'
  FUZZ=miniscript_string /usr/bin/time   ./bld-cmake/bin/fuzz  ./41bae50cffd1741150a1b330d02ab09f46ff8cd1
  ```

  Inspecting the inputs shows that it has many sub frags, so rejecting based on `HasTooManySubFrag` should be sufficient.

ACKs for top commit:
  darosior:
    ACK fac70ea8b5bb33d05a47c36f2c5f1d79f119315c
  brunoerg:
    code review ACK fac70ea8b5bb33d05a47c36f2c5f1d79f119315c
  dergoegge:
    utACK fac70ea8b5bb33d05a47c36f2c5f1d79f119315c

Tree-SHA512: 7f1e0d9ce24d67ec63e5b7c2dd194efa51f38beb013564690afe0f920e5ff1980c85ce344828c0dc3f34b6851db7fe72a76b1a775c6d51c94fb91431834f453b
2026-01-15 13:55:27 +00:00
merge-script
baa554f708
Merge bitcoin/bitcoin#34259: Find minimal chunks in SFL
da56ef239b12786e3a177afda14352dda4a70bc6 clusterlin: minimize chunks (feature) (Pieter Wuille)

Pull request description:

  Part of #30289.

  This was split off from #34023, because it's not really an optimization but a feature. The feature existed pre-SFL, so this brings SFL to parity in terms of functionality with the old code.

  The idea is that while optimality - as achieved by SFL before this PR - guarantees a linearization whose feerate diagram is optimal, it may be possible to split chunks into smaller equal-feerate parts. This is desirable because even though it doesn't change the diagram, it provides more flexibility for optimization (binpacking is easier when the pieces are smaller).

  Thus, this PR introduces the stronger notion of "minimality": optimal chunks, which are also split into their smallest possible pieces. To accomplish that, an additional step in the SFL algorithm is added which aims to split chunks into minimal equal-feerate parts where possible, without introducing circular dependencies between them. It works based on the observation that if an (already otherwise optimal) chunk has a way of being split into two equal-feerate parts, and T is a given transaction in the chunk, then we can find the split in two steps:
  * One time, pretend T has $\epsilon$ higher feerate than it really has. If a split exists with T in the top part, this will find it.
  * The other time, pretend T has $\epsilon$ lower feerate than it really has. If a split exists with T in the bottom part, this will find it.

  So we try both on each found optimal chunk. If neither works, the chunk is minimal. If one works, recurse into the split chunks to split them further.

ACKs for top commit:
  instagibbs:
    reACK da56ef239b
  marcofleon:
    crACK da56ef239b12786e3a177afda14352dda4a70bc6

Tree-SHA512: 2e94d6b78725f5f9470a939dedef46450b85c4e5e6f30cba0b038622ec2b417380747e8df923d1f303706602ab6d834350716df9678de144f857e3a8d163f6c2
2026-01-15 10:07:21 +00:00
MarcoFalke
fa64d8424b
refactor: Enforce readability-avoid-const-params-in-decls 2026-01-14 23:04:12 +01:00
Ava Chow
b0b65336e7
Merge bitcoin/bitcoin#32740: refactor: Header sync optimisations & simplifications
de4242f47476769d0a7f3e79e8297ed2dd60d9a4 refactor: Use reference for chain_start in HeadersSyncState (Daniela Brozzoni)
e37555e5401f9fca39ada0bd153e46b2c7ebd095 refactor: Use initializer list in CompressedHeader (Daniela Brozzoni)
0488bdfefe92b2c9a924be9244c91fe472462aab refactor: Remove unused parameter in ReportHeadersPresync (Daniela Brozzoni)
256246a9fa5b05141c93aeeb359394b9c7a80e49 refactor: Remove redundant parameter from CheckHeadersPoW (Daniela Brozzoni)
ca0243e3a6d77d2b218749f1ba113b81444e3f4a refactor: Remove useless CBlock::GetBlockHeader (Pieter Wuille)
45686522224598bed9923e60daad109094d7bc29 refactor: Use std::span in HasValidProofOfWork (Daniela Brozzoni)
4066bfe561a45f61a3c9bf24bec7f600ddcc7467 refactor: Compute work from headers without CBlockIndex (Daniela Brozzoni)
0bf6139e194f355d121bb2aea74715d1c4099598 p2p: Avoid an IsAncestorOfBestHeaderOrTip call (Pieter Wuille)

Pull request description:

  This is a partial* revival of #25968

  It contains a list of most-unrelated simplifications and optimizations to the code merged in #25717:

  - Avoid an IsAncestorOfBestHeaderOrTip call: Just don't call this function when it won't have any effect.
  - Compute work from headers without CBlockIndex: Avoid the need to construct a CBlockIndex object just to compute work for a header, when its nBits value suffices for that. Also use some Spans where possible.
  - Remove useless CBlock::GetBlockHeader: There is no need for a function to convert a CBlock to a CBlockHeader, as it's a child class of it.

  It also contains the following code cleanups, which were suggested by reviewers in #25968:
  - Remove redundant parameter from CheckHeadersPoW: No need to pass consensusParams, as CheckHeadersPow already has access to m_chainparams.GetConsensus()
  - Remove unused parameter in ReportHeadersPresync
  - Use initializer list in CompressedHeader, also make GetFullHeader const
  - Use reference for chain_start in HeadersSyncState: chain_start can never be null, so it's better to pass it as a reference rather than a raw pointer

  *I decided to leave out three commits that were in #25968 (4e7ac7b94d04e056e9994ed1c8273c52b7b23931, ab52fb4e95aa2732d1a1391331ea01362e035984, 7f1cf440ca1a9c86085716745ca64d3ac26957c0), since they're a bit more involved, and I'm a new contributor. If this PR gets merged, I'll comment under #25968 to note that these three commits are still up for grabs :)

ACKs for top commit:
  l0rinc:
    ACK de4242f47476769d0a7f3e79e8297ed2dd60d9a4
  polespinasa:
    re-ACK de4242f47476769d0a7f3e79e8297ed2dd60d9a4
  sipa:
    ACK de4242f47476769d0a7f3e79e8297ed2dd60d9a4
  achow101:
    ACK de4242f47476769d0a7f3e79e8297ed2dd60d9a4
  hodlinator:
    re-ACK de4242f47476769d0a7f3e79e8297ed2dd60d9a4

Tree-SHA512: 1de4f3ce0854a196712505f2b52ccb985856f5133769552bf37375225ea8664a3a7a6a9578c4fd461e935cd94a7cbbb08f15751a1da7651f8962c866146d9d4b
2026-01-14 11:38:07 -08:00
MarcoFalke
fac70ea8b5
fuzz: Exclude too expensive inputs in miniscript_string target 2026-01-14 20:02:38 +01:00
MarcoFalke
fa90786478
iwyu: Fix includes for test/fuzz/util/descriptor module
Also, fix a typo.
2026-01-14 19:19:18 +01:00
Pieter Wuille
da56ef239b clusterlin: minimize chunks (feature)
After the normal optimization process finishes, and finds an optimal
spanning forest, run a second process (while computation budget remains)
to split chunks into minimal equal-feerate chunks.
2026-01-12 17:38:30 -05:00
Lőrinc
8d531c6210
validation: invert m_cached_finished_ibd to m_cached_is_ibd
Rename and invert the internal IBD latch so the cached value directly matches `IsInitialBlockDownload()` (true while in IBD, then latched to false).

This is a behavior-preserving refactor to avoid double negatives.
2026-01-12 16:54:11 +01:00
MarcoFalke
fa8d56f9f0
fuzz: Reject too large descriptor leaf sizes in scriptpubkeyman target 2026-01-08 14:26:29 +01:00
MarcoFalke
333333356f
fuzz: [refactor] Use std::span over FuzzBufferType in descriptor utils
They are exactly the same, but the descriptor utils should not prescribe
to use the FuzzBufferType. Using a dedicated type for them clarifies
that the utils are not tied to FuzzBufferType.

Also, while touching the lines, use `const` only where it is meaningful.
2026-01-08 12:18:01 +01:00
Novo
9e5e9824f1 descriptor: ToPrivateString() pass if at least 1 priv key exists
- Refactor Descriptor::ToPrivateString() to allow descriptors with
  missing private keys to be printed. Useful in descriptors with
  multiple keys e.g tr() etc.
- The existing behaviour of listdescriptors is preserved as much as
  possible, if no private keys are availablle ToPrivateString will
  return false
2026-01-07 10:44:38 +01:00
Andrew Toth
eec551aaf1
fuzz: keep coinscache_sim backend free of spent coins
`CoinsViewBottom` roughly simulates a memory-backed `CCoinsViewDB`, which never stores spent coins.

Stop returning spent coins from `GetCoin()`, erase spent entries in `BatchWrite()`, and tighten comparisons to expect `std::nullopt` when the simulator has no coin.

Co-authored-by: Lőrinc <pap.lorinc@gmail.com>
2026-01-06 12:16:46 +01:00
Pieter Wuille
1808b5aaf7 clusterlin: remove unused FixLinearization (cleanup) 2026-01-05 11:48:34 -05:00
Pieter Wuille
01ffcf464a clusterlin: support fixing linearizations (feature)
This also updates FixLinearization to just be a thin wrapper around Linearize.
In a future commit, FixLinearization will be removed entirely.
2026-01-05 11:48:16 -05:00
Pieter Wuille
c6ca2b85a3
validation: do not wipe utxo cache for stats/scans/snapshots
Since #28280, the cost of a non-wiping sync of the UTXO cache is only proportional to the number of dirty entries, rather than proportional to the size of the entire cache. Because of that, there is no reason to perform a wiping flush in case the contents of the cache is still useful.

Split the FlushStateMode::ALWAYS mode into a FORCE_SYNC (non-wiping) and a FORCE_FLUSH (wiping), and then use the former in scantxoutset, gettxoutsetinfo, snapshot creation.

Co-authored-by: l0rinc <pap.lorinc@gmail.com>
Co-authored-by: cedwies <141683552+cedwies@users.noreply.github.com>
2026-01-03 12:43:57 +01:00
Ava Chow
ab233255d4
Merge bitcoin/bitcoin#33866: refactor: Let CCoinsViewCache::BatchWrite return void
6da6f503a6dd8de85780ca402f5202095aa8b6ea refactor: Let CCoinsViewCache::BatchWrite return void (TheCharlatan)

Pull request description:

  CCoinsViewCache::BatchWrite always returns true if called from a backed cache, so just return void instead. Also return void from ::Sync and ::Flush.

  This allows for dropping a FatalError condition and simplifying some dead error handling code a bit.

  Since we now no longer exercise the "error path" when returning from `CCoinsView::BatchWrite`, make the method clear the cache instead. This should only be exercised by tests and not change production behaviour. This might slightly improve the coins_view fuzz test's ability to generate better coverage.

ACKs for top commit:
  l0rinc:
    ACK 6da6f503a6dd8de85780ca402f5202095aa8b6ea
  andrewtoth:
    re-ACK 6da6f503a6dd8de85780ca402f5202095aa8b6ea
  achow101:
    ACK 6da6f503a6dd8de85780ca402f5202095aa8b6ea
  w0xlt:
    ACK 6da6f503a6

Tree-SHA512: dfaa325b0cf8108910aebf1b27434aaddb639d10d860e96797c77ea42eca9035a54a7dc1d6a5d4eae2b75fcc9356206d3d5672243d2c906e80d19024c8b95408
2026-01-02 16:49:23 -08:00
bensig
08ed802bab doc: fix double-word typos in comments 2025-12-30 12:12:26 -08:00
fanquake
3e4765ee10
scripted-diff: [doc] Unify stale copyright headers
-BEGIN VERIFY SCRIPT-

sed --in-place --regexp-extended \
       's;( 20[0-2][0-9])(-20[0-2][0-9])? The Bitcoin Core developers;\1-present The Bitcoin Core developers;g' \
       $( git grep -l 'The Bitcoin Core developers' -- ':(exclude)COPYING' ':(exclude)src/ipc/libmultiprocess' ':(exclude)src/minisketch' )

-END VERIFY SCRIPT-
2025-12-19 16:58:36 +00:00
merge-script
7f295e1d9b
Merge bitcoin/bitcoin#34084: scripted-diff: [doc] Unify stale copyright headers
fa4cb13b52030c2e55c6bea170649ab69d75f758 test: [doc] Manually unify stale headers (MarcoFalke)
fa5f29774872d18febc0df38831a6e45f3de69cc scripted-diff: [doc] Unify stale copyright headers (MarcoFalke)

Pull request description:

  Historically, the upper year range in file headers was bumped manually
  or with a script.

  This has many issues:

  * The script is causing churn. See for example commit 306ccd4, or
    drive-by first-time contributions bumping them one-by-one. (A few from
    this year: https://github.com/bitcoin/bitcoin/pull/32008,
    https://github.com/bitcoin/bitcoin/pull/31642,
    https://github.com/bitcoin/bitcoin/pull/32963, ...)
  * Some, or likely most, upper year values were wrong. Reasons for
    incorrect dates could be code moves, cherry-picks, or simply bugs in
    the script.
  * The upper range is not needed for anything.
  * Anyone who wants to find the initial file creation date, or file
    history, can use `git log` or `git blame` to get more accurate
    results.
  * Many places are already using the `-present` suffix, with the meaning
    that the upper range is omitted.

  To fix all issues, this bumps the upper range of the copyright headers
  to `-present`.

  Further notes:

  * Obviously, the yearly 4-line bump commit for the build system (c.f.
    b537a2c02a9921235d1ecf8c3c7dc1836ec68131) is fine and will remain.
  * For new code, the date range can be fully omitted, as it is done
    already by some developers. Obviously, developers are free to pick
    whatever style they want. One can list the commits for each style.
  * For example, to list all commits that use `-present`:
    `git log --format='%an (%ae) [%h: %s]' -S 'present The Bitcoin'`.
  * Alternatively, to list all commits that use no range at all:
    `git log --format='%an (%ae) [%h: %s]' -S '(c) The Bitcoin'`.

  <!--
  * The lower range can be wrong as well, so it could be omitted as well,
    but this is left for a follow-up. A previous attempt was in
    https://github.com/bitcoin/bitcoin/pull/26817.

ACKs for top commit:
  l0rinc:
    ACK fa4cb13b52030c2e55c6bea170649ab69d75f758
  rkrux:
    re-ACK fa4cb13b52030c2e55c6bea170649ab69d75f758
  janb84:
    ACK fa4cb13b52030c2e55c6bea170649ab69d75f758

Tree-SHA512: e5132781bdc4417d1e2922809b27ef4cf0abb37ffb68c65aab8a5391d3c917b61a18928ec2ec2c75ef5184cb79a5b8c8290d63e949220dbeab3bd2c0dfbdc4c5
2025-12-19 16:56:02 +00:00
Pieter Wuille
75bdb925f4 clusterlin: drop support for improvable chunking (simplification)
With MergeLinearizations() gone and the LIMO-based Linearize() replaced by SFL, we do not
need a class (LinearizationChunking) that can maintain an incrementally-improving chunk
set anymore.

Replace it with a function (ChunkLinearizationInfo) that just computes the chunks as
SetInfos once, and returns them as a vector. This simplifies several call sites too.
2025-12-18 16:01:31 -05:00
Pieter Wuille
91399a7912 clusterlin: remove unused MergeLinearizations (cleanup)
This ended up never being used in txgraph.
2025-12-18 16:01:31 -05:00
Pieter Wuille
13aad26b78 clusterlin: randomize various decisions in SFL (feature)
This introduces a local RNG inside the SFL state, which is used to randomize
various decisions inside the algorithm, in order to make it hard to create
pathological clusters which predictably have bad performance.

The decisions being randomized are:
* When deciding what chunk to attempt to split, the queue order is
  randomized.
* When deciding which dependency to split on, a uniformly random one is
  chosen among those with higher top feerate than bottom feerate within
  the chosen chunk.
* When deciding which chunks to merge, a uniformly random one among those
  with the higher feerate difference is picked.
* When merging two chunks, a uniformly random dependency between them is
  now activated.
* When making the state topological, the queue of chunks to process is
  randomized.
2025-12-18 16:01:31 -05:00
Pieter Wuille
ddbfa4dfac clusterlin: keep FIFO queue of improvable chunks (preparation)
This introduces a queue of chunks that still need processing, in both
MakeTopological() and OptimizationStep(). This is simultaneously:
* A preparation for introducing randomization, by allowing permuting the
  queue.
* An improvement to the fairness of suboptimal solutions, by distributing
  the work more fairly over chunks.
* An optimization, by avoiding retrying chunks over and over again which
  are already known to be optimal.
2025-12-18 16:01:31 -05:00
Pieter Wuille
3efc94d656 clusterlin: replace cluster linearization with SFL (feature)
This replaces the existing LIMO linearization algorithm (which internally uses
ancestor set finding and candidate set finding) with the much more performant
spanning-forest linearization algorithm.

This removes the old candidate-set search algorithm, and several of its tests,
benchmarks, and needed utility code.

The worst case time per cost is similar to the previous algorithm, so
ACCEPTABLE_ITERS is unchanged.
2025-12-18 16:01:31 -05:00
Pieter Wuille
6a8fa821b8 clusterlin: add support for loading existing linearization (feature) 2025-12-18 16:01:22 -05:00
Pieter Wuille
da48ed9f34 clusterlin: ReadLinearization for non-topological (tests)
Rather than using an ad-hoc no-dependency copy of the graph when a potentially
non-topological linearization is needed in the clusterlin fuzz test, add this
directly as a feature in ReadLinearization().

This is preparation for a later commit where another use for such a function
is added.
2025-12-18 15:49:07 -05:00
Pieter Wuille
c461259fb6 clusterlin: add class implementing SFL state (preparation)
This adds a data structure representing the optimization state for the spanning-forest
linearization algorithm (SFL), plus a fuzz test for its correctness.

This is preparation for switching over Linearize() to use this algorithm.

See https://delvingbitcoin.org/t/spanning-forest-cluster-linearization/1419 for
a description of the algorithm.
2025-12-18 15:49:01 -05:00
merge-script
516ae5ede4
Merge bitcoin/bitcoin#31533: fuzz: Add fuzz target for block index tree and related validation events
db2d39f642979f929261e5f1cd67f0c2f2ca045f fuzz: add subtest for re-downloading a previously pruned block (Eugene Siegel)
45f5b2dac330906368352a1c585183f0d75d779d fuzz: Add fuzzer for block index (Martin Zumsande)
c011e3aa542631a8857039df796ebf13a653e8a6 test: Wrap validation functions with TestChainstateManager (Martin Zumsande)

Pull request description:

  This adds a fuzz target for the block index and various events in validation that interact with it.

  It can create arbitrary tree-like structure of block indexes, simulating (so far) the following events:
  - Adding a header
  - Receiving the full block (may be valid or not)
  - `ActivateBestChain()` - Reorging the chain to a new chain tip (possibly encountering invalid blocks on the way)
  - Pruning a block in the best chain
  - Receiving a previously pruned block again (`getblockfrompeer`)

  It might be interesting / possible to extend this to more events, such as dealing with more than one chainstate (assumeutxo).

  The test skips all actual validation of header/ block / transaction data by just simulating the outcome, and also doesn't interact with the data directory.
  The main goal is to ensure the integrity of the block index tree in all fuzzed constellations, by calling `CheckBlockIndex()` at the end of each iteration.

  Compared to #29158 this approach has a more limited scope (by skipping all actual validation), but it is fast - it doesn't do a full init sequence on each iteration, but "cleans up" after itself by resetting the global validation state after each iteration.

ACKs for top commit:
  Crypt-iQ:
    reACK db2d39f642
  maflcko:
    review ACK db2d39f642979f929261e5f1cd67f0c2f2ca045f 🍶
  sedited:
    Re-ACK db2d39f642979f929261e5f1cd67f0c2f2ca045f

Tree-SHA512: 76cd5f8f4d7d7258620b46d7438bad4508c3bdc98825b48b60f694b5a9838e2b2cf4967c0ead181f86f66f4939ddfe552471851b9d18f84f584c03dd7e09fc43
2025-12-18 15:26:42 +00:00
merge-script
8d38b6f5f1
Merge bitcoin/bitcoin#34091: fuzz: doc: remove any mention to address_deserialize_v2
caf4843a59a9d2512d69f8fd88a9672112bd80ac fuzz: doc: remove any mention to address_deserialize_v2 (brunoerg)

Pull request description:

  We don't have `address_deserialize_v2` target anymore since fac81affb527132945773a5315bd27fec61ec52f (we used to have `address_deserialize_v1_notime`, `address_deserialize_v1_withtime` and `address_deserialize_v2` but now we only have a single `address_deserialize` target) so it removes any mention to it.

ACKs for top commit:
  maflcko:
    review ACK caf4843a59a9d2512d69f8fd88a9672112bd80ac 🎾
  marcofleon:
    ACK caf4843a59a9d2512d69f8fd88a9672112bd80ac

Tree-SHA512: 539d69edbfe4ca11eb0701ed5c789ad81976e3e85e8a229e39e9dc1b1c72264f01d10a1c16d0a3bb4a354794412dc8b625298f4f72430905a00b65faeaa37d6b
2025-12-18 11:35:41 +00:00
Ryan Ofsky
ab513103df
Merge bitcoin/bitcoin#33192: refactor: unify container presence checks
d9319b06cf82664d55f255387a348135fd7f91c7 refactor: unify container presence checks - non-trivial counts (Lőrinc)
039307554eb311ce41648d1f9a12b543f480f871 refactor: unify container presence checks - trivial counts (Lőrinc)
8bb9219b6301215f53e43967d17445aaf1b81090 refactor: unify container presence checks - find (Lőrinc)

Pull request description:

  ### Summary
  Instead of counting occurrences in sets and maps, the C++20 `::contains` method expresses the intent unambiguously and can return early on first encounter.

  ### Context
  Applied clang‑tidy's [readability‑container‑contains](https://clang.llvm.org/extra/clang-tidy/checks/readability/container-contains.html) check, though many cases required manual changes since tidy couldn't fix them automatically.

  ### Changes
  The changes made here were:

  | From                   | To               |
  |------------------------|------------------|
  | `m.find(k) == m.end()` | `!m.contains(k)` |
  | `m.find(k) != m.end()` | `m.contains(k)`  |
  | `m.count(k)`           | `m.contains(k)`  |
  | `!m.count(k)`          | `!m.contains(k)` |
  | `m.count(k) == 0`      | `!m.contains(k)` |
  | `m.count(k) != 1`      | `!m.contains(k)` |
  | `m.count(k) == 1`      | `m.contains(k)`  |
  | `m.count(k) < 1`       | `!m.contains(k)`  |
  | `m.count(k) > 0`       | `m.contains(k)`  |
  | `m.count(k) != 0`      | `m.contains(k)`  |

  > Note that `== 1`/`!= 1`/`< 1` only apply to simple [maps](https://en.cppreference.com/w/cpp/container/map/contains)/[sets](https://en.cppreference.com/w/cpp/container/set/contains) and had to be changed manually.

  There are many other cases that could have been changed, but we've reverted most of those to reduce conflict with other open PRs.

  -----

  <details>
  <summary>clang-tidy command on Mac</summary>

  ```bash
  rm -rfd build && \
  cmake -B build \
    -DCMAKE_C_COMPILER="$(brew --prefix llvm)/bin/clang" \
    -DCMAKE_CXX_COMPILER="$(brew --prefix llvm)/bin/clang++" \
    -DCMAKE_OSX_SYSROOT="$(xcrun --show-sdk-path)" \
    -DCMAKE_C_FLAGS="-target arm64-apple-macos11" \
    -DCMAKE_CXX_FLAGS="-target arm64-apple-macos11" \
    -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBUILD_BENCH=ON -DBUILD_FUZZ_BINARY=ON -DBUILD_FOR_FUZZING=ON

   "$(brew --prefix llvm)/bin/run-clang-tidy" -quiet -p build -j$(nproc) -checks='-*,readability-container-contains' | grep -v 'clang-tidy'
  ```

  </details>

  Note: this is a take 2 of https://github.com/bitcoin/bitcoin/pull/33094 with fewer contentious changes.

ACKs for top commit:
  optout21:
    reACK d9319b06cf82664d55f255387a348135fd7f91c7
  sedited:
    ACK d9319b06cf82664d55f255387a348135fd7f91c7
  janb84:
    re ACK d9319b06cf82664d55f255387a348135fd7f91c7
  pablomartin4btc:
    re-ACK d9319b06cf82664d55f255387a348135fd7f91c7
  ryanofsky:
    Code review ACK d9319b06cf82664d55f255387a348135fd7f91c7. I manually reviewed the full change, and it seems there are a lot of positive comments about this and no more very significant conflicts, so I will merge it shortly.

Tree-SHA512: e4415221676cfb88413ccc446e5f4369df7a55b6642347277667b973f515c3c8ee5bfa9ee0022479c8de945c89fbc9ff61bd8ba086e70f30298cbc1762610fe1
2025-12-17 16:17:29 -05:00
Hennadii Stepanov
f46e3ec0f9
net: Fix -Wmissing-braces 2025-12-17 16:54:35 +00:00
brunoerg
caf4843a59 fuzz: doc: remove any mention to address_deserialize_v2 2025-12-17 11:57:11 -03:00
MarcoFalke
fa5f297748
scripted-diff: [doc] Unify stale copyright headers
-BEGIN VERIFY SCRIPT-

 sed --in-place --regexp-extended \
   's;( 20[0-2][0-9])(-20[0-2][0-9])? The Bitcoin Core developers;\1-present The Bitcoin Core developers;g' \
   $( git grep -l 'The Bitcoin Core developers' -- ':(exclude)COPYING' ':(exclude)src/ipc/libmultiprocess' ':(exclude)src/minisketch' )

-END VERIFY SCRIPT-
2025-12-16 22:21:15 +01:00
Eugene Siegel
db2d39f642 fuzz: add subtest for re-downloading a previously pruned block
This imitates the use of the getblockfrompeer rpc.
Note that currently pruning is limited to blocks in the active chain.

Co-authored-by: Martin Zumsande <mzumsande@gmail.com>
2025-12-16 11:25:46 -05:00