#35444 wallet: make descriptor SPKM mutex non-recursive

full analysis

https://github.com/bitcoin/bitcoin/pull/35444 · w0xlt · +506/-213 in 8 files, 4 commits · labels: Wallet

Goal

  • Prevent deadlocks and re-entrancy bugs by making descriptor script manager locking non-recursive
  • Clarify wallet lock hierarchies and safely dispatch callbacks outside of lock scope

This PR converts `DescriptorScriptPubKeyMan`'s internal mutex `cs_desc_man` from a public `RecursiveMutex` to a private `Mutex` (renamed to `m_desc_mutex`). It splits internal routines into lock-held helpers and self-locking public entry points, removes external locking from caller sites, and defers address-availability callbacks until locks are released.

Problem: Recursive and externally exposed mutexes obscure locking hierarchies, making wallet components susceptible to deadlocks and re-entrancy issues as concurrency patterns evolve.

Category: Wallet (#51 of 84)

P3 · cleanup

  • P3 because it is an internal concurrency cleanup that reduces deadlock risk without fixing an active bug
  • Helps unblock the broader project effort to eliminate recursive mutexes

P3 because this is an internal concurrency cleanup that reduces deadlock risks rather than fixing an active regression or user-reported bug. It contributes to the project-wide effort to eliminate RecursiveMutex instances (#19303) and ensures safe callback dispatch without locks held.

Membership: Touches descriptor ScriptPubKeyMan locking and wallet synchronization in src/wallet/.

Factors: security/stability 1, bug 0, performance 0, user value 0, leverage 1

Reviewability: Ready

  • Ready for review
  • Cleanly rebased with passing CI and no open blockers

The PR is rebased, mergeable, and passing CI with no open blocker.

Author status: active, recently rebased the branch

Resolved concerns:

  • pablomartin4btc questioned whether reading descriptor metadata and descriptor strings under separate locks in listdescriptors could introduce race conditions; w0xlt clarified that cs_wallet is held across both calls.

Agreement: Strong

  • Strong support for the locking approach and clear commit structure (pablomartin4btc)
  • Concept approval without stated reasons (hebasto)
  • Atomicity concern regarding listdescriptors was resolved by clarifying wallet locking (pablomartin4btc)

Strong: two Concept ACKs with positive review feedback; minor questions answered and addressed

Reviewers support the approach and commit breakdown; the one atomicity concern raised was satisfactorily explained.

  • pablomartin4btc: Concept ACK, praised the commit structure and internal helper separation, confirmed correctness.
  • hebasto: Concept ACK.
  • w0xlt addressed suggestions and rebased.

Review verdicts (DrahtBot): 0

Dependencies

Enables:

Files

119 lines under test/bench/ci.

  • src/wallet/scriptpubkeyman.cpp +317/-143
  • src/wallet/scriptpubkeyman.h +67/-52
  • src/wallet/test/scriptpubkeyman_tests.cpp +118/-0
  • src/wallet/external_signer_scriptpubkeyman.cpp +2/-9
  • src/wallet/wallet.cpp +2/-6
  • src/wallet/export.cpp +0/-1
  • src/wallet/rpc/wallet.cpp +0/-1
  • src/wallet/test/fuzz/scriptpubkeyman.cpp +0/-1

Card

This PR refactors DescriptorScriptPubKeyMan to make its mutex private and non-recursive, renaming it from cs_desc_man to m_desc_mutex. It internalizes locking inside public methods, replaces recursive call paths with lock-held helper functions, and defers address availability notifications outside critical sections to prevent re-entrancy deadlocks. The change advances the project-wide initiative to replace RecursiveMutex across the codebase (issue #19303). The PR has Concept ACKs from two reviewers, has resolved all review comments, and is cleanly rebased and ready for final review.

Data

dossier JSON · extract JSON · model openrouter/google/gemini-3.8-flash, generated 2026-09-17T15:53, confidence high, input hash fac33def9b88cb1f