Skip to content

Commit

Permalink
Re-org the new opcodes, move frames out of experimental
Browse files Browse the repository at this point in the history
  • Loading branch information
jannotti committed Sep 27, 2022
1 parent aac2007 commit 21ff73b
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 91 deletions.
2 changes: 1 addition & 1 deletion data/transactions/logic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -598,9 +598,9 @@ Account fields used in the `acct_params_get` opcode.
| `select` | selects one of two values based on top-of-stack: B if C != 0, else A |
| `assert` | immediately fail unless A is a non-zero number |
| `callsub target` | branch unconditionally to TARGET, saving the next instruction on the call stack |
| `proto a r` | Prepare top call frame for a retsub that will assume A args and R return values. |
| `retsub` | pop the top instruction from the call stack and branch to it |
| `switch target ...` | branch to the Ath label. Continue at following instruction if index A exceeds the number of labels. |
| `proto a r` | Prepare top call frame for a retsub that will assume A args and R return values. |

### State Access

Expand Down
62 changes: 31 additions & 31 deletions data/transactions/logic/TEAL_opcodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,13 @@ See `bnz` for details on how branches work. `b` always jumps to the offset.
- immediately fail unless A is a non-zero number
- Availability: v3

## bury n

- Opcode: 0x45 {uint8 depth}
- Stack: ..., A → ...
- Replace the Nth value from the top of the stack. bury 0 fails.
- Availability: v8

## popn n

