WIP: feat(wallet): implement NUT-XX Efficient Wallet Recovery #1735
No reviewers
Labels
No labels
DB & Storage
Deployment
Error Handling & Logging
Maintenance
Payment Backend
backport
backport v0.13.x
backport v0.14.x
backport v0.15.x
bindings
blocked
bug
cdk-sql
ci
cli
deps
documentation
duplicate
enhancement
good first issue
help wanted
invalid
keep-open
ldk-node-ui
migrations
mint
mutation-testing
needs rebase
needs review
new nut
nut change
question
ready
rust-version
rustfmt
stacked hold
stale
testing
wallet
weekly-report
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
cashubtc/cdk!1735
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "a1denvalu3/feat/nut-xx-efficient-wallet-recovery"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
This pull request implements the new NUT-XX Efficient Wallet Recovery specification for the
cdkwallet, reducing recovery complexity fromO(T)toO(log N)and maintaining the required Depth Invariant.Changes
keyset_countertoProofInfoacross SQLite and PostgreSQL, with corresponding migrations.Wallet::ensure_depth_invariantthat triggers a consolidation swap if unspent proofs exceed theT - dthreshold or the compaction limitd.recv_proofs/change_proofscorrectly acrossissue,melt,receive, andswapsagas to maintain accuracy.find_t(binary search).scan_gap(gap scan) to handle gaps securely.Wallet::restore_fast.restorelogic to accept a newRecoveryOptionswithRecoveryStrategy::Fast(default) andRecoveryStrategy::LinearScanto fall back to the old NUT-13 scan.RecoveryOptionsacross UniFFI (cdk-ffi) and added a--legacy-scanflag to thecdk-clifor backwards compatibility.ensure_depth_invariantat startup whenWallet::recover_incomplete_sagasverifies keysets to migrate pre-existingkeyset_counter = NULLproofs.The compaction logic is handled primarily through an automatic, internal
SwapSagathat is triggered whenever the wallet detects that the 'Depth Invariant' ( > T - d$) constraint is at risk.Here is the specific breakdown of how it works:
Triggering
ensure_depth_invariant:Before running any wallet operation that generates new signatures (like a standard swap, receive, or issue), the wallet calls
Wallet::ensure_depth_invariant(keyset_id, new_outputs). This predicts what the keyset counter ($) will be after the operation.Evaluating the Threshold:
It fetches all
Unspentproofs for the active keyset and checks three conditions against the depth limit ( = 100$):new_outputsexceeds 00$, all proofs for that keyset are marked for consolidation.keyset_counter(). If \le T - 100, the specific proof is too old and is marked for consolidation.keyset_counter(e.g., loaded from an older DB schema) is automatically marked for consolidation.Executing the Compaction Swap:
If any proofs are marked, the wallet instantiates an internal
SwapSagato exchange the offending proofs for fresh ones.Bypassing the Loop (
skip_invariant: true):A standard
SwapSaganaturally checks the depth invariant before running. Since this compaction is a swap, doing an invariant check inside the compaction swap would result in an infinite recursive loop. To solve this, the internal swap is initialized viasaga.prepare(..., skip_invariant: true).Mint Interaction:
saga.execute().await?is called. The selected, outdated proofs are sent to the Mint to be melted down, and new proofs are issued in their place.Because the new proofs are freshly issued, their
keyset_countervalues represent the newest sequence indices at the top of the derivation path. This safely resolves the gap, compacts the outputs, and guarantees the entire wallet state successfully meets the strict (\log N)$ fast-recovery invariant before the user's primary operation proceeds.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.