Skip to content

Rehearse chain settlement end to end on the scripted chain - #384

Merged
ctfbruce merged 5 commits into
mainfrom
test/sui-payment-rehearsal
Oct 5, 2026
Merged

ctfbruce merged 5 commits into
mainfrom
test/sui-payment-rehearsal

Conversation

@ctfbruce

@ctfbruce ctfbruce commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Behaviour

Tests only: internal/dispatcher/payments/rehearsal_test.go rehearses the composed chain settlement path (settlement ledger, receipts, transfers, adapter, payout and refund lifecycle) on real SQLite through the real PaymentHandler in enabled mode, with the scripted chain the transfer tests already use. No production code changes; no wallet, network, chain endpoint or enablement.

Proof

Eight drills, each asserting the final rows of transactions, debuglet_order, order_settlements, earnings, chain_transfers and payment_receipts and the backend call counts:

  1. A USDC intent paid by its receipt, admitted, finished with exit 0, credited once, paid out (reserved, sent, confirmed); a second receipt for the nonce is duplicate, a differing one mismatch; earnings arriving during the payout survive.
  2. A lost response leaves the payout unknown; a verified lookup confirms it without a second broadcast; an unverified success stays unknown.
  3. Stopped after the reservation and before the submission: after a restart the stale reservation is resubmitted once from the stored bytes with the same digest, then confirmed.
  4. Stopped after the submission and before the outcome write: resolved by lookup after a restart; one transfer in total.
  5. A failed refund (not broadcast) keeps the order Refunded and the settlement row and is never sent again; a refund owed but never attempted is sent exactly once by the settlement pass, from its reserved row.
  6. The inline credit refused by a trigger is delivered once by the settlement pass; duplicate terminal reports change nothing.
  7. Every drill again with the database closed and reopened after each step: every state is read back identically (7 to 13 reopenings per drill).
  8. Disabled mode: every chain action refuses with payments_disabled, no receipt or transfer row is written, leftover chain orders stay as they are, TEST flows are unchanged.

Deliberate faults in a throwaway copy (an unverified lookup recorded confirmed; a lost response recorded failed; resubmission only from sent) each fail the drills that guard them. The payments, Sui, HTTP API and dispatcher packages pass under -race with the drills.

Upgrade

None. Stacked on #381, whose commits show in the diff against main until it merges.

Limits

The drills run against the scripted chain and local fixtures only; no live-network test has been run, and enabling chain payments remains the operator's explicit step described in docs/operations/payments.md. The drills established three product limits, recorded on #381: a transfer whose stored bytes the chain no longer knows is resubmitted on every reconciliation pass without a bound; an invalid refund address is detected at the refund, not at intent creation; a failed refund has no re-attempt path.

GitHub issue #87.

Candidate CI

The branch then took the corrected payout branch by merge (ed84410) and asserts the refund outcome it now reports (f558a5a); Run 37310404192 on f558a5a: 16 of 16 lanes and required succeeded. Run 37294915212 on c649c42: 16 of 16 lanes and required succeeded.

Add a rehearsal of the composed chain settlement path on real SQLite
through the real payment handler and the scripted chain: a paid run
credited and paid out exactly once with duplicate and mismatching
receipts recorded; a lost response resolved by a verified lookup
without a second broadcast; the dispatcher stopped after reserving a
transfer and before submitting it, resubmitting the stored bytes once
with the same digest; stopped after submitting and before recording,
resolved after restart with one transfer in total; a failed refund
never sent again while an owed one is sent once from its reserved row;
the settlement pass delivering a credit once after the inline attempt
failed, with duplicate terminal reports ignored; every drill repeated
with the database closed and reopened after each step; and disabled
mode refusing every chain action, including for leftover chain orders,
while TEST flows are unchanged. Each drill asserts the exact rows of
the payment tables and the backend call counts. No wallet, network or
chain endpoint is involved.

GitHub issue #87.
@ctfbruce ctfbruce added In progress Implementation is active. Review Implementation is ready for review and required validation. and removed In progress Implementation is active. labels Oct 5, 2026
@ctfbruce
ctfbruce marked this pull request as ready for review October 5, 2026 10:21
Bring the payout and refund branch at its corrected head under the
rehearsal drills, so that they run against the lifecycle as it will
merge: the refund outcome returned to callers, bounded reconciliation
lookups and the adapter's id validation.

GitHub issue #87.
@ctfbruce
ctfbruce marked this pull request as draft October 5, 2026 12:10
@ctfbruce ctfbruce added In progress Implementation is active. and removed Review Implementation is ready for review and required validation. labels Oct 5, 2026
The refund of an unadmitted intent now reports what became of the
money besides its error, so the drills read that outcome: nothing
transferred when chain payments are disabled, failed after a refund
that was not broadcast, and sent once the next refund is confirmed.

GitHub issue #87.
@ctfbruce ctfbruce added Review Implementation is ready for review and required validation. and removed In progress Implementation is active. labels Oct 5, 2026
@ctfbruce
ctfbruce marked this pull request as ready for review October 5, 2026 13:30
Exercise settlement rehearsals alongside the current payment lifecycle, quote pricing, allowances and operator documentation.

GitHub issue #87.
@ctfbruce
ctfbruce marked this pull request as draft October 5, 2026 14:03
@ctfbruce
ctfbruce marked this pull request as ready for review October 5, 2026 14:19
@ctfbruce
ctfbruce marked this pull request as draft October 5, 2026 14:57
Keep the chain settlement rehearsal with the corrected TCP and UDP two-port test fixtures.

GitHub issues #87 and #389.
@ctfbruce
ctfbruce marked this pull request as ready for review October 5, 2026 15:32
@ctfbruce ctfbruce added the Ready to merge Reviewed and CI passed; merge in dependency order after required approval. label Oct 5, 2026
@ctfbruce
ctfbruce merged commit 76937ad into main Oct 5, 2026
18 of 32 checks passed
@vincent10400094
vincent10400094 deleted the test/sui-payment-rehearsal branch October 8, 2026 00:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready to merge Reviewed and CI passed; merge in dependency order after required approval. Review Implementation is ready for review and required validation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant