Skip to content

Commit 47bdbf8

Browse files
committed
gloads opcode
* Fix incorrect opcode details * Refactor `gload` implementation into shared method
1 parent e7cefb4 commit 47bdbf8

File tree

5 files changed

+65
-30
lines changed

5 files changed

+65
-30
lines changed

data/transactions/logic/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ Some of these have immediate data in the byte or bytes after the opcode.
170170
| `load i` | copy a value from scratch space to the stack |
171171
| `store i` | pop a value from the stack and store to scratch space |
172172
| `gload t i` | push Ith scratch space index of the Tth transaction in the current group |
173+
| `gloads i` | push Ith scratch space index of the Ath transaction in the current group |
173174

174175
**Transaction Fields**
175176

data/transactions/logic/TEAL_opcodes.md

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,24 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
521521
- push Ith value of the array field F from the Ath transaction in the current group
522522
- LogicSigVersion >= 3
523523

524+
## gload t i
525+
526+
- Opcode: 0x3a {uint8 transaction group index} {uint8 position in scratch space to load from}
527+
- Pops: _None_
528+
- Pushes: any
529+
- push Ith scratch space index of the Tth transaction in the current group
530+
- LogicSigVersion >= 4
531+
- Mode: Application
532+
533+
## gloads i
534+
535+
- Opcode: 0x3b {uint8 position in scratch space to load from}
536+
- Pops: *... stack*, uint64
537+
- Pushes: any
538+
- push Ith scratch space index of the Ath transaction in the current group
539+
- LogicSigVersion >= 4
540+
- Mode: Application
541+
524542
## bnz target
525543

526544
- Opcode: 0x40 {int16 branch offset, big endian. (negative offsets are illegal before v4)}
@@ -881,11 +899,3 @@ The call stack is separate from the data stack. Only `callsub` and `retsub` mani
881899
- LogicSigVersion >= 4
882900

