#33043 [POC] wallet: Enable non-electronic (paper-based) wallet backup with codex32

ReviewabilityReviewsAgreementSize
#33043 w0xlt [POC] wallet: Enable non-electronic (paper-based) wallet backup with codex32Waiting on author0Mild965 + 472 tests
  • Enable physical, human-verifiable paper backups and recovery for wallets using codex32 encoding
  • Allow descriptor wallets to retain seed material instead of requiring raw databases or long descriptors
  • Waiting on author to answer open objections from Sjors and BenWestgate
  • Needs rebase
  • No review verdicts recorded
  • Concept support because paper backups are a standard feature missing since legacy wallet removal (rkrux)
  • Unaddressed objection: bypasses descriptor backups and fragments key import logic away from addhdkey (Sjors)
  • Unaddressed objection: lacks wallet birth timestamps for rescanning and descriptor associations (BenWestgate)
  • 965 lines added or modified outside tests
  • 472 lines added or modified in tests
  • 46 lines removed in total
  • 31 files, 5 commits
Wallet#59 of 92
P3 · new feature
  • P3 after comparing with the other PRs here (assessed alone as P2): Lowered from P2: an explicit proof of concept seeking feedback on whether Core should store seeds at all; value is speculative until that is settled.
  • P2 because it fills a key feature gap by enabling paper-based backup and recovery for descriptor wallets
  • Provides human-verifiable recovery without relying on raw database files or full descriptor strings
Reviewability: ReadyStalePaused
Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets
Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs.
Size: lines added or modified outside tests, then in tests; greener = smaller.

Goal

This pull request adds support for persisting wallet seeds and introduces codex32 (BIP 93) encoding to enable paper-based backup and recovery. It ports the codex32 implementation from Core Lightning into C++ and adds two new RPCs: exposesecret to export seeds in codex32 format, and recoverwalletfromseed to restore a wallet from a codex32 string.

Problem: Bitcoin Core descriptor wallets do not retain the original seed material after generating descriptors, preventing users from backing up or restoring wallets using physical, human-verifiable paper backups like codex32 without retaining raw database files or long descriptor strings.

Evidence of importance:

  • The author states in the PR description: 'Because Bitcoin Core wallets currently do not store the seed material by default, this PR adds support for doing so, along with a new wallet flag to explicitly indicate when this feature is enabled.'
  • Author notes the POC status: 'This PR is intended as a proposal for feedback—to assess whether this functionality is desirable, and to explore how it might evolve further.'

Scope: Includes a port of external code (codex32.{c,h} from Core Lightning) adapted into C++ (wallet/codex32.cpp and tests). It also introduces new persistent wallet database keys (WALLETSEEDKEY and WALLETSEEDCKEY) and a new wallet flag WALLET_FLAG_SEEDS_STORED.

Reviewability

Paused · Waiting on author

Open objections from BenWestgate, Sjors with no author reply for 207 days; review would repeat what has been asked.

Agreement

Mild

objection that needs an answer has none yet (Sjors, BenWestgate)

Thread notes: Initial record for the POC PR. Reviewers support the concept of paper backups in principle, but open objections remain regarding the architecture: Sjors and BenWestgate noted that seed recovery without descriptors and birth timestamps is incomplete for modern descriptor wallets, and Sjors prefers integration via addhdkey.

Objections, suggestions, and questions:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
apoelstra (contributor)objection, safetya raw codex32 seed allows an attacker to sweep funds without needing the wallet passphraseanswered · v1, not yet re-checkedansweredyes2025-07-23: 'the seed is the seed -- once an attacker has it, it's game over. He doesn't need the passphrase or any other part of the wallet to sweep coins'
Status from: 2025-07-23: w0xlt: 'Yes, you're right. I thought the passphrase deterministically modified the seed to create the BIP 32 Extended Key, but that's not the case.'
Sjors (member)objection, approachbacking up raw keys in custom seed RPCs bypasses descriptor backups needed for complex wallets and fragments key import logic away from addhdkeyopen · v1, not yet re-checkedansweredno2025-07-25: 'It seems to me that codex32 only plays a role in (1). And so importing it should be done with `addhdkey`. Exporting could be done with `gethdkeys`.'
BenWestgate (contributor)objection, interfacerestoring solely from seed lacks wallet birth timestamps needed for efficient rescanning and lacks descriptor associationsopen · v1, not yet re-checkedansweredno2025-10-13: 'we need the timestamp no? Other approaches made the import/restore command require a corresponding descriptor to function and that seems more robust for existing wallets.'

