Matt Corallo [ARCHIVE] on Nostr: 📅 Original date posted:2021-10-13 📝 Original message: I'm sure most of y'all ...
📅 Original date posted:2021-10-13
📝 Original message:
I'm sure most of y'all are familiar with this problem by now - a lightning user on a phone trying to
pay another lightning user on a phone requires some amount of coordination to ensure the sender and
recipient are, roughly, online at the same time.
Invoices provide this somewhat today by requiring the recipient provide some live-ish data to the
sender with their phone in their hand.
But for some reason those pesky users keep wanting to use lightning for tips, or at least accept
payment on their phones without keeping them unlocked with the lightning app open on the foreground
24/7.
There's a few things live today which make progress towards this goal, but don't quite get there
(and mostly aren't trying to solve this problem, but are worth mentioning):
* just have the recipient use a custodial product/run a full lightning node at home on an RPi.
Obviously this has some pretty substantial drawbacks, I'm not sure I even need to list them, but
the "just require the recipient use a custodial service" is what Twitter ended up shipping with for
lightning tipping, and we should all probably feel ashamed that they felt the need to do that.
* Blockstream Greenlight.
This change the online-requirements model - with the keys on your phone/elsewhere you still have
to have your phone online with the same requirements as running a full lightning node. It just means
fewer resources on that device.
* use keysend/AMP/whatever.
This is great for tips, but only half the story. Sender goes to send a keysend payment, gets to
one hop before the recipient, and then a day later the recipient comes online to find the payment
long-since timed out and failed backwards. Or you could use a long CLTV on the payment to make sure
the recipient has time to claim it, which is basically a DoS on the lightning network's capacity,
one that may eventually be fixed, breaking your payments, and which is just generally antisocial.
Still, my understanding is some folks do this today cause its the only option for a mobile device.
* lnurl
...is a great way to get an invoice, presumably from a trusted LSP for the recipient, trusting
them to not give the same invoice twice, but doesn't help the recipient receive the payment, they
still need to be online, unless...
* have a fully-trusted LSP that accepts payments and forwards them later
this is also fine, where its practical, I guess, but I'd hope we can do better. Worse, as far as
I understand the places where this is practical are becoming fewer and fewer as the regulatory
uncertainty clears and everyone realizes the regulatory overhead of this is...well you might as well
start applying for that banking charter now.
* have an untrusted LSP that sends you a notification to open the app when a payment is received
Several lightning apps do this today, and its somewhat of a stop-gap but does help. On platforms
where the app gets some meager CPU time in response to a notification, this can even fully solve the
problem by claiming the HTLC in response to the notification pushed out-of-band. Sadly, the refrain
I've heard repeatedly is, these days, on both Android and especially iOS, you can't even rely on a
microsecond of CPU time in response to a notification. The OS fully expects your app to run code
only when its on and in the foreground, unless you're a VoIP app you're screwed. Relying on the user
to open the app immediately when they receive a notification is...fine, I guess, absent a better
idea it seems like the best we've got today, but I'm not sure you'd find a UX designer who would
*suggest* this :).
But what would it take to do better? What follows is a simple straw-man, but something that's
borderline practical today and may at least generate a few ideas. It comes in two variants
If we accept the lnurl trust model of "a third-party I can give a list of pre-signed invoices, which
I trust to never provide an invoice twice, but otherwise is untrusted", then we could do something
like this:
Step 1. Tipper gets an invoice from the lnurl endpoint they wish to pay, which contains some
"recipient is behind an LSP and rarely online, act accordingly" flag.
Step 2. Tipper sender sends a HTLC with a long CLTV timeout to their own LSP with instructions
saying "when you get an onion message telling you nonce B, forward this HTLC, until then, just sit
on it". The LSP accepts this HTLC but does not forward it and is generally okay with the long CLTV
delta because it would otherwise just be the users' balance anyway - if they want to encumber their
own funds forever, no harm done.
Note that if tipper is online regularly they can skip this step and move on.
Step 3. The Tipper sends an onion message to recipient's LSP saying "hey, when recipient is online
again, use the included reply path to send nonce B to my LSP".
- sender can now safely go offline -
Step 4. When the Recipient comes online, their LSP sends the reply to the Tipper's LSP,
Step 5. causing the Tipper's LSP to (finally) forward the original HTLC, which the Recipient receives.
You'll note that this solution, unlike simply sending a high-CLTV HTLC, does not encumber funds for
any extended period of time except for the original sender, who wants to send the funds off
elsewhere anyway. Nor does it rely on any parties who can at any point run away with the funds (or
reasonably be construed as custodians for the funds). Further, this solution does not rely on the
sender deanonymizing themselves to the recipient (or even informing the recipient who the senders'
LSP is).
Note that lnurl here could be replaced with BOLT 12 if BOLT 12 gets some flag indicating the Tipper
should ask an LSP for the invoice.
But, okay, so the lnurl model of a trusted party not reusing invoices so that the Recipient's LSP
cannot just steal all funds after the first claim kinda really sucks, how do we do better?
The Obvious (tm) solution here is PTLCs - just have the sender always add some random nonce * G to
the PTLC they're paying and send the recipient a random nonce in the onion. I'd generally suggest we
just go ahead and do this for every PTLC payment, cause why not? Now the sender and the lnurl
endpoint have to collude to steal the funds, but, like, the sender could always just give the lnurl
endpoint the money. I'd love suggestions for fixing this short of PTLCs, but its not immediately
obvious to me that this is possible.
Thanks to Steve for pushing on the "how does a let users get tips in lightning" issue, various
people for giving him feedback and the relayed to me, AJ for the PTLC proposal, and Rusty for
tireless drum-beating on onion messages and BOLT 12.
Matt
📝 Original message:
I'm sure most of y'all are familiar with this problem by now - a lightning user on a phone trying to
pay another lightning user on a phone requires some amount of coordination to ensure the sender and
recipient are, roughly, online at the same time.
Invoices provide this somewhat today by requiring the recipient provide some live-ish data to the
sender with their phone in their hand.
But for some reason those pesky users keep wanting to use lightning for tips, or at least accept
payment on their phones without keeping them unlocked with the lightning app open on the foreground
24/7.
There's a few things live today which make progress towards this goal, but don't quite get there
(and mostly aren't trying to solve this problem, but are worth mentioning):
* just have the recipient use a custodial product/run a full lightning node at home on an RPi.
Obviously this has some pretty substantial drawbacks, I'm not sure I even need to list them, but
the "just require the recipient use a custodial service" is what Twitter ended up shipping with for
lightning tipping, and we should all probably feel ashamed that they felt the need to do that.
* Blockstream Greenlight.
This change the online-requirements model - with the keys on your phone/elsewhere you still have
to have your phone online with the same requirements as running a full lightning node. It just means
fewer resources on that device.
* use keysend/AMP/whatever.
This is great for tips, but only half the story. Sender goes to send a keysend payment, gets to
one hop before the recipient, and then a day later the recipient comes online to find the payment
long-since timed out and failed backwards. Or you could use a long CLTV on the payment to make sure
the recipient has time to claim it, which is basically a DoS on the lightning network's capacity,
one that may eventually be fixed, breaking your payments, and which is just generally antisocial.
Still, my understanding is some folks do this today cause its the only option for a mobile device.
* lnurl
...is a great way to get an invoice, presumably from a trusted LSP for the recipient, trusting
them to not give the same invoice twice, but doesn't help the recipient receive the payment, they
still need to be online, unless...
* have a fully-trusted LSP that accepts payments and forwards them later
this is also fine, where its practical, I guess, but I'd hope we can do better. Worse, as far as
I understand the places where this is practical are becoming fewer and fewer as the regulatory
uncertainty clears and everyone realizes the regulatory overhead of this is...well you might as well
start applying for that banking charter now.
* have an untrusted LSP that sends you a notification to open the app when a payment is received
Several lightning apps do this today, and its somewhat of a stop-gap but does help. On platforms
where the app gets some meager CPU time in response to a notification, this can even fully solve the
problem by claiming the HTLC in response to the notification pushed out-of-band. Sadly, the refrain
I've heard repeatedly is, these days, on both Android and especially iOS, you can't even rely on a
microsecond of CPU time in response to a notification. The OS fully expects your app to run code
only when its on and in the foreground, unless you're a VoIP app you're screwed. Relying on the user
to open the app immediately when they receive a notification is...fine, I guess, absent a better
idea it seems like the best we've got today, but I'm not sure you'd find a UX designer who would
*suggest* this :).
But what would it take to do better? What follows is a simple straw-man, but something that's
borderline practical today and may at least generate a few ideas. It comes in two variants
If we accept the lnurl trust model of "a third-party I can give a list of pre-signed invoices, which
I trust to never provide an invoice twice, but otherwise is untrusted", then we could do something
like this:
Step 1. Tipper gets an invoice from the lnurl endpoint they wish to pay, which contains some
"recipient is behind an LSP and rarely online, act accordingly" flag.
Step 2. Tipper sender sends a HTLC with a long CLTV timeout to their own LSP with instructions
saying "when you get an onion message telling you nonce B, forward this HTLC, until then, just sit
on it". The LSP accepts this HTLC but does not forward it and is generally okay with the long CLTV
delta because it would otherwise just be the users' balance anyway - if they want to encumber their
own funds forever, no harm done.
Note that if tipper is online regularly they can skip this step and move on.
Step 3. The Tipper sends an onion message to recipient's LSP saying "hey, when recipient is online
again, use the included reply path to send nonce B to my LSP".
- sender can now safely go offline -
Step 4. When the Recipient comes online, their LSP sends the reply to the Tipper's LSP,
Step 5. causing the Tipper's LSP to (finally) forward the original HTLC, which the Recipient receives.
You'll note that this solution, unlike simply sending a high-CLTV HTLC, does not encumber funds for
any extended period of time except for the original sender, who wants to send the funds off
elsewhere anyway. Nor does it rely on any parties who can at any point run away with the funds (or
reasonably be construed as custodians for the funds). Further, this solution does not rely on the
sender deanonymizing themselves to the recipient (or even informing the recipient who the senders'
LSP is).
Note that lnurl here could be replaced with BOLT 12 if BOLT 12 gets some flag indicating the Tipper
should ask an LSP for the invoice.
But, okay, so the lnurl model of a trusted party not reusing invoices so that the Recipient's LSP
cannot just steal all funds after the first claim kinda really sucks, how do we do better?
The Obvious (tm) solution here is PTLCs - just have the sender always add some random nonce * G to
the PTLC they're paying and send the recipient a random nonce in the onion. I'd generally suggest we
just go ahead and do this for every PTLC payment, cause why not? Now the sender and the lnurl
endpoint have to collude to steal the funds, but, like, the sender could always just give the lnurl
endpoint the money. I'd love suggestions for fixing this short of PTLCs, but its not immediately
obvious to me that this is possible.
Thanks to Steve for pushing on the "how does a let users get tips in lightning" issue, various
people for giving him feedback and the relayed to me, AJ for the PTLC proposal, and Rusty for
tireless drum-beating on onion messages and BOLT 12.
Matt