Repository navigation
fix: commit carves before the settlement wait (#6) - #8
Merged
Merged
Conversation
A flow that carves and then waits minutes on a settlement poll used to commit the carve only after the whole flow resolved - an abort mid-wait left burned inputs spendable locally and stranded the fresh outputs. ensureExactAmount now reports a mutation-bearing carve through the new FundOperationOptions.onCarve checkpoint the moment its outcome is known; payWithBearers and transferBetweenMints thread it through. Because the carve may now be committed before the flows' classification rotates run, those rotations no longer rewrite carve.note in the result - returned funds come back as a separate verified rotatedNote, so the committed carve and the re-secured note can both be persisted. NWC's payChangeset adapts to the rotatedNote field; its own commit timing is unchanged (follow-up).
The three composables commit the carve inside onCarve via the existing commitCarve helper instead of after the flow, falling back to a URL lookup for no-mutation carves (which fire no hook). On failed-funds-returned with a rotation, the re-secured note is added before the burned carved note is marked spent.
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.
Closes #6.
Problem
Every flow that carves (split/merge) notes and then waits on a settlement poll — send, pay, and inter-mint move — committed the carve's changeset only after the whole flow resolved. A user abort, tab close, or crash during the (up to 2-minute) wait left the carved inputs burned at the mint but spendable locally, and stranded the fresh outputs entirely: their secrets lived only in the pending promise's memory. Observed in the wild with a target mint's Lightning node down.
Fix
FundOperationOptions.onCarve— a checkpoint fired byensureExactAmountthe moment a mutation-bearing carve's outcome is known (inputs burned, outputs known), before the flow moves on to the melt/wait. Never fires for a no-op exact-match carve. A rejecting hook aborts the flow before the melt — nothing further is spent from an uncommitted carve.carve.notein the result —PayResult/TransferResultcarry a separate verifiedrotatedNote. (This closes a regression the first cut of this PR introduced: the early-committed carve plus the old in-place rotation would have stranded the returned funds onfailed-funds-returned— caught in review, fixed here with tests.)onCarvevia the existingcommitCarvehelper; no-mutation carves fall back to a URL lookup;failed-funds-returnedadds the rotated note before marking the burned carve note spent.payChangesetadapts torotatedNote; its commit timing is unchanged (its own early-commit threading is a deliberate follow-up — see below).Verification
npx vitest run: 340/340, incl. new coverage: hook fires with the result / never fires for no-mutation carves / hook failure aborts pay and transfer before the melt / hook provably runs before the melt starts / rotation arrives asrotatedNotewith the carve untouched.npx vue-tsc --noEmitclean, eslint clean, e2e 25/25 (chromium).Scope notes
pay_invoicegets its ownonCarvethreading as a follow-up — flagged by review, deliberately kept out to keep this diff tight.