[Lightning-dev] Opening balanced channels using PSBT

2021-09-21 Thread Ole Henrik Skogstrøm
Hi

I have found a way of opening balanced channels using LND's psbt option
when opening channels. What I'm doing is essentially just joining funded
PSBTs before signing and submitting them. This makes it possible to open a
balanced channel between two nodes or open a ring of balanced channels
between multiple nodes (ROF).

I found this interesting, however I don't know if this is somehow unsafe or
for some other reason a bad idea. If not, then it could be an interesting
alternative to only being able to open unbalanced channels.

To do this efficiently, nodes need to collaborate by sending PSBTs back and
forth to each other and doing this manually is a pain, so if this makes
sense to do, it would be best to automate it through a client.

--
--- Here is an example of the complete flow for a single channel:
--

** Node A: generates a new address and sends address to Node B *(lncli
newaddress p2wkh)

** Node A starts an Interactive channel **open** to Node B* *using psbt*
(lncli openchannel --psbt  200 100)

** Node A funds the channel address *(bitcoin-cli walletcreatefundedpsbt []
'[{"":0.02}]')

** Node B funds the refund transaction to Node A and sends PSBT back to
Node A (*bitcoin-cli walletcreatefundedpsbt []
'[{"":0.01}]')

* *Node A joins the two PSBTs and sends it back to Node B (*bitcoin-cli
joinpsbts '["", ""]')

** Node B verifies the content and signs the joined PSBT before sending it
back to Node A *(bitcoin-cli walletprocesspsbt )

** Node A: Verifies the content and signs the joined PSBT *(bitcoin-cli
walletprocesspsbt )

** Node A: Completes channel open by publishing the fully signed PSBT*


--
--- Here is an example of the complete flow for a ring of channels between
multiple nodes:
--

** Node A starts an Interactive open channel to Node B using psbt* (lncli
openchannel --psbt --no_publish  200 100)
** Node A funds the channel address* (bitcoin-cli walletcreatefundedpsbt []
'[{"":0.02}]')

** Node B starts an Interactive open channel to Node C using psbt* (lncli
openchannel --psbt --no_publish  200 100)
** Node B funds the channel address* (bitcoin-cli walletcreatefundedpsbt []
'[{"":0.02}]')

** Node C starts an Interactive open channel to Node A using psbt* (lncli
openchannel --psbt  200 100)
** Node C funds the channel address *(bitcoin-cli walletcreatefundedpsbt []
'[{"":0.02}]')

** Node B and C sends Node A their PSBTs*

** Node A joins all the PSBTs* (bitcoin-cli joinpsbts
'["", "",
""]')

Using (bitcoin-cli walletprocesspsbt ):



** Node A verifies and signs the PSBT and sends it to Node B (1/3
signatures)* Node B verifies and signs the PSBT and sends it to Node C (2/3
signatures)* Node C verifies and signs the PSBT (3/3 signatures) before
sending it to Node A and B.*


** Node A completes channel open (no_publish)* Node B completes channel
open (no_publish)* Node C completes channel open and publishes the
transaction.*

--
Ole Henrik Skogstrøm
___
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev


Re: [Lightning-dev] Stateless invoices with proof-of-payment

2021-09-21 Thread Joost Jager
On Tue, Sep 21, 2021 at 5:47 PM Bastien TEINTURIER  wrote:

> Hi Joost,
>
> Concept ACK, I had toyed with something similar a while ago, but I hadn't
> realized
> that invoice storage was such a DoS vector for merchants/hubs and wasn't
> sure it
> would be useful.
>

Yes, I definitely think it is. Especially in a future where LN invoices are
generated casually everywhere.

I started a PR on lightning-rfc to explore the impact points.
https://github.com/lightningnetwork/lightning-rfc/pull/912


> Do you have an example of what information you would usually put in your
> `encoded_order_details`?
>
> I'd imagine that it would usually be simply a skuID from the merchant's
> product
> database, but it could also be fully self-contained data to identify a
> "transaction"
> (probably encrypted with a key belonging to the payee).
>

I think it depends on the application. For a paywall it could be the
article id and an identifier for the user - perhaps a cookie in the user's
browser. But it could indeed go as far as a list of skus and the physical
delivery address for the goods. That obviously won't be suitable for every
application because of the limited space. Passing a full online supermarket
shopping cart in the tlv payload is probably stretching it too far.

Last year, me and my former colleagues Oliver and Desiree ran tlvshop.com.
The site is offline now, but still viewable at
https://joostjager.github.io/tlvshop.com/. If you fill out all the fields,
it encodes the data into a (non-standard) tlv field. In the case of
tlvshop, the payment is truly spontaneous. However the idea of encoding
metadata is the same.

Attaching metadata to a payment is almost impossible with traditional
payments. Lightning changes this and I think that is also a great
opportunity to rethink typical design patterns for ecommerce applications.


> We'd want to ensure that this field is reasonably small, to ensure it can
> fit in
> onions without forcing the sender to use shorter routes or disable other
> features.
>

I don't know if something bad can happen if the sender is forced to use
shorter routes. Maybe as a method to shape traffic in a certain way? Not
totally sure, but perhaps this is already possible today by creating bogus
route hints. In general I'd say that too much metadata just decreases the
payment success rate and therefore something the payee will consider when
creating the invoice. A reasonable cap is an easy fix to address any doubts
on this front though. Only what constant to pick...

Joost.
___
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev


Re: [Lightning-dev] Stateless invoices with proof-of-payment

2021-09-21 Thread Bastien TEINTURIER
Hi Joost,

Concept ACK, I had toyed with something similar a while ago, but I hadn't
realized
that invoice storage was such a DoS vector for merchants/hubs and wasn't
sure it
would be useful.

Do you have an example of what information you would usually put in your
`encoded_order_details`?

I'd imagine that it would usually be simply a skuID from the merchant's
product
database, but it could also be fully self-contained data to identify a
"transaction"
(probably encrypted with a key belonging to the payee).

We'd want to ensure that this field is reasonably small, to ensure it can
fit in
onions without forcing the sender to use shorter routes or disable other
features.

Cheers,
Bastien


Le mar. 21 sept. 2021 à 15:17, Joost Jager  a écrit :

> On Tue, Sep 21, 2021 at 3:06 PM fiatjaf  wrote:
>
>> I would say, however, that these are two separate proposals:
>>
>>   1. implementations should expose a "stateless invoice" API for
>> receiving using the payment_secret;
>>   2. when sending, implementations should attach a TLV record with
>> encoded order details.
>>
>> Of these, 1 is very simple to do and do not require anyone to cooperate,
>> it just works.
>>
>> 2 requires full network compatibility, so it's harder. But 2 is also very
>> much needed otherwise the payee has to keep track of all the invoice ids
>> related to the orders they refer to, right?
>>
>
> Not completely sure what you mean by full network compatibility, but a
> network-wide upgrade including all routing nodes isn't needed. I think to
> do it cleanly we need a new tag for bolt11 and node implementations that
> carry over the contents of this field to a tlv record. So senders do need
> to support this.
>
>
>> But I think just having 1 already improves the situation a lot, and there
>> are application-specific workarounds that can be applied for 2 (having a
>> fixed, hardcoded set of possible orders, encoding the order very minimally
>> in the payment secret or route hint, storing order details on redis for
>> only 3 minutes and using lnurlpay to reduce the delay between invoice
>> issuance and user confirmation to zero, and so on).
>>
>
> A stateless invoice API would be a great thing to have. I've prototyped
> this in lnd and if you implement it so that a regular invoice is inserted
> 'just in time', it isn't too involved as you say.
>
> Joost
> ___
> Lightning-dev mailing list
> Lightning-dev@lists.linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev
>
___
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev


Re: [Lightning-dev] Stateless invoices with proof-of-payment

2021-09-21 Thread Joost Jager
On Tue, Sep 21, 2021 at 3:06 PM fiatjaf  wrote:

