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

Access values from a previous app call's scratch space #2158

Merged
merged 37 commits into from
May 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
a08e8da
Add mechanism for accessing previous `EvalContext`s from within a txn…
jdtzmn May 17, 2021
3a861a3
Set up tests
jdtzmn May 18, 2021
1b68083
Implement `Scratch` gtxna field
jdtzmn May 18, 2021
a7f64c2
Add error conditions
jdtzmn May 18, 2021
f952852
Add Scratch field description
jdtzmn May 18, 2021
d375f56
Error if accessing Scratch space of non-app call
jdtzmn May 18, 2021
4406bae
Revert "Add mechanism for accessing previous `EvalContext`s from with…
jdtzmn May 18, 2021
be4b38c
Use `EvalSideEffects` struct in `EvalParams`
jdtzmn May 19, 2021
065de3c
Remove artifacts from previous attempts
jdtzmn May 19, 2021
6b508b4
Add helper method `accumulatePastSideEffects`
jdtzmn May 20, 2021
918accc
Error if using Scratch field from within a LogicSig
jdtzmn May 20, 2021
3f810a2
Use `testProg` instead of `AssembleString`
jdtzmn May 20, 2021
0ec9658
Remove unnecessary `SideEffects` property to better contain logic
jdtzmn May 21, 2021
76da67e
Address review feedback
jdtzmn May 21, 2021
64442f2
Use `typecheck` for consistent type checking
jdtzmn May 21, 2021
0eb1998
Revert exposing `stackValue`
jdtzmn May 21, 2021
57c9c06
`stackPos` typo
jdtzmn May 21, 2021
6780633
Remove unnecessary variable declarations from `opTxn` and friends
jdtzmn May 21, 2021
98eb20f
Remove `Scratch` field from transaction field specs
jdtzmn May 24, 2021
f39ecdb
Convert from Scratch test to `gload` test
jdtzmn May 24, 2021
169886d
`gload` opcode
jdtzmn May 24, 2021
e7cefb4
Add `gloads` unit test
jdtzmn May 24, 2021
47bdbf8
`gloads` opcode
jdtzmn May 24, 2021
badb635
Fix failing tests
jdtzmn May 25, 2021
94ee198
Document only previous app calls limitation
jdtzmn May 25, 2021
8672182
`gloads` integration test
jdtzmn May 26, 2021
68fac4e
`opGloadImpl` improvements
jdtzmn May 26, 2021
12f6424
Merge branch 'master' into teal-group-composability
jdtzmn May 26, 2021
1aa1bfa
Remove useless pointer slice types
jdtzmn May 26, 2021
e0963ee
Wrap first line to improve TEAL readability
jdtzmn May 26, 2021
554b674
Reduce ambiguity between `txnIdx` and `scratchIdx`
jdtzmn May 26, 2021
b1ff62a
Unexpose internal scratch space methods
jdtzmn May 26, 2021
665c0bd
Add utility method for initializing past side effect slices
jdtzmn May 27, 2021
a1fb497
Add check to only set side effects during an application call
jdtzmn May 27, 2021
96584f1
Move side effect logic into `EvalStateful` function
jdtzmn May 27, 2021
dee9b08
Populate `EvalParams` from test suites with past side effect slices
jdtzmn May 27, 2021
a9f8f69
Merge branch 'master' into teal-group-composability
jdtzmn May 28, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 48 additions & 31 deletions cmd/tealdbg/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,16 +205,17 @@ const (

// evaluation is a description of a single debugger run
type evaluation struct {
program []byte
source string
offsetToLine map[int]int
name string
groupIndex int
mode modeType
aidx basics.AppIndex
ba apply.Balances
result evalResult
states AppState
program []byte
source string
offsetToLine map[int]int
name string
groupIndex int
pastSideEffects []logic.EvalSideEffects
mode modeType
aidx basics.AppIndex
ba apply.Balances
result evalResult
states AppState
}

func (e *evaluation) eval(ep logic.EvalParams) (pass bool, err error) {
Expand Down Expand Up @@ -339,6 +340,17 @@ func (r *LocalRunner) Setup(dp *DebugParams) (err error) {
dp.LatestTimestamp = int64(ddr.LatestTimestamp)
}

if dp.PastSideEffects == nil {
dp.PastSideEffects = logic.MakePastSideEffects(len(r.txnGroup))
} else if len(dp.PastSideEffects) != len(r.txnGroup) {
err = fmt.Errorf(
"invalid past side effects slice with length %d should match group length of %d txns",
len(dp.PastSideEffects),
len(r.txnGroup),
)
return
}

// if program(s) specified then run from it
if len(dp.ProgramBlobs) > 0 {
if len(r.txnGroup) == 1 && dp.GroupIndex != 0 {
Expand Down Expand Up @@ -376,6 +388,7 @@ func (r *LocalRunner) Setup(dp *DebugParams) (err error) {
}
}
r.runs[i].groupIndex = dp.GroupIndex
r.runs[i].pastSideEffects = dp.PastSideEffects
r.runs[i].name = dp.ProgramNames[i]

var mode modeType
Expand Down Expand Up @@ -438,12 +451,13 @@ func (r *LocalRunner) Setup(dp *DebugParams) (err error) {
return
}
run := evaluation{
program: stxn.Txn.ApprovalProgram,
groupIndex: gi,
mode: modeStateful,
aidx: appIdx,
ba: b,
states: states,
program: stxn.Txn.ApprovalProgram,
groupIndex: gi,
pastSideEffects: dp.PastSideEffects,
mode: modeStateful,
aidx: appIdx,
ba: b,
states: states,
}
r.runs = append(r.runs, run)
}
Expand Down Expand Up @@ -473,12 +487,13 @@ func (r *LocalRunner) Setup(dp *DebugParams) (err error) {
return
}
run := evaluation{
program: program,
groupIndex: gi,
mode: modeStateful,
aidx: appIdx,
ba: b,
states: states,
program: program,
groupIndex: gi,
pastSideEffects: dp.PastSideEffects,
mode: modeStateful,
aidx: appIdx,
ba: b,
states: states,
}
r.runs = append(r.runs, run)
found = true
Expand Down Expand Up @@ -513,11 +528,12 @@ func (r *LocalRunner) RunAll() error {
r.debugger.SaveProgram(run.name, run.program, run.source, run.offsetToLine, run.states)

ep := logic.EvalParams{
Proto: &r.proto,
Debugger: r.debugger,
Txn: &r.txnGroup[groupIndex],
TxnGroup: r.txnGroup,
GroupIndex: run.groupIndex,
Proto: &r.proto,
Debugger: r.debugger,
Txn: &r.txnGroup[groupIndex],
TxnGroup: r.txnGroup,
GroupIndex: run.groupIndex,
PastSideEffects: run.pastSideEffects,
}

run.result.pass, run.result.err = run.eval(ep)
Expand All @@ -541,10 +557,11 @@ func (r *LocalRunner) Run() (bool, error) {
run := r.runs[0]

ep := logic.EvalParams{
Proto: &r.proto,
Txn: &r.txnGroup[groupIndex],
TxnGroup: r.txnGroup,
GroupIndex: run.groupIndex,
Proto: &r.proto,
Txn: &r.txnGroup[groupIndex],
TxnGroup: r.txnGroup,
GroupIndex: run.groupIndex,
PastSideEffects: run.pastSideEffects,
}

// Workaround for Go's nil/empty interfaces nil check after nil assignment, i.e.
Expand Down
10 changes: 6 additions & 4 deletions cmd/tealdbg/localLedger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,13 @@ int 2
a.NoError(err)

proto := config.Consensus[protocol.ConsensusCurrentVersion]
pse := logic.MakePastSideEffects(1)
ep := logic.EvalParams{
Txn: &txn,
Proto: &proto,
TxnGroup: []transactions.SignedTxn{txn},
GroupIndex: 0,
Txn: &txn,
Proto: &proto,
TxnGroup: []transactions.SignedTxn{txn},
GroupIndex: 0,
PastSideEffects: pse,
}
pass, delta, err := ba.StatefulEval(ep, appIdx, program)
a.NoError(err)
Expand Down
2 changes: 2 additions & 0 deletions cmd/tealdbg/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"strings"
"time"

"github.com/algorand/go-algorand/data/transactions/logic"
"github.com/algorand/websocket"
"github.com/gorilla/mux"
)
Expand Down Expand Up @@ -72,6 +73,7 @@ type DebugParams struct {
Proto string
TxnBlob []byte
GroupIndex int
PastSideEffects []logic.EvalSideEffects
BalanceBlob []byte
DdrBlob []byte
IndexerURL string
Expand Down
10 changes: 6 additions & 4 deletions daemon/algod/api/server/v2/dryrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,11 +400,13 @@ func doDryrunRequest(dr *DryrunRequest, response *generated.DryrunResponse) {

response.Txns = make([]generated.DryrunTxnResult, len(dr.Txns))
for ti, stxn := range dr.Txns {
pse := logic.MakePastSideEffects(1)
ep := logic.EvalParams{
Txn: &stxn,
Proto: &proto,
TxnGroup: dr.Txns,
GroupIndex: ti,
Txn: &stxn,
Proto: &proto,
TxnGroup: dr.Txns,
GroupIndex: ti,
PastSideEffects: pse,
}
var result generated.DryrunTxnResult
if len(stxn.Lsig.Logic) > 0 {
Expand Down
2 changes: 2 additions & 0 deletions data/transactions/logic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ Some of these have immediate data in the byte or bytes after the opcode.
| `global f` | push value from globals to stack |
| `load i` | copy a value from scratch space to the stack |
| `store i` | pop a value from the stack and store to scratch space |
| `gload t i` | push Ith scratch space index of the Tth transaction in the current group |
| `gloads i` | push Ith scratch space index of the Ath transaction in the current group |

**Transaction Fields**

Expand Down
22 changes: 22 additions & 0 deletions data/transactions/logic/TEAL_opcodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,28 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
- push Ith value of the array field F from the Ath transaction in the current group
- LogicSigVersion >= 3

## gload t i

- Opcode: 0x3a {uint8 transaction group index} {uint8 position in scratch space to load from}
- Pops: _None_
- Pushes: any
- push Ith scratch space index of the Tth transaction in the current group
- LogicSigVersion >= 4
- Mode: Application

The `gload` opcode can only access scratch spaces of previous app calls contained in the current group.

## gloads i

- Opcode: 0x3b {uint8 position in scratch space to load from}
- Pops: *... stack*, uint64
- Pushes: any
- push Ith scratch space index of the Ath transaction in the current group
- LogicSigVersion >= 4
- Mode: Application

The `gloads` opcode can only access scratch spaces of previous app calls contained in the current group.

## bnz target

- Opcode: 0x40 {int16 branch offset, big endian. (negative offsets are illegal before v4)}
Expand Down
4 changes: 3 additions & 1 deletion data/transactions/logic/assembler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ b^
b~
int 2
bzero
gload 0 0
gloads 0
`

var nonsense = map[uint64]string{
Expand All @@ -298,7 +300,7 @@ var compiled = map[uint64]string{
1: "012008b7a60cf8acd19181cf959a12f8acd19181cf951af8acd19181cf15f8acd191810f01020026050212340c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d024242047465737400320032013202320328292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e0102222324252104082209240a220b230c240d250e230f23102311231223132314181b1c2b1716154000032903494",
2: "022008b7a60cf8acd19181cf959a12f8acd19181cf951af8acd19181cf15f8acd191810f01020026050212340c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d024242047465737400320032013202320328292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e0102222324252104082209240a220b230c240d250e230f23102311231223132314181b1c2b171615400003290349483403350222231d4a484848482a50512a63222352410003420000432105602105612105270463484821052b62482b642b65484821052b2106662b21056721072b682b692107210570004848210771004848361c0037001a0031183119311b311d311e311f3120210721051e312131223123312431253126312731283129312a312b312c312d312e312f",
3: "032008b7a60cf8acd19181cf959a12f8acd19181cf951af8acd19181cf15f8acd191810f01020026050212340c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d024242047465737400320032013202320328292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e0102222324252104082209240a220b230c240d250e230f23102311231223132314181b1c2b171615400003290349483403350222231d4a484848482a50512a63222352410003420000432105602105612105270463484821052b62482b642b65484821052b2106662b21056721072b682b692107210570004848210771004848361c0037001a0031183119311b311d311e311f3120210721051e312131223123312431253126312731283129312a312b312c312d312e312f4478222105531421055427042106552105082106564c4d4b02210538212106391c0081e80780046a6f686e",
4: "042008b7a60cf8acd19181cf959a12f8acd19181cf951af8acd19181cf15f8acd191810f01020026050212340c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d024242047465737400320032013202320328292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e0102222324252104082209240a220b230c240d250e230f23102311231223132314181b1c2b171615400003290349483403350222231d4a484848482a50512a63222352410003420000432105602105612105270463484821052b62482b642b65484821052b2106662b21056721072b682b692107210570004848210771004848361c0037001a0031183119311b311d311e311f3120210721051e312131223123312431253126312731283129312a312b312c312d312e312f4478222105531421055427042106552105082106564c4d4b02210538212106391c0081e80780046a6f686e210581d00f210721061f8800034200018921052106902105919221069421069593a0a1a2a3a4a5a6a7a8a9aaabacadae2106af",
4: "042008b7a60cf8acd19181cf959a12f8acd19181cf951af8acd19181cf15f8acd191810f01020026050212340c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d024242047465737400320032013202320328292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e0102222324252104082209240a220b230c240d250e230f23102311231223132314181b1c2b171615400003290349483403350222231d4a484848482a50512a63222352410003420000432105602105612105270463484821052b62482b642b65484821052b2106662b21056721072b682b692107210570004848210771004848361c0037001a0031183119311b311d311e311f3120210721051e312131223123312431253126312731283129312a312b312c312d312e312f4478222105531421055427042106552105082106564c4d4b02210538212106391c0081e80780046a6f686e210581d00f210721061f8800034200018921052106902105919221069421069593a0a1a2a3a4a5a6a7a8a9aaabacadae2106af3a00003b00",
}

func pseudoOp(opcode string) bool {
Expand Down
8 changes: 7 additions & 1 deletion data/transactions/logic/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ var opDocByName = map[string]string{
"global": "push value from globals to stack",
"load": "copy a value from scratch space to the stack",
"store": "pop a value from the stack and store to scratch space",
"gload": "push Ith scratch space index of the Tth transaction in the current group",
"gloads": "push Ith scratch space index of the Ath transaction in the current group",
"bnz": "branch to TARGET if value X is not zero",
"bz": "branch to TARGET if value X is zero",
"b": "branch unconditionally to TARGET",
Expand Down Expand Up @@ -164,6 +166,8 @@ var opcodeImmediateNotes = map[string]string{
"b": "{int16 branch offset, big endian. (negative offsets are illegal before v4)}",
"load": "{uint8 position in scratch space to load from}",
"store": "{uint8 position in scratch space to store to}",
"gload": "{uint8 transaction group index} {uint8 position in scratch space to load from}",
"gloads": "{uint8 position in scratch space to load from}",
"substring": "{uint8 start position} {uint8 end position}",
"dig": "{uint8 depth}",
"asset_holding_get": "{uint8 asset holding field index}",
Expand Down Expand Up @@ -192,6 +196,8 @@ var opDocExtras = map[string]string{
"txn": "FirstValidTime causes the program to fail. The field is reserved for future use.",
"gtxn": "for notes on transaction fields available, see `txn`. If this transaction is _i_ in the group, `gtxn i field` is equivalent to `txn field`.",
"gtxns": "for notes on transaction fields available, see `txn`. If top of stack is _i_, `gtxns field` is equivalent to `gtxn _i_ field`. gtxns exists so that _i_ can be calculated, often based on the index of the current transaction.",
"gload": "The `gload` opcode can only access scratch spaces of previous app calls contained in the current group.",
"gloads": "The `gloads` opcode can only access scratch spaces of previous app calls contained in the current group.",
"btoi": "`btoi` panics if the input is longer than 8 bytes.",
"concat": "`concat` panics if the result would be greater than 4096 bytes.",
"pushbytes": "pushbytes args are not added to the bytecblock during assembly processes",
Expand Down Expand Up @@ -220,7 +226,7 @@ var OpGroups = map[string][]string{
"Arithmetic": {"sha256", "keccak256", "sha512_256", "ed25519verify", "+", "-", "/", "*", "<", ">", "<=", ">=", "&&", "||", "shl", "shr", "sqrt", "bitlen", "exp", "==", "!=", "!", "len", "itob", "btoi", "%", "|", "&", "^", "~", "mulw", "addw", "divmodw", "expw", "getbit", "setbit", "getbyte", "setbyte", "concat", "substring", "substring3"},
"Byteslice Arithmetic": {"b+", "b-", "b/", "b*", "b<", "b>", "b<=", "b>=", "b==", "b!=", "b%"},
"Byteslice Logic": {"b|", "b&", "b^", "b~"},
"Loading Values": {"intcblock", "intc", "intc_0", "intc_1", "intc_2", "intc_3", "pushint", "bytecblock", "bytec", "bytec_0", "bytec_1", "bytec_2", "bytec_3", "pushbytes", "bzero", "arg", "arg_0", "arg_1", "arg_2", "arg_3", "txn", "gtxn", "txna", "gtxna", "gtxns", "gtxnsa", "global", "load", "store"},
"Loading Values": {"intcblock", "intc", "intc_0", "intc_1", "intc_2", "intc_3", "pushint", "bytecblock", "bytec", "bytec_0", "bytec_1", "bytec_2", "bytec_3", "pushbytes", "bzero", "arg", "arg_0", "arg_1", "arg_2", "arg_3", "txn", "gtxn", "txna", "gtxna", "gtxns", "gtxnsa", "global", "load", "store", "gload", "gloads"},
"Flow Control": {"err", "bnz", "bz", "b", "return", "pop", "dup", "dup2", "dig", "swap", "select", "assert", "callsub", "retsub"},
"State Access": {"balance", "min_balance", "app_opted_in", "app_local_get", "app_local_get_ex", "app_global_get", "app_global_get_ex", "app_local_put", "app_global_put", "app_local_del", "app_global_del", "asset_holding_get", "asset_params_get"},
}
Expand Down
Loading