Skip to content

Support client_trusts_lsp on LSPS2#3838

Merged
TheBlueMatt merged 1 commit intolightningdevkit:mainfrom
martinsaposnic:client-trusts-lsp
Sep 26, 2025
Merged

Support client_trusts_lsp on LSPS2#3838
TheBlueMatt merged 1 commit intolightningdevkit:mainfrom
martinsaposnic:client-trusts-lsp

Conversation

@martinsaposnic
Copy link
Copy Markdown
Contributor

@martinsaposnic martinsaposnic commented Jun 9, 2025

The feature

lightningdevkit/ldk-node#479

Currently, our LSPS2 service implementation only supports the lsp_trusts_client model, which means that "If the client does not claim the payment, and the funding transaction confirms, then the LSP will have its funds locked in a channel that was not paid for."

On a client_trusts_lsp model, the LSP will NOT broadcast the funding transaction until the client claims the payment.

The plan:

(This plan was validated and acknowledged by @tnull in private). There are differences between the plan and the implementation, but it roughly describes the approach.

  • LSPS2 Process & Events:
These are handled the same way as before. No changes here.

  • When the OpenChannel event is emitted, ldk-node calls create_channel as usual. The key difference is: If client_trusts_lsp = true, after emitting the OpenChannel event, we start tracking the HTLC that our client will eventually claim.

  • Funding Transaction Broadcast Logic:
The batch_funding_transaction_generated_intern function decides whether the funding transaction should be broadcast automatically. There are two existing funding types:

    • Checked: Validates and auto-broadcasts.
    • Unchecked: Skips validation and requires manual broadcast.

    I will introduce a third type:

    • CheckedManualBroadcast: Validates, but sets manual broadcast.
  • With this:

    • If client_trusts_lsp = false, ldk-node uses funding_transaction_generated (default behavior).
    • If client_trusts_lsp = true, it uses funding_transaction_generated_with_delayed_broadcast, which sets the funding type to CheckedManualBroadcast (validates but sets manual broadcast).
  • lsps2_service on
ldk-node will now interact with lsps2_service on rust-lightning in two new key moments:

    • When it receives the FundingTxBroadcastSafe event, it notifies lsps2_service on rust-lightning, which marks a flag as true.
    • When the client claims the HTLC (::PaymentClaimed), ldk-node notifies lsps2_service on rust-lightning, which marks another flag as true.
    • Once both flags are true, we are ok to proceed to broadcast the funding transaction.

Changes:

  • a new FundingType called CheckedManualBroadcast, which behaves the same as the FundingType::Checked, but it returns false when is_manual_broadcast is called. Essentially, it validates everything (same as the FundingType::Checked) but it does not automatically broadcast (same as FundingType::Unchecked)
  • new public function funding_transaction_generated_manual_broadcast on channel_manager. Uses FundingType::CheckedManualBroadcast, which validates but does not automatically broadcast
  • new public function channel_needs_manual_broadcast. This is used by ldk-node to know if funding_transaction_generated or funding_transaction_generated_manual_broadcast should be called when FundingGenerationReady event is triggered
  • new public function store_funding_transaction. This is used by ldk-node when the funding transaction is created. We need to store it because the broadcast of the funding transaction may be deferred.
  • new public function funding_tx_broadcast_safe. This is used by ldk-node when the FundingTxBroadcastSafe event is triggered
  • a new enum TrustModel is introduced, which depending on the trust model that the user chose, it will have a few properties to track:
    • if the client claimed the htlc,
    • the status of funding_tx_broadcast_safe.
    • hold the funding_tx for later use
  • This new TrustModel enum will be created when the OpenChannel is triggered, and will be saved in the OutboundJITChannelState
  • Every time the TrustModel changes values, the function broadcast_transaction_if_applies is called, so it checks if it's time to broadcast the funding transaction
  • An unsafe_broadcast_transaction function is also introduced on channel_manager, which will be called by broadcast_transaction_if_applies from the lsps2/service

LDK Node integration

In this PR lightningdevkit/ldk-node#572 on ldk-node, you can see that 2 tests are created that demonstrates the funcionality described above.

  • First test:

client_trusts_lsp=true

In the test, receive_via_jit_channel_manual_claim is called, the mempool is checked to assert that the funding transaction was not broadcasted yet (it should not because client_trusts_lsp=true, and the client has not claimed the htlc yet).

Then the client calls claim_for_hash, and the mempool is checked again, and now the funding transaction should be there

  • Second test:

client_trusts_lsp=false

In the test, receive_via_jit_channel_manual_claim is called, the mempool is checked to assert that the funding transaction was broadcasted (because the LSP trusts the client), even though the client has not claimed the htlc yet. In this case, the LSP was tricked, and it will have its funds locked in a channel that was not paid for.

Side note: for the tests to work I had to create a new receive_via_jit_channel_manual_claim so the client can manually claim the htlc using the claim_for_hash.

Loading
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.

4 participants