Skip to content

NUT-XX: Efficient wallet recovery#342

Open
Forte11Cuba wants to merge 3 commits intocashubtc:mainfrom
Forte11Cuba:nut-xx-efficient-wallet-recovery
Open

NUT-XX: Efficient wallet recovery#342
Forte11Cuba wants to merge 3 commits intocashubtc:mainfrom
Forte11Cuba:nut-xx-efficient-wallet-recovery

Conversation

@Forte11Cuba
Copy link

@Forte11Cuba Forte11Cuba commented Feb 18, 2026

Motivated by #301 . Replaces the NUT-13 linear scan with binary search + a depth invariant that bounds unspent proofs to the last d nonce indices.

Reduces BlindedMessages revealed to the mint from O(T) to ~182 (constant), and requests from O(T/b) to ~35. No mint changes required.

Builds on the binary search and d-invariant ideas from #301 . Credit to @a1denvalu3 for the original proposal and algorithm design, @robwoodgate for the halfway-house approach and the concerns around coin-selection that shaped the final invariant, @gandlafbtc for the local-search alternative that framed the trade-offs, and @davidcaseria for raising the practicality constraints that led to the relaxed invariant.

Open for discussion this is a draft NUT, not final. Feedback welcome especially on: the Depth Invariant definition, the gap-tolerance approach, and the default value of d.

@a1denvalu3
Copy link
Contributor

Just amazing.

@a1denvalu3
Copy link
Contributor

This NUT reduces leakage to O(log N + g + d) BlindedMessages

It also speeds up recovery, because you send log N requests.

XX.md Outdated
Comment on lines +11 to +14
The recovery procedure defined in [NUT-13][13] reveals the wallet's entire transaction history to the mint. During recovery, the wallet sends every `BlindedMessage` it has ever generated — including nonces for tokens that were never issued — to the mint in sequential batches. This has two consequences:

1. **Privacy**: The mint can correlate all of the user's past ecash activity retroactively, defeating the unlinkability guarantees of ecash.
2. **Efficiency**: Recovery requires O(T/b) network requests, where T is the total number of issued notes and b is the batch size.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would cut this and instead put in the PR description. This is more of a motivation.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point trimmed it down to a two-line summary. The detailed motivation is already in the PR description.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not specific to this pr but we should also make sure we include context like this not just in the PR description but in the git log so we don't lose it the day github enviably doesn't work.

2. **On send (swap-to-send)**: A send operation involves a [NUT-03][03] swap that creates new outputs (send proofs + change proofs), which increases T. If this increase causes any remaining unspent proofs (those not involved in the swap) to have index `i ≤ T - d`, the wallet **MUST** consolidate them. Note: a pure melt (paying a Lightning invoice without swap) does not increase T and therefore cannot violate the invariant.

3. **Coin selection**: Wallets **MAY** use arbitrary coin selection. After any operation that increases T, the wallet **MUST** check whether any unspent proof now has index `i ≤ T - d` and consolidate if so. This preserves free coin selection while enforcing the invariant.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also the case where a wallet already has d unspent proofs, and adding any more would violate the constraint no matter if you reissue the old ones. In that case, the operation should fail and compaction should be done to compress all of the existing unspent proofs into fewer ones.

Comment on lines +189 to +197
### Breakeven points

This NUT reveals **more** nonces than [NUT-13][13] for small wallets:

- **Privacy breakeven**: T ≈ 132. For wallets with T < 132, [NUT-13][13] reveals fewer nonces.
- **Efficiency breakeven**: T ≈ 825 (with batched gap scan). For wallets with T < 825, [NUT-13][13] makes fewer requests.

For wallets below these thresholds, the overhead of binary search (32 sequential round-trips) and the fixed recovery window (`d` nonces) exceeds the cost of a simple linear scan. Wallets **MAY** use a heuristic: if a previous recovery or local state suggests T < 200, fall back to the [NUT-13][13] linear scan.

Copy link
Contributor

@a1denvalu3 a1denvalu3 Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really good, although one doesn't know T until found.

Comment on lines +198 to +203
### Privacy properties

The privacy gain for wallets above the breakeven comes from two properties:

1. **Bounded leakage**: The number of revealed nonces is constant (182) regardless of wallet history size. A wallet with T = 1,000 reveals the same number of nonces as one with T = 100,000.
2. **Non-sequential probes**: The 32 binary search probes are spread across the entire nonce space and are non-contiguous, making transaction history correlation significantly harder for the mint compared to the sequential batches of [NUT-13][13].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this information is not necessary to implementors and can be documented elsewhere.

@a1denvalu3
Copy link
Contributor

a1denvalu3 commented Mar 2, 2026

I think d = 100 is a good choice for the window, because to completely exhaust that you'd need a balance of 2^99-1 (assuming base 2 denominations), which is large enough.

Co-authored-by: a1denvalu3 <43107113+a1denvalu3@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

3 participants