> I would say, however, that these are two separate proposals:
>
>   1. implementations should expose a "stateless invoice" API for receiving
> using the payment_secret;
>   2. when sending, implementations should attach a TLV record with encoded
> order details.
>
> Of these, 1 is very simple to do and do not require anyone to cooperate,
> it just works.
>
> 2 requires full network compatibility, so it's harder. But 2 is also very
> much needed otherwise the payee has to keep track of all the invoice ids
> related to the orders they refer to, right?
>

Not completely sure what you mean by full network compatibility, but a
network-wide upgrade including all routing nodes isn't needed. I think to
do it cleanly we need a new tag for bolt11 and node implementations that
carry over the contents of this field to a tlv record. So senders do need
to support this.


> But I think just having 1 already improves the situation a lot, and there
> are application-specific workarounds that can be applied for 2 (having a
> fixed, hardcoded set of possible orders, encoding the order very minimally
> in the payment secret or route hint, storing order details on redis for
> only 3 minutes and using lnurlpay to reduce the delay between invoice
> issuance and user confirmation to zero, and so on).
>

A stateless invoice API would be a great thing to have. I've prototyped
this in lnd and if you implement it so that a regular invoice is inserted
'just in time', it isn't too involved as you say.

Joost
___
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev


Re: [Lightning-dev] Stateless invoices with proof-of-payment

2021-09-21 Thread fiatjaf
Indeed, sorry, I misunderstood it because I read AMP/keysend and assumed
you were talking about payer-generated preimage.
It doesn't help that "payer" and "payee" are so similar words.

So yes, I agree very much.

I also think the part about including the order details inside the TLV
would be very good to have.

I would say, however, that these are two separate proposals:

  1. implementations should expose a "stateless invoice" API for receiving
using the payment_secret;
  2. when sending, implementations should attach a TLV record with encoded
order details.

Of these, 1 is very simple to do and do not require anyone to cooperate, it
just works.

2 requires full network compatibility, so it's harder. But 2 is also very
much needed otherwise the payee has to keep track of all the invoice ids
related to the orders they refer to, right? But I think just having 1
already improves the situation a lot, and there are application-specific
workarounds that can be applied for 2 (having a fixed, hardcoded set of
possible orders, encoding the order very minimally in the payment secret or
route hint, storing order details on redis for only 3 minutes and using
lnurlpay to reduce the delay between invoice issuance and user confirmation
to zero, and so on).

On Tue, Sep 21, 2021 at 9:41 AM Joost Jager  wrote:

