db: Preserve OOR dispatch idempotency keys - #1109
Open
bhandras wants to merge 1 commit into
Open
Conversation
bhandras
force-pushed
the
agent/preserve-oor-idempotency-key
branch
from
August 6, 2026 17:39
6b4cdef to
1657f1f
Compare
bhandras
marked this pull request as draft
August 6, 2026 17:54
Incoming lifecycle records omit the outgoing dispatch key. Replacing that key with NULL lets a retry admit a duplicate transfer. Keep the prior non-NULL key while advancing the shared session row.
bhandras
force-pushed
the
agent/preserve-oor-idempotency-key
branch
from
August 6, 2026 18:04
1657f1f to
e0dbb21
Compare
bhandras
marked this pull request as ready for review
August 6, 2026 18:05
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.
Summary
Motivation
Outgoing and incoming OOR lifecycles share one session registry row. When a sender observes its own OOR output or change, the incoming upsert carries no dispatch key and has an incoming snapshot. Replacing the row previously erased both the outgoing identity and the recipient proof. A later lost-response retry could either admit a second transfer or fail closed because the incoming snapshot cannot prove the original recipient.
Terminal outgoing snapshots also intentionally omit Ark artifacts because they are resume no-ops. The durable proof therefore must be the first earlier canonical snapshot whose Ark PSBT decodes to recipient outputs, not merely the latest outgoing snapshot.
This is a prerequisite for the restart-safe credit-redemption fix in lightninglabs/swapdk-server#298.
Causal proof
Before the query change,
TestOORSessionRegistryIncomingUpsertPreservesIdempotencyKeyfailed because the incoming upsert changeddurable-dispatch-keyto the empty value.After preserving only the key, the real RPC regression still failed: keyed replay found the original session but returned no recipient outpoint because it tried to decode the incoming snapshot.
The final regressions prove that the real outgoing bridge first persists decodable recipient proof, a terminal update omits proof without overwriting it, a following incoming update preserves the original key and proof, and
SendOOR(existing_only=true)returns the exact original outpoint with one total wallet selection. They also cover attempted same-session key replacement, legacy terminal/local-update fail-closed behavior, and an exact downgrade state containing both a released failed row and its successful retry.Verification
db,oor, andwavedunit packagesdbpackagemake lint-changed-localmake sqlc-checkmake tidy-module-checkmake fmt-changed-checkmake commitmsg-lint range="origin/main..HEAD"