- Opcode: 0x46 {uint8 stack depth}
Expand Down Expand Up @@ -1067,9 +1074,32 @@ The call stack is separate from the data stack. Only `callsub`, `retsub`, and `p

If the current frame was prepared by `proto A R`, `retsub` will remove the 'A' arguments from the stack, move the `R` return values down, and pop any stack locations above the relocated return values.

## proto a r

- Opcode: 0x8a {uint8 arguments} {uint8 return values}
- Stack: ... → ...
- Prepare top call frame for a retsub that will assume A args and R return values.
- Availability: v8

Fails unless the last instruction executed was a `callsub`.

## frame_dig i

- Opcode: 0x8b {int8 frame slot}
- Stack: ... → ..., any
- Nth (signed) value from the frame pointer.
- Availability: v8

## frame_bury i

- Opcode: 0x8c {int8 frame slot}
- Stack: ..., A → ...
- Replace the Nth (signed) value from the frame pointer in the stack
- Availability: v8

## switch target ...

- Opcode: 0x8a {uint8 branch count} [{int16 branch offset, big-endian}, ...]
- Opcode: 0x8d {uint8 branch count} [{int16 branch offset, big-endian}, ...]
- Stack: ..., A: uint64 → ...
- branch to the Ath label. Continue at following instruction if index A exceeds the number of labels.
- Availability: v8
Expand Down Expand Up @@ -1432,33 +1462,3 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
| 0 | BlkSeed | []byte | |
| 1 | BlkTimestamp | uint64 | |


## proto a r

- Opcode: 0xf0 {uint8 arguments} {uint8 return values}
- Stack: ... → ...
- Prepare top call frame for a retsub that will assume A args and R return values.
- Availability: v8

Fails unless the last instruction executed was a `callsub`.

## frame_dig i

- Opcode: 0xf1 {int8 frame slot}
- Stack: ... → ..., any
- Nth (signed) value from the frame pointer.
- Availability: v8

## frame_bury i

- Opcode: 0xf2 {int8 frame slot}
- Stack: ..., A → ...
- Replace the Nth (signed) value from the frame pointer in the stack
- Availability: v8

## bury n

- Opcode: 0xf3 {uint8 depth}
- Stack: ..., A → ...
- Replace the Nth value from the top of the stack. bury 0 fails.
- Availability: v8
4 changes: 2 additions & 2 deletions data/transactions/logic/assembler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ const randomnessCompiled = "81ffff03d101d000"
const v7Compiled = v6Compiled + "5e005f018120af060180070123456789abcd49490501988003012345494984" +
randomnessCompiled + "800243218001775c0280018881015d"

const switchCompiled = "81018a02fff800008101"
const switchCompiled = "81018d02fff800008101"

const v8Compiled = v7Compiled + switchCompiled + frameCompiled

Expand Down Expand Up @@ -496,7 +496,7 @@ func TestAssemble(t *testing.T) {
}
}

var experiments = []uint64{pairingVersion, fpVersion}
var experiments = []uint64{pairingVersion}

// TestExperimental forces a conscious choice to promote "experimental" opcode
// groups. This will fail when we increment vFuture's LogicSigVersion. If we had
Expand Down
2 changes: 1 addition & 1 deletion data/transactions/logic/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ var OpGroups = map[string][]string{
"Byte Array Arithmetic": {"b+", "b-", "b/", "b*", "b<", "b>", "b<=", "b>=", "b==", "b!=", "b%", "bsqrt"},
"Byte Array 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", "args", "txn", "gtxn", "txna", "txnas", "gtxna", "gtxnas", "gtxns", "gtxnsa", "gtxnsas", "global", "load", "loads", "store", "stores", "gload", "gloads", "gloadss", "gaid", "gaids"},
"Flow Control": {"err", "bnz", "bz", "b", "return", "pop", "popn", "dup", "dup2", "dupn", "dig", "bury", "cover", "uncover", "frame_dig", "frame_bury", "swap", "select", "assert", "callsub", "retsub", "switch", "proto"},
"Flow Control": {"err", "bnz", "bz", "b", "return", "pop", "popn", "dup", "dup2", "dupn", "dig", "bury", "cover", "uncover", "frame_dig", "frame_bury", "swap", "select", "assert", "callsub", "proto", "retsub", "switch"},
"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", "app_params_get", "acct_params_get", "log", "block"},
"Inner Transactions": {"itxn_begin", "itxn_next", "itxn_field", "itxn_submit", "itxn", "itxna", "itxnas", "gitxn", "gitxna", "gitxnas"},
}
Expand Down
2 changes: 1 addition & 1 deletion data/transactions/logic/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -2119,7 +2119,7 @@ func opSwitch(cx *EvalContext) error {
return nil
}

const protoByte = 0xf0
const protoByte = 0x8a

func opCallSub(cx *EvalContext) error {
cx.callstack = append(cx.callstack, frame{
Expand Down
2 changes: 1 addition & 1 deletion data/transactions/logic/frames_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const frameNonsense = `
bury 9
`

const frameCompiled = "43f00102f1ff240bf20089810246014704f309"
const frameCompiled = "438a01028bff240b8c00898102460147044509"

func TestDupPopN(t *testing.T) {
partitiontest.PartitionTest(t)
Expand Down
88 changes: 44 additions & 44 deletions data/transactions/logic/langspec.json
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,17 @@
"Flow Control"
]
},
{
"Opcode": 69,
"Name": "bury",
"Args": ".",
"Size": 2,
"Doc": "Replace the Nth value from the top of the stack. bury 0 fails.",
"ImmediateNote": "{uint8 depth}",
"Groups": [
"Flow Control"
]
},
{
"Opcode": 70,
"Name": "popn",
Expand Down Expand Up @@ -1599,6 +1610,39 @@
},
{
"Opcode": 138,
"Name": "proto",
"Size": 3,
"Doc": "Prepare top call frame for a retsub that will assume A args and R return values.",
"DocExtra": "Fails unless the last instruction executed was a `callsub`.",
"ImmediateNote": "{uint8 arguments} {uint8 return values}",
"Groups": [
"Flow Control"
]
},
{
"Opcode": 139,
"Name": "frame_dig",
"Returns": ".",
"Size": 2,
"Doc": "Nth (signed) value from the frame pointer.",
"ImmediateNote": "{int8 frame slot}",
"Groups": [
"Flow Control"
]
},
{
"Opcode": 140,
"Name": "frame_bury",
"Args": ".",
"Size": 2,
"Doc": "Replace the Nth (signed) value from the frame pointer in the stack",
"ImmediateNote": "{int8 frame slot}",
"Groups": [
"Flow Control"
]
},
{
"Opcode": 141,
"Name": "switch",
"Args": "U",
"Size": 0,
Expand Down Expand Up @@ -2334,50 +2378,6 @@
"Groups": [
"State Access"
]
},
{
"Opcode": 240,
"Name": "proto",
"Size": 3,
"Doc": "Prepare top call frame for a retsub that will assume A args and R return values.",
"DocExtra": "Fails unless the last instruction executed was a `callsub`.",
"ImmediateNote": "{uint8 arguments} {uint8 return values}",
"Groups": [
"Flow Control"
]
},
{
"Opcode": 241,
"Name": "frame_dig",
"Returns": ".",
"Size": 2,
"Doc": "Nth (signed) value from the frame pointer.",
"ImmediateNote": "{int8 frame slot}",
"Groups": [
"Flow Control"
]
},
{
"Opcode": 242,
"Name": "frame_bury",
"Args": ".",
"Size": 2,
"Doc": "Replace the Nth (signed) value from the frame pointer in the stack",
"ImmediateNote": "{int8 frame slot}",
"Groups": [
"Flow Control"
]
},
{
"Opcode": 243,
"Name": "bury",
"Args": ".",
"Size": 2,
"Doc": "Replace the Nth value from the top of the stack. bury 0 fails.",
"ImmediateNote": "{uint8 depth}",
"Groups": [
"Flow Control"
]
}
]
}
18 changes: 8 additions & 10 deletions data/transactions/logic/opcodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ const appAddressAvailableVersion = 7

const fidoVersion = 7 // base64, json, secp256r1
const randomnessVersion = 7 // vrf_verify, block
const fpVersion = 8 // changes for frame pointers and simpler function discipline

// EXPERIMENTAL. These should be revisited whenever a new LogicSigVersion is
// moved from vFuture to a new consensus version. If they remain unready, bump
// their version, and fixup TestAssemble() in assembler_test.go.
const pairingVersion = 9 // bn256 opcodes. will add bls12-381, and unify the available opcodes.
const fpVersion = 8 // changes for frame pointers and simpler function discipline

type linearCost struct {
baseCost int
Expand Down Expand Up @@ -499,6 +499,7 @@ var OpSpecs = []OpSpec{
{0x42, "b", opB, proto(":"), 2, detBranch()},
{0x43, "return", opReturn, proto("i:x"), 2, detDefault()},
{0x44, "assert", opAssert, proto("i:"), 3, detDefault()},
{0x45, "bury", opBury, proto("a:"), fpVersion, immediates("n").typed(typeBury)},
{0x46, "popn", opPopN, proto(":", "[N items]", ""), fpVersion, immediates("n").typed(typePopN).trust()},
{0x47, "dupn", opDupN, proto("a:", "", "A, b[N copies of A]"), fpVersion, immediates("n").typed(typeDupN).trust()},
{0x48, "pop", opPop, proto("a:"), 1, detDefault()},
Expand All @@ -525,7 +526,6 @@ var OpSpecs = []OpSpec{
{0x5b, "extract_uint64", opExtract64Bits, proto("bi:i"), 5, detDefault()},
{0x5c, "replace2", opReplace2, proto("bb:b"), 7, immediates("s")},
{0x5d, "replace3", opReplace3, proto("bib:b"), 7, detDefault()},

{0x5e, "base64_decode", opBase64Decode, proto("b:b"), fidoVersion, field("e", &Base64Encodings).costByLength(1, 1, 16, 0)},
{0x5f, "json_ref", opJSONRef, proto("bb:a"), fidoVersion, field("r", &JSONRefTypes).costByLength(25, 2, 7, 1)},

Expand Down Expand Up @@ -564,8 +564,12 @@ var OpSpecs = []OpSpec{
// "Function oriented"
{0x88, "callsub", opCallSub, proto(":"), 4, detBranch()},
{0x89, "retsub", opRetSub, proto(":"), 4, detDefault().trust()},
{0x8a, "switch", opSwitch, proto("i:"), 8, detSwitch()},
// 0x8b will likely be a switch on pairs of values/targets, called `match`
// protoByte is a named constant because opCallSub needs to know it.
{protoByte, "proto", opProto, proto(":"), fpVersion, immediates("a", "r").typed(typeProto)},
{0x8b, "frame_dig", opFrameDig, proto(":a"), fpVersion, immKinded(immInt8, "i").typed(typeFrameDig)},
{0x8c, "frame_bury", opFrameBury, proto("a:"), fpVersion, immKinded(immInt8, "i").typed(typeFrameBury)},
{0x8d, "switch", opSwitch, proto("i:"), 8, detSwitch()},
// 0x8e will likely be a switch on pairs of values/targets, called `match`

// More math
{0x90, "shl", opShiftLeft, proto("ii:i"), 4, detDefault()},
Expand Down Expand Up @@ -626,12 +630,6 @@ var OpSpecs = []OpSpec{
// randomness support
{0xd0, "vrf_verify", opVrfVerify, proto("bbb:bi"), randomnessVersion, field("s", &VrfStandards).costs(5700)},
{0xd1, "block", opBlock, proto("i:a"), randomnessVersion, field("f", &BlockFields)},

// protoByte is a named constant because opCallsub needs to know it.
{protoByte, "proto", opProto, proto(":"), fpVersion, immediates("a", "r").typed(typeProto)},
{0xf1, "frame_dig", opFrameDig, proto(":a"), fpVersion, immKinded(immInt8, "i").typed(typeFrameDig)},
{0xf2, "frame_bury", opFrameBury, proto("a:"), fpVersion, immKinded(immInt8, "i").typed(typeFrameBury)},
{0xf3, "bury", opBury, proto("a:"), fpVersion, immediates("n").typed(typeBury)},
}

type sortByOpcode []OpSpec
Expand Down

0 comments on commit 21ff73b

Please sign in to comment.