Skip to content

Wallet birthday height for seed recovery on pruned nodes #818

@FreeOnlineUser

Description

@FreeOnlineUser

When restoring an ldk-node wallet from seed, the node starts syncing from the current chain tip. Any on-chain deposits made before the restore are never seen by synchronize_listeners, so the wallet balance shows zero even though funds exist on-chain.

This affects all seed restores, but pruned nodes are hit hardest: historical blocks are gone, so there is no workaround via rescan.

There is an existing TODO acknowledging this:

// TODO: Use a proper wallet birthday once BDK supports it.

(src/builder.rs:1327)

Impact

  • On-chain balance shows 0 after seed restore
  • Cannot open Lightning channels (no visible funds)
  • Funds are safe on-chain but inaccessible through ldk-node
  • Mobile wallets (where reinstalls and data loss are common) are the primary use case

What we did

We hit this building Bitcoin Pocket Node, an Android app running bitcoind + ldk-node on GrapheneOS with pruned storage.

Our workaround overrides chain_tip_opt in the Builder when a birthday height is provided. Caller flow:

  1. User restores seed words
  2. App uses bitcoind scantxoutset to find UTXOs and their block heights (works on pruned nodes)
  3. Sets birthday to min(heights) - 10 as safety margin
  4. ldk-node syncs from there, balance appears with zero transaction fees

Working fork with the changes (~100 lines): FreeOnlineUser/ldk-node@upstream/wallet-birthday

Verified end-to-end on real hardware: seed restore, UTXO scan, birthday set, 110,628 sats recovered in seconds.

Upstream context

BDK is working on related pieces:

  • bdk#2126: Adding start_height to FilterIter::new
  • bdk#2050: Pruned node support via scantxoutset

Once BDK ships native birthday support, ldk-node can use that directly (which is what the TODO anticipates). Our fork is a pragmatic solution in the meantime.

We are also the folks working on the watchtower improvements discussed in #813.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions