6491 Commits

Author SHA1 Message Date
merge-script
b9bf24cfe2
Merge bitcoin/bitcoin#34616: Cluster mempool: SFL cost model (take 2)
744d47fcee0d32a71154292699bfdecf954a6065 clusterlin: adopt trained cost model (feature) (Pieter Wuille)
4eefdfc5b7d0b86a523683de2a90da910b77a106 clusterlin: rescale costs (preparation) (Pieter Wuille)
ecc9a84f854e5b77dfc8876cf7c9b8d0f3de89d0 clusterlin: use 'cost' terminology instead of 'iters' (refactor) (Pieter Wuille)
9e7129df2962f7c52d07c14a56398bb285cac084 clusterlin: introduce CostModel class (preparation) (Pieter Wuille)

Pull request description:

  Part of #30289, replaces earlier #34138.

  This introduces a more accurate cost model for SFL, to control how much CPU time is spent inside the algorithm for clusters that cannot be linearized perfectly within a reasonable amount of time.

  The goal is having a metric for the amount of work performed, so that txmempool can impose limits on that work: a lower bound that is always performed (unless optimality is reached before that point, of course), and an upper bound to limit the latency and total CPU time spent on this. There are conflicting design goals here:
  * On the one hand, it seems ideal if this metric is closely correlated to actual CPU time, because otherwise the limits become inaccurate.
  * On the other hand, it seems a nightmare to have the metric be platform/system dependent, as it makes network-wide reasoning nearly impossible. It's expected that slower systems take longer to do the same thing; this holds for everything, and we don't need to compensate for this.

  There are multiple solutions to this:
  * One extreme is just measuring the time. This is very accurate, but extremely platform dependent, and also non-deterministic due to random scheduling/cache effects.
  * The other extreme is using a very abstract metric like counting how many times certain loops/function inside the algorithm run. That is what is implemented in master right now, just counting the sum of the numbers of transactions updated across all `UpdateChunks()` calls. It however necessarily fails to account for significant portions of runtime spent elsewhere, resulting in a rather wide range of "ns per cost" values.
  * This PR takes a middle ground, counting many function calls / branches / loops, with weights that were determined through benchmarking on an average on a number of systems.

  Specifically, the cost model was obtained by:
  * For a variety of machines:
    * Running a fixed collection of ~385000 clusters found through random generation and fuzzing, optimizing for difficulty of linearization.
      * Linearize each 1000-5000 times, with different random seeds. Sometimes without input linearization, sometimes with a bad one.
        * Gather cycle counts for each of the operations included in this cost model, broken down by their parameters.
    * Correct the data by subtracting the runtime of obtaining the cycle count.
    * Drop the 5% top and bottom samples from each cycle count dataset, and compute the average of the remaining samples.
    * For each operation, fit a least-squares linear function approximation through the samples.
  * Rescale all machine expressions to make their total time match, as we only care about relative cost of each operation.
  * Take the per-operation average of operation expressions across all machines, to construct expressions for an average machine.
  * Approximate the result with integer coefficients.

  The benchmarks were performed by `l0rinc <pap.lorinc@gmail.com>` and myself, on AMD Ryzen 5950X, AMD Ryzen 7995WX, AMD Ryzen 9980X, Apple M4 Max, Intel Core i5-12500H, Intel Core Ultra 7 155H, Intel N150 (Umbrel), Intel Core i7-7700, Intel Core i9-9900K, Intel Haswell (VPS, virtualized), Intel Xeon E5-2637, ARM Cortex-A76 (Raspberry Pi 5), ARM Cortex-A72 (Raspberry Pi 4).

  Based on final benchmarking, the "acceptable" iteration count (which is the minimum spent on every cluster) is to 75000 units, which corresponds to roughly 50 μs on Ryzen 5950X and similar modern desktop hardware.

ACKs for top commit:
  instagibbs:
    ACK 744d47fcee0d32a71154292699bfdecf954a6065
  murchandamus:
    reACK 744d47fcee0d32a71154292699bfdecf954a6065

Tree-SHA512: 5cb37a6bdd930389937c435f910410c3581e53ce609b9b594a8dc89601e6fca6e6e26216e961acfe9540581f889c14bf289b6a08438a2d7adafd696fc81ff517
2026-02-25 12:11:13 +00:00
Ava Chow
76eb04b16f
Merge bitcoin/bitcoin#34655: fuzz: keep coins_view fuzzers within caller contracts
3281824ecfa72c4f69ab69c94003b7f5a82c7265 fuzz: prevent invalid `FRESH` entries and surface `BatchWrite` errors (Lőrinc)
780f460635af86b91c4215e761b6895be762ed3e fuzz: avoid invalid `AddCoin` overwrites (Lőrinc)
d7e0d510f2bf2981e92e3b323aeba1c845377950 fuzz: make `AddCoins` query view for overwrites (Lőrinc)
b8fa6f0f701f04cffca6a085337b508381016649 util: introduce `TrySub` to prevent unsigned underflow (Lőrinc)

Pull request description:

  ### Problem
  This is an alternative approach to #34647, fixes #34645.

  ### Fix
  First, add `CheckedSub` and use it for decrements of `m_dirty_count` and `cachedCoinsUsage`, so unsigned underflows turn into immediate failures instead of silently wrapping and only failing later.

  <details><summary>Assertion `j <= i' failed.</summary>

  ```bash
  util/overflow.h:44 T CheckedSub(const T, const U) [T = unsigned long, U = bool]: Assertion `j <= i' failed.
  ==72817== ERROR: libFuzzer: deadly signal
      #0 0x556e9225eab5 in __sanitizer_print_stack_trace (/mnt/my_storage/bitcoin/build_fuzz/bin/fuzz+0x191dab5) (BuildId: d77c4d5f9dfd38ea06fab463f49341735205e109)
      #1 0x556e921acafc in fuzzer::PrintStackTrace() (/mnt/my_storage/bitcoin/build_fuzz/bin/fuzz+0x186bafc) (BuildId: d77c4d5f9dfd38ea06fab463f49341735205e109)
      #2 0x556e92191bb7 in fuzzer::Fuzzer::CrashCallback() (/mnt/my_storage/bitcoin/build_fuzz/bin/fuzz+0x1850bb7) (BuildId: d77c4d5f9dfd38ea06fab463f49341735205e109)
      #3 0x7164cfc458cf  (/lib/x86_64-linux-gnu/libc.so.6+0x458cf) (BuildId: ae7440bbdce614e0e79280c3b2e45b1df44e639c)
      #4 0x7164cfca49bb in __pthread_kill_implementation nptl/pthread_kill.c:43:17
      #5 0x7164cfca49bb in __pthread_kill_internal nptl/pthread_kill.c:89:10
      #6 0x7164cfca49bb in pthread_kill nptl/pthread_kill.c💯10
      #7 0x7164cfc4579d in raise signal/../sysdeps/posix/raise.c:26:13
      #8 0x7164cfc288cc in abort stdlib/abort.c:73:3
      #9 0x556e92f9d591 in assertion_fail(std::source_location const&, std::basic_string_view<char, std::char_traits<char>>) /mnt/my_storage/bitcoin/src/util/check.cpp:41:5
      #10 0x556e9250daf0 in bool&& inline_assertion_check<false, bool>(bool&&, std::source_location const&, std::basic_string_view<char, std::char_traits<char>>) /mnt/my_storage/bitcoin/src/util/check.h:90:13
      #11 0x556e9250daf0 in unsigned long CheckedSub<unsigned long, bool>(unsigned long, bool) /mnt/my_storage/bitcoin/src/util/overflow.h:44:5
      #12 0x556e9250daf0 in CoinsViewCacheCursor::NextAndMaybeErase(std::pair<COutPoint const, CCoinsCacheEntry>&) /mnt/my_storage/bitcoin/src/coins.h:282:25
      #13 0x556e92507eb2 in (anonymous namespace)::MutationGuardCoinsViewCache::BatchWrite(CoinsViewCacheCursor&, uint256 const&) /mnt/my_storage/bitcoin/src/test/fuzz/coins_view.cpp:90:75
      #14 0x556e92c17a2b in CCoinsViewCache::Flush(bool) /mnt/my_storage/bitcoin/src/coins.cpp:282:11
      #15 0x556e924fb732 in TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_1::operator()() const /mnt/my_storage/bitcoin/src/test/fuzz/coins_view.cpp:135:34
      #16 0x556e924fb732 in unsigned long CallOneOf<TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_0, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_1, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_2, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_3, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_4, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_5, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_6, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_7, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_8, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_9, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_10, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_11>(FuzzedDataProvider&, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_0, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_1, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_2, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_3, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_4, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_5, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_6, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_7, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_8, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_9, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_10, TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool)::$_11) /mnt/my_storage/bitcoin/src/test/fuzz/util.h:42:27
      #17 0x556e924fb732 in TestCoinsView(FuzzedDataProvider&, CCoinsViewCache&, CCoinsView&, bool) /mnt/my_storage/bitcoin/src/test/fuzz/coins_view.cpp:114:9
      #18 0x556e92503b0c in coins_view_overlay_fuzz_target(std::span<unsigned char const, 18446744073709551615ul>) /mnt/my_storage/bitcoin/src/test/fuzz/coins_view.cpp:404:5
      #19 0x556e92bcb7a5 in std::function<void (std::span<unsigned char const, 18446744073709551615ul>)>::operator()(std::span<unsigned char const, 18446744073709551615ul>) const /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/bits/std_function.h:593:9
      #20 0x556e92bcb7a5 in test_one_input(std::span<unsigned char const, 18446744073709551615ul>) /mnt/my_storage/bitcoin/src/test/fuzz/fuzz.cpp:88:5
      #21 0x556e92bcb7a5 in LLVMFuzzerTestOneInput /mnt/my_storage/bitcoin/src/test/fuzz/fuzz.cpp:216:5
      #22 0x556e9219318f in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/mnt/my_storage/bitcoin/build_fuzz/bin/fuzz+0x185218f) (BuildId: d77c4d5f9dfd38ea06fab463f49341735205e109)
      #23 0x556e92192799 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/mnt/my_storage/bitcoin/build_fuzz/bin/fuzz+0x1851799) (BuildId: d77c4d5f9dfd38ea06fab463f49341735205e109)
      #24 0x556e92194139 in fuzzer::Fuzzer::MutateAndTestOne() (/mnt/my_storage/bitcoin/build_fuzz/bin/fuzz+0x1853139) (BuildId: d77c4d5f9dfd38ea06fab463f49341735205e109)
      #25 0x556e92194c95 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (/mnt/my_storage/bitcoin/build_fuzz/bin/fuzz+0x1853c95) (BuildId: d77c4d5f9dfd38ea06fab463f49341735205e109)
      #26 0x556e92181255 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/mnt/my_storage/bitcoin/build_fuzz/bin/fuzz+0x1840255) (BuildId: d77c4d5f9dfd38ea06fab463f49341735205e109)
      #27 0x556e921ad696 in main (/mnt/my_storage/bitcoin/build_fuzz/bin/fuzz+0x186c696) (BuildId: d77c4d5f9dfd38ea06fab463f49341735205e109)
      #28 0x7164cfc2a577 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
      #29 0x7164cfc2a63a in __libc_start_main csu/../csu/libc-start.c:360:3
      #30 0x556e921757e4 in _start (/mnt/my_storage/bitcoin/build_fuzz/bin/fuzz+0x18347e4) (BuildId: d77c4d5f9dfd38ea06fab463f49341735205e109)

  NOTE: libFuzzer has rudimentary signal handlers.
        Combine libFuzzer with AddressSanitizer or similar for better crash reports.
  SUMMARY: libFuzzer: deadly signal
  MS: 2 PersAutoDict-CopyPart- DE: "\005\000"-; base unit: ecb626aff8724f0fdde38a0a6965718f2096d474
  artifact_prefix='/tmp/fuzz_artifacts/'; Test unit written to /tmp/fuzz_artifacts/crash-1d19026c1a23f08bfe693fd684a56ce51187c6e5
  ./build_fuzz/bin/fuzz /tmp/fuzz_corpus/coins_view_overlay -max_total_time=3600 -rss_limit_mb=2560 -artifact_prefix=/tmp/fuzz_artifacts/ >fuzz-16.log 2>&1
  ```

  </details>

  The coins view fuzz targets can call `AddCoin`/`AddCoins` and construct `BatchWrite` cursors in ways that violate `CCoinsViewCache` caller contracts. These invalid states can trigger `BatchWrite` `std::logic_error` and can desync dirty-entry accounting (caught by `Assume(m_dirty_count == 0)` currently).

  Make the fuzzer avoid generating invalid states instead of catching and resetting:
  * Derive `AddCoin`’s `possible_overwrite` from `PeekCoin`, so `possible_overwrite=false` is only used when the outpoint is absent - similarly to 67c0d1798e/src/test/fuzz/coinscache_sim.cpp (L312-L317)
  - Only use `AddCoins(check=false)` when we have confirmed the txid has no unspent outputs; otherwise fall back to `check=true` so `AddCoins` determines overwrites via the view.
  - When constructing a `CoinsViewCacheCursor`, avoid setting `FRESH` when the parent already has an unspent coin, and ensure `FRESH` implies `DIRTY`.

  ### Fuzzing
  The original error could be reproduced in ~10 minutes using `coins_view_overlay`. I ran the `coins_view`, `coins_view_db`, `coins_view_overlay`, and `coinscache_sim` fuzzers for this PR overnight and they didn't fail anymore.

ACKs for top commit:
  achow101:
    ACK 3281824ecfa72c4f69ab69c94003b7f5a82c7265
  sipa:
    ACK 3281824ecfa72c4f69ab69c94003b7f5a82c7265. Ran the 4 relevant fuzz tests for ~1 CPU day each. Will run more overnight.
  andrewtoth:
    ACK 3281824ecfa72c4f69ab69c94003b7f5a82c7265

Tree-SHA512: b8155e8d21740eb7800e373c27a8a1457eb84468c24af879bac5a1ed251ade2aec99c34a350a31f2ebb74e41bb7380bf20214d38d14fe23310a43282d2434fb7
2026-02-24 14:44:45 -08:00
Ava Chow
c88c916e72
Merge bitcoin/bitcoin#34653: test: improve txospender index tests code
e8f8b74a46aa075bf6c74c104fd572cc89d3b53b test: index, improve txospenderindex_initial_sync() test code (furszy)
ac3bea07cdceac9e316448a9a5f190848156efd5 test: improve rpc_gettxspendingprevout.py code (furszy)

Pull request description:

  Fixes #34637.

  Was reviewing #34637 and, while reading the new txospender index
  test code for the first time, found it could use some cleanups. Finding
  stuff in there is harder than it should be due to the amount of dup code.

  The first commit cleans up `rpc_gettxspendingprevout.py` by introducing
  helper functions to avoid repeating the same dicts everywhere, using
  for-loops instead of duplicating the same checks for each node, and
  renaming variables to better reflect what they actually represent.

  The second commit reorganizes `txospenderindex_initial_sync()`
  moving index initialization after the test setup phase, since the index
  doesn't participate in it anyway. It adds a post-sync check to catch
  cases where `Sync()` aborted prematurely.

  Note:
  This is just a pre-work for deeper index changes I'm cooking.

