LND: Generate non-standard forwards... to implement Lightning Service Provide Specification #2 (LSPS2) #8882
Replies: 4 comments 3 replies
-
In lspd I made a PR for LSPS2 on top of LND here: breez/lspd#149 It does lean on a fork of LND with the following rpc modifications:
You can't use SendToRouteV2, because you don't have the payment secret. Only the sender and the recipient know this. So you'll have to forward the original onion sent by the sender in order to get the payment to settle. The part of lspd that does the onion rewriting is for breezmobile. For LSPS2 there is no need to rewrite the onion blob, only the lower amount and new short channel id have to be passed to LND. I believe the diff for that is fairly small: breez@5f0a699 |
Beta Was this translation helpful? Give feedback.
-
Thanks much. Obviously would rather not fork LND but unless we find a cleaner solution, we'll use this. |
Beta Was this translation helpful? Give feedback.
-
@JssDWt Thanks for the diff ( breez@5f0a699 ) you provided, which will be very useful. I wanted to see if you agreed with this idea: In addition to your proposed modifications, the forked LND must incorporate additional changes, which will be necessary in order to protect against payment probes, as well as possible malicious attacks against the LSP, where clients attempt to open many channels and never settle the paying invoices. HERE IS MY REASONING: I'm hoping you could look at it and tell me if I've got something wrong..... At the top of the page, here: https://github.com/BitcoinAndLightningLayerSpecs/lsp/tree/main/LSPS2#lsps2-jit-channel-negotiation
So, to be safe, a "Client trusts LSP" model is necessary. Given that, near the bottom of LSPS2, we find this:
So: Both peers must send I don't see anything in the LND API that would allow us to open a channel, but then "sit" on that channel, and not broadcast the funding transaction to the mempool until a later time.... So: A further addition to the proposed fork to LND would be required (am I right about this?): NEW CODE THAT MUST BE RUNNING IN THE FORKED LND: This Line 2676 in d7e0f69 .... must conditionally NOT run, .... if the channel is LSPS2 related... then in this case... . instead of immediately running PublishTransaction , we take the the data will be necessary to run PublishTransaction in the FUTURE... and persist it to our own database.... and then run a sendChannelReady Line 3163 in d7e0f69 PROPOSED SEQUENCE OF EVENTS FOR CHANNEL OPENING:
In this way, the LSP would be protected from spurious payments (which the client will refuse to settle), and also would be protected from from payment probes (which will never settle). |
Beta Was this translation helpful? Give feedback.
-
I haven't read the full thread here, just wanted to point out this PR which might be useful for this situation (or parts of it): #8633 The above PR is currently merged to the |
Beta Was this translation helpful? Give feedback.
-
The Challenge: "non-standard" forwards
We're working on implementing an "LSP-side" implementation of LSPS2.
LSPS2 goes a long way to solving the "chicken or egg" problem where a wallet user needs a lightning channel, but doesn't already have onchain funds or funds in an existing Lightning channel to pay for a channel.
LDK's client-side solution for LSPS2 is exceptionally elegant. It requires just two functions...
node.set_liquidity_source_lsps2
andnode.bolt11_payment().receive_via_jit_channel
. This proof of concept works perfectly in our initial tests, and should be a really easy way for mobile wallet developers to incorporate an LSP.The challenge... building the "LSP-side" implementation of LSPS2 that will work with LND. This is critical, as most of the biggest liquidity sources on the Lightning Network are running LND. (Like our nodes, for example.)
"LSP-side" LSPS2 is rather complicated, but we have the implementation nearly finished, and up to this point have been able to do everything using just Alex Bosworth's lightning library, and our own custom code with NodeJS, Postgres, and Redis.
We're REALLY close to finishing this, but we have a blocker right at this point in the specification:
Currently, we are intercepting the forwards with subscribeToForwardRequests.
We can intercept and log the forwards without problems.... but... Currently this
subscribeToForwardRequests
function only allows for.accept()
or.reject()
or.settle()
.So our challenge is to figure out how to "generate non-standard forwards" and send these to the client node.
Here is where we are with our research.
Can we use existing LND APIs?
Could the SendToRouteV2 API work? Would it be as simple as modifying the payment hash, and then sending it?
Do we need to drop down into Go to use internal LND functions?
Here is an example from Breez's LSPD library, where they use a function to construct an onion and then send it.
Is this something similar to what we need to do?
LDK has already implemented this
LDK already has an "LSP-side" implementation for LSPS2.
In LDK's
channelmanager.rs
, the pub fn forward_intercepted_htlc seems to do exactly what we need, specifically this code, which I think satisfies thisThe LSP generates non-standard forwards, where the amount received by the client is smaller than specified in the onion;
line in the specification:Similar code is here, in the lightning-liquidity crate.
So: Does anyone have any suggestions for a strategy we should look at for LND?
thanks!
Beta Was this translation helpful? Give feedback.
All reactions