Skip to content

feat: add liquidity management Loop In and Loop Out - #1643

Draft
quake wants to merge 247 commits into
developfrom
liquidity-management-m0
Draft

feat: add liquidity management Loop In and Loop Out#1643
quake wants to merge 247 commits into
developfrom
liquidity-management-m0

Conversation

@quake

@quake quake commented Sep 1, 2026

Copy link
Copy Markdown
Member

Summary

  • add persisted liquidity assets, quotes, swaps, provider controls, RPCs, and restart-safe actor orchestration
  • implement CKB Loop In and Loop Out chain/payment flows with the deployed liquidity-lock artifact and exact outpoint spend tracing
  • add real-process Bruno E2E coverage for CKB and UDT flows, provider-mode gating, malformed lock rejection, lock-time refund behavior, and provider restart recovery
  • harden Loop Out payout authorization, fee caps, invoice recovery, tracer registration, dynamic CI ports, and failure diagnostics

Test Plan

  • In-process CKB Loop Out, restart, and malicious payout E2Es
  • Bruno helper smoke suite: 7 requests, 10 tests, 20 assertions
  • Mutator workspace tests: 23 passed
  • tests/deploy/udt-init tests: 3 passed
  • Native liquidity/RPC suites and CKB Loop Out E2Es passed locally
  • cargo clippy --all-targets --all-features -p fnn -p fiber-bin -- -D warnings
  • cargo fmt --all -- --check
  • make check-migrate
  • make check-dirty-rpc-doc
  • Real Bruno suites require the CI CKB dev chain and FNN processes; local machine lacks the ckb binary

Follow-ups

  • UDT Loop Out payment propagation remains blocked by the existing payment-layer limitation and is documented in the suite README.
  • Refund RefundPending actor transition remains an M0 limitation and is documented in the refund suite README.

Closes #1541

@quake
quake marked this pull request as draft September 1, 2026 11:48
@chainTe

chainTe commented Sep 2, 2026

Copy link
Copy Markdown

Security Review

Result: 2 confirmed finding(s)
Reviewed range: c991b44e75994585a27eace794f37d2d64567df9..92ed7dd597234a6fbb657a5fd54b7737d6423e1d
Review model: grok-4.6

Validation:

  • Existing broad tests were not run locally; CI is expected to cover them.
  • Review was a local static source trace of the PR diff and the coupled liquidity-lock source at fiber-scripts@4da5d299.

Notes:

  • Critical: Loop In quote/import copies the client invoice payment_hash into lock args without requiring HashAlgorithm::CkbHash. liquidity-lock claim always checks blake2b_256(preimage). A Loop In client can present a Sha256 invoice, receive the Fiber payment, then refund the on-chain lock because the provider cannot claim. Bind Loop In invoices to CkbHash (including the omitted default) before persisting a quote.
  • High: Client Loop Out Fiber payment hardcodes udt_type_script: None while UDT quotes and provider invoices carry the UDT type script. Until SendPayment uses the quoted asset, fail closed on UDT Loop Out execution.
  • Quote envelopes and swap RPC records omit preimages. Observed payout live-cell checks match lock args, amount, and claimant/refund hashes. Missing Biscuit rules for liquidity methods fail closed when RPC auth is enabled.
  • liquidity-lock is not on fiber-scripts main; this review used the commit recorded by tests/deploy/contracts/README.md.

quake added 26 commits September 4, 2026 21:19
Add the liquidity Bruno suites to the E2E workflow as independent jobs:

- e2e-testing matrix gains liquidity/{ckb-loop-out,ckb-loop-in,udt-loop-out,
  udt-loop-in,udt-loop-in-rejection,provider-mode} entries. Each matrix job
  is a fresh VM, so the dev chain is always provisioned clean (fresh-VM run
  stands in for REMOVE_OLD_STATE=y; on a fresh VM the nilpotent
  init-dev-chain.sh performs the identical one-time provisioning).
- The rejection matrix entry needs the liquidity-lock-mutator sidecar: the
  job prebuilds it (cargo build --locked --manifest-path
  tests/liquidity-lock-mutator/Cargo.toml, target dir added to the build
  cache paths) and delegates to the suite's own run.sh, which starts the
  sidecar with its own PID, exports CKB_MUTATOR_URL, runs Bruno, and stops
  the sidecar on exit (no pkill).
- Dedicated e2e-liquidity-refund job: REMOVE_OLD_STATE=y provisioning via
  tests/nodes/start.sh, then the refund suite runner (mutator sidecar
  lifecycle owned by the runner; chain+nodes assumed running like the
  matrix suites).
- Dedicated e2e-liquidity-restart-recovery job: invokes
  restart-recovery/run-restart-test.sh directly; the supervisor provisions
  the clean dev chain, builds fnn, runs both phases with the provider
  restart in between.
- Dedicated e2e-liquidity-existing-state-rerun job: twice-run plan
  interpreted pragmatically - instead of running every suite twice, run
  ckb-loop-out once from a clean chain (REMOVE_OLD_STATE=y) and once more
  against the exact state the first run left behind (same chain and nodes,
  no reset), proving suite independence from prior state.
- On failure each job uploads tests/nodes/*.log plus the suite-written
  diagnostics (node/CKB snapshots, swap JSON, chain tx JSON) under
  tests/artifacts/liquidity/.
Follow-up to the liquidity E2E workflow jobs: actually write the failure
diagnostics the artifact upload steps expect under
tests/artifacts/liquidity/<suite>/, instead of only uploading
tests/nodes logs.

- New tests/bruno/scripts/collect-liquidity-failure-diagnostics.sh:
  best-effort collector that snapshots the CKB tip header plus, per node
  (client node1 / provider node2, RPC URL conventions 127.0.0.1:21714/21715,
  env-overridable), the list_swaps response (limit 0x64) and
  list_liquidity_chain_transactions for at most MAX_CHAIN_TX_SWAPS (default
  8) swap ids harvested from that list. The JSON is piped through
  write-liquidity-diagnostics.sh so sensitive fields are redacted, and
  lands in tests/artifacts/liquidity/<suite>/failure-<stamp>.json. RPC and
  parse errors degrade to null sections; the script exits 0 on partial
  failures and never masks the Bruno exit code.
- udt-loop-in-rejection/run.sh and refund/run.sh: on non-zero Bruno exit,
  invoke the collector (suite-scoped) while preserving the Bruno exit code
  via set +e capture and an explicit exit.
- e2e.yml: new if:failure() 'Collect liquidity failure diagnostics' step for
  the liquidity matrix entries (suite dir from matrix.workflow basename),
  so the happy-path and provider-mode entries write diagnostics even though
  Bruno itself cannot; rerun job wraps each Bruno run with set +e capture,
  collects diagnostics on failure, and exits with the stored code.
- Fix a latent path bug in both runners: repo_root was computed with four
  parent jumps, but tests/bruno/e2e/liquidity/<suite> sits five levels below
  the repo root, so the mutator path and the tests/bruno cd were both wrong
  (tests/tests/...). Use five jumps like restart-recovery's supervisor.

Validated with mock JSON-RPC servers: redaction applied, partial-failure
and all-endpoints-down runs exit 0 with files written, chain-tx fetches
bounded, and both runners preserve the injected Bruno exit code (7) while
writing diagnostics, writing nothing on the success path.
@quake
quake force-pushed the liquidity-management-m0 branch from fe736a8 to a7eed47 Compare September 4, 2026 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Design: Fiber liquidity management milestones

2 participants