ACKs for top commit:
  achow101:
    ACK e8f8b74a46aa075bf6c74c104fd572cc89d3b53b
  sedited:
    Re-ACK e8f8b74a46aa075bf6c74c104fd572cc89d3b53b
  w0xlt:
    reACK e8f8b74a46aa075bf6c74c104fd572cc89d3b53b

Tree-SHA512: 3f7026712ab20a43f376afa28c683dcd5daec8ed1bbf1c36d7ec6bbf231f468d4de74efae4aa8295ff3afb83986286ccaf31c03b34e45fc9971652f064791ed0
2026-02-24 11:12:23 -08:00
Pieter Wuille
744d47fcee clusterlin: adopt trained cost model (feature)
See the comments for the SFLDefaultCostModel class for details on how
the numbers were obtained.
2026-02-24 12:05:17 -05:00
Pieter Wuille
4eefdfc5b7 clusterlin: rescale costs (preparation) 2026-02-24 10:45:49 -05:00
Pieter Wuille
ecc9a84f85 clusterlin: use 'cost' terminology instead of 'iters' (refactor) 2026-02-24 10:08:47 -05:00
furszy
e8f8b74a46
test: index, improve txospenderindex_initial_sync() test code
The index is now initialized after the setup phase (chain generation
and txs creation), since it doesn't participate on it at all.
This improves readability and splits setup from what we actually
want to check.

This also adds a check after Sync() to verify the index best block hash
matches the tip, so we know it fully synced before checking the
processed data. This will help catching errors as Sync() could have
aborted prematurely.

As a happy side effect, the SyncWithValidationInterfaceQueue() call at
the end of the test is no longer needed and has been removed.
2026-02-24 11:57:29 -03:00
Ryan Ofsky
bd9e0e65f5
Merge bitcoin/bitcoin#34184: mining: add cooldown to createNewBlock() immediately after IBD
fcaec2544b32226fd5357a88506fe080058d25bc doc: release note for IPC cooldown and interrupt (Sjors Provoost)
1e82fa498cf4881466f0539146c101242b9dc30d mining: add interrupt() (Sjors Provoost)
a11297a9048e0d910915e1a37b2be467c057a78d mining: add cooldown argument to createNewBlock() (Sjors Provoost)

Pull request description:

  As reported in #33994, connected mining clients will receive a flood of new templates if the node is still going through IBD or catching up on the last 24 hours. This PR fixes that using an _optional_ cooldown mechanism, only applied to `createNewBlock()`.

  First, cooldown waits for IBD. Then, as the tip keeps moving forward, it waits a few seconds to see if the tip updated. If so, it restarts the timer and waits again. The trade-offs for this mechanism are explained below.

  Because this PR changes `createNewBlock()` from a method that returns quickly to one that can block for minutes, we rely on #34568 to fix a bug in our `.capnp` definition, adding the missing `context` to `createNewBlock` (and `checkBlock`).

  The second commit then adds an `interrupt()` method so that clients can cleanly disconnect.

  ---

  ## Rationale

  The cooldown argument is optional, and not used by internal non-IPC code, for two reasons:

  1. The mechanism wreaks havoc on the functional test suite, which would require very careful mock time handling to work around. But that's pointless, because only IPC clients need it.
  2. It needs to be optional for IPC clients too, because in some situations, like a signet with only one miner, waiting for IBD can mean being stuck forever.

  The reason it's only applied to `createNewBlock()` is that this is the first method called by clients; `waitNext()` is a method on the interface returned by `createNewBlock()`, at which point the cooldown is done.

  After IBD, we wait N seconds if the header is N blocks ahead of the tip, with a minimum of 3 and a maximum of 20 seconds. The minimum waiting time is short enough that it shouldn't be annoying or confusing for someone manually starting up a client. While the maximum should be harmless if it happens spuriously (which it shouldn't).

  If the minimum wait is too short, clients get a burst of templates, as observed in the original issue. We can't entirely rule this out without a lot of additional complexity (like scanning our own log file for heuristics). This PR should make it a lot less likely, and thanks to the IBD wait also limit it to one day worth of blocks (`-maxtipage`).

  Some test runs on an M4 MacBook Pro, where I had a node catch up on the last few days worth of blocks:

  <img width="872" height="972" alt="Schermafbeelding 2026-02-04 om 18 21 17" src="https://github.com/user-attachments/assets/7902a0f2-0e0b-4604-9688-cec2da073261" />

  As the chart shows, sometimes it takes longer than 3 seconds. But it turns out that in all those cases there were quite a few headers ahead of the tip. It also demonstrates that it's important to first wait for IBD, because it's less likely a random tip update takes longer than 20 seconds.

  - modified sv2-apps: https://github.com/Sjors/sv2-apps/tree/2026/02/cooldown
  - test script: https://gist.github.com/Sjors/feb6122c97acc2b9e6d66b168614609c#file-run_mainnet_pool_loop-zsh
  - chart script: https://gist.github.com/Sjors/feb6122c97acc2b9e6d66b168614609c#file-tip_interval_charts-py

ACKs for top commit:
  ryanofsky:
    Code review ACK fcaec2544b32226fd5357a88506fe080058d25bc. Only changes since last review were removing two cooldown arguments from the mining IPC test to simplify it
  enirox001:
    ACK fcaec2544b

Tree-SHA512: 08b75470f7c5c80a583a2fdb918fad145e7d5377309e5c599f67fc0d0e3139d09881067ba50c74114f117e69da17ee50666838259491691c031b1feaf050853f
2026-02-24 06:54:17 -05:00
Lőrinc
3281824ecf
fuzz: prevent invalid FRESH entries and surface BatchWrite errors
Modify fuzzer logic to avoid setting `FRESH` for an outpoint that already exists unspent in the parent view, and ensure `FRESH` implies `DIRTY`.
This keeps cursor invariants realistic and lets `BatchWrite` failures expose real bugs without resetting state.
2026-02-23 15:58:24 +01:00
Lőrinc
780f460635
fuzz: avoid invalid AddCoin overwrites
The coins view fuzzer can call `AddCoin` with `possible_overwrite=false` for an outpoint that already exists unspent in the view, which violates the `AddCoin` caller contract.
Derive `possible_overwrite` from `PeekCoin` so `possible_overwrite=false` is only used when the outpoint is absent.
This matches the approach used by the `coinscache_sim` fuzzer, which derives the overwrite flag from simulated state.
2026-02-23 15:58:23 +01:00
Lőrinc
d7e0d510f2
fuzz: make AddCoins query view for overwrites
In validation, `AddCoins(check_for_overwrite=false)` is only used after BIP30 has already ensured the transaction does not overwrite any unspent outputs in the UTXO view.
The coins view fuzz target can call `AddCoins` with arbitrary txids, so using the `check_for_overwrite=false` fast path on non-coinbase transactions may violate the `AddCoin` caller contract and trigger logic errors.
Only use `check_for_overwrite=false` when we have first confirmed that none of the outputs are currently unspent.
Otherwise, fall back to `check_for_overwrite=true` so `AddCoins` determines overwrites via the view.
2026-02-23 15:58:07 +01:00
merge-script
d9c7364ac5
Merge bitcoin/bitcoin#34141: miniscript: Use Func and Expr when parsing keys, hashes, and locktimes
4b53cbd69220c1c786bb23a72c0b26a6f78a38f7 test: Test for musig() in various miniscript expressions (Ava Chow)
ec0f47b15cb3269015523e6fab8ae9241f4181a1 miniscript: Using Func and Expr when parsing keys, hashes, and locktimes (Ava Chow)
6fd780d4fbc497b657025afe48d0dfbf103ee120 descriptors: Increment key_exp_index in ParsePubkey(Inner) (Ava Chow)
b12281bd86e2298ba6cdd79d55c9d6e23e5136a5 miniscript: Use a reference to key_exp_index in KeyParser (Ava Chow)
ce4c66eb7c5e99e3df1c20d5c0ae8278a714b9f8 test: Test that key expression indexes match key count (Ava Chow)

