Skip to content

fix(cch): check HTLC expiry delta before sending outgoing payment#1148

Open
doitian wants to merge 4 commits intonervosnetwork:developfrom
doitian:safe-cch-expiry-check-before-sending-payment
Open

fix(cch): check HTLC expiry delta before sending outgoing payment#1148
doitian wants to merge 4 commits intonervosnetwork:developfrom
doitian:safe-cch-expiry-check-before-sending-payment

Conversation

@doitian
Copy link
Member

@doitian doitian commented Feb 26, 2026

Summary

Add a dynamic expiry check when dispatching outgoing payments to prevent fund loss when the outgoing route's total expiry (including all routing hops) exceeds the incoming payment's remaining time.

Problem

Previously, CCH only compared final_tlc_expiry_delta values statically at order creation time. This missed the scenario described in #1000: if there are many routing nodes for the outbound payment, the accumulated tlc_expiry_delta of the entire route can exceed the inbound.final_tlc_expiry_delta, causing the inbound payment to expire before CCH can settle it.

Solution

When dispatching the outgoing payment (after incoming is accepted):

  1. Compute remaining incoming time: incoming_final_expiry_delta - elapsed_since_order_creation
  2. Allocate half for outgoing: max_outgoing = remaining / 2 (other half reserved for settling incoming)
  3. Validate sufficiency: If max_outgoing is less than the outgoing invoice's minimum final expiry delta, fail the order immediately
  4. Cap the outgoing route:
    • BTC (LND): Set cltv_limit on SendPaymentRequest
    • CKB (Fiber): Set tlc_expiry_limit on SendPaymentCommand

Tests

  • test_send_btc_fails_insufficient_expiry_delta — SendBTC order with insufficient remaining incoming time
  • test_receive_btc_fails_insufficient_expiry_delta — ReceiveBTC order with outgoing CKB TLC expiry exceeding available time
  • test_send_btc_passes_sufficient_expiry_delta — Verifies valid orders pass the check

Fixes #1000

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a dynamic HTLC/TLC expiry-budget check at outgoing-payment dispatch time to prevent cross-chain fund loss when the total outbound route timelock exceeds the remaining inbound timelock (issue #1000).

Changes:

  • Compute remaining inbound expiry time at dispatch time and reserve half for settling inbound after preimage receipt.
  • Enforce a route-wide expiry cap on outgoing payments (LND cltv_limit, Fiber tlc_expiry_limit) and fail orders early when insufficient.
  • Add/update specs documentation and introduce new actor tests covering insufficient/sufficient expiry scenarios.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
docs/specs/cch-expiry-dependency.md Documents the new dynamic outgoing route-expiry cap and the reasoning behind it.
crates/fiber-lib/src/cch/actions/send_outgoing_payment.rs Implements remaining-time computation, sufficiency validation, and route-expiry caps for outbound payments.
crates/fiber-lib/src/cch/tests/actor_tests.rs Adds harness configurability and tests for failure/success cases around the new expiry logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@doitian doitian force-pushed the safe-cch-expiry-check-before-sending-payment branch from 87f4514 to 1d3039c Compare March 2, 2026 06:35
@quake
Copy link
Member

quake commented Mar 3, 2026

@doitian need to resolve conflicts

@doitian doitian force-pushed the safe-cch-expiry-check-before-sending-payment branch 2 times, most recently from bfbc2b0 to 7ad93ff Compare March 3, 2026 07:33
doitian added 4 commits March 5, 2026 12:42
…rvosnetwork#1000)

Add a dynamic expiry check when dispatching outgoing payments to prevent
fund loss when the outgoing route's total expiry exceeds the incoming
payment's remaining time.

Previously, CCH only compared final_tlc_expiry_delta values statically
at order creation. This missed the case where multiple routing hops
accumulate enough expiry delta to exceed the incoming payment's expiry.

Changes:
- Compute remaining incoming time and allocate half for outgoing route
- Fail the order if remaining time is insufficient for outgoing invoice's
  minimum final expiry delta
- Set cltv_limit (LND) and tlc_expiry_limit (Fiber) on outgoing payments
  to cap the route expiry

Tests:
- test_send_btc_fails_insufficient_expiry_delta
- test_receive_btc_fails_insufficient_expiry_delta
- test_send_btc_passes_sufficient_expiry_delta

Fixes nervosnetwork#1000
@doitian doitian force-pushed the safe-cch-expiry-check-before-sending-payment branch from 7ad93ff to 7e622ea Compare March 5, 2026 04:54
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.

[cch] Insufficient HTLC Expiry Delta Check

3 participants