Compute (potentially reorging) Settlement Status From Wallet Data#1692
Draft
DanGould wants to merge 5 commits into
Draft
Compute (potentially reorging) Settlement Status From Wallet Data#1692DanGould wants to merge 5 commits into
DanGould wants to merge 5 commits into
Conversation
Introduce outpoint-based settlement attribution for a monitored
session. A pure, total classify maps caller-supplied chain facts to a
settlement status without any I/O or persisted events.
Add the compute types SettlementStatus and SettlementOutcome
{Cooperative, Fallback, Other} (sealed #[non_exhaustive]) plus
ChainView/OutpointSpend, and the primitive getters the wallet needs
(payjoin_txid, fallback_txid, contested_outpoints, receiver_input).
classify recognizes a cooperative settlement by either signal: the
spending transaction carries the receiver's contributed input (the
input fingerprint) or, for an output-substitution proposal, reproduces
the proposal's output set (a cut-through). Both are structural, so a
non-SegWit txid change does not hide them. Precedence is
Cooperative > Fallback > Other.
Add Receiver<Monitor>::conclude, which persists the single terminal Closed(SessionOutcome) event once the caller's confidence bar is met, mapping Cooperative -> Success, Fallback -> FallbackBroadcasted, and Other -> Other. Grow the persisted SessionOutcome for settlement attribution: collapse Success to a unit variant (the spending transaction is chain data the caller already holds, so witnesses are not persisted), add Other(Txid) mapped to SessionStatus::Failed, and seal the enum #[non_exhaustive] with an aborted() constructor so downstream crates keep building the replay sentinel. Re-express the legacy check_for_transaction over classify via a txid-only ChainView, concluding a unit Success. Update the payjoin-cli SessionOutcome matches and history construction, and the integration assertions, for the unit Success.
Add the foreign-facing settlement surface: a ChainBackend trait that reports each contested outpoint's spend status, the ChainSpend record, and SettlementStatus/SettlementOutcome uniffi mirrors. Monitor::classify queries the backend, builds a ChainView, and returns the status without persisting anything. SettlementOutcome is #[non_exhaustive] in core, so the conversion keeps a wildcard arm that degrades a finer label this binding predates to Other until the binding is regenerated.
Drive the monitor loop from classify: build a ChainView by querying the wallet for each contested outpoint (get_raw_transaction_verbose for the spending tx and its confirmations), then render the status each tick as Pending / cooperative / fallback / other, concluding once a configurable confirmation bar is met.
Spell out the Monitor contract so integrators do not trust an imprecise 0-conf verdict. The proposal and the fallback double-spend the sender's inputs, so detection is necessary but not sufficient: only confirmation resolves the race, and confirmation depth is a confidence dial, not a state transition. Document the division of labor (library knows the semantics, wallet knows the ground truth and holds the spending transaction), the classify/conclude flow, and that the legacy check_for_transaction cannot surface Other and concludes optimistically on first sight.
8832e47 to
e7c0dde
Compare
Collaborator
Coverage Report for CI Build 28389258738Coverage increased (+0.3%) to 85.769%Details
Uncovered Changes
Coverage Regressions2 previously-covered lines in 2 files lost coverage.
Coverage Stats
💛 - Coveralls |
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.
This is following up on #1684 where I figured out Monitor's status can go stale in the case of a reorg. Instead, we can run a classifier that can always classify the status based on mempool+chain state data instead.
This classification, that tracks
OutPointstatus also makes the #1218 workaround that skips monitoring the status of non-segwit outputs obsolete and can actually monitor non-segwit spending Payjoin cooperative txs.Sessions still close once a
Receiver<Monitor>detects a transaction but the actual SettlementStatus is determined by callingclassifyon chain state each time.Co-authored by Claude code
Pull Request Checklist
Please confirm the following before requesting review:
AI
in the body of this PR.