Skip to content
This repository has been archived by the owner on Jan 10, 2025. It is now read-only.

Prepayment probing conflicts with LSPS2 (and JIT Channels in general) #44

Closed
ZmnSCPxj-jr opened this issue Aug 1, 2023 · 12 comments
Closed

Comments

@ZmnSCPxj-jr
Copy link
Contributor

ZmnSCPxj-jr commented Aug 1, 2023

As reported in the 2023-07-26 meeting, prepayment probing causes LSPS2 JIT channels to open prematurely.

Briefly, prepayment probing is a technique where a payer temporarily replaces the payment hash of an invoice with a randomly-generated one, then performs normal payment attempt. If the payment fails at the payee (client in LSPS2) with unknown_or_incorrect_payment_details, then the payer knows it was able to reach the payee with a specific fee paid to the routing nodes, and can with high probability reuse the same path with the correct payment hash to reach the payee.

The typical use-case is with a custodial wallet where the UI first shows "calculating LN fees" to the user while performing the prepayment probe. Then once the payment has reached the payee and gotten unknown_or_incorrect_payment_details failure, the UI displays the fee (which is deducted from the custodial user account) and a confirmation prompt whether to pay with the fee or not.

With JIT channels (not just LSPS2 specifically), there are two problems:

  • If the LSP knows the payment hash of the JIT payment, then the LSP issues the unknown_or_incorrect_payment_details failure, but the payer expects this failure to be issued by the payee (the client), not the LSP.
  • If the LSP does not know the payment hash of the JIT payment (as in LSPS2, in order to be compatible with keysend and future protocols that rely on a keysend-like protocol, like async receives), then the LSP opens a channel to the client and forwards the prepayment HTLC to the client, but then the client cannot claim the funds, resulting in the LSP being unable to charge the opening fee.

The latter is the problem we need to fix in LSPS2.

Here are solutions proposed so far:

  • LSPS4 Fixes This ™
    • Con: LSPS4 requires work to be done on the node software to expose onion decoding and re-encoding, and hopefully as well payment handling logic, to users of the LN software. MPP payment handling in particular is hard to expose (though I should note that LSPS4 allows clients to implement MPP, but clients themselves do not have to actually support it).
  • Send the onion+payment_hash in a notification to the client, and have client respond with a new API call lsps4.respond_to_htlc with either "ok" or "no, give this error" so that the client can send the unknown_or_incorrect_payment_details failure correctly.
    • Con: You probably need the same amount of work to be done on the node software to expose onion decoding and re-encoding (and hopefully as well payment handling logic) as in LSPS4 anyway.
    • Con: Depending on how this is implemented, may sacrifice MPP support. LSPS2 currently supports MPP if the client tells the LSP what the total amount is. If you implement MPP support then see LSPS4 PPP which is what you need to support MPP correctly while also supporting var-amount invoices.
  • Punt. Just add a warning to LSPs that the HTLC may fail and it should keep deducting the opening fee until it gets paid. Basically: if the LSP does not know the amount (which requires MPP-disabled) or the LSP receives a single HTLC that matches the amount (MPP enabled by payee but payer used non-MPP) then the LSP should be "lenient" and allow that HTLC to fail, but will deduct the opening_fee on any future HTLC until it gets paid. Then prioritize LSPS4 but still implement LSPS2 for simplicity first.
    • Con: Just because the prepayment probe succeeded does not mean that the user of the payer app will actually click "OK send the payment". In addition, the payment can still fail afterwards due to changes in liquidity in between getting incorrect_or_unknown_payment_details and doing the Real Payment (though presumably the payer app will loop here and re-attempt with a new prepayment probe to compute a new fee).
@kingonly
Copy link
Collaborator

kingonly commented Aug 2, 2023

There's also a simple workaround Breez and Muun are implementing currently: https://github.com/breez/lspd#probing-support

lightningnetwork/lnd#4785

@ZmnSCPxj-jr
Copy link
Contributor Author

ZmnSCPxj-jr commented Aug 3, 2023

There's also a simple workaround Breez and Muun are implementing currently: https://github.com/breez/lspd#probing-support