Pull request description:

  The miniscript parser currently only looks for the next `)` when parsing key, hash, and locktime expressions. This fails to parse when the expressions contain a nested expression. Currently, this is only possible with `musig()` inside of key expressions. However, this pattern can be generalized to handling hashes and locktimes, so I implemented those too.

  Fixes #34076

ACKs for top commit:
  rkrux:
    ACK 4b53cbd69220c1c786bb23a72c0b26a6f78a38f7
  sipa:
    ACK 4b53cbd69220c1c786bb23a72c0b26a6f78a38f7
  darosior:
    Other than that, Approach ACK 4b53cbd69220c1c786bb23a72c0b26a6f78a38f7. That makes sense to me but i have not closely reviewed the code.

Tree-SHA512: 01040c7b07a59d8e3725ff11ab9543b256aea22535fb94059f490a5bb45319e859666af04c2f0a4edcb8cf1e6dfc7bd8a8271b21ad81143bafccd4d0a39cae9c
2026-02-21 12:18:56 +01:00
Ava Chow
d907d65acd
Merge bitcoin/bitcoin#29770: index: Check all necessary block data is available before starting to sync
fd06157d1465d93b960e8be6e8e419295abde9a1 test: Add coverage for restarted node without any block sync (Fabian Jahr)
3d7ab7ecb7dfcdfb8aaa45869388887b948841c8 rpc, test: Address feedback from #29668 (Fabian Jahr)
312919c9dd5dba7da20317604e1638bdc5010f14 test: Indices can not start based on block data without undo data (Fabian Jahr)
a9a3b29dd687b4c355e131fefc145e8e48b48b17 index: Check availability of undo data for indices (Fabian Jahr)
881ab4fc82fe3cf36b227cf1ba704448df160745 support multiple block status checks in CheckBlockDataAvailability (furszy)

Pull request description:

  Currently, we check that `BLOCK_HAVE_DATA` is available for all blocks an index needs to sync during startup. However, for `coinstatsindex` and `blockfilterindex` we also need the undo data for these blocks. If that data is missing in the blocks, we are currently still starting to sync each of these indices and then crash later when we encounter the missing data.

  This PR adds explicit knowledge of which block data is needed for each index and then checks its availability during startup before initializing the sync process on them.

  This also addresses a few open comments from #29668 in the last commit.

ACKs for top commit:
  achow101:
    ACK fd06157d1465d93b960e8be6e8e419295abde9a1
  furszy:
    utACK fd06157d1465d93b960e8be6e8e419295abde9a1
  sedited:
    Re-ACK fd06157d1465d93b960e8be6e8e419295abde9a1

Tree-SHA512: e2ed81c93372b02daa8ddf2819df4164f96d92de05b1d48855410ecac78d5fcd9612d7f0e63a9d57d7e75a0b46e1bea278e43ea87f2693af0220d1f9c600e416
2026-02-20 15:58:48 -08:00
Sjors Provoost
a11297a904
mining: add cooldown argument to createNewBlock()
At startup, if the needs to catch up, connected mining clients will
receive a flood of new templates as new blocks are connected.

Fix this by adding a cooldown argument to createNewBlock(). When set
to true, block template creation is briefly paused while the best
header chain is ahead of the tip.

This wait only happens when the best header extends the current tip,
to ignore competing branches.

Additionally, cooldown waits for isInitialBlockDownload() to latch to
false, which happens when there is less than a day of blocks left to sync.

When cooldown is false createNewBlock() returns immediately. The argument
is optional, because many tests are negatively impacted by this
mechanism, and single miner signets could end up stuck if no block
was mined for a day.

The getblocktemplate RPC also opts out, because it would add a delay
to each call.

Fixes #33994
2026-02-20 16:49:15 +01:00
merge-script
1a54886b63
Merge bitcoin/bitcoin#24539: Add a "tx output spender" index
0b96b9c600e0dd946fd4d0e827e7f7cbef7a571a Minimize mempool lock, sync txo spender index only when and if needed (sstone)
3d82ec5bdd019cf1c048c41fe44faa855fcb8b53 Add a "tx output spender" index (sstone)

