You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
docs: use a pool of durable nonce accounts for withdrawals - #240
A withdrawal transaction that actually landed can still be reported as missing: getSignatureStatuses without searchTransactionHistory only searches the recent status cache of roughly 300 rooted slots, while both getSignatureStatuses with the flag and getTransaction search the node's local blockstore and an optional archive, whose retention is a provider choice rather than a protocol guarantee. Re-signing such a transaction with a fresh blockhash can pay the withdrawal out twice.
This PR extends the design document so that withdrawal transactions no longer rely on status queries for the resubmission decision. Withdrawals use a pool of durable nonce accounts that are set up offline and passed to the minter via init/upgrade arguments; deposit sweeps and consolidations keep using recent blockhashes. With at most one in-flight transaction per nonce account and at most one message signed per nonce value, reading the nonce account tells the minter definitively whether a withdrawal transaction landed: if the nonce is unchanged, the identical signed transaction is re-broadcast without re-signing; if it advanced, the transaction landed and is never submitted again.
Unchanged finalized nonce does not prove a transaction never landed
docs/design.md:447
An unchanged nonce in a finalized account read does not prove the transaction has never landed: it may already be processed or confirmed on an unfinalized fork. Here and in the “Nonce value unchanged” bullet in Section 3.2.3, say that no finalized nonce advance is visible rather than that the transaction has not landed. Rebroadcasting the identical signed transaction remains safe; the prescribed behavior need not change.
Manual-flow diagram references the wrong finalization section
docs/design.md:523
Renumbering finalization to Section 3.2.3 leaves the manual-flow sequence diagram at line 334 pointing to Section 3.2.2, which now describes withdrawal submission. Change that note to Note over Minter: ⏱️ Finalization timer (Section 3.2.3).
Prevent stale nonce reuse after finalized withdrawal
docs/design.md:470
The slot floor also needs to include status-based finalization. After reading nonce N at slot 100 and observing its withdrawal finalized at slot 200, a lagging account response at slot 150 still satisfies minContextSlot: 100. Reusing N produces a batch that cannot land; a later fresh read then wrongly classifies it as Landed. Persist the maximum of account-read and finalized-withdrawal slots before releasing the account, and require a nonce different from the last consumed value before signing another batch.
Prevent untracked nonce advances from falsely marking withdrawals landed
docs/design.md:609
A separate manual nonce advance can consume the nonce without the withdrawal landing, invalidating the documented inclusion check. If that advance wins the race, the minter marks the original withdrawal Landed, but its transaction can never be fetched to resolve the burned request. Explicitly prohibit this recovery action under the current design, or define a tracked cancellation flow that distinguishes which transaction consumed the nonce before allowing it.
Persist finalized slots before releasing accounts to prevent nonce reuse
docs/design.md:470
The slot floor misses finalization through getSignatureStatuses. If withdrawal A reads nonce N at slot 100 and finalizes at slot 110, a subsequent read at slot 105 still satisfies minContextSlot: 100. After the account is released, batch B can therefore sign the already-consumed nonce. B cannot execute, yet a later read falsely classifies it as Landed, leaving its withdrawals unpaid. Include finalized transaction slots in the persisted floor before releasing the account, and reject the previously consumed nonce when preparing a new batch.
Include withdrawal burn indices in CreatedTransaction
docs/design.md:518
Include the batch's withdrawal burn indices in CreatedTransaction. The listed Solana message and nonce fields do not identify the ledger requests, especially when multiple requests have identical destinations and amounts. Recovery after an upgrade between creation and submission needs that association to keep those requests reserved and update their statuses. The existing SubmittedTransaction event preserves it through TransactionPurpose::WithdrawSol { burn_indices } in minter/src/state/event.rs.
Treat unchanged nonce as inconclusive, not proof of non-inclusion
docs/design.md:470
An equal nonce does not prove that the transaction has not landed: a lagging provider can return the pre-advance value even after finalization, and a finalized read also does not rule out inclusion on an unfinalized fork. Describe equality as “no advance observed,” with the outcome still unknown. Rebroadcasting the identical signed transaction remains safe; only a never-seen value proves a finalized advance under the stated invariants, at which point rebroadcasting stops. Apply this distinction consistently here, in the unchanged-nonce bullet at line 580, and in the endpoint summary at line 69.
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
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.
A withdrawal transaction that actually landed can still be reported as missing:
getSignatureStatuseswithoutsearchTransactionHistoryonly searches the recent status cache of roughly 300 rooted slots, while bothgetSignatureStatuseswith the flag andgetTransactionsearch the node's local blockstore and an optional archive, whose retention is a provider choice rather than a protocol guarantee. Re-signing such a transaction with a fresh blockhash can pay the withdrawal out twice.This PR extends the design document so that withdrawal transactions no longer rely on status queries for the resubmission decision. Withdrawals use a pool of durable nonce accounts that are set up offline and passed to the minter via init/upgrade arguments; deposit sweeps and consolidations keep using recent blockhashes. With at most one in-flight transaction per nonce account and at most one message signed per nonce value, reading the nonce account tells the minter definitively whether a withdrawal transaction landed: if the nonce is unchanged, the identical signed transaction is re-broadcast without re-signing; if it advanced, the transaction landed and is never submitted again.
🤖 Generated with Claude Code