summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Jannotti <john.jannotti@algorand.com>2022-01-17 22:04:54 -0500
committerGitHub <noreply@github.com>2022-01-17 22:04:54 -0500
commita106e8366ac37b49cd9ad48f7423ab0ecc867422 (patch)
treea2550964769490596011d76dcaf895ff0ff9b078
parent593be3cc32c7924a88ac5f0156dbb9ab878d6b71 (diff)
Allow 256 inners (#3422)
* Three new globals for to help contract-to-contract usability * detritis * Check error * doc comments * Impose limits on the entire "tree" of inner calls. This also increases the realism of testing of multiple app calls in a group by creating the EvalParams with the real constructor, thus getting the pooling stuff tested here without playing games manipulating the ep after construction. * Move appID tracking into EvalContext, out of LedgerForLogic This change increases the seperation between AVM execution and the ledger being used to lookup resources. Previously, the ledger kept track of the appID being executed, to offer a narrower interface to those resources. But now, with app-to-app calls, the appID being executed must change, and the AVM needs to maintain the current appID. * Stupid linter * Fix unit tests error messages * Allow access to resources created in the same transaction group The method will be reworked, but the tests are correct and want to get them visible to team. * Access to apps created in group Also adds some tests that are currently skipped for testing - access to addresses of newly created apps - use of gaid in inner transactions Both require some work to implement the thing being tested. * Remove tracked created mechanism in favor of examining applydata. * Allow v6 AVM code to use in-group created asas, apps (& their accts) One exception - apps can not mutate (put or del) keys from the app accounts, because EvalDelta cannot encode such changes. * lint docs * typo * The review dog needs obedience training. * Use one EvalParams for logic evals, another for apps in dry run We used to use one ep per transaction, shared between sig and and app. But the new model of ep usage is to keep using one while evaluating an entire group. The app ep is now built logic.NewAppEvalParams which, hopefully, will prevent some bugs when we change something in the EvalParams and don't reflect it in what was a "raw" EvalParams construction in debugger and dry run. * Use logic.NewAppEvalParams to decrease copying and bugs in debugger * Simplify use of NewEvalParams. No more nil return when no apps. This way, NewEvalParams can be used for all creations of EvalParams, whether they are intended for logicsig or app use, greatly simplifying the way we make them for use by dry run or debugger (where they serve double duty). * Remove explicit PastSideEffects handling in tealdbg * Always create EvalParams to evaluate a transaction group. We used to have an optimization to avoid creating EvalParams unless there was an app call in the transaction group. But the interface to allow transaction processing to communicate changes into the EvalParams is complicated by that (we must only do it if there is one!) This also allows us to use the same construction function for eps created for app and logic evaluation, simplifying dry-run and debugger. The optimization is less needed now anyway: 1) The ep is now shared for the whole group, so it's only one. 2) The ep is smaller now, as we only store nil pointers instead of larger scratch space objects for non-app calls. * Correct mistaken commit * Spec improvments * More spec improvments, including resource "availability" * Recursively return inner transaction tree * Lint * No need for ConfirmedRound, so don't deref a nil pointer! * license check * Shut up, dawg. * base64 merge cleanup * Remove the extraneous field type arrays. * bsqrt * acct_holding_get, a unified opcode for account field access * Thanks, dawg * CR and more spec simplification * e2e test for inner transaction appls * Give max group size * 16 inner txns, regardless of apps present * Adjust test for allowing 256 inners
-rw-r--r--data/transactions/logic/eval.go2
-rw-r--r--data/transactions/logic/evalAppTxn_test.go57
-rw-r--r--data/transactions/logic/eval_test.go2
-rw-r--r--data/transactions/logic/export_test.go4
4 files changed, 37 insertions, 28 deletions
diff --git a/data/transactions/logic/eval.go b/data/transactions/logic/eval.go
index 05ee3ae02..e3d39535d 100644
--- a/data/transactions/logic/eval.go
+++ b/data/transactions/logic/eval.go
@@ -315,7 +315,7 @@ func NewEvalParams(txgroup []transactions.SignedTxnWithAD, proto *config.Consens
if proto.EnableInnerTransactionPooling {
pooledAllowedInners = new(int)
- *pooledAllowedInners = apps * proto.MaxInnerTransactions
+ *pooledAllowedInners = proto.MaxTxGroupSize * proto.MaxInnerTransactions
}
return &EvalParams{
diff --git a/data/transactions/logic/evalAppTxn_test.go b/data/transactions/logic/evalAppTxn_test.go
index 72867018a..786b60bf8 100644
--- a/data/transactions/logic/evalAppTxn_test.go
+++ b/data/transactions/logic/evalAppTxn_test.go
@@ -423,6 +423,8 @@ func TestNumInnerShallow(t *testing.T) {
`
ep, tx, ledger := MakeSampleEnv()
+ ep.Proto.EnableInnerTransactionPooling = false
+ ep.Reset()
ledger.NewApp(tx.Receiver, 888, basics.AppParams{})
ledger.NewAccount(appAddr(888), 1000000)
TestApp(t, pay+";int 1", ep)
@@ -431,6 +433,19 @@ func TestNumInnerShallow(t *testing.T) {
TestApp(t, pay+pay+pay+pay+";int 1", ep)
// In the sample proto, MaxInnerTransactions = 4
TestApp(t, pay+pay+pay+pay+pay+";int 1", ep, "too many inner transactions")
+
+ ep, tx, ledger = MakeSampleEnv()
+ ledger.NewApp(tx.Receiver, 888, basics.AppParams{})
+ ledger.NewAccount(appAddr(888), 1000000)
+ TestApp(t, pay+";int 1", ep)
+ TestApp(t, pay+pay+";int 1", ep)
+ TestApp(t, pay+pay+pay+";int 1", ep)
+ TestApp(t, pay+pay+pay+pay+";int 1", ep)
+ // In the sample proto, MaxInnerTransactions = 4, but when pooling you get
+ // MaxTxGroupSize (here, 8) * that.
+ TestApp(t, pay+pay+pay+pay+pay+";int 1", ep)
+ TestApp(t, strings.Repeat(pay, 32)+";int 1", ep)
+ TestApp(t, strings.Repeat(pay, 33)+";int 1", ep, "too many inner transactions")
}
// TestNumInnerPooled ensures that inner call limits are pooled across app calls
@@ -454,33 +469,21 @@ func TestNumInnerPooled(t *testing.T) {
ledger.NewApp(tx.Txn.Receiver, 888, basics.AppParams{})
ledger.NewAccount(appAddr(888), 1000000)
short := pay + ";int 1"
- long := pay + pay + pay + pay + pay + ";int 1"
- // First two just replicate the non-pooled test
- one := MakeSampleTxnGroup(tx)
- TestApps(t, []string{short, ""}, one, LogicVersion, ledger)
- TestApps(t, []string{short, ""}, one, LogicVersion, ledger)
- TestApps(t, []string{short, ""}, one, LogicVersion, ledger)
- TestApps(t, []string{short, ""}, one, LogicVersion, ledger)
- TestApps(t, []string{short, ""}, one, LogicVersion, ledger)
- TestApps(t, []string{short, ""}, one, LogicVersion, ledger)
- TestApps(t, []string{long, ""}, one, LogicVersion, ledger,
- NewExpect(0, "too many inner transactions"))
-
- // Now try pooling. But it won't work, because in `one`, only the first txn
- // is an appcall.
- TestApps(t, []string{long, short}, one, LogicVersion, ledger,
- NewExpect(0, "too many inner transactions"))
- TestApps(t, []string{short, long}, one, LogicVersion, ledger,
+ long := strings.Repeat(pay, 17) + ";int 1" // More than half allowed
+
+ grp := MakeSampleTxnGroup(tx)
+ TestApps(t, []string{short, ""}, grp, LogicVersion, ledger)
+ TestApps(t, []string{short, short}, grp, LogicVersion, ledger)
+ TestApps(t, []string{long, ""}, grp, LogicVersion, ledger)
+ TestApps(t, []string{short, long}, grp, LogicVersion, ledger)
+ TestApps(t, []string{long, short}, grp, LogicVersion, ledger)
+ TestApps(t, []string{long, long}, grp, LogicVersion, ledger,
NewExpect(1, "too many inner transactions"))
-
- // Now show pooling works, whether the first txn is heavy, or the second (but not both)
- two := MakeSampleTxnGroup(tx)
- two[1].Txn.Type = protocol.ApplicationCallTx
- TestApps(t, []string{short, long}, two, LogicVersion, ledger)
- TestApps(t, []string{long, short}, two, LogicVersion, ledger)
- TestApps(t, []string{long, long}, two, LogicVersion, ledger,
+ grp = append(grp, grp[0])
+ TestApps(t, []string{short, long, long}, grp, LogicVersion, ledger,
+ NewExpect(2, "too many inner transactions"))
+ TestApps(t, []string{long, long, long}, grp, LogicVersion, ledger,
NewExpect(1, "too many inner transactions"))
-
}
func TestAssetCreate(t *testing.T) {
@@ -1321,7 +1324,9 @@ itxn_submit
ledger.NewAccount(appAddr(222), 1_000_000)
TestApp(t, callpay3+"int 1", ep)
- TestApp(t, callpay3+callpay3+"int 1", ep, "too many inner transactions")
+ // Each use of callpay3 is 4 inners total, so 8 is ok. (32 allowed in test ep)
+ TestApp(t, strings.Repeat(callpay3, 8)+"int 1", ep)
+ TestApp(t, strings.Repeat(callpay3, 9)+"int 1", ep, "too many inner transactions")
}
// TestCreateAndUse checks that an ASA can be created in an inner app, and then
diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go
index 4e03c2a26..3aea31b1b 100644
--- a/data/transactions/logic/eval_test.go
+++ b/data/transactions/logic/eval_test.go
@@ -138,7 +138,7 @@ func (ep *EvalParams) reset() {
ep.PooledApplicationBudget = &budget
}
if ep.Proto.EnableInnerTransactionPooling {
- inners := ep.Proto.MaxInnerTransactions
+ inners := ep.Proto.MaxTxGroupSize * ep.Proto.MaxInnerTransactions
ep.pooledAllowedInners = &inners
}
ep.pastScratch = make([]*scratchSpace, ep.Proto.MaxTxGroupSize)
diff --git a/data/transactions/logic/export_test.go b/data/transactions/logic/export_test.go
index b6634cfa5..d0ca904b2 100644
--- a/data/transactions/logic/export_test.go
+++ b/data/transactions/logic/export_test.go
@@ -24,6 +24,10 @@ func NewExpect(l int, s string) Expect {
return Expect{l, s}
}
+func (ep *EvalParams) Reset() {
+ ep.reset()
+}
+
var MakeSampleEnv = makeSampleEnv
var MakeSampleEnvWithVersion = makeSampleEnvWithVersion
var MakeSampleTxn = makeSampleTxn