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

Increase max app opt ins to 50 #2750

Merged
merged 4 commits into from
Sep 2, 2021

Conversation

algorandskiy
Copy link
Contributor

@algorandskiy algorandskiy commented Aug 16, 2021

Summary

As a temporary relief increase max number of opt ins to 50.
Also found and fixed an error check in new ledger testing harness.

Test Plan

  • Unit tested ledger.apply and ledger.eval

Benchmarks

Benchmark 1: create 100k accounts, 500 apps (no local data) and opt-in 10k accounts to max number of apps. Restart ledgers, measure a single block validation time of 50k pay transactions on random opted-in accounts.

10 opt ins 50 opt ins 100 opt ins
644 ms 660 ms 683 ms

Benchmark 2: same as 2 but with full local data (16 keys each 64 bytes long with 64 bytes of value data)

10 opt ins 50 opt ins 100 opt ins
1.4 - 2.2 s 9-16 s ~20-25 s

Benchmark 3: same as 2 but 5k txns per block

50 opt ins 30 opt ins 20 opt ins 10 opt ins
3.2 s 1.7 s 1.1 s 0.27 s

@algorandskiy algorandskiy force-pushed the pavel/app-optins branch 2 times, most recently from 0ac6af5 to dd69c6f Compare August 16, 2021 19:24
@codecov-commenter
Copy link

codecov-commenter commented Aug 16, 2021

Codecov Report

Merging #2750 (6185ceb) into master (66e54d9) will decrease coverage by 0.01%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2750      +/-   ##
==========================================
- Coverage   47.12%   47.10%   -0.02%     
==========================================
  Files         349      349              
  Lines       56326    56327       +1     
==========================================
- Hits        26541    26535       -6     
- Misses      26814    26816       +2     
- Partials     2971     2976       +5     
Impacted Files Coverage Δ
data/basics/userBalance.go 16.88% <ø> (ø)
config/consensus.go 84.17% <100.00%> (+0.05%) ⬆️
ledger/blockqueue.go 82.18% <0.00%> (-2.88%) ⬇️
catchup/peerSelector.go 98.95% <0.00%> (-1.05%) ⬇️
ledger/apply/application.go 80.09% <0.00%> (-0.98%) ⬇️
ledger/acctupdates.go 62.13% <0.00%> (-0.34%) ⬇️
network/requestTracker.go 71.55% <0.00%> (+0.43%) ⬆️
catchup/service.go 70.12% <0.00%> (+0.77%) ⬆️
cmd/tealdbg/debugger.go 73.86% <0.00%> (+1.00%) ⬆️

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 66e54d9...6185ceb. Read the comment docs.

Comment on lines +1440 to +1803
ApprovalProgram: []byte{0x02, 0x20, 0x01, 0x01, 0x22},
ClearStateProgram: []byte{0x02, 0x20, 0x01, 0x01, 0x22},
Copy link
Contributor

Choose a reason for hiding this comment

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

This will get clearer after my last PR. You'll put the actual program text in ApprovalProgram, and it'll get assembled on demand.

Comment on lines +1414 to +1775
// TestAppInsMinBalance checks that accounts with MaxAppsOptedIn are accepted by block evaluator
// and do not cause any MaximumMinimumBalance problems
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 it should also be opted into 1000 assets, to make sure MaxMinBalance is correct.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, the apps being opted into must have "full" schemas to get max min balance.

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, the apps being opted into must have "full" schemas to get max min balance.

Agree

I guess it should also be opted into 1000 assets, to make sure MaxMinBalance is correct.

No, because 1000 assets will consume entire MinMaxBalance alone (1000 * 0.1 = 100 that is almost 100.1 of MaxMinBalance). So a user needs to decide what he wants to store - if we want to change it, it needs to be a separate 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 think that MinMaxBalance value is, essentially, a bug right now. I believe the spec says you can opt into 1000 assets and 10 apps. That's not true. But I think the intent is that it is.

I guess I don't care too much if it's in this PR or another.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The spec only says without binding it 1000 assets or 10 apps or something. I might be missing something tho

A transaction must be rejected if its inclusion in a block would cause an account's minimum balance to exceed the maximum minimum balance of 100100000 microalgos.

Copy link
Contributor

Choose a reason for hiding this comment

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

It also separately says both of the asset and app limits:
"Accounts can hold up to $Assets_{\max}$ assets (1000 in this protocol)"
"The maximum number of applications that a single account may opt in to is 10."

I suppose the statement on MaxMinBalance supersedes these statements, in a sense, but I think the intent was to set MaxMinBalance so that it did not prevent the other limits but we forgot to bump it when we added apps. I'm only guessing.

@jannotti
Copy link
Contributor

High level question - since we will have a different value for app creation limit and app optin limit, can I do BOTH? Create 10 apps (but not opt in to them) and then opt in to 50 more?

I don't know if we currently allow 10 creations and then 10 (separate) opt-ins. I suppose we do, so I suppose this 10+50 I mentioned above will be allowed as well.

@algorandskiy algorandskiy force-pushed the pavel/app-optins branch 2 times, most recently from 82b9729 to 18d0cb1 Compare August 18, 2021 15:24
Copy link
Contributor

@brianolson brianolson left a comment

Choose a reason for hiding this comment

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

I'm mostly here for the expanded ledger/eval_test.go and generally it LGTM

@algorandskiy
Copy link
Contributor Author

High level question - since we will have a different value for app creation limit and app optin limit, can I do BOTH? Create 10 apps (but not opt in to them) and then opt in to 50 more?

Yes, it is still allowed: 1) checks are in different places - create app / optin app. 2) MaximumMinimumBalance is not exceeded.

@tsachiherman
Copy link
Contributor

hm. I'm a bit concerned about the timing non-symmetry between the block assembly and validation. When we create a proposal, we limit the time to a specific threshold (250ms). The assumption is that the block validation would take roughly the same time. However, the transactions used in the block assembly are taken from the transaction pool - which means that the corresponding accounts have already been loaded into memory.

When receiving a transaction to validate - we do not have that "luxury" of knowing that the account information was already loaded into memory. Instead, we'll need to fetch it from disk (bummer..). As long a the account's data wasn't substantial, it was perfectly fine. However, in case we have large accounts, we need to make sure that we'll be able to load all of them into memory in a reasonable time.

@pzbitskiy's test was already on the right track - but it would need to be "fine-tuned" for the worst case scenario:
we need to find how many of these "large" accounts we can process on the validator on a block size with 5K transactions.
then, we could establish that we want to complete the block verification within ( let's say ) 3 seconds. And from there, we can find what size we can increase the app without any risk to the protocol.
( or - if that's not the case, we should make a decision based on that.. )

@algorandskiy
Copy link
Contributor Author

When receiving a transaction to validate - we do not have that "luxury" of knowing that the account information was already loaded into memory. Instead, we'll need to fetch it from disk (bummer..).

The test already does it - it reopens the ledger so evaluation happens on empty caches. Plus all 5k txns are from random addresses out of 10k opted in accounts so they are presumably different.

Data on 5k txn per block:

50 opt ins 30 opt ins 20 opt ins 10 opt ins
3.2 s 1.7 s 1.1 s 0.27 s

@algorandskiy
Copy link
Contributor Author

@tsachiherman @Priegle thoughts? evaluation of 5k txns on accounts with full local state in each of 50 app slots would takes 3.2s on a cold DB.

@tsachiherman
Copy link
Contributor

@tsachiherman @Priegle thoughts? evaluation of 5k txns on accounts with full local state in each of 50 app slots would takes 3.2s on a cold DB.

No - that's exactly what I was looking for. It tells me that it's fine to increase the number to application to 50 as long as our block size is roughly 5k transaction. If we will make an attempt to increase it, we could see an inevitable increase in round time.

@algorandskiy
Copy link
Contributor Author

Btw, as JJ noted, we already have a similar problem with 1k assets per account.

@algorandskiy
Copy link
Contributor Author

algorandskiy commented Aug 24, 2021

Chris pointed out to the code

// makeProposals creates a slice of block proposals for the given round and period.
func (n asyncPseudonode) makeProposals(round basics.Round, period period, accounts []account.Participation) ([]proposal, []unauthenticatedVote) {
    deadline := time.Now().Add(config.ProposalAssemblyTime)
    ve, err := n.factory.AssembleBlock(round, deadline)
    if err != nil {

So the assembly deadline is hard.

For a block verification case looks like agreement switches if there is not enough cert votes to a next period that lead so a longer round time.

@tsachiherman
Copy link
Contributor

tsachiherman commented Aug 25, 2021 via email

@algorandskiy
Copy link
Contributor Author

Chris and I went through node.AssembleBlock and it looks like it takes as many transaction as it can under the assembly deadline, or generates an empty block.

@tsachiherman
Copy link
Contributor

Chris and I went through node.AssembleBlock and it looks like it takes as many transaction as it can under the assembly deadline, or generates an empty block.

Kindof. It's not an "or". It takes as many transactions as it can within the node.AssembleBlock timeout. The empty block generation is if it got "stuck" from some reason for more then 10ms beyond the timeout.

And the issue is on the validator, which doesn't have a validation time limit.

@cce
Copy link
Contributor

cce commented Aug 26, 2021

It looked like AssembleBlock() signals the deadline and round number to the block evaluator, then there is an additional assemblyWaitEps of 150ms extra time for AssembleBlock() to wait for the block evaluator to finish up a partial block before giving up and returning an empty block? Is that generous enough?

@tsachiherman
Copy link
Contributor

tsachiherman commented Aug 26, 2021 via email

@cce
Copy link
Contributor

cce commented Aug 26, 2021

On the validation side, from agreement's perspective I don't think there needs to be a deadline for BlockValidator.Validate() — as long as enough nodes validate proposed blocks eventually, agreement will progress. Giving up on valid proposed blocks may hurt liveness. If we miss the first filter/soft-vote timeout there will be more opportunities in future periods to come to consensus on the best block.. however like Tsachi says improving the performance of block validation will keep us from having to go off the fast path and into a new period.

@cce
Copy link
Contributor

cce commented Aug 27, 2021

Looking at the agreement code more deeply, soft votes are issued based on the lowest observed proposal-value, but the cert vote requires a "committableEvent" (proposalCommittable) from the proposalStore that will only be returned if the block was validated (after receiving payloadVerified). So if the block was still not validated by the time the soft vote quorum is observed, the cert vote would not be issued but would eventually be issued later when the late payloadVerified event was delivered to the player. Assuming the validation takes less than 17 additional seconds after the soft vote was issued (itself a 4 second timeout from the start of the round), the cert vote would go out for period 0 without requiring a next vote to a new period.

@tsachiherman
Copy link
Contributor

tsachiherman commented Aug 27, 2021 via email

jannotti
jannotti previously approved these changes Sep 1, 2021
@@ -42,7 +42,7 @@ const (

// MaxEncodedAccountDataSize is a rough estimate for the worst-case scenario we're going to have of the account data and address serialized.
// this number is verified by the TestEncodedAccountDataSize function.
MaxEncodedAccountDataSize = 750000
MaxEncodedAccountDataSize = 850000
Copy link
Contributor

Choose a reason for hiding this comment

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

We talked about this earlier, but I'm wondering if this takes into account worst case asa creation. I think that can be very big.

* Fixed error check in new ledger testing harness
* Unit tested ledger.apply and ledger.eval
* Benchmarked 10 opt-ins vs 50 opt-ins eval times on reopened ledger
@algorandskiy
Copy link
Contributor Author

Rebased

@jannotti jannotti merged commit ac51e70 into algorand:master Sep 2, 2021
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.

None yet

6 participants