Commit Graph

8314 Commits

Author SHA1 Message Date
Gregory Sanders
5aea3d0373 private broadcast: limit outstanding txs to count of 10,000
Add a belt-and-suspenders feature, limit the amount of
memory and cpu possible when unlucky or simply misconfigured.
The worst case limit is roughly 400kB * 10,000 = 4GB, regardless
of usage pattern.

Before this change, sheer volume of broadcasts, mismatches in
standardness rules, or simply fee mismatches may result in unbounded
growth of memory usage. As the feature may be expanded in
the future, explicit bounds helps reasoning going forward.
2026-06-30 14:53:59 -04:00
merge-script
dc282ff31d Merge bitcoin/bitcoin#35597: logging: More fully remove libevent log category
3765b428d1 logging: More fully remove libevent log category (Ryan Ofsky)

Pull request description:

  Libevent log category was partially removed in 39e9099da5, and this commit extends that with the following changes:

  - Stops showing libevent in the list of supported log categories in `bitcoind -help` and `bitcoin-cli help logging` output.
  - Stops returning `"libevent": false` in `logging` RPC output.

  It's not good to treat libevent as a supported log category when it can't be enabled and trying to enable it results in warnings.

  There's also no need to define an unused LIBEVENT constant value and keep more complicated logic for dealing with deprecated log categories, so this change also simplifies code internally.

ACKs for top commit:
  l0rinc:
    code review ACK 3765b428d1
  pinheadmz:
    ACK 3765b428d1
  sedited:
    ACK 3765b428d1

Tree-SHA512: 09e9514f905bb0a79d870689af491886baaa31fa19f2ad6aef4283fa20c2fa6ce8d384178139227aeeabffabff6e83d254114daaeefbbfe2c6172b9da8871298
2026-06-30 18:00:09 +02:00
ekzyis
a318f43254 bitcoin-util: Add netmagic command 2026-06-30 00:33:00 +02:00
Ava Chow
e1290ce7f7 Merge bitcoin/bitcoin#35543: test: introduce ExtendedPrivateKey and ExtendedPublicKey classes
8791c4764c test: use ExtendedPrivateKey in wallet_taproot.py (rkrux)
89ceafafb9 test: use ExtendedPrivateKey in wallet_listdescriptors.py (rkrux)
bbfffcab58 test: use ExtendedPrivateKey in wallet_send.py (rkrux)
2ab6e590f7 test: use ExtendedPrivateKey in wallet_keypool.py (rkrux)
9e20118720 test: use ExtendedPrivateKey in wallet_fundrawtransaction.py (rkrux)
06af0cddbb test: use ExtendedPrivateKey in wallet_descriptor.py (rkrux)
4100fac20e test: use ExtendedPrivateKey in wallet_createwallet.py (rkrux)
ff3f6def9a test: use ExtendedPrivateKey in wallet_bumpfee.py (rkrux)
003f2a01f6 test: use ExtendedPrivateKey in feature_notifications.py (rkrux)
f988e6d6e6 test: use ExtendedPrivateKey in wallet_importdescriptors.py (rkrux)
d2a03d50ac test: add extendedkey.py unit tests by using BIP32 test vectors (rkrux)
afdb378082 test: introduce ExtendedPrivateKey and ExtendedPublicKey classes (rkrux)
4dbaa7cc65 test: generalise byte_to_base58 utility function to allow more version types (rkrux)

Pull request description:

  Many a times there has been a need to come up with dynamic xprvs and xpubs
  in the functional tests, but the lack of code that creates them dynamically has
  led to the presence of several hardcoded keys in the testing framework. This
  is not developer friendly and not self-documenting, clutters the testing code,
  and makes it difficult to update the tests in the future.

  This PR introduces two utility classes ExtendedPrivateKey and
  ExtendedPublicKey that allows the developer to create them on the fly
  to be used in the tests. I have intentionally not introduced any library for this
  purpose and have reused the existing libraries and functions in the framework.
  The implementation is supposed to provide basic functionality for creating
  xprv randomly or from a fixed seed, creating corresponding xpub, and
  deriving child xprvs and xpubs at custom derivation paths.

  I've updated many tests to show how these can be used, there are more
  tests as well that can be updated in the future to completely remove such
  non-deterministic hardcoded keys.

ACKs for top commit:
  achow101:
    ACK 8791c4764c
  w0xlt:
    ACK 8791c4764c

Tree-SHA512: f8ec4e09eaa6cc44b0f1c9a91337e570b12fb882c258be89b470de1a8cecf9d2fd40d9f02ee739dcbf639462ea7710aa145a3726f0f537f5a1f1e7772e5b019d
2026-06-26 15:56:05 -07:00
merge-script
295ce6f45c Merge bitcoin/bitcoin#35576: test: raise feature_reindex RPC timeout
9e6546c517 test: raise reindex mining RPC timeout (Lőrinc)

Pull request description:

  **Problem:** I often hit a timeout in `feature_reindex.py` when running functional tests locally in parallel in debug mode (especially on battery or in power-saving mode).
  **Fix:** Increase the test-local RPC timeout for the reindex mining setup.

ACKs for top commit:
  mercie-ux:
    ACK 9e6546c517
  sedited:
    ACK 9e6546c517

Tree-SHA512: d3541dd6752f943921a030393b00e684b3b5d00b93aa0b2b1f85c017698bdfe2216d7f5441bb7dd5f153453385e4df6f9cc8055589e57bca83fa48f0b7de4252
2026-06-25 09:30:50 +01:00
merge-script
633044f143 Merge bitcoin/bitcoin#35266: rpc, wallet: add an option to not load the wallet after migrating
0cdd817a82 add release note (Pol Espinasa)
517d37ce3e test: tests wallet migration with load_wallet disabled (Pol Espinasa)
b98dd63da7 rpc: Add load_wallet argument to migratewallet RPC (Pol Espinasa)
4acd063ba6 wallet: make loading the wallet after migrating optional (Pol Espinasa)
97d08d62ba refactor: store wallet names to MigrationResult (Pol Espinasa)

