wallet: support bip388 policy with external signer #33008

pull Sjors wants to merge 6 commits into bitcoin:master from Sjors:2025/07/bip388-register changing 15 files +422 −4
  1. Sjors commented at 3:31 PM on July 18, 2025: member

    External signers such as Ledger, BitBox02 and Jade, when used with multisig, use BIP388 to display (and constrain) descriptor policies to their users.

    At least in the case of Ledger (no others so far, see #33008 (comment)) this requires us to hold on to an hmac, which proves to the device that the user previously reviewed and approved it.

    This PR adds a new RPC call registerpolicy which converts our descriptor(s) into a BIP388 policy (partially implemented), calls a new HWI method register (implemented) and stores the resulting HMAC (implemented).

    When signing a transaction using HWI's signtx it passes the HMAC along with the PSBT (TODO).

    For convenience the HMAC can be retrieved via getwalletinfo (implemented). This is useful for scenario's where we can't (yet) complete a transaction via HWI calls.

    Note that the HMAC itself is not specified in BIP388 and may be different for different hardware vendors. So we'll store and echo any hex string the device gives us.

    An alternative approach to directly supporting BIP388 policies would be to pass the involved descriptors to HWI and have it figure out how to derive a policy.

    Testing:

    TODO:

    • derive policy using Descriptor class instead regex madness, implement all constraints
    • pass hmac along when signing

    Depends on:

    Potential followups:

  2. DrahtBot added the label Wallet on Jul 18, 2025
  3. DrahtBot commented at 3:31 PM on July 18, 2025: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33008.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process. A summary of reviews will appear here.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #bitcoin-core/gui/872 (Menu action to export a watchonly wallet by achow101)
    • #34681 (wallet: refactor ScanForWalletTransactions by Eunovo)
    • #34400 (wallet: parallel fast rescan (approx 5x speed up with 8 threads) by Eunovo)
    • #33034 (wallet: Store transactions in a separate sqlite table by achow101)
    • #32895 (wallet: Prepare for future upgrades by recording versions of last client to open and decrypt by achow101)
    • #32876 (refactor: use options struct for signing and PSBT operations by Sjors)
    • #32861 (Have createwalletdescriptor auto-detect an unused(KEY) by Sjors)
    • #32857 (wallet: allow skipping script paths by Sjors)
    • #32784 (wallet: derivehdkey RPC to get xpub at arbitrary path by Sjors)
    • #32489 (wallet: Add exportwatchonlywallet RPC to export a watchonly version of a wallet by achow101)
    • #29136 (wallet: addhdkey RPC to add just keys to wallets via new unused(KEY) descriptor by achow101)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

    LLM Linter (✨ experimental)

    Possible typos and grammar issues:

    • furth -> further [misspelled in // - apply furth BIP388 restrictions; it should be further]
    • swith -> switch [misspelled in // Replace keys in descriptor swith [@1](/bitcoin-bitcoin/contributor/1/), etc; it should be switch]
    • manangers -> managers [misspelled in Derive a BIP388 policy from a pair of descriptor scriptpubkey manangers.; it should be managers]

    Possible places where named args for integral literals may be used (e.g. func(x, /*named_arg=*/0) in C++, and func(x, named_arg=0) in Python):

    • util::ReplaceAll(descriptor_template, key_info, strprintf("@%d", key_index), false) in src/wallet/wallet.cpp
    • util::ReplaceAll(descriptor_template_check, key_info, strprintf("@%d", key_index), false) in src/wallet/wallet.cpp
    • util::ReplaceAll(descriptor_template, "/0/*", "/**", false) in src/wallet/wallet.cpp
    • util::ReplaceAll(descriptor_template_check, "/1/*", "/**", false) in src/wallet/wallet.cpp
    • util::ReplaceAll(key, "h/", "'/", false) in src/wallet/wallet.cpp
    • util::ReplaceAll(key, "h]", "']", false) in src/wallet/wallet.cpp

    <sup>2026-04-28 14:36:23</sup>

  4. DrahtBot added the label CI failed on Jul 18, 2025
  5. DrahtBot commented at 4:31 PM on July 18, 2025: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task previous releases, depends DEBUG: https://github.com/bitcoin/bitcoin/runs/46270694515</sub> <sub>LLM reason (✨ experimental): The CI failure is caused by a compilation error due to a redundant declaration of 'RPCHelpMan wallet::registerpolicy()' which is treated as an error because all warnings are enabled as errors.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  6. Sjors force-pushed on Jul 21, 2025
  7. Sjors force-pushed on Jul 21, 2025
  8. DrahtBot removed the label CI failed on Jul 21, 2025
  9. Sjors force-pushed on Jul 24, 2025
  10. Sjors force-pushed on Aug 5, 2025
  11. Sjors force-pushed on Aug 5, 2025
  12. DrahtBot added the label CI failed on Aug 5, 2025
  13. DrahtBot commented at 9:20 PM on August 5, 2025: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task tidy: https://github.com/bitcoin/bitcoin/runs/47448999684</sub> <sub>LLM reason (✨ experimental): The CI failure is due to an error flagged by clang-tidy in wallet.cpp at line 2621.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  14. Sjors force-pushed on Aug 6, 2025
  15. DrahtBot removed the label CI failed on Aug 6, 2025
  16. Sjors force-pushed on Aug 6, 2025
  17. Sjors force-pushed on Aug 6, 2025
  18. pythcoiner commented at 5:12 PM on August 7, 2025: contributor

    At least in the case of Ledger (haven't tested the others) this requires us to hold on to an hmac, which proves to the device that the user previously reviewed and approved it.

    In the range of devices supporting miniscript, only Ledger requires the software to store the Proof Of Registration, other devices stores it internally(SpecterDiy, BitBox, Coldcard, Jade) or not at all (Krux).

  19. DrahtBot added the label Needs rebase on Aug 12, 2025
  20. Sjors force-pushed on Aug 25, 2025
  21. Sjors commented at 12:16 PM on August 25, 2025: member

    @pythcoiner thanks, updated the description.

  22. DrahtBot removed the label Needs rebase on Aug 25, 2025
  23. Sjors force-pushed on Jan 5, 2026
  24. DrahtBot added the label Needs rebase on Jan 19, 2026
  25. Sjors force-pushed on Jan 22, 2026
  26. DrahtBot removed the label Needs rebase on Jan 22, 2026
  27. DrahtBot added the label CI failed on Jan 22, 2026
  28. DrahtBot commented at 10:58 AM on January 22, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task tidy: https://github.com/bitcoin/bitcoin/actions/runs/21242962354/job/61125116517</sub> <sub>LLM reason (✨ experimental): clang-tidy failure: parameter 'regex' is const-qualified in the ReplaceAll declaration, causing linting to fail.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  29. Sjors force-pushed on Jan 22, 2026
  30. DrahtBot removed the label CI failed on Jan 22, 2026
  31. wallet: add bip388_hmac record c247a8b327
  32. wallet: add RegisterPolicy to external signer 15a27d7b93
  33. wallet: add RegisterPolicy to signer SPKM f5b74cc9ca
  34. refactor: avoid std::regex in ReplaceAll fb05bb20d0
  35. wallet: add registerPolicy() c356a24dce
  36. rpc: add registerpolicy 4c64d7f6fe
  37. Sjors force-pushed on Apr 28, 2026
  38. Sjors force-pushed on Apr 28, 2026
  39. DrahtBot added the label CI failed on Apr 28, 2026
  40. DrahtBot removed the label CI failed on Apr 28, 2026
  41. Sjors commented at 9:23 AM on April 29, 2026: member

    I'm going to expand this to include address display (https://github.com/Sjors/bitcoin/pull/110), signing (https://github.com/Sjors/bitcoin/pull/111) and functional tests. That's a lot of fairly experimental code, so I'll open a PR on my own fork instead.

  42. Sjors closed this on Apr 29, 2026

Labels

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-05-03 21:12 UTC

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