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

Enhancement: Add missing ArgEnum fields, tweaks to immediate note #4903

Merged
merged 4 commits into from
Dec 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 23 additions & 4 deletions cmd/opdoc/opdoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,14 +270,20 @@ func typeString(types []logic.StackType) string {
case logic.StackAny:
out[i] = '.'
case logic.StackNone:
if i == 0 && len(types) == 1 {
return ""
}
panic("unexpected StackNone in opdoc typeString")
out[i] = '_'
default:
panic("unexpected type in opdoc typeString")
}
}

// Cant return None and !None from same op
if strings.Contains(string(out), "_") {
if strings.ContainsAny(string(out), "UB.") {
panic("unexpected StackNone in opdoc typeString")
}
return ""
}

return string(out)
}

Expand All @@ -295,6 +301,9 @@ func fieldsAndTypes(group logic.FieldGroup) ([]string, string) {
}

func argEnums(name string) ([]string, string) {
// reminder: this needs to be manually updated every time
// a new opcode is added with an associated FieldGroup
// it'd be nice to have this auto-update
switch name {
case "txn", "gtxn", "gtxns", "itxn", "gitxn":
return fieldsAndTypes(logic.TxnFields)
Expand All @@ -314,6 +323,16 @@ func argEnums(name string) ([]string, string) {
return fieldsAndTypes(logic.AppParamsFields)
case "acct_params_get":
return fieldsAndTypes(logic.AcctParamsFields)
case "block":
return fieldsAndTypes(logic.BlockFields)
case "json_ref":
return fieldsAndTypes(logic.JSONRefTypes)
case "base64_decode":
return fieldsAndTypes(logic.Base64Encodings)
case "vrf_verify":
return fieldsAndTypes(logic.VrfStandards)
case "ecdsa_pk_recover", "ecdsa_verify", "ecdsa_pk_decompress":
return fieldsAndTypes(logic.EcdsaCurves)
default:
return nil, ""
}
Expand Down
10 changes: 5 additions & 5 deletions data/transactions/logic/TEAL_opcodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ The notation J,K indicates that two uint64 values J and K are interpreted as a u

## bytecblock bytes ...

- Opcode: 0x26 {varuint count} [({varuint value length} bytes), ...]
- Opcode: 0x26 {varuint count} [({varuint length} bytes), ...]
- Stack: ... → ...
- prepare block of byte-array constants for use by bytec

Expand Down Expand Up @@ -318,7 +318,7 @@ The notation J,K indicates that two uint64 values J and K are interpreted as a u

## arg n

- Opcode: 0x2c {uint8 arg index N}
- Opcode: 0x2c {uint8 arg index}
- Stack: ... → ..., []byte
- Nth LogicSig argument
- Mode: Signature
Expand Down Expand Up @@ -811,7 +811,7 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on

## json_ref r

- Opcode: 0x5f {uint8 return type}
- Opcode: 0x5f {uint8 return type index}
- Stack: ..., A: []byte, B: []byte → ..., any
- key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A
- **Cost**: 25 + 2 per 7 bytes of A
Expand Down Expand Up @@ -1059,7 +1059,7 @@ pushint args are not added to the intcblock during assembly processes

## pushbytess bytes ...

- Opcode: 0x82 {varuint count} [({varuint value length} bytes), ...]
- Opcode: 0x82 {varuint count} [({varuint length} bytes), ...]
- Stack: ... → ..., [N items]
- push sequences of immediate byte arrays to stack (first byte array being deepest)
- Availability: v8
Expand Down Expand Up @@ -1548,7 +1548,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo

## block f

- Opcode: 0xd1 {uint8 block field}
- Opcode: 0xd1 {uint8 block field index}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with this change (and similar, above) I suppose, but don't love it. The word "index" helps to convey that the encoding here is a number that is an index into an arbitrary list of fields, defined elsewhere. Without it, a reasonable person could ask, "What do you mean, how do I encode a field?"

On the other hand, it's not as though having the word index there makes it obvious what's going on.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

open to other suggestions, option?

- Stack: ..., A: uint64 → ..., any
- field F of block A. Fail unless A falls between txn.LastValid-1002 and txn.FirstValid (exclusive)
- Availability: v7
Expand Down
10 changes: 5 additions & 5 deletions data/transactions/logic/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,12 @@ var opcodeImmediateNotes = map[string]string{
"intc": "{uint8 int constant index}",
"pushint": "{varuint int}",
"pushints": "{varuint count} [{varuint value}, ...]",
"bytecblock": "{varuint count} [({varuint value length} bytes), ...]",
"bytecblock": "{varuint count} [({varuint length} bytes), ...]",
"bytec": "{uint8 byte constant index}",
"pushbytes": "{varuint length} {bytes}",
"pushbytess": "{varuint count} [({varuint value length} bytes), ...]",
"pushbytess": "{varuint count} [({varuint length} bytes), ...]",

"arg": "{uint8 arg index N}",
"arg": "{uint8 arg index}",
"global": "{uint8 global field index}",

"txn": "{uint8 transaction field index}",
Expand Down Expand Up @@ -279,10 +279,10 @@ var opcodeImmediateNotes = map[string]string{
"ecdsa_pk_recover": "{uint8 curve index}",

"base64_decode": "{uint8 encoding index}",
"json_ref": "{uint8 return type}",
"json_ref": "{uint8 return type index}",

"vrf_verify": "{uint8 parameters index}",
"block": "{uint8 block field}",
"block": "{uint8 block field index}",

"switch": "{uint8 branch count} [{int16 branch offset, big-endian}, ...]",
"match": "{uint8 branch count} [{int16 branch offset, big-endian}, ...]",
Expand Down
41 changes: 36 additions & 5 deletions data/transactions/logic/langspec.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@
"Args": "BBBBB",
"Returns": "U",
"Size": 2,
"ArgEnum": [
"Secp256k1",
"Secp256r1"
],
"Doc": "for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey =\u003e {0 or 1}",
"DocExtra": "The 32 byte Y-component of a public key is the last element on the stack, preceded by X-component of a pubkey, preceded by S and R components of a signature, preceded by the data that is fifth element on the stack. All values are big-endian encoded. The signed data must be 32 bytes long, and signatures in lower-S form are only accepted.",
"ImmediateNote": "{uint8 curve index}",
Expand All @@ -81,6 +85,10 @@
"Args": "B",
"Returns": "BB",
"Size": 2,
"ArgEnum": [
"Secp256k1",
"Secp256r1"
],
"Doc": "decompress pubkey A into components X, Y",
"DocExtra": "The 33 byte public key in a compressed form to be decompressed into X and Y (top) components. All values are big-endian encoded.",
"ImmediateNote": "{uint8 curve index}",
Expand All @@ -95,6 +103,10 @@
"Args": "BUBB",
"Returns": "BB",
"Size": 2,
"ArgEnum": [
"Secp256k1",
"Secp256r1"
],
"Doc": "for (data A, recovery id B, signature C, D) recover a public key",
"DocExtra": "S (top) and R elements of a signature, recovery id and data (bottom) are expected on the stack and used to deriver a public key. All values are big-endian encoded. The signed data must be 32 bytes long.",
"ImmediateNote": "{uint8 curve index}",
Expand Down Expand Up @@ -470,7 +482,7 @@
"Size": 0,
"Doc": "prepare block of byte-array constants for use by bytec",
"DocExtra": "`bytecblock` loads the following program bytes into an array of byte-array constants in the evaluator. These constants can be referred to by `bytec` and `bytec_*` which will push the value onto the stack. Subsequent calls to `bytecblock` reset and replace the bytes constants available to the script.",
"ImmediateNote": "{varuint count} [({varuint value length} bytes), ...]",
"ImmediateNote": "{varuint count} [({varuint length} bytes), ...]",
"IntroducedVersion": 1,
"Groups": [
"Loading Values"
Expand Down Expand Up @@ -538,7 +550,7 @@
"Returns": "B",
"Size": 2,
"Doc": "Nth LogicSig argument",
"ImmediateNote": "{uint8 arg index N}",
"ImmediateNote": "{uint8 arg index}",
"IntroducedVersion": 1,
"Groups": [
"Loading Values"
Expand Down Expand Up @@ -1410,6 +1422,11 @@
"Args": "B",
"Returns": "B",
"Size": 2,
"ArgEnum": [
"URLEncoding",
"StdEncoding"
],
"ArgEnumTypes": "..",
"Doc": "decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E",
"DocExtra": "*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings.\tThis opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
"ImmediateNote": "{uint8 encoding index}",
Expand All @@ -1424,9 +1441,15 @@
"Args": "BB",
"Returns": ".",
"Size": 2,
"ArgEnum": [
"JSONString",
"JSONUint64",
"JSONObject"
],
"ArgEnumTypes": "BUB",
"Doc": "key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A",
"DocExtra": "*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
"ImmediateNote": "{uint8 return type}",
"ImmediateNote": "{uint8 return type index}",
"IntroducedVersion": 7,
"Groups": [
"Byte Array Manipulation"
Expand Down Expand Up @@ -1704,7 +1727,7 @@
"Size": 0,
"Doc": "push sequences of immediate byte arrays to stack (first byte array being deepest)",
"DocExtra": "pushbytess args are not added to the bytecblock during assembly processes",
"ImmediateNote": "{varuint count} [({varuint value length} bytes), ...]",
"ImmediateNote": "{varuint count} [({varuint length} bytes), ...]",
"IntroducedVersion": 8,
"Groups": [
"Loading Values"
Expand Down Expand Up @@ -2651,6 +2674,9 @@
"Args": "BBB",
"Returns": "BU",
"Size": 2,
"ArgEnum": [
"VrfAlgorand"
],
"Doc": "Verify the proof B of message A against pubkey C. Returns vrf output and verification flag.",
"DocExtra": "`VrfAlgorand` is the VRF used in Algorand. It is ECVRF-ED25519-SHA512-Elligator2, specified in the IETF internet draft [draft-irtf-cfrg-vrf-03](https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/03/).",
"ImmediateNote": "{uint8 parameters index}",
Expand All @@ -2665,8 +2691,13 @@
"Args": "U",
"Returns": ".",
"Size": 2,
"ArgEnum": [
"BlkSeed",
"BlkTimestamp"
],
"ArgEnumTypes": "BU",
"Doc": "field F of block A. Fail unless A falls between txn.LastValid-1002 and txn.FirstValid (exclusive)",
"ImmediateNote": "{uint8 block field}",
"ImmediateNote": "{uint8 block field index}",
"IntroducedVersion": 7,
"Groups": [
"State Access"
Expand Down