Pull request description:

  This PR adds a new "tx output spender" index, which allows users to query which tx spent a given outpoint with the `gettxspendingprevout` RPC call that was added by https://github.com/bitcoin/bitcoin/pull/24408.

  Such an index would be extremely useful for Lightning, and probably for most layer-2 protocols that rely on chains of unpublished transactions.

  UPDATE: this PR is ready for review and issues have been addressed:
  - using a watch-only wallet instead would not work if there is a significant number of outpoints to watch (see https://github.com/bitcoin/bitcoin/pull/24539#issuecomment-1276595646)
  - this PR does not require `-txindex` anymore

  We use a composite key with 2 parts (suggested by romanz): hash(spent outpoint) and tx position, with an empty value. Average composite key size is 15 bytes.

  The spending tx can optionally be returned by `gettxspendingprevout` (even it `-txindex is not set`).

ACKs for top commit:
  hodlinator:
    re-ACK 0b96b9c600e0dd946fd4d0e827e7f7cbef7a571a
  sedited:
    Re-ACK 0b96b9c600e0dd946fd4d0e827e7f7cbef7a571a
  fjahr:
    ACK 0b96b9c600e0dd946fd4d0e827e7f7cbef7a571a
  w0xlt:
    reACK 0b96b9c600e0dd946fd4d0e827e7f7cbef7a571a

Tree-SHA512: 95c2c313ef4086e7d5bf1cf1a3c7b91cfe2bb1a0dcb4c9d3aa8a6e5bfde66aaca48d85a1f1251a780523c3e4356ec8a97fe6f5c7145bc6ccb6f820b26716ae01
2026-02-20 09:27:17 +01:00
Ryan Ofsky
ee2065fdea
Merge bitcoin/bitcoin#34165: coins: don't mutate main cache when connecting block
cae6d895f8a8cf5f57e05519536fda5d62b10841 fuzz: add target for CoinsViewOverlay (Andrew Toth)
86eda88c8e486eb1db724e60948f71349d050e1d fuzz: move backend mutating block to end of coins_view (Andrew Toth)
89824fb27b228a12d5c2f63106c2a4d793e73107 fuzz: pass coins_view_cache to TestCoinsView in coins_view (Andrew Toth)
73e99a59665551243d6dbe03a0e9baa9cab046b9 coins: don't mutate main cache when connecting block (Andrew Toth)
67c0d1798e6147f48d4bafc2c9e5ff30f2a62340 coins: introduce CoinsViewOverlay (Andrew Toth)
69b01af0eb9017a6ae7ca3134c9dcf89e74dbfa8 coins: add PeekCoin() (Andrew Toth)

Pull request description:

  This is a slightly modified version of the first few commits of #31132, which can be merged as an independent change. It has a small benefit on its own, but will help in moving the parent PR forward.

  When accessing coins via the `CCoinsViewCache`, methods like `GetCoin` can call `FetchCoin` which actually mutate `cacheCoins` internally to cache entries when they are pulled from the backing db. This is generally a performance improvement for single threaded access patterns, but it precludes us from accessing entries in a `CCoinsViewCache` from multiple threads without a lock.

  Another aspect is that when we use the resettable `CCoinsViewCache` view backed by the main cache for use in `ConnectBlock()`, we will insert entries into the main cache even if the block is determined to be invalid. This is not the biggest concern, since an invalid block requires proof-of-work. But, an attacker could craft multiple invalid blocks to fill the main cache. This would make us `Flush` the cache more often than necessary. Obviously this would be very expensive to do on mainnet.

  Introduce `CoinsViewOverlay`, a `CCoinsViewCache` subclass that reads coins without mutating the underlying cache via `FetchCoin()`.

  Add `PeekCoin()` to look up a Coin through a stack of `CCoinsViewCache` layers without populating parent caches. This prevents the main cache from caching inputs pulled from disk for a block that has not yet been fully validated. Once `Flush()` is called on the view, these inputs will be added as spent to `coinsCache` in the main cache via `BatchWrite()`.

  This is the foundation for async input fetching, where worker threads must not mutate shared state.

ACKs for top commit:
  l0rinc:
    ACK cae6d895f8a8cf5f57e05519536fda5d62b10841
  sipa:
    reACK cae6d895f8a8cf5f57e05519536fda5d62b10841
  sedited:
    Re-ACK cae6d895f8a8cf5f57e05519536fda5d62b10841
  willcl-ark:
    ACK cae6d895f8a8cf5f57e05519536fda5d62b10841
  vasild:
    Cursory ACK cae6d895f8a8cf5f57e05519536fda5d62b10841
  ryanofsky:
    Code review ACK cae6d895f8a8cf5f57e05519536fda5d62b10841. PR is basically back to the form I had acked the first time, implementing `PeekCoin()` by calling `GetCoin()`. This is not ideal because `PeekCoin()` is not supposed to modify caches and `GetCoin()` does that, but it at least avoids problems of the subsequent approach tried where `GetCoin()` calls `PeekCoin` and would result in bugs when subclasses implement `GetCoin` forgetting to override `PeekCoin`. Hopefully #34124 can clean all of this by making relevant methods pure virtual.

Tree-SHA512: a81a98e60ca9e47454933ad879840cc226cb3b841bc36a4b746c34b350e07c546cdb5ddc55ec1ff66cf65d1ec503d22201d3dc12d4e82a8f4d386ccc52ba6441
2026-02-19 22:10:41 -05:00
Ava Chow
c808dfbbdc
Merge bitcoin/bitcoin#34329: rpc,net: Add private broadcast RPCs
2a1d0db7994eb2aa8527944f62161b6b8af682da doc: Mention private broadcast RPCs in release notes (Andrew Toth)
c3378be10b0a90e81b46e53eb85c41eb8caabac5 test: Cover abortprivatebroadcast in p2p_private_broadcast (Andrew Toth)
557260ca14ac5fb4732f4ce0692a2bf364bb5238 rpc: Add abortprivatebroadcast (Andrew Toth)
15dff452eb61ae9e2fd7b48c957e795c4c397443 test: Cover getprivatebroadcastinfo in p2p_private_broadcast (Andrew Toth)
996f20c18af02281034c51af4b2766d8f4d37a2c rpc: Add getprivatebroadcastinfo (Andrew Toth)
5e64982541f301773156a87988c60ca7797a3f06 net: Add PrivateBroadcast::GetBroadcastInfo (Andrew Toth)
573bb542be80b63b1713a0b76bedaa5e37c3783f net: Store recipient node address in private broadcast (Andrew Toth)

Pull request description:

  Follow up from #29415

  Sending a transaction via private broadcast does not have any way for a user to track the status of the transaction before it gets returned by another peer. The default logs have been removed as well in #34267. Nor is there any way to abort a transaction once it has been added to the private broadcast queue.

  This adds two new RPCs:
  - `getprivatebroadastinfo` returns information about what transactions are in the private broadcast queue, including all the peers' addresses we have chosen and timestamps.
  - `abortprivatebroadcast` stops broadcasting a transaction in the private broadcast queue.

ACKs for top commit:
  nervana21:
    tACK 2a1d0db7994eb2aa8527944f62161b6b8af682da
  achow101:
    ACK 2a1d0db7994eb2aa8527944f62161b6b8af682da
  l0rinc:
    ACK 2a1d0db7994eb2aa8527944f62161b6b8af682da
  danielabrozzoni:
    tACK 2a1d0db7994eb2aa8527944f62161b6b8af682da
  sedited:
    ACK 2a1d0db7994eb2aa8527944f62161b6b8af682da

Tree-SHA512: cc8682d0be68a57b42bea6e3d091da2b80995d9e6d3b98644cb120a05c2b48a97c2e211173289b758c4f4e23f1d1a1f9be528a9b8c6644f71d1dd0ae5f673326
2026-02-19 13:42:11 -08:00
merge-script
739f75c098
Merge bitcoin/bitcoin#33512: coins: use dirty entry count for flush warnings and disk space checks
afb1bc120ecce2bf663093e15c93f5592c0d4a98 validation: Use dirty entry count in flush warnings and disk space checks (Pieter Wuille)
b413491a1cdd9a51f2aa10b775650f54f6785e3e coins: Keep track of number of dirty entries in `CCoinsViewCache` (Pieter Wuille)
7e52b1b945c4137e0fb05715090635ce82ed04b3 fuzz: call `EmplaceCoinInternalDANGER` as well in `SimulationTest` (Lőrinc)

Pull request description:

  ### Problem
  Now that non-wiping flushes are possible (#28280, #28233), the cache may be mostly clean at flush time.
  But the flush warning, disk-space check, and benchmark logging still used total cache size, so a node with a 10 GiB cache that only needs to write a small fraction of dirty entries could still trigger a scary warning via the disk-space checks.

  The previous `DynamicMemoryUsage` metric was also fundamentally wrong for estimating disk writes, even before non-wiping flushes. In-memory coin size differs from on-disk write size due to LevelDB overhead, log doubling, and compaction.

  The warning also only fired in `FlushStateToDisk`, so `AssumeUTXO` snapshot loads never warned at all.

  ### Fix

  This PR tracks the actual number of dirty entries via `m_dirty_count` in `CCoinsViewCache`, maintained alongside the existing dirty-flag linked list, `SanityCheck` cross-validating both counts.

  The warning and benchmark log move from `FlushStateToDisk` down to `CCoinsViewDB::BatchWrite`, where the actual I/O happens. This is the single place all flush paths converge (regular flushes, syncs, and snapshot loads), so the warning now fires correctly for `AssumeUTXO` too.
  The threshold changes from 1 GiB of memory to 10 million dirty entries, which is roughly equivalent but avoids the in-memory vs on-disk size confusion.

  The disk-space safety check now uses `GetDirtyCount()` with the existing conservative 48-byte-per-entry estimate, preventing unnecessary shutdowns when the cache is large but mostly clean.

  ---

  Note: the first commit adds fuzz coverage for `EmplaceCoinInternalDANGER` in `SimulationTest` to exercise the accounting paths before modifying them.
  Note: this is a revival of #31703 with all outstanding review feedback addressed.

ACKs for top commit:
  Eunovo:
    Concept ACK afb1bc120e
  andrewtoth:
    re-ACK afb1bc120ecce2bf663093e15c93f5592c0d4a98
  sipa:
    Code review ACK afb1bc120ecce2bf663093e15c93f5592c0d4a98
  sedited:
    ACK afb1bc120ecce2bf663093e15c93f5592c0d4a98

Tree-SHA512: 4133c6669fd20836ae2fb62ed804cdf6ebaa61076927b54fc412e42455a2f0d4cadfab0844064f9c32431eacb1f5e47b78de8e5cde1b26ba7239a7becf92f369
2026-02-19 22:18:38 +01:00
Ava Chow
02c83fef84
Merge bitcoin/bitcoin#34577: http: fix submission during shutdown race
726b3663cc8e2164d4e9452f12f5866f5e8f6f1a http: properly respond to HTTP request during shutdown (furszy)
59d24bd5dd2a4549888cf7c557461e6b4959f82f threadpool: make Submit return Expected instead of throwing (furszy)

Pull request description:

  Fixes #34573.

  As mentioned in https://github.com/bitcoin/bitcoin/issues/34573#issuecomment-3891596958, the ThreadPool PR (#33689) revealed an existing issue.

  Before that PR, we were returning an incorrect error "Request rejected because http work queue depth exceeded" during shutdown for unhandled requests (we were not differentiating between "queue depth exceeded" and "server interrupted" errors). Now, with the ThreadPool inclusion, we return the proper error but we don't handle it properly.

  This PR improves exactly that. Handling the missing error and properly returning it to the user.

  The race can be reproduced as follows:

  1) The server receives an http request.
  2) Processing of the request is delayed, and shutdown is triggered in the meantime.
  3) During shutdown, the libevent callback is unregistered and the threadpool interrupted.
  4) The delayed request (step 2) resumes and tries to submit a task to the now-interrupted server.

  Reproduction test can be found https://github.com/bitcoin/bitcoin/pull/34577#issuecomment-3902672521.

  Also, to prevent this kind of issue from happening again, this PR changes task submission
  to return the error as part of the function's return value using `util::Expected` instead of
  throwing the exception. Unlike exceptions, which require extra try-catch blocks and can be
  ignored, returning `Expected` forces callers to explicitly handle failures, and attributes
  like `[[nodiscard]]` allow us catch unhandled ones at compile time.

