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

2021-09-23 Thread Joost Jager
>
> > 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?
>
> Isn't this ultimately an engineering issue? How much exactly is "too much"
> in this case? Invoices are relatively small, and also don't even
> necessarily
> need to be ever written to disk assuming a slim expiration window. It's
> likely the case that a service can just throw everything in Redis and call
> it a day. In terms of rate limiting a service would likely already need to
> implement that on the API/service level to mitigate app level DoS attacks.
>

It is an engineering issue and indeed, you can use something like Redis to
solve it. Today's internet is probably doing the same thing and it seems to
work so far. With lightning though, there is another option. And it could
be an engineering advantage to not have to keep that state. I can also
imagine that slim expiration windows aren't always desirable. Thinking of
personalized payment requests in mass mailings for example.

So yes, this is not about new functionality, but I still think it is worth
exploring the path.

As far as pre-images go, this can already be "stateless" by generating a
> single random seed (storing that somewhere w/ a counter likely) and then
> using shachain or elkrem to deterministically generate payment hashes. You
> can then either use the payment_addr/secret to index into the hash chain,
> or
> have the user send some counter extracted from the invoice as a custom
> record. Similar schemes have been proposed in the past to support "offline"
> vending machine payments.
>

What would be the advantage of using elkrem or shachain compared to just
using `H(receiver_node_secret | payment_secret)` as the preimage? The
sender knows all the preimages already anyway, they aren't revealed one by
one by another party.

Also I think it could be beneficial to add more data into that hash
function such as the payment amount and the order details. With that, the
receiver knows that they received a payment for something that they offered
in the past, without having the actual record of that stored somewhere.


> Taking it one step further, the service could maintain a unique
> elkrem/shachain state for each unique user, which would then allow them to
> also collapse the pre-image into the hash chain, which lets them save space
> and be able to reproduce a given "proof that someone in the world paid"
> (that no service/wallet seems to accept/generate in an
> automated/standardized manner) statement dynamically
>

Can you provide an example to clarify this idea a bit more? If I read it
correctly, the goal is for the receiver to produce a proof that someone in
the world paid. But how can this be proven if the receiver can generate all
the preimages that they want?

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-22 Thread Olaoluwa Osuntokun
Hi Joost,

> 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?

Isn't this ultimately an engineering issue? How much exactly is "too much"
in this case? Invoices are relatively small, and also don't even necessarily
need to be ever written to disk assuming a slim expiration window. It's
likely the case that a service can just throw everything in Redis and call
it a day. In terms of rate limiting a service would likely already need to
implement that on the API/service level to mitigate app level DoS attacks.

As far as pre-images go, this can already be "stateless" by generating a
single random seed (storing that somewhere w/ a counter likely) and then
using shachain or elkrem to deterministically generate payment hashes. You
can then either use the payment_addr/secret to index into the hash chain, or
have the user send some counter extracted from the invoice as a custom
record. Similar schemes have been proposed in the past to support "offline"
vending machine payments.

Taking it one step further, the service could maintain a unique
elkrem/shachain state for each unique user, which would then allow them to
also collapse the pre-image into the hash chain, which lets them save space
and be able to reproduce a given "proof that someone in the world paid"
(that no service/wallet seems to accept/generate in an
automated/standardized manner) statement dynamically.

-- Laolu


On Tue, Sep 21, 2021 at 3:08 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 

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