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 that are paid multiple times do not reflect their full amount paid #2208

Closed
alexbosworth opened this issue Nov 22, 2018 · 11 comments · Fixed by #3390
Closed

Invoices that are paid multiple times do not reflect their full amount paid #2208

alexbosworth opened this issue Nov 22, 2018 · 11 comments · Fixed by #3390
Labels
bug Unintended code behaviour database Related to the database/storage of LND intermediate Issues suitable for developers moderately familiar with the codebase and LN payments Related to invoices/payments rpc Related to the RPC interface

Comments

@alexbosworth
Copy link
Contributor

Background

When accounting for received payments, invoices should reflect the full amount received, even in the case of a non-standard payment where a payment hash is reused across payments.

Your environment

  • lnd "0.5.0-beta commit=v0.5-beta-330-g881ed0870930e9fc2833c3bebd042b1453c56e06"
  • MacOS Mojave
  • Bitcoin Core

Steps to reproduce

  1. Create an invoice
  2. Pay the invoice on one node
  3. Pay the invoice on another node
  4. Lookup the invoice to check on amt_paid_msat

Expected behaviour

amt_paid_msat = invoice amount x 2

Actual behaviour

amt_paid_msat = invoice amount x 1

@alexbosworth
Copy link
Contributor Author

Note: I appreciate that at invoice can be paid multiple times if the receiver wishes to allow this potentially unsafe behavior, however I also think that by default the node should not allow receiving a second payment to an already resolved payment hash

@Roasbeef Roasbeef added bug Unintended code behaviour beginner Issues suitable for new developers database Related to the database/storage of LND payments Related to invoices/payments rpc Related to the RPC interface labels Nov 26, 2018
@mlerner
Copy link
Contributor

mlerner commented Nov 26, 2018

I can pick this one up.

@Roasbeef
Copy link
Member

@mlerner sounds good to me!

@Roasbeef Roasbeef added intermediate Issues suitable for developers moderately familiar with the codebase and LN and removed beginner Issues suitable for new developers labels Nov 28, 2018
@mlerner
Copy link
Contributor

mlerner commented Dec 3, 2018

@alexbosworth: I confirmed that if the same node tries to send payment for an invoice more than once, the later payments fail. Additionally, I checked that multiple nodes paying the same invoice aren't accounted for in the receiving node's database, and the payments succeed.

Should controlling whether a receiver will accept payment for a resolved invoice be configurable (so that a receiving node can turn on the ability to receive multiple payments for the same invoice), or should receiving nodes always fail the payments for a resolved invoice?

FWIW, my reading of Eclair's code is that multiple payments for the same payment hash will fail because the payment hash is used as a primary key in their database: https://github.com/ACINQ/eclair/blob/71e50520ec8627cbcb5cc3f7d669b9274aa5a3bd/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqlitePaymentsDb.scala#L45

@alexbosworth
Copy link
Contributor Author

In this issue I would say that receiving multiple times should be reflected in the accounting of an invoice

More broadly I would say that the receiver should be able to choose whether or not they re-resolve preimages

@cfromknecht
Copy link
Contributor

The reason we accept multiple payments atm is due to possible ambiguity of restart behavior. We currently don't record the CircuitKey (ChanID, HtlcID) which ultimately settled the invoice, so in the presence of processing multiple HTLCs that could settle an invoice, we don't know which one to reject and which one to accept when replaying the events.

In order to properly do the accounting proposed here, an invoice will have to keep track of these circuit keys. Otherwise, we also risk double counting the same HTLC after a restart.

However, I'd say that once we've gone through the trouble of properly tracking which CircuitKey settled an invoice, the proper fix is then to reject all others and not accept payment to the same invoice.

TL;DR: properly doing this accounting requires fixing the restart ambiguity, which means can safely reject duplicates and not have to actually modify the accounting.

@cfromknecht
Copy link
Contributor

Just remembered there are some additional privacy arguments that could be made in favor of accepting duplicate payments to the same invoice, so there may still be some desire to accept duplicates. With a generic enough solution to the ambiguity discussed above, this would be fairly straightforward.

@heuristics222
Copy link

If you decide to allow multiple payments of the same invoice, subscribers using SubscribeInvoices should be notified of the subsequent payments, currently they are not.

@Roasbeef Roasbeef added this to Needs triage in Bug Triage via automation Dec 18, 2018
@Roasbeef Roasbeef added this to To do in High Priority via automation Dec 18, 2018
@Roasbeef Roasbeef added this to To do in Ingress/merchants Requests via automation Dec 18, 2018
@Roasbeef Roasbeef moved this from To do to In progress in Ingress/merchants Requests Dec 18, 2018
@sergioabril
Copy link

if amt_paid_msat is going to show the total amount paid (eg. amount x 2), would be possible to add a new field to the invoice, holding an array of payments (like a payment_log), maybe just with the amount, timestamp and node, so you can get more details of what happened to that invoice when is paid more than once?

@rahil471
Copy link

My suggestion would be to not allow and payment to an invoice that is already settled. But we know who doesn't like some extra money.. :\

I'm coming from an angle of Lightning integration in an exchange/wallet provider.
The only way to know of an incoming invoice is via SubscribeInvoices and check the amt_paid_sat field. Can't depend on value because in case of 0 any-amount invoice the value stays 0.

Now if we send multiple settled events for same rhash I wonder how this can be handled in wallet provides, probably have to compromise the immutability of the records.
Also, how would the settled_index be handled? Because we consider invoice settled once total value is paid off.

Not sure if I'm making sense to you guys, but we can take this conversation on slack if needed.

@joostjager
Copy link
Collaborator

Fix coming up in #3390

High Priority automation moved this from To do to Done Sep 5, 2019
Bug Triage automation moved this from Needs triage to Closed Sep 5, 2019
Ingress/merchants Requests automation moved this from In progress to Done Sep 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Unintended code behaviour database Related to the database/storage of LND intermediate Issues suitable for developers moderately familiar with the codebase and LN payments Related to invoices/payments rpc Related to the RPC interface
Projects
Bug Triage
  
Closed
Development

Successfully merging a pull request may close this issue.

8 participants