Commit Graph

50478 Commits

Author SHA1 Message Date
merge-script
6f6b2bbde2 Merge bitcoin/bitcoin#35808: fuzz: reset connman state in p2p targets
d29b22d078 fuzz: reset connman state in p2p targets (Hao Xu)

Pull request description:

  Resets `ConnmanTestMsg` at the start of each input in `cmpctblock` and `p2p_handshake`, matching the other reused-connman fuzz targets and preventing sticky `CConnman` state from leaking between corpus inputs.

  Before this, deterministic-fuzz-coverage showed single inputs were stable, but all-input directory runs were not:

  ```diff
  cmpctblock, src/net.cpp:4172
  - Branch (4172:9): [True: 1.21k, False: 33.0k]
  + Branch (4172:9): [True: 613, False: 33.6k]
  - Branch (4172:72): [True: 901, False: 311]
  + Branch (4172:72): [True: 497, False: 116]
  ```

  ```diff
  p2p_handshake, src/net.cpp:4172
  - Branch (4172:9): [True: 98, False: 1.67k]
  + Branch (4172:9): [True: 743, False: 1.03k]
  - Branch (4172:72): [True: 90, False: 8]
  + Branch (4172:72): [True: 612, False: 131]
  ```

  With the resets, `deterministic-fuzz-coverage` passed for both `cmpctblock` and `p2p_handshake`.

ACKs for top commit:
  nervana21:
    re-tACK d29b22d078
  maflcko:
    lgtm ACK d29b22d078

Tree-SHA512: bd445ae33ab7f9850046e3de4e318bee9ae7b38ee77ee282d0f5c3a88a4b67610dd00faef2af913a4d7d42bfc42b957855b2d85f1849f77823149baa089afce2
2026-09-02 09:29:26 +01:00
will
e85e27976b rpc: detail x-bitcoin-unit in openrpc help 2026-09-02 09:29:08 +01:00
Matthew Zipkin
3d1004cb9b http: throttle per-connection reads while a request is in flight
A client streaming pipelined requests into a busy connection
(or any connection whose replies are slower than the sender) could grow
server memory without limit, up to remote OOM.

Stop selecting RecvEvent for clients whose request is being processed;
pipelined data then backs up in the kernel socket buffer, applying TCP
backpressure to the sender. One request per connection is in flight
at a time.

Functional test streams pipelined submitblock requests into a connection
blocked on waitforblockheight. Unpatched builds continue draining the
socket buffer indefinitely, patched builds will stall.
2026-09-01 15:56:09 -04:00
Lőrinc
db39de5601 doc: add -walletnotify security note
Co-authored-by: maflcko <6399679+maflcko@users.noreply.github.com>
2026-09-01 11:49:26 -07:00
Lőrinc
1f9dfabef6 refactor: use string views in ReplaceAll
PR #25803 changed these parameters to `const std::string&` for `std::regex_replace()`.
The literal implementation no longer needs owned strings, so restore the original `std::string_view` interface.
2026-09-01 11:46:55 -07:00
Lőrinc
469b0e59a2 util: make ReplaceAll literal
`ReplaceAll()` substitutes fixed tokens in notification commands and other strings.
PR #25803 replaced the Boost helper with `std::regex_replace()`, treating searches as regular expressions and substitutes as replacement-format syntax.

Restore literal, non-recursive replacement so callers match fixed tokens and preserve replacement bytes exactly, while avoiding a new string when the search text is absent.

Co-authored-by: Rob Hamilton <6456095+Rob1Ham@users.noreply.github.com>
2026-09-01 11:46:55 -07:00
Lőrinc
604d7e8fdd test: characterize walletnotify shell injection
`-walletnotify` shell-escapes wallet names before substituting `%w` into the configured command.
`ReplaceAll()` uses `%w` as the regex pattern and the escaped wallet name as replacement text, where `$'` copies the command suffix into the escaped name and allows its shell metacharacters to alter the command.

Record the command execution, missing notification file, regex pattern matching, replacement expansion, and non-recursive replacement.
2026-09-01 11:46:55 -07:00
Lőrinc
4efaa6763a test: simplify ReplaceAll coverage
Let each case provide its input so strings outside the original fixture can use the same table without separate temporary variables.
2026-09-01 11:27:50 -07:00
Lőrinc
74ddf1c0a0 refactor: use structured bindings for map entries 2026-09-01 09:54:28 -07:00
Lőrinc
21d5d5cb73 rpc: append unique container keys directly
RPC responses that build objects from `std::map` or `std::set` keys already have unique keys.

