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

full analysis

https://github.com/bitcoin/bitcoin/pull/33043 · w0xlt · +1437/-46 in 31 files, 5 commits · labels: Needs rebase · draft

Goal

  • Enable non-electronic paper backup and recovery for wallets using codex32
  • Help users back up and restore wallets without needing to manage raw descriptor strings

This proof-of-concept PR ports the codex32 implementation from Core Lightning to C++ and adds support for non-electronic (paper-based) wallet backups. It persists master seeds in the wallet database, introduces a new WALLET_FLAG_SEEDS_STORED flag, and exposes exposesecret and recoverwalletfromseed RPCs.

Problem: Bitcoin Core descriptor wallets do not retain or export an overarching seed or paper backup phrase, making non-electronic seed backup and recovery difficult for users who do not want to manage raw descriptor strings.

Category: Wallet (#67 of 84)

P3 · new feature

  • P3 because it fulfills an enduring user request for non-electronic paper backups
  • Backing up raw seeds without descriptor metadata or timestamps offers incomplete wallet recovery

Enables non-electronic paper backups for wallets using the BIP 93 codex32 format, addressing an enduring user request. However, raw seed recovery without descriptor metadata or timestamps offers incomplete wallet recovery, keeping this in the worthwhile exploratory tier.

Membership: Touches wallet database structures, wallet flags, descriptor setup, and adds wallet backup/recovery RPCs.

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

Reviewability: Stale: Needs rebase

  • Draft proof of concept needs a rebase and has been inactive for over a year

The PR has merge conflicts across 8 open PRs, is marked as a draft POC, and has seen no author activity in over 400 days.

Author status: silent since 2025-07-24

Open concerns:

  • apoelstra noted that codex32 has no notion of passphrases or encryption, correcting the author's assumption that an encrypted wallet's passphrase protects exported seeds from an attacker.
  • Sjors noted that paper backups must account for output descriptors and timestamps, arguing key material import should go through addhdkey (#32652) rather than creating custom seed-recovery wallet flows.
  • BenWestgate pointed out that seed recovery requires wallet birthtime timestamps and suggested supporting codex32 Shamir shares rather than only bare secrets.

Resolved concerns:

  • Author acknowledged that passphrases do not deterministically protect BIP32 master keys in the way originally assumed.

Agreement: Mild

  • Concept approval for the broad idea of paper backups (rkrux)
  • Unaddressed objection: backing up keys without descriptors or timestamps is insufficient (Sjors)
  • Warning that exported seeds bypass wallet encryption and grant full spending access (apoelstra)
  • Suggested requiring wallet birth timestamps and supporting Shamir shares (BenWestgate)

General concept support for paper backups, but reviewers questioned the design and reliance on raw seeds without descriptors.

Reviewers support the broad idea of paper backups, but architectural concerns from Sjors and apoelstra about separating descriptors, timestamps, and seed derivation remain unanswered on this inactive POC.

  • apoelstra noted codex32 seeds are unencrypted and give full spending access regardless of wallet passphrases.
  • Sjors recommended using addhdkey (#32652) and emphasized that backing up keys without descriptors is insufficient for modern wallets.
  • rkrux offered concept ACK for the high-level idea of non-electronic backups.

Review verdicts (DrahtBot): 0

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

This draft POC introduces non-electronic wallet backup and recovery via codex32 (BIP 93) by storing seed material in the wallet database and adding exposesecret and recoverwalletfromseed RPCs. It addresses a long-standing request for paper backups, though reviewers caution that raw seed backups omit necessary output descriptor and timestamp metadata. The PR is stale, conflicting with multiple open wallet changes, and has been inactive since July 2025.

Data

dossier JSON · extract JSON · model openrouter/google/gemini-3.8-flash, generated 2026-09-17T15:49, confidence high, input hash 596f4d2bea232fe7