ACKs for top commit:
  achow101:
    ACK 726b3663cc8e2164d4e9452f12f5866f5e8f6f1a
  sedited:
    ACK 726b3663cc8e2164d4e9452f12f5866f5e8f6f1a
  pinheadmz:
    re-ACK 726b3663cc8e2164d4e9452f12f5866f5e8f6f1a
  andrewtoth:
    ACK 726b3663cc8e2164d4e9452f12f5866f5e8f6f1a
  hodlinator:
    re-ACK 726b3663cc8e2164d4e9452f12f5866f5e8f6f1a

Tree-SHA512: ef026e299adde1148c9fc575e7d937e957bf0ddedfc1cf081941b568736417c2eefcd8bc8c8aea795d7347040ed05da4371bddcdbda7d385e04bf4dc8d875780
2026-02-19 12:41:12 -08:00
merge-script
910bd1c964
Merge bitcoin/bitcoin#34582: rpc: Properly parse -rpcworkqueue/-rpcthreads
fa5672dcafa154dff7409eaaf762febe1d76aad7 refactor: [gui] Use SettingTo<int64_t> over deprecated SettingToInt (MarcoFalke)
fac3ecaf69d6f2d655e71644c98364206f7e2ddc rpc: Properly parse -rpcworkqueue/-rpcthreads (MarcoFalke)
faee36f63b5fde886458d0415778719ea2233d14 util: Add SettingTo<Int>() and GetArg<Int>() (MarcoFalke)