883901
The call stack is separate from the data stack. Only `callsub` and `retsub` manipulate it.`
884-
885-
## gload t i
886-
887-
- Opcode: 0xb0 {uint8 transaction group index} {uint8 position in scratch space to store to}
888-
- Pops: _None_
889-
- Pushes: any
890-
- push Ith scratch space index of the Tth transaction in the current group
891-
- LogicSigVersion >= 2

data/transactions/logic/doc.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ var opDocByName = map[string]string{
8282
"load": "copy a value from scratch space to the stack",
8383
"store": "pop a value from the stack and store to scratch space",
8484
"gload": "push Ith scratch space index of the Tth transaction in the current group",
85+
"gloads": "push Ith scratch space index of the Ath transaction in the current group",
8586
"bnz": "branch to TARGET if value X is not zero",
8687
"bz": "branch to TARGET if value X is zero",
8788
"b": "branch unconditionally to TARGET",
@@ -142,7 +143,8 @@ var opcodeImmediateNotes = map[string]string{
142143
"b": "{int16 branch offset, big endian. (negative offsets are illegal before v4)}",
143144
"load": "{uint8 position in scratch space to load from}",
144145
"store": "{uint8 position in scratch space to store to}",
145-
"gload": "{uint8 transaction group index} {uint8 position in scratch space to store to}",
146+
"gload": "{uint8 transaction group index} {uint8 position in scratch space to load from}",
147+
"gloads": "{uint8 position in scratch space to load from}",
146148
"substring": "{uint8 start position} {uint8 end position}",
147149
"dig": "{uint8 depth}",
148150
"asset_holding_get": "{uint8 asset holding field index}",
@@ -203,7 +205,7 @@ type OpGroup struct {
203205
// OpGroupList is groupings of ops for documentation purposes.
204206
var OpGroupList = []OpGroup{
205207
{"Arithmetic", []string{"sha256", "keccak256", "sha512_256", "ed25519verify", "+", "-", "/", "*", "<", ">", "<=", ">=", "&&", "||", "==", "!=", "!", "len", "itob", "btoi", "%", "|", "&", "^", "~", "mulw", "addw", "divw", "getbit", "setbit", "getbyte", "setbyte", "concat", "substring", "substring3"}},
206-
{"Loading Values", []string{"intcblock", "intc", "intc_0", "intc_1", "intc_2", "intc_3", "pushint", "bytecblock", "bytec", "bytec_0", "bytec_1", "bytec_2", "bytec_3", "pushbytes", "arg", "arg_0", "arg_1", "arg_2", "arg_3", "txn", "gtxn", "txna", "gtxna", "gtxns", "gtxnsa", "global", "load", "store", "gload"}},
208+
{"Loading Values", []string{"intcblock", "intc", "intc_0", "intc_1", "intc_2", "intc_3", "pushint", "bytecblock", "bytec", "bytec_0", "bytec_1", "bytec_2", "bytec_3", "pushbytes", "arg", "arg_0", "arg_1", "arg_2", "arg_3", "txn", "gtxn", "txna", "gtxna", "gtxns", "gtxnsa", "global", "load", "store", "gload", "gloads"}},
207209
{"Flow Control", []string{"err", "bnz", "bz", "b", "return", "pop", "dup", "dup2", "dig", "swap", "select", "assert", "callsub", "retsub"}},
208210
{"State Access", []string{"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"}},
209211
}

data/transactions/logic/eval.go

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1911,34 +1911,56 @@ func opStore(cx *evalContext) {
19111911
cx.stack = cx.stack[:last]
19121912
}
19131913

1914-
func opGload(cx *evalContext) {
1915-
gtxid := int(uint(cx.program[cx.pc+1]))
1916-
if gtxid >= len(cx.TxnGroup) {
1917-
cx.err = fmt.Errorf("gload lookup TxnGroup[%d] but it only has %d", gtxid, len(cx.TxnGroup))
1914+
func opGloadImpl(cx *evalContext, groupIdx int, scratchIdx int) (err error, scratchValue stackValue) {
1915+
if groupIdx >= len(cx.TxnGroup) {
1916+
err = fmt.Errorf("gload lookup TxnGroup[%d] but it only has %d", groupIdx, len(cx.TxnGroup))
19181917
return
1919-
}
1920-
txn := cx.TxnGroup[gtxid].Txn
1921-
gindex := int(uint(cx.program[cx.pc+2]))
1922-
if gindex >= 256 {
1923-
cx.err = fmt.Errorf("invalid Scratch index %d", gindex)
1918+
} else if scratchIdx >= 256 {
1919+
err = fmt.Errorf("invalid Scratch index %d", scratchIdx)
19241920
return
1925-
} else if txn.Type != protocol.ApplicationCallTx {
1926-
cx.err = fmt.Errorf("can't use gload on non-app call txn with index %d", gtxid)
1921+
} else if txn := cx.TxnGroup[groupIdx].Txn; txn.Type != protocol.ApplicationCallTx {
1922+
err = fmt.Errorf("can't use gload on non-app call txn with index %d", groupIdx)
19271923
return
19281924
} else if cx.runModeFlags == runModeSignature {
1929-
cx.err = fmt.Errorf("can't use gload from within a LogicSig")
1925+
err = fmt.Errorf("can't use gload from within a LogicSig")
1926+
return
1927+
} else if groupIdx == cx.GroupIndex {
1928+
err = fmt.Errorf("can't use gload on self, use load instead")
19301929
return
1931-
} else if gtxid == cx.GroupIndex {
1932-
cx.err = fmt.Errorf("can't use gload on self, use load instead")
1930+
} else if groupIdx > cx.GroupIndex {
1931+
err = fmt.Errorf("gload can't get future scratch space from txn with index %d", groupIdx)
19331932
return
1934-
} else if gtxid > cx.GroupIndex {
1935-
cx.err = fmt.Errorf("gload can't get future scratch space from txn with index %d", gtxid)
1933+
}
1934+
1935+
scratchValue = cx.PastSideEffects[groupIdx].GetScratchValue(uint8(scratchIdx))
1936+
return
1937+
}
1938+
1939+
func opGload(cx *evalContext) {
1940+
groupIdx := int(uint(cx.program[cx.pc+1]))
1941+
scratchIdx := int(uint(cx.program[cx.pc+2]))
1942+
err, scratchValue := opGloadImpl(cx, groupIdx, scratchIdx)
1943+
if err != nil {
1944+
cx.err = err
19361945
return
19371946
}
1938-
scratchValue := cx.PastSideEffects[gtxid].GetScratchValue(uint8(gindex))
1947+
19391948
cx.stack = append(cx.stack, scratchValue)
19401949
}
19411950

1951+
func opGloads(cx *evalContext) {
1952+
last := len(cx.stack) - 1
1953+
groupIdx := int(cx.stack[last].Uint)
1954+
scratchIdx := int(uint(cx.program[cx.pc+1]))
1955+
err, scratchValue := opGloadImpl(cx, groupIdx, scratchIdx)
1956+
if err != nil {
1957+
cx.err = err
1958+
return
1959+
}
1960+
1961+
cx.stack[last] = scratchValue
1962+
}
1963+
19421964
func opConcat(cx *evalContext) {
19431965
last := len(cx.stack) - 1
19441966
prev := last - 1

data/transactions/logic/opcodes.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ var OpSpecs = []OpSpec{
189189
// Like gtxn, but gets txn index from stack, rather than immediate arg
190190
{0x38, "gtxns", opGtxns, assembleGtxns, disTxn, oneInt, oneAny, 3, modeAny, immediates("f")},
191191
{0x39, "gtxnsa", opGtxnsa, assembleGtxns, disTxna, oneInt, oneAny, 3, modeAny, immediates("f", "i")},
192+
// Group scratch space access
193+
{0x3a, "gload", opGload, asmDefault, disDefault, nil, oneAny, 4, runModeApplication, immediates("t", "i")},
194+
{0x3b, "gloads", opGloads, asmDefault, disDefault, oneInt, oneAny, 4, runModeApplication, immediates("i")},
192195

193196
{0x40, "bnz", opBnz, assembleBranch, disBranch, oneInt, nil, 1, modeAny, opBranch},
194197
{0x41, "bz", opBz, assembleBranch, disBranch, oneInt, nil, 2, modeAny, opBranch},
@@ -241,9 +244,6 @@ var OpSpecs = []OpSpec{
241244
// shl, shr
242245
// divw, modw convenience
243246
// expmod
244-
245-
// Group scratch space access
246-
{0xb0, "gload", opGload, asmDefault, disDefault, nil, oneAny, 2, modeAny, immediates("t", "i")},
247247
}
248248

249249
type sortByOpcode []OpSpec

0 commit comments

Comments
 (0)