Improved recovery #301
Labels
No labels
breaking change
bug
documentation
enhancement
needs discussion
needs implementation
new nut
ready
wallet-only
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo-admin/nuts#301
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Improved Recovery (Efficiency and Privacy)
The way recovery is currently performed is a privacy disaster: the wallet leaks the entire spending history in an attempt to recover unspent user funds. This issue describes the current recovery method, followed by a revised approach which reduces the number of leaked unissued notes by a logarithmic factor and limits the number of leaked issued notes to an arbitrary
d.Current Recovery Modal
Let
Tbe the index of the nonce that was issued in the lastBlindMessage(meaning there is no other issued note whose nonce indexO > T).On the first iteration our current approach sets a batch size
b, then computes the nonces and relativeBlindMessages in[0, b-1]and queries the Mint find out which one of them are issued and spent.On the second iteration, we check the next batch of
BlindMessagess in[b, 2b-1].This process continues until the $i$-th iteration, when we find that the last batch was returned empty or partially empty.
After which it follows that if
uis the number of un-issued notes in the last batch, thenT = i\cdot b-u-1, and we conclude.Obviously, this procedure is terrible for privacy because we're linking together our entire wallet activity history and -on top of that- we're revealing nonces for which
BlindMessages were unissued (the segment part marked with*).Other than being non-privacy friendly, this approach is also relatively in-efficient: it takes
\mathcal{O}(\frac{n}{b})network requests, withnbeing the total number of issued notes.Improved Approach
We subdivide our improved approach into two "phases" to make it more digestable:
Twith logarithmically fewer queries.1. Spent-Issued Invariant
Let
dbe an arbitrary size andKbe the index of the nonce used for the last spent note (meaning that there is no other spent note whose nonce is of indexO > K). Our invariant providesT - d < K \leq Talways .In english, this means: "The unspent ecash notes are always situated in a region of the nonce space that is never larger than a fixed, pre-decided, size."
Visualization:
Where
=marks nonces used for spent notes and-marks nonces used for issued notes.This property alone doesn't help us: we still need to scan
[0, 2^{32}-1]to findKandT.But we at least know that, when we find
K,Tcan't be far away (and vice-versa).2. Nonce space binary search
This is where things get interesting. Turns out we can use binary search to efficiently determine
Tand thenK, leaking far fewer notes that we would with a linear scan.Here's how it works. At iteration
i = 0we have:The wallet only queries the Mint with the
BlindedMessagefor the nonce with indexm.If
mwas issued then we restrict the range from the left (we updatel). Vice-versa ifmis un-issued (empty response) we restrict the range from the right (updater).Formally, we have:
At the end of this process, we are ideally left with
l = m = r, which is ourT.We can repeat this a second time to find
K, now with a much smaller admissible range which, due to our invariant, is[T-d, T]Once both
TandKare determined, we can get the unspent notes with a single network request to the mint containingT-Kblinded messages whose nonces have indices in[T-K, T].Result
Privacy
We improve on privacy, by only revealing
\log_2{N} + \log_2{d} + dnotes at worst, withNbeing the nonce space (i.e.2^{32}).Efficiency
We improve on efficiency for the same reason: we make fewer network requests.
Consequences
This results don't come for free. Maintaining the invariant described above would require:
KProofobject.dis exceeded by a quantitye- we reissue the oldesteunspent notes and updateK.TandKdoesn't get larger thand. Therefore, we would have to re-issue some of the notes from indexKonwards, under bigger denominations. If this can't be done the wallet would be at capacity and the operation should be aborted.Since recovery is infrequent, ideally never used, and coin selection is a routine operation for a wallet, it doesn't seem to me that the benefit justifies this consequence.
recovery as it is, however infrequent, destroys the privacy properties of the ecash retroactively for the entire history of the wallet.
Note that I'm not expecting to see this implemented any time soon. It's necessary but definetely not urgent.
This is a fantastic use for binary search, but the consequences 3 & 4 are pretty restrictive, and may be hard to swallow.
3) Coinselection in order of derivation
The loss of good coinselection is a blow - if you HAVE to take oldest proofs in order, you can't optimize for fees. For example, you might end up burning loads of single unit proofs in fees, rather than being able to use them judiciously to cover fees in larger swaps.
The only upside to that might be that it takes "old proofs" out of circulation faster, which is useful for key rotations.
But I'm not sure the gain will outweigh the potential pain.
Maybe this is less of a concern if the wallet does good target denomination management?
4) Arbitrary capacity (
d)Again, this creates high potential for fee churn, unless the wallet is good at managing target denominations.
Do you envisage the user being able to set this arbitrary capacity (ie take on more privacy leak risk for convenience)?
I wonder if we need the
drestriction at all... with a binary search, even a search from origin is never going to leak a fantastic number of proofs vs an arbitraryd. The chop will narrow down the field pretty quickly.Less consequential option?
Maybe the "halfway-house" is a recovery that does binary search to find
T, starting at some "typical" (arbitrary) point nearer the start than the end of the nonce space.That way, there isn't as much leakage of unissued nonces as current method.
Be interesting to see what people think of the pros and cons of this approach.
The d-invariant is necessary if you want to ensure a full recovery (meaning you are certain you're not leaving behind nonces for unspent notes).
BUT here's how I think it could be relaxed: we could allow arbitrary coin-selection with the condition that -if
dis exceeded by a quantity $e$- we reissue the oldesteunspent notes and updateK.This is way simpler and more compatible with the current wallet implementations.
There is also the option to have zero leaks, by downloading all BM, signatures and spent secrets from the mint and do the search locally.
Not elegant, but best privacy