-
Notifications
You must be signed in to change notification settings - Fork 91
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
Closed
account min-balance #825
Changes from all commits
Commits
Show all changes
62 commits
Select commit
Hold shift + click to select a range
3e9c0c3
markdown lint
eadb8a7
Merge remote-tracking branch 'origin' into tzaffi/min-balance
1432816
update submodule
957070c
more control ovedr submodule
5a67bc5
typo
f0da64b
experimental differ scripts
bbfb7fe
reporting diffs
45babc0
reasonable looking reports
7f658fe
human friendly parity report
98205d0
maybe now it's human legible
0e0f61f
maybe now it human legible
cdd986e
reporting in good shape
779a347
summary code
2851191
wip
bde9d1a
rm
23a7264
rm
b727bdb
yaml is the best
ceb74ae
looking good
a7335a0
bare essentials diff of swaggers
997de01
set asserted diffs as drops and full
3405292
simplification
207fcfa
simplify
bf42127
imports reorg
8281a16
simplify
835b4b2
refresh submodule
7814815
pyaml in the right requirements.txt
81f5ab6
add algod v. indexer parity check to circle
1f73166
parity test
73ff3fe
try parity again (.PHONYness)
0f701cb
sync instead of force
b7dc9c0
don't need requirements in parity anymore
600c873
EOL
4ff2e35
Update parity/test_indexer_v_algod.py
tzaffi f3fe681
remove extra space
289bf2b
investigatory comment
e352b1c
update swagger for min-balance and a couple of others out of sync
a5ed930
stub the MinBalance using an Enricher()
e225d5a
pass lint
c5730ef
skip parity test by removing it from .PHONY
82341ba
do pg port changes bork circle?
73d6cae
did the tests get borked? yes - common.sh actually needs port 5434
a18bc0b
rename swagger make command
317ea61
remove parity test from Circle (memorializing issue https://github.co…
aa8673b
revert
84846e2
min-balance should not be required, especially when rewinding
a9906aa
enriching fetchAccounts with MinBalance
054de94
Update Makefile
tzaffi f8e5b39
Update Makefile
tzaffi 7ef690b
oops == nil
tzaffi 2bc1eb1
go fmt
e73ec07
lint
b11545f
Update api/handlers_test.go
tzaffi fe41ad9
Merge remote-tracking branch 'origin' into tzaffi/min-balance
6e8aa8b
breakout algodvindexer into its own PR
522a03a
re-merge
f31b049
Update accounting/calculated.go
tzaffi 2610b8a
Merge remote-tracking branch 'origin/develop' into tzaffi/min-balance
e28e1d0
merge
bbd3c66
revert
aca823c
Merge branch 'develop' of https://github.com/algorand/indexer into tz…
481e45d
replace entire &blockheader with &blockheader.CurrentProtocol
d45da61
fmt
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,3 +34,6 @@ __pycache__ | |
*.tar.bz2 | ||
|
||
coverage.txt | ||
|
||
# mac OS | ||
.DS_store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
package accounting | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/algorand/go-algorand/config" | ||
"github.com/algorand/go-algorand/data/basics" | ||
"github.com/algorand/go-algorand/protocol" | ||
"github.com/algorand/indexer/api/generated/v2" | ||
) | ||
|
||
// EnrichMinBalance addes the MinBalance information to a generated.Account by: | ||
// 1. projecting its essential maintenance cost information to an initially empty basics.AccountData bAccount | ||
// 2. calculating bAccount.MinBalance(protocol) using the protocol gotten from a recent blockheader | ||
// 3. adding the result to the generated.Account | ||
// | ||
// TODO: this could present compatability challenges with rewind() as we need to also rewind the MinBalance calculation-logic and protocol along with the account. | ||
// | ||
// TODO: use new MinBalance() function that doesn't require slice lengths when branch feature/unlimited-assets is merged in go-algorand | ||
func EnrichMinBalance(account *generated.Account, consensusVersion *protocol.ConsensusVersion) error { | ||
if consensusVersion == nil { | ||
return fmt.Errorf("cannot EnrichMinBalance as consensus version is missing") | ||
} | ||
proto, ok := config.Consensus[*consensusVersion] | ||
if !ok { | ||
return fmt.Errorf("cannot EnrichMinBalance as consensus version %s is unknown", *consensusVersion) | ||
} | ||
raw := minBalanceProjection(account).MinBalance(&proto).Raw | ||
account.MinBalance = &raw | ||
return nil | ||
} | ||
|
||
// inspired by api::pointer_utils.go and then renamed | ||
// TODO: unify common utils | ||
|
||
func boolZerovalIfNil(b *bool) bool { | ||
if b != nil { | ||
return *b | ||
} | ||
return false | ||
} | ||
|
||
func uint32ZerovalIfNil(x *uint64) uint32 { | ||
if x != nil { | ||
return uint32(*x) | ||
} | ||
return uint32(0) | ||
} | ||
|
||
func convertAssetHoldings(gAssets *[]generated.AssetHolding) map[basics.AssetIndex]basics.AssetHolding { | ||
// assumes WYSIWYG ignoring round information except for Deleted which is skipped | ||
// TODO: handle OptedInAtRound and OptedOutAtRound | ||
// Make sure to add an integration test case that opts in and out and also back in | ||
if gAssets == nil { | ||
return nil | ||
} | ||
bAssets := make(map[basics.AssetIndex]basics.AssetHolding) | ||
for _, gAsset := range *gAssets { | ||
if boolZerovalIfNil(gAsset.Deleted) { | ||
continue | ||
} | ||
|
||
bAssetID := basics.AssetIndex(gAsset.AssetId) | ||
if _, alreadyExists := bAssets[bAssetID]; alreadyExists { | ||
// skip dupes | ||
continue | ||
} | ||
|
||
// for the purposes if MinBalance calculation, there is no need for Amount field, etc. | ||
bAssets[bAssetID] = basics.AssetHolding{} | ||
} | ||
if len(bAssets) > 0 { | ||
return bAssets | ||
} | ||
return nil | ||
} | ||
|
||
func convertAppsCreated(gApps *[]generated.Application) map[basics.AppIndex]basics.AppParams { | ||
// assumes WYSIWYG ignoring most round information except for Deleted or DeletedAtRound which are skipped | ||
if gApps == nil { | ||
return nil | ||
} | ||
bAapps := make(map[basics.AppIndex]basics.AppParams) | ||
for _, gApp := range *gApps { | ||
if boolZerovalIfNil(gApp.Deleted) || gApp.DeletedAtRound != nil { | ||
continue | ||
} | ||
bAppID := basics.AppIndex(gApp.Id) | ||
if _, alreadyExists := bAapps[bAppID]; alreadyExists { | ||
// skip dupes | ||
continue | ||
} | ||
|
||
// MinBalance doesn't dig into AppParams, so provide a zeroval struct | ||
bAapps[bAppID] = basics.AppParams{} | ||
} | ||
if len(bAapps) > 0 { | ||
return bAapps | ||
} | ||
return nil | ||
} | ||
|
||
func convertAppsOptedIn(gApps *[]generated.ApplicationLocalState) map[basics.AppIndex]basics.AppLocalState { | ||
// assumes WYSIWYG ignoring most round information except for Deleted or ClosedOutAtRound which are skipped | ||
if gApps == nil { | ||
return nil | ||
} | ||
bAapps := make(map[basics.AppIndex]basics.AppLocalState) | ||
for _, gApp := range *gApps { | ||
if boolZerovalIfNil(gApp.Deleted) || gApp.ClosedOutAtRound != nil { | ||
continue | ||
} | ||
bAppID := basics.AppIndex(gApp.Id) | ||
if _, alreadyExists := bAapps[bAppID]; alreadyExists { | ||
// skip dupes | ||
continue | ||
} | ||
|
||
// MinBalance doesn't dig into AppLocalStates, so provide a zeroval struct | ||
bAapps[bAppID] = basics.AppLocalState{} | ||
} | ||
if len(bAapps) > 0 { | ||
return bAapps | ||
} | ||
return nil | ||
} | ||
|
||
// minBalanceProjection projects a part of a generated.Account to a basics.AccountData struct. | ||
// It does so for the purpose of calculating an account's minumum balance using the official | ||
// calculator go-algorand/data/basics/userBalance.go::MinBalance() | ||
// 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 { | ||
if boolZerovalIfNil(account.Deleted) { | ||
return basics.AccountData{} | ||
} | ||
|
||
totalAppSchema := basics.StateSchema{} | ||
if account.AppsTotalSchema != nil { | ||
totalAppSchema.NumUint = account.AppsTotalSchema.NumUint | ||
totalAppSchema.NumByteSlice = account.AppsTotalSchema.NumByteSlice | ||
} | ||
totalExtraAppPages := uint32(0) | ||
if account.AppsTotalExtraPages != nil { | ||
totalExtraAppPages = uint32ZerovalIfNil(account.AppsTotalExtraPages) | ||
} | ||
|
||
return basics.AccountData{ | ||
Assets: convertAssetHoldings(account.Assets), | ||
AppParams: convertAppsCreated(account.CreatedApps), | ||
AppLocalStates: convertAppsOptedIn(account.AppsLocalState), | ||
TotalAppSchema: totalAppSchema, | ||
TotalExtraAppPages: totalExtraAppPages, | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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
ingo-algorand
that fills out all of the fields (but has some minor issues when applied to Indexer'sgenerated.Account
). It is also possible to try and unmarshall thebasics.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 abasics.AccountData
at the most convenient location and calculateMinBalance
from it.