> On Tue, Sep 21, 2021 at 2:05 PM fiatjaf  wrote:
>
>> What if instead of the payer generating the preimage the payee could
>> generate stateless invoices? Basically just use some secret to compute the
>> preimage upon receiving the HTLC, for example:
>>
>
> Maybe my explanation wasn't clear enough, but this is exactly what I am
> proposing. The payee generates a stateless invoice and gives it to the
> payer.
>
>
>> 1. Payer requests an invoice.
>> 2. Payee computes hash = sha256(hmac(local_secret,
>> arbitrary_invoice_id)), then encodes arbitrary_invoice_id into the invoice
>> somehow.
>> 3. Payer sends payment with arbitrary_invoice_id as tlv_record_a.
>> 4. Upon receiving the HTLC, payee computes preimage = hmac(local_secret,
>> tlv_record_a) and resolves it.
>>
>
> One way to do this that I tried to describe in the initial post is via the
> payment_secret. This is already an arbitrary invoice id that is already
> sent as a tlv record.
>
>
>> I've implemented such a scheme on @lntxbot, but it required low level
>> code in a c-lightning plugin and a hack with route hints: since TLV
>> payloads were not an option (as payers wouldn't know how to send them) I've
>> used a "shadow" route hint to a private channel that didn't exist, so
>> preimage was generated on the payee using preimage = hmac(local_secret,
>> next_channel_scid).
>>
>
> Clever workaround.
>
> Joost
>
>
___
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev


Re: [Lightning-dev] Stateless invoices with proof-of-payment

2021-09-21 Thread Joost Jager
On Tue, Sep 21, 2021 at 2:05 PM fiatjaf  wrote:

> What if instead of the payer generating the preimage the payee could
> generate stateless invoices? Basically just use some secret to compute the
> preimage upon receiving the HTLC, for example:
>

Maybe my explanation wasn't clear enough, but this is exactly what I am
proposing. The payee generates a stateless invoice and gives it to the
payer.


> 1. Payer requests an invoice.
> 2. Payee computes hash = sha256(hmac(local_secret, arbitrary_invoice_id)),
> then encodes arbitrary_invoice_id into the invoice somehow.
> 3. Payer sends payment with arbitrary_invoice_id as tlv_record_a.
> 4. Upon receiving the HTLC, payee computes preimage = hmac(local_secret,
> tlv_record_a) and resolves it.
>

One way to do this that I tried to describe in the initial post is via the
payment_secret. This is already an arbitrary invoice id that is already
sent as a tlv record.


> I've implemented such a scheme on @lntxbot, but it required low level code
> in a c-lightning plugin and a hack with route hints: since TLV payloads
> were not an option (as payers wouldn't know how to send them) I've used a
> "shadow" route hint to a private channel that didn't exist, so preimage was
> generated on the payee using preimage = hmac(local_secret,
> next_channel_scid).
>

Clever workaround.

Joost
___
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev


Re: [Lightning-dev] Stateless invoices with proof-of-payment

2021-09-21 Thread fiatjaf
What if instead of the payer generating the preimage the payee could
generate stateless invoices? Basically just use some secret to compute the
preimage upon receiving the HTLC, for example:

1. Payer requests an invoice.
2. Payee computes hash = sha256(hmac(local_secret, arbitrary_invoice_id)),
then encodes arbitrary_invoice_id into the invoice somehow.
3. Payer sends payment with arbitrary_invoice_id as tlv_record_a.
4. Upon receiving the HTLC, payee computes preimage = hmac(local_secret,
tlv_record_a) and resolves it.

I've implemented such a scheme on @lntxbot, but it required low level code
in a c-lightning plugin and a hack with route hints: since TLV payloads
were not an option (as payers wouldn't know how to send them) I've used a
"shadow" route hint to a private channel that didn't exist, so preimage was
generated on the payee using preimage = hmac(local_secret,
next_channel_scid).

If however node implementations could provide such a thing it would reduce
database requirements and improve the lives of application developers very
much.

On Tue, Sep 21, 2021 at 7:09 AM Joost Jager  wrote:

> Problem
>
> One of the qualities of lightning is that it can provide light-weight,
> no-login payments with minimal friction. Games, paywalls, podcasts, etc can
> immediately present a QR code that is ready for scan and pay.
>
> Optimistically presenting payment requests does lead to many of those
> payment requests going unused. A user visits a news site and decides not to
> buy the article. The conventional approach is to create a lightning invoice
> on a node and store the invoice together with order details in a database.
> If the order then goes unfulfilled, cleaning processes remove the data from
> the node and database again.
>
> The problem with this setup is that it needs protection against unbounded
> generation of payment requests. There are solutions for that such as rate
> limiting, but wouldn't it be nice if invoices can be generated without the
> need to keep any state at all?
>
> Stateless invoices
>
> What would happen if a lightning invoice is only generated and stored
> nowhere on the recipient side? To the user, it won't make a difference.
> They would still scan and pay the invoice. When the payment arrives at the
> recipient though, two problems arise:
>
> 1. Recipient doesn't know whom or what the payment is for.
>
> This can be solved by attaching additional custom tlv records to the htlc.
> On the wire, this is all arranged for. The only missing piece is the
> ability to specify additional data for that custom tlv record in a bolt11
> invoice. One way would be to define a new tagged field for this in which
> the recipient can encode the order details.
>
> An alternative is to use the existing invoice description field and simply
> always pass that along with the htlc as a custom tlv record.
>
> A second alternative that already works today is to use part (for example
> 16 out of 32 bytes) of the payment_secret (aka payment address) to encode
> the order details in. This assumes that the secret is still secret enough
> with reduced entropy. Also there may not be enough space for every
> application.
>
> 2. Recipient doesn't know the preimage that is needed to settle the
> htlc(s).
>
> One option is to use a keysend payment or AMP payment. In that case, the
> sender includes the preimage with the htlc. Unfortunately this doesn't
> provide the sender with a proof of payment that they'd get with a regular
> lightning payment.
>
> An alternative solution is to use a deterministic preimage based on a
> (recipient node key-derived) secret, the payment secret and other relevant
> properties. This allows the recipient to derive the same preimage twice:
> Once when the lightning invoice is generated and again when a payment
> arrives.
>
> It could be something like this:
>
> payment_secret = random
> preimage = H(node_secret | payment_secret | payment_amount |
> encoded_order_details)
> invoice_hash = H(preimage)
>
> The sender sends an htlc locked to invoice_hash for payment_amount and
> passes along payment_secret and encoded_order_details in a custom tlv
> record.
>
> When the recipient receives the htlc, they reconstruct the preimage
> according to the formula above. At this point, all data is available to do
> so. When H(preimage) indeed matches the htlc hash, they can settle the
> payment knowing that this is an order that they committed to earlier.
> Settling could be implemented as a just-in-time inserted invoice to keep
> the diff small.
>
> The preimage is returned to the sender and serves as a proof of payment.
>
> Resilience
>
> To me it seems that stateless invoices can be a relatively simple way to
> improve the resiliency of systems that deal with lightning invoices.
> Unlimited amounts of invoices can be generated without worrying about
> storage or memory, no matter if the requests are due to popularity of a
> service or a deliberate dos attack.
>
> Interested to hear your 

Re: [Lightning-dev] Stateless invoices with proof-of-payment

2021-09-21 Thread ZmnSCPxj via Lightning-dev
Good morning Joost,

> > > preimage = H(node_secret | payment_secret | payment_amount | 
> > > encoded_order_details)
> > > invoice_hash = H(preimage)
> > >
> > > The sender sends an htlc locked to invoice_hash for payment_amount and 
> > > passes along payment_secret and encoded_order_details in a custom tlv 
> > > record.
> > >
> > > When the recipient receives the htlc, they reconstruct the preimage 
> > > according to the formula above. At this point, all data is available to 
> > > do so. When H(preimage) indeed matches the htlc hash, they can settle the 
> > > payment knowing that this is an order that they committed to earlier. 
> > > Settling could be implemented as a just-in-time inserted invoice to keep 
> > > the diff small.
> > >
> > > The preimage is returned to the sender and serves as a proof of payment.
> >
> > Does this actually work?
> > How does the sender know the `invoice_hash` to lock the HTLC(s) to?
>
> > If the sender does not know the `node_secret` (from its name, I am guessing 
> > it is a secret known only by the recipient?) then it cannot compute 
> > `invoice_hash`, the `invoice_hash` has to be somehow learned by the sender 
> > from the recipient.
>
> So to be clear: this isn't a spontaneous payment protocol with 
> proof-of-payment. The sender will still request an invoice from the recipient 
> via an ordinary http request (think of a paywall with qr invoice that is 
> presented when web-browsing to a paid article). That is also how the sender 
> learns the invoice_hash. It is part of the bolt11 payment request as it 
> always is.
>
> The goal of the scheme is to alleviate the recipient from storing the 
> invoices that they generate.

Ah, thanks for the clarification.
This should probably work, then.

Regards,
ZmnSCPxj
___
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev


Re: [Lightning-dev] Stateless invoices with proof-of-payment

2021-09-21 Thread ZmnSCPxj via Lightning-dev
Good morning again Joost,

> However, we can do "pay for signature" protocols using PTLCs, and rather than 
> requesting for a scalar behind a point as the proof-of-payment, we can 
> instead ask for a signature of a message that attests "this recipient got 
> paid `payment_amount` with `encoded_order_details`" and have a recipient 
> pubkey (not necessarily the node key, it might be best to reduce signing for 
> node keys) as the signing key.
>
> So it seems to me that this cannot work with hashes, but can work with PTLCs 
> if we use pay-for-signature and the proof-of-payment is a signature rather 
> than a scalar.

No, it does not work either.

The reason is that for signing, we need an `R` as well.
Typically, this is a transient keypair generated by the signer as `r = rand(); 
R = r * G`.

In order to set up a pay-for-signature, the sender needs to know an `R` from 
the recipient, and the recipient, being the signer, has to generate that `R` 
for itself.
And if you are just going to do something like sender->request->receiver, 
receiver->R->sender, and *then* do the sender->PTLC->receiver, then you might 
as well just do sender->request->receiver, receiver->invoice->sender, 
sender->PTLC->receiver.

I think your goal, as I understand it, is to reduce it to one round, i.e. 
sender->PTLC+some_data->receiver, then receiver responds to the PTLC that 
somehow generates the proof-of-payment.
Is my understanding correct?

We cannot have the sender generate the `r` and `R = r * G` as knowledge of `r`, 
`s` and the signed message `m` results in learning the privkey `a`:

s = r - a * h(R | m)
a = (r - s) / h(R | m)

Even with MuSig2 we need a separate round for `R` establishment before the 
round where everyone gives shares of `s`, and one can argue that a 
proof-of-payment, being an agreement of the sender and a receiver, is 
semantically equivalent to a 2-of-2 signature of both sender and the receiver 
signing off on the fact that the payment happened.
Thus, it seems to me that we can adapt any *secure* single-round multisignature 
Schnorr scheme to this problem of needing a single-round pay-for-signature.


Perhaps another mechanism?
WARNING: THIS IS NOVEL CRYPTOGRAPHY I THOUGHT UP IN FIVE MINUTES AND I AM NOT A 
CRYPTOGRAPHER, DO NOT ROLL YOUR OWN CRYPTO.

Instead of having a single receiver-scalar, the receiver knows two scalars.

   A = a * G
   B = b * G

The sender knows both `A` and `B`.

Now, suppose sender wants to make a payment to the receiver.
At its simplest, the sender can simply add `A + B` and lock an outgoing PTLC to 
that point.
The proof-of-payment is the sum `a + b`, but knowledge of this sum does not 
imply knowledge of either `a` or `b` (I THINK --- I AM NOT A CRYPTOGRAPHER).

Now, suppose we want a proof-of-payment to be keyed to some data.
We can translate that data to a scalar (e.g. just hash it) and call it `d`.
Then the sender makes a payment to the receiver using this point:

d * A + B

The sender then receives the scalar behind the above point:

d * a + b

Even with knowledge of `d`, the sender cannot learn either `a` or `b` and thus 
cannot synthesize any other proof-of-payment with a different `d`, thus 
"locking" the proof-of-payment to a specific `d`.

The above proof-of-payment is sufficient by showing the point `d * A + B`, the 
committed data `d`, and the receiver public keys `A` and `B`.

AGAIN THIS IS NOVEL CRYPTOGRAPHY I THOUGHT UP IN FIVE MINUTES AND I AM NOT A 
CRYPTOGRAPHER, THIS NEEDS ACTUAL MATHEMATICAL REVIEW FROM AN ACTUAL 
CRYPTOGRAPHER.

Regards,
ZmnSCPxj
___
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev


Re: [Lightning-dev] Stateless invoices with proof-of-payment

2021-09-21 Thread ZmnSCPxj via Lightning-dev


Good morning Joost,

> It could be something like this:
>
> payment_secret = random
> preimage = H(node_secret | payment_secret | payment_amount | 
> encoded_order_details)
> invoice_hash = H(preimage)
>
> The sender sends an htlc locked to invoice_hash for payment_amount and passes 
> along payment_secret and encoded_order_details in a custom tlv record.
>
> When the recipient receives the htlc, they reconstruct the preimage according 
> to the formula above. At this point, all data is available to do so. When 
> H(preimage) indeed matches the htlc hash, they can settle the payment knowing 
> that this is an order that they committed to earlier. Settling could be 
> implemented as a just-in-time inserted invoice to keep the diff small.
>
> The preimage is returned to the sender and serves as a proof of payment.

Does this actually work?
How does the sender know the `invoice_hash` to lock the HTLC(s) to?

If the sender does not know the `node_secret` (from its name, I am guessing it 
is a secret known only by the recipient?) then it cannot compute 
`invoice_hash`, the `invoice_hash` has to be somehow learned by the sender from 
the recipient.

And that is done in the BOLT12 protocol by having the sender send a message to 
the recipient and getting a reply back, included in the reply is a unique 
BOLT11 invoice for a single intended payment.


Note that even using point shenanigans and PTLCs seems not to work.
If you provide, say, a BIP32 nonhardened point / master pubkey, the sender 
could select an arbitrary `i` and ask for the scalar / privkey behind it, but 
that also lets the sender derive the master privete key used in the derivation.
Hardening the derivation would prevent master public keys from being used in 
derivations in the first place.

However, we can do "pay for signature" protocols using PTLCs, and rather than 
requesting for a scalar behind a point as the proof-of-payment, we can instead 
ask for a signature of a message that attests "this recipient got paid 
`payment_amount` with `encoded_order_details`" and have a recipient pubkey (not 
necessarily the node key, it might be best to reduce signing for node keys) as 
the signing key.


So it seems to me that this cannot work with hashes, but *can* work with PTLCs 
if we use pay-for-signature and the proof-of-payment is a signature rather than 
a scalar.

Regards,
ZmnSCPxj
___
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev


[Lightning-dev] Stateless invoices with proof-of-payment

2021-09-21 Thread Joost Jager
Problem

One of the qualities of lightning is that it can provide light-weight,
no-login payments with minimal friction. Games, paywalls, podcasts, etc can
immediately present a QR code that is ready for scan and pay.

Optimistically presenting payment requests does lead to many of those
payment requests going unused. A user visits a news site and decides not to
buy the article. The conventional approach is to create a lightning invoice
on a node and store the invoice together with order details in a database.
If the order then goes unfulfilled, cleaning processes remove the data from
the node and database again.

The problem with this setup is that it needs protection against unbounded
generation of payment requests. There are solutions for that such as rate
limiting, but wouldn't it be nice if invoices can be generated without the
need to keep any state at all?

Stateless invoices

What would happen if a lightning invoice is only generated and stored
nowhere on the recipient side? To the user, it won't make a difference.
They would still scan and pay the invoice. When the payment arrives at the
recipient though, two problems arise:

1. Recipient doesn't know whom or what the payment is for.

This can be solved by attaching additional custom tlv records to the htlc.
On the wire, this is all arranged for. The only missing piece is the
ability to specify additional data for that custom tlv record in a bolt11
invoice. One way would be to define a new tagged field for this in which
the recipient can encode the order details.

An alternative is to use the existing invoice description field and simply
always pass that along with the htlc as a custom tlv record.

A second alternative that already works today is to use part (for example
16 out of 32 bytes) of the payment_secret (aka payment address) to encode
the order details in. This assumes that the secret is still secret enough
with reduced entropy. Also there may not be enough space for every
application.

2. Recipient doesn't know the preimage that is needed to settle the htlc(s).

One option is to use a keysend payment or AMP payment. In that case, the
sender includes the preimage with the htlc. Unfortunately this doesn't
provide the sender with a proof of payment that they'd get with a regular
lightning payment.

An alternative solution is to use a deterministic preimage based on a
(recipient node key-derived) secret, the payment secret and other relevant
properties. This allows the recipient to derive the same preimage twice:
Once when the lightning invoice is generated and again when a payment
arrives.

It could be something like this:

payment_secret = random
preimage = H(node_secret | payment_secret | payment_amount |
encoded_order_details)
invoice_hash = H(preimage)

The sender sends an htlc locked to invoice_hash for payment_amount and
passes along payment_secret and encoded_order_details in a custom tlv
record.

When the recipient receives the htlc, they reconstruct the preimage
according to the formula above. At this point, all data is available to do
so. When H(preimage) indeed matches the htlc hash, they can settle the
payment knowing that this is an order that they committed to earlier.
Settling could be implemented as a just-in-time inserted invoice to keep
the diff small.

The preimage is returned to the sender and serves as a proof of payment.

Resilience

To me it seems that stateless invoices can be a relatively simple way to
improve the resiliency of systems that deal with lightning invoices.
Unlimited amounts of invoices can be generated without worrying about
storage or memory, no matter if the requests are due to popularity of a
service or a deliberate dos attack.

Interested to hear your thoughts.
___
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev