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

split Balances Get/Put interface methods into separate methods for creatables #3151

Merged
merged 24 commits into from
Nov 18, 2021

Conversation

cce
Copy link
Contributor

@cce cce commented Oct 27, 2021

Summary

This adds extra methods to the apply.Balances interface to offer creatable-specific alternatives to Get and Put, including chasing down all the use cases of Get and Put to call the new interface methods. A new apply.AccountData type restricts access to the full basics.AccountData structure.

In later PRs, the goal is to replace basics.AccountData and migrate to a database that uses separate tables for account data and per-(account, app/asset) data.

Test Plan

All the current tests pass. I'm also running it against mainnet and testnet with CatchpointTracking enabled and comparing the resulting catchpoint hashes with historical catchpoint hash values. I'm also looking at coverage of files in apply to see if there are any new tests I could add to master (and then merge into this branch) to cover any corner cases not currently handled by our existing unit tests.

@tolikzinovyev
Copy link
Contributor

Is Balances.Get() going to go away? What is the plan?

@tsachiherman
Copy link
Contributor

Is Balances.Get() going to go away? What is the plan?

As you recall from the ledger refactoring documentation, the resources table is going to be separate from the account data. There will definitely be a method that would return the basics of what an account could hold, but all the maps are planned to have a separate accessors.

@tolikzinovyev
Copy link
Contributor

So it will return a different type that doesn't contain maps?

Copy link
Contributor

@algorandskiy algorandskiy left a comment

Choose a reason for hiding this comment

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

Looks good. Please fix the build, comment new functions, and it is ready to go

ledger/apply/asset.go Outdated Show resolved Hide resolved
@@ -406,18 +396,10 @@ func AssetFreeze(cf transactions.AssetFreezeTxnFields, header transactions.Heade
}

// Get the account to be frozen/unfrozen.
record, err := balances.Get(cf.FreezeAccount, false)
holding, err := balances.GetAssetHolding(cf.FreezeAccount, cf.FreezeAsset)
Copy link
Contributor

Choose a reason for hiding this comment

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

wondering why are these "business logic" values passed down to retrieval code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

how so?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd expect GetAssetHolding to return holdings by address (cf.FreezeAccount in this case), but looks like it also checks/sets cf.FreezeAsset value

@cce
Copy link
Contributor Author

cce commented Nov 1, 2021

To try and catch anything I missed, I prefixed the maps in AccountData with X and chased down all the users in the ledger package: cce@1b91783#diff-831e406846493c27b22aca1b7482743df94cec8a6957b34059c912ff7996ec28R464

I found AccountData.MinBalance() which counts the size of Assets, AppParams, and AppLocalStates, which is called by logicLedger.MinBalance() and BlockEvaluator.checkMinBalance(). I modified AccountData.MinBalance to accept an external totalAssets, totalAppParams, totalAppLocalStates rather than looking it up from maps.

WDYT — I was thinking of moving AccountData.MinBalance() to an internal helper function in ledger called by both callers, would that be a good idea?

ledger/apply/application.go Outdated Show resolved Hide resolved
@codecov-commenter
Copy link

codecov-commenter commented Nov 3, 2021

Codecov Report

Merging #3151 (a094ff5) into feature/unlimited-assets (f72764b) will increase coverage by 0.20%.
The diff coverage is 47.03%.

Impacted file tree graph

@@                     Coverage Diff                      @@
##           feature/unlimited-assets    #3151      +/-   ##
============================================================
+ Coverage                     47.23%   47.43%   +0.20%     
============================================================
  Files                           365      370       +5     
  Lines                         58361    59646    +1285     
============================================================
+ Hits                          27564    28296     +732     
- Misses                        27611    28032     +421     
- Partials                       3186     3318     +132     
Impacted Files Coverage Δ
agreement/abstractions.go 50.00% <ø> (ø)
agreement/agreementtest/keyManager.go 100.00% <ø> (ø)
cmd/goal/clerk.go 9.18% <0.00%> (ø)
cmd/goal/multisig.go 10.00% <0.00%> (ø)
config/config.go 47.05% <ø> (ø)
daemon/algod/api/server/v2/handlers.go 0.00% <0.00%> (ø)
daemon/algod/api/server/v2/test/helpers.go 74.81% <0.00%> (-2.29%) ⬇️
data/accountManager.go 0.00% <0.00%> (ø)
data/transactions/logic/assembler.go 78.77% <0.00%> (-0.31%) ⬇️
data/transactions/logic/doc.go 77.41% <ø> (ø)
... and 40 more

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 f72764b...a094ff5. Read the comment docs.

@cce cce requested a review from jannotti November 4, 2021 17:10
Copy link
Contributor

@jannotti jannotti left a comment

Choose a reason for hiding this comment

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

Had a few questions, but looks like a nice step forward to me.

@@ -86,19 +85,22 @@ func createApplication(ac *transactions.ApplicationCallTxnFields, balances Balan
return
}

// look up how many apps they have
totalAppParams, err := balances.TotalAppParams(creator)
Copy link
Contributor

@jannotti jannotti Nov 4, 2021

Choose a reason for hiding this comment

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

I don't follow why this became a method, but total TotalExtraAppPages is accessed directly. Aren't they both keeping a cached sum of things we would otherwise have to chase down? I suppose the answer might be, "Yes, so we should move TotalExtraAppPages into nice protected method where we can be sure to track it properly too, but that's not the job of this PR."

Copy link
Contributor

Choose a reason for hiding this comment

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

I now see that, at least for now, you're not caching a total count. I wonder if we should. The reasoning would be similar, but it does mean writing these objects (man, I really want them to have another name like "AccountHeader" or "AccountBase" so I don't have to distinguish by package name), whenever we add or remove an asset or app. Then again, I guess we already have to, exactly so we can calc min balance.

ledger/apply/apply.go Outdated Show resolved Hide resolved
Comment on lines +46 to +48
// ToApplyAccountData returns apply.AccountData from basics.AccountData
func ToApplyAccountData(acct basics.AccountData) AccountData {
return AccountData{
Copy link
Contributor

Choose a reason for hiding this comment

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

This makes me start to wonder if apply.AccountData should be basics.AccountBase and be embedded in basics.AccountData. Why does it belong in apply?

It would also make the distinction I mentioned earlier clear. It's not some sort of "view" of the AccountData that the apply package prefers, it's the constant sized base of the full basics.AccountData.

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess apply.AccountData is a temporary type while we do not have other/better types.
The idea is to have in-mem and persistent data types for components of basics.AccountData

Copy link
Contributor

Choose a reason for hiding this comment

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

I get that, but it seems to me that this in-memory type is, in fact, the beginning of basics.AccountData, so why not make that explicit?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There was a bigger potential change I considered, where basics.AccountData loses these maps altogether, ledger.Lookup() gets split into separate acct/app/asset methods too, all former users of AccountData are updated to get asset data separately, and the original AccountData type (and its msgp encoding) is moved inside ledger and becomes an implementation detail of account DB, eval, COW, etc.

I didn't think of embedding it as an AccountBase in AccountData because I figured we this PR was moving us towards that goal, starting with apply.Balances.

However looking at what's missing, really only the REST API is left after this I believe.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh, also I was worried a change to basics.AccountData directly might involving updating a ton of tests.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see, so the plan might be that basics.AccountData becomes what I was calling basics.AccountBase, and it gets (maybe) embedded in ledger.accountFull. The apply package will take the various pieces it needs, never an entire ledger.accountFull.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

y'know, I already changed cowForLogicLedger to have Get() return the new apply.AccountData, which is now out of sync with Ledger.Get() returning basics.AccountData, so I will try plumbing through Ledger.GetAppParams, etc to see how much more changes it would be.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, don't get carried away on my behalf. This is nice enough to do as is, and I don't want it to get so large we we have trouble moving forward incrementally.

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 tried tracking down everywhere that was using the maps in basics.AccountData, it was the REST API (account data and dryrun endpoints), tealdbg, and goal, all calling through Ledger.Lookup() basically. I think it's probably best for now to have ledger.Ledger just hide the logic behind Lookup() of joining the asset/app data with account data, rather than change all the tests and callers to Lookup that use basics.AccountData.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines 66 to 69
// AssignAccountData assigns the contents of apply.AccountData to the fields in basics.AccountData
func AssignAccountData(a *basics.AccountData, acct AccountData) {
a.Status = acct.Status
a.MicroAlgos = acct.MicroAlgos
Copy link
Contributor

Choose a reason for hiding this comment

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

Now even more so. This would become a simple assignment.

ledger/apply/apply.go Outdated Show resolved Hide resolved
ledger/apply/apply.go Outdated Show resolved Hide resolved
Amount: cc.AssetParams.Total,
}

if len(record.Assets) > balances.ConsensusParams().MaxAssetsPerAccount {
return fmt.Errorf("too many assets in account: %d > %d", len(record.Assets), balances.ConsensusParams().MaxAssetsPerAccount)
if totalAssets >= balances.ConsensusParams().MaxAssetsPerAccount {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: check this before the above work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah, I was overoptimizing for min diff length, I think there are a few places like this I can pull the "too many X" checks up

Copy link
Contributor

Choose a reason for hiding this comment

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

No strong need, sometimes I don't really notice what's new and what was already there.

ledger/internal/cow_creatables.go Outdated Show resolved Hide resolved
ledger/internal/cow_creatables.go Outdated Show resolved Hide resolved
@cce cce marked this pull request as ready for review November 5, 2021 15:29
cce and others added 5 commits November 5, 2021 11:32
* Add error strings to v2 TEAL compile endpoint

* Move number of errors to end so it is consistent with goal clerk compile

* Refactor ReportProblems() to take io.Writer

* Don't report number of errors on the API call
@cce cce changed the title WIP: split Balances Get/Put interface methods into separate methods for creatables Split Balances Get/Put interface methods into separate methods for creatables Nov 8, 2021
@cce cce changed the title Split Balances Get/Put interface methods into separate methods for creatables split Balances Get/Put interface methods into separate methods for creatables Nov 8, 2021
ahangsu and others added 5 commits November 9, 2021 18:07
* add abi encoding

* accord with go-algorand code format

* minor modification

* add partition test

* resolve review, need more testcase rewrite

* move from cmd/goal to data, resolve review

* rewrite is-dynamic, dynamic array

* update dynamic array 0 element support, test needed

* minor

* minor

* minor

* add more testcase for abi encode/decode

* update comments in encoding test

* minor

* attempt to split abi.go into 2 files

* separate abi files to smaller files

* resolve reviews, work on random gen tuple value encode/decode

* add random tuple test

* remove math-rand, use crypto-rand

* minor

* minor

* some change requested from community

* fix for 1 corner case

* resolve review comments

* resolve review comments

* minor

* minor

* update encode slot capacity

* minor

* resolve reviews

* minor update on bool bytelen calculate

* update encode/decode from types

* random test remain to be modified

* testing variable renaming, encode int support (u)int types

* update test scripts and remove value struct

* follow golint

* partly resolving comments

* whoops uint encoding update

* update int decode to primitive types method

* go fmt

* update parseAppArg to accept abi input (attempt)

* need to check cmdline arg validity

* update unmarshal from JSON in ABI type

* unmarshal from json for ABI type

* update ABI type unmarshal values from JSON bytes

* update ABI methods for string/array/address

* update unmarshal from JSON in abi

* fix for error in ufixed json unmarshal

* fix

* update on method sub command

* minor

* probably better separate abi json to a single file

* i just want to add a required flag plz...

* minor fix on interface from json

* consider some rough test cases

* minor

* add partition test

* update static uint test

* update marshal/unmarshal json methods for abi

* marshal byte array to b64 string

* abi json polish

* update golangci lint rules

* revert golangci config

* update method impl

* update method signature return type check

* minor

* copy-paste code from call app cmd

* minor

* add method flag to txn flags

* minor

* update changes

* minor

* moving helper functions to abi

* update comments

* update method app call

* resolve part in abi impl

* add oncomplete support

* minor

* try to use stringarrayvar

* minor

* update goal return log handing process

* go simple

* add a line of e2e test for now

* update

* minor

* minor

* minor

* go fmt

* approval/clear prog nil

* discard all changes to e2d-app-cross-round, going to write separately e2e test

* update e2d tests

* check ret valu

* use constant

* resolve review partly

* resolve review on code reformatting

* resolve review on code reformatting, use code chunk for datadir and client

* go fmt

* export tuple type maker

* update comments in e2e test

* update filter empty string

* resolve issues with JSON abi

* minor
* adding missing  to opcode docs for external gets

* update TEAL_opcodes.md
## Summary

* new `ParticipationRegistry` interface designed to manage keys and collect usage metrics.
* new REST endpoints for interacting with keys.
* improved `goal account partkeyinfo` and `goal account listpartkeys` formatting.

## Test Plan

New unit and integration tests.
Integration tests (specifically, e2e-go tests) seem to be having resource issues lately, so this returns integration tests to using large instances (4 cores, ~16GB RAM) after they were downsized to medium (2 cores ~8GB RAM) in algorand#3095. Nightly integration tests are already using large VMs.
## Summary

When implementing the catchpoint tracker, I missed the re-initilization location for some of the local variables.
This would generate incorrect catchpoint labels after a node completes a fast-catchup.

algorand#3085

## Test Plan

- [x] Add unit tests
- [x] Perform manual testing
@cce cce changed the base branch from master to feature/unlimited-assets November 16, 2021 15:13
@cce cce merged commit c737cb9 into algorand:feature/unlimited-assets Nov 18, 2021
@cce cce deleted the split-balances branch November 18, 2021 20:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.