Pull request description:

  This PR is motivated by this [Stack Exchange question](https://bitcoin.stackexchange.com/questions/130713/bitcoin-core-quickest-method-legacy-descriptor-wallet-migration).

  Long story short, someone who has a node pruned before his legacy wallet birthday, is unable to migrate the wallet as it is not possible to load it.

  Loading is not necessary for migration, and migrating without wanting to use the wallet in that node is a valid use-case.

  This PR adds a new RPC argument to `migratewallet` that allow the user disabling the wallet loading.
  Second commits adds tests for it.

  Follow-up: Add an option to the GUI to not load the wallet after migrating.

ACKs for top commit:
  achow101:
    ACK 0cdd817a82
  w0xlt:
    ACK 0cdd817a82
  pablomartin4btc:
    ACK 0cdd817a82

Tree-SHA512: 8389599e63603b1a532e1bfba0b6c652653386c001f5a881bd49843302b74ff4dbaa4131b5b377c24f483d42e0e70a92b96f760244e3c2e2b44ce08cd04ca1e0
2026-06-24 21:28:55 +02:00
Ryan Ofsky
3765b428d1 logging: More fully remove libevent log category
Libevent log category was partially removed in 39e9099da5, and this
commit extends that with the following changes:

- Stops showing libevent in the list of supported log categories in
  `bitcoind -help` and `bitcoin-cli help logging` output.

- Stops returning `"libevent": false` in `logging` RPC output.

It's not good to treat libevent as a supported log category when it
can't be enabled and trying to enable it results in warnings.

There's also no need to define an unused LIBEVENT constant value and
keep more complicated logic for dealing with deprecated log categories,
so this change also simplifies code internally.

Co-authored-by: David Gumberg <davidzgumberg@gmail.com>
Co-authored-by: l0rinc <pap.lorinc@gmail.com>
2026-06-23 22:10:34 -04:00
Ava Chow
d84fc352cb Merge bitcoin/bitcoin#35550: net_processing: fix BIP152 first integer interpretation
abc33ff043 test: announce field must be 0 or 1 in sendcmpct (brunoerg)
2d0dce0af5 net_processing: fix BIP152 first integer interpretation (brunoerg)

Pull request description:

  Fixes #35542

  According to the BIP152, the first integer in `sendcmpct` message shall be interpreted as a boolean (and MUST have a value of either 1 or 0). We currently correctly interpret it as boolean, however, we accept any value >=1 and treat it as `true`, deviating from the specification. This PR fixes it.

ACKs for top commit:
  edilmedeiros:
    utACK abc33ff043
  davidgumberg:
    crACK abc33ff043 Seems reasonable to comply with BIP152 strictly, test looks good as well.
  Sjors:
    ACK abc33ff043
  jonatack:
    re-ACK abc33ff043
  achow101:
    ACK abc33ff043
  w0xlt:
    ACK abc33ff043

Tree-SHA512: 77fed86d4de81f7c35ff002b6e1b2a90882ea55f159075da4d34a619d1075f625fca34f929cdd981f1b2eb06f76b64f42cda46502dcd1b4a634c690b0882ec7c
2026-06-23 16:19:13 -07:00
Ava Chow
fafff08e1f Merge bitcoin/bitcoin#35403: mining: pr 33966 followups (disentangle miner startup defaults)
b847626562 test: refresh MiniWallet after node restart (Sjors Provoost)
f4e643cb15 test: merge mining options in package feerate check (Sjors Provoost)
280ce6a0ae miner: ensure block_max_weight is flattened before limit checks (Sjors Provoost)
65bd3164fb mining: clarify test_block_validity comment (Sjors Provoost)
978e7216e6 test: use shared default_ipc_timeout (Sjors Provoost)

Pull request description:

  This implement the suggested followups from #33966. Each commit links  to the original comment.

  The most important change is the extra asserts added in `miner: ensure block_max_weight is flattened before limit checks`.

ACKs for top commit:
  achow101:
    ACK b847626562
  enirox001:
    tACK b847626562
  sedited:
    ACK b847626562
  w0xlt:
    ACK b847626562

Tree-SHA512: 47678eaed604228269bd892ccf8ff58804745bbc7675b4a93528da9a9292a2eb1e0562cdb8341edac77178563420885b48282bb9e5c2b997b28f2fc64ceeff3d
2026-06-23 15:07:29 -07:00
merge-script
fa8e4700ba Merge bitcoin/bitcoin#35424: doc, wallet: align external signer documentation, reject sendtoaddress/sendmany
2fe34808fa wallet: reject sendtoaddress and sendmany for external signers (Sjors Provoost)
bd5a32f7db doc: add taproot descriptor to getdescriptors example (woltx)
7131c82937 doc: clarify which commands receive --chain, --fingerprint and --stdin (woltx)
4fdd4d8d29 doc: replace stale signtransaction wording with current signtx flow (woltx)
fab92257fe doc, rpc: document enumerate model field and fingerprint deduplication (woltx)

Pull request description:

  This PR aligns the external signer documentation with current behavior, and makes one previously implicit behavior explicit.
  Per review feedback, each commit fixes a limited set of issues:

  * **doc, rpc: document enumerate model field and fingerprint deduplication** — the `enumerate` response uses the optional `model` field, which Bitcoin Core maps to the `name` field of the `enumeratesigners` RPC result. Duplicate fingerprints are skipped, and wallet operations require exactly one connected signer.

  * **doc: replace stale signtransaction wording with current signtx flow** — spending from an external signer wallet uses `send`/`sendall` (and `bumpfee` for fee-bumping), which invoke `<cmd> --stdin` and pass the `signtx` subcommand and PSBT over stdin.

  * **doc: clarify which commands receive --chain, --fingerprint and --stdin** — mark `--chain` and `--fingerprint` as required except for `enumerate`, keep `--stdin` required for protocol flexibility, and match the order and form of the actual invocations in the usage examples.

  * **doc: add taproot descriptor to getdescriptors example** — show the BIP86 `tr()` descriptor alongside the other address types.

  * **wallet: reject sendtoaddress and sendmany for external signers** — return a specific error instead of the misleading "Private keys are disabled for this wallet", with functional test coverage. Cherry-picked from #33112 (thanks Sjors).

  How the documentation went stale:

  * The `enumerate` example has shown a `name` field since external signer support landed in #16546, but the implementation has always read `model`.

   * `sendtoaddress`/`sendmany` external signer support was effectively precluded by #21201, which was merged a few days before #16546, so the interaction was missed in review and the documented `signtransaction` flow never existed in this form.

  * Fingerprint deduplication was added in #35251.

  * The documentation was last updated in #33765.

ACKs for top commit:
  Sjors:
    ACK 2fe34808fa
  optout21:
    ACK 2fe34808fa
  naiyoma:
    ACK 2fe34808fa

Tree-SHA512: 86859d2f81ac337f3b4b6578c6ee0151ffb76b8374dfa58e28e00ce4eb69dc200cd6bd2d0a99f73d0475c3824d6ac1cb9e2542b119ca124dd835132dc95cd023
2026-06-23 14:01:48 +01:00
rkrux
8791c4764c test: use ExtendedPrivateKey in wallet_taproot.py 2026-06-23 15:13:49 +05:30
rkrux
89ceafafb9 test: use ExtendedPrivateKey in wallet_listdescriptors.py 2026-06-23 15:13:48 +05:30
rkrux
bbfffcab58 test: use ExtendedPrivateKey in wallet_send.py 2026-06-23 15:13:48 +05:30
rkrux
2ab6e590f7 test: use ExtendedPrivateKey in wallet_keypool.py 2026-06-23 15:13:48 +05:30
rkrux
9e20118720 test: use ExtendedPrivateKey in wallet_fundrawtransaction.py 2026-06-23 15:13:48 +05:30
rkrux
06af0cddbb test: use ExtendedPrivateKey in wallet_descriptor.py 2026-06-23 15:13:48 +05:30
rkrux
4100fac20e test: use ExtendedPrivateKey in wallet_createwallet.py 2026-06-23 15:13:48 +05:30
rkrux
ff3f6def9a test: use ExtendedPrivateKey in wallet_bumpfee.py 2026-06-23 15:13:47 +05:30
rkrux
003f2a01f6 test: use ExtendedPrivateKey in feature_notifications.py 2026-06-23 15:13:47 +05:30
rkrux
f988e6d6e6 test: use ExtendedPrivateKey in wallet_importdescriptors.py
This avoids hardcoding xprvs and xpubs in the test.

Also use key's parent fingerprint and derivation path while creating descriptors
so that all of it is self-documenting and not dependent on hardcoded values,
making them easy to read and update.

Also use descsum_create function more to avoid hardcoding the descriptor
checksum.
2026-06-23 15:13:42 +05:30
merge-script
6b58eb6d51 Merge bitcoin/bitcoin#35070: validation: prevent FindMostWorkChain from causing UB
d6359937bf validation: check invariants when inserting into m_blocks_unlinked (stratospher)
0852925bd8 test/doc: remove misleading comment and improve tests (stratospher)
ca4a380281 test: add coverage for UB caused by FindMostWorkChain (stratospher)
c787b3b99b validation: avoid duplicates in m_blocks_unlinked (stratospher)

Pull request description:

  This is joint work with @ mzumsande.

  note: this requires a pruned node with deep reorgs to trigger. still it breaks assumptions in the codebase and is good to fix. A similar UB was fixed in https://github.com/bitcoin/bitcoin/pull/34521.

  This PR prevents duplicate insertions into `m_blocks_unlinked` in `FindMostWorkChain`. There are 3 ways to insert into `m_blocks_unlinked`:

  1. `LoadBlockIndex` - not problematic, as each block index is processed only once.
  2. `ReceivedBlockTransactions` - not problematic, as this is usually only called once per block when it is first accepted in `AcceptBlock`. in the rare case it’s triggered again after pruning, the block would have been removed from `m_blocks_unlinked` when it was initially pruned, so duplicates still can’t arise.
  3. `FindMostWorkChain` - problematic when multiple candidate tips share common chains of ancestors, traversals from each tip to the fork point may insert duplicate (`pprev`, `pindex`) entries for blocks whose parents have been pruned.

  When the missing parent is later received and `ReceivedBlockTransactions` processes `m_blocks_unlinked`, the same entry may be processed multiple times. This can result in the block being re-added to `setBlockIndexCandidates` with a modified `nSequenceId`, violating its ordering invariants and leading to undefined behavior. So avoid duplicate insertions into `m_blocks_unlinked` in `FindMostWorkChain`.

  ### how to test:

  use the updated `feature_pruning.py` which adds coverage for this scenario.
  - on master: the test (with the below diff) fails since `nSequenceId` is being modified for an entry in `setBlockIndexCandidates`
  - on this branch: the test (with the below diff) passes

  ```diff --git a/src/validation.cpp b/src/validation.cpp
  --- a/src/validation.cpp
  +++ b/src/validation.cpp
  @@ -3814,6 +3814,12 @@ void ChainstateManager::ReceivedBlockTransactions(const CBlock& block, CBlockInd
                      pindex->nHeight, pindex->m_chain_tx_count, prev_tx_sum(*pindex), CLIENT_NAME, FormatFullVersion(), CLIENT_BUGREPORT);
               }
               pindex->m_chain_tx_count = prev_tx_sum(*pindex);
  +            for (const auto& c : m_chainstates) {
  +                if (c->setBlockIndexCandidates.contains(pindex)) {
  +                    LogInfo("### pindex UB = %s", pindex);
  +                    assert(false);
  +                }
  +            }
               pindex->nSequenceId = nBlockSequenceId++;
               for (const auto& c : m_chainstates) {
                   c->TryAddBlockIndexCandidate(pindex);
  ```

ACKs for top commit:
  sedited:
    Re-ACK d6359937bf
  marcofleon:
    crACK d6359937bf
  stringintech:
    ACK d6359937bf
  mzumsande:
    Sure - Code Review ACK [d635993](d6359937bf)

Tree-SHA512: bb21adc2d92fe1865bbbcebf775a850ca3eccac6fe83d7bca10b78eee4c0abf782e44fa0ddfec9d9a70f42fa40bdc49b68a1d1b4905cdc371ba29117d3120619
2026-06-23 09:25:06 +01:00
Pol Espinasa
517d37ce3e test: tests wallet migration with load_wallet disabled
Co-authored-by: w0xlt <woltx@protonmail.com>
2026-06-22 23:07:18 +02:00
Matthew Zipkin
39e9099da5 logging: deprecate libevent category
Creates logic to deprecate logging categories but still
"support" them so the software doesn't quit with unknown category
on startup. Deprecated categories are always false and attempts
to switch them are logged as warnings.
2026-06-22 05:47:01 -04:00
Matthew Zipkin
21c7542cf8 http: switch servers from libevent to bitcoin 2026-06-22 05:47:00 -04:00
Matthew Zipkin
881d4b6c75 test: cover common HTTP attacks and common malformed requests 2026-06-22 05:46:31 -04:00
Lőrinc
9e6546c517 test: raise reindex mining RPC timeout
`feature_reindex.py` mines a long chain before restarting during reindex.
Bump its local RPC timeout to avoid client timeouts in parallel debug-mode runs.
2026-06-21 19:28:00 +02:00
merge-script
ea626c268a Merge bitcoin/bitcoin#35560: lint: Require scripted-diff script to succeed (take 2)
fab2874269 lint: Require scripted-diff script to succeed (MarcoFalke)

Pull request description:

  Currently, scripted diffs may silently pass with errors.

  Fix this issue by calling the script from a Bash instance with error checking enabled: `bash -o errexit -o nounset -o pipefail -c "$SCRIPT"`.

  Also, use Bash (not sh) when launching the script itself, because Bash is required anyway.

  Can be tested by running something like this and observing the behavior before and after:

  ```
  git commit --allow-empty -m $'scripted-diff: foo\n\n-BEGIN VERIFY SCRIPT-\n  false;falseasfsafsaf;true;false|cat; echo "${NO_UN_SET}"|cat  \n-END VERIFY SCRIPT-\n' && ./test/lint/commit-script-check.sh HEAD~..HEAD ; echo $?
  ```

  Alternatively, an ancient brittle script can be tested:

  ```
  ./test/lint/commit-script-check.sh fb65dde147f63422c4148b089c2f5be0bf5ba80f~..fb65dde147f63422c4148b089c2f5be0bf5ba80f

ACKs for top commit:
  hodlinator:
    ACK fab2874269
  sedited:
    ACK fab2874269

Tree-SHA512: e3e8167e150be45a096d4883057640eb5624456f21b134cfa901fe490e5afb192855e55a752cb6121399314f65db155544a60645a101c39a084a62de4af23298
2026-06-21 15:47:03 +02:00
Ava Chow
1a2523e901 Merge bitcoin/bitcoin#34937: Fix startup failure with RLIM_INFINITY fd limits
735b25519a support: clamp RLIMIT_MEMLOCK to size_t (Sjors Provoost)
8ab4b9fc85 init: clamp fd limits to int (Sjors Provoost)
4afbabdcef Fix startup failure with RLIM_INFINITY fd limits (Sjors Provoost)

Pull request description:

  When setting the fd limit to unlimited, the node fails to start:

  ```sh
  ulimit -n unlimited
  build/bin/bitcoind
  Error: Not enough file descriptors available. -1 available, 160 required.
  ```

  This was caused by `RaiseFileDescriptorLimit()` (introduced in #2568) casting `limitFD.rlim_cur` to `int`, which for `RLIM_INFINITY` overflows to `-1`. Fix it by returning `std::numeric_limits<int>::max()` instead.

  Some platforms implement `RLIM_INFINITY` as the maximum uint64, others as int64 (-1). So simply changing the return type to `uint64_t` wouldn't work.

  Similarly, though unlikely to actually happen:

  ```sh
  ulimit -n 214748364
  build/bin/bitcoind
  Error: Not enough file descriptors available. -2147483648 available, 160 required.
  ```

  The second commit expands the fix by clamping all values above `std::numeric_limits<int>::max()` instead of letting them overflow.

  This PR also expands `test/functional/feature_init.py` to cover these, using `resource.setrlimit`. The check is skipped on environments with a hard limit below infinity (or that don't have the Python [Resource module](https://docs.python.org/3/library/resource.html)).

  macOS by default has a hard limit of infinity, but on e.g. Ubuntu the default hard limit is 524288.

  The third commit applies a similar fix to `PosixLockedPageAllocator::GetLimit()` for 32-bit systems, but without a test.

ACKs for top commit:
  winterrdog:
    Re-ACK 735b25519a
  achow101:
    ACK 735b25519a
  sedited:
    Re-ACK 735b25519a
  pinheadmz:
    ACK 735b25519a

Tree-SHA512: 0ce0292ecd61456bdec6943b06cbb9ecfc5180ee6dce850f8496ef54af22c1fae6ea473085202f5ba6f72e4dc51a29247620c9a0eae31e96658adc77b293129f
2026-06-19 15:57:59 -07:00
Ryan Ofsky
794befd4b0 Merge bitcoin/bitcoin#35384: util: Check write failures before renaming settings.json
0654511e1b util: Check write failures before renaming settings.json (Shrey)

Pull request description:

  This PR Fixes #35373.
  The error message was updated from: "This is probably caused by disk corruption or a crash" to: "This is probably caused by a full disk, disk corruption or a crash"

  The following files were updated:
  1. src/common/settings.cpp -- Updated the main string formatting for the parse failure.
  2. src/test/settings_tests.cpp -- Updated the exact string expectation in the C++ unit test.
  3. test/functional/feature_settings.py -- Updated the expected error message in the Python test suite.

  Configured the Bitcoin Core project natively on Windows using Visual Studio (cmake --preset vs2026-static -DBUILD_GUI=OFF) and it compiled with 100% of the C++ tests passed successfully (347 out of 347).

ACKs for top commit:
  maflcko:
    review ACK 0654511e1b 💧
  winterrdog:
    ACK 0654511e1b
  sedited:
    ACK 0654511e1b
  ryanofsky:
    Code review ACK 0654511e1b with commit message and error message improved since last review

Tree-SHA512: d7b49860f2081a5a9d1d44917b0cf372a77f10cf21773c9b3291871c788a122ec5dde063fdf9e1052cf45b8d2667e15585b952e9f037e84f98fb41546bdd1fa9
2026-06-19 07:38:26 -04:00
rkrux
d2a03d50ac test: add extendedkey.py unit tests by using BIP32 test vectors 2026-06-19 16:09:43 +05:30
rkrux
afdb378082 test: introduce ExtendedPrivateKey and ExtendedPublicKey classes
Using these classes allows the developers to dynamically create
xprvs and xpubs so that they don't need to hardcode such long keys
in the tests that most of the times clutter the tests and make them
difficult to update.

Co-authored-by: w0xlt <94266259+w0xlt@users.noreply.github.com>
2026-06-19 16:09:38 +05:30
MarcoFalke
fab2874269 lint: Require scripted-diff script to succeed 2026-06-18 11:35:26 +02:00
brunoerg
abc33ff043 test: announce field must be 0 or 1 in sendcmpct 2026-06-17 19:50:02 -03:00
Shrey
0654511e1b util: Check write failures before renaming settings.json
In WriteSettings(), verify that writing to the stream and closing it
succeeded before returning true. This prevents RenameOver() from replacing
a valid settings.json with a corrupted or zero-byte file when write limits
or a full disk are encountered.

Additionally, update the ReadSettings() parse failure message to mention
power loss, full disk, or storage error as possible causes.

Fixes #35373
2026-06-17 20:47:21 +05:30
Hennadii Stepanov
f570d7cd53 Merge bitcoin/bitcoin#35547: lint: Require scripted-diff script to succeed
2a36d6a561 lint: Require scripted-diff script to succeed (Hodlinator)

Pull request description:

  Previous version of commit-script-check.sh would succeed as long as git diff succeeded.

  Can be verified through adding a failing scripted diff commit such as:
  ```
  git commit --allow-empty -m $'scripted-diff: foo\n\n-BEGIN VERIFY SCRIPT-\nadsasd\n-END VERIFY SCRIPT-\n'
  ```
  ...and running...
  ```
  cargo run --manifest-path ./test/lint/test_runner/Cargo.toml -- --lint=scripted_diff
  ```

ACKs for top commit:
  maflcko:
    lgtm ACK 2a36d6a561
  furszy:
    ACK 2a36d6a561
  hebasto:
    ACK 2a36d6a561.

Tree-SHA512: 160397cc009b18ccb3bc66c85c1b89404a81c9a85acee534638f4752577165aead56d6cfb21d9fcb424484bc6710658cd0f1d2f483d8298e9e3a2f5243ef8e8b
2026-06-17 14:59:34 +01:00
Hodlinator
2a36d6a561 lint: Require scripted-diff script to succeed
Previous version of commit-script-check.sh would succeed as long as git diff succeeded.

Can be verified through adding a failing scripted diff commit such as:
    git commit --allow-empty -m $'scripted-diff: foo\n\n-BEGIN VERIFY SCRIPT-\nadsasd\n-END VERIFY SCRIPT-\n'
...and running...
    cargo run --manifest-path ./test/lint/test_runner/Cargo.toml -- --lint=scripted_diff
2026-06-17 14:59:46 +02:00
rkrux
4dbaa7cc65 test: generalise byte_to_base58 utility function to allow more version types
Passing a version in the byte form is allowed now in addition to the integral
version type. This will be helpful in the next commit.
2026-06-16 20:37:17 +05:30
merge-script
9460090f1a Merge bitcoin/bitcoin#35520: lint: remove redundant test suite uniqueness check
946feb3f1f test: remove redundant test suite uniqueness lint (Lőrinc)

Pull request description:

  Follow-up to https://github.com/bitcoin/bitcoin/pull/35451#discussion_r3403672298.

  **Problem:** That duplicate check in `test/lint/lint-tests.py` is redundant now: CMake already registers each Boost test suite as a CTest test name and rejects duplicates there.

  **Fix:** Remove the `check_unique_test_names` path and its now-unused duplicate helper and inline remaining helper into `main()`.

  **Reproducers:** These throwaway patches pass `test/lint/lint-tests.py` and fail during CMake test registration.

  <details><summary>Internal `src/test` duplicate</summary>

  ```diff
  diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp
  index 051a8fcd25..3b50bff724 100644
  --- a/src/test/base32_tests.cpp
  +++ b/src/test/base32_tests.cpp
  @@ -54,3 +54,7 @@ BOOST_AUTO_TEST_CASE(base32_padding)
   }

   BOOST_AUTO_TEST_SUITE_END()
  +
  +BOOST_AUTO_TEST_SUITE(base32_tests)
  +BOOST_AUTO_TEST_CASE(base32_duplicate_probe) { BOOST_CHECK(true); }
  +BOOST_AUTO_TEST_SUITE_END()
  ```
  </details>
  <details><summary>Internal `src/wallet/test` duplicate</summary>

  ```diff
  diff --git a/src/wallet/test/wallet_rpc_tests.cpp b/src/wallet/test/wallet_rpc_tests.cpp
  index 8bf5eab443..854d010ec0 100644
  --- a/src/wallet/test/wallet_rpc_tests.cpp
  +++ b/src/wallet/test/wallet_rpc_tests.cpp
  @@ -37,5 +37,10 @@ BOOST_AUTO_TEST_CASE(ensure_unique_wallet_name)
       BOOST_CHECK_THROW(TestWalletName("/wallet/foobar", "foo"), UniValue);
   }

  +BOOST_AUTO_TEST_SUITE_END()
  +
  +BOOST_FIXTURE_TEST_SUITE(wallet_rpc_tests, BasicTestingSetup)
  +BOOST_AUTO_TEST_CASE(wallet_rpc_duplicate_probe) { BOOST_CHECK(true); }
  +
   BOOST_AUTO_TEST_SUITE_END()
   } // namespace wallet
  ```
  </details>
  <details><summary>Cross `src/test` and `src/wallet/test` duplicate</summary>

  ```diff
  diff --git a/src/wallet/test/CMakeLists.txt b/src/wallet/test/CMakeLists.txt
  index 524c7218f4..04628e0327 100644
  --- a/src/wallet/test/CMakeLists.txt
  +++ b/src/wallet/test/CMakeLists.txt
  @@ -8,6 +8,7 @@ target_sources(test_bitcoin
     PRIVATE
       init_test_fixture.cpp
       wallet_test_fixture.cpp
  +    base32_tests.cpp
       db_tests.cpp
       coinselector_tests.cpp
       coinselection_tests.cpp
  diff --git a/src/wallet/test/base32_tests.cpp b/src/wallet/test/base32_tests.cpp
  new file mode 100644
  index 0000000000..da91d87dca
  --- /dev/null
  +++ b/src/wallet/test/base32_tests.cpp
  @@ -0,0 +1,5 @@
  +#include <boost/test/unit_test.hpp>
  +
  +BOOST_AUTO_TEST_SUITE(base32_tests)
  +BOOST_AUTO_TEST_CASE(wallet_cross_duplicate_probe) { BOOST_CHECK(true); }
  +BOOST_AUTO_TEST_SUITE_END()
  ```
  </details>

  The CMake failures are in the form:

  ```text
  CMake Error at src/test/CMakeLists.txt:199 (add_test):
    add_test given test NAME "<duplicate_suite>" which already exists in this
    directory.
  ```

ACKs for top commit:
  maflcko:
    lgtm ACK 946feb3f1f
  sedited:
    ACK 946feb3f1f

Tree-SHA512: a511507d21db142b3f2ed6e966d9e8f1e7016e750de122d88f4502edc84c0cfc696054e757bf905ca58d9774ad6263b2a59ec8cbbcc1f3e28ed1896ba4cdd8aa
2026-06-16 14:28:31 +02:00
Lőrinc
d3e40af259 index: shorten indexer thread names
`BaseIndex` currently uses the same name for logs, `getindexinfo`, prune locks, and the sync thread.
Linux truncates system thread names to 15 visible bytes after the `b-` prefix, so long indexer names are clipped in system tools.

Pass a separate thread name explicitly at each `BaseIndex` call site and shorten the OS-visible indexer names to `txidx`, `blkfltbscidx`, `coinstatsidx`, and `txospenderidx`.
Add an `Assume` to `ThreadRename()` so future OS-visible thread names keep fitting the same Linux limit.
The public index names, `getindexinfo` keys, command-line options, and on-disk paths stay unchanged.

Co-authored-by: winterrdog <winterrdog@users.noreply.github.com>
Co-authored-by: Hodlinator <172445034+hodlinator@users.noreply.github.com>
Co-authored-by: sedited <seb.kung@gmail.com>
Co-authored-by: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz>
2026-06-16 11:16:00 +02:00
merge-script
355fffb8cc Merge bitcoin/bitcoin#35528: test: doc: remove --perf profiling from functional test framework
9fae7e9886 test: doc: remove `--perf` profiling from functional test framework (Sebastian Falbesoner)

Pull request description:

  This PR is an alternative to #35509. Rather than fixing, it removes the `--perf` option / `profile_with_perf` context manager features (both introduced in #14519) from the functional test framework. Given that no developer apparently even noticed that it's been broken for more than a year, we can conclude that it's largely unused and getting rid of it to reduce maintenance burden seems a reasonable choice. So far, neither in #35509 nor [on IRC](https://bitcoin-irc.chaincode.com/bitcoin-core-dev/2026-06-12#1227556;) anyone has signaled strong interest to use or wanting to keep this feature.

  The corresponding test documentation is removed as well, though the mentioning of `perf` profiling is still kept in the general developer docs -- only the reference to functional test framework integration is removed there.

ACKs for top commit:
  l0rinc:
    lightweight code review ACK 9fae7e9886
  maflcko:
    lgtm ACK 9fae7e9886  While this seems useful, no one using it is a good reason to remove it. If a user comes after this is merged, it should be trivial to revert.

Tree-SHA512: cf7bdce72aed877c7dfa52a230840e0729e74b00f0c40c6ceecf04957707f4699f123c2cde5fc1c4ee21f4b1b14319c74acc78cd8066eab2b9a4d6efb4d11539
2026-06-15 15:04:45 +02:00
merge-script
46927cf82c Merge bitcoin/bitcoin#35504: test/doc: Follow-up nits for #35269
b3371029dc doc: use signing pubkey instead of aggregate xonly key (kevkevinpal)
ddceb4e603 test: updated different_key to be different_field and also used a single assert_equal with 3 args instead of multiple assert_equals (kevkevinpal)

Pull request description:

  ## Summary:
  This is a follow-up to https://github.com/bitcoin/bitcoin/pull/35269

  - Rename `different_key` to `different_field` in `assert_musig_signer_data` ([discussion](https://github.com/bitcoin/bitcoin/pull/35269#discussion_r3337676268))
  - Use 3-argument `assert_equal` for pubnonce/partial-sig length checks, matching the pattern already used for `finalized["complete"]` ([discussion](https://github.com/bitcoin/bitcoin/pull/35269#discussion_r3337695530))
  - Fix `MuSig2SessionID` doc to say "signing pubkey" instead of "aggregate xonly key" ([discussion](https://github.com/bitcoin/bitcoin/pull/35269#pullrequestreview-4350165352))

ACKs for top commit:
  rkrux:
    code review ACK b3371029dc
  theStack:
    ACK b3371029dc

Tree-SHA512: 5fa46ef8a5c2710dbbb50ece22c50e423fad81617c0f7f235a01c862d3d6a650a301aa3076fbbe0101b06a7fbeb7403bcc556dafcca16d1873199fad645b7c14
2026-06-15 14:51:59 +02:00
Sebastian Falbesoner
9fae7e9886 test: doc: remove --perf profiling from functional test framework
This feature was broken for more than a year and no developer apparently
even noticed, so one can conclude that it is largely unused; it seems
thus reasonable to remove it to reduce maintenance burden.
2026-06-13 22:59:23 +02:00
stringintech
406c2348dd rpc: tighten setmocktime upper bound to UINT32_MAX
The previous bound (~year 2262) was too permissive: paths that add an offset to the mocked time (e.g. the future-time check in ContextualCheckBlockHeader) can overflow int64_t (caught by UBSan), and paths that assign it to a uint32_t field (e.g. pblock->nTime in miner.cpp) silently truncate it (caught by the integer sanitizer). UINT32_MAX is the natural ceiling since block header nTime is uint32_t, and mocking beyond it is meaningless for anything consensus-related.

Add setmocktime bound checks to the existing _test_y2106 case in rpc_blockchain.py, and remove the negative bound check from rpc_uptime.py.
2026-06-13 13:17:15 +03:30
Lőrinc
946feb3f1f test: remove redundant test suite uniqueness lint
Duplicate Boost test suite names are already rejected by CMake when the suites are registered as CTest tests.
Follow-up to https://github.com/bitcoin/bitcoin/pull/35451#discussion_r3403672298.

Co-authored-by: maflcko <6399679+maflcko@users.noreply.github.com>
2026-06-12 23:00:57 +02:00
merge-script
142e86a65c Merge bitcoin/bitcoin#35458: qa: Avoid extra tracebacks when exception is raised
472b950b7f qa: Use custom assert_greater_than() over naked assert (Hodlinator)
f42226d526 qa: Silence socket.timeout exception when substituting it for a JSONRPCException (Hodlinator)
659671ac3d qa: Avoid cleanup when exception is raised (Hodlinator)

Pull request description:

  Clean up some cases in which we would trigger multiple tracebacks, which makes it unclear what issue is occuring (https://github.com/bitcoin/bitcoin/issues/31894#issuecomment-4616130031).

  CI log of this occurring: https://github.com/bitcoin/bitcoin/actions/runs/26907239657/job/79375388058?pr=35179

  <details><summary>Relevant log excerpt</summary>

  ```
   test  2026-06-03T19:28:28.119804Z TestFramework.node0 (DEBUG): TestNode.generate() dispatches `generate` call to `generatetoaddress`
   test  2026-06-03T19:28:28.120483Z TestFramework (ERROR): Unexpected exception:
                                     Traceback (most recent call last):
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 165, in _get_response
                                         http_response = self.__conn.getresponse()
                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/usr/lib/python3.12/http/client.py", line 1448, in getresponse
                                         response.begin()
                                       File "/usr/lib/python3.12/http/client.py", line 336, in begin
                                         version, status, reason = self._read_status()
                                                                   ^^^^^^^^^^^^^^^^^^^
                                       File "/usr/lib/python3.12/http/client.py", line 297, in _read_status
                                         line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/usr/lib/python3.12/socket.py", line 707, in readinto
                                         return self._sock.recv_into(b)
                                                ^^^^^^^^^^^^^^^^^^^^^^^
                                     TimeoutError: timed out
                                     During handling of the above exception, another exception occurred:
                                     Traceback (most recent call last):
                                       File "/home/runner/work/bitcoin/bitcoin/ci_build/test/functional/p2p_orphan_handling.py", line 54, in wrapper
                                         func(self)
                                       File "/home/runner/work/bitcoin/bitcoin/ci_build/test/functional/p2p_orphan_handling.py", line 633, in test_maximal_package_protected
                                         testres = node.testmempoolaccept([large_orphan.serialize().hex()])
                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/coverage.py", line 50, in __call__
                                         return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 128, in __call__
                                         response, status = self._request('POST', self.__url.path, postdata.encode('utf-8'))
                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 102, in _request
                                         return self._get_response()
                                                ^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 167, in _get_response
                                         raise JSONRPCException({
                                     test_framework.util.JSONRPCException: 'testmempoolaccept' RPC took longer than 30.000000 seconds. Consider using larger timeout for calls that take longer to return. (-344)  [http_status=None]
                                     During handling of the above exception, another exception occurred:
                                     Traceback (most recent call last):
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/test_framework.py", line 143, in main
                                         self.run_test()
                                       File "/home/runner/work/bitcoin/bitcoin/ci_build/test/functional/p2p_orphan_handling.py", line 837, in run_test
                                         self.test_maximal_package_protected()
                                       File "/home/runner/work/bitcoin/bitcoin/ci_build/test/functional/p2p_orphan_handling.py", line 57, in wrapper
                                         self.generate(self.nodes[0], 1)
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/test_framework.py", line 666, in generate
                                         blocks = generator.generate(*args, called_by_framework=True, **kwargs)
                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/test_node.py", line 445, in generate
                                         return self.generatetoaddress(nblocks=nblocks, address=self.get_deterministic_priv_key().address, maxtries=maxtries, **kwargs)
                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/test_node.py", line 453, in generatetoaddress
                                         return self.__getattr__('generatetoaddress')(*args, **kwargs)
                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/coverage.py", line 50, in __call__
                                         return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 128, in __call__
                                         response, status = self._request('POST', self.__url.path, postdata.encode('utf-8'))
                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 101, in _request
                                         self.__conn.request(method, path, postdata, headers)
                                       File "/usr/lib/python3.12/http/client.py", line 1356, in request
                                         self._send_request(method, url, body, headers, encode_chunked)
                                       File "/usr/lib/python3.12/http/client.py", line 1367, in _send_request
                                         self.putrequest(method, url, **skips)
                                       File "/usr/lib/python3.12/http/client.py", line 1193, in putrequest
                                         raise CannotSendRequest(self.__state)
                                     http.client.CannotSendRequest: Request-sent
   test  2026-06-03T19:28:28.124908Z TestFramework (DEBUG): Closing down network thread
  ```

  </details>

  Fix in authproxy.py can be verified through applying the below diff with/without PR changes and running `./build/test/functional/p2p_orphan_handling.py`:

  ```diff
  --- a/test/functional/test_framework/authproxy.py
  +++ b/test/functional/test_framework/authproxy.py
  @@ -162,6 +162,8 @@ class AuthServiceProxy():
       def _get_response(self):
           req_start_time = time.time()
           try:
  +            if AuthServiceProxy.__id_count > 55:
  +                raise socket.timeout()
               http_response = self.__conn.getresponse()
           except socket.timeout:
               raise JSONRPCException({
  ```

ACKs for top commit:
  maflcko:
    review ACK 472b950b7f 🔼
  polespinasa:
    reACK 472b950b7f

Tree-SHA512: ec1ede0340da9d1338643980e7f2e4646f0aed2e64f339f8b41a447cbbfb4da8158c1cbcb22f2d0cc383c2dd945075602d02b07a47b33b44cc6215f3292c1d46
2026-06-12 10:51:47 +02:00
Ava Chow
216b50c9a6 Merge bitcoin/bitcoin#35179: test: Add importdescriptors rpc error coverage
ed11dd6a5f test: add coverage for importdescriptors when manually interrupting a wallet rescan (Pol Espinasa)
d90d7f0a55 test: add coverage for importdescriptors errors when using assumeutxo (Pol Espinasa)
ad388bf254 test: add coverage for importdescriptors while wallet is rescanning (Pol Espinasa)
84d07e471c test: add coverage for importdescriptor with an encrypted wallet (Pol Espinasa)

Pull request description:

  The current tests for `importdescriptors` RPC do not check for cases where RPC errors should be thrown.

  This PR adds coverage for _importing a descriptor when the wallet is encrypted_ , for _importing a descriptor while the wallet is rescanning_ and _importing a descriptor while using assumeutxo_

  For context, this lack of coverage was found while implementing #34861 when a reviewer found that this was being silently broken in the PR.

  I am not sure if the "rescanning test" approach is the optimal solution, I am open to suggestions.

ACKs for top commit:
  achow101:
    ACK ed11dd6a5f
  w0xlt:
    ACK ed11dd6a5f

Tree-SHA512: 18e7111314ff003d39538d53899a3e2261027f5f965945f259eec4b56ece5c22706faf2891694c47575f3a5089ca02c80ea0bd05c453c4e072335d4a45ab8edd
2026-06-11 16:05:33 -07:00
Sjors Provoost
2fe34808fa wallet: reject sendtoaddress and sendmany for external signers
The sendtoaddress and sendmany RPCs always go through SendMoney(), which
expects to sign internally. External signer wallets should use the PSBT
flow instead, via the send RPC.

Return a more specific error for external signer wallets and add
functional test coverage for both RPCs.
2026-06-11 10:40:04 -07:00
Hennadii Stepanov
46d0e21d75 Merge bitcoin/bitcoin#35288: ci: Bump toward Ubuntu 26.04
fab52281f7 refactor: Drop unused includes after iwyu CI bump (MarcoFalke)
fa4774d032 ci: Bump APT_LLVM_V-based task configs to Ubuntu 26.04 (MarcoFalke)
fa1414a36a ci: Debian Trixie -> Ubuntu 26.04 (MarcoFalke)

Pull request description:

  This is for the upcoming 32.x, because I presume users and devs are more likely using a later distro. This comes with tool bumps, such as:

  * GCC 14 -> 15 (https://packages.debian.org/trixie/g++ -> https://packages.ubuntu.com/resolute/g++)
  * Clang 19 -> 21
  * Cmake 3.31 -> 4.2
  * Valgrind 3.24 -> 3.26

ACKs for top commit:
  l0rinc:
    code review ACK fab52281f7
  hebasto:
    re-ACK fab52281f7.

Tree-SHA512: 9d5be2f5b15cf7904c50687ce5e8cceeb2f740c7d5180190d6a10e751998ce2c2156098f89352eac49f24c8cd9ab55b78321e310240ac829dcbe48b576b6240c
2026-06-11 10:36:31 +01:00
stratospher
0852925bd8 test/doc: remove misleading comment and improve tests
remove misleading comment for m_blocks_unlinked since for
pruned nodes:
- usually A is the missing data (just like in non-pruned nodes)
- in PruneOneBlockFile, we remove entries once data for B is missing.

Co-authored-by: Martin Zumsande <mzumsande@gmail.com>
2026-06-11 13:04:57 +05:30
stratospher
ca4a380281 test: add coverage for UB caused by FindMostWorkChain
when pruned node2 finally receives the blocks from
node0, node2 will process duplicate entires in
ReceivedBlockTransactions twice but it will only
insert into setBlockIndexCandidates if the block has
more work that the current chain tip.

the duplicate entries in m_blocks_unlinked in this
test are from height 1171 to 1294.

before this commit
- we invalidated height 1320 and chain tip became
1319. so we won't add duplicate entries (all have
<1319) into setBlockIndexCandidates and won't
have coverage for this UB scenario.

with this commit
- we invalidate height 1295 and chain tip became
1294. so we will process the duplicate entry
1294 in m_blocks_unlinked and have coverage
for this UB.

Co-authored-by: Martin Zumsande <mzumsande@gmail.com>
2026-06-11 13:04:57 +05:30