-
Notifications
You must be signed in to change notification settings - Fork 523
Pool App call budget in group transactions #2711
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
Conversation
jannotti
left a comment
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.
Let's discuss the shared budget pointer idea. I think it fits more closely with how we have done some other recent features. (In fact, see my PR for how I'm handling the excess fee credit in app txn creation: Look for "FeeCredit" in https://github.com/algorand/go-algorand/pull/2661/files)
ledger/eval_test.go
Outdated
| {approvalProgram2, "dynamic cost budget exceeded, executing keccak256: remaining budget is 700 but program cost was 783"}, | ||
| } | ||
|
|
||
| for _, testCase := range cases { |
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.
I think at one point we wanted to do the protocol checks in data/transactions/logic/evalStateful_test.go, but there is some ledger code that also needs to be tested (prepareEvalParams) for correct protocol, so I put this test in the ledger tests.
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.
these tests look good but I think we should not test everything here because in ledger package we only set pooled budget for multiple app calls in one group. And the decisions are made in logic.
Let's do the following:
- a unit test for
prepareEvalParamscall on a group with 2 txns with app calls on old and new protos. No ledger construction/blocks needed. - Preserve a high-level test with block evaluator: no pooling on old proto and pooling on new proto. Programs should be simple but valid, something like
"byte "a"\n" + strings.Repeat("keccak256\n", 50). - Make more precise testing on
ed25519verifyin logic package - it is needed anyway, and theEvalParamswith proto and budget can be easily set there.
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.
I added the prepareEvalParams tests above like you have suggested. Just to be clear, we should probably only check for correct pooling here, and check for cost/budget in the data/transactions/logic/evalStateful_test.go file?
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.
It is always a good idea to check both happy case and error case. The idea is to have 1) minimal sufficient coverage 2) without knowing to much details about stuff from other packeges.
I I suggest to use the following code to generate test programs of difference cost by varying N:
prog := "byte "a\n" + strings.Repeat("keccak256\n", N) + "pop\nint 1\n";So here in ledger the following four cases would be enough:
- cost ~701 + cost ~100 => FAIL on v29.
- same combo OK on vFuture
- ~701 + ~701 => FAIL on both v29 and vFuture
data/transactions/logic/eval.go
Outdated
| if pass && cx.EvalParams.Proto.EnableAppCostPooling { | ||
| // if eval passes, then budget is always greater than cost, so should not have underflow | ||
| *cx.EvalParams.PooledApplicationBudget -= cx.cost | ||
| } |
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.
If an app doesn't pass, everything's probably going to get aborted. Nonetheless, I don't see a good reason not to decrease the pooled budget.
This also needs to be super careful about underflow. Going negative here almost certainly leads to the possibility of a the budget being interpreted as a high number elsewhere.
Codecov Report
@@ Coverage Diff @@
## master #2711 +/- ##
=======================================
Coverage 47.09% 47.10%
=======================================
Files 350 350
Lines 56309 56321 +12
=======================================
+ Hits 26520 26528 +8
- Misses 26817 26821 +4
Partials 2972 2972
Continue to review full report at Codecov.
|
algorandskiy
left a comment
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.
Looks good, some work needed: 1) ed25519verify must be only allowed in stateful TEAL v5+ 2) restructure your TEAL tests in legder: it only should check evaluation on old/new proto with as trivial programs as possible. All TEAL heavy-lifting should go into logic package. Especially this change does not depends on ledger interface for TEAL, only EvalParams preparation, so this preparation in isolation, and a big picture needed to be tested there.
ledger/eval_test.go
Outdated
| {approvalProgram2, "dynamic cost budget exceeded, executing keccak256: remaining budget is 700 but program cost was 783"}, | ||
| } | ||
|
|
||
| for _, testCase := range cases { |
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.
these tests look good but I think we should not test everything here because in ledger package we only set pooled budget for multiple app calls in one group. And the decisions are made in logic.
Let's do the following:
- a unit test for
prepareEvalParamscall on a group with 2 txns with app calls on old and new protos. No ledger construction/blocks needed. - Preserve a high-level test with block evaluator: no pooling on old proto and pooling on new proto. Programs should be simple but valid, something like
"byte "a"\n" + strings.Repeat("keccak256\n", 50). - Make more precise testing on
ed25519verifyin logic package - it is needed anyway, and theEvalParamswith proto and budget can be easily set there.
ledger/eval_test.go
Outdated
| for i, testCase := range cases { | ||
| t.Run(fmt.Sprintf("i=%d", i), func(t *testing.T) { |
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.
this is not must but something you might to consider: there are two almost identical loops.
If fact, it can be done as a single loop over cases.
- Remove fake proto from
evalconstruction above - Make
paramsarray consisting on 3 elements: fake params withApplication: true, MaxAppProgramCost: 700, vFuture, v29. - Modify
evalTestCasestruct and add number of app calls in tx group (numAppCalls) - Run loops over cases, params, and calculate pooled cost as
proto.MaxAppProgramCost * numAppCalls, and compare against a value EvalParams
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.
Good suggestion, will refactor this part.
algorandskiy
left a comment
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.
LGTM, one question about pushint in tests.
… algochoi/pool-tx-costs
Summary
ed25519verifyto be called in Application calls, given that there is enough budget in the poolvFutureconsensus parameterCloses #2636
Test Plan
ledger/to check that group transactions pool the App call budget (700 * number of app calls)ed25519verifyis allowed in App calls, given enough budget in the pool