Pre-1.0 Doorkeeper for SessionOutcome in#1747
Conversation
Coverage Report for CI Build 29807705209Coverage decreased (-0.01%) to 86.284%Details
Uncovered Changes
Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
There was a problem hiding this comment.
This seems like a nice path that leaves the door open for non-breaking 1.x Monitor fixes. However, there are 4 distinct components to this PR and I think each deserves standalone attention:
- ACK Reserve the
SessionOutcome::Othervariant - this is the actually useful part, but the justification in the docstring and commit message argues for the wrong thing. "binaries pinned to this persisted format can still parse event logs written by a later minor release that does emit it" is a fine side-effect but forwards-compatibility is not the thing we actually care about (even the docs in persist.rs say "Forward compatibility in general is not appropriate"). Backwards compatibility is the goal. The reason to reserveOtherisn't data compat at all, it's API semver: reserving the name now makes the classifier additive by construction. That argument doesn't appear in the PR. - cACK Change
SessionOutcome::Successto a unit variant. This one requires historical context: the original monitor (0c67af7) recorded an empty witness on the non-segwit path, the path where it actually would have mattered to store those as the only way to reconstruct the final payjoin transaction (see comment). #1218 then deleted that path entirely, so the stored event payload is indeed dead code now. However, #1692 would restore non-segwit detection, which would make this event payload undead once again. I think an argument can be made for only storing aSuccess(Txid)instead of the full script_sig/witnesses. This would also make this PR self-consistent: as written we record the txid of a transaction we don't recognize (Other(Txid)) and nothing for the payjoin we do. - NACK Make SessionOutcome
#[non_exhaustive]. This reverses 8c92050, which explicitly namedSessionOutcomein the keep-exhaustive list, without engaging with that rationale, so I'm not sure whether this is intentional or an accidental omission/hallucination. TheSessionOutcome::Othervariant already grants exactly one named extension. I think any additional unforeseen outcomes should break at compile time instead of leading to unexpected behavior (e.g. as written any future unrecognized outcome would render as "Session closed" in payjoin-cli, with no compile error). - NACK Add
success()andaborted()constructors on SessionOutcome. I don't understand the rationale for this. This seems to simply accomodate a payjoin-cli implementation detail for history display? I'm not even sure that implementation is correct, currently it looks like the sender just hardcodesaborted()it to display "Session aborted" if a replay error occurred.
506891d to
92dfe80
Compare
Adopted. docstring & commit message now refer to semver compat & exhaustive rationale so that we don't regress.
Adopted as suggested including the #1218 reference AND the rationale for only Txid in the variant in the commit history. It keeps it simpler to let an underlying wallet handle saving the witnesses while our lib only stores the Txid as a link to that wallet state.
Reverted as suggested, please ignore. payjoin-cli does seem limited here in that it presents Just one commit now. |
92dfe80 to
c91f1d1
Compare
There was a problem hiding this comment.
ACK c91f1d1 and confirmed this change allows #1692 to be rolled out additively with no breaking changes.
I made some changes:
- Renamed the
Other(Txid)variant toUnrecognized(Txid)- IMO "Other" is too vague and connotes some kind of miscallaneous outcome when it's in fact a specific identified spend. Both doc strings already used the "unrecognized" terminology. - Deleted superfluous comments and unit test.
- Simplified the cli display to not print the txid in history status line. I think adding txid as a standalone column would make sense in a follow-up for success/fallback/unrecognized tx outcomes.
The persisted SessionEvent format freezes at the payjoin-cli 1.0 database-backwards-compatibility commitment, so reshape the receiver's terminal SessionOutcome while a format break is still free. - Change `Success(Vec<(ScriptBuf, Witness)>)` to `Success(Txid)`. The witness payload was recorded so the receiver could reconstruct the final Payjoin on the non-segwit path, but payjoin#1218 removed that path entirely, leaving the enum payload as dead code. The Receiver settlement classifier (payjoin#1692) will restore non-segwit detection, which would make the payload live again, but sufficient record of a settlement is the txid of the transaction that settled it rather than the witness list. The wallet that observed the spend already holds the full transaction. Recording `Success(Txid)` also keeps the terminal variants consistent where the outcome for the transaction we recognize carries the same evidence as the one we do not. - Add `Unrecognized(Txid)` for contested outpoints settled by an unrecognized transaction. Nothing produces it yet but it is reserved now because adding a variant after 1.0 would be a semver-breaking change. Naming `Unrecognized` before the freeze makes the settlement classifier additive in a 1.x follow-up while keeping the enum exhaustive. Co-authored-by: DanGould <d@ngould.dev>
c91f1d1 to
4548e25
Compare
|
rebased after #1753 to fix ci |
caarloshenriq
left a comment
There was a problem hiding this comment.
tACK 4548e25
Unit tests in payjoin::receive::v2::session and payjoin::receive::v2 covering the new Success(Txid) and Unrecognized(Txid) variants pass, as do the two e2e integration tests in payjoin/tests/integration.rs that assert the settlement txid.
| /// NOTE: Nothing in this release produces this variant. It is reserved now because this enum is | ||
| /// deliberately exhaustive, so a new variant after 1.0 would be a semver-breaking API | ||
| /// change; naming it before the freeze lets the settlement classifier land additively. | ||
| Unrecognized(bitcoin::Txid), |
There was a problem hiding this comment.
Is this in theory what would occur if a regular transaction was sent to the same address as the one listed in the bip21 outside of the payjoin flow?
There was a problem hiding this comment.
Not quite, it occurs if one of the sender's inputs is spent in any transaction that is not the payjoin or fallback tx, thus invalidating the payjoin session (receiver can't get paid with an already spent txo)
150 lines of release hygiene that seals the persisted
SessionOutcomeformat before 1.0 freezes itso that after 1.0's db compatibility commitment we can add terminal outcomes (like the settlement classifier's in #1692) additively in 1.x instead of via a semver break plus a db migration. no behavior changes, and the cost is one more rc.
Pre-change:
Co-authored by Claude Code
Pull Request Checklist
Please confirm the following before requesting review:
AI
in the body of this PR.