Skip to content

refactor(swap): replace atomic two-leg intercept with HODL-invoice flow#4

Draft
Arshia-r-m wants to merge 1 commit into
codex/hodl-invoice-pr-91from
feat/swaps-with-hodl
Draft

refactor(swap): replace atomic two-leg intercept with HODL-invoice flow#4
Arshia-r-m wants to merge 1 commit into
codex/hodl-invoice-pr-91from
feat/swaps-with-hodl

Conversation

@Arshia-r-m

Copy link
Copy Markdown
Member

The previous swap mechanism required three coordinated calls (maker_init → taker whitelist → maker_execute) and a custom HTLCIntercepted path keyed on an IS_SWAP_SCID flag to fire both legs atomically.

Swaps now use a HODL BOLT11 invoice plus a forward keysend:

  • maker_init takes a taker_pubkey, generates its own preimage, builds a HODL invoice for qty_from, and stores the swap (taker_pubkey lives in SwapInfo at TLV 5, and the swapstring is extended to 7 fields).
  • The taker pays the invoice with plain /sendpayment — no whitelist.
  • On PaymentClaimable for a maker-swap HODL, the maker validates the incoming amount and fires a single-leg spontaneous payment (carrying the RGB asset when qty_to is RGB) to taker_pubkey, encoding the HODL hash in PaymentId so the follow-up events can correlate.
  • PaymentSent on the forward leg triggers claim_funds on the HODL; PaymentClaimed finalises the swap and updates the RGB channel balance. PaymentFailed (or an immediate send failure) calls fail_htlc_backwards to refund the taker and marks the swap Failed.

Deletes maker_execute, the /taker whitelist requirement (the endpoint is kept for optional taker-side bookkeeping), the HTLCIntercepted swap branch, IS_SWAP_SCID, and the swap_roundtrip_fail_whitelist test. Also drops a handful of now-dead helpers (get_route, Router/Scorer type aliases, DEFAULT_FINAL_CLTV_EXPIRY_DELTA, the UnlockedAppState.router field) that were only reachable from the removed paths.

All swap tests are rewritten around the new helpers (taker_pay_invoice replaces taker + maker_execute) and channel- balance assertions are updated to reflect that each leg is now a separate LN payment with a single forwarding fee at the middle hop (and sub-dust receiver balances for tiny-msat forward legs).

Trade-off: the atomic two-HTLC property is gone. If the maker crashes after the HODL is claimable but before claim_funds runs, manual recovery via the existing claim_hodl_invoice endpoint is required — the standard HODL-invoice tradeoff.

Verified: cargo build --tests is warning-free; all 17 swap tests pass (1003s wall time).

The previous swap mechanism required three coordinated calls
(maker_init → taker whitelist → maker_execute) and a custom
HTLCIntercepted path keyed on an IS_SWAP_SCID flag to fire both
legs atomically.

Swaps now use a HODL BOLT11 invoice plus a forward keysend:

  * maker_init takes a taker_pubkey, generates its own preimage,
    builds a HODL invoice for qty_from, and stores the swap
    (taker_pubkey lives in SwapInfo at TLV 5, and the swapstring
    is extended to 7 fields).
  * The taker pays the invoice with plain /sendpayment — no
    whitelist.
  * On PaymentClaimable for a maker-swap HODL, the maker validates
    the incoming amount and fires a single-leg spontaneous payment
    (carrying the RGB asset when qty_to is RGB) to taker_pubkey,
    encoding the HODL hash in PaymentId so the follow-up events
    can correlate.
  * PaymentSent on the forward leg triggers claim_funds on the
    HODL; PaymentClaimed finalises the swap and updates the RGB
    channel balance. PaymentFailed (or an immediate send failure)
    calls fail_htlc_backwards to refund the taker and marks the
    swap Failed.

Deletes maker_execute, the /taker whitelist requirement (the
endpoint is kept for optional taker-side bookkeeping), the
HTLCIntercepted swap branch, IS_SWAP_SCID, and the
swap_roundtrip_fail_whitelist test. Also drops a handful of
now-dead helpers (get_route, Router/Scorer type aliases,
DEFAULT_FINAL_CLTV_EXPIRY_DELTA, the UnlockedAppState.router
field) that were only reachable from the removed paths.

All swap tests are rewritten around the new helpers
(taker_pay_invoice replaces taker + maker_execute) and channel-
balance assertions are updated to reflect that each leg is now
a separate LN payment with a single forwarding fee at the middle
hop (and sub-dust receiver balances for tiny-msat forward legs).

Trade-off: the atomic two-HTLC property is gone. If the maker
crashes after the HODL is claimable but before claim_funds runs,
manual recovery via the existing claim_hodl_invoice endpoint is
required — the standard HODL-invoice tradeoff.

Verified: cargo build --tests is warning-free; all 17 swap tests
pass (1003s wall time).
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.

1 participant