#36143 descriptor: add CreateMultisigDescriptor()

full analysis

https://github.com/bitcoin/bitcoin/pull/36143 · rxbryan · +203/-0 in 3 files, 2 commits · labels: Needs rebase, Descriptors · draft

Goal

  • Help wallet users assemble multisig descriptors safely from cosigner keys
  • Prevent setup mistakes from manual string formatting, duplicate keys, and invalid thresholds

Adds a new helper function `CreateMultisigDescriptor()` in `src/script/descriptor.cpp` to construct ranged multipath multisig descriptors from cosigner extended public keys. It enforces key origin requirements, checks against duplicate keys or existing derivation paths, supports SegWit (wsh) and Taproot (tr with sortedmulti_a), and verifies the resulting descriptor structure with unit tests.

Problem: Setting up multisig descriptor wallets currently requires manual string interpolation, risking user error with key origins, derivation paths, duplicate keys, or invalid thresholds.

Category: Wallet (#62 of 84)

P3 · new feature

  • P3 because safer multisig descriptor creation is a non-critical setup convenience
  • Reduces user errors when assembling descriptors across multiple signers
  • Provides non-essential foundation work for future multisig setup tooling

Multisig descriptor creation tooling helps prevent user errors when assembling descriptors from multiple signers. As noted in the description, 'multisig setup flows need to assemble a descriptor from collected cosigner keys without hand-crafting the descriptor string, which today means bash interpolation with no validation'. While valuable for the multisig wizard (#35645), this is a non-critical setup convenience that is reasonably deferrable.

Membership: Touches descriptor creation logic and validation in src/script/descriptor.cpp aimed at wallet multisig setup.

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

Reviewability: Stale: Needs rebase

  • Needs rebase due to merge conflicts against master
  • Author has been silent following a Concept NACK

The PR has merge conflicts against master and the author has been silent for 14 days following a Concept NACK.

Author status: silent since 2026-09-02 after reviewer confirmed preference for Python prototype first

Open concerns:

  • Sjors Concept NACKed adding an unused C++ helper without a caller, arguing that multisig setup should start with an external Python prototype before committing to C++ RPCs or helpers.

Agreement: Blocked

  • Concept NACK against adding an uncalled C++ helper without an end-to-end caller (Sjors)
  • Prefers prototyping the multisig setup flow in Python before committing to C++ (Sjors)
  • Unaddressed follow-up: author suggested exposing via RPC but has not responded further

Blocked: Concept NACK from Sjors against uncalled helper; author has not replied to follow-up

Sjors issued a Concept NACK stating that introducing an uncalled C++ descriptor helper is premature without an end-to-end consumer or prior Python prototyping. The author inquired about adding an RPC, Sjors reiterated preference for prototyping first, and the author has not responded.

  • Sjors: 'Concept NACK, unless this is part of a larger end-to-end implementation (with some buy-in)... A Python utility is more flexible...'
  • rxbryan: 'Would exposing this via an RPC in the same PR address the "nothing uses it" concern...'
  • Sjors: 'I think that's the better yes [referring to Python flow first]'

Review verdicts (DrahtBot): 0 -1

Dependencies

Enables:

Files

79 lines under test/bench/ci.

  • src/script/descriptor.cpp +111/-0
  • src/test/descriptor_tests.cpp +79/-0
  • src/script/descriptor.h +13/-0

Card

Adds CreateMultisigDescriptor to build and validate wsh and tr multisig descriptors from cosigner xpubs with strict origin checks. Solves the issue of manual and error-prone descriptor assembly for users setting up multisig wallets. Sjors Concept NACKed the change as premature without an end-to-end caller or prior Python workflow prototyping. The branch currently needs a rebase and has been inactive for two weeks following the discussion.

Data

dossier JSON · extract JSON · model openrouter/google/gemini-3.8-flash, generated 2026-09-17T16:23, confidence high, input hash af0b84240f5550ca