Mint note secrets under LUD-25's own derivation - #64
Merged
Conversation
The draft specifies a BIP-32 scheme under m/139' and the reference wallet implements it. This wallet had been using lnurlcash-kit's pre-spec HMAC scheme, which shipped four days before that section existed. The same twelve words now restore the same notes in any wallet that implements LUD-25, which was the entire point of deriving them. (d1, d2, d3, d4) = HMAC-SHA256(key = m/139'/0, msg = "<mint host>")[0..16] k1[i] = m/139'/d1/d2/d3/d4/i' Nothing already minted is lost. restoreFromMint walks both ladders in one pass and records which one found each note; a record with no scheme is a pre-spec one, which is exactly what every record written before now is, so no stored wallet needs rewriting. Those notes keep working and move onto the new ladder the first time they are rotated. counters keeps its meaning - the pre-spec ladder's position - because that is where a restore starts looking for those notes, and reading it as an m/139' position would claim rungs on a ladder nothing has used. The new ladder lives in cashCounters beside it. Both sync, both merge upwards only, since a counter that went backwards would hand a second device an index the first has already minted at. Counter sync payloads are v2 and carry both maps. A device that predates this reads the one it knows and ignores the other, and never mints on the new ladder, so the two cannot collide. A v1 payload reads as no cash counters, which is the truth rather than a gap. Also says plainly in the README and llms.txt that the counter is half the backup: a mint answers a private lookup for a burned note exactly as for one it never issued, and every rotate burns the index below, so a wallet that has rotated more than the gap would scan as empty without it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The draft specifies a BIP-32 scheme under
m/139'and the reference wallet implements it. This wallet had been usinglnurlcash-kit's pre-spec HMAC scheme, which shipped four days before that section existed. The same twelve words now restore the same notes in any wallet that implements LUD-25, which was the entire point of deriving them.Nothing already minted is lost
restoreFromMintwalks both ladders in one pass and records which one found each note. A record with noschemeis a pre-spec one, which is exactly what every record written before now is, so no stored wallet needs rewriting. Those notes keep working and move onto the new ladder the first time they are rotated.Two counters, and the old one is not repurposed
counterskeeps its meaning, the pre-spec ladder's position, because that is where a restore starts looking for those notes and reading it as anm/139'position would claim rungs on a ladder nothing has used. The new ladder lives incashCountersbeside it. Both sync across devices, both merge upwards only: a counter that went backwards would hand a second device an index the first has already minted at.Counter sync payloads are
v: 2and carry both maps. A device that predates this reads the one it knows and ignores the other, and never mints on the new ladder, so the two cannot collide. Av: 1payload reads as no cash counters, which is the truth rather than a gap. Both directions are covered by tests.And the thing that is easy to get wrong
The README and
llms.txtnow say plainly that the counter is half the backup, not an optimisation. A mint must answer a private lookup for a burned note exactly as it answers one for a note it never issued, so a walk cannot see a spent index; and since every rotate burns the index below it, a wallet that has rotated more than the gap would scan as empty without its counter. It is not secret, so it belongs in an ordinary backup.322 passing, typecheck and build clean. Requires
lnurlcash-kit0.8.0.