Skip to content

Regression: swap-CLI soak fails at proposal delivery on master (post-#534/#536); daemon-vs-CLI take divergent paths on token validation #545

Description

@vrogojin

Summary

manual-test-swap-roundtrip.sh (Scenario A) fails on master with ASSERT FAIL (proposal-ingest-timeout) — bob does not receive alice's swap proposal within the 90s budget. The same soak script, against the same testnet+escrow, passes green end-to-end when sphere-cli loads a pre-#534/#536 sphere-sdk (commit 8c7d93d).

Surfaced while validating trader-service#29 (PR vrogojin/trader-service#32). Independent of #29; my code changes are confined to trader-service.

A/B test result

Two consecutive runs of bash manual-test-swap-roundtrip.sh SCENARIO=A KEEP=1 differing only in which sphere-sdk checkout sphere-cli/node_modules/@unicitylabs/sphere-sdk symlinks to:

sphere-sdk state Result
commit 8c7d93d (pre-#534, pre-#536) PASS — proposal delivered, both sides reached completed, poison-pill scan clean
current master (post-#534/#536) with freshly-built dist FAILproposal-ingest-timeout; bob saw No swaps found for the full 90s window; reproduced twice

The diff between the two checkouts is exclusively #534 (fix(oracle,soak): payments.validate() always reported invalid + stale swap-soak escrow) + #536 (fix(swap)(sphere-sdk#535): use state-transition-sdk primitives for verifyPayout) — see git diff 8c7d93d HEAD -- '*.ts' (12 files, +1074/-127).

This contradicts the assertion in vrogojin/trader-service#29 that the swap-CLI soak validated #536 end-to-end. Either that validation was incomplete (e.g. did not include the cross-process Nostr-DM ingest step of manual-test-swap-roundtrip.sh), or something has regressed since.

Failure mode is divergent between daemon and CLI consumers

Same SDK delta, different observed symptom depending on consumer:

So pre-#534/#536 the CLI's sphere swap wait --state completed reaches completed successfully, while the daemon's auto-verify loop hangs. The two consumers exercise the validation gate differently:

  • daemon = long-running, drives verifyPayout directly via its auto-retry loop
  • CLI = short-lived, drives swap progression event-by-event through sphere swap wait

The wait command may bypass or short-circuit the validation gate that the daemon's polling loop hits. Worth understanding both paths before locking in either #534 or #536's behavior.

Repro

# Working tree assumed: sphere-cli/node_modules/@unicitylabs/sphere-sdk is a symlink
# to whichever sphere-sdk checkout you want to test.

# Pin to pre-#534/#536:
ln -sfn /path/to/sphere-sdk-at-8c7d93d sphere-cli/node_modules/@unicitylabs/sphere-sdk
( cd /path/to/sphere-sdk-at-8c7d93d && npm run build )
rm -rf /tmp/swap-soak && SWAP_TEST_DIR=/tmp/swap-soak SCENARIO=A KEEP=1 \
  bash manual-test-swap-roundtrip.sh
# → ALL GREEN — swap round-trip succeeded (Scenario A)

# Pin to master (post-#534/#536):
ln -sfn /path/to/sphere-sdk-at-master sphere-cli/node_modules/@unicitylabs/sphere-sdk
( cd /path/to/sphere-sdk-at-master && npm run build )
rm -rf /tmp/swap-soak && SWAP_TEST_DIR=/tmp/swap-soak SCENARIO=A KEEP=1 \
  bash manual-test-swap-roundtrip.sh
# → ASSERT FAIL (proposal-ingest-timeout) after 90s

Workspace preserved at /tmp/swap-soak for log inspection.

Investigation candidates

  1. Bisect fix(oracle,soak): payments.validate() always reported invalid; stale swap-soak escrow #534 vs fix(swap)(sphere-sdk#535): use state-transition-sdk primitives for verifyPayout #536. Apply fix(oracle,soak): payments.validate() always reported invalid; stale swap-soak escrow #534 alone (a063d4b7) and re-run; apply fix(swap)(sphere-sdk#535): use state-transition-sdk primitives for verifyPayout #536 alone (8b1955a9) and re-run. Quickly narrows which one introduced the proposal-delivery regression.
  2. Where does the CLI's sphere swap wait skip validation that the daemon hits? Compare the verify-trigger sequence in both consumers. The CLI's pre-fix(oracle,soak): payments.validate() always reported invalid; stale swap-soak escrow #534/fix(swap)(sphere-sdk#535): use state-transition-sdk primitives for verifyPayout #536 green-completion suggests the wait command isn't running the same payments.validate() invariant the daemon's auto-verify loop is. If true, fix(oracle,soak): payments.validate() always reported invalid; stale swap-soak escrow #534's validate() fix has different blast radius across consumers.
  3. Is the proposal-ingest failure really about the proposer or about the acceptor? Capture alice's transport state (her Nostr publish ack) and bob's transport subscription with a probe to determine whether alice's CLI exits before the publish flushes, or whether bob's subscription is misconfigured under post-fix(oracle,soak): payments.validate() always reported invalid; stale swap-soak escrow #534/fix(swap)(sphere-sdk#535): use state-transition-sdk primitives for verifyPayout #536 SDK.

Workaround (until root cause lands)

Pin sphere-cli's @unicitylabs/sphere-sdk symlink to commit 8c7d93d (pre-#534/#536). Trader-service's daemon is not currently green against any sphere-sdk version, so the workaround restores the swap-CLI soak only.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions