Skip to content

accounts: add functionality to update balance by given amount #962

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

Conversation

ViktorTigerstrom
Copy link
Contributor

Fixes #648

Based on #954

This PR introduces functionality to update an account's balance by a given amount, rather than the current update method, which sets the balance to a specific value.

My plan is to deprecate the old functionality in a follow-up PR after this one is merged.

ellemouton and others added 6 commits January 31, 2025 08:54
In this commit, we add the SQLStore type which implements the
accounts.Store interface. To demonstrate that it works as expected, we
also plug this implementation into all the account unit tests to show
that they pass against the sqlite and postgres backends.

One can use `make unit pkg=accounts tags=test_db_postgres` or
`make unit pkg=accounts tags=test_db_sqlite` to test locally.

Note that 2 small timestamp related changes are made to the unit tests.
This is to compensate for timestamp precision in postgres.
The current go.sum file was out of sync with the go.mod file. This commit
updates the go.sum file by running `go mod tidy` to match the go.mod file.
This commit introduces the structure for a new endpoint in the accounts
subsystem, enabling balance adjustments by adding or deducting a
specified amount. This contrasts with the existing `UpdateAccount`
implementation, which directly sets the balance to a fixed value.

For more details on the drawbacks of the current implementation, see
[issue lightninglabs#648](lightninglabs#648).

The actual implementation of the endpoint will be introduced in
subsequent commits.
This commit implements the `updatebalance` command in `litcli`. The
command is implemented with two different subcommands: `add`, which
increases an existing off-chain account’s balance, and `deduct`, which
decreases it accordingly.
To support updating an existing off-chain account’s balance by a
specified amount in the database, we'll implement a corresponding
functions for the different stores. This commit introduces the
`AdjustAccountBalance` function in the kvdb store.
Comment on lines 12 to 20
-- name: AdjustAccountBalance :one
UPDATE accounts
SET current_balance_msat = current_balance_msat + CASE
WHEN sqlc.arg(is_addition)::BOOLEAN THEN sqlc.arg(amount) -- If IsAddition is true, add the amount
ELSE -sqlc.arg(amount) -- If IsAddition is false, subtract the amount
END
WHERE id = sqlc.arg(id)
RETURNING id;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let me know if you prefer that I use the current functionality instead to fetch the current balance, and then set the balance to the currentBalance +- amount.
My motivation for introducing this was to discourage such functionality in the future, which directly sets the balance.

Copy link
Member

Choose a reason for hiding this comment

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

agreed re having specific queries for how we prefer to use it 👍
see comment re splitting this out though

This commit introduces the `AdjustAccountBalance` function in the sqlc
store, to support updating an existing off-chain account’s balance by a
specified amount for sql backends.
With all underlying functionality in place to support updating an
existing off-chain account’s balance by a specified amount, this commit
implements the `UpdateBalance` endpoint to utilize that functionality.
@ViktorTigerstrom ViktorTigerstrom force-pushed the 2025-02-accounts-cli-update-rework branch from a851302 to aed7ef3 Compare February 6, 2025 00:41
Copy link
Member

@ellemouton ellemouton left a comment

Choose a reason for hiding this comment

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

took quick peek (before review was requested - hope you dont mind!) - just leaving some drive by comments in the mean time.

I think we can split this up into 2 PRs: 1) DB + Service additions & tests for those. 2) expose new functionality via RPC + CLI calling code


