BC
← All projectsBitcoin Core

Bitcoin Core

The Bitcoin network's reference node and wallet implementation.

BitcoinSupply chainNormal
Repository coverage

3157 commits in the local evidence base

Every captured commit receives deterministic security triage and a separate communication-quality score. Security candidates and broader second-pass signals receive full-patch Ollama analysis.

314security candidates665second-pass queue2999AI analyses
155commits · 30 days
332commits · 60 days
1303commits · 180 days
2860commits · 365 days
Backfill bands
Aug 5 → Feb 61351 seen45 candidatesComplete
Feb 6 → Jun 61033 seen63 candidatesComplete
Jun 6 → Jul 6281 seen11 candidatesComplete
Jul 6 → Aug 5207 seen5 candidatesComplete
Commit communication

Does the history explain itself?

Message quality measures whether a commit identifies its scope, purpose, rationale, testing, and supporting references. It does not change the security-severity score.

71/100 average clarity
1162Strong · 80–100
1206Adequate · 60–79
701Thin · 40–59
88Opaque · 0–39
6security candidates with opaque commit messaging
Read the scoring rubric →
Developer activity

Who is changing the project?

Public Git author strings; identities are not independently verified.

DeveloperCommitsCandidatesAnalyzedHigh riskMessage avg.
merge-script1964487389
Antoine Poinsot22422170
Ava Chow19165185068
MarcoFalke41421408074
fanquake23121228058
Lőrinc18121177081
Hennadii Stepanov22316211064
rkrux57957074
Sjors Provoost89889074
Sebastian Falbesoner33733073
David Gumberg55655072
Pieter Wuille95595066
Analysis record

Published AI watches

Last scanned 48 minutes ago

Informational 19 AI analysisMessage 91 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#35675: mining: add block template manager

This is a large internal code reorganization (refactor) in Bitcoin Core. It creates a new BlockTemplateManager class that takes over block-template creation, block submission, and tip-waiting helpers that were previously spread across seve…

Large refactor touching mining, RPC, interfaces, and test shutdown pathsNew object lifetime dependency: BlockTemplateManager holds references to mempool, chainman, and notifications; explicit reset ordering added in Shutdown/InitAndLoadChainstate/test setupsRemoval of early-init node.mining interface; BlockTemplateManager is now created after chainstate load, with a comment that it must exist before setChainstateLoaded(true) unblocks IPC waiters
5c726f20by Ryan Ofsky+561−44926 files
No security note in commit
Informational 12 AI analysisMessage 91 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#35301: Silent Payments: Implement bip352 (take 2)

This commit adds the first implementation of BIP352 (Silent Payments) to Bitcoin Core. Silent Payments are a new type of privacy-preserving Bitcoin address that lets someone receive payments without publicly revealing a fixed address. The …

New cryptographic feature implementation (BIP352 Silent Payments)Extensive use of secp256k1 silentpayments moduleInput public key extraction from P2PKH, P2WPKH, P2SH-P2WPKH, and P2TR inputs
be5d0b55by Ava Chow+6951−010 files
No security note in commit
Low 45 AI analysisMessage 96 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#35440: wallet: check descriptor cache xpub length before decoding

This update fixes a wallet database loading bug where a damaged or tampered Bitcoin wallet file could cause the program to read past the end of a stored extended public key (xpub). The patch makes the loader check the stored xpub length be…

Out-of-bounds read in wallet descriptor cache deserializationASan container-overflow triggered by malformed on-disk recordMissing length validation between record size prefix and fixed-size decoder
b3f846ecby Ava Chow+225−8511 files
Vendor flagged security relevance
Informational 20 AI analysisMessage 100 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#35813: wallet, rpc: Add listrawtransactions RPC

This commit adds a new wallet RPC called listrawtransactions to Bitcoin Core. It is a feature addition that lets users list every transaction their wallet knows about, including internal transfers and consolidations that the existing listt…

No security-relevant bug fix or vulnerability patch is present in the diff.New RPC exposes additional wallet transaction metadata, but only to callers already authorized for wallet RPCs.Code is a refactor of existing gettransaction logic into shared helpers; no new cryptographic, network, or consensus code.
2b95b45aby Ava Chow+334−276 files
No security note in commit
Moderate 68 AI analysisMessage 91 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#35752: wallet: make encryption state updates atomic

This Bitcoin Core update fixes several wallet bugs where a failed database write could leave a wallet in an inconsistent state. For example, encrypting a wallet or changing its passphrase could appear to succeed in memory while the change …

Atomicity fix for encryption state and descriptor key persistenceFailure to persist master key during encryption previously reported success in memoryPassphrase change could activate new passphrase only in memory
7ee3d622by Ava Chow+379−16418 files
Vendor flagged security relevance
Informational 15 AI analysisMessage 100 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#35619: test: ExtendedPrivateKey follow-ups

This commit only changes Bitcoin Core's internal functional test code. It replaces hard-coded test keys and addresses with ones generated from a new test helper class, and unifies how tests tell nodes not to create a default wallet. There …

248ce46fby merge-script+18−244 files
No security note in commit
Informational 15 AI analysisMessage 91 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#36261: test: cover PSBT unknown field merging

This commit only adds a new automated test to Bitcoin Core. It checks that when two partially-signed Bitcoin transactions (PSBTs) are combined, any custom 'unknown' data fields attached to them are preserved correctly. There is no change t…

bbc40edeby merge-script+130−01 file
No security note in commit
Informational 18 AI analysisMessage 100 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#36230: wallet: Improve `HasWalletDescriptor` performance and other canonical descriptor string followups

This is a Bitcoin Core wallet maintenance patch. It speeds up a wallet function that checks whether a descriptor already exists by caching a hash of the descriptor's canonical text, instead of rebuilding that text every time. It also tidie…

No security-relevant signal in commit message or diffChange is described as performance improvement and code cleanupBackwards-compatibility test notes a known miniscript wallet loading incompatibility between v31.0/v31.1 and other versions, but this is a documented compatibility quirk, not a vulnerability
4a583f38by merge-script+97−429 files
No security note in commit
Informational 21 AI analysisMessage 81 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#36297: rpc: Correct invalid OpenRPC defaults

This is a documentation-only fix for Bitcoin Core's machine-readable RPC help data. It changes several default values from literal strings to 'hint' labels (because the real default depends on context) and corrects one boolean default from…

OpenRPC schema/default mismatch correctionRPC help metadata type correction (string 'false' to boolean false)No executable code path changes
5f05d8c5by merge-script+6−63 files
No security note in commit
Informational 20 AI analysisMessage 68 · Adequate
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

rpc: Correct OpenRPC default metadata

This commit fixes documentation metadata for six Bitcoin Core RPC arguments. It changes how default values are described so that automatically generated API docs and schemas are accurate. The actual behavior of the software when running is…

No runtime code changesOnly RPC help/schema metadata modifiedVendor explicitly states runtime behavior is unchanged
b7f740c5by will+6−63 files
No security note in commit
Informational 24 AI analysisMessage 91 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#36286: crypto: Fix MuHash3072 division by itself

This commit fixes a bug in Bitcoin Core's MuHash3072 cryptographic code where dividing a MuHash object by itself (x /= x) produced the wrong mathematical result. The fix is straightforward: the code now saves the divisor's numerator before…

Cryptographic correctness bug in MuHash3072 division operatorSelf-aliasing in operator/= produces incorrect 1/D result instead of empty setNo production code path identified that triggers self-division
d48e76e6by merge-script+11−13 files
No security note in commit
Informational 18 AI analysisMessage 93 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#36285: refactor: Use static const over inline const to work around ld64 bug

This is a build-compatibility fix, not a security patch. It changes how some constant data is stored internally so that Apple's macOS linker (ld64) can build Bitcoin Core correctly. The change avoids a linker bug that caused build failures…

No security-relevant code logic changedChange is a linker bug workaround, not a vulnerability fixConstants remain read-only; no new attack surface introduced
ad97933aby merge-script+8−82 files
No security note in commit
Informational 23 AI analysisMessage 91 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#34861: wallet: Add importdescriptors interface

This commit refactors Bitcoin Core's wallet descriptor import feature so the same logic can be used by both the RPC command and a new GUI-facing interface. It also tightens one input rule: negative timestamps are now rejected, and the mini…

Refactor of security-sensitive wallet import code into shared CWallet pathNew input validation: negative timestamps rejected for importdescriptorsCentralization of descriptor range bound checks in CheckDescriptorRangeBounds
2bbbeaa6by Ava Chow+619−26415 files
No security note in commit
Low 30 AI analysisMessage 100 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#36260: torcontrol: Use reconnect backoff after dropped connections

This change fixes a bug in how Bitcoin Core reconnects to the Tor control port. A previous update accidentally removed the wait time between reconnect attempts when an already-established Tor control connection was dropped. Without the wai…