Pull request description:

  The integral arg parsing has many issues:

  * There is no way to parse an unsigned integral type at all
  * There is no way to parse an integral type of less width than int64_t
  * As a result, calling code splatters confusing c-style casts just to let the code compile. However, usually there are no range checks and proper range handling.

  For example, when someone (maybe for testing) wants to set the rpc work queue to the maximum possible number, there is no easy way to do so without reading the source code and manually crafting the exact integer value. Using the "9999 hack" will silently set it to `-1` (!)

  To test:

  `/bld-cmake/bin/bitcoin-qt -datadir=/tmp -regtest -rpcworkqueue=99999999999999999999999999 -printtoconsole=1 -server=1 -debug=http | grep 'set work queue of depth'`

  Before:

  ```
  [http] set work queue of depth -1
  ```

  After:

  ```
  [http] set work queue of depth 2147483647

ACKs for top commit:
  stickies-v:
    ACK fa5672dcafa154dff7409eaaf762febe1d76aad7
  pinheadmz:
    ACK fa5672dcafa154dff7409eaaf762febe1d76aad7
  sedited:
    ACK fa5672dcafa154dff7409eaaf762febe1d76aad7

Tree-SHA512: e5060453a0aa1c4e27080e928b0ae2d1015fe487246e4059866eef415f301bc7712ce306d95076ce5b66a5e57c620715b33998192c0ff06b0384085a0390c714
2026-02-19 17:44:52 +01:00
sstone
3d82ec5bdd
Add a "tx output spender" index
Adds an outpoint -> txid index, which can be used to find which transactions spent a given output.
We use a composite key with 2 parts (suggested by @romanz): hash(spent outpoint) and tx position, with an empty value.
To find the spending tx for a given outpoint, we do a prefix search (prefix being the hash of the provided outpoint), and for all keys that match this prefix
we load the tx at the position specified in the key and return it, along with the block hash, if does spend the provided outpoint.
To handle reorgs we just erase the keys computed from the removed block.

This index is extremely useful for Lightning and more generally for layer-2 protocols that rely on chains of unpublished transactions.
If enabled, this index will be used by `gettxspendingprevout` when it does not find a spending transaction in the mempool.
2026-02-19 11:41:53 +01:00
Ava Chow
6d482b22de
Merge bitcoin/bitcoin#32138: wallet, rpc: remove settxfee and paytxfee
24f93c9af7f6627cd7d09a1a5f10667846b048eb release note (Pol Espinasa)
331a5279d2775fb701a0bf4607436ec05e476df3 wallet, rpc:remove settxfee and paytxfee (Pol Espinasa)

Pull request description:

  **Summary**

  This PR removes the settxfee RPC and paytxfee setting (Bitcoin Core 31.0).
  These two features were deprecated in https://github.com/bitcoin/bitcoin/pull/31278.

ACKs for top commit:
  achow101:
    ACK 24f93c9af7f6627cd7d09a1a5f10667846b048eb
  w0xlt:
    reACK 24f93c9af7f6627cd7d09a1a5f10667846b048eb

Tree-SHA512: e090f1a72ba2cbeba7c982dd51dfdcf6baf0a164827337cf56fd85f733e143b8d6116b8cd53c59c812cacef193dfa0b101a830fc455e32bf225e8505e7b2a554
2026-02-18 16:36:13 -08:00
merge-script
655b9d12ee
Merge bitcoin/bitcoin#32950: validation: remove BLOCK_FAILED_CHILD
fb3e1bf9c9772631571ca46d29c50330ebf54dfd test: check LoadBlockIndex correctly recomputes invalidity flags (stratospher)
29740c06ac53f55f71acf2a1b42b193aac39f579 validation: remove BLOCK_FAILED_MASK (stratospher)
b5b2956bda32b7b4ebc25c83b4d792ecd01f02b4 validation: reset BLOCK_FAILED_CHILD to BLOCK_FAILED_VALID when loading from disk (stratospher)
37bc207852788340dc2a1b33a73748f43226978a validation: stop using BLOCK_FAILED_CHILD (stratospher)
120c631e16893821ea4c73ff70ac60e4fec0429f refactor: use clearer variables in InvalidateBlock() (stratospher)
18f11695c755c379ca67ca0bce8d17492ad9af18 validation: don't update BLOCK_FAILED_VALID to BLOCK_FAILED_CHILD in InvalidateBlock (stratospher)

Pull request description:

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

  even though we have a distinction between `BLOCK_FAILED_VALID` and `BLOCK_FAILED_CHILD` in the codebase,
  we don't use it for anything. Whenever we check for BlockStatus, we use `BLOCK_FAILED_MASK` which encompasses both of them.

  Since there is no functional difference between `BLOCK_FAILED_VALID` and `BLOCK_FAILED_CHILD` and it's added
  code complexity to correctly categorise them (ex: https://github.com/bitcoin/bitcoin/pull/31405#discussion_r1914366243, https://github.com/bitcoin/bitcoin/pull/16856#issuecomment-565506585), we could just remove it.

  Looking for conceptual feedback on whether it's better to improve handling of `BLOCK_FAILED_CHILD` in the codebase or remove `BLOCK_FAILED_CHILD`.

  Of less relevance, but it would also fix a `reconsiderblock` crash that could happen in the situation mentioned in https://github.com/bitcoin/bitcoin/issues/32173#issuecomment-2767030982

  Similar attempt in the past in https://github.com/bitcoin/bitcoin/pull/16856#issuecomment-568073859

ACKs for top commit:
  stickies-v:
    re-ACK fb3e1bf9c9772631571ca46d29c50330ebf54dfd
  alexanderwiederin:
    ACK fb3e1bf9c9772631571ca46d29c50330ebf54dfd
  mzumsande:
    re-ACK fb3e1bf9c9772631571ca46d29c50330ebf54dfd

Tree-SHA512: e97b739885c40a8c021966438e9767cc02bc183056236d6a8c64f6819347ae70c0fbcd71cc2528917560d9f4fd56aed45faf1b6c75d98de7b08b621693a97fbc
2026-02-18 15:47:57 +00:00
merge-script
2706758dc3
Merge bitcoin/bitcoin#34349: util: Remove brittle and confusing sp::Popen(std::string)
fa48d421636c256069010bc03c121c36ed9c0a0c test: Stricter unit test (MarcoFalke)
fa626bd143419a7141311e84490aacd8a6691c33 util: Remove brittle and confusing sp::Popen(std::string) (MarcoFalke)

Pull request description:

  The subprocess Popen call that accepts a full `std::string` has many issues:

  * It promotes brittle and broken code, where spaces are not properly quoted. Example: https://github.com/bitcoin/bitcoin/pull/33929#discussion_r2590523065
  * The internally used `util::split` function does incorrectly split on spaces, instead of using `shlex.split`.
  * It is redundant and not needed, because a vector interface already exists.

  Fix all issues by removing it and just using the vector interface.

  This pull request should not change any behavior: Note that the command taken from `gArgs.GetArg("-signer", "")` is still passed through the `sp::util::split` helper, just like before. Fixing that is left for a follow-up, so that this change here is basically just a refactor.

  This also fixes a unit test bug as a side-effect: Fixes https://github.com/bitcoin/bitcoin/issues/32574.

ACKs for top commit:
  janb84:
    cr ACK fa48d421636c256069010bc03c121c36ed9c0a0c
  fjahr:
    Code review ACK fa48d421636c256069010bc03c121c36ed9c0a0c
  hebasto:
    re-ACK fa48d421636c256069010bc03c121c36ed9c0a0c.

Tree-SHA512: 3d29226977c9392502f9361e2bd42b471ad03761bbf6a94ef6e545cbe4492ad5858da1ac9cc64b2791aacb9b6e6f3c3f63dbcc3a2bf45f6a13b5bc33eddf8c2b
2026-02-18 10:18:25 +00:00
furszy
59d24bd5dd
threadpool: make Submit return Expected instead of throwing
Unlike exceptions, which can be ignored as they require extra try-catch
blocks, returning expected errors forces callers to always handle
submission failures.

Not throwing an exception also fixes an unclean shutdown bug
#34573 since we no longer throw when attempting to Submit()
from the libevent callback http_request_cb().
2026-02-17 15:02:40 -05:00
stratospher
fb3e1bf9c9 test: check LoadBlockIndex correctly recomputes invalidity flags
Add a test for block index transitioning from legacy
BLOCK_FAILED_CHILD to BLOCK_FAILED_VALID behavior.

In the scenario where a valid block has a BLOCK_FAILED_CHILD
parent and a BLOCK_FAILED_VALID grandparent, ensure that all
three blocks are correctly marked as BLOCK_FAILED_VALID
after reloading the block index.
2026-02-17 21:40:46 +05:30
stratospher
29740c06ac validation: remove BLOCK_FAILED_MASK
since it's the same as BLOCK_FAILED_VALID now
2026-02-17 21:40:46 +05:30
stratospher
37bc207852 validation: stop using BLOCK_FAILED_CHILD
even though we have a distinction between BLOCK_FAILED_VALID
and BLOCK_FAILED_CHILD in the codebase, we don't use it for
anything. since there's no functional difference between them
and it's unnecessary code complexity to categorise them correctly,
just mark as BLOCK_FAILED_VALID instead.
2026-02-17 21:40:28 +05:30
Pieter Wuille
b684f954bb clusterlin: unidirectional MakeTopological initially (optimization)
It suffices to initially only attempt one direction of merges in
MakeTopological(), and only try both directions on chunks that are the
result of other merges.
2026-02-17 09:04:36 -05:00
Pieter Wuille
1daa600c1c clusterlin: track suboptimal chunks (optimization)
This avoids adding them a second time to m_suboptimal_chunks when they
happen to already be there.
2026-02-17 09:04:36 -05:00
Pieter Wuille
6f898dbb8b clusterlin: simplify PickMergeCandidate (optimization)
The current process consists of iterating over the transactions of the
chunk one by one, and then for each figuring out which of its
parents/children are in unprocessed chunks.

Simplify this (and speed it up slightly) by splitting this process into
two phases: first determine the union of all parents/children, and then
find which chunks those belong to.
2026-02-17 09:04:36 -05:00
Pieter Wuille
7c6f63a8a9 clusterlin: pool SetInfos (preparation)
This significantly changes the data structures used in SFL, based on the
observation that the DepData::top_setinfo fields are quite wasteful:
there is one per dependency (up to n^2/4), but we only ever need one per
active dependency (of which there at most n-1). In total, the number of
chunks plus the number of active dependencies is always exactly equal to
the number of transactions, so it makes sense to have a shared pool of
SetInfos, which are used for both chunks and top sets.

To that effect, introduce a separate m_set_info variable, which stores a
SetInfo per transaction. Some of these are used for chunk sets, and some
for active dependencies' top sets. Every activation transforms the
parent's chunk into the top set for the new dependency. Every
deactivation transforms the top set into the new parent chunk.

With indexes into m_set_data (SetIdx) becoming bounded by the number of
transactions, we can use a SetType to represent sets of SetIdxs.
Specifically, an m_chunk_idxs is added which contains all SetIdx
referring to chunks. This leads to a much more natural way of iterating
over chunks.

Also use this opportunity to normalize many variable names.
2026-02-17 09:04:36 -05:00
Pieter Wuille
f66fa69ce0 clusterlin: split tx/chunk dep counting (preparation)
This splits the chunk_deps variable in LoadLinearization in two, one for
tracking tx dependencies and one for chunk dependencies. This is a
preparation for a later commit, where chunks won't be identified anymore
by a representative transaction in them, but by a separate index. With
that, it seems weird to keep them both in the same structure if they
will be indexed in an unrelated way.

Note that the changes in src/test/util/cluster_linearize.h to the table
of worst observed iteration counts are due to switching to a different
data set, and are unrelated to the changes in this commit.
2026-02-17 09:04:36 -05:00
Pieter Wuille
900e459778 clusterlin: avoid depgraph argument in SanityCheck (cleanup)
Since the deterministic ordering change, SpanningForestState holds a
reference to the DepGraph it is linearizing. So this means we do not
need to pass it to SanityCheck() as an argument anymore.
2026-02-17 09:04:36 -05:00
merge-script
a7c29df0e5
Merge bitcoin/bitcoin#34552: fees: refactor: separate feerate format from fee estimate mode
c1355493e2c26b613109bfac3dcd898b3acca75a refactor: fees: split fee rate format from fee estimate mode (ismaelsadeeq)
922ebf96ed6674ae7acc6f0cde4d7b064f759834 refactor: move-only: move `FeeEstimateMode` enum to `util/fees.h` (ismaelsadeeq)

Pull request description:

  ### Motivation

  Part of #34075

  - The `FeeEstimateMode` enum was responsible for both selecting the fee estimation algorithm and specifying the fee rate' format.

  ####  Changes in this PR:
     * The `FeeEstimateMode` enum (`UNSET`, `ECONOMICAL`, `CONSERVATIVE`) is moved to a new util/fees.h header.
     * A new `FeeRateFormat `enum (`BTC_KVB`, `SAT_VB`) is introduced in `policy/feerate.h` for feerate formatting.
     * The `CFeeRate::ToString()` method is updated to use `FeeRateFormat`.
     * All relevant function calls have been updated to use the new `FeeRateFormat` enum for formatting and `FeeEstimateMode` for fee estimation mode.

   This refactoring separates these unrelated responsibilities to improve code clarity.

ACKs for top commit:
  l0rinc:
    ACK c1355493e2c26b613109bfac3dcd898b3acca75a
  furszy:
    utACK c1355493e2c26b613109bfac3dcd898b3acca75a
  musaHaruna:
    ACK [c135549](c1355493e2) — reviewed in the context of PR [34075](https://github.com/bitcoin/bitcoin/pull/34075)
  willcl-ark:
    ACK c1355493e2c26b613109bfac3dcd898b3acca75a

Tree-SHA512: 7cbe36350744313d3d688d3fd282a58c441af1818b1e8ad9cddbc911c499a5205f8d4a39c36b21fed60542db1ef763eb69752d141bcef3393bf33c0922018645
2026-02-17 14:15:38 +01:00
MarcoFalke
fa48d42163
test: Stricter unit test
Now that the previous commit fixed a unit test bug, make the test
stricter, to prevent this issue from happening again in the future.
2026-02-17 12:55:28 +01:00
MarcoFalke
fa626bd143
util: Remove brittle and confusing sp::Popen(std::string) 2026-02-17 12:55:26 +01:00
Fabian Jahr
3d7ab7ecb7
rpc, test: Address feedback from #29668 2026-02-17 12:44:23 +01:00
Fabian Jahr
a9a3b29dd6
index: Check availability of undo data for indices 2026-02-17 12:44:21 +01:00
MarcoFalke
faee36f63b
util: Add SettingTo<Int>() and GetArg<Int>()
Redirect:
* SettingToInt to SettingTo<int64_t>, and
* GetIntArg to GetArg<int64_t>
2026-02-16 09:52:28 +01:00
merge-script
84e826ddc1
Merge bitcoin/bitcoin#34511: test: fully reset the state of CConnman in tests
2cb7e99deee1017a6edd94d82de556895138361d test: also reset CConnman::m_private_broadcast in tests (Vasil Dimov)
91b7c874e2b1479ed29f067cd1bef7724aabd951 test: add ConnmanTestMsg convenience method Reset() (Vasil Dimov)

Pull request description:

  Member variables of `CConnman::m_private_broadcast` (introduced in
  https://github.com/bitcoin/bitcoin/pull/29415) could influence the tests
  which creates non-determinism if the same instance of `CConnman` is used
  for repeated test iterations.

  So, reset the state of `CConnman::m_private_broadcast` from
  `ConnmanTestMsg::Reset()`. Currently this affects the fuzz tests
  `process_message` and `process_messages`.

  Reported in https://github.com/bitcoin/bitcoin/issues/34476#issuecomment-3849088794

ACKs for top commit:
  maflcko:
    review ACK 2cb7e99deee1017a6edd94d82de556895138361d 🚙
  Crypt-iQ:
    tACK 2cb7e99deee1017a6edd94d82de556895138361d
  frankomosh:
    Code Review ACK 2cb7e99deee1017a6edd94d82de556895138361d
  brunoerg:
    code review ACK 2cb7e99deee1017a6edd94d82de556895138361d

Tree-SHA512: 0f4b114542da8dc611689457ce67034c15cbfe409b006b2db72bc74078ee9513f5ce3d0e6e67d37c127cfa0a5170fe72fe3ea45ce2a61d45a358dd11bd1881f8
2026-02-13 11:17:26 +00:00
Pol Espinasa
331a5279d2
wallet, rpc:remove settxfee and paytxfee 2026-02-13 10:52:25 +01:00
Andrew Toth
cae6d895f8
fuzz: add target for CoinsViewOverlay
Co-authored-by: l0rinc <pap.lorinc@gmail.com>
2026-02-12 21:31:23 -05:00
Andrew Toth
86eda88c8e
fuzz: move backend mutating block to end of coins_view
Refactor TestCoinsView() to move code that directly modifies
backend_coins_view to the end of the function.
This prepares for a CoinsViewOverlay fuzz target that asserts
the backend_coins_view is not mutated by any methods before
BatchWrite is called.

Co-authored-by: l0rinc <pap.lorinc@gmail.com>
2026-02-12 21:31:23 -05:00
Andrew Toth
89824fb27b
fuzz: pass coins_view_cache to TestCoinsView in coins_view
Refactor TestCoinsView() to accept the cache as a parameter instead of
creating it internally. This prepares for adding a CoinsViewOverlay
fuzz target that needs to pass in a different cache type.

This is a non-functional change.

Co-authored-by: l0rinc <pap.lorinc@gmail.com>
2026-02-12 21:31:23 -05:00
Andrew Toth
73e99a5966
coins: don't mutate main cache when connecting block
Use `CoinsViewOverlay` when connecting blocks in `ConnectTip`.

Add a new integration test to verify that using
CoinsViewOverlay does not mutate the main cache
during validation for an invalid block.

Co-authored-by: l0rinc <pap.lorinc@gmail.com>
2026-02-12 21:31:23 -05:00
Andrew Toth
67c0d1798e
coins: introduce CoinsViewOverlay
Introduce `CoinsViewOverlay`, a `CCoinsViewCache` subclass that reads
coins without mutating the underlying cache via `FetchCoin()`.

Use `PeekCoin()` to look up a Coin through a stack of `CCoinsViewCache` layers without populating parent caches. This prevents the main cache from caching inputs pulled from disk for a block that has not yet been fully validated. Once `Flush()` is called on the view, these inputs will be added as spent to `coinsCache` in the main cache via `BatchWrite()`.

This is the foundation for async input fetching, where worker threads must not
mutate shared state.

Co-authored-by: l0rinc <pap.lorinc@gmail.com>
2026-02-12 21:31:23 -05:00
Andrew Toth
69b01af0eb
coins: add PeekCoin()
Introduce a helper to look up a Coin through a stack of CCoinsViewCache layers without populating parent caches.

This is useful for ephemeral views (e.g. during ConnectBlock) that want to avoid polluting CoinsTip() when validating invalid blocks.

Co-authored-by: l0rinc <pap.lorinc@gmail.com>
Co-authored-by: Pieter Wuille <pieter@wuille.net>
Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
2026-02-12 21:31:23 -05:00
Andrew Toth
557260ca14
rpc: Add abortprivatebroadcast
Co-authored-by: l0rinc <pap.lorinc@gmail.com>
2026-02-11 19:46:19 -05:00
Andrew Toth
996f20c18a
rpc: Add getprivatebroadcastinfo
Co-authored-by: Vasil Dimov <vd@freebsd.org>
2026-02-11 19:46:12 -05:00