wallet: Add exportaddresskey RPC for descriptor wallets #36697

pull jaromil wants to merge 7 commits into bitcoin:master from jaromil:wallet/exportaddresskey changing 22 files +3533 −0
  1. jaromil commented at 8:21 PM on October 29, 2026: contributor

    Adds exportaddresskey "address" ( "key_type" ) to export locally available private keys for an address in a descriptor wallet. Callers can obtain private keys without identifying the descriptor index and reproducing key derivation outside Core.

    The RPC has two modes:

    • wallet (default) returns the original wallet keys, with their public keys and roles.
    • taproot_output returns effective Taproot key-path keys using the known output commitment. Direct output keys are returned without another tweak. MuSig2 participant secrets are never combined into an aggregate private key.

    Supported constructions include single-key addresses, recognized P2SH/P2WSH scripts, multisig, Miniscript, and Taproot, including MuSig2 participants. A locally available key can be exported even when the wallet cannot satisfy all spending conditions.

    Lookup is limited to existing wallet metadata and known derivation indices. Encrypted wallets must be unlocked. Missing spending data, unavailable keys, and inconsistent wallet data have distinct errors.

    The result contains hexadecimal private scalars, not WIF. Exported keys are not a wallet backup; scripts, cosigners, or other spending data may still be needed. Reused keys and MuSig2 participants may control other outputs.

    Includes key, descriptor, wallet manager, wallet RPC, and console-history tests. Functional coverage reconstructs scripts independently and verifies spending with exported keys, partial ownership, authorization, inconsistent metadata, and absence of wallet or nonce mutation.

    The initial single-key implementation was ported from Bitcoin Roots and now extended to cover more use-cases. Initial motivation was the lack of dumppriv since v30 and the need for it in the making of the Quietproof client.

  2. DrahtBot added the label Wallet on Oct 29, 2026
  3. DrahtBot commented at 8:21 PM on October 29, 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. A summary of reviews will appear here.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #36641 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/36641.svg"></sub> (wallet: bound pending MuSig2 sessions by fametrano)
    • #36188 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/36188.svg"></sub> (crypto: plug hardware optimized SHA256 into libsecp256k1's context by furszy)
    • #36167 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/36167.svg"></sub> ([RFC] Enable -Wunused by fanquake)
    • #35918 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/35918.svg"></sub> (descriptor: Expose key expression parsing by pseudoramdom)
    • #35713 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/35713.svg"></sub> (Remove boost as a unit test runner by rustaceanrob)
    • #35444 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/35444.svg"></sub> (wallet: make descriptor SPKM mutex non-recursive by w0xlt)
    • #34520 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/34520.svg"></sub> (refactor: Add [[nodiscard]] to functions returning bool+mutable ref by maflcko)

    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 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):

    • src/test/key_tests.cpp: internal.Set(secret.begin(), secret.end(), true)
    • src/wallet/test/scriptpubkeyman_tests.cpp: even.Set(one.begin(), one.end(), true)
    • src/wallet/test/scriptpubkeyman_tests.cpp: odd.Set(minus_one.begin(), minus_one.end(), true)
    • src/wallet/test/scriptpubkeyman_tests.cpp: uncompressed.Set(one.begin(), one.end(), false)
    • src/wallet/test/scriptpubkeyman_tests.cpp: uncompressed.Set(complete->begin(), complete->end(), false)
    • src/wallet/test/scriptpubkeyman_tests.cpp: positive.Set(bytes.begin(), bytes.end(), true)
    • src/wallet/test/scriptpubkeyman_tests.cpp: opposite.Set(opposite_bytes.begin(), opposite_bytes.end(), false)
    • src/wallet/test/scriptpubkeyman_tests.cpp: participant.Set(one.begin(), one.end(), true)
    • src/wallet/test/scriptpubkeyman_tests.cpp: uncompressed.Set(one.begin(), one.end(), false)
    • src/wallet/test/scriptpubkeyman_tests.cpp: opposite.Set(minus_one.begin(), minus_one.end(), true)
    • src/wallet/test/scriptpubkeyman_tests.cpp: opposite_uncompressed.Set(minus_one.begin(), minus_one.end(), false)
    • test/functional/wallet_exportaddresskey.py: wallet.lockunspent(False, [{'txid': coins[0]['txid'], 'vout': coins[0]['vout']}], True)

    Possible places where comparison-specific test macros should replace generic comparisons:

    • test/functional/wallet_exportaddresskey.py: assert tweak < ORDER in derive_leaf → Prefer assert_greater_than(ORDER, tweak).
    • test/functional/wallet_exportaddresskey.py: assert tweak < ORDER in musig_public_key → Prefer assert_greater_than(ORDER, tweak).
    • test/functional/wallet_exportaddresskey.py: assert tweak < ORDER in taproot_output_secret → Prefer assert_greater_than(ORDER, tweak).

    <sup>2026-10-30 06:20:30</sup>

  4. jaromil marked this as a draft on Oct 29, 2026
  5. jaromil force-pushed on Oct 29, 2026
  6. DrahtBot added the label CI failed on Oct 29, 2026
  7. DrahtBot commented at 8:54 PM on October 29, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task test ancestor commits: https://github.com/bitcoin/bitcoin/actions/runs/40948337977/job/123709495885</sub> <sub>LLM reason (✨ experimental): CI failed during compilation: Clang’s thread-safety analysis rejected AssertLockHeld(wallet.cs_wallet) in scriptpubkeyman_tests.cpp because the wallet lock wasn’t held.</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>

  8. jaromil force-pushed on Oct 29, 2026
  9. jaromil force-pushed on Oct 29, 2026
  10. test: synchronize blocks in test_uncompressed_pubkey
    Wait for confirmation blocks to reach both nodes before building or testing their spends. Otherwise block relay can lag behind the test, causing missing-input or stale-tip failures.
    e6d9e8424f
  11. wallet: add exportaddresskey RPC
    Port address-specific private key export from Bitcoin Roots, adapting it to Core's RPCMethod API. Preserve wallet authorization, exact destination checks, console history filtering, and focused regression coverage.
    
    Source: fad94e12f7b830e820c9f722a8545bffc809f2d5 (Jaromil), with destination comparison fix 59185c317e.
    7778c8cbd5
  12. jaromil force-pushed on Oct 29, 2026
  13. wallet: structure address key export results a09a3cc568
  14. wallet: export keys for script-based addresses 10dc6e401c
  15. wallet: support Taproot address key export b43ea1716f
  16. wallet: verify address key export failure and security contracts f3b48dd891
  17. wallet: trim address key export includes 4f64a4d7ad
  18. jaromil force-pushed on Oct 30, 2026
  19. DrahtBot removed the label CI failed on Oct 30, 2026
  20. jaromil marked this as ready for review on Oct 30, 2026
Contributors
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-10-30 15:51 UTC

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