Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invoices can be paid after expiration #3448

Closed
NicolasDorier opened this issue Sep 2, 2019 · 7 comments
Closed

Invoices can be paid after expiration #3448

NicolasDorier opened this issue Sep 2, 2019 · 7 comments
Assignees
Labels
beginner Issues suitable for new developers enhancement Improvements to existing features / behaviour payments Related to invoices/payments spec

Comments

@NicolasDorier
Copy link
Contributor

NicolasDorier commented Sep 2, 2019

On version v0.7.1.

We got report of the possibility of paying an LND invoice after it got expired, in violation with BOLT11.

A payee after the timestamp plus expiry has passed SHOULD NOT accept a payment

This cause significant problem for merchant because:

  1. BTCPay won't register the payment. This happen because BTCPay invoice is expired and the server stop listening LND.
  2. Even if BTCPay would register the payment, it is painful for the merchant as he will need to manually contact the customer for reimbursing him.

There exist a workaround via hodl invoices, but implementing it put the burden of accepting an incoming payment on the shoulder of the LND client.

Because BTCPay is using an abstraction layer for lightning implementation and that hodl invoices can't fit into such abstraction, we can't really use this alternative.

@junderw
Copy link
Contributor

junderw commented Sep 3, 2019

ahh nvm you mean that LND will receive payments via expired payment requests.

Yeah, it does seem like LND will not send to an expired payment request, but it will receive a payment through a payment request that it sets as expired.

IMO, this is a bug of the sending side. If everyone refuses to send, then no problem.

Rejecting based on the receiving end means you will have to roll back an HTLC which is really bad and can cause issues.

So TLDR:

  1. Receiving side should do sanity check.
  2. Sending side MUST refuse to send when payment request is expired. Since there are many problems that can arise from rejecting incoming HTLCs in large numbers.

@NicolasDorier
Copy link
Contributor Author

NicolasDorier commented Sep 3, 2019

BOLT11:

Payer / Payee Requirements
A payer:

after the timestamp plus expiry has passed:
SHOULD NOT attempt a payment.
otherwise:
if a Lightning payment fails:
MAY attempt to use the address given in the first f field that it understands for payment.
MAY use the sequence of channels, specified by the r field, to route to the payee.
SHOULD consider the fee amount and payment timeout before initiating payment.
SHOULD use the first p field that it did NOT skip as the payment hash.
A payee:

after the timestamp plus expiry has passed:
SHOULD NOT accept a payment.

** after the timestamp plus expiry has passed SHOULD NOT accept a payment. **

Eclair wallet acknowledged the issue (ACINQ/eclair-mobile#209) and fixed it for next release. @jackeveritt tested other implementations, those reject payment correctly.

@junderw
Copy link
Contributor

junderw commented Sep 3, 2019

According to RFC2119: https://www.ipa.go.jp/security/rfc/RFC2119EN.html

4. SHOULD NOT   This phrase, or the phrase "NOT RECOMMENDED" mean that
   there may exist valid reasons in particular circumstances when the
   particular behavior is acceptable or even useful, but the full
   implications should be understood and the case carefully weighed
   before implementing any behavior described with this label.

@junderw
Copy link
Contributor

junderw commented Sep 3, 2019

That being said, I think LND should reject incoming payment to requests they generated with an expiry if that expiry is passed.

@junderw
Copy link
Contributor

junderw commented Sep 3, 2019

In fact, this is pretty much necessary for exchanges to support lightning using LND.

If a user uses a wallet that sends to expired requests, and we accept it even though it's required... then we need to add extra logic to double-check the invoice just in case forever. Which is not realistic.

@wpaulino wpaulino added enhancement Improvements to existing features / behaviour payments Related to invoices/payments spec labels Sep 3, 2019
@Roasbeef Roasbeef added the beginner Issues suitable for new developers label Oct 30, 2019
@bhandras bhandras self-assigned this Nov 7, 2019
@bhandras
Copy link
Collaborator

bhandras commented Dec 2, 2019

This is fixed in PR #3694 and waiting for review.

@Roasbeef
Copy link
Member

Fixed by #3694.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
beginner Issues suitable for new developers enhancement Improvements to existing features / behaviour payments Related to invoices/payments spec
Projects
None yet
Development

No branches or pull requests

5 participants