switch reqType := req.GetUpdate().(type) {
case *litrpc.UpdateAccountBalanceRequest_Add:
log.Infof("[addbalance] id=%s, label=%v, amount=%d",
Copy link
Member

Choose a reason for hiding this comment

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

what do you think of using "credit/debit" instead of "add/deduct"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yeah definitely! I was struggling with naming, and agree that credit & debit is better.

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

// Adjust the account balance by first adding 10000, and then deducting
// 5000.
Copy link
Member

Choose a reason for hiding this comment

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

for review it's nicer if unit tests are in the same commit as the new addition :)

Comment on lines 29 to +30
updateAccountCommand,
updateBalanceCommands,
Copy link
Member

Choose a reason for hiding this comment

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

wondering if we cant fit this under the existing update category somehow?

Copy link
Member

Choose a reason for hiding this comment

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

also, how about just having explicit credit/debit sub commands?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

also, how about just having explicit credit/debit sub commands?

Went with this option!

@@ -132,6 +132,14 @@ func (s *RPCServer) UpdateAccount(ctx context.Context,
return marshalAccount(account), nil
}

// UpdateBalance adds or deducts an amount from an existing account in the
Copy link
Member

@ellemouton ellemouton Feb 6, 2025

Choose a reason for hiding this comment

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

just an idea for standard PR flow: we always try to (as much as possible at least) to keep commits ordered such that things are working commit by commit. For 2 reasons: 1) reverting back to any single commit isnt a problem and 2) review story telling.

so the ideal flow for RPC additions is:

  1. add DB/Service functionality along with any tests for those (in small PR world, that could honestly be the whole PR - since that is like 1 unit of code that is easy to reason about and also lets us continue the on the accounts SQL PR while we iterate on the second unit here which is proto/CLI design).
  2. add proto definitions & call the new code from the rpc server code
  3. add CLI calling code

the high level pattern im describing here is:

  1. server implements new functionality but doesnt expose it yet
  2. server exposes new functionality
  3. client starts calling new functionality

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks a lot for the suggestion! I've tried to follow this with the introduction of the new #973 & #974 PRs.

Comment on lines +161 to +164
if amount <= 0 {
return nil, fmt.Errorf("amount %v must be greater than 0",
int64(amount/1000))
}
Copy link
Member

Choose a reason for hiding this comment

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

why not use uints in the proto definitions then?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea! Addressed in the new PR.

Comment on lines +12 to +20
-- name: AdjustAccountBalance :one
UPDATE accounts
SET current_balance_msat = current_balance_msat + CASE
WHEN sqlc.arg(is_addition) THEN sqlc.arg(amount) -- If IsAddition is true, add the amount
ELSE -sqlc.arg(amount) -- If IsAddition is false, subtract the amount
END
WHERE id = sqlc.arg(id)
RETURNING id;

Copy link
Member

Choose a reason for hiding this comment

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

i think let's keep things simple with just having
CreditAccount and DebitAccount queries?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated in the new PR :)

@@ -148,6 +154,28 @@ message UpdateAccountRequest {
string label = 4;
}

message UpdateAccountBalanceRequest {
Copy link
Member

Choose a reason for hiding this comment

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

so expanding on my other comment: it doesnt really make sense to starting off the PR with rpc definitions as we dont really know how this is going to be used yet etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in the new PR :)

Comment on lines +170 to +176
oneof update {
// Increase the account's balance by the given amount.
int64 add = 3;

// Deducts the given amount from the account balance.
int64 deduct = 4;
}
Copy link
Member

Choose a reason for hiding this comment

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

when defining enums like this, it's good to ask: is there a future where more than 2 options will actually be needed? if not, then this can either be a boolean. Or we can even just have separate Credit/Debit definitions

Copy link
Member

Choose a reason for hiding this comment

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

so either:

Update {
       - ID
       - Amount
       - Credit/Debit bool
}

or

Credit { ID, Amount }
_and_
Debit {ID, Amount}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

redit { ID, Amount }
and
Debit {ID, Amount}

Thanks! Went with the second option :)

@ellemouton
Copy link
Member

My plan is to deprecate the old functionality in a follow-up PR after this one is merged.

good idea. I think we always want to give notice of deprecated endpoints though. So i think in the proto definitions here, you can add a deprecated annotation along with the release where it will be completely removed. Then in the release notes, add a notice about this planned depreciation. Then our next release (or couple releases) will include supporting both to give folks a chance to update to the new endpoint

@ViktorTigerstrom
Copy link
Contributor Author

Replaced by #973 & #974.

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.

accounts: extend update command functionality
2 participants