Use `pushKVEnd()` for direct map and set loops in `decodepsbt` and verbose mempool ancestor and descendant results.
Do the same for `getpeerinfo` message counters and selected `getblockstats` results.
2026-09-01 09:50:03 -07:00
Lőrinc
23e512a58e rpc: avoid quadratic prioritised transaction JSON
`GetPrioritisedTransactions()` returns unique keys in map order.
Append them directly instead of scanning the growing UniValue object for duplicates.
2026-09-01 09:50:03 -07:00
jeanpablo
9f0543d69a wallet: remove unused DatabaseOptions members
`use_shared_memory` and `max_log_mb` are never read or written; they
only ever hold their initializers. Their last readers, in
`GetBerkeleyEnv()` and the `BerkeleyDatabase` constructor, were removed
in 04a7a7a28c ("build, wallet, doc: Remove BDB"), along with the
`-privdb` and `-dblogsize` options that set them.

Co-authored-by: pablomartin4btc <pablomartin4btc@gmail.com>
2026-09-01 13:25:22 +01:00
merge-script
dc0395c585 Merge bitcoin/bitcoin#36112: ci: Exclude subtrees from iwyu
fa3971011d ci: Exclude subtrees from iwyu (MarcoFalke)
fa8566152a refactor: Bump old copyright header in univalue (MarcoFalke)

Pull request description:

  The iwyu CI may modify subtrees when iwyu thinks a header inside a subtree is "associated" (due to the naming).

  This happens to not be a problem on current master, but can become a problem if an iwyu-enforced file is renamed or a file is iwyu-enforced in the future.

  Fix this by excluding subtrees.

  Can be tested by running the iwyu CI on `src/test/fuzz/minisketch.cpp` and seeing a change in `minisketch.h` before this CI fix.

ACKs for top commit:
  hebasto:
    re-ACK fa3971011d.

Tree-SHA512: 9a555ab020f0f1a2bc4d70ea72011f8d42ba4bfe4a463947d31b0d208b4671b76b466f92a18b6295bc7a8c5bb67c6f697844f673fc02e18983b062d25bc0dc8c
2026-09-01 11:39:19 +01:00
merge-script
37c57bc5c2 Merge bitcoin/bitcoin#36065: test: refactor: Remove confusing ignore_errors=True
fa7be0a8df test: refactor: Remove confusing ignore_errors=True (MarcoFalke)

Pull request description:

  There is an unexplained `ignore_errors=True` in the internal `_initialize_chain` helper:

  ```py

  shutil.rmtree(cache_path('fees'), ignore_errors=True)
  ```

  This is fine, because no error should happen. But it is a bit confusing, because an ignored error may lead to a later error anyway.

  Fix that by failing early instead.

  Also, re-write the simple block to `pathlib`.

ACKs for top commit:
  willcl-ark:
    ACK fa7be0a8df

Tree-SHA512: c533a8aebd92f3f1054563f20af438165632c98f7a2f189f3306420780468b143c24001f794a79ddfc0527c9605a4cfe59949648a9a7f41bbe138128b09f0a6e
2026-09-01 09:52:00 +01:00
merge-script
8157964e66 Merge bitcoin/bitcoin#36134: doc: Correct comment about which subsystem detects lagging clocks
55390d1827 doc: Correct comment about which subsystem detects lagging clocks (Hodlinator)

Pull request description:

  Turns out a completely fresh datadir means there is no chain state to load and hence no detection of a lagging clock occurs in that subsystem. Instead we do proceed into attempting to start a headers sync.

  <details><summary>Diff to repro with fresh -datadir</summary>

  ```diff
  --- a/src/init.cpp
  +++ b/src/init.cpp
  @@ -1499,6 +1499,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
       const ArgsManager& args = *Assert(node.args);
       const CChainParams& chainparams = Params();

  +    SetMockTime(chainparams.GenesisBlock().Time() - 3h);
  +
       auto opt_max_upload = ParseByteUnits(args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET), ByteUnit::M);
       if (!opt_max_upload) {
           return InitError(strprintf(_("Unable to parse -maxuploadtarget: '%s'"), args.GetArg("-maxuploadtarget", "")));
  ```

  </details>

  Follow-up to #35351

ACKs for top commit:
  sedited:
    ACK 55390d1827
  jonatack:
    ACK 55390d1827

Tree-SHA512: 244a0cb634a0ba67fa88fe83f73111e475f6fff258cd1783b9b0a39669eefdd3b2e739a0b761616972bc938216336e18b0c0322e1201c2e805767cb813ca616c
2026-09-01 09:43:48 +01:00
merge-script
259553c662 Merge bitcoin/bitcoin#36131: rpc: Improve two field's OpenRPC types
78e691ea10 rpc: Change listunspent's ancestorfees type to NUM (sedited)
73fb9ced56 rpc: Fix private key type in signrawtransactionwithkey (sedited)

Pull request description:

  This corrects the types for two fields in the OpenRPC dump. Both changes have no effect on the rpc help output. The changes to the schema's format are:

  ```diff
  diff dump.json dump_new.json
  11452d11451
  <                 "x-bitcoin-unit": "amount",
  13844,13845c13843
  <               "type": "string",
  <               "pattern": "^[0-9a-fA-F]+$"
  ---
  >               "type": "string"
  ```

  I asked Claude to flag any inconsistencies in the dump and these were the two, out of many others, that I thought were worthwhile to fix.

ACKs for top commit:
  maflcko:
    lgtm ACK 78e691ea10
  stickies-v:
    ACK 78e691ea10
  musaHaruna:
    Tested ACK [78e691e](78e691ea10)

Tree-SHA512: 121d80520a39738c1c7375a50bb552203fe2db403cb3414195e6a79142677ac3c3509ba5f18d4b1982a8e2872c73e47cf6e54b6acd66b1a71ddcbe335ea33f34
2026-09-01 09:41:27 +01:00
Craig Raw
1dad06eff3 remove stale canonical form claim from getdescriptorinfo help 2026-09-01 08:45:06 +02:00
Hodlinator
55390d1827 doc: Correct comment about which subsystem detects lagging clocks 2026-08-31 21:29:31 +02:00
merge-script
fe3c92cfe0 Merge bitcoin/bitcoin#36102: util: Replace !ContainsNoNUL() with ContainsNUL()
8d930981e9 refactor: Replace !ContainsNoNUL() with ContainsNUL() (Hodlinator)

Pull request description:

  Avoids frequent double negation. See also fa7078d84f when it was renamed from the previous name, "ValidAsCString()".

  Found while reviewing #35041.

ACKs for top commit:
  maflcko:
    lgtm ACK 8d930981e9
  l0rinc:
    code review ACK 8d930981e9
  sedited:
    ACK 8d930981e9
  janb84:
    ACK 8d930981e9

Tree-SHA512: 3ed1d264953f08272c115d760e8149c5985d63331404ac3b1017a277c4b3a61862915851fe45746e26ed46fe7478f851680d205e5ef83e727d061f2867fed99c
2026-08-31 19:57:03 +02:00
merge-script
58dfcf29f6 Merge bitcoin/bitcoin#35351: net: Disallow invalid HeadersSyncState due to lagging clock
ff3e2e4ebd net: Trigger process abort when behind start block MTP (Hodlinator)
1883cecb4d test: Characterize lagging-clock headers presync (Hodlinator)

Pull request description:

  ### Problem

  Headers presync computes `m_max_commitments` from the elapsed time since the chain-start MTP plus `MAX_FUTURE_BLOCK_TIME`. When the local system clock is more than `MAX_FUTURE_BLOCK_TIME` behind the chain-start MTP, that elapsed value is negative, but it is used in arithmetic assigned to the unsigned commitment cap. This can turn the intended zero bound into a large cap, letting low-work headers presync continue instead of aborting when a reasonable commitment cap would have been exceeded.

  ### Fix

  Instead of allowing an invalid `HeadersSyncState` object to be created, emit an error and **abort the node process**.

  Typically, the node will detect that the system clock is set too far in the past when comparing it to the chain tip during chain state loading and shut down before we start syncing headers. So in practice this is very unlikely to make a difference (might be possible if the system clock jumps backwards after we loaded the chain state).

  #### Commits

  * Add functional and unit characterization tests [pinning the current behavior](https://github.com/bitcoin/bitcoin/pull/35260).
  * The fix, along with corresponding test changes.

  ---

  Replaces #35208 which was clamping `m_max_commitments` to zero and then letting the `HeadersSyncState` consume headers until the block height either reached the the next `commitment_period` point and aborted, or reached the minimum work threshold and succeeded (possible when having been offline for >144 blocks).

ACKs for top commit:
  l0rinc:
    diff and code review ACK ff3e2e4ebd
  sedited:
    ACK ff3e2e4ebd
  mzumsande:
    Code Review ACK [ff3e2e4](ff3e2e4ebd)

Tree-SHA512: bdd82fd0609309aa4bea026db1b607ae856c53403ec01b2511fa2ccae9db4ff1bb9e39523b446583c09ae53823275b8a603050d9090b61fabb84fab35e458f28
2026-08-31 18:35:19 +02:00
merge-script
c0ed327845 Merge bitcoin/bitcoin#36103: validation: remove unused code
15630c7b85 validation: remove unused m_chainparams from ATMPArgs (fanquake)
84c5290149 validation: remove unused args from PolicyScriptChecks (fanquake)
a9d5cf7f99 validation: remove unused args from ConsensusScriptChecks (fanquake)
d26dc09ee3 validation: remove unused total_vsize arg from PackageRBFChecks (fanquake)
2cb6c156e1 validation: remove unused PackageMempoolAcceptResult constructor (fanquake)

Pull request description:

  Remove some unused code from validation.

ACKs for top commit:
  thomasbuilds:
    ACK 15630c7
  sedited:
    ACK 15630c7b85
  yuvicc:
    ACK 15630c7b85
  hebasto:
    ACK 15630c7b85, completeness of removing unused parameters in the `validation` module verified by overriding the `-Wunused-parameter` compiler flag for `src/validation.cpp`.
  jeanpablojp:
    tACK 15630c7b85

Tree-SHA512: a01ff6ea758132d6ad4c163d51c36d9e2cfaf91e90ca6451323591341fefec23c875af26e0b66e6cdba87ae6cab1418048c8788361d9c62fb8e0400d4dcaeac7
2026-08-31 18:22:50 +02:00
sedited
78e691ea10 rpc: Change listunspent's ancestorfees type to NUM
This seems to be the only place where a STR_AMOUNT is used for a sats
denominated fee amount. Many other places use the raw NUM type for a fee
amount, for example getblockstats and getblocktemplate. This doesn't
change the actual result of the RPC call.

The change is motivated by OpenRPC, where the field was previously given
a 'x-bitcoin-unit' tag. This usually describes a decimal amount, and may
be confusing for consumers applying this tag.
2026-08-31 17:12:59 +02:00
sedited
73fb9ced56 rpc: Fix private key type in signrawtransactionwithkey
It is base58, so shouldn't be qualified with STR_HEX. Similarly,
signmessagewithprivkey also declares the argument as a STR.

This fix is motivated by the OpenRPC dump, where fields tagged with STR_HEX are
described with a restricting regex that would make its correct usage a
violation against the unpatched schema.
2026-08-31 17:12:40 +02:00
merge-script
128e5c6805 Merge bitcoin/bitcoin#35477: test: exercise Schnorr signature cache in txvalidationcache_tests.cpp
3ba1bbfa3f test: exercise Schnorr signature cache in txvalidationcache_tests.cpp (Sebastian Falbesoner)
198b36bc85 test: respect "TAPROOT requires WITNESS" rule in `ValidateCheckInputsForAllFlags` (Sebastian Falbesoner)
e78a2a0d00 test: refactor: simplify tx vin/vout creation in txvalidationcache_tests.cpp (Sebastian Falbesoner)

Pull request description:

  The Schnorr verification path of the signature cache is currently never hit in the unit tests, i.e. with the following patch they still pass:
  ```diff
  diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp
  index c6fcc8f8eb..87688c1049 100644
  --- a/src/script/sigcache.cpp
  +++ b/src/script/sigcache.cpp
  @@ -44,6 +44,7 @@ void SignatureCache::ComputeEntryECDSA(uint256& entry, const uint256& hash, cons

   void SignatureCache::ComputeEntrySchnorr(uint256& entry, const uint256& hash, std::span<const unsigned char> sig, const XOnlyPubKey& pubkey) const
   {
  +    assert(false);
       CSHA256 hasher = m_salted_hasher_schnorr;
       hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(sig.data(), sig.size()).Finalize(entry.begin());
   }
  ```
  This PR adds missing coverage for that by adding a Taproot key-path spend to `checkinputs_test` in `txvalidationcache_tests.cpp`. Same as for the already-existing ECDSA spends, the caching is tested across a large number of flag combinations (using `ValidateCheckInputsForAllFlags`), both with an invalid Schnorr signature (-> should only fail if `SCRIPT_VERIFY_TAPROOT` is set) and a valid one (-> should pass for all flag combinations).

ACKs for top commit:
  Bortlesboat:
    tACK 3ba1bbfa3f
  sedited:
    ACK 3ba1bbfa3f
  instagibbs:
    ACK 3ba1bbfa3f

Tree-SHA512: e43f7077d9e9ab6f8b5e9e70f0187767d65f686ce24350ce5d61cc4cdf07d5eebdf5e4327ce665c212b7cc02be1e8632a6a9fbcf6be2916f8e058993e5fb2650
2026-08-31 15:31:15 +02:00
jeanpablo
bbed824a64 wallet: remove unused warnings parameter from CreateFromDump
`CreateFromDump` never writes to the vector, so the loop that prints it
in wallet-tool cannot produce output. `tool_wallet.py` already asserts
empty output for `createfromdump`.

The only `warnings.push_back()` was removed in 7a41c939f0 ("wallet:
Remove -format and bdb from wallet tool's createfromdump").
2026-08-31 13:37:45 +01:00
jeanpablo
2f6aa41d3d wallet: remove unused WalletDatabase::m_refcount
The counter is never incremented. Only the BDB implementation ever
maintained it, and that went away in 04a7a7a28c ("build, wallet, doc:
Remove BDB"). `AddRef()` and `RemoveRef()`, which the comment above the
member describes as maintaining it, were removed in c0f3f3264f
("wallet: Remove unused db functions"), leaving the member behind.
2026-08-31 13:37:45 +01:00
jeanpablo
f64b3fa70f wallet: remove unused CHDChain keypool index members
`m_next_external_index` and `m_next_internal_index` are declared and
initialized and never read or written afterwards. Their last uses were
removed in 83af1a3cca ("wallet: Delete LegacySPKM"). Neither appears in
`SERIALIZE_METHODS` or in `SetNull`.
2026-08-31 13:37:45 +01:00
jeanpablo
4afc7bc40d wallet: remove unused COutput::ToString
No callers. It was used by `COutput::print()`, which was removed in
3802224110 ("Remove all other print() methods").
2026-08-31 13:37:45 +01:00
jeanpablo
a0e9aac428 wallet: remove unused DescriptorScriptPubKeyMan::AddDescriptorKey
The private method has no callers. It opened a `WalletBatch` and
forwarded to `AddDescriptorKeyWithDB`, which is still called from two
other places.

Its last caller, in `CWallet::AddWalletDescriptor`, was replaced in
aa4f7823aa ("wallet: include keys when constructing DescriptorSPKM
during import"), which builds the manager with `CreateFromMigration`
instead of adding the key afterwards.
2026-08-31 13:37:45 +01:00
merge-script
d2e24e951d Merge bitcoin/bitcoin#36054: test: add script_tests cases covering interpreter mutants
4a12773f26 test: cover DERSIG rejects a non-compound signature type (ViniciusCestarii)
86c7fb910d test: cover OP_16 does not count towards the opcode limit (ViniciusCestarii)
331bf79881 test: cover OP_WITHIN must pop all 3 elements (ViniciusCestarii)
3bb87bc61b test: cover OP_FROMALTSTACK must pop the altstack (ViniciusCestarii)

Pull request description:

  Kills some live mutants on interpreter.cpp that affect consensus found by https://bitcoincore.space. They are:

  <details>
  <summary><a href="https://bitcoincore.space/src/script/interpreter.cpp#3951">interpreter.cpp#3951</a>: <code>OP_FROMALTSTACK</code>: removed <code>popstack(altstack)</code></summary>

  ```diff
  diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
  index 98b16eca6b..68265d20b5 100644
  --- a/src/script/interpreter.cpp
  +++ b/src/script/interpreter.cpp
  @@ -698,7 +698,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
                       if (altstack.size() < 1)
                           return set_error(serror, SCRIPT_ERR_INVALID_ALTSTACK_OPERATION);
                       stack.push_back(altstacktop(-1));
  -                    popstack(altstack);
  +
                   }
                   break;
  ```

  </details>

  <details>
  <summary><a href="https://bitcoincore.space/src/script/interpreter.cpp#4084">interpreter.cpp#4084</a>: <code>OP_WITHIN</code>: removed one <code>popstack(stack)</code></summary>

  ```diff
  diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
  index 98b16eca6b..874cf5e1cf 100644
  --- a/src/script/interpreter.cpp
  +++ b/src/script/interpreter.cpp
  @@ -1018,7 +1018,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
                       CScriptNum bn2(stacktop(-2), fRequireMinimal);
                       CScriptNum bn3(stacktop(-1), fRequireMinimal);
                       bool fValue = (bn2 <= bn1 && bn1 < bn3);
  -                    popstack(stack);
  +
                       popstack(stack);
                       popstack(stack);
                       stack.push_back(fValue ? vchTrue : vchFalse);
  ```

  </details>

  <details>
  <summary><a href="https://bitcoincore.space/src/script/interpreter.cpp#3883">interpreter.cpp#3883</a>: opcode limit: <code>opcode > OP_16</code> → <code>opcode >= OP_16</code></summary>

  ```diff
  diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
  index 98b16eca6b..e985643606 100644
  --- a/src/script/interpreter.cpp
  +++ b/src/script/interpreter.cpp
  @@ -459,7 +459,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&

               if (sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0) {
                   // Note how OP_RESERVED does not count towards the opcode limit.
  -                if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT) {
  +                if (opcode >= OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT) {
                       return set_error(serror, SCRIPT_ERR_OP_COUNT);
                   }
               }
  ```

  </details>

  <details>
  <summary><a href="https://bitcoincore.space/src/script/interpreter.cpp#3808">interpreter.cpp#3808</a>: <code>IsValidSignatureEncoding</code>: compound type check returns <code>true</code></summary>

  ```diff
  diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
  index 98b16eca6b..b613a6ac19 100644
  --- a/src/script/interpreter.cpp
  +++ b/src/script/interpreter.cpp
  @@ -133,7 +133,7 @@ bool static IsValidSignatureEncoding(const std::vector<unsigned char> &sig) {
       if (sig.size() > 73) return false;

       // A signature is of type 0x30 (compound).
  -    if (sig[0] != 0x30) return false;
  +    if (sig[0] != 0x30) return true;

       // Make sure the length covers the entire signature.
       if (sig[1] != sig.size() - 3) return false;
  ```

  </details>

  Recommend reviewing per commit.

ACKs for top commit:
  instagibbs:
    ACK 4a12773f26
  brunoerg:
    ACK 4a12773f26
  jeanpablojp:
    tACK 4a12773f26

Tree-SHA512: 5f53c733d11cb5d645f420d90ab626f894ef0bb155d01b9de0cae502109b2eaa46c072797d08df115da7a8738f01f31212a207a4d0e6f782128beb37332cf46e
2026-08-31 10:01:42 +01:00
furszy
75f64e50c6 test: exercise node abort on UTXO deserialization failure
This ensures that UTXO unserialization errors abort the node, and does
not cause a consensus divergence.

A valid UTXO is created and shared between two nodes. The raw database
entry is then deliberately modified on one node so it can no longer be
deserialized. When the other node spends that UTXO and mines a block,
the node with the unserializable entry must abort during block connection
rather than silently treating the coin as absent and marking the block
BLOCK_FAILED_VALID, which would cause it to permanently diverge from the
network's best chain.
2026-08-29 10:59:21 -04:00
furszy
4652cd0d82 txdb: detect UTXO deserialization errors via CDBWrapper::TryRead()
If a UTXO entry on disk can't be deserialized, the node treats it
as if the coin doesn't exist. Any block that spends that coin is
permanently rejected as invalid (BLOCK_FAILED_VALID), silently
forking the node from the rest of the network. This can hardly be
triggered in practice (details below), but it's still the wrong
behavior that could affect us in the future.

The root cause is that CDBWrapper::Read() returns false for both
missing keys and deserialization failures, so the consensus
class CCoinsViewDB::GetCoin() has no way to tell them apart.
CCoinsViewErrorCatcher was built to catch database read errors
and abort, but it never fires because CDBWrapper::Read() swallows
the exception before it can propagate.

In practice, this scenario isn't a latent risk at the moment. It
requires either a bug in the coin serialization path, or memory
corruption before the data reaches LevelDB (at which point we have
bigger problems). Any random disk-level bit flips are caught earlier
by LevelDB's verification (the verify_checksums=true option enabled
by default), which surfaces as a DatabaseError rather than a
deserialization failure.

This commit switches CCoinsViewDB::GetCoin() to use
CDBWrapper::TryRead(), which lets the caller discriminate between
all possible outcomes. On deserialization error, the exception now
propagates through CCoinsViewErrorCatcher to ExecuteBackedWrapper(),
which invokes the shutdown callbacks and aborts the node accordantly.

This also fixes PeekCoin(), which delegates to GetCoin() at the
CCoinsViewDB level.
2026-08-29 10:59:21 -04:00
furszy
5dfbb91b6c dbwrapper: add TryRead() to distinguish errors from valid outcomes
Read() returns false for both a missing key and a deserialization
failure, making it impossible for callers to distinguish between
them.

This commits adds TryRead() returning a ReadStatus struct that
discriminates between:

- true:                  record found, value deserialized
- false:                 record not found
- DatabaseError:         levelDB threw during record read
- DeserializationError:  key present, value incompatible with
                         expected format

An err_msg field preserves the original exception message for
diagnostic purposes.

This also makes Read() a thin wrapper over TryRead() to keep
existing call sites unchanged.

Note:
Key serialization is the only operation that may throw in
TryRead(), as callers are expected to provide well-formed keys.
This is why this function is not noexcept.
2026-08-29 10:59:12 -04:00
merge-script
ca7162cde5 Merge bitcoin/bitcoin#35868: rpc, wallet: fix invalid JSON in HelpExampleRpc curl examples
21d4e0ba75 rpc, wallet, test: fix invalid JSON in HelpExampleRpc curl examples (GuTS805)

Pull request description:

  Several `HelpExampleRpc` call sites reused CLI-style argument strings
  verbatim instead of valid JSON — missing commas, bare unquoted words, or
  single backslashes that are not valid JSON escapes. As a result the
  documented `curl` command for 14 RPCs (`getblockfrompeer`, `addnode`,
  `addconnection`, `sendmsgtopeer`, `restorewallet`, `getmempoolcluster`,
  `importmempool`, `getindexinfo`, `listlabels`, `unloadwallet`,
  `createwalletdescriptor`, `addhdkey`, `loadwallet`, `listunspent`) fails
  to parse as JSON if copy-pasted as-is. Also fixes a stray trailing quote
  in the `restorewallet` named-argument examples.

  This was previously raised in #31275, which sipa confirmed at runtime by
  adding a `UniValue::read` check, but that PR was closed unmerged. Since
  then two more examples broke the same way (`getmempoolcluster`,
  `addhdkey`), which is why this adds a permanent regression check to
  `rpc_help.py::dump_help()` instead of just fixing the current list.

  Fixes #35864.

ACKs for top commit:
  maflcko:
    review ACK 21d4e0ba75 🚝
  sedited:
    ACK 21d4e0ba75

Tree-SHA512: 2a8abc07d681b9dc81b8079a68421278da890049cea33a1561a48d53cbf919a30df588f559e9df94fa4a1ab7027f742f3b12c163afc25246a620340cb3522336
2026-08-29 10:33:22 +02:00
merge-script
d0e777baf5 Merge bitcoin/bitcoin#36111: rpc: bound memory for overlong Bech32 errors
7fcaccd9d0 bech32: bound overlength error locations (Lőrinc)

Pull request description:

  **Problem:** `validateaddress` reports likely error positions for invalid Bech32 inputs, including multiple useful positions for character and checksum errors.
  For an overlength input, `LocateErrors()` returns every position after the 90-character limit, which the RPC converts to a `UniValue` number before serializing the response.
  A near-limit authenticated request therefore creates about 33 million `int` values and 33 million `UniValue` objects.

  **Fix:** Return position 90 for an overlength input, which identifies where the single length violation begins.
  Character and checksum errors continue to return multiple useful positions when they can be determined.
  The tests now include an oversized example and pin the bounded result.

  **Reproducer:** Peak memory usage for a near-limit authenticated request:

  <details>
  <summary>Linux reproducer</summary>

  ```bash
  sed -i "/def test_validateaddress(self):/a\\
          self.nodes[0].validateaddress('bcrt1' + 'q' * (2**25 - 100))\\
          __import__('time').sleep(30)" test/functional/rpc_invalid_address_message.py
  cmake -B build && cmake --build build -j2
  build/test/functional/rpc_invalid_address_message.py >/dev/null 2>&1 &
  sleep 20 && awk '/VmHWM/' /proc/$(pgrep bitcoind)/status
  ```
  </details>

  ```text
  Before ████████████████████████ 5.69 GiB
  After  █░░░░░░░░░░░░░░░░░░░░░░░  240 MiB
  ```

ACKs for top commit:
  maflcko:
    lgtm ACK 7fcaccd9d0
  sedited:
    ACK 7fcaccd9d0
  janb84:
    ACK 7fcaccd9d0

Tree-SHA512: 3d439774d394f081b8107f8131963f7aa23ed048b0d6d349a80f9b3481fefeef7b5ce239fbd33606ad1f4960e6bfd899f968c50febc70d38b2fe731c6049583f
2026-08-29 10:20:42 +02:00
MarcoFalke
fa3971011d ci: Exclude subtrees from iwyu 2026-08-28 15:45:03 +02:00
MarcoFalke
fa8566152a refactor: Bump old copyright header in univalue
Noted in the last iwyu PR: https://github.com/bitcoin/bitcoin/pull/35900#pullrequestreview-5040554983
2026-08-28 15:44:13 +02:00
Hennadii Stepanov
05e49b342f Merge bitcoin/bitcoin#36107: iwyu: Fix warnings in src/init and treat them as errors
1ad8641278 iwyu: Fix warnings in `src/init` and treat them as errors (Hennadii Stepanov)

Pull request description:

  This PR continues the ongoing effort to enforce IWYU warnings.

  See [Developer Notes](https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#using-iwyu).

ACKs for top commit:
  maflcko:
    lgtm ACK 1ad8641278

Tree-SHA512: d63d2f5aeac487f01012b8802aff32eb53a8b5d53b8a6c8ece2a40b8c9603402f4f9a20c0918b3007ffaee1ed38a1009698e7b80be29c6a5175517e3279db952
2026-08-28 12:47:04 +01:00
Sjors Provoost
1fca81960a psbt: fix rendering for invalid long sighash type field
The PSBT sighash type field is a 32 bit unsigned integer in BIP 174,
signed in PSBTInput, and it is not validated when deserialized.

decodepsbt incorrectly truncates this field before looking up its
name. Fix that and add a test.
2026-08-28 12:39:04 +02:00
Lőrinc
7fcaccd9d0 bech32: bound overlength error locations
`LocateErrors()` returns multiple useful positions for character and checksum errors, but an overlength string has one structural error.
Every character from the limit onward is outside the permitted address, so listing each position adds no diagnostic value.
`validateaddress` converts every returned position into a `UniValue` number before serializing the response.
An authenticated request below the HTTP body limit can therefore require several gigabytes of memory.

Return only the first position beyond the length limit, which identifies where the violation begins.
Character and checksum errors continue to report multiple useful positions when they can be determined, and the existing unit and functional tests cover both behaviors.
2026-08-27 23:49:18 -05:00
Hennadii Stepanov
ea7d459ac0 Merge bitcoin/bitcoin#36057: build: check for SetThreadDescription() at configure time
bed46bd16c build: check for SetThreadDescription() at configure time (ViniciusCestarii)

Pull request description:

  SetThreadDescription() is missing from mingw-w64 headers before 12.0.0, so the Windows cross-compile fails on distro toolchains, e.g. Ubuntu 24.04. Reported by hebasto in https://github.com/bitcoin/bitcoin/pull/35884#issuecomment-5379490348.

  Check for the symbol at configure time and guard its use with a new `HAVE_SETTHREADDESCRIPTION` guard, as cmake/introspection.cmake already does for other optional symbols. This avoids having to declare a minimum mingw-w64 version: toolchains that have the symbol get OS-level thread names, older ones build fine without them.

ACKs for top commit:
  fanquake:
    utACK bed46bd16c - could be reverted + docs updated post branch-off.
  hebasto:
    re-ACK bed46bd16c.

Tree-SHA512: 3edbbd252fc68e976d930a8a6124746b3ba586ea58dc0720a67f8975e935057e2838bb7484d6b789771a327d2b69a092d64f335dd483f90b84a3ef290c138bfb
2026-08-27 23:11:24 +01:00
Hennadii Stepanov
1ad8641278 iwyu: Fix warnings in src/init and treat them as errors 2026-08-27 20:23:24 +01:00
GuTS805
21d4e0ba75 rpc, wallet, test: fix invalid JSON in HelpExampleRpc curl examples
Several HelpExampleRpc call sites reused CLI-style argument strings
verbatim (missing commas, bare unquoted words, or single backslashes
that are not valid JSON escapes), producing curl examples that fail
JSON parsing as documented. Also fixes a stray trailing quote in the
restorewallet named-argument examples, a missing comma in the
listunspent example, and a wrong-schema string-instead-of-array
listunspent argument caught in review.

Lines touched are converted to raw string literals (or strprintf with a
raw string template) throughout, for consistency and to avoid manual
quote/backslash escaping.

Adds a regression check to rpc_help.py::dump_help() so this class of
bug can't silently reappear.
2026-08-27 22:34:18 +05:30
fanquake
15630c7b85 validation: remove unused m_chainparams from ATMPArgs 2026-08-27 18:00:54 +01:00
MarcoFalke
fa7be0a8df test: refactor: Remove confusing ignore_errors=True 2026-08-27 17:37:01 +02:00
fanquake
84c5290149 validation: remove unused args from PolicyScriptChecks 2026-08-27 15:47:12 +01:00
fanquake
a9d5cf7f99 validation: remove unused args from ConsensusScriptChecks 2026-08-27 15:47:12 +01:00
fanquake
d26dc09ee3 validation: remove unused total_vsize arg from PackageRBFChecks 2026-08-27 15:47:12 +01:00
fanquake
2cb6c156e1 validation: remove unused PackageMempoolAcceptResult constructor 2026-08-27 15:47:12 +01:00
Hodlinator
8d930981e9 refactor: Replace !ContainsNoNUL() with ContainsNUL()
Avoids frequent double negation. See also fa7078d84f when it was renamed from the previous name, "ValidAsCString()".
2026-08-27 16:43:42 +02:00