Skip to content

Commit

Permalink
Merge pull request #981 from ViktorTigerstrom/2025-02-credit-debit-ac…
Browse files Browse the repository at this point in the history
…counts-kvdb-prep

accounts: Credit and debit accounts `kvdb` additions prep
  • Loading branch information
ellemouton authored Feb 20, 2025
2 parents fff0a73 + 3d67a7e commit 400a129
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 8 deletions.
9 changes: 7 additions & 2 deletions accounts/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,14 @@ type Store interface {
AddAccountInvoice(ctx context.Context, id AccountID,
hash lntypes.Hash) error

// IncreaseAccountBalance increases the balance of the account with the
// CreditAccount increases the balance of the account with the
// given ID by the given amount.
IncreaseAccountBalance(ctx context.Context, id AccountID,
CreditAccount(ctx context.Context, id AccountID,
amount lnwire.MilliSatoshi) error

// DebitAccount decreases the balance of the account with the
// given ID by the given amount.
DebitAccount(ctx context.Context, id AccountID,
amount lnwire.MilliSatoshi) error

// UpsertAccountPayment updates or inserts a payment entry for the given
Expand Down
2 changes: 1 addition & 1 deletion accounts/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ func (s *InterceptorService) invoiceUpdate(ctx context.Context,
// If we get here, the current account has the invoice associated with
// it that was just paid. Credit the amount to the account and update it
// in the DB.
err := s.store.IncreaseAccountBalance(ctx, acctID, invoice.AmountPaid)
err := s.store.CreditAccount(ctx, acctID, invoice.AmountPaid)
if err != nil {
return s.disableAndErrorfUnsafe("error increasing account "+
"balance account: %w", err)
Expand Down
31 changes: 29 additions & 2 deletions accounts/store_kvdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,11 +223,11 @@ func (s *BoltStore) AddAccountInvoice(_ context.Context, id AccountID,
return s.updateAccount(id, update)
}

// IncreaseAccountBalance increases the balance of the account with the given ID
// CreditAccount increases the balance of the account with the given ID
// by the given amount.
//
// NOTE: This is part of the Store interface.
func (s *BoltStore) IncreaseAccountBalance(_ context.Context, id AccountID,
func (s *BoltStore) CreditAccount(_ context.Context, id AccountID,
amount lnwire.MilliSatoshi) error {

update := func(account *OffChainBalanceAccount) error {
Expand All @@ -244,6 +244,33 @@ func (s *BoltStore) IncreaseAccountBalance(_ context.Context, id AccountID,
return s.updateAccount(id, update)
}

// DebitAccount decreases the balance of the account with the given ID
// by the given amount.
//
// NOTE: This is part of the Store interface.
func (s *BoltStore) DebitAccount(_ context.Context, id AccountID,
amount lnwire.MilliSatoshi) error {

if amount > math.MaxInt64 {
return fmt.Errorf("amount %v exceeds the maximum of %v",
amount, int64(math.MaxInt64))
}

update := func(account *OffChainBalanceAccount) error {
if account.CurrentBalance-int64(amount) < 0 {
return fmt.Errorf("cannot debit %v from the account "+
"balance, as the resulting balance would be "+
"below 0", int64(amount/1000))
}

account.CurrentBalance -= int64(amount)

return nil
}

return s.updateAccount(id, update)
}

// UpsertAccountPayment updates or inserts a payment entry for the given
// account. Various functional options can be passed to modify the behavior of
// the method. The returned boolean is true if the payment was already known
Expand Down
34 changes: 31 additions & 3 deletions accounts/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package accounts

import (
"context"
"github.com/lightningnetwork/lnd/lnwire"
"testing"
"time"

Expand Down Expand Up @@ -71,6 +72,14 @@ func TestAccountStore(t *testing.T) {
)
require.NoError(t, err)

// Adjust the account balance by first crediting 10000, and then
// debiting 5000.
err = store.CreditAccount(ctx, acct1.ID, lnwire.MilliSatoshi(10000))
require.NoError(t, err)

err = store.DebitAccount(ctx, acct1.ID, lnwire.MilliSatoshi(5000))
require.NoError(t, err)

// Update the in-memory account so that we can compare it with the
// account we get from the store.
acct1.CurrentBalance = -500
Expand All @@ -85,11 +94,30 @@ func TestAccountStore(t *testing.T) {
}
acct1.Invoices[lntypes.Hash{12, 34, 56, 78}] = struct{}{}
acct1.Invoices[lntypes.Hash{34, 56, 78, 90}] = struct{}{}
acct1.CurrentBalance += 10000
acct1.CurrentBalance -= 5000

dbAccount, err = store.Account(ctx, acct1.ID)
require.NoError(t, err)
assertEqualAccounts(t, acct1, dbAccount)

// Test that adjusting the balance to exactly 0 should work, while
// adjusting the balance to below 0 should fail.
err = store.DebitAccount(
ctx, acct1.ID, lnwire.MilliSatoshi(acct1.CurrentBalance),
)
require.NoError(t, err)

acct1.CurrentBalance = 0

dbAccount, err = store.Account(ctx, acct1.ID)
require.NoError(t, err)
assertEqualAccounts(t, acct1, dbAccount)

// Adjusting the value to below 0 should fail.
err = store.DebitAccount(ctx, acct1.ID, lnwire.MilliSatoshi(1))
require.ErrorContains(t, err, "balance would be below 0")

// Sleep just a tiny bit to make sure we are never too quick to measure
// the expiry, even though the time is nanosecond scale and writing to
// the store and reading again should take at least a couple of
Expand Down Expand Up @@ -262,12 +290,12 @@ func TestAccountUpdateMethods(t *testing.T) {
assertInvoices(hash1, hash2)
})

t.Run("IncreaseAccountBalance", func(t *testing.T) {
t.Run("CreditAccount", func(t *testing.T) {
store := NewTestDB(t, clock.NewTestClock(time.Now()))

// Increasing the balance of an account that doesn't exist
// should error out.
err := store.IncreaseAccountBalance(ctx, AccountID{}, 100)
err := store.CreditAccount(ctx, AccountID{}, 100)
require.ErrorIs(t, err, ErrAccNotFound)

acct, err := store.NewAccount(ctx, 123, time.Time{}, "foo")
Expand All @@ -284,7 +312,7 @@ func TestAccountUpdateMethods(t *testing.T) {

// Increase the balance by 100 and assert that the new balance
// is 223.
err = store.IncreaseAccountBalance(ctx, acct.ID, 100)
err = store.CreditAccount(ctx, acct.ID, 100)
require.NoError(t, err)

assertBalance(223)
Expand Down

0 comments on commit 400a129

Please sign in to comment.