This still requires the LSP to know the payment hash, which is not compatible with keysend-style payments (and therefore asynchronous payments), has the error unknown_or_incorrect_payment_details arise from the LSP hop instead of the final payee (violates BOLT spec), and requires that payers implement this kind of probing as opposed to just a random payment_hash. LSPS4 remains a more complete solution.

An even simpler (non-)solution of the same style would be to just have the client always give every payment hash it issues to the LSP, and if the LSP receives a payment hash outside of the set given by the client, give the same error as that proposal. No need to modify payers to use SHA256("probing-01"|payment_hash). Because for the LSP to recognize this the client has to hand over the payment_hash anyway. At least that way payers do not have to be modified.

@yaslama
Copy link
Collaborator

yaslama commented Aug 3, 2023

We can add a field jit_channel_probing_scid in the return object of lsps2.buy and this scid will be used for the probing.

@ZmnSCPxj-jr
Copy link
Contributor Author

ZmnSCPxj-jr commented Aug 6, 2023

We can add a field jit_channel_probing_scid in the return object of lsps2.buy and this scid will be used for the probing.

It is the payer which does probing. Often the way the payer learns anything from the payee (client in this case) is via BOLT11 invoice. Are you proposing to add a new bespoke BOLT11 field for this? That seems like an even harder solution; now you have to convince everyone to add such a field to BOLT11 invoices, not just payers but probably needs more feedback from the wider set of users of BOLT11.

@yaslama
Copy link
Collaborator

yaslama commented Aug 6, 2023

We can add a field jit_channel_probing_scid in the return object of lsps2.buy and this scid will be used for the probing.

It is the payer which does probing. Often the way the payer learns anything from the payee (client in this case) is via BOLT11 invoice. Are you proposing to add a new bespoke BOLT11 field for this? That seems like an even harder solution; now you have to convince everyone to add such a field to BOLT11 invoices.

The payee can send two invoices to the payer or better let jit_channel_probing_scid be calculated from jit_channel_scid (for instance by xoring the 3 bytes of the tx index to 0xffffff). So the LSP can always detect that it's a probing for a specific channel request.

@ZmnSCPxj-jr
Copy link
Contributor Author

The payee can send two invoices to the payer or better let jit_channel_probing_scid be calculated from jit_channel_scid (for instance by xoring the 3 bytes of the tx index to 0xffffff). So the LSP can always detect that it's a probing for a specific channel request.

Still needs a payer implementation change. It is better if we adapt to existing payer implementations than to force payer implementations to adapt to us.

@kingonly
Copy link
Collaborator

kingonly commented Aug 7, 2023

Still needs a payer implementation change. It is better if we adapt to existing payer implementations than to force payer implementations to adapt to us.

Depends on the alternative. The probing landscape is pretty clear: Strike, Galoy, Binance and perhaps a couple of more. It's very manageable and we were able to work with them to adopt the payer implementations. If there's a BLIP, I don't think this would be an issue.

@kingonly
Copy link
Collaborator

kingonly commented Aug 15, 2023

lnd is now documenting this for private channel probing: https://docs.lightning.engineering/lightning-network-tools/lnd/payments#prepay-probes-to-private-wallets

Binance has agreed to implement it and Galoy are already implementing it. I think it's a good enough solution.

@ZmnSCPxj-jr
Copy link
Contributor Author

@kingonly looks good. Still, I think having some text, in case someone else implements naive probing that goes all the way to the payee.

@tnull
Copy link
Collaborator

tnull commented Sep 11, 2023

lnd is now documenting this for private channel probing: https://docs.lightning.engineering/lightning-network-tools/lnd/payments#prepay-probes-to-private-wallets

Binance has agreed to implement it and Galoy are already implementing it. I think it's a good enough solution.

Note that the corresponding paragraphs are somehow gone from the LND docs (cf. https://docs.lightning.engineering/lightning-network-tools/lnd/payments#prepay-probes)

@kingonly
Copy link
Collaborator

Note that the corresponding paragraphs are somehow gone from the LND docs (cf. https://docs.lightning.engineering/lightning-network-tools/lnd/payments#prepay-probes)

I believe this because lnd decided to implement it as part of their estimatefee.

@tnull
Copy link
Collaborator

tnull commented Jan 10, 2025

Closing this as this repository will be archived shortly. Please reopen on the bLIP repository if still relevant.

@tnull tnull closed this as completed Jan 10, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
4 participants