Skip to content

Add wallet birthday height for seed recovery on pruned nodes#822

Draft
FreeOnlineUser wants to merge 2 commits intolightningdevkit:mainfrom
FreeOnlineUser:upstream/wallet-birthday-pr
Draft

Add wallet birthday height for seed recovery on pruned nodes#822
FreeOnlineUser wants to merge 2 commits intolightningdevkit:mainfrom
FreeOnlineUser:upstream/wallet-birthday-pr

Conversation

@FreeOnlineUser
Copy link

Adds set_wallet_birthday_height(height) to the builder, allowing the on-chain wallet to sync from a specific block height instead of the current tip or genesis.

This complements the existing set_wallet_recovery_mode() from #769 by supporting pruned nodes where scanning from genesis fails due to missing blocks.

Motivation

When restoring a wallet from seed on a pruned node:

  • recovery_mode (scan from genesis) fails: blocks are pruned
  • Default behavior (checkpoint at tip) misses historical funds

With a birthday height, the wallet checkpoints at a known block before the first transaction, recovering funds without needing the full chain.

How it works

Three-way logic in wallet creation:

  1. Birthday set: fetch block hash at birthday height, checkpoint there
  2. No birthday, no recovery mode: checkpoint at current tip (existing behavior)
  3. Recovery mode without birthday: sync from genesis (existing behavior)

Falls back to current tip if the birthday block hash cannot be fetched.

Real-world use

Built and verified in Bitcoin Pocket Node, an Android app running bitcoind + ldk-node on GrapheneOS with pruned storage. Recovery flow:

  1. User restores seed
  2. App runs scantxoutset to find UTXOs and their block heights
  3. Sets birthday to min(heights) - 10
  4. ldk-node syncs from that height, balance appears

Tested end-to-end on real hardware: 10,844 sats recovered in seconds.

Closes #818

When set_wallet_birthday_height(height) is called, the BDK wallet
checkpoint is set to the birthday block instead of the current chain
tip. This allows the wallet to sync from the birthday forward,
recovering historical UTXOs without scanning from genesis.

This is critical for pruned nodes where blocks before the birthday
are unavailable, making recovery_mode (which scans from genesis)
unusable.

Three-way logic:
- Birthday set: checkpoint at birthday block
- No birthday, no recovery mode: checkpoint at current tip (existing)
- Recovery mode without birthday: sync from genesis (existing)

Falls back to current tip if the birthday block hash cannot be
fetched.

Resolves the TODO: 'Use a proper wallet birthday once BDK supports it.'
Closes lightningdevkit#818
@ldk-reviews-bot
Copy link

👋 Hi! I see this is a draft PR.
I'll wait to assign reviewers until you mark it as ready for review.
Just convert it out of draft status when you're ready for review!

Extend get_block_hash_by_height to work with Esplora and Electrum
in addition to bitcoind. Esplora uses its native get_block_hash API.
Electrum uses block_header_raw and extracts the hash from the header.

For Electrum, if the runtime client hasn't started yet (called during
build), a temporary connection is created for the lookup.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wallet birthday height for seed recovery on pruned nodes

2 participants