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

Fix/add fee provision 2 #395

Merged
merged 29 commits into from
Jul 7, 2023
Merged

Fix/add fee provision 2 #395

merged 29 commits into from
Jul 7, 2023

Conversation

kiwiidb
Copy link
Contributor

@kiwiidb kiwiidb commented Jul 4, 2023

This PR ensures that there is no way an account can go below 0.

  • A new entry_type field is added to the transaction entry model to indicate the different types: incoming, outgoing, outgoing_reversal, fee_reserve, fee_reserve_reversal, fee.
  • When making an non-internal transaction the fee reserve is debited from the current account.
  • When the payment has completed, the fee_reserve entry is always reversed if there is one. This is done regardless if lndhub has restarted in the meantime or not.
  • The database constraint on unique tx entry tuples is updated to include the new entry_type field (because we now have identical entries under the previous schema).
  • An integration test has been added that would previously make an account go below 0.
  • Existing integration tests also needed to be updated because they assumed a standard payment has 2 transaction entries associated with it (outgoing + fee or outgoing + reversal), whereas it now has 4 transaction entries associated with it ( fee_reserve + fee_reserve reversal are always there in addition to the ones mentioned above).

To do:

  • fix integration tests
  • add new integration test to ensure this works as intended.

@codecov
Copy link

codecov bot commented Jul 5, 2023

Codecov Report

Merging #395 (5a264de) into main (c9b394f) will decrease coverage by 0.35%.
The diff coverage is 61.59%.

@@            Coverage Diff             @@
##             main     #395      +/-   ##
==========================================
- Coverage   60.07%   59.73%   -0.35%     
==========================================
  Files          51       51              
  Lines        3264     3365     +101     
==========================================
+ Hits         1961     2010      +49     
- Misses       1097     1138      +41     
- Partials      206      217      +11     
Impacted Files Coverage Δ
lib/service/checkpayments.go 50.49% <39.28%> (-6.65%) ⬇️
lib/service/invoices.go 68.07% <66.66%> (-2.48%) ⬇️
integration_tests/lnd_mock_hodl.go 82.60% <100.00%> (ø)
lib/service/invoicesubscription.go 59.81% <100.00%> (+0.18%) ⬆️

... and 1 file with indirect coverage changes

@kiwiidb kiwiidb marked this pull request as ready for review July 6, 2023 14:52
@kiwiidb kiwiidb merged commit c46480d into main Jul 7, 2023
4 of 5 checks passed
@kiwiidb kiwiidb deleted the fix/add-fee-provision-2 branch July 7, 2023 09:02
@kiwiidb kiwiidb mentioned this pull request Jul 8, 2023
2 tasks
@@ -14,9 +23,11 @@ type TransactionEntry struct {
ParentID int64 `bun:",nullzero"`
Parent *TransactionEntry `bun:"rel:belongs-to"`
CreditAccountID int64 `bun:",notnull"`
FeeReserve *TransactionEntry `bun:"rel:belongs-to"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does this reference work? where is the FeeReserveID saved?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's added there in https://github.com/getAlby/lndhub.go/blob/main/lib/service/checkpayments.go#L68.
The FeeReserveID is not saved on the transaction entry, I could not figure out how to get the id of the inserted record in https://github.com/getAlby/lndhub.go/blob/main/lib/service/invoices.go#L329 , I think because we're using a db transaction there it's not possible.

We're looking it up with its invoice id and entry_type = fee_reserve , and then adding it to its parent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so you say this feeReserveEntry here does not have an Id: https://github.com/getAlby/lndhub.go/blob/main/lib/service/invoices.go#L329C34-L329C49

which then can be used in here: https://github.com/getAlby/lndhub.go/blob/main/lib/service/invoices.go#L311-L316 (if moved down)

by SQL it should be possible
and for documentation and proper references I would find it nice to have it, then the other query is also easier because we simply get the association.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if bun does not do that automatically then I think we can use returning
https://bun.uptrace.dev/guide/query-insert.html#api

with that we at least should have the inserted ID in the result: https://pkg.go.dev/database/sql#Result
which we then can use to set the foreign key.

so we save the fee reserve, get the ID of that entry and save that in the tx and all this in a transaction.
PG can do that.

@@ -0,0 +1,2 @@
alter table transaction_entries
add column entry_type character varying;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's with old payments? I guess we can update that entry for those?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they can just be kept as they are, it seems a lot of work and not very useful to update.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's inconsitent data that also requires special handling.
currently we only have incoming outgoing and fee transactions so the migration should be possible, e.g by iterating through the entries and checking the accounts.
I'd prefer not having old/inconsistent data if possible


err := svc.DB.NewSelect().Model(&entry).Where("invoice_id = ?", id).Limit(1).Scan(ctx)
return entry, err
err := svc.DB.NewSelect().Model(&entry).Where("invoice_id = ? and entry_type = ?", id, models.EntryTypeOutgoing).Limit(1).Scan(ctx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was theGetTransactionEntryByInvoiceIdalways returning the outgoing tx entry?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

if err != nil {
//migration issue: pre-feereserve payment will cause a "no rows in result set" error.
//in this case, we also look for the entries without the outgoing check, and do not add the fee reserve
//we can remove this later when all relevant payments will have an entry_type and a fee_reserve tx
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo we should update the data.
otherwise we can never get rid of this code handling old data.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can get rid of it after 2 weeks because we won't encounter any more pre-feereserve payments in this code block by then.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a generic GetTransactionEntryByInvoiceId method so it should be independent of where it is used.
if we don't migrate the data this function will be broken when used elsewhere.

Amount: invoice.Amount,
feeAccount, err := svc.AccountFor(ctx, common.AccountTypeFees, userId)
if err != nil {
svc.Logger.Errorf("Could not find outgoing account user_id:%v", userId)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that should be the:

svc.Logger.Errorf("Could not find fee account for user_id:%v", userId)

if err != nil {
return entry, err
}
entry.FeeReserve = &feeReserveEntry
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to manually load this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -287,49 +293,142 @@ func (svc *LndhubService) HandleFailedPayment(ctx context.Context, invoice *mode
return err
}

func (svc *LndhubService) InsertTransactionEntry(ctx context.Context, invoice *models.Invoice, creditAccount, debitAccount, feeAccount models.Account) (entry models.TransactionEntry, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we call this explicitly InsertOutgoingTransactionEntry
is EntryType always outgoing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be better called InsertOutgoingTransactionEntries, yes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants