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

account min-balance #825

Closed
wants to merge 62 commits into from
Closed

account min-balance #825

wants to merge 62 commits into from

Conversation

tzaffi
Copy link
Contributor

@tzaffi tzaffi commented Jan 14, 2022

Add min-balance information to the /v2/accounts endpoint

Fixes

#808 #676

Summary of changes

  • accounting/calculated.go - EnrichMinBalance: main workhorse of thie PR
  • accounting/calculated_test.go - new unit tests
  • api/error_messages.go - new error message
  • api/handlers.go - mostly in fetchAccounts()
  • api/indexer.oas2.json - add min-balance and fix a couple of typos (discovered by future circle test in Nightly Tests: compare2algod in addition to the regular tests #839 )
  • idb/postgres/postgres.go - modify GetAccounts adding a third output of type *bookkeeping.BlockHeader

Minor Changes in GetAccounts() Just for Tests to Pass

  • api/handlers_test.go
  • cmd/e2equeries/main.go
  • cmd/idbtest/idbtest.go
  • idb/dummy/dummy.go
  • idb/idb.go
  • idb/mocks/IndexerDb.go
  • idb/postgres/postgres_integration_test.go
  • util/test/testutil.go

Auto Generated

  • api/generated/common/routes.go
  • api/generated/common/types.go
  • api/generated/v2/routes.go
  • api/generated/v2/types.go
  • api/indexer.oas3.yml

Test Plan

Unit Tests. Working on an integration tests via the sandbox.

Related Follow-up PR

#839 - Add a test that alerts automatically when a new discrepency arises between algod and indexer

algod compatriate

algorand/go-algorand#3287

@tzaffi tzaffi marked this pull request as draft January 14, 2022 22:23
@tzaffi tzaffi linked an issue Jan 14, 2022 that may be closed by this pull request
@codecov-commenter
Copy link

codecov-commenter commented Jan 14, 2022

Codecov Report

Merging #825 (aca823c) into develop (bf4571d) will increase coverage by 0.51%.
The diff coverage is 83.33%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop     #825      +/-   ##
===========================================
+ Coverage    57.67%   58.19%   +0.51%     
===========================================
  Files           35       36       +1     
  Lines         4362     4432      +70     
===========================================
+ Hits          2516     2579      +63     
- Misses        1539     1545       +6     
- Partials       307      308       +1     
Impacted Files Coverage Δ
api/error_messages.go 100.00% <ø> (ø)
idb/idb.go 51.21% <ø> (ø)
idb/postgres/postgres.go 49.01% <14.28%> (ø)
api/handlers.go 59.59% <50.00%> (-0.25%) ⬇️
accounting/calculated.go 95.23% <95.23%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update bf4571d...aca823c. Read the comment docs.

Makefile Outdated Show resolved Hide resolved
README.md Outdated
@@ -1,23 +1,28 @@
<!-- markdownlint-disable MD041 -->
Copy link
Contributor Author

@tzaffi tzaffi Jan 16, 2022

Choose a reason for hiding this comment

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

linting with vscode's markdownlint extension

api/README.md Outdated
The Makefile will install our fork of **oapi-codegen**, use `make oapi-codegen` to install it directly.

1. Document your changes by editing **indexer.oas2.yml**
1. Document your changes by editing **indexer.oas2.json**
Copy link
Contributor Author

@tzaffi tzaffi Jan 16, 2022

Choose a reason for hiding this comment

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

typo

@@ -0,0 +1,197 @@
from copy import deepcopy
Copy link
Contributor Author

@tzaffi tzaffi Jan 16, 2022

Choose a reason for hiding this comment

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

Code to generate algod v. indexer parity reports. I include a circle test that:

  1. pulls latest go-algorand submodule
  2. uses this library to generate yaml reports
  3. asserts that the results are as expected. In particular:
  • all essential features of algod have their counterparts in indexer (think of min-balance)
  • terminology remain consistent
  • etc.

@@ -0,0 +1,115 @@
____________________ 61 New Attributes ____________________
Copy link
Contributor Author

@tzaffi tzaffi Jan 16, 2022

Choose a reason for hiding this comment

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

This report shows all the "essential" differences between algod and indexer in a relatively human-friendly format. There are variants of this report that limit the scope to:

  • changes of common attributes
  • attributes which are not present in algod but exist in indexer
  • attributes which are present in algod but missing from indexer

However, this report shos ALL the differences (the union of the above)

Comment on lines 51 to 52
- INDEXER: '"[\\lsch\\] global schema"'
- ALGOD: '"[\\gsch\\] global schema"'
Copy link
Contributor Author

@tzaffi tzaffi Jan 17, 2022

Choose a reason for hiding this comment

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

typo?

Comment on lines 130 to 131
- INDEXER: '"\\[tt\\] value type."'
- ALGOD: '"\\[tt\\] value type. Value `1` refers to **bytes**, value `2` refers to **uint**"'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

looks outdated on indexer

// Some data which is relevant for MinBalance but duplicated is ignored. In particular:
// * TotalAppSchema - gotten from account.AppsTotalSchema and not re-calc'ed from CreatedApps
// * TotalExtraPages - gotten from account.AppsTotalExtraPages and not re-calc'ed from CreatedApps
func minBalanceProjection(account *generated.Account) basics.AccountData {
Copy link
Contributor Author

@tzaffi tzaffi Jan 25, 2022

Choose a reason for hiding this comment

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

There is a similar function AccountToAccountData in go-algorand that fills out all of the fields (but has some minor issues when applied to Indexer's generated.Account). It is also possible to try and unmarshall the basics.Account directly from the database as is partially done elsewhere. After some thought, I decided that this was the simplest approach - get only the essential data into a basics.AccountData at the most convenient location and calculate MinBalance from it.

api/handlers.go Outdated
@@ -13,6 +13,7 @@ import (
log "github.com/sirupsen/logrus"

"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

for BlockHeader

api/handlers.go Outdated Show resolved Hide resolved
@@ -960,7 +964,7 @@
],
"properties": {
"type": {
"description": "\\[tt\\] value type.",
"description": "\\[tt\\] value type. Value `1` refers to **bytes**, value `2` refers to **uint**",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was spotted by the new python indexer vs. algod parity test.

@@ -1036,7 +1040,7 @@
"$ref": "#/definitions/ApplicationStateSchema"
},
"global-state-schema": {
"description": "[\\lsch\\] global schema",
"description": "[\\gsch\\] global schema",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ditto

Zeph Grunschlag added 2 commits January 24, 2022 23:18
api/handlers_test.go Outdated Show resolved Hide resolved
@tzaffi tzaffi changed the title WIP: account min-balance account min-balance Jan 25, 2022
@tzaffi tzaffi marked this pull request as ready for review January 25, 2022 14:44
accounting/calculated.go Outdated Show resolved Hide resolved
@tzaffi
Copy link
Contributor Author

tzaffi commented Jan 25, 2022

@winder and @algorandskiy have brought to my attention some important changes that are in the works to handle unlimited assets and which affect the way min-balance is calculated (though technically, the formula remains the same). In particular, we can see that new Total* fields will enter the ledger through a brand new struct AccountBaseData. It may make sense for indexer to import these new ledger fields directly, in which case the minbalance calculation would use the new stand alone MinBalance func something like the following:

var a basics.Account // which perhaps? has as part of it a ledger.AccountBase, or something like that

... populate a ...

minBalance := basics.MinBalance(proto, a.TotalAssets, a.TotalAppSchema, a.TotalAppParams, a.TotalAppLocalStates, a.TotalExtraAPpPages)

@winder - Do you think we should wait for these changes to the ledger to get merged into go-algorand before continuing with this PR? On the other hand, do you see any fairly simple and future-aware work-arounds that can let us proceed without waiting?

@@ -252,6 +252,8 @@ type AccountQueryOptions struct {

IncludeAssetHoldings bool
IncludeAssetParams bool
// IncludeMinBalance indicates whether to calculate min-balance as well (a realatively slow operation)
IncludeMinBalance bool
Copy link
Contributor

Choose a reason for hiding this comment

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

These are database layer options, so this option doesn't need to be here. I think we can get away with using the nil round check, or just skip/unset it in the rewind function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

idb/idb.go Outdated
@@ -173,7 +173,7 @@ type IndexerDb interface {
// The next multiple functions return a channel with results as well as the latest round
// accounted.
Transactions(ctx context.Context, tf TransactionFilter) (<-chan TxnRow, uint64)
GetAccounts(ctx context.Context, opts AccountQueryOptions) (<-chan AccountRow, uint64)
GetAccounts(ctx context.Context, opts AccountQueryOptions) (<-chan AccountRow, uint64, *bookkeeping.BlockHeader)
Copy link
Contributor

Choose a reason for hiding this comment

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

@tolikzinovyev I'm curious what you think about this. The protocol is needed for the min balance calculation, but this approach puts accounting logic in the REST API. There are a few other bits of accounting logic outside of the eval function (sig type, created/deleted at, pending rewards calculations, maybe others). Is there a way to make this sort of accounting logic pluggable so that it can be encapsulated so that it doesn't need to be part of the DB/REST API?

cc: @AlgoStephenAkiki @shiqizng

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 the right solution is to return basics.AccountDatas in IndexerDb.GetAccounts() like it's done in other IndexerDb functions, and in api invoke basics.AccountData.MinBalance().

Copy link
Contributor

Choose a reason for hiding this comment

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

That seems reasonable, but it still has the same problem, you need ConsensusParams to pass into MinBalance.

Copy link
Contributor

Choose a reason for hiding this comment

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

I wouldn't say it's a problem. GetAccounts() returns the current round. Similarly, it can return the current consensus version.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

Copy link
Contributor Author

@tzaffi tzaffi Jan 31, 2022

Choose a reason for hiding this comment

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

An Even Quicker Approach

If we're aiming to get this PR out as soon as possible, an even quicker option is C which doesn't return any basics.AccountData. I could still push the calc of MinBalance closer to the view without a large effort. In this case, I would still create issues similar to the above.

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 we need to wait for the ledger refactoring changes. Whether or not these approaches will continue working depend on changes that are yet to be made. For example, do we add the asset counts lazily or as a migration? If it's done lazily we may not always be able to compute the min balance depending on the REST API changes for the ledger refactoring (one proposal includes an option to return account data with asset/application data removed).

Regardless of that, I think we should skip the basics.AccountData conversion. Does it really help solve our problem? We're constructing it from metadata outside of algod, so we may end up with data inconsistencies based on how we reassemble it from Postgres.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree with the first part, but ideally the database layer shouldn't construct api types imo. Constructing basics.AccountData from data in postgres is pretty straightforward, it's already done in idb/postgres/internal/ledger_for_evaluator/.

Copy link
Contributor

Choose a reason for hiding this comment

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

I support Will's position that we wait for the ledger refactoring changes. We don't want to add this now, and then have updates to this work become a blocker for the ledger refactoring project (we have enough complex dependencies there already).
People can continue to work without min balance being easily available for a little bit longer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

image

@tzaffi tzaffi closed this Jan 31, 2022
@tzaffi tzaffi deleted the tzaffi/min-balance branch January 31, 2022 21:57
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.

Expose account info field min-balance
5 participants