Support:

  • rkrux (contributor) (Concept ACK, 2026-04-08): paper-based backups are a ubiquitous industry standard and timely now that legacy wallets are removed

Participants:

  • apoelstra (contributor, objection, 1 statements 2025-07-23 to 2025-07-23): pointed out that codex32 seeds are unencrypted and bypass wallet passphrases
  • Sjors (member, objection, 2 statements 2025-07-24 to 2025-07-25): argued key material import/export should use addhdkey/gethdkeys and must account for descriptors
  • BenWestgate (contributor, objection, 3 statements 2025-08-21 to 2025-10-13): pointed out missing timestamps for rescans and urged support for share sets and descriptors
  • rkrux (contributor, support, 1 statements 2026-04-08 to 2026-04-08): Concept ACK for introducing paper-based wallet backups

Files

484 lines under test/bench/ci.

  • src/wallet/codex32.cpp +420/-0
  • src/wallet/test/codex32_tests.cpp +366/-0
  • src/wallet/rpc/backup.cpp +263/-0
  • src/wallet/wallet.cpp +82/-15
  • test/functional/wallet_codex32.py +92/-0
  • src/wallet/walletdb.cpp +85/-0
  • src/wallet/codex32.h +63/-0
  • src/wallet/wallet.h +20/-7
  • src/bech32.cpp +5/-5
  • src/wallet/rpc/wallet.cpp +7/-1
  • src/bench/wallet_create_tx.cpp +2/-2
  • src/wallet/interfaces.cpp +2/-2
  • src/wallet/test/util.cpp +2/-2
  • src/wallet/walletdb.h +4/-0
  • test/functional/wallet_avoidreuse.py +2/-2
  • src/bech32.h +3/-0
  • src/rpc/client.cpp +3/-0
  • src/wallet/walletutil.h +3/-0
  • src/bench/wallet_balance.cpp +1/-1
  • src/bench/wallet_create.cpp +1/-1
  • src/interfaces/wallet.h +1/-1
  • src/qt/test/addressbooktests.cpp +1/-1
  • src/qt/test/wallettests.cpp +1/-1
  • src/qt/walletcontroller.cpp +1/-1
  • src/wallet/load.cpp +1/-1
  • src/wallet/test/coinselector_tests.cpp +1/-1
  • src/wallet/test/group_outputs_tests.cpp +1/-1
  • src/wallet/wallettool.cpp +1/-1
  • src/wallet/CMakeLists.txt +1/-0
  • src/wallet/test/CMakeLists.txt +1/-0
  • test/functional/test_runner.py +1/-0

Card

The short text the ranking pass compares across PRs.

This pull request adds the ability to back up and restore Bitcoin Core wallets using paper-based codex32 (BIP 93) seeds. Bitcoin Core descriptor wallets currently do not store seed material or provide paper backup workflows, forcing users to rely on electronic descriptor or file backups. The PR ports codex32 logic from Core Lightning, stores encrypted/plaintext seeds in the wallet database under a new wallet flag, and adds exposesecret and recoverwalletfromseed RPCs. The work is submitted as a proof of concept to gather feedback on seed storage in Core.

Data

dossier JSON · extract JSON · model ledger, generated 2026-09-18T03:48, confidence high, input hash 9aed4d547afc0f98
thread read through 2026-04-08 (10 statements), head 14f3342262
Discussion read under schema 1 rules: suggestions and questions may be missing, and an objection may combine several harms (schema history).
labels: Needs rebase · draft

Categories

Wallet

P3 · new feature (assessed alone as P2; Lowered from P2: an explicit proof of concept seeking feedback on whether Core should store seeds at all; value is speculative until that is settled.)

Addresses the inability of descriptor wallets to support standard human-verifiable paper backups without preserving raw databases or descriptor strings. As noted in the discussion, paper backups are an industry standard whose absence in descriptor wallets is a notable gap following legacy wallet removal.

Membership: Adds codex32 (BIP 93) seed persistence, database keys, and recovery RPCs across src/wallet/.

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