Uncontrolled retry loop causing resource exhaustion and log floodingLocal-only Tor control port interaction; no remote attacker path by defaultRegression introduced by prior refactor (#34158) and restored here
fb68c270by merge-script+32−332 files
No security note in commit
Informational 18 AI analysisMessage 100 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#36256: guix: Update osslsigncode to 2.14

This change updates the Windows code-signing tool used in Bitcoin Core's reproducible build process. It fixes a build-time failure where signature verification could not complete because a certificate package was missing and the old tool v…

Tooling update in release signing pipelineRestores CA certificate store for signature verificationDisables CRL/CDP network lookups during verification
7dedc454by Hennadii Stepanov+22−22 files
No security note in commit
Informational 19 AI analysisMessage 96 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#34566: feature: Use different datadirs for different signets

This change lets Bitcoin Core store different custom signet blockchains in separate data folders, using a unique suffix derived from each signet's network identifier. It also adds a friendlier error hint in bitcoin-cli when an RPC authenti…

Data isolation between distinct custom signets reduces risk of cross-network state corruption or accidental mainnet/testnet confusionNo memory-safety, cryptographic, or consensus changes observedNo privilege escalation, remote code execution, or denial-of-service vectors introduced in the diff
d32a515fby merge-script+211−4412 files
No security note in commit
Informational 19 AI analysisMessage 81 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#36251: rest: add `generated` and `height` to spenttxouts JSON

This change adds two extra pieces of information—whether a spent output came from a coinbase transaction and the block height at which it was created—to a Bitcoin Core REST API endpoint. It is a feature/parity improvement to make the REST …

dadca55fby merge-script+13−54 files
No security note in commit
Low 33 AI analysisMessage 91 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#34743: p2p: don't disconnect manual peers for block stalling

This change makes Bitcoin Core treat manually-added peers (from -addnode, -connect, or the addnode RPC) more gently during Initial Block Download (IBD). Previously, if such a peer was slow or stalled at sending blocks, the node would disco…

Behavior change in peer disconnection logic during IBDManual peers exempted from block-stalling disconnectionNew per-peer cooldown state m_block_download_paused_until introduced
cff00c54by merge-script+148−168 files
No security note in commit
Informational 20 AI analysisMessage 96 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#36186: test: return False for a too-short ECDSA signature

This is a small fix in Bitcoin Core's own test helper code. A helper function used only in tests could crash with an IndexError when given an extremely short fake signature, instead of cleanly returning False. The change moves a length che…

Out-of-order bounds check leading to IndexError in test helperRegression test added for malformed short DER signaturesTest-only code path, no production validation logic changed
76343a09by merge-script+11−21 file
No security note in commit
Informational 15 AI analysisMessage 100 · Strong
BC Bitcoin CoreBitcoin Core BitcoinSupply chain

Merge bitcoin/bitcoin#36083: test: cover getrawtransaction on a stale block via txindex

This commit only adds a new functional test to Bitcoin Core. It checks that the getrawtransaction RPC can retrieve a stale block's coinbase transaction via the optional txindex, and that the response correctly shows the block is no longer …

dd3c62c5by merge-script+41−341 file
No security note in commit
Repository ledger

Explore captured commits

Expand any commit for its author, full message, clarity score, changed files, triage signals, analysis, and source link.

AI review queuedMerge bitcoin/bitcoin#36032: rpc: avoid quadratic output lookupsby Ava Chow · 03117519 · Aug 25, 2026 · 1 fileMessage 91 · StrongModerate 59Details
Commit message · Ava Chow

Merge bitcoin/bitcoin#36032: rpc: avoid quadratic output lookups

747cff842481153357199bf9a81b5a4d82ea91fb rpc: avoid quadratic output lookups (Lőrinc)

Pull request description:

**Problem:** Transaction-creation RPCs currently take quadratic time to parse outputs.
An authenticated RPC client can therefore tie up a worker with a large request.
`sendmany` also holds the wallet lock while parsing, delaying other operations on the same wallet.

**Fix:** Parse transaction outputs in linear time by reading corresponding keys and values by index instead of looking up each value by key.

**Reproducer:** Run `time build/bin/test_bitcoin --run_test=rpc_tests/parse_outputs` before and after the fix:
<details>
<summary>parse_outputs test in `rpc_tests.cpp`</summary>

```cpp
BOOST_AUTO_TEST_CASE(parse_outputs)
{
constexpr size_t OUTPUT_COUNT{10'000};
UniValue outputs{UniValue::VOBJ};
for (size_t i{0}; i < OUTPUT_COUNT; ++i) {
auto destination{EncodeDestination(WitnessV0ScriptHash{CScript{} << i})};
outputs.pushKVEnd(destination, ValueFromAmount(i + 1));
}

const auto parsed_outputs{ParseOutputs(outputs)};
BOOST_REQUIRE_EQUAL(parsed_outputs.size(), OUTPUT_COUNT);
for (size_t i{OUTPUT_COUNT}; i > 0; --i) {
std::pair expected{CTxDestination{WitnessV0ScriptHash{CScript{} << (i - 1)}}, static_cast<CAmount>(i)};
BOOST_CHECK(parsed_outputs[i - 1] == expected);
}
}
```
</details>
E.g. on my M4 Max with `debug` build:

```python
Before ████████████████████ 1.80 s
After █████▒░░░░░░░░░░░░░░ 0.50 s -72%
```
Related to #35889

ACKs for top commit:
achow101:
ACK 747cff842481153357199bf9a81b5a4d82ea91fb
jonatack:
ACK 747cff842481153357199bf9a81b5a4d82ea91fb
jeanpablojp:
tACK 747cff842481153357199bf9a81b5a4d82ea91fb
hodlinator:
ACK 747cff842481153357199bf9a81b5a4d82ea91fb

Tree-SHA512: 154c9f583f6e7f4154882aeb1ae11c40b327d0ef04147e12a0fee749494ae95314cdfc56baad78723f3383f225d752654be0ae9ed7458b1c73f7a6a80922e3ef

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
signing or wallet pathmerge-commit duplicate discountsecond-pass: security-sensitive path
AI analysis · Moderate 59/100

This change fixes a performance bug in Bitcoin Core's RPC (remote procedure call) handling where creating a transaction with many outputs could take much longer than necessary. An authenticated RPC user could send a specially crafted request with thousands of outputs and temporarily slow down or stall a server worker. The fix makes the output parsing run in linear time instead of quadratic time, and removes a wallet-lock delay in the `sendmany` RPC. It is a denial-of-service improvement rather than a code-execution or theft bug.

Lower-priorityMerge bitcoin/bitcoin#36078: qa: Reduce `-maxconnections` in the functional test frameworkby Ava Chow · b91d983f · Aug 25, 2026 · 2 filesMessage 91 · StrongTriage 0Details
Commit message · Ava Chow

Merge bitcoin/bitcoin#36078: qa: Reduce `-maxconnections` in the functional test framework

b8a8893bf2a101e24f63902097c59ec0baddabb5 qa: Lower `-rpcmaxconnections` in `interface_http.py` test (Hennadii Stepanov)
6f4109b4489182bf5fa517630043df1829f00808 qa: Reduce `-maxconnections` in the functional test framework (Hennadii Stepanov)

Pull request description:

This PR follows up on bitcoin/bitcoin#35730 and fixes a [regression](https://github.com/bitcoin/bitcoin/pull/35730#issuecomment-5409592163) on NetBSD.

Since bitcoin/bitcoin#35730 the HTTP server reserves file descriptors for its listen sockets and for `-rpcmaxconnections` connected clients (16 by default), so `min_required_fds` in `init.cpp` grew.

On select()-based platforms `available_fds` is capped at FD_SETSIZE, which is 256 on NetBSD. The previous value of 94 no longer fits and every node in the test suite started up with a warning, which the framework treats as unexpected stderr and fails on.

Recompute the value with the new accounting (256 - 179 = 77) and update the comment to match the current variable names in `init.cpp`.

ACKs for top commit:
achow101:
ACK b8a8893bf2a101e24f63902097c59ec0baddabb5
hodlinator:
re-ACK b8a8893bf2a101e24f63902097c59ec0baddabb5
winterrdog:
re-ACK b8a8893bf2a101e24f63902097c59ec0baddabb5

Tree-SHA512: d6200cc334b98148d71992b1d085ca8f72ba68d330b26d7ba373a0917cca56a444b8d89b0c0827e2a56242893b268e9f581bffc8a631a2ff20cc51f10db3255e

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discount
Lower-priorityMerge bitcoin/bitcoin#35618: depends: Make tarball creation from local directory reproducibleby merge-script · 0f5c6d0b · Aug 25, 2026 · 1 fileMessage 81 · StrongTriage 0Details
Commit message · merge-script

Merge bitcoin/bitcoin#35618: depends: Make tarball creation from local directory reproducible

7e973cce52caeadaa9dcd4b5b6b7f53372e0aa0e depends: Make tarball creation from local directory reproducible (Hennadii Stepanov)

Pull request description:

This guarantees `$(package)_sha256_hash` reproducibility regardless of the default behavior of `$(build_TAR)` and fixes [caching](https://github.com/bitcoin/bitcoin/pull/36006#issuecomment-5328809116) for the `native_libmultiprocess` package.

Steps to reproduce the issue using the master branch @ 2a9e35d293b308e81811fa93ad2e5e8ed20e66e0:
```console
$ mkdir a && cd a && git init
$ git remote add origin https://github.com/bitcoin/bitcoin.git
$ git fetch --depth 1 origin 2a9e35d293b308e81811fa93ad2e5e8ed20e66e0
$ git checkout FETCH_HEAD
$ cd depends
$ gmake print-native_libmultiprocess_sha256_hash # Hash A. Compare with Hash B.
native_libmultiprocess_sha256_hash=7dd817bfc0ee23c408299907aff13fefb0bd3a54ec66dc14ea15b0cc38c3d9ce
$ cd ../../ && sleep 2
$ mkdir b && cd b && git init
$ git remote add origin https://github.com/bitcoin/bitcoin.git
$ git fetch --depth 1 origin 2a9e35d293b308e81811fa93ad2e5e8ed20e66e0
$ git checkout FETCH_HEAD
$ cd depends
$ gmake print-native_libmultiprocess_sha256_hash # Hash B. Compare with Hash A.
native_libmultiprocess_sha256_hash=34d6f79560c0ff7a4f46bd6bfb4693076546b41f071b6dbf879da45ac8384688
```

ACKs for top commit:
fanquake:
ACK 7e973cce52caeadaa9dcd4b5b6b7f53372e0aa0e
willcl-ark:
ACK 7e973cce52caeadaa9dcd4b5b6b7f53372e0aa0e

Tree-SHA512: f939cd1b2aca04eaa0f8426858bae3657ee9625f915834980caacfbf80843b952451f4d1c29e27179e533de3e10d31688593e4c25ed32e62392bfbaf9e58dd12

81/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discount
Lower-priorityMerge bitcoin/bitcoin#35583: test: close the listeners before terminating the event loopby merge-script · 794a7539 · Aug 25, 2026 · 1 fileMessage 91 · StrongTriage 0Details
Commit message · merge-script

Merge bitcoin/bitcoin#35583: test: close the listeners before terminating the event loop

e4d80e7001e9996a2836225f45a905dd16ffc777 test: close the loop after the network thread has completed (Vasil Dimov)
29fba5ddbb9ed4ddfd4f90c44d02dc877c5052da test: close the listeners before terminating the event loop (Vasil Dimov)

Pull request description:

Whenever a test creates a new `P2PInterface` object a new listener is
created inside `NetworkThread.create_listen_server()` by calling
`cls.network_event_loop.create_server()`.

These listeners are never closed which might result in:

```
2026-06-10T22:13:35.3934880Z Task was destroyed but it is pending!
2026-06-10T22:13:35.3936020Z task: <Task pending name='Task-54' coro=<BaseSelectorEventLoop._accept_connection2() done, defined at /opt/homebrew/Cellar/python@3.14/3.14.5/Frameworks/Python.framework/Versions/3.14/lib/python3.14/asyncio/selector_events.py:217> wait_for=<Future finished result=None>>
```

when the event loop is closed.

Fix that by closing the listeners.

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

ACKs for top commit:
andrewtoth:
ACK e4d80e7001e9996a2836225f45a905dd16ffc777
sedited:
ACK e4d80e7001e9996a2836225f45a905dd16ffc777

Tree-SHA512: b93d06526b4eb31ac445a1a0e379e5ec947661f8ea29f2e07ac88b9e4760b0cc5348638b320ab8d60735f34fc163fcdd18eba42b20e0a7726a98a5136433bd64

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discount
Lower-priorityMerge bitcoin/bitcoin#36064: qa: Minor improvement follow-ups to 35730by merge-script · f6b3f2ff · Aug 25, 2026 · 2 filesMessage 91 · StrongTriage 0Details
Commit message · merge-script

Merge bitcoin/bitcoin#36064: qa: Minor improvement follow-ups to 35730

290be9eafa488dd49820b3bb5698391c0abbc6a2 qa: Minor feature_init.py improvements (Hodlinator)
6248331b295c5540399cd7754e03a19c93b24318 qa: Switch to warning when skipping tests (Hodlinator)
6d570415a018dd2fb43486c97427bcea03c0add1 refactor(qa): Move check right below related check (Hodlinator)
7e3b60584b365a99ee240380e9d6de4c3809a7c7 refactor(qa): Simplify through using assert_raises() (Hodlinator)

Pull request description:

* Simplify code through `assert_raises()` - https://github.com/bitcoin/bitcoin/pull/35730#discussion_r3812910717
* Move check below related check - https://github.com/bitcoin/bitcoin/pull/35730#discussion_r3812910717
* Warn when skipping checks - https://github.com/bitcoin/bitcoin/pull/35730#discussion_r3813035181
* Minor improvements in 1 commit:
* Log message instead of comment - https://github.com/bitcoin/bitcoin/pull/35730#discussion_r3814377374
* Drop `r` from string literal prefix - https://github.com/bitcoin/bitcoin/pull/35730#discussion_r3814347609

ACKs for top commit:
pinheadmz:
ACK 290be9eafa488dd49820b3bb5698391c0abbc6a2
winterrdog:
tACK 290be9eafa488dd49820b3bb5698391c0abbc6a2

Tree-SHA512: 528a9701bc7529c74c02d56f0ca498dc2c0165e7d5a4ca5c8f35f7887e89df6898db9a5077811bed3d5318116479e1c974e9979a9b0c93eb72ed1d467fd8f01d

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discount
Security candidateMerge bitcoin/bitcoin#36025: psbt: avoid duplicate taproot leaf script keys when mergingby Ava Chow · 6a028161 · Aug 24, 2026 · 2 filesMessage 91 · StrongModerate 50Details
Commit message · Ava Chow

Merge bitcoin/bitcoin#36025: psbt: avoid duplicate taproot leaf script keys when merging

1cb416397b7aa4addd714f9ab68ae0a861ff81c3 psbt: avoid duplicate taproot leaf script keys when merging (Shuvam Pandey)

Pull request description:

Follow-up to #35665, which fixed the same combiner defect for `PSBT_GLOBAL_XPUB`. thomasbuilds
and winterrdog asked for this one as its own PR when I reported it there.

`m_tap_scripts` maps a leaf script to a set of control blocks, but is serialized as one record
per control block, keyed by the control block (`SerializeToVector(s, PSBT_IN_TAP_LEAF_SCRIPT,
std::span{control_block})`). `PSBTInput::Merge` unions it by the map key, so two PSBTs that map
the same control block to different leaf scripts merge into an input that serializes the `0x15`
key twice. Duplicate keys make a PSBT invalid, so it is the same `combinepsbt` then
`decodepsbt` failure as the xpub case, at the input level. Present since #22558 (v24.0).

Both decode on their own, and differ only in the leaf script the control block maps to, `OP_1`
against `OP_1 OP_1`:

```
$ A=cHNidP8BADwCAAAAAaqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAIhXAUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsACUcAAAA==
$ B=cHNidP8BADwCAAAAAaqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAIhXAUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsADUVHAAAA=
$ bitcoin-cli -regtest decodepsbt "$(bitcoin-cli -regtest combinepsbt "[\"$A\",\"$B\"]")"
error code: -22
error message:
TX decode failed Duplicate Key, input key "15c050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" already provided: unspecified iostream_category error
```

winterrdog reproduced it on the #35665 thread with another pair.

Merge the records rather than the map entries, keeping the leaf script already there. BIP 174
lets the combiner "pick arbitrarily when conflicts occur", and unknown and proprietary records
already resolve that way. Refusing to combine is the BIP's other option, but that would fail
`combinepsbt` on input it accepts today.

Merging by map key drops records as well. `std::map::insert` leaves existing keys alone, so
when both PSBTs carry the same leaf script with different control blocks, the incoming set was
dropped. Those keys do not conflict, so merging per record keeps them.

The control blocks already present are collected once per merge rather than searched for per
incoming record, which would be quadratic in the size of the two PSBTs `combinepsbt` takes from
the caller.

Since this is the second field with this shape I checked the rest. `m_xpubs` (#35665) and
`m_tap_scripts` are the only two whose record key comes from the value, so two map entries can
serialize the same key. `partial_sigs` is keyed by `CKeyID` and serialized under the pubkey,
but the pubkey determines the `CKeyID`, so those records stay distinct. The others key the
record by the map key, `m_proprietary` included, and `PSBTOutput` has no such field.

The test fails on master on both counts, and covers the merges that do not conflict as well.

I found this with a local assertion in the psbt fuzz target that a combined PSBT must
roundtrip. That assertion can go in a follow-up.

Tested:

```
./build/bin/test_bitcoin --run_test=psbt_tests
./build/bin/test_bitcoin --run_test=psbt_wallet_tests
./build/test/functional/test_runner.py rpc_psbt.py rpc_rawtransaction.py wallet_taproot.py wallet_signer.py feature_taproot.py wallet_basic.py
```

ACKs for top commit:
achow101:
ACK 1cb416397b7aa4addd714f9ab68ae0a861ff81c3
winterrdog:
re-ACK 1cb416397b7aa4addd714f9ab68ae0a861ff81c3

Tree-SHA512: 2599beffe701ba9b672e8dcc3d43844f3853ceeb3d86fc53798a428d3288aa8edd2e42f338b32a1046fa558d6cc5cfa5d55b3a0aaf960278b0f3002158381623

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
signing boundaryfuzzing or regression evidencesigning or wallet pathmerge-commit duplicate discount
AI analysis · Moderate 50/100

This commit fixes a bug in Bitcoin Core's PSBT (Partially Signed Bitcoin Transaction) merging code. When two PSBTs contained the same Taproot control block but mapped it to different leaf scripts, the old code would produce an invalid PSBT with duplicate keys, causing tools like `combinepsbt` followed by `decodepsbt` to fail. The fix merges records by their serialized key (the control block) rather than by logical map entries, keeping one leaf script arbitrarily when there is a conflict and preserving non-conflicting records. It also prevents dropping valid records that shared a leaf script but had different control blocks.

Security candidateMerge bitcoin/bitcoin#35516: rpc: preserve global xpubs and proprietary fields in joinpsbtsby Ava Chow · 07d92a9d · Aug 24, 2026 · 2 filesMessage 100 · StrongLow 38Details
Commit message · Ava Chow

Merge bitcoin/bitcoin#35516: rpc: preserve global xpubs and proprietary fields in joinpsbts

436921eb469a1c4dde9f46e2fbad231da0e17e7a test: check joinpsbts preserves global xpubs and proprietary fields (Thomas)
011094b282b22484090213a20a4c04b32c0d90fc rpc: preserve global xpubs and proprietary fields in joinpsbts (Thomas)

Pull request description:

`joinpsbts` collects the global xpubs of all the joined PSBTs into `merged_psbt`, but returns a separately constructed `shuffled_psbt` into which only the inputs, outputs, and unknown fields are copied. The collected `PSBT_GLOBAL_XPUB` records are silently dropped, and `PSBT_GLOBAL_PROPRIETARY` records are not collected at all.

The xpub collection was added in #17034, which was written against a `joinpsbts` that still returned `merged_psbt`, but was merged after #16512 had introduced the `shuffled_psbt` rebuild, so the collected xpubs have never reached the result.

Shuffle the inputs and outputs of `merged_psbt` in place instead of rebuilding a new PSBT, so that all global data is preserved, and union the global proprietary records in the merge loop, matching the `combinepsbt` behavior from #34893.

ACKs for top commit:
jpk68:
ACK 436921eb469a1c4dde9f46e2fbad231da0e17e7a
achow101:
ACK 436921eb469a1c4dde9f46e2fbad231da0e17e7a
winterrdog:
tACK 436921eb469a1c4dde9f46e2fbad231da0e17e7a

Tree-SHA512: d9de34c25aecc29b6b4fb80d6584fa919cc5ff9b7ef2f4d8ce35c4043fe7638fefb8af10448f2cd14021f5d25e149f0efc8798c5b8c9bc8b5582c6152010e891

100/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
signing boundarysigning or wallet pathmerge-commit duplicate discount
AI analysis · Low 38/100

This commit fixes a bug in Bitcoin Core's `joinpsbts` RPC command. When joining multiple PSBTs (Partially Signed Bitcoin Transactions), the command was accidentally dropping some global metadata—specifically global xpubs (extended public keys used for wallet coordination) and proprietary fields (vendor-specific data). The fix makes the command preserve this data instead of rebuilding the result PSBT from scratch, which had been silently discarding it. This is a data-loss bug rather than a theft-of-funds vulnerability, but losing xpubs or proprietary fields can break multi-party wallet workflows that rely on `joinpsbts`.

AI review queuedMerge bitcoin/bitcoin#34993: wallet: `NotifyCanGetAddressesChanged` when advancing `next_index`by Ava Chow · 4375d74d · Aug 24, 2026 · 4 filesMessage 91 · StrongLow 26Details
Commit message · Ava Chow

Merge bitcoin/bitcoin#34993: wallet: `NotifyCanGetAddressesChanged` when advancing `next_index`

e2ab8ae55142370f31d8606531a065e098be6c77 wallet: spkm: Only notify CanGetAddressesChanged on change (David Gumberg)
0892f16f911d0e2ac7ebf40946b74c2cef485e2c refactor: moveonly: Pair CanGetAddressesChanged notifications with desc range. (David Gumberg)
e6adae3db242a2146504bc72cf18ae58bb73401e wallet: `NotifyCanGetAddressesChanged` when advancing `next_index` (David Gumberg)

Pull request description:

Even though `TopUp()` notifies, advancing `next_index` after can deplete available addresses, so make sure to notify any time it's changed.

This would manifest as users seeing a clickable `Receive` button in the GUI when in fact no address can be generated in some edge cases, e.g. when a user has a watch only wallet with a hardened derivation path and runs out of keys.

This feels like it's begging for:

1) a refactor to make it impossible to modify `next_index` or `range_end` without firing `CanGetAddressesChanged`
2) a test

I banged my head against the keyboard for a bit but I couldn't get either of these to fall out, I also tried massaging a few clankers into doing it but I couldn't get any results that seemed reasonable to me, still seems like a worthwhile fix so opening PR anyway.

I also included a moveonly commit to pair code that can change the result of `CanGetAddresses()` with the notification firing

ACKs for top commit:
achow101:
ACK e2ab8ae55142370f31d8606531a065e098be6c77
polespinasa:
ACK e2ab8ae55142370f31d8606531a065e098be6c77
furszy:
utACK e2ab8ae55142370f31d8606531a065e098be6c77

Tree-SHA512: 5bb00d1ef4909a3e55535d283e5995df75e4288a151647f4a368b2086e2f2f4140693f43cae4f72727eafb49c9050aea8604cd6ddddc8646f7ac47b1357ed287

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
defensive validationsigning or wallet pathmerge-commit duplicate discountsecond-pass: security-sensitive path
AI analysis · Low 26/100

This Bitcoin Core change fixes a wallet notification bug. In the GUI, the 'Receive' button could stay clickable even when the wallet had actually run out of addresses it could generate. The patch makes sure the wallet emits a 'CanGetAddressesChanged' signal whenever the next available address index advances, so the UI can disable the Receive button at the right time. It is a correctness/UI fix, not a remote code execution or theft vulnerability.

Lower-priorityMerge bitcoin/bitcoin#35978: contrib/init: fix unused variables in openrc scriptby merge-script · 04cf9ece · Aug 24, 2026 · 1 fileMessage 93 · StrongTriage 0Details
Commit message · merge-script

Merge bitcoin/bitcoin#35978: contrib/init: fix unused variables in openrc script

d837bb38a44de445d2c459a477302d78871ae1a6 contrib/init: fix unused variables in openrc script (jpk68)

Pull request description:

- Makes it so that `${BITCOIND_BIN}` is actually used as `command=`, rather than the hardcoded `/usr/bin/bitcoind`.
- Passes `BITCOIND_GROUP` to `start-stop-daemon`, so that the daemon process itself runs under it.

ACKs for top commit:
jeanpablojp:
utACK d837bb38a44de445d2c459a477302d78871ae1a6
thomasbuilds:
ACK d837bb38
winterrdog:
utACK d837bb38a44de445d2c459a477302d78871ae1a6

Tree-SHA512: 78c237224d65cc47ade606df4808fbf4ca70109d95301c35d1b336eead1b25138a83ce6f2314775b8a11a6745af2220af9027640530b9edb7e0167ccea081b6b

93/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discount
Lower-priorityMerge bitcoin/bitcoin#36067: test: Remove `BOOST_CHECK_CLOSE` in favor of exact comparisonby merge-script · aed80c73 · Aug 24, 2026 · 1 fileMessage 91 · StrongTriage 0Details
Commit message · merge-script

Merge bitcoin/bitcoin#36067: test: Remove `BOOST_CHECK_CLOSE` in favor of exact comparison

9e115edd39ffffa81b0b2a7eafada44ecf01c057 test: Remove `BOOST_CHECK_CLOSE` in favor of exact comparison (rustaceanrob)

Pull request description:

`max_cache` is known ahead of time in this test as a `size_t` of `10000`, and each of these calculations should be known ahead of time (500.0, 9500.0). This test can truncate the double and assert exact equality rather than use a tolerance. Found in #35713 whereby this is the only use of this macro in the unit tests. IMO it is appropriate to tighten this test and remove the macro.

ACKs for top commit:
maflcko:
lgtm ACK 9e115edd39ffffa81b0b2a7eafada44ecf01c057
josibake:
ACK https://github.com/bitcoin/bitcoin/pull/36067/changes/9e115edd39ffffa81b0b2a7eafada44ecf01c057

Tree-SHA512: 738f05650bd1426e8e29e94955685e8ad3cd62e57f1c65b7af045161e4ca5af64bbd1f0cfed8da427a1f778620e3c8f7dfb835881f8de169806096213056e863

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discount
AI review queuedMerge bitcoin/bitcoin#36059: test: make index crash test check saved stateby merge-script · 07ca9ba9 · Aug 24, 2026 · 1 fileMessage 91 · StrongInformational 13Details
Commit message · merge-script

Merge bitcoin/bitcoin#36059: test: make index crash test check saved state

7ea36e985a900b2291ce549e468f6baab5324dc6 test: preserve index crash test state (Lőrinc)
5aa15df60c49aacd3b3dafe13a4ceded9cec07cc test: expose missing index crash checkpoint (Lőrinc)

Pull request description:

**Problem:** #35847 moved the unclean-shutdown test into the shared base index tests, but it checked only that each index could reopen and start background sync.
Both checks also pass when the index reopens at height 0, so they do not verify that a height-100 checkpoint was saved before the simulated crash and reloaded afterward.

**Fix:** The first commit records the existing false positive by asserting that each index reopens at height 0 before background sync.
The second commit establishes a durable checkpoint at height 100, drains its setup notification, and changes the same assertion to the pre-crash height.

ACKs for top commit:
jeanpablojp:
tACK 7ea36e985a900b2291ce549e468f6baab5324dc6
mzumsande:
ACK 7ea36e985a900b2291ce549e468f6baab5324dc6

Tree-SHA512: 0dca2bdd978c5df4acbb01692bb2058e74efa70da3d7191687628075a680a57848ddda8087629b5d743d9a1648d7dc849fda9ff487252136a0c91cdfda33ba32

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discountsecond-pass: broader security terminology
AI analysis · Informational 13/100

This is a test-only change for Bitcoin Core. It strengthens an existing automated test that simulates a crash to make sure that, after a restart, an index resumes from the correct block height rather than silently starting over from block 0. No production code was changed, and there is no fix for a live security vulnerability in this commit.

AI review queuedMerge bitcoin/bitcoin#36063: refactor: [test] Remove deprecated SetMockTime(i64) aliasby merge-script · 402f1fda · Aug 24, 2026 · 7 filesMessage 91 · StrongInformational 15Details
Commit message · merge-script

Merge bitcoin/bitcoin#36063: refactor: [test] Remove deprecated SetMockTime(i64) alias

fad1e6bf238ef4693464faf4102934c5b2dc7cb2 util: refactor: Remove deprecated SetMockTime(i64) alias (MarcoFalke)
faf87c3535c51ab2d5c64ed9660d7b3846975469 test: refactor: Use FakeNodeClock over manual/global SetMockTime (MarcoFalke)

Pull request description:

The deprecated test-only alias is only used in a few places and required in none.

In fact, it is incorrectly used in two unit tests, so first fixup those, and then remove it.

ACKs for top commit:
rustaceanrob:
ACK fad1e6bf238ef4693464faf4102934c5b2dc7cb2

Tree-SHA512: 1fa49e363bf8ccad07d61a77d3bc55c84724cd4cf034756b534cdb56614f334c0009d62dbdb08a940ddf46e0143ec6ecd6b4608baa2f8f581f56a6eef0f0abb8

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
signing or wallet pathmerge-commit duplicate discountsecond-pass: security-sensitive path
AI analysis · Informational 15/100

This commit is a code cleanup in Bitcoin Core's test and utility code. It removes an old, deprecated shortcut function called SetMockTime that accepted a plain integer, and updates the few remaining callers to use a modern, type-safe time API. There is no security vulnerability here; it is purely a refactoring change to make the codebase easier to maintain.

Lower-priorityMerge bitcoin/bitcoin#36046: fuzz: Use ImmediateBackgroundTaskRunner in process_messagesby merge-script · 135e05cf · Aug 24, 2026 · 3 filesMessage 91 · StrongTriage 0Details
Commit message · merge-script

Merge bitcoin/bitcoin#36046: fuzz: Use ImmediateBackgroundTaskRunner in process_messages

fae6665f01348d084696f7c39668b3d46272c111 fuzz: Use ImmediateBackgroundTaskRunner in process_messages (MarcoFalke)

Pull request description:

The `process_messages` target may complain about false-positive debug lock-order issues:

```
echo 'Gv8uXPBdXV0QEP//dHVhxyoVKP////8A/0BrLmNrAEEAIP+MXHR0OQAAAAD+///txgIUADBgAAEC
fgAAAK0ArQEAAAD/AFwAQf9cdHf5XGhlYWRlcltbyzHIw8RcX2Jsb2NrAAAAAGNtcAAAADAftOvd
D0sFqXEx6US5VIknlsOJqZ5goMwtmwZBPdCxQZbatBsWPOR3FcUvSLLsKwcgKT8XdmjvDgskH5pK
iAUI/uVJTf//fyAAAAAAAQIAAAAAAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
//8DAskA/v///wIA+QKVAAAAAAFRAAAAAAAAAAAmaiSqIant4vYcP3HR3v0/qZnfo2lTdVxcaQaJ
eZlitIvr2DaXToz5ASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMgAAAD/XPB0eAD/
AgAAAAD9ABZqCwAAAAAEAAAAXPBhYVtbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tb
W1tb//9bW1tbW1tbW1sAAAAxNgAAADc5MzU5NDk2ODEwNzg3NAAAAAICAgL9a4jAhyQCAgICAQAA
AAAABSpvdGhlcir/8wICAgICAAAAeAL0AAAAAAAAaW52O///BAAAAAAAtbW1tWFbW2FhtbVhYWFh
YSkpW1tbW2QAJwAAAAAAAAAAMTYAAAA3OTM1OTQ5NjgxMDc4NzQAAAACAgIC/WuIwIckAgICAgEA
AAAAAAUAAAAAAv7///MAeAL0AAAAAAAAaW52Ow==' | base64 --decode > /tmp/fuzz.input

FUZZ=process_messages ./bld-cmake/bin/fuzz /tmp/fuzz.input --printtoconsole=1 | grep -A99 'POTENTIAL DEADLOCK DETECTED'
```

```
[test] [sync.cpp:108] [potential_deadlock_detected] [error] POTENTIAL DEADLOCK DETECTED
[test] [sync.cpp:109] [potential_deadlock_detected] [error] Previous lock order was:
[test] [sync.cpp:118] [potential_deadlock_detected] [error] 'NetEventsInterface::g_msgproc_mutex' in test/fuzz/process_messages.cpp:89 (in thread 'test')
[test] [sync.cpp:118] [potential_deadlock_detected] [error] 'm_chainstate_mutex' in validation.cpp:3351 (in thread 'test')
[test] [sync.cpp:118] [potential_deadlock_detected] [error] 'cs_main' in validation.cpp:3373 (in thread 'test')
[test] [sync.cpp:118] [potential_deadlock_detected] [error] (2) 'MempoolMutex()' in validation.cpp:3376 (in thread 'test')
[test] [sync.cpp:118] [potential_deadlock_detected] [error] (1) 'm_tx_download_mutex' in net_processing.cpp:2216 (in thread 'test')
[test] [sync.cpp:122] [potential_deadlock_detected] [error] Current lock order is:
[test] [sync.cpp:133] [potential_deadlock_detected] [error] 'NetEventsInterface::g_msgproc_mutex' in test/fuzz/process_messages.cpp:89 (in thread 'test')
[test] [sync.cpp:133] [potential_deadlock_detected] [error] 'cs_main' in net_processing.cpp:4725 (in thread 'test')
[test] [sync.cpp:133] [potential_deadlock_detected] [error] (1) 'm_tx_download_mutex' in net_processing.cpp:4725 (in thread 'test')
[test] [sync.cpp:133] [potential_deadlock_detected] [error] (2) 'cs' in txmempool.h:521 (in thread 'test')
```

Fix this by using the `ImmediateBackgroundTaskRunner` from `src/test/fuzz/cmpctblock.cpp`.

ACKs for top commit:
Crypt-iQ:
ACK fae6665f01348d084696f7c39668b3d46272c111
sedited:
ACK fae6665f01348d084696f7c39668b3d46272c111
marcofleon:
tACK fae6665f01348d084696f7c39668b3d46272c111
frankomosh:
Tested ACK fae6665f01348d084696f7c39668b3d46272c111

Tree-SHA512: 9cee43aa72495abfd69211004b27ee6857d3a1a6bbab9fdc5a8b5349159a54e270236f198a516a7d9087917af8c95ee626e8307155ded8d08314a6b606dd0c33

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
fuzzing or regression evidencemerge-commit duplicate discount
AI review queuedutil: refactor: Remove deprecated SetMockTime(i64) aliasby MarcoFalke · fad1e6bf · Aug 24, 2026 · 5 filesMessage 75 · AdequateInformational 15Details
Commit message · MarcoFalke

util: refactor: Remove deprecated SetMockTime(i64) alias

The deprecated test-only alias is only used in three places and required
in none.

So remove it.

75/100 · AdequateMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides an explanatory body✓ Mentions testing or verification
Why it was queued
signing or wallet pathsecond-pass: security-sensitive path
AI analysis · Informational 15/100

This is a small internal cleanup change in Bitcoin Core. It removes an old, redundant shortcut function called SetMockTime that accepted a plain integer, and updates the few remaining callers to use the newer version that takes a typed chrono duration. There is no security fix here; it is purely a code simplification and modernization.

Lower-prioritytest: refactor: Use FakeNodeClock over manual/global SetMockTimeby MarcoFalke · faf87c35 · Aug 24, 2026 · 2 filesMessage 100 · StrongTriage 0Details
Commit message · MarcoFalke

test: refactor: Use FakeNodeClock over manual/global SetMockTime

Using SetMockTime in tests is problematic, because it often requires
verbose calls to
`SetMockTime(GetTime<std::chrono::seconds>() + offset)`.
Also, it requires manual `SetMockTime(0);` at the end.

Fix both issues by using FakeNodeClock.

100/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Uses a recognizable type or scope✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Mentions testing or verification
Security candidateMerge bitcoin/bitcoin#34697: descriptor: fix musig() duplicate key checks and doubled PSBT origin pathsby merge-script · 994c17d6 · Aug 24, 2026 · 3 filesMessage 100 · StrongModerate 55Details
Commit message · merge-script

Merge bitcoin/bitcoin#34697: descriptor: fix musig() duplicate key checks and doubled PSBT origin paths

b42f7fade0cd9a6fb3d69fcdff71436a99ba0005 descriptor: don't prepend key origins twice (Shuvam Pandey)
7b15e2cb442c0bfec76d7d4b9abdd31c7a538da8 descriptor: fix duplicate check for hardened keys (Shuvam Pandey)

Pull request description:

Fixes #34273.

Importing a descriptor that uses the same `musig()` participants twice in one
tapleaf, with different musig subderivations, fails with
`is not sane: contains duplicate public keys`. It only fails when one of the
participants is a private key on a hardened path. The all-xpub version of the
same descriptor imports fine. That's what gave it away.

The duplicate check (`KeyCompare`) resolves each key expression to a pubkey and
compares the results. It does this at index 0, and the old code used an empty
signing provider. With that empty provider, a `musig()` expression can't resolve
when one of its participants is on a hardened path, because deriving that
participant needs its private key, so the whole aggregate key comes back empty.
Two different musig expressions both came back empty, so the check treated them
as duplicates. The fix derives against the signing provider populated during
parsing, which holds the private keys, and only compares the expression strings
when neither side resolves. 151henry151 had suggested looking at the empty
signing provider on the issue.

scgbckbone found a second, separate bug in the same descriptors. When another
expression that reuses those participants is handled in the same expansion, its
participant origin in the PSBT is added twice, so `m/86h/1h/0h` becomes
`m/86h/1h/0h/86h/1h/0h` in both the input and output Taproot BIP32 derivation
maps. `OriginPubkeyProvider::GetPubKey()` now derives into a temporary provider,
merges it, and writes the corrected origin once, so a later expression can't
prepend the same origin again.

Tested:
```
./build/bin/test_bitcoin --run_test=descriptor_tests
./build/bin/test_bitcoin --run_test=miniscript_tests
./build/bin/test_bitcoin --run_test=bip328_tests
./build/bin/test_bitcoin --run_test=psbt_wallet_tests
./build/test/functional/test_runner.py wallet_musig.py --jobs=1
```

ACKs for top commit:
achow101:
ACK b42f7fade0cd9a6fb3d69fcdff71436a99ba0005
scgbckbone:
ACK b42f7fade0cd9a6fb3d69fcdff71436a99ba0005

Tree-SHA512: ab36caa6bc484fa1fc3289c79e9a3d713278d82f80de478e53e1bdbe645037e07776ac798eba085733abc139c11a9dbf0d3f49d3c0eee9632e4ddf33d2242f92

100/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference✓ Names security-relevant behavior explicitly
Why it was queued
secret or key materialsigning boundarydefensive validationsigning or wallet pathmerge-commit duplicate discount
AI analysis · Moderate 55/100

This Bitcoin Core patch fixes two bugs in how advanced wallet descriptors are parsed and turned into wallet data. First, the code could wrongly reject valid multi-signature setups as 'duplicate keys' when a private key on a hardened derivation path was involved, because it compared empty placeholder keys instead of the real ones. Second, when the same participant key appeared in multiple places in a descriptor, the wallet could double-prefix its BIP32 origin path in PSBT data (for example turning m/86h/1h/0h into m/86h/1h/0h/86h/1h/0h), which could confuse signing devices or wallet software. The patch corrects the duplicate-key comparison to use the real signing provider and prevents the origin path from being prepended more than once.

Lower-priorityMerge bitcoin/bitcoin#35730: http: limit connected HTTPRemoteClientsby merge-script · 32765aca · Aug 24, 2026 · 7 filesMessage 100 · StrongTriage 0Details
Commit message · merge-script

Merge bitcoin/bitcoin#35730: http: limit connected HTTPRemoteClients

bd4b1524eabfb1d9e9924941b7fecccac4daa615 init: do not count file descriptors for HTTPServer if -server=0 (Matthew Zipkin)
b08662060db7b13bb98b46d90f1b023be7324530 init: account for maximum file descriptors needed by HTTP (Matthew Zipkin)
cc2acebefb049043bfb571832a86718877a9f328 http: configure simultaneous connection limit with -rpcmaxconnections (Matthew Zipkin)
b3d6d2d1a7ef601e11eace7e000bf9fcee3928b9 http: limit connected clients to 16 (Matthew Zipkin)
86651d81971bf46381bd01f050190aab4350daf2 scripted-diff: Rename nUserBind, nBind, nMaxConnections to snake_case (Matthew Zipkin)

Pull request description:

Introduces a new configuration option `-rpcmaxconnections` with default value `16`. This is used to limit the number of simultaneous `HTTPClient` connected to the `HTTPServer`. When the limit is reached, new pending connections remain queued in the kernel's socket buffer. Those connections have complete TCP handshakes with the kernel but do not occupy any application memory.

The previous libevent-based HTTP server had no limit on connections but it did have a limit on the kernel socket queue:

https://github.com/libevent/libevent/blob/e7ff4ef2b4fc950a765008c18e74281cdb5e7668/http.c#L3510
```c
if (listen(fd, 128) == -1) {
```

The current HTTP server, like the p2p server, uses a platform constant here:

https://github.com/bitcoin/bitcoin/blob/b6becf3534c7b7f1b4d356a8f6113d62b6dd05bf/src/httpserver.cpp#L743

(on my macOS `SOMAXCONN` is `128` but on my Debian machine it's `4096`)

The default of 16 was chosen as a reasonable upper bound for single-user RPC use cases. Systems designed to handle more simultaneous HTTP connections than this (previously relying on the absence of a limit) can adjust the setting.

## File descriptors

Because of the connection limit, we can now account for the maximum number of file descriptors needed by the HTTP server. This addresses several issues (#11368 #11322 maybe #27732) that could have been fixed by a PR waiting in vain for a libevent release (#27731).

## Bonus performance improvement

The new limit is managed in a loop that drains the kernel's socket queue with `accept()`. All pending connections from the queue (up to the limit) are processed in one single call to `SocketHandlerListening()`. The previous code would only accept one connection from the queue on each I/O loop tick, with a `SELECT_TIMEOUT` (50ms) sleep between each.

ACKs for top commit:
fjahr:
tACK bd4b1524eabfb1d9e9924941b7fecccac4daa615
janb84:
ACK bd4b1524eabfb1d9e9924941b7fecccac4daa615
winterrdog:
tested ACK bd4b1524eabfb1d9e9924941b7fecccac4daa615
hodlinator:
Concept ACK bd4b1524eabfb1d9e9924941b7fecccac4daa615
willcl-ark:
ACK bd4b1524eabfb1d9e9924941b7fecccac4daa615

Tree-SHA512: 2ef7a96da4d7037c7343ec0ea03fda5bb55d10c2a071fce4929141297515923b203d3d338dbcb6599849768f52aa3c9da509fb5d1d6f7c574a1d2034ea2a9e74

100/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discount
Lower-priorityMerge bitcoin/bitcoin#35580: bugfix: compare non-adjusted chunk weight against block weight limitby merge-script · a3335994 · Aug 24, 2026 · 3 filesMessage 91 · StrongTriage 0Details
Commit message · merge-script

Merge bitcoin/bitcoin#35580: bugfix: compare non-adjusted chunk weight against block weight limit

5be248341a8e9ad97143647e7f480eecf1f90eb4 bugfix: compare real chunk weight against block weight limit (ismaelsadeeq)
fc987908699086161c4d735d7ac3bcc7110a5fa0 test: `TestChunkBlockLimits` uses incorrect weight for comparison (ismaelsadeeq)

Pull request description:

Partially fixes #35596

When assembling a block template, `BlockAssembler::addChunks()` adds chunks of transactions until the block is close to being full. For each chunk, `TestChunkBlockLimits()` checks both the weight and the sigop-cost limits before the chunk is included.

The weight check compared the chunk's **sigops-adjusted** weight against `block_max_weight`:

```cpp
if (nBlockWeight + chunk_feerate.size >= m_options.block_max_weight) {
return false;
}
```

Whereas `nBlockWeight` accumulates the actual chunk weight.

A chunk whose sigop-adjusted weight exceeds the actual weight can be wrongly skipped even though the block sigop limit is enforced independently on the next line, and that could pass. Those chunks pay higher fees, so this could potentially cause miners to needlessly forfeit some fees revenue.

This PR fixes this by passing the chunk's real weight (sum of `GetTxWeight()`, accumulated in the same loop that already sums sigop cost) to `TestChunkBlockLimits()`. The separate sigop-cost check is unchanged.

- The first commit adds `TestSigOpsAdjustedWeightChunkLimit`: it builds one sigop-dense transaction sized to fit by real weight but not by adjusted weight, and asserts that the tx is skipped and only the coinbase is mined.

- The second commit applies the fix and flips the assertion to show the transaction is now included.

ACKs for top commit:
pablomartin4btc:
Code Review ACK 5be248341a8e9ad97143647e7f480eecf1f90eb4
sedited:
ACK 5be248341a8e9ad97143647e7f480eecf1f90eb4

Tree-SHA512: b3fe9bfaa6d83d713d0243c0fc0d0fb8e68e1060bf6d606e43d9a52bd1ec07e42c561a1ba3426f180903726826c4a664bb131ddc5160354a96e3454d538fbf6c

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discount
Security candidateMerge bitcoin/bitcoin#35933: psbt: don't abort on invalid MuSig2 derivationsby merge-script · 0ea81904 · Aug 24, 2026 · 2 filesMessage 91 · StrongHigh 78Details
Commit message · merge-script

Merge bitcoin/bitcoin#35933: psbt: don't abort on invalid MuSig2 derivations

73a94b45459a9433ffcf99aff3b044cc7166ee12 psbt: avoid aborting on invalid MuSig2 derivations (Lőrinc)
e3d1e75a519a3542a736c3097ce8ab3a2bd8dc5c test: characterize MuSig2 derivation aborts (Lőrinc)

Pull request description:

**Problem:** A PSBT may contain MuSig2 derivation metadata with a hardened child index or a path that derives to a different key.
The hardened index aborts during public derivation, while the mismatched key aborts at the result assertion.
`analyzepsbt`, `finalizepsbt`, and `descriptorprocesspsbt` all reach this code without a wallet.
Even the read-only `analyzepsbt` can force a co-signer service to restart its node after unexpected input.

**Fix:** Return failure when a MuSig2 derivation path contains a hardened child index, and skip only the current aggregate when the path derives to a different key so another matching aggregate can still be tried.

This follows [#35154](https://github.com/bitcoin/bitcoin/pull/35154), with the related contributions credited in the commits.

ACKs for top commit:
jeanpablojp:
ACK 73a94b45459a9433ffcf99aff3b044cc7166ee12
achow101:
ACK 73a94b45459a9433ffcf99aff3b044cc7166ee12
andrewtoth:
ACK 73a94b45459a9433ffcf99aff3b044cc7166ee12

Tree-SHA512: d8e28c5a4184154a4427c644ce62423cbcccdc3d82a6293f36fe99055fa04714598bc92c43b526fbcc7c99b231140669c2d0f1b853999d7dc33f949564c90504

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
signing boundarydefensive validationsigning or wallet pathmerge-commit duplicate discount
AI analysis · High 78/100

This update fixes a crash bug in Bitcoin Core's handling of certain partially-signed Bitcoin transactions (PSBTs). A malformed MuSig2 derivation path could previously trigger an internal abort (assertion failure or hard crash), even through a read-only RPC call like analyzepsbt. The fix turns those crashes into ordinary failures, so an attacker can no longer force a co-signer node to restart by submitting a bad PSBT.

Lower-priorityMerge bitcoin/bitcoin#36051: ci: use ruff 0.16.xby merge-script · 58a7869f · Aug 21, 2026 · 2 filesMessage 76 · AdequateTriage 0Details
Commit message · merge-script

Merge bitcoin/bitcoin#36051: ci: use ruff 0.16.x

9d0c38db74668b0383daadbff5093910b269a860 ci: use mypy 2.3.1 (fanquake)
7a53beca06a8537287825f73891abc8815daf2b4 ci: use pyzmq 27.2.0 (fanquake)
f29f076f3c27d29bd2c95875a4f79deaa8235a63 ci: use ruff 16 (fanquake)

Pull request description:

Also use mypy `2.3.1` and pyzmq `27.2.0`.

ACKs for top commit:
willcl-ark:
ACK 9d0c38db74668b0383daadbff5093910b269a860
janb84:
ACK 9d0c38db74668b0383daadbff5093910b269a860
maflcko:
lgtm ACK 9d0c38db74668b0383daadbff5093910b269a860

Tree-SHA512: 819fa465d34dd1c3de1753f4b7227a2f7217b108b5a4e4d3ff0527d2273140c9c0bf973b9fc8c60791bfe89dc1e7ed0fa17da8797cebe74fafb3a0b810c603bf

76/100 · AdequateMessage clarity
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discount
AI review queuedMerge bitcoin/bitcoin#35884: util: set os-level thread names on Windowsby merge-script · f5e91c6f · Aug 21, 2026 · 1 fileMessage 91 · StrongInformational 15Details
Commit message · merge-script

Merge bitcoin/bitcoin#35884: util: set os-level thread names on Windows

dd669f40b98bb864bb9713673f0c38d946040591 util: set os-level thread names on Windows (ViniciusCestarii)

Pull request description:

Update SetThreadName to set os-level thread names on Windows too.

This is useful for debugging-ergonomics on Windows. Threads currently show up unnamed in debuggers, crash dumps on Windows and mismatch what's documented under https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#threads.

Tested with the mingw cross build running on Windows 11, print from WinDbg:

<img width="713" height="631" alt="image" src="https://github.com/user-attachments/assets/05e03383-c9b1-4e6b-91f3-9088b2fc7e90" />

ACKs for top commit:
l0rinc:
code review ACK dd669f40b98bb864bb9713673f0c38d946040591
hebasto:
ACK dd669f40b98bb864bb9713673f0c38d946040591, tested Guix-built `bitcoind.exe` on Windows 11 Pro using WinDbg:
winterrdog:
utACK dd669f40b98bb864bb9713673f0c38d946040591

Tree-SHA512: 3632584f5f0612414a53ad6d868b9f832e8e7f1fad19f212f292172a4a6516f6e0055ec6ac8fbb71b22acdd003d09c9a5f97c0c15a137e1ad242580f997aca6f

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discountsecond-pass: broader security terminology
AI analysis · Informational 15/100

This change lets Bitcoin Core give meaningful names to its internal threads when running on Windows, so they appear labeled in debuggers and crash dumps. It is purely a debugging convenience improvement and does not change how the software behaves or process any attacker-controlled data.

Lower-priorityMerge bitcoin/bitcoin#36045: test: avoid undersized Boost.Test signal stacksby merge-script · a1e27162 · Aug 21, 2026 · 2 filesMessage 91 · StrongTriage 0Details
Commit message · merge-script

Merge bitcoin/bitcoin#36045: test: avoid undersized Boost.Test signal stacks

9eba3aafa6c26994a301965ef8ddca0ada5f85c7 test: avoid undersized Boost.Test signal stacks (Lőrinc)

Pull request description:

**Problem:** Boost.Test can fail while an Alpine CI test binary is starting, before any tests run.
The required signal stack size depends on the runner's CPU features, while musl provides a fixed size.

**Fix:** Use the [regular process stack](https://www.boost.org/doc/libs/latest/libs/test/doc/html/boost_test/utf_reference/link_references/config_disable_alt_stack.html) for Boost.Test signal handling in both unit-test binaries.

Fixes #36026

ACKs for top commit:
maflcko:
lgtm ACK 9eba3aafa6c26994a301965ef8ddca0ada5f85c7

Tree-SHA512: 177a31ab325f4ebce0ad7e4679b171cd5a28787595bf0e117fc66731b8bf9157c4f5bef74cc6bb7651021bafb616fe5e9a25709abf30b7689d10ddd0fbd484cb

91/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discount
Security candidateMerge bitcoin/bitcoin#34075: fees: Introduce Mempool Based Fee Estimation to reduce overestimationby merge-script · 7dcb7f09 · Aug 21, 2026 · 64 filesMessage 100 · StrongLow 40Details
Commit message · merge-script

Merge bitcoin/bitcoin#34075: fees: Introduce Mempool Based Fee Estimation to reduce overestimation

7f9c4e2928991704e9e2224ad32d3b159b2551ac doc: add release notes (ismaelsadeeq)
e18d392689da72d857fc590097889060a48d98e0 test: add mempool estimator i/o fuzz test (ismaelsadeeq)
970f02096d37447d04bf84993f2922a1e6f7d7a7 fees: persist mempool policy estimator data (ismaelsadeeq)
7dcb37989d25bccdb335aaa4aa429588cd26c874 fees: move fee_estimates.dat into fees directory (ismaelsadeeq)
0db2b69e6db7ad07d1d4edfcf3f84c3fde568992 rpc: add verbosity option to estimatesmartfee options (ismaelsadeeq)
06bb65730ebee2dd66bb79566dd29936a366e3eb fees: gate mempool estimates on recent block coverage (ismaelsadeeq)
cfe585df25c482c157e239fcd6c81b7afe3bab00 validation: emit block mempool removal signal from ConnectTip (ismaelsadeeq)
0d88558f95113a5041fa957432fa5d9c12314466 fees: return mempool estimates when it's lower than block policy (ismaelsadeeq)
693b1351aff422c4c75e0f4c3be7571193d236bf fees: add caching to MemPoolFeeRateEstimator (ismaelsadeeq)
c9bb3df29ff9ba2952af1e5349c93657a1483d3f fees: add MemPoolFeeRateEstimator class (ismaelsadeeq)
9cacf677a918ba89b6a47f4ae2fde8d62f1cf384 rpc: add fee_rate_estimator option to estimatesmartfee (ismaelsadeeq)
ba6c61bbdd32d01fb1d20ebcd1e48e3b32cf0932 fees: add FeeRateEstimatorManager class (ismaelsadeeq)
2cb6b831e0304c7caf7953a991b97c15c0c24550 fees: add EstimateFeeRate and MaximumTarget to CBlockPolicyEstimator (ismaelsadeeq)
5adb2ab084333c7a968895848123302b88cb4183 refactor: test block policy estimator directly (ismaelsadeeq)
9c8309a89097fac0128129cdfb2072c334b21a87 test: rename policy estimator tests to block policy estimator tests (ismaelsadeeq)
e3d5ef1b5fb282025751c894cd0f0e0494cd0641 fees: move StringForBlockPolicyEstimateReason to block policy estimator (ismaelsadeeq)
74245c20e05e6fb5844a9bdfca489f107c6c8aca fees: split wallet and estimator fee reasons (ismaelsadeeq)

Pull request description:

This PR is another attempt to fix #27995 using a better approach.

For background and motivation, see #27995 and the discussion in the Delving Bitcoin post [Mempool Based Fee Estimation on Bitcoin Core](https://delvingbitcoin.org/t/mempool-based-fee-estimation-on-bitcoin-core/703).

This PR is currently limited to using the mempool only to lower what is recommended by the Block Policy Estimator.
Accurate and safe fee estimation using the mempool is challenging. There are open questions about how to prevent mempool games that are theoretically possible for miners [(a variant of the Finney attack)](https://delvingbitcoin.org/t/mempool-based-fee-estimation-on-bitcoin-core/703/6).

This is one reason this PR uses the mempool only to lower the Block Policy Estimator result. The Block Policy Estimator itself is not gameable in this way, so the combined estimate is not susceptible to this attack increasing the returned feerate.

The underlying assumption is that, with the current tools and work done to make RBF and CPFP feasible and reliable (TRUC transaction relay, ephemeral anchors, cluster size 2 package RBF), underestimation is safer than overestimation. We now assume it is relatively easy to fee-bump later if a transaction does not confirm, whereas once a fee is overestimated there is no way to recover from that.

Another open question when using the mempool for fee estimation is how to account for incoming transaction inflow.
[Bitcoin Augur](https://github.com/block/bitcoin-augur) does this by using past inflow plus a constant expected inflow to predict future inflow. I find this unconvincing for fee estimation and potentially prone to more overestimation, as past conditions are not always representative of the future. See my [review of the Augur fee rate estimator and open questions](https://github.com/block/bitcoin-augur/issues/3).

This PR uses a much simpler approach based on current user behavior, similar to the widely used method employed by mempool.space: looking at the top block of the mempool and selecting a percentile feerate depending on whether the user is economical or conservative.

Empirical data from both myself and Clara Shikhelman shows that the 75th percentile feerate for economical users and the 50th percentile feerate for conservative users provide positive confirmation guarantees, hence this is what is used in this PR.

Parallel research by Rene Pickhardt and his student suggests that using the [average fee per byte of the block template performs well](https://delvingbitcoin.org/t/mempool-based-fee-estimation-on-bitcoin-core/703/12).

All of these are constants that can be adjusted. There is parallel work exploring these constants and running benchmarks across fee estimators to find a sweet spot.

See also work in LND, the [LND Budget Sweeper](https://delvingbitcoin.org/t/lnds-deadline-aware-budget-sweeper/1512), which applies this idea successfully. Their approach is to estimate fees initially with bitcoind, then increment gradually as the confirmation deadline approaches, using a fixed fee budget.

Historical data indicates that this PR's approach can [reduce overestimation quite significantly (~29%)](https://delvingbitcoin.org/t/mempool-based-fee-estimation-on-bitcoin-core/703/8).

This is particularly useful in scenarios where the Block Policy Estimator recommends a high feerate while the mempool is empty.

<img width="1800" height="1090" alt="56f3ba26c0184521c42bb82ec9d8c9f2224d4f8e" src="https://github.com/user-attachments/assets/c035c40c-8ece-42a7-b290-d29f1ac9bf4d" />

As seen in the image above, there is only one remaining unfixed case: when there is a sudden inflow of transactions and the feerate rises, the Block Policy Estimator takes time to reflect this. In that case, users will continue to see a low feerate estimate until it slowly updates. From the historical data linked above, [this occurs about ~26% of the time](https://delvingbitcoin.org/t/mempool-based-fee-estimation-on-bitcoin-core/703/8).

Overall, we observe a **73% success rate with 0% overestimation, and 26% underestimation** with this approach.

See https://bitcoincorefeerate.com/stats for recent running stats that have almost identical data.

This PR also includes refactors that enable this work. Rather than splitting the PR and implementing changes incrementally, I opted for an end-to-end implementation:

### 1. Refactors

* Split the mixed fee reason enum into separate wallet and block policy concepts. The wallet now has a `FeeReason` enum for why the wallet selected a fee rate (`FEE_RATE_ESTIMATOR`, `MEMPOOL_MIN`, `USER_SPECIFIED`, `FALLBACK`, `REQUIRED`), while the Block Policy Estimator uses `BlockPolicyEstimateReason` for its internal threshold details.
* Move `StringForBlockPolicyEstimateReason` to the Block Policy Estimator code, keeping the estimator-specific strings with the estimator.
* Move detailed Block Policy Estimator logging out of wallet transaction creation and into the estimator path. Wallet transaction creation now logs the selected fee and wallet fee reason instead of leaking estimator internals.
* Keep the wallet RPC `fee_reason` field name for compatibility, but update its meaning to report the wallet fee reason instead of the Block Policy Estimator's internal threshold reason.
* Rename policy estimator tests and files to block-policy-specific names where appropriate.
* Update Block Policy Estimator unit tests to be independent of the mempool and validation interface.

### 2. Introduce Mempool-Based Fee Estimator and Fee Estimator Manager

* Introduce `FeeRateEstimation` and `FeeRateEstimationError` as common estimator result types, avoiding new out-parameters for fee estimation results.
* Add `FeeRateEstimatorType` to identify the estimator that produced a result.
* Add `FeeRateEstimatorManager`, responsible for owning the Block Policy Estimator and Mempool Fee Rate Estimator.
* Update the node context to store a `std::unique_ptr` to `FeeRateEstimatorManager` instead of `CBlockPolicyEstimator`.
* Update `CBlockPolicyEstimator` to no longer subscribe directly to the validation interface; instead, `FeeRateEstimatorManager` subscribes and forwards relevant notifications.
* Add a mempool fee estimator that generates a block template when called, calculates a percentile feerate, and returns the 75th percentile for economical mode or the 50th percentile for conservative mode.
* When the selected estimate is below the node's fee floor, `estimatesmartfee` still returns at least the max of `mempoolminfee` and `minrelaytxfee`.
* Add caching to the mempool estimator so new estimates are generated at most every 7 seconds while the chain tip is unchanged, assuming enough [transactions have propagated](https://bitcoin.stackexchange.com/questions/125776/how-long-does-it-take-for-a-transaction-to-propagate-through-the-network/125777#125777) to make a meaningful difference.
This heuristic will likely be replaced by requesting block templates via the general-purpose block template cache proposed here: https://github.com/bitcoin/bitcoin/issues/33389
* Update `MempoolTransactionsRemovedForBlock` to receive the connected block as well as the transactions removed from the mempool.
* Track the weight of block transactions and mempool transactions removed due to block connection after each block connection.
This data is tracked for the last 6 mined blocks. A mempool feerate estimate is returned only when the ratio of mempool transaction weight removed due to block connection to block transaction weight is greater than 75% across the tracked window. This heuristic provides rough confidence that the node's mempool matches that of the majority of the hashrate. The 75% threshold is arbitrary and can be adjusted.

There is a caveat when transactions in the local mempool are consistently not mined by the network, as described in #27995 (e.g. due to filtering).
Accounting for these transactions during fee estimation is not necessary, as they should be evicted from the mempool itself (see #33510). Handling this again within fee estimation would be redundant.

* Persist statistics for the 6 most recent mined blocks to `fees/mempool_policy_estimator.dat` during periodic flushes and shutdown, so this data is available after restarts.
* Move Block Policy Estimator data from `fee_estimates.dat` to `fees/block_policy_estimates.dat`, migrating the legacy file during startup when needed.
* Add `fee_rate_estimator` to the `estimatesmartfee` options object. Supported values are `"none"` (default combined behavior), `"block_policy"` (use only the Block Policy Estimator), and `"mempool_policy"` (use only the Mempool Fee Rate Estimator). Unknown values are treated as `"none"`.
* Add `verbosity` to the `estimatesmartfee` options object. With `verbosity >= 2`, the RPC returns recent mempool health statistics.
* Expose the selected fee rate estimator in `estimatesmartfee` results when `fee_rate_estimator` is `"none"` and the estimate succeeds.
* Add unit, functional, and fuzz test coverage for the new estimator behavior, persistence, RPC options, and estimator I/O.

<details>
<summary>see example output</summary>

```bash
bitcoin-cli estimatesmartfee 1 economical '{"verbosity": 2, "fee_rate_estimator": "none"}'
```

```json
{
"feerate": 0.00002133,
"estimator": "mempool_policy",
"blocks": 2,
"mempool_health_statistics": [
{
"block_height": 927953,
"block_weight": 3991729,
"mempool_txs_weight": 3942409
}
]
}
```

</details>

ACKs for top commit:
willcl-ark:
reACK 7f9c4e2928991704e9e2224ad32d3b159b2551ac
jsarenik:
Approach ACK 7f9c4e2

Tree-SHA512: c35b423eea0eb34524cf5ad07822c0ab8d53e2ab78965b58c8738044c61c77352184822360ed077a51bfbf83d0226d221e988f7156b1948023707c7e1fb31495

100/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference✓ Names security-relevant behavior explicitly
Why it was queued
explicit security languageaccess controlfuzzing or regression evidencesigning or wallet pathmerge-commit duplicate discount
AI analysis · Low 40/100

This commit merges a major Bitcoin Core change that adds a second, mempool-based fee estimator alongside the existing block-history estimator. By default, `estimatesmartfee` now returns the lower of the two estimates, intended to reduce overpayment during quiet mempool periods. The change also renames files, moves fee-estimate data into a new `fees/` directory, and adds new RPC options so users can pick which estimator to use. It is a deliberate design change, not a hidden bug fix, and the authors explicitly discuss the trade-offs (risk of underestimation during sudden fee spikes).

Lower-priorityMerge bitcoin/bitcoin#36019: bench: Construct CTxOut and COutPoint in a single expressionby merge-script · 5e8586ec · Aug 21, 2026 · 2 filesMessage 81 · StrongTriage 0Details
Commit message · merge-script

Merge bitcoin/bitcoin#36019: bench: Construct CTxOut and COutPoint in a single expression

950bdb763e17bf7dc527b8aecb0d392062aec437 bench: Construct CTxOut and COutPoint in a single expression (Alexander Wiederin)

Pull request description:

Replaces field-by-field mutation of `CTxOut` and `COutPoint` in two bench files with brace initialisation, which requires the `size_t` conversions to be made explicit.

Noticed while looking at #35994, where switching the proposed fix-it to `{}` surfaces implicit narrowing conversions like these.

The constructed values are unchanged.

*Note: Only the sites where a conversion is involved are included in this PR; the remaining field-by-field construction in `bench/` would be covered by #35994's follow-ups.*

ACKs for top commit:
l0rinc:
code review ACK 950bdb763e17bf7dc527b8aecb0d392062aec437
maflcko:
review ACK 950bdb763e17bf7dc527b8aecb0d392062aec437 🐯

Tree-SHA512: c664d41eeeb9241d381e5fa27689f18d9445a942055734463978498f60d0f2c495a0d7a58131493bb63267371bb6fe2d45ac124d910c919c8905322948d17a23

81/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Links an issue, advisory, or supporting reference
Why it was queued
merge-commit duplicate discount
Security candidateMerge bitcoin/bitcoin#32958: wallet/refactor: Update SignPSBTInput to return util::Expected<void, PSBTError> and remove PSBTError:Okby Ava Chow · bf8402c8 · Aug 20, 2026 · 7 filesMessage 81 · StrongInformational 15Details
Commit message · Ava Chow

Merge bitcoin/bitcoin#32958: wallet/refactor: Update SignPSBTInput to return util::Expected<void, PSBTError> and remove PSBTError:Ok

6cca38e2b92967b3c057407319e39c6aebadd032 refactor: remove unused PSBTError::Ok (kevkevinpal)
3660678b953c7de8c1d2c670296df90649630f5d refactor: SignPSBTInput now uses util:Expected (kevkevinpal)

Pull request description:

### Description
This is a follow-up to https://github.com/bitcoin/bitcoin/pull/31622#discussion_r2092030045 and https://github.com/bitcoin/bitcoin/pull/31622#discussion_r2092035407

### What this changes
- Updates `SignPSBTInput` to return `util::Expected<void, PSBTError>`
- Removes `PSBTError:Ok` from the `PSBTError` Enum

ACKs for top commit:
achow101:
ACK 6cca38e2b92967b3c057407319e39c6aebadd032
rkrux:
lgtm ACK 6cca38e2b92967b3c057407319e39c6aebadd032
jeanpablojp:
tACK 6cca38e2b92967b3c057407319e39c6aebadd032

Tree-SHA512: c83b2e7e440aff01becc788e36a732756085f507d447eaa16dd1276d0d0b54070d0d8a51727d553d214043935072586111a175f34338a8d1886a6d5b251de7e4

81/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Links an issue, advisory, or supporting reference
Why it was queued
signing boundarysigning or wallet pathmerge-commit duplicate discount
AI analysis · Informational 15/100

This commit is a code cleanup (refactor) that changes how a PSBT signing function reports success or failure. It replaces an explicit 'OK' success code with a standard C++ expected-result type. There is no security bug being fixed here; the behavior of the signing logic is unchanged.