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

ledger: fix LookupLatest when the ledger advances #3769

Conversation

algorandskiy
Copy link
Contributor

@algorandskiy algorandskiy commented Mar 14, 2022

Summary

LookupLatest combines base account and resources data, and in some cases it cannot
determine reliably how many resources account has, therefore it reads data directly from the DB.
The DB might advance causing cachedDBRound (and base account data) and resourceDbRound
to be out of sync, and a retry needed.
If on retry baseAccount data is outdated, foundAccount flag incorrectly contains a value from
a previous iteration causing completion by checkDone because of empty ad (ledgercore.AccountData).
Having ad and foundAccount synchronized on retry eliminates the problem.

In addition checkDone improved for scenarios when accounts have only own assets.

Test Plan

Added new test

var wg sync.WaitGroup
wg.Add(1)
done := make(chan struct{})
go func() {
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 had another implementation with timer a bit simpler but this looks a bit more robust. Any suggestions on how to check lookupLatest has been blocked at au.accountsReadCond.Wait() ?

Copy link
Contributor

@cce cce Mar 15, 2022

Choose a reason for hiding this comment

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

I think you'd have to change accountsReadCond to use an interface and create a mock (or wrapped) sync.Cond?

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 thought about adding some code into lookupLatest or abstracting the cond var, but thought it is too much only for a single tests.

@algorandskiy algorandskiy force-pushed the pavel/ledger-unlimited-asset-lookuplatest-2 branch from d4848e1 to c720cb4 Compare March 15, 2022 00:44
@@ -886,7 +886,7 @@ func (au *accountUpdates) lookupLatest(addr basics.Address) (data basics.Account
var resourceDbRound basics.Round
withRewards := true

foundAccount := false
var foundAccount bool
Copy link
Contributor

Choose a reason for hiding this comment

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

The two are equivilent..

@tsachiherman tsachiherman merged commit 14544e2 into algorand:master Mar 15, 2022
@@ -957,6 +960,7 @@ func (au *accountUpdates) lookupLatest(addr basics.Address) (data basics.Account
return basics.AccountData{}, basics.Round(0), basics.MicroAlgos{}, fmt.Errorf("offset != len(au.deltas): %w", ErrLookupLatestResources)
}
ad = ledgercore.AccountData{}
foundAccount = false
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for finding this...

@algojack algojack mentioned this pull request Mar 15, 2022
tsachiherman pushed a commit that referenced this pull request Mar 19, 2022
## Summary

The changes in #3770 didn't include the changes in #3769 and so tests don't compile on master currently — this updates another test that uses `Totals` to use `LatestTotals` instead.

## Test Plan

Fixes tests.
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.

3 participants