wallet: add BIP39 mnemonic support to addhdkey #35857

pull mateusz-klatt wants to merge 4 commits into bitcoin:master from mateusz-klatt:wallet-bip39-import changing 11 files +2832 −4
  1. mateusz-klatt commented at 8:34 PM on July 31, 2026: none

    Allows addhdkey to derive and import a BIP 32 master key from an English BIP 39 mnemonic and an optional ASCII passphrase.

    Only the derived key is stored. Creating active descriptors and rescanning remain explicit steps.

    Motivation

    • Enable recovery and import workflows for an existing wallet from a mnemonic without first converting the seed phrase to an xprv using an external tool.
    • Reduce exposure of the mnemonic to additional software.

    Changes

    • Allow addhdkey to accept a mnemonic as an alternative to hdkey, together with an optional bip39_passphrase.
    • Support the English word list and ASCII-only passphrases.
    • Validate the word count, word-list membership, and checksum.
    • Store only the derived HD key in the wallet.
    • Do not create active descriptors or initiate a blockchain rescan.

    Tests

    The following tests were run locally on the PR head (RelWithDebInfo build with -DBUILD_GUI=ON -DWITH_ZMQ=ON -DWITH_USDT=ON):

    • Unit tests: full CTest suite (ctest --test-dir build -j16) — 372/372 passed, 0 failed. script_assets_tests was skipped as it requires an external asset file. Includes the new src/wallet/test/bip39_tests.cpp (build/bin/test_bitcoin --run_test=bip39_tests).
    • Functional tests: full suite (build/test/functional/test_runner.py -j12) — 280 passed, 0 failed, 16 skipped for environment reasons (USDT tests need root/BPF, backwards-compatibility tests need previous-release binaries, IPC mining needs a multiprocess build). Includes test/functional/wallet_hd.py.
    • Fuzz targets: bip39 and bip39_valid in src/wallet/test/fuzz/bip39.cpp, built with -DBUILD_FUZZ_BINARY=ON -DBUILD_FOR_FUZZING=ON and run against seed inputs (official test vectors, unknown words, empty input, random bytes).
  2. DrahtBot added the label Wallet on Jul 31, 2026
  3. DrahtBot commented at 8:34 PM on July 31, 2026: 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/35857.

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

    • #35868 (rpc, wallet: fix invalid JSON in HelpExampleRpc curl examples by GuTS805)
    • #35436 (wallet: Add addHDkey interface by pseudoramdom)

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

  4. DrahtBot added the label CI failed on Aug 5, 2026
  5. DrahtBot commented at 11:56 PM on August 5, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task riscv32 bare metal, static libbitcoin_consensus: https://github.com/bitcoin/bitcoin/actions/runs/30664847895/job/92449812346</sub> <sub>LLM reason (✨ experimental): CI failed because the Docker base install step couldn’t clone the binutils-gdb submodule from sourceware.org due to an HTTP 429 (rate limit) error.</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. mateusz-klatt commented at 6:51 AM on August 6, 2026: none

    CI failure is an infra flake: the ci_native_riscv_bare image build hits HTTP 429 from sourceware.org while cloning GCC submodules (binutils-gdb, newlib-cygwin) in 01_base_install.sh, even after the built-in retry.

  7. wallet: add BIP 39 mnemonic decoder
    Implement validation for English-wordlist BIP 39 mnemonics and derive
    the corresponding BIP 32 master key with PBKDF2-HMAC-SHA512.
    Restrict passphrases to ASCII so normalization is unambiguous without
    adding a Unicode dependency, and cleanse intermediate secret buffers.
    
    Validate the decoder against official vectors, every supported word
    count, checksum failures, whitespace normalization, and passphrase
    edge cases.
    4702e627c2
  8. wallet: support BIP 39 mnemonics in addhdkey
    Allow addhdkey to derive a BIP 32 master key from an English BIP 39
    mnemonic and an optional ASCII passphrase. Keep the random and xprv
    flows unchanged, and store only the derived key through the unused
    descriptor.
    
    Document the import-only recovery flow and passphrase behavior. Add
    functional coverage for argument validation, encrypted wallets,
    descriptor creation, and recovery of a transaction that predates the
    wallet import.
    3f7ce9e1b7
  9. test: add BIP 39 mnemonic fuzz targets
    Exercise arbitrary uncapped mnemonic inputs in a fast parser target.
    Add a structured target that constructs valid mnemonics at every
    supported word count, varies ASCII whitespace and passphrases, and
    reaches checksum validation, PBKDF2, and BIP 32 derivation.
    c1360747e5
  10. doc: add BIP 39 entry and release note f64ecf6f06
  11. mateusz-klatt requested review from Copilot on Aug 6, 2026
  12. mateusz-klatt force-pushed on Aug 6, 2026
  13. ?
    copilot_work_started mateusz-klatt
  14. Copilot commented at 7:04 AM on August 6, 2026: none

    Pull request overview

    This PR extends the wallet RPC addhdkey to optionally derive and import a BIP32 master key from an English BIP39 mnemonic plus optional ASCII passphrase, while ensuring only the derived HD key is stored (not the mnemonic/passphrase) and leaving descriptor creation and rescanning as explicit follow-up steps.

    Changes:

    • Added BIP39 mnemonic + optional ASCII passphrase support to addhdkey, including validation and clear RPC help/error messaging.
    • Introduced a new wallet::bip39::DecodeMnemonic() implementation (English wordlist, checksum validation, PBKDF2-HMAC-SHA512 seed derivation) and integrated it into wallet builds.
    • Added functional, unit, and fuzz tests covering valid vectors, invalid inputs, whitespace normalization, and passphrase ASCII restrictions.

    Reviewed changes

    Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

    <details> <summary>Show a summary per file</summary>

    File Description
    test/functional/wallet_hd.py Adds functional coverage for addhdkey mnemonic/passphrase paths, encrypted-wallet behavior, and descriptor-based recovery flow.
    src/wallet/test/fuzz/CMakeLists.txt Registers new BIP39 fuzz target.
    src/wallet/test/fuzz/bip39.cpp Adds fuzz coverage for arbitrary and structured-valid mnemonics (plus passphrase handling).
    src/wallet/test/CMakeLists.txt Registers new BIP39 unit test file in the wallet test binary.
    src/wallet/test/bip39_tests.cpp Adds BIP39 unit tests using official vectors plus additional validation/error-path coverage.
    src/wallet/rpc/wallet.cpp Extends addhdkey RPC args/help and implements mnemonic/passphrase decoding and validation-to-RPC error mapping.
    src/wallet/CMakeLists.txt Adds bip39.cpp to the wallet library build.
    src/wallet/bip39.h Declares DecodeMnemonic() and the error enum.
    src/wallet/bip39.cpp Implements English-wordlist mnemonic decoding, checksum validation, and seed/master-key derivation.
    doc/release-notes-35857.md Adds release-note entry describing new addhdkey mnemonic/passphrase support and operational guidance.
    doc/bips.md Documents partial BIP39 support scope via addhdkey.

    </details>


    💡 <a href="/bitcoin/bitcoin/new/master?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.

  15. maflcko commented at 7:55 AM on August 6, 2026: member

    This pull request violates the https://github.com/bitcoin/bitcoin/blob/master/doc/AI_POLICY.md and does not take #32115 into account.

    Closing for now, but a new pull can be opened. At a minimum:

    • It needs to follow the AI policy
    • It needs to explain the context in light of #32115, #19151, ...
  16. maflcko closed this on Aug 6, 2026

  17. Zeegaths commented at 12:22 PM on August 11, 2026: none

    I know this is closed, but I was already testing it, so I thought to include it anyway:

    Tested ACK

    • Happy path - valid mnemonics return xpub; mistyped passphrases silently produce different keys
    • Correct error handling with non-English words and white spaces, wrong-size mnemonics, hdkey + mnemonic and bip39_passphrase without mnemonic rejected
    • 8 test cases passing
    • Checked debug.log after running the steps above and found no leakage of mnemonic or passphrase.

    I think issue #32115 was closed for introducing Rust to /share, and this is a good attempt at implementing it properly The importdescriptors issue, however, seems to be out of scope for this PR, as it separates the mnemonic storage from descriptor creation and rescanning. Users have to call createwalletdescriptor explicitly. The ambiguity issue in import descriptors could use more documentation or wrappers, but as far as this PR is concerned, it is a separate issue

    I'm wondering if there are any plans to reopen this so I can maybe make more comparisons with the Rust tool implementation.


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-08-21 17:51 UTC

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