descriptor: add CreateMultisigDescriptor() #36143

pull rxbryan wants to merge 2 commits into bitcoin:master from rxbryan:create-multisig-descriptor changing 3 files +201 −0
  1. rxbryan commented at 11:57 PM on September 1, 2026: none

    The 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 of key forms, duplicates, or threshold.

    CreateMultisigDescriptor() takes a threshold, a list of key expressions with origin info, and an output type, and returns a ranged, multipath wsh(sortedmulti(...)) descriptor with checksum.

    Part of the multisig wizard tracking issue #35645.

  2. DrahtBot added the label Descriptors on Sep 1, 2026
  3. DrahtBot commented at 11:57 PM on September 1, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    External sites

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    Concept NACK Sjors

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    No conflicts as of last run.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

    LLM Linter (✨ experimental)

    Possible typos and grammar issues:

    • complaint hardware wallets -> compliant hardware wallets [“complaint” is the wrong word here; “compliant” is clearly intended]

    <sup>2026-10-06 16:20:35</sup>

  4. Sjors commented at 11:44 AM on September 2, 2026: member

    Concept NACK, unless this is part of a larger end-to-end implementation (with some buy-in), like a GUI or RPC that actually uses this new method.

    But I also think that's premature. Wallet setup is a one-off thing, and it's not obvious what the best approach is. A Python utility is more flexible. A full c++ implementation is also likely to need a huge stack of commits, see e.g. https://github.com/Sjors/bitcoin/pull/91 which only implements spending from an existing multisig wallet.

    So I think the better sequence is:

    1.introduce a Python utility that helps the user construct and import a multisig descriptor 2. gradually improve / add RPC methods to simplify that utility and eventually make it unnecessary

    Step (2) is where changes like this may be useful.

  5. rxbryan commented at 11:23 PM on September 2, 2026: none

    So I think the better sequence is:

    1.introduce a Python utility that helps the user construct and import a multisig descriptor 2. gradually improve / add RPC methods to simplify that utility and eventually make it unnecessary

    That sequencing makes sense. Would exposing this via an RPC in the same PR address the "nothing uses it" concern, or do you specifically want the Python flow to exist first so the RPC surface is shaped by what that flow needs?

  6. Sjors commented at 6:27 AM on September 3, 2026: member

    Would exposing this via an RPC in the same PR address the "nothing uses it" concern

    Yes, but.

    do you specifically want the Python flow to exist first so the RPC surface is shaped by what that flow needs?

    I think that's the better yes.

  7. DrahtBot added the label Needs rebase on Sep 17, 2026
  8. rxbryan referenced this in commit 492260c9be on Sep 24, 2026
  9. rxbryan referenced this in commit 6feb6063bd on Sep 25, 2026
  10. rxbryan commented at 9:31 AM on September 26, 2026: none

    Following the Python wizard #36325, which exercises the actual setup flow, the contract for createMultisigDescriptor() is now concrete and has real consumers: the Python utility (#36325), the GUI, and potentially the createmultisig RPC.

    It becomes a function that constructs ranged, multipath descriptors for bech32 and bech32m, as well as the unranged plain-key case createmultisig builds today.

    This fits the multisig setup process better because the descriptor is built up front and becomes the source of truth, and bech32m falls out naturally. By contrast, createmultisig recovers its descriptor with InferDescriptor, which only sees the script: it always produces multi(...), since nothing in the script records that the keys were sorted, and its inputs are raw public keys, so there are no origins or ranges to express.

  11. rxbryan commented at 9:34 AM on September 26, 2026: none

    1.introduce a Python utility that helps the user construct and import a multisig descriptor 2. gradually improve / add RPC methods to simplify that utility and eventually make it unnecessary

    Step 1 is #36325. CreateMultisigDescriptor() would be the first change step 2 asks for.

  12. achow101 commented at 10:11 PM on September 29, 2026: member

    unless this is part of a larger end-to-end implementation (with some buy-in), like a GUI or RPC that actually uses this new method.

    In general it is, we want the GUI to be calling a utility function like this one to construct the descriptors for import.

    We already have a createmultisig RPC, and it should be modernized to produce descriptors.

    1.introduce a Python utility that helps the user construct and import a multisig descriptor

    I think this is entirely unnecessary. The RPC already exists, it should be modernized and refactored such that the GUI can use it too.

  13. rxbryan force-pushed on Oct 6, 2026
  14. rxbryan commented at 12:57 PM on October 6, 2026: none

    createmultisig can delegate to CreateMultisigDescriptor() for key expressions and bech32m, while keeping its existing contract for hex pubkeys unchanged. That gives the GUI and the RPC one assembly function.

  15. rxbryan force-pushed on Oct 6, 2026
  16. rxbryan marked this as ready for review on Oct 6, 2026
  17. DrahtBot removed the label Needs rebase on Oct 6, 2026
  18. descriptor: add CreateMultisigDescriptor()
    The 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 of key forms, duplicates, or
    threshold.
    
    CreateMultisigDescriptor() takes a threshold, a list of key expressions
    with origin info, and an output type, and returns a ranged, multipath
    wsh(sortedmulti(...)) descriptor with checksum.
    
    Parsing is done by the existing internal ParsePubkey(); the setup-specific
    policy is applied here on top of it. Private key, missing origin
    info, keys that already carry a derivation, and duplicate keys are all
    rejected. The /<0;1>/* suffix is appended internally, so callers supply
    bare account xpubs only.
    
    Covered by unit tests in descriptor_tests.cpp.
    
    Part of the multisig wizard backend tracked in #35645.
    d7e11d03d6
  19. descriptor: generate taproot multisig desc with musig2 keypath
    For taproot the key path is a MuSig2 aggregate of all n keys
    rather than a fixed or variable NUMS point: it cannot bypass the
    policy, since spending that way needs every signer, and it avoids
    the fingerprinting that a well-known internal key would cause.
    
    keys must be bare because derivation before aggregation cannot be
    expressed in a BIP 388 policy
    589f3fe6b5
  20. rxbryan force-pushed on Oct 6, 2026
  21. DrahtBot added the label CI failed on Oct 9, 2026
  22. DrahtBot removed the label CI failed on Oct 9, 2026

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-10-14 19:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me