diff --git a/cmd/opdoc/opdoc.go b/cmd/opdoc/opdoc.go index 58d32705b2..aaa55c5d2d 100644 --- a/cmd/opdoc/opdoc.go +++ b/cmd/opdoc/opdoc.go @@ -466,7 +466,7 @@ func main() { AVMType: t.AVMType.String(), }) } - sort.Slice(named, func(i, j int) bool { return named[i].Name > named[j].Name }) + sort.Slice(named, func(i, j int) bool { return named[i].Name < named[j].Name }) constants := create("named_integer_constants.md") integerConstantsTableMarkdown(constants) diff --git a/cmd/opdoc/tmLanguage.go b/cmd/opdoc/tmLanguage.go index fb14381016..63c558ea3d 100644 --- a/cmd/opdoc/tmLanguage.go +++ b/cmd/opdoc/tmLanguage.go @@ -205,7 +205,7 @@ func buildSyntaxHighlight(version uint64) *tmLanguage { // and only add to keyword.Patterns later, when all // have been collected. case "Arithmetic", "Byte Array Manipulation", "Byte Array Arithmetic", - "Byte Array Logic", "Inner Transactions": + "Byte Array Logic", "Cryptography", "Inner Transactions": escape := map[rune]bool{ '*': true, '+': true, diff --git a/crypto/onetimesig.go b/crypto/onetimesig.go index 344fd33f77..1de4854967 100644 --- a/crypto/onetimesig.go +++ b/crypto/onetimesig.go @@ -35,8 +35,8 @@ import ( // of a secret-key compromise. type OneTimeSignature struct { // Unfortunately we forgot to mark this struct as omitempty at - // one point, and now it's hard to recover from that if we want - // to preserve encodings.. + // one point, and now it's hard to change if we want to preserve + // encodings. _struct struct{} `codec:""` // Sig is a signature of msg under the key PK. diff --git a/data/transactions/logic/README.md b/data/transactions/logic/README.md index 07b4a078be..1ec45b6e2c 100644 --- a/data/transactions/logic/README.md +++ b/data/transactions/logic/README.md @@ -52,17 +52,19 @@ assembly time to do type checking and to provide more informative error messages | Name | Bound | AVM Type | | ---- | ---- | -------- | -| uint64 | x <= 18446744073709551615 | uint64 | -| stateKey | len(x) <= 64 | []byte | -| none | | none | -| method | len(x) == 4 | []byte | -| boxName | 1 <= len(x) <= 64 | []byte | -| bool | x <= 1 | uint64 | -| bigint | len(x) <= 64 | []byte | -| any | | any | -| address | len(x) == 32 | []byte | -| []byte | len(x) <= 4096 | []byte | | [32]byte | len(x) == 32 | []byte | +| [64]byte | len(x) == 64 | []byte | +| [80]byte | len(x) == 80 | []byte | +| []byte | len(x) <= 4096 | []byte | +| address | len(x) == 32 | []byte | +| any | | any | +| bigint | len(x) <= 64 | []byte | +| bool | x <= 1 | uint64 | +| boxName | 1 <= len(x) <= 64 | []byte | +| method | len(x) == 4 | []byte | +| none | | none | +| stateKey | len(x) <= 64 | []byte | +| uint64 | x <= 18446744073709551615 | uint64 | @@ -359,26 +361,10 @@ an opcode manipulates the stack in such a way that a value changes position but is otherwise unchanged, the name of the output on the return stack matches the name of the input value. -### Arithmetic, Logic, and Cryptographic Operations +### Arithmetic and Logic Operations | Opcode | Description | | - | -- | -| `sha256` | SHA256 hash of value A, yields [32]byte | -| `keccak256` | Keccak256 hash of value A, yields [32]byte | -| `sha512_256` | SHA512_256 hash of value A, yields [32]byte | -| `sha3_256` | SHA3_256 hash of value A, yields [32]byte | -| `ed25519verify` | for (data A, signature B, pubkey C) verify the signature of ("ProgData" \|\| program_hash \|\| data) against the pubkey => {0 or 1} | -| `ed25519verify_bare` | for (data A, signature B, pubkey C) verify the signature of the data against the pubkey => {0 or 1} | -| `ecdsa_verify v` | for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1} | -| `ecdsa_pk_recover v` | for (data A, recovery id B, signature C, D) recover a public key | -| `ecdsa_pk_decompress v` | decompress pubkey A into components X, Y | -| `vrf_verify s` | Verify the proof B of message A against pubkey C. Returns vrf output and verification flag. | -| `ec_add g` | for curve points A and B, return the curve point A + B | -| `ec_scalar_mul g` | for curve point A and scalar B, return the curve point BA, the point A multiplied by the scalar B. | -| `ec_pairing_check g` | 1 if the product of the pairing of each point in A with its respective point in B is equal to the identity element of the target group Gt, else 0 | -| `ec_multi_scalar_mul g` | for curve points A and scalars B, return curve point B0A0 + B1A1 + B2A2 + ... + BnAn | -| `ec_subgroup_check g` | 1 if A is in the main prime-order subgroup of G (including the point at infinity) else 0. Program fails if A is not in G at all. | -| `ec_map_to g` | maps field element A to group G | | `+` | A plus B. Fail on overflow. | | `-` | A minus B. Fail if B > A. | | `/` | A divided by B (truncated division). Fail if B == 0. | @@ -397,7 +383,6 @@ return stack matches the name of the input value. | `==` | A is equal to B => {0 or 1} | | `!=` | A is not equal to B => {0 or 1} | | `!` | A == 0 yields 1; else 0 | -| `len` | yields length of byte value A | | `itob` | converts uint64 A to big-endian byte array, always of length 8 | | `btoi` | converts big-endian byte array A to uint64. Fails if len(A) > 8. Padded by leading 0s if len(A) < 8. | | `%` | A modulo B. Fail if B == 0. | @@ -410,16 +395,17 @@ return stack matches the name of the input value. | `divw` | A,B / C. Fail if C == 0 or if result overflows. | | `divmodw` | W,X = (A,B / C,D); Y,Z = (A,B modulo C,D) | | `expw` | A raised to the Bth power as a 128-bit result in two uint64s. X is the high 64 bits, Y is the low. Fail if A == B == 0 or if the results exceeds 2^128-1 | -| `getbit` | Bth bit of (byte-array or integer) A. If B is greater than or equal to the bit length of the value (8*byte length), the program fails | -| `setbit` | Copy of (byte-array or integer) A, with the Bth bit set to (0 or 1) C. If B is greater than or equal to the bit length of the value (8*byte length), the program fails | -| `getbyte` | Bth byte of A, as an integer. If B is greater than or equal to the array length, the program fails | -| `setbyte` | Copy of A with the Bth byte set to small integer (between 0..255) C. If B is greater than or equal to the array length, the program fails | -| `concat` | join A and B | ### Byte Array Manipulation | Opcode | Description | | - | -- | +| `getbit` | Bth bit of (byte-array or integer) A. If B is greater than or equal to the bit length of the value (8*byte length), the program fails | +| `setbit` | Copy of (byte-array or integer) A, with the Bth bit set to (0 or 1) C. If B is greater than or equal to the bit length of the value (8*byte length), the program fails | +| `getbyte` | Bth byte of A, as an integer. If B is greater than or equal to the array length, the program fails | +| `setbyte` | Copy of A with the Bth byte set to small integer (between 0..255) C. If B is greater than or equal to the array length, the program fails | +| `concat` | join A and B | +| `len` | yields length of byte value A | | `substring s e` | A range of bytes from A starting at S up to but not including E. If E < S, or either is larger than the array length, the program fails | | `substring3` | A range of bytes from A starting at B up to but not including C. If C < B, or either is larger than the array length, the program fails | | `extract s l` | A range of bytes from A starting at S up to but not including S+L. If L is 0, then extract to the end of the string. If S or S+L is larger than the array length, the program fails | @@ -472,6 +458,27 @@ these results may contain leading zero bytes. | `b^` | A bitwise-xor B. A and B are zero-left extended to the greater of their lengths | | `b~` | A with all bits inverted | +### Cryptographic Operations + +| Opcode | Description | +| - | -- | +| `sha256` | SHA256 hash of value A, yields [32]byte | +| `keccak256` | Keccak256 hash of value A, yields [32]byte | +| `sha512_256` | SHA512_256 hash of value A, yields [32]byte | +| `sha3_256` | SHA3_256 hash of value A, yields [32]byte | +| `ed25519verify` | for (data A, signature B, pubkey C) verify the signature of ("ProgData" \|\| program_hash \|\| data) against the pubkey => {0 or 1} | +| `ed25519verify_bare` | for (data A, signature B, pubkey C) verify the signature of the data against the pubkey => {0 or 1} | +| `ecdsa_verify v` | for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1} | +| `ecdsa_pk_recover v` | for (data A, recovery id B, signature C, D) recover a public key | +| `ecdsa_pk_decompress v` | decompress pubkey A into components X, Y | +| `vrf_verify s` | Verify the proof B of message A against pubkey C. Returns vrf output and verification flag. | +| `ec_add g` | for curve points A and B, return the curve point A + B | +| `ec_scalar_mul g` | for curve point A and scalar B, return the curve point BA, the point A multiplied by the scalar B. | +| `ec_pairing_check g` | 1 if the product of the pairing of each point in A with its respective point in B is equal to the identity element of the target group Gt, else 0 | +| `ec_multi_scalar_mul g` | for curve points A and scalars B, return curve point B0A0 + B1A1 + B2A2 + ... + BnAn | +| `ec_subgroup_check g` | 1 if A is in the main prime-order subgroup of G (including the point at infinity) else 0. Program fails if A is not in G at all. | +| `ec_map_to g` | maps field element A to group G | + ### Loading Values Opcodes for getting data onto the stack. diff --git a/data/transactions/logic/README_in.md b/data/transactions/logic/README_in.md index 04c67758cc..ecbf2c6bbb 100644 --- a/data/transactions/logic/README_in.md +++ b/data/transactions/logic/README_in.md @@ -320,7 +320,7 @@ an opcode manipulates the stack in such a way that a value changes position but is otherwise unchanged, the name of the output on the return stack matches the name of the input value. -### Arithmetic, Logic, and Cryptographic Operations +### Arithmetic and Logic Operations @@ Arithmetic.md @@ @@ -350,6 +350,10 @@ these results may contain leading zero bytes. @@ Byte_Array_Logic.md @@ +### Cryptographic Operations + +@@ Cryptography.md @@ + ### Loading Values Opcodes for getting data onto the stack. diff --git a/data/transactions/logic/TEAL_opcodes_v1.md b/data/transactions/logic/TEAL_opcodes_v1.md index f9ef580cfc..d98190643b 100644 --- a/data/transactions/logic/TEAL_opcodes_v1.md +++ b/data/transactions/logic/TEAL_opcodes_v1.md @@ -33,7 +33,7 @@ Ops have a 'cost' of 1 unless otherwise specified. ## ed25519verify - Bytecode: 0x04 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of ("ProgData" || program_hash || data) against the pubkey => {0 or 1} - **Cost**: 1900 - Mode: Signature diff --git a/data/transactions/logic/TEAL_opcodes_v10.md b/data/transactions/logic/TEAL_opcodes_v10.md index 31beb6c388..4ec00a52bb 100644 --- a/data/transactions/logic/TEAL_opcodes_v10.md +++ b/data/transactions/logic/TEAL_opcodes_v10.md @@ -33,7 +33,7 @@ Ops have a 'cost' of 1 unless otherwise specified. ## ed25519verify - Bytecode: 0x04 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of ("ProgData" || program_hash || data) against the pubkey => {0 or 1} - **Cost**: 1900 @@ -43,7 +43,7 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte - Syntax: `ecdsa_verify V` ∋ V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x05 {uint8} -- Stack: ..., A: []byte, B: []byte, C: []byte, D: []byte, E: []byte → ..., bool +- Stack: ..., A: [32]byte, B: []byte, C: []byte, D: []byte, E: []byte → ..., bool - for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1} - **Cost**: Secp256k1=1700; Secp256r1=2500 - Availability: v5 @@ -75,7 +75,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top - Syntax: `ecdsa_pk_recover V` ∋ V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x07 {uint8} -- Stack: ..., A: []byte, B: uint64, C: []byte, D: []byte → ..., X: []byte, Y: []byte +- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: []byte, Y: []byte - for (data A, recovery id B, signature C, D) recover a public key - **Cost**: 2000 - Availability: v5 @@ -1136,7 +1136,7 @@ pushints args are not added to the intcblock during assembly processes ## ed25519verify_bare - Bytecode: 0x84 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of the data against the pubkey => {0 or 1} - **Cost**: 1900 - Availability: v7 @@ -1607,7 +1607,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo - Syntax: `vrf_verify S` ∋ S: [vrf_verify](#field-group-vrf_verify) - Bytecode: 0xd0 {uint8} -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., X: []byte, Y: bool +- Stack: ..., A: []byte, B: [80]byte, C: [32]byte → ..., X: []byte, Y: bool - Verify the proof B of message A against pubkey C. Returns vrf output and verification flag. - **Cost**: 5700 - Availability: v7 diff --git a/data/transactions/logic/TEAL_opcodes_v2.md b/data/transactions/logic/TEAL_opcodes_v2.md index 52e65591bc..180f899be8 100644 --- a/data/transactions/logic/TEAL_opcodes_v2.md +++ b/data/transactions/logic/TEAL_opcodes_v2.md @@ -33,7 +33,7 @@ Ops have a 'cost' of 1 unless otherwise specified. ## ed25519verify - Bytecode: 0x04 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of ("ProgData" || program_hash || data) against the pubkey => {0 or 1} - **Cost**: 1900 - Mode: Signature diff --git a/data/transactions/logic/TEAL_opcodes_v3.md b/data/transactions/logic/TEAL_opcodes_v3.md index c09a75df18..9915f61027 100644 --- a/data/transactions/logic/TEAL_opcodes_v3.md +++ b/data/transactions/logic/TEAL_opcodes_v3.md @@ -33,7 +33,7 @@ Ops have a 'cost' of 1 unless otherwise specified. ## ed25519verify - Bytecode: 0x04 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of ("ProgData" || program_hash || data) against the pubkey => {0 or 1} - **Cost**: 1900 - Mode: Signature diff --git a/data/transactions/logic/TEAL_opcodes_v4.md b/data/transactions/logic/TEAL_opcodes_v4.md index 96e51dee04..3da0bcba03 100644 --- a/data/transactions/logic/TEAL_opcodes_v4.md +++ b/data/transactions/logic/TEAL_opcodes_v4.md @@ -33,7 +33,7 @@ Ops have a 'cost' of 1 unless otherwise specified. ## ed25519verify - Bytecode: 0x04 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of ("ProgData" || program_hash || data) against the pubkey => {0 or 1} - **Cost**: 1900 - Mode: Signature diff --git a/data/transactions/logic/TEAL_opcodes_v5.md b/data/transactions/logic/TEAL_opcodes_v5.md index 012d504ce1..584e8bc1f0 100644 --- a/data/transactions/logic/TEAL_opcodes_v5.md +++ b/data/transactions/logic/TEAL_opcodes_v5.md @@ -33,7 +33,7 @@ Ops have a 'cost' of 1 unless otherwise specified. ## ed25519verify - Bytecode: 0x04 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of ("ProgData" || program_hash || data) against the pubkey => {0 or 1} - **Cost**: 1900 @@ -43,7 +43,7 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte - Syntax: `ecdsa_verify V` ∋ V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x05 {uint8} -- Stack: ..., A: []byte, B: []byte, C: []byte, D: []byte, E: []byte → ..., bool +- Stack: ..., A: [32]byte, B: []byte, C: []byte, D: []byte, E: []byte → ..., bool - for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1} - **Cost**: Secp256k1=1700 - Availability: v5 @@ -74,7 +74,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top - Syntax: `ecdsa_pk_recover V` ∋ V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x07 {uint8} -- Stack: ..., A: []byte, B: uint64, C: []byte, D: []byte → ..., X: []byte, Y: []byte +- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: []byte, Y: []byte - for (data A, recovery id B, signature C, D) recover a public key - **Cost**: 2000 - Availability: v5 diff --git a/data/transactions/logic/TEAL_opcodes_v6.md b/data/transactions/logic/TEAL_opcodes_v6.md index d21931430c..eab29a84cb 100644 --- a/data/transactions/logic/TEAL_opcodes_v6.md +++ b/data/transactions/logic/TEAL_opcodes_v6.md @@ -33,7 +33,7 @@ Ops have a 'cost' of 1 unless otherwise specified. ## ed25519verify - Bytecode: 0x04 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of ("ProgData" || program_hash || data) against the pubkey => {0 or 1} - **Cost**: 1900 @@ -43,7 +43,7 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte - Syntax: `ecdsa_verify V` ∋ V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x05 {uint8} -- Stack: ..., A: []byte, B: []byte, C: []byte, D: []byte, E: []byte → ..., bool +- Stack: ..., A: [32]byte, B: []byte, C: []byte, D: []byte, E: []byte → ..., bool - for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1} - **Cost**: Secp256k1=1700 - Availability: v5 @@ -74,7 +74,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top - Syntax: `ecdsa_pk_recover V` ∋ V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x07 {uint8} -- Stack: ..., A: []byte, B: uint64, C: []byte, D: []byte → ..., X: []byte, Y: []byte +- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: []byte, Y: []byte - for (data A, recovery id B, signature C, D) recover a public key - **Cost**: 2000 - Availability: v5 diff --git a/data/transactions/logic/TEAL_opcodes_v7.md b/data/transactions/logic/TEAL_opcodes_v7.md index 41b1468ae5..5eb79e38f3 100644 --- a/data/transactions/logic/TEAL_opcodes_v7.md +++ b/data/transactions/logic/TEAL_opcodes_v7.md @@ -33,7 +33,7 @@ Ops have a 'cost' of 1 unless otherwise specified. ## ed25519verify - Bytecode: 0x04 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of ("ProgData" || program_hash || data) against the pubkey => {0 or 1} - **Cost**: 1900 @@ -43,7 +43,7 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte - Syntax: `ecdsa_verify V` ∋ V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x05 {uint8} -- Stack: ..., A: []byte, B: []byte, C: []byte, D: []byte, E: []byte → ..., bool +- Stack: ..., A: [32]byte, B: []byte, C: []byte, D: []byte, E: []byte → ..., bool - for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1} - **Cost**: Secp256k1=1700; Secp256r1=2500 - Availability: v5 @@ -75,7 +75,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top - Syntax: `ecdsa_pk_recover V` ∋ V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x07 {uint8} -- Stack: ..., A: []byte, B: uint64, C: []byte, D: []byte → ..., X: []byte, Y: []byte +- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: []byte, Y: []byte - for (data A, recovery id B, signature C, D) recover a public key - **Cost**: 2000 - Availability: v5 @@ -1081,7 +1081,7 @@ pushint args are not added to the intcblock during assembly processes ## ed25519verify_bare - Bytecode: 0x84 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of the data against the pubkey => {0 or 1} - **Cost**: 1900 - Availability: v7 @@ -1446,7 +1446,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with - Syntax: `vrf_verify S` ∋ S: [vrf_verify](#field-group-vrf_verify) - Bytecode: 0xd0 {uint8} -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., X: []byte, Y: bool +- Stack: ..., A: []byte, B: [80]byte, C: [32]byte → ..., X: []byte, Y: bool - Verify the proof B of message A against pubkey C. Returns vrf output and verification flag. - **Cost**: 5700 - Availability: v7 diff --git a/data/transactions/logic/TEAL_opcodes_v8.md b/data/transactions/logic/TEAL_opcodes_v8.md index b2d1b851d6..b8efb37fa3 100644 --- a/data/transactions/logic/TEAL_opcodes_v8.md +++ b/data/transactions/logic/TEAL_opcodes_v8.md @@ -33,7 +33,7 @@ Ops have a 'cost' of 1 unless otherwise specified. ## ed25519verify - Bytecode: 0x04 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of ("ProgData" || program_hash || data) against the pubkey => {0 or 1} - **Cost**: 1900 @@ -43,7 +43,7 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte - Syntax: `ecdsa_verify V` ∋ V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x05 {uint8} -- Stack: ..., A: []byte, B: []byte, C: []byte, D: []byte, E: []byte → ..., bool +- Stack: ..., A: [32]byte, B: []byte, C: []byte, D: []byte, E: []byte → ..., bool - for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1} - **Cost**: Secp256k1=1700; Secp256r1=2500 - Availability: v5 @@ -75,7 +75,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top - Syntax: `ecdsa_pk_recover V` ∋ V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x07 {uint8} -- Stack: ..., A: []byte, B: uint64, C: []byte, D: []byte → ..., X: []byte, Y: []byte +- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: []byte, Y: []byte - for (data A, recovery id B, signature C, D) recover a public key - **Cost**: 2000 - Availability: v5 @@ -1134,7 +1134,7 @@ pushints args are not added to the intcblock during assembly processes ## ed25519verify_bare - Bytecode: 0x84 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of the data against the pubkey => {0 or 1} - **Cost**: 1900 - Availability: v7 @@ -1605,7 +1605,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo - Syntax: `vrf_verify S` ∋ S: [vrf_verify](#field-group-vrf_verify) - Bytecode: 0xd0 {uint8} -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., X: []byte, Y: bool +- Stack: ..., A: []byte, B: [80]byte, C: [32]byte → ..., X: []byte, Y: bool - Verify the proof B of message A against pubkey C. Returns vrf output and verification flag. - **Cost**: 5700 - Availability: v7 diff --git a/data/transactions/logic/TEAL_opcodes_v9.md b/data/transactions/logic/TEAL_opcodes_v9.md index 231343564d..54f053686f 100644 --- a/data/transactions/logic/TEAL_opcodes_v9.md +++ b/data/transactions/logic/TEAL_opcodes_v9.md @@ -33,7 +33,7 @@ Ops have a 'cost' of 1 unless otherwise specified. ## ed25519verify - Bytecode: 0x04 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of ("ProgData" || program_hash || data) against the pubkey => {0 or 1} - **Cost**: 1900 @@ -43,7 +43,7 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte - Syntax: `ecdsa_verify V` ∋ V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x05 {uint8} -- Stack: ..., A: []byte, B: []byte, C: []byte, D: []byte, E: []byte → ..., bool +- Stack: ..., A: [32]byte, B: []byte, C: []byte, D: []byte, E: []byte → ..., bool - for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1} - **Cost**: Secp256k1=1700; Secp256r1=2500 - Availability: v5 @@ -75,7 +75,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top - Syntax: `ecdsa_pk_recover V` ∋ V: [ECDSA](#field-group-ecdsa) - Bytecode: 0x07 {uint8} -- Stack: ..., A: []byte, B: uint64, C: []byte, D: []byte → ..., X: []byte, Y: []byte +- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: []byte, Y: []byte - for (data A, recovery id B, signature C, D) recover a public key - **Cost**: 2000 - Availability: v5 @@ -1134,7 +1134,7 @@ pushints args are not added to the intcblock during assembly processes ## ed25519verify_bare - Bytecode: 0x84 -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., bool +- Stack: ..., A: []byte, B: [64]byte, C: [32]byte → ..., bool - for (data A, signature B, pubkey C) verify the signature of the data against the pubkey => {0 or 1} - **Cost**: 1900 - Availability: v7 @@ -1605,7 +1605,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo - Syntax: `vrf_verify S` ∋ S: [vrf_verify](#field-group-vrf_verify) - Bytecode: 0xd0 {uint8} -- Stack: ..., A: []byte, B: []byte, C: []byte → ..., X: []byte, Y: bool +- Stack: ..., A: []byte, B: [80]byte, C: [32]byte → ..., X: []byte, Y: bool - Verify the proof B of message A against pubkey C. Returns vrf output and verification flag. - **Cost**: 5700 - Availability: v7 diff --git a/data/transactions/logic/assembler_test.go b/data/transactions/logic/assembler_test.go index d983492501..0a6a0c1f89 100644 --- a/data/transactions/logic/assembler_test.go +++ b/data/transactions/logic/assembler_test.go @@ -518,7 +518,7 @@ func TestAssemble(t *testing.T) { // this month that we did last month. bytecode, ok := compiled[v] require.True(t, ok, "Need v%d bytecode", v) - expectedBytes, _ := hex.DecodeString(bytecode) + expectedBytes, _ := hex.DecodeString(strings.ReplaceAll(bytecode, " ", "")) require.NotEmpty(t, expectedBytes) // the hex is for convenience if the program has been changed. the // hex string can be copy pasted back in as a new expected result. diff --git a/data/transactions/logic/crypto.go b/data/transactions/logic/crypto.go new file mode 100644 index 0000000000..43fe4d50d5 --- /dev/null +++ b/data/transactions/logic/crypto.go @@ -0,0 +1,360 @@ +// Copyright (C) 2019-2023 Algorand, Inc. +// This file is part of go-algorand +// +// go-algorand is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// go-algorand is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with go-algorand. If not, see . + +package logic + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/sha256" + "crypto/sha512" + "errors" + "fmt" + "math/big" + + "github.com/algorand/go-algorand/crypto" + "github.com/algorand/go-algorand/crypto/secp256k1" + "github.com/algorand/go-algorand/protocol" + "golang.org/x/crypto/sha3" +) + +func opSHA256(cx *EvalContext) error { + last := len(cx.Stack) - 1 + hash := sha256.Sum256(cx.Stack[last].Bytes) + cx.Stack[last].Bytes = hash[:] + return nil +} + +// The NIST SHA3-256 is implemented for compatibility with ICON +func opSHA3_256(cx *EvalContext) error { + last := len(cx.Stack) - 1 + hash := sha3.Sum256(cx.Stack[last].Bytes) + cx.Stack[last].Bytes = hash[:] + return nil +} + +// The Keccak256 variant of SHA-3 is implemented for compatibility with Ethereum +func opKeccak256(cx *EvalContext) error { + last := len(cx.Stack) - 1 + hasher := sha3.NewLegacyKeccak256() + hasher.Write(cx.Stack[last].Bytes) + hv := make([]byte, 0, hasher.Size()) + hv = hasher.Sum(hv) + cx.Stack[last].Bytes = hv + return nil +} + +// This is the hash commonly used in Algorand in crypto/util.go Hash() +// +// It is explicitly implemented here in terms of the specific hash for +// stability and portability in case the rest of Algorand ever moves +// to a different default hash. For stability of this language, at +// that time a new opcode should be made with the new hash. +func opSHA512_256(cx *EvalContext) error { + last := len(cx.Stack) - 1 + hash := sha512.Sum512_256(cx.Stack[last].Bytes) + cx.Stack[last].Bytes = hash[:] + return nil +} + +// Msg is data meant to be signed and then verified with the +// ed25519verify opcode. +type Msg struct { + _struct struct{} `codec:",omitempty,omitemptyarray"` + ProgramHash crypto.Digest `codec:"p"` + Data []byte `codec:"d"` +} + +// ToBeHashed implements crypto.Hashable +func (msg Msg) ToBeHashed() (protocol.HashID, []byte) { + return protocol.ProgramData, append(msg.ProgramHash[:], msg.Data...) +} + +// programHash lets us lazily compute H(cx.program) +func (cx *EvalContext) programHash() crypto.Digest { + if cx.programHashCached == (crypto.Digest{}) { + cx.programHashCached = crypto.HashObj(Program(cx.program)) + } + return cx.programHashCached +} + +func opEd25519Verify(cx *EvalContext) error { + last := len(cx.Stack) - 1 // index of PK + prev := last - 1 // index of signature + pprev := prev - 1 // index of data + + var sv crypto.SignatureVerifier + if len(cx.Stack[last].Bytes) != len(sv) { + return errors.New("invalid public key") + } + copy(sv[:], cx.Stack[last].Bytes) + + var sig crypto.Signature + if len(cx.Stack[prev].Bytes) != len(sig) { + return errors.New("invalid signature") + } + copy(sig[:], cx.Stack[prev].Bytes) + + msg := Msg{ProgramHash: cx.programHash(), Data: cx.Stack[pprev].Bytes} + cx.Stack[pprev] = boolToSV(sv.Verify(msg, sig)) + cx.Stack = cx.Stack[:prev] + return nil +} + +func opEd25519VerifyBare(cx *EvalContext) error { + last := len(cx.Stack) - 1 // index of PK + prev := last - 1 // index of signature + pprev := prev - 1 // index of data + + var sv crypto.SignatureVerifier + if len(cx.Stack[last].Bytes) != len(sv) { + return errors.New("invalid public key") + } + copy(sv[:], cx.Stack[last].Bytes) + + var sig crypto.Signature + if len(cx.Stack[prev].Bytes) != len(sig) { + return errors.New("invalid signature") + } + copy(sig[:], cx.Stack[prev].Bytes) + + cx.Stack[pprev] = boolToSV(sv.VerifyBytes(cx.Stack[pprev].Bytes, sig)) + cx.Stack = cx.Stack[:prev] + return nil +} + +func leadingZeros(size int, b *big.Int) ([]byte, error) { + byteLength := (b.BitLen() + 7) / 8 + if size < byteLength { + return nil, fmt.Errorf("insufficient buffer size: %d < %d", size, byteLength) + } + buf := make([]byte, size) + b.FillBytes(buf) + return buf, nil +} + +var ecdsaVerifyCosts = []int{ + Secp256k1: 1700, + Secp256r1: 2500, +} + +var secp256r1 = elliptic.P256() + +func opEcdsaVerify(cx *EvalContext) error { + ecdsaCurve := EcdsaCurve(cx.program[cx.pc+1]) + fs, ok := ecdsaCurveSpecByField(ecdsaCurve) + if !ok || fs.version > cx.version { + return fmt.Errorf("invalid curve %d", ecdsaCurve) + } + + if fs.field != Secp256k1 && fs.field != Secp256r1 { + return fmt.Errorf("unsupported curve %d", fs.field) + } + + last := len(cx.Stack) - 1 // index of PK y + prev := last - 1 // index of PK x + pprev := prev - 1 // index of signature s + fourth := pprev - 1 // index of signature r + fifth := fourth - 1 // index of data + + pkY := cx.Stack[last].Bytes + pkX := cx.Stack[prev].Bytes + sigS := cx.Stack[pprev].Bytes + sigR := cx.Stack[fourth].Bytes + msg := cx.Stack[fifth].Bytes + + if len(msg) != 32 { + return fmt.Errorf("the signed data must be 32 bytes long, not %d", len(msg)) + } + + x := new(big.Int).SetBytes(pkX) + y := new(big.Int).SetBytes(pkY) + + var result bool + if fs.field == Secp256k1 { + signature := make([]byte, 0, len(sigR)+len(sigS)) + signature = append(signature, sigR...) + signature = append(signature, sigS...) + + pubkey := secp256k1.S256().Marshal(x, y) + result = secp256k1.VerifySignature(pubkey, msg, signature) + } else if fs.field == Secp256r1 { + if !cx.Proto.EnablePrecheckECDSACurve || secp256r1.IsOnCurve(x, y) { + pubkey := ecdsa.PublicKey{ + Curve: secp256r1, + X: x, + Y: y, + } + r := new(big.Int).SetBytes(sigR) + s := new(big.Int).SetBytes(sigS) + result = ecdsa.Verify(&pubkey, msg, r, s) + } + } + + cx.Stack[fifth] = boolToSV(result) + cx.Stack = cx.Stack[:fourth] + return nil +} + +var ecdsaDecompressCosts = []int{ + Secp256k1: 650, + Secp256r1: 2400, +} + +func opEcdsaPkDecompress(cx *EvalContext) error { + ecdsaCurve := EcdsaCurve(cx.program[cx.pc+1]) + fs, ok := ecdsaCurveSpecByField(ecdsaCurve) + if !ok || fs.version > cx.version { + return fmt.Errorf("invalid curve %d", ecdsaCurve) + } + + if fs.field != Secp256k1 && fs.field != Secp256r1 { + return fmt.Errorf("unsupported curve %d", fs.field) + } + + last := len(cx.Stack) - 1 // compressed PK + + pubkey := cx.Stack[last].Bytes + var x, y *big.Int + if fs.field == Secp256k1 { + x, y = secp256k1.DecompressPubkey(pubkey) + if x == nil { + return fmt.Errorf("invalid pubkey") + } + } else if fs.field == Secp256r1 { + x, y = elliptic.UnmarshalCompressed(elliptic.P256(), pubkey) + if x == nil { + return fmt.Errorf("invalid compressed pubkey") + } + } + + var err error + cx.Stack[last].Uint = 0 + cx.Stack[last].Bytes, err = leadingZeros(32, x) + if err != nil { + return fmt.Errorf("x component zeroing failed: %w", err) + } + + var sv stackValue + sv.Bytes, err = leadingZeros(32, y) + if err != nil { + return fmt.Errorf("y component zeroing failed: %w", err) + } + + cx.Stack = append(cx.Stack, sv) + return nil +} + +func opEcdsaPkRecover(cx *EvalContext) error { + ecdsaCurve := EcdsaCurve(cx.program[cx.pc+1]) + fs, ok := ecdsaCurveSpecByField(ecdsaCurve) + if !ok || fs.version > cx.version { + return fmt.Errorf("invalid curve %d", ecdsaCurve) + } + + if fs.field != Secp256k1 { + return fmt.Errorf("unsupported curve %d", fs.field) + } + + last := len(cx.Stack) - 1 // index of signature s + prev := last - 1 // index of signature r + pprev := prev - 1 // index of recovery id + fourth := pprev - 1 // index of data + + sigS := cx.Stack[last].Bytes + sigR := cx.Stack[prev].Bytes + recid := cx.Stack[pprev].Uint + msg := cx.Stack[fourth].Bytes + + if recid > 3 { + return fmt.Errorf("invalid recovery id: %d", recid) + } + + signature := make([]byte, 0, len(sigR)+len(sigS)+1) + signature = append(signature, sigR...) + signature = append(signature, sigS...) + signature = append(signature, uint8(recid)) + + pk, err := secp256k1.RecoverPubkey(msg, signature) + if err != nil { + return fmt.Errorf("pubkey recover failed: %s", err.Error()) + } + x, y := secp256k1.S256().Unmarshal(pk) + if x == nil { + return fmt.Errorf("pubkey unmarshal failed") + } + + cx.Stack[fourth].Uint = 0 + cx.Stack[fourth].Bytes, err = leadingZeros(32, x) + if err != nil { + return fmt.Errorf("x component zeroing failed: %s", err.Error()) + } + cx.Stack[pprev].Uint = 0 + cx.Stack[pprev].Bytes, err = leadingZeros(32, y) + if err != nil { + return fmt.Errorf("y component zeroing failed: %s", err.Error()) + } + cx.Stack = cx.Stack[:prev] + return nil +} + +type rawMessage []byte + +func (rm rawMessage) ToBeHashed() (protocol.HashID, []byte) { + return "", []byte(rm) +} + +func opVrfVerify(cx *EvalContext) error { + last := len(cx.Stack) - 1 // PK + prev := last - 1 // proof + pprev := prev - 1 // data + + data := rawMessage(cx.Stack[pprev].Bytes) + proofbytes := cx.Stack[prev].Bytes + var proof crypto.VrfProof + if len(proofbytes) != len(proof) { + return fmt.Errorf("vrf proof wrong size %d != %d", len(proofbytes), len(proof)) + } + copy(proof[:], proofbytes[:]) + + pubkeybytes := cx.Stack[last].Bytes + var pubkey crypto.VrfPubkey + if len(pubkeybytes) != len(pubkey) { + return fmt.Errorf("vrf pubkey wrong size %d != %d", len(pubkeybytes), len(pubkey)) + } + copy(pubkey[:], pubkeybytes[:]) + + var verified bool + var output []byte + std := VrfStandard(cx.program[cx.pc+1]) + ss, ok := vrfStandardSpecByField(std) + if !ok || ss.version > cx.version { + return fmt.Errorf("invalid VRF standard %s", std) + } + switch std { + case VrfAlgorand: + var out crypto.VrfOutput + verified, out = pubkey.Verify(proof, data) + output = out[:] + default: + return fmt.Errorf("unsupported vrf_verify standard %s", std) + } + + cx.Stack[pprev].Bytes = output[:] + cx.Stack[prev] = boolToSV(verified) + cx.Stack = cx.Stack[:last] // pop 1 because we take 3 args and return 2 + return nil +} diff --git a/data/transactions/logic/evalCrypto_test.go b/data/transactions/logic/crypto_test.go similarity index 93% rename from data/transactions/logic/evalCrypto_test.go rename to data/transactions/logic/crypto_test.go index 946b649562..7c0dc5f582 100644 --- a/data/transactions/logic/evalCrypto_test.go +++ b/data/transactions/logic/crypto_test.go @@ -117,9 +117,9 @@ func TestVrfVerify(t *testing.T) { testApp(t, notrack("byte 0x1122; byte 0x2233; int 3; vrf_verify VrfAlgorand"), ep, "arg 2 wanted") ep = defaultSigParams() - testLogic(t, "byte 0x1122; byte 0x2233; byte 0x3344; vrf_verify VrfAlgorand", LogicVersion, ep, "vrf proof wrong size") + testLogic(t, notrack("byte 0x1122; byte 0x2233; byte 0x3344; vrf_verify VrfAlgorand"), LogicVersion, ep, "vrf proof wrong size") // 80 byte proof - testLogic(t, "byte 0x1122; int 80; bzero; byte 0x3344; vrf_verify VrfAlgorand", LogicVersion, ep, "vrf pubkey wrong size") + testLogic(t, notrack("byte 0x1122; int 80; bzero; byte 0x3344; vrf_verify VrfAlgorand"), LogicVersion, ep, "vrf pubkey wrong size") // 32 byte pubkey testLogic(t, "byte 0x3344; int 80; bzero; int 32; bzero; vrf_verify VrfAlgorand", LogicVersion, ep, "stack len is 2") @@ -194,33 +194,32 @@ func TestEd25519verify(t *testing.T) { msg := "62fdfc072182654f163f5f0f9a621d729566c74d0aa413bf009c9800418c19cd" data, err := hex.DecodeString(msg) require.NoError(t, err) - pk := basics.Address(c.SignatureVerifier) - pkStr := pk.String() for v := uint64(1); v <= AssemblerMaxVersion; v++ { t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) { - ops := testProg(t, fmt.Sprintf(`arg 0 -arg 1 -addr %s -ed25519verify`, pkStr), v) + ops := testProg(t, fmt.Sprintf("arg 0; arg 1; arg 2; ed25519verify"), v) sig := c.Sign(Msg{ ProgramHash: crypto.HashObj(Program(ops.Program)), Data: data[:], }) var txn transactions.SignedTxn txn.Lsig.Logic = ops.Program - txn.Lsig.Args = [][]byte{data[:], sig[:]} + txn.Lsig.Args = [][]byte{data[:], sig[:], c.SignatureVerifier[:]} testLogicBytes(t, ops.Program, defaultSigParams(txn)) // short sig will fail - txn.Lsig.Args[1] = sig[1:] + txn.Lsig.Args = [][]byte{data[:], sig[1:], c.SignatureVerifier[:]} testLogicBytes(t, ops.Program, defaultSigParams(txn), "invalid signature") + // short pk will fail + txn.Lsig.Args = [][]byte{data[:], sig[:], c.SignatureVerifier[1:]} + testLogicBytes(t, ops.Program, defaultSigParams(txn), "invalid public key") + // flip a bit and it should not pass - msg1 := "52fdfc072182654f163f5f0f9a621d729566c74d0aa413bf009c9800418c19cd" + msg1 := "5" + msg[1:] data1, err := hex.DecodeString(msg1) require.NoError(t, err) - txn.Lsig.Args = [][]byte{data1, sig[:]} + txn.Lsig.Args = [][]byte{data1, sig[:], c.SignatureVerifier[:]} testLogicBytes(t, ops.Program, defaultSigParams(txn), "REJECT") }) } @@ -236,31 +235,30 @@ func TestEd25519VerifyBare(t *testing.T) { msg := "62fdfc072182654f163f5f0f9a621d729566c74d0aa413bf009c9800418c19cd" data, err := hex.DecodeString(msg) require.NoError(t, err) - pk := basics.Address(c.SignatureVerifier) - pkStr := pk.String() for v := uint64(7); v <= AssemblerMaxVersion; v++ { t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) { - ops := testProg(t, fmt.Sprintf(`arg 0 -arg 1 -addr %s -ed25519verify_bare`, pkStr), v) + ops := testProg(t, "arg 0; arg 1; arg 2; ed25519verify_bare", v) require.NoError(t, err) sig := c.SignBytes(data) var txn transactions.SignedTxn txn.Lsig.Logic = ops.Program - txn.Lsig.Args = [][]byte{data[:], sig[:]} + txn.Lsig.Args = [][]byte{data[:], sig[:], c.SignatureVerifier[:]} testLogicBytes(t, ops.Program, defaultSigParams(txn)) // short sig will fail - txn.Lsig.Args[1] = sig[1:] + txn.Lsig.Args = [][]byte{data[:], sig[1:], c.SignatureVerifier[:]} testLogicBytes(t, ops.Program, defaultSigParams(txn), "invalid signature") + // short pk will fail + txn.Lsig.Args = [][]byte{data[:], sig[:], c.SignatureVerifier[1:]} + testLogicBytes(t, ops.Program, defaultSigParams(txn), "invalid public key") + // flip a bit and it should not pass - msg1 := "52fdfc072182654f163f5f0f9a621d729566c74d0aa413bf009c9800418c19cd" + msg1 := "5" + msg[1:] data1, err := hex.DecodeString(msg1) require.NoError(t, err) - txn.Lsig.Args = [][]byte{data1, sig[:]} + txn.Lsig.Args = [][]byte{data1, sig[:], c.SignatureVerifier[:]} testLogicBytes(t, ops.Program, defaultSigParams(txn), "REJECT") }) } @@ -360,15 +358,7 @@ byte 0x%s } // ecdsa verify tests - source = ` -byte "%s" -sha512_256 -byte 0x%s -byte 0x%s -byte 0x%s -byte 0x%s -ecdsa_verify Secp256k1 -` + source = `byte "%s"; sha512_256; byte 0x%s; byte 0x%s; byte 0x%s; byte 0x%s; ecdsa_verify Secp256k1` data := []byte("testdata") msg := sha512.Sum512_256(data) @@ -403,6 +393,9 @@ ecdsa_verify Secp256k1 }) } + // coverage for pk length check + testPanics(t, `int 31; bzero; byte 0x; byte 0x; byte 0x; byte 0x; ecdsa_verify Secp256k1`, 5, "must be 32") + // ecdsa recover tests source = ` byte 0x%s @@ -434,7 +427,10 @@ load 1 {v, testAccepts}, {v ^ 1, testRejects}, {3, func(t *testing.T, program string, introduced uint64) { - testPanics(t, program, introduced) + testPanics(t, program, introduced, "recover failed") + }}, + {4, func(t *testing.T, program string, introduced uint64) { + testPanics(t, program, introduced, "invalid recovery id") }}, } pkExpanded := secp256k1.S256().Marshal(key.PublicKey.X, key.PublicKey.Y) diff --git a/data/transactions/logic/doc.go b/data/transactions/logic/doc.go index ad4f1674bd..c060d82623 100644 --- a/data/transactions/logic/doc.go +++ b/data/transactions/logic/doc.go @@ -343,10 +343,11 @@ func OpDocExtra(opName string) string { // here is the order args opcodes are presented, so place related // opcodes consecutively, even if their opcode values are not. var OpGroups = map[string][]string{ - "Arithmetic": {"sha256", "keccak256", "sha512_256", "sha3_256", "ed25519verify", "ed25519verify_bare", "ecdsa_verify", "ecdsa_pk_recover", "ecdsa_pk_decompress", "vrf_verify", "ec_add", "ec_scalar_mul", "ec_pairing_check", "ec_multi_scalar_mul", "ec_subgroup_check", "ec_map_to", "+", "-", "/", "*", "<", ">", "<=", ">=", "&&", "||", "shl", "shr", "sqrt", "bitlen", "exp", "==", "!=", "!", "len", "itob", "btoi", "%", "|", "&", "^", "~", "mulw", "addw", "divw", "divmodw", "expw", "getbit", "setbit", "getbyte", "setbyte", "concat"}, - "Byte Array Manipulation": {"substring", "substring3", "extract", "extract3", "extract_uint16", "extract_uint32", "extract_uint64", "replace2", "replace3", "base64_decode", "json_ref"}, + "Arithmetic": {"+", "-", "/", "*", "<", ">", "<=", ">=", "&&", "||", "shl", "shr", "sqrt", "bitlen", "exp", "==", "!=", "!", "itob", "btoi", "%", "|", "&", "^", "~", "mulw", "addw", "divw", "divmodw", "expw"}, + "Byte Array Manipulation": {"getbit", "setbit", "getbyte", "setbyte", "concat", "len", "substring", "substring3", "extract", "extract3", "extract_uint16", "extract_uint32", "extract_uint64", "replace2", "replace3", "base64_decode", "json_ref"}, "Byte Array Arithmetic": {"b+", "b-", "b/", "b*", "b<", "b>", "b<=", "b>=", "b==", "b!=", "b%", "bsqrt"}, "Byte Array Logic": {"b|", "b&", "b^", "b~"}, + "Cryptography": {"sha256", "keccak256", "sha512_256", "sha3_256", "ed25519verify", "ed25519verify_bare", "ecdsa_verify", "ecdsa_pk_recover", "ecdsa_pk_decompress", "vrf_verify", "ec_add", "ec_scalar_mul", "ec_pairing_check", "ec_multi_scalar_mul", "ec_subgroup_check", "ec_map_to"}, "Loading Values": {"intcblock", "intc", "intc_0", "intc_1", "intc_2", "intc_3", "pushint", "pushints", "bytecblock", "bytec", "bytec_0", "bytec_1", "bytec_2", "bytec_3", "pushbytes", "pushbytess", "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", "proto", "retsub", "switch", "match"}, "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"}, diff --git a/data/transactions/logic/doc_test.go b/data/transactions/logic/doc_test.go index 300c0ffdb9..9c9dad4ec3 100644 --- a/data/transactions/logic/doc_test.go +++ b/data/transactions/logic/doc_test.go @@ -51,9 +51,9 @@ func TestOpGroupCoverage(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - opsSeen := make(map[string]bool, len(OpSpecs)) + opsSeen := make(map[string]int, len(OpSpecs)) for _, op := range OpSpecs { - opsSeen[op.Name] = false + opsSeen[op.Name] = 0 } for _, names := range OpGroups { for _, name := range names { @@ -62,13 +62,16 @@ func TestOpGroupCoverage(t *testing.T) { t.Errorf("op %#v in group list but not in OpSpecs\n", name) continue } - opsSeen[name] = true + opsSeen[name]++ } } for name, seen := range opsSeen { - if !seen { + if seen == 0 { t.Errorf("op %#v not in any group of OpGroups\n", name) } + if seen > 1 { + t.Errorf("op %#v in %d groups of OpGroups\n", name, seen) + } } } diff --git a/data/transactions/logic/eval.go b/data/transactions/logic/eval.go index ad4acd69dd..2db51b24a7 100644 --- a/data/transactions/logic/eval.go +++ b/data/transactions/logic/eval.go @@ -18,10 +18,6 @@ package logic import ( "bytes" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/sha256" - "crypto/sha512" "encoding/base64" "encoding/binary" "encoding/hex" @@ -34,12 +30,10 @@ import ( "runtime" "strings" - "golang.org/x/crypto/sha3" "golang.org/x/exp/slices" "github.com/algorand/go-algorand/config" "github.com/algorand/go-algorand/crypto" - "github.com/algorand/go-algorand/crypto/secp256k1" "github.com/algorand/go-algorand/data/basics" "github.com/algorand/go-algorand/data/bookkeeping" "github.com/algorand/go-algorand/data/transactions" @@ -757,6 +751,10 @@ var ( StackAddress = NewStackType(avmBytes, static(32), "address") // StackBytes32 represents a bytestring that should have exactly 32 bytes StackBytes32 = NewStackType(avmBytes, static(32), "[32]byte") + // StackBytes64 represents a bytestring that should have exactly 64 bytes + StackBytes64 = NewStackType(avmBytes, static(64), "[64]byte") + // StackBytes80 represents a bytestring that should have exactly 80 bytes + StackBytes80 = NewStackType(avmBytes, static(80), "[80]byte") // StackBigInt represents a bytestring that should be treated like an int StackBigInt = NewStackType(avmBytes, bound(0, maxByteMathSize), "bigint") // StackMethodSelector represents a bytestring that should be treated like a method selector @@ -782,7 +780,9 @@ var ( 'A': StackAddress, 'I': StackBigInt, 'T': StackBoolean, - 'H': StackBytes32, + '3': StackBytes32, + '6': StackBytes64, + '8': StackBytes80, 'M': StackMethodSelector, 'K': StackStateKey, 'N': StackBoxName, @@ -1628,45 +1628,6 @@ func opSelect(cx *EvalContext) error { return nil } -func opSHA256(cx *EvalContext) error { - last := len(cx.Stack) - 1 - hash := sha256.Sum256(cx.Stack[last].Bytes) - cx.Stack[last].Bytes = hash[:] - return nil -} - -// The NIST SHA3-256 is implemented for compatibility with ICON -func opSHA3_256(cx *EvalContext) error { - last := len(cx.Stack) - 1 - hash := sha3.Sum256(cx.Stack[last].Bytes) - cx.Stack[last].Bytes = hash[:] - return nil -} - -// The Keccak256 variant of SHA-3 is implemented for compatibility with Ethereum -func opKeccak256(cx *EvalContext) error { - last := len(cx.Stack) - 1 - hasher := sha3.NewLegacyKeccak256() - hasher.Write(cx.Stack[last].Bytes) - hv := make([]byte, 0, hasher.Size()) - hv = hasher.Sum(hv) - cx.Stack[last].Bytes = hv - return nil -} - -// This is the hash commonly used in Algorand in crypto/util.go Hash() -// -// It is explicitly implemented here in terms of the specific hash for -// stability and portability in case the rest of Algorand ever moves -// to a different default hash. For stability of this language, at -// that time a new opcode should be made with the new hash. -func opSHA512_256(cx *EvalContext) error { - last := len(cx.Stack) - 1 - hash := sha512.Sum512_256(cx.Stack[last].Bytes) - cx.Stack[last].Bytes = hash[:] - return nil -} - func opPlus(cx *EvalContext) error { last := len(cx.Stack) - 1 prev := last - 1 @@ -3679,247 +3640,6 @@ func opGlobal(cx *EvalContext) error { return nil } -// Msg is data meant to be signed and then verified with the -// ed25519verify opcode. -type Msg struct { - _struct struct{} `codec:",omitempty,omitemptyarray"` - ProgramHash crypto.Digest `codec:"p"` - Data []byte `codec:"d"` -} - -// ToBeHashed implements crypto.Hashable -func (msg Msg) ToBeHashed() (protocol.HashID, []byte) { - return protocol.ProgramData, append(msg.ProgramHash[:], msg.Data...) -} - -// programHash lets us lazily compute H(cx.program) -func (cx *EvalContext) programHash() crypto.Digest { - if cx.programHashCached == (crypto.Digest{}) { - cx.programHashCached = crypto.HashObj(Program(cx.program)) - } - return cx.programHashCached -} - -func opEd25519Verify(cx *EvalContext) error { - last := len(cx.Stack) - 1 // index of PK - prev := last - 1 // index of signature - pprev := prev - 1 // index of data - - var sv crypto.SignatureVerifier - if len(cx.Stack[last].Bytes) != len(sv) { - return errors.New("invalid public key") - } - copy(sv[:], cx.Stack[last].Bytes) - - var sig crypto.Signature - if len(cx.Stack[prev].Bytes) != len(sig) { - return errors.New("invalid signature") - } - copy(sig[:], cx.Stack[prev].Bytes) - - msg := Msg{ProgramHash: cx.programHash(), Data: cx.Stack[pprev].Bytes} - cx.Stack[pprev] = boolToSV(sv.Verify(msg, sig)) - cx.Stack = cx.Stack[:prev] - return nil -} - -func opEd25519VerifyBare(cx *EvalContext) error { - last := len(cx.Stack) - 1 // index of PK - prev := last - 1 // index of signature - pprev := prev - 1 // index of data - - var sv crypto.SignatureVerifier - if len(cx.Stack[last].Bytes) != len(sv) { - return errors.New("invalid public key") - } - copy(sv[:], cx.Stack[last].Bytes) - - var sig crypto.Signature - if len(cx.Stack[prev].Bytes) != len(sig) { - return errors.New("invalid signature") - } - copy(sig[:], cx.Stack[prev].Bytes) - - cx.Stack[pprev] = boolToSV(sv.VerifyBytes(cx.Stack[pprev].Bytes, sig)) - cx.Stack = cx.Stack[:prev] - return nil -} - -func leadingZeros(size int, b *big.Int) ([]byte, error) { - byteLength := (b.BitLen() + 7) / 8 - if size < byteLength { - return nil, fmt.Errorf("insufficient buffer size: %d < %d", size, byteLength) - } - buf := make([]byte, size) - b.FillBytes(buf) - return buf, nil -} - -var ecdsaVerifyCosts = []int{ - Secp256k1: 1700, - Secp256r1: 2500, -} - -var secp256r1 = elliptic.P256() - -func opEcdsaVerify(cx *EvalContext) error { - ecdsaCurve := EcdsaCurve(cx.program[cx.pc+1]) - fs, ok := ecdsaCurveSpecByField(ecdsaCurve) - if !ok || fs.version > cx.version { - return fmt.Errorf("invalid curve %d", ecdsaCurve) - } - - if fs.field != Secp256k1 && fs.field != Secp256r1 { - return fmt.Errorf("unsupported curve %d", fs.field) - } - - last := len(cx.Stack) - 1 // index of PK y - prev := last - 1 // index of PK x - pprev := prev - 1 // index of signature s - fourth := pprev - 1 // index of signature r - fifth := fourth - 1 // index of data - - pkY := cx.Stack[last].Bytes - pkX := cx.Stack[prev].Bytes - sigS := cx.Stack[pprev].Bytes - sigR := cx.Stack[fourth].Bytes - msg := cx.Stack[fifth].Bytes - - if len(msg) != 32 { - return fmt.Errorf("the signed data must be 32 bytes long, not %d", len(msg)) - } - - x := new(big.Int).SetBytes(pkX) - y := new(big.Int).SetBytes(pkY) - - var result bool - if fs.field == Secp256k1 { - signature := make([]byte, 0, len(sigR)+len(sigS)) - signature = append(signature, sigR...) - signature = append(signature, sigS...) - - pubkey := secp256k1.S256().Marshal(x, y) - result = secp256k1.VerifySignature(pubkey, msg, signature) - } else if fs.field == Secp256r1 { - if !cx.Proto.EnablePrecheckECDSACurve || secp256r1.IsOnCurve(x, y) { - pubkey := ecdsa.PublicKey{ - Curve: secp256r1, - X: x, - Y: y, - } - r := new(big.Int).SetBytes(sigR) - s := new(big.Int).SetBytes(sigS) - result = ecdsa.Verify(&pubkey, msg, r, s) - } - } - - cx.Stack[fifth] = boolToSV(result) - cx.Stack = cx.Stack[:fourth] - return nil -} - -var ecdsaDecompressCosts = []int{ - Secp256k1: 650, - Secp256r1: 2400, -} - -func opEcdsaPkDecompress(cx *EvalContext) error { - ecdsaCurve := EcdsaCurve(cx.program[cx.pc+1]) - fs, ok := ecdsaCurveSpecByField(ecdsaCurve) - if !ok || fs.version > cx.version { - return fmt.Errorf("invalid curve %d", ecdsaCurve) - } - - if fs.field != Secp256k1 && fs.field != Secp256r1 { - return fmt.Errorf("unsupported curve %d", fs.field) - } - - last := len(cx.Stack) - 1 // compressed PK - - pubkey := cx.Stack[last].Bytes - var x, y *big.Int - if fs.field == Secp256k1 { - x, y = secp256k1.DecompressPubkey(pubkey) - if x == nil { - return fmt.Errorf("invalid pubkey") - } - } else if fs.field == Secp256r1 { - x, y = elliptic.UnmarshalCompressed(elliptic.P256(), pubkey) - if x == nil { - return fmt.Errorf("invalid compressed pubkey") - } - } - - var err error - cx.Stack[last].Uint = 0 - cx.Stack[last].Bytes, err = leadingZeros(32, x) - if err != nil { - return fmt.Errorf("x component zeroing failed: %w", err) - } - - var sv stackValue - sv.Bytes, err = leadingZeros(32, y) - if err != nil { - return fmt.Errorf("y component zeroing failed: %w", err) - } - - cx.Stack = append(cx.Stack, sv) - return nil -} - -func opEcdsaPkRecover(cx *EvalContext) error { - ecdsaCurve := EcdsaCurve(cx.program[cx.pc+1]) - fs, ok := ecdsaCurveSpecByField(ecdsaCurve) - if !ok || fs.version > cx.version { - return fmt.Errorf("invalid curve %d", ecdsaCurve) - } - - if fs.field != Secp256k1 { - return fmt.Errorf("unsupported curve %d", fs.field) - } - - last := len(cx.Stack) - 1 // index of signature s - prev := last - 1 // index of signature r - pprev := prev - 1 // index of recovery id - fourth := pprev - 1 // index of data - - sigS := cx.Stack[last].Bytes - sigR := cx.Stack[prev].Bytes - recid := cx.Stack[pprev].Uint - msg := cx.Stack[fourth].Bytes - - if recid > 3 { - return fmt.Errorf("invalid recovery id: %d", recid) - } - - signature := make([]byte, 0, len(sigR)+len(sigS)+1) - signature = append(signature, sigR...) - signature = append(signature, sigS...) - signature = append(signature, uint8(recid)) - - pk, err := secp256k1.RecoverPubkey(msg, signature) - if err != nil { - return fmt.Errorf("pubkey recover failed: %s", err.Error()) - } - x, y := secp256k1.S256().Unmarshal(pk) - if x == nil { - return fmt.Errorf("pubkey unmarshal failed") - } - - cx.Stack[fourth].Uint = 0 - cx.Stack[fourth].Bytes, err = leadingZeros(32, x) - if err != nil { - return fmt.Errorf("x component zeroing failed: %s", err.Error()) - } - cx.Stack[pprev].Uint = 0 - cx.Stack[pprev].Bytes, err = leadingZeros(32, y) - if err != nil { - return fmt.Errorf("y component zeroing failed: %s", err.Error()) - } - cx.Stack = cx.Stack[:prev] - return nil -} - func opLoad(cx *EvalContext) error { n := cx.program[cx.pc+1] cx.Stack = append(cx.Stack, cx.Scratch[n]) @@ -5819,54 +5539,6 @@ func opItxnSubmit(cx *EvalContext) (err error) { return nil } -type rawMessage []byte - -func (rm rawMessage) ToBeHashed() (protocol.HashID, []byte) { - return "", []byte(rm) -} - -func opVrfVerify(cx *EvalContext) error { - last := len(cx.Stack) - 1 // PK - prev := last - 1 // proof - pprev := prev - 1 // data - - data := rawMessage(cx.Stack[pprev].Bytes) - proofbytes := cx.Stack[prev].Bytes - var proof crypto.VrfProof - if len(proofbytes) != len(proof) { - return fmt.Errorf("vrf proof wrong size %d != %d", len(proofbytes), len(proof)) - } - copy(proof[:], proofbytes[:]) - - pubkeybytes := cx.Stack[last].Bytes - var pubkey crypto.VrfPubkey - if len(pubkeybytes) != len(pubkey) { - return fmt.Errorf("vrf pubkey wrong size %d != %d", len(pubkeybytes), len(pubkey)) - } - copy(pubkey[:], pubkeybytes[:]) - - var verified bool - var output []byte - std := VrfStandard(cx.program[cx.pc+1]) - ss, ok := vrfStandardSpecByField(std) - if !ok || ss.version > cx.version { - return fmt.Errorf("invalid VRF standard %s", std) - } - switch std { - case VrfAlgorand: - var out crypto.VrfOutput - verified, out = pubkey.Verify(proof, data) - output = out[:] - default: - return fmt.Errorf("unsupported vrf_verify standard %s", std) - } - - cx.Stack[pprev].Bytes = output[:] - cx.Stack[prev] = boolToSV(verified) - cx.Stack = cx.Stack[:last] // pop 1 because we take 3 args and return 2 - return nil -} - // availableRound checks to see if the requested round, `r`, is allowed to be // accessed. If it is, it's returned as a basics.Round. It is named by analogy // to the availableAsset and availableApp helpers. diff --git a/data/transactions/logic/evalStateful_test.go b/data/transactions/logic/evalStateful_test.go index 5f2a5970b7..436643e4c2 100644 --- a/data/transactions/logic/evalStateful_test.go +++ b/data/transactions/logic/evalStateful_test.go @@ -299,7 +299,7 @@ log // check that ed25519verify and arg is not allowed in stateful mode between v2-v4 disallowedV4 := []string{ - "byte 0x01\nbyte 0x01\nbyte 0x01\ned25519verify", + "byte 0x01; int 32; bzero; int 64; bzero; ed25519verify", "arg 0", "arg_0", "arg_1", @@ -3001,11 +3001,23 @@ func TestReturnTypes(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - // Ensure all opcodes return values they are supposed to according to the OpSpecs table - typeToArg := map[avmType]string{ - avmUint64: "int 1\n", - avmAny: "int 1\n", - avmBytes: "byte 0x33343536\n", // Which is the string "3456" + // Generate a plausible (and consistent) value for a given StackType + typeToArg := func(t StackType) string { + switch t.AVMType { + case avmUint64: + if t.Bound[0] > 0 { + return fmt.Sprintf("int %d\n", t.Bound[0]) + } + return "int 1\n" + case avmAny: + return "int 1\n" + case avmBytes: + if t.Bound[0] > 0 { + return fmt.Sprintf("byte 0x%s\n", strings.Repeat("33", int(t.Bound[0]))) + } + return "byte 0x33343536\n" // Which is the string "3456" + } + panic(t) } // We try to form a snippet that will test every opcode, by sandwiching it @@ -3016,11 +3028,6 @@ func TestReturnTypes(t *testing.T) { // opcodes that need to set up their own stack inputs, a ": at the front of // the string means "start with an empty stack". specialCmd := map[string]string{ - "txn": "txn Sender", - "txna": "txna ApplicationArgs 0", - "gtxn": "gtxn 0 Sender", - "gtxna": "gtxna 0 ApplicationArgs 0", - "global": "global MinTxnFee", "gaids": ": int 0; gaids", "gloads": ": int 0; gloads 0", // Needs txn index = 0 to work "gloadss": ": int 0; int 1; gloadss", // Needs txn index = 0 to work @@ -3039,11 +3046,8 @@ func TestReturnTypes(t *testing.T) { "extract_uint64": ": byte 0x010203040506070809; int 1; extract_uint64", "replace2": ": byte 0x0102030405; byte 0x0809; replace2 2", "replace3": ": byte 0x0102030405; int 2; byte 0x0809; replace3", - "gtxns": "gtxns Sender", "gtxnsa": ": int 0; gtxnsa ApplicationArgs 0", "extract": "extract 0 2", - "txnas": "txnas ApplicationArgs", - "gtxnas": "gtxnas 0 ApplicationArgs", "gtxnsas": ": int 0; int 0; gtxnsas ApplicationArgs", "divw": ": int 1; int 2; int 3; divw", @@ -3073,10 +3077,7 @@ func TestReturnTypes(t *testing.T) { "gitxna": "itxn_begin; int pay; itxn_field TypeEnum; itxn_submit; gitxna 0 Accounts 0", "gitxnas": ": itxn_begin; int pay; itxn_field TypeEnum; itxn_submit; int 0; gitxnas 0 Accounts", - "base64_decode": `: byte "YWJjMTIzIT8kKiYoKSctPUB+"; base64_decode StdEncoding`, - "json_ref": `: byte "{\"k\": 7}"; byte "k"; json_ref JSONUint64`, - - "block": "block BlkSeed", + "json_ref": `: byte "{\"k\": 7}"; byte "k"; json_ref JSONUint64`, "proto": "callsub p; p: proto 0 3", "bury": ": int 1; int 2; int 3; bury 2; pop; pop;", @@ -3097,14 +3098,8 @@ func TestReturnTypes(t *testing.T) { "err": true, "return": true, - "ed25519verify": true, - "ed25519verify_bare": true, - "ecdsa_verify": true, - "ecdsa_pk_recover": true, "ecdsa_pk_decompress": true, - "vrf_verify": true, - "frame_dig": true, // would need a "proto" subroutine "frame_bury": true, // would need a "proto" subroutine @@ -3142,32 +3137,42 @@ func TestReturnTypes(t *testing.T) { } } else { for _, imm := range spec.OpDetails.Immediates { - switch imm.kind { - case immByte: - cmd += " 0" - case immInt8: - cmd += " -2" - case immInt: - cmd += " 10" - case immInts: - cmd += " 11 12 13" - case immBytes: - cmd += " 0x123456" - case immBytess: - cmd += " 0x12 0x34 0x56" - case immLabel: - cmd += " done; done: ;" - case immLabels: - cmd += " done1 done2; done1: ; done2: ;" - default: - require.Fail(t, "bad immediate", "%s", imm) + if imm.Group != nil { + for _, name := range imm.Group.Names { + // missing names exist because of array vs normal opcodes + if name != "" { + cmd += " " + name + break + } + } + } else { + switch imm.kind { + case immByte: + cmd += " 0" + case immInt8: + cmd += " -2" + case immInt: + cmd += " 10" + case immInts: + cmd += " 11 12 13" + case immBytes: + cmd += " 0x123456" + case immBytess: + cmd += " 0x12 0x34 0x56" + case immLabel: + cmd += " done; done: ;" + case immLabels: + cmd += " done1 done2; done1: ; done2: ;" + default: + require.Fail(t, "bad immediate", "%s", imm) + } } } } var sb strings.Builder if provideStackInput { for _, t := range spec.Arg.Types { - sb.WriteString(typeToArg[t.AVMType]) + sb.WriteString(typeToArg(t)) } } sb.WriteString(cmd + "\n") @@ -3178,7 +3183,7 @@ func TestReturnTypes(t *testing.T) { tx0.Txn.ApplicationID = 300 tx0.Txn.ForeignApps = []basics.AppIndex{300} tx0.Txn.ForeignAssets = []basics.AssetIndex{400} - tx0.Txn.Boxes = []transactions.BoxRef{{Name: []byte("3456")}} + tx0.Txn.Boxes = []transactions.BoxRef{{Name: []byte("3")}} // The arg given for boxName type tx0.Lsig.Args = [][]byte{ []byte("aoeu"), []byte("aoeu"), @@ -3218,12 +3223,13 @@ func TestReturnTypes(t *testing.T) { ledger.NewAccount(appAddr(300), 1000000) // these allows the box_* opcodes that to work - ledger.CreateBox(300, "3456", 10) + ledger.CreateBox(300, "3", 10) // We are running gi=1, but we never ran gi=0. Set things up as // if we did, so they can be accessed with gtxn, gload, gaid aep.pastScratch[0] = &scratchSpace{} aep.TxnGroup[0].ConfigAsset = 100 + *aep.PooledApplicationBudget = 10_000 // so we can run verifies var cx *EvalContext if m == ModeApp { diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go index 230ad8c640..fd8b9ff806 100644 --- a/data/transactions/logic/eval_test.go +++ b/data/transactions/logic/eval_test.go @@ -395,6 +395,8 @@ func TestWrongProtoVersion(t *testing.T) { } } +// TestBlankStackSufficient will fail if an opcode is added with more than the +// current max number of stack arguments. Update `blankStack` to be longer. func TestBlankStackSufficient(t *testing.T) { partitiontest.PartitionTest(t) diff --git a/data/transactions/logic/langspec_v1.json b/data/transactions/logic/langspec_v1.json index e88de1429d..b659e662af 100644 --- a/data/transactions/logic/langspec_v1.json +++ b/data/transactions/logic/langspec_v1.json @@ -3,46 +3,64 @@ "LogicSigVersion": 9, "NamedTypes": [ { - "Name": "uint64", - "Abbreviation": "i", + "Name": "[32]byte", + "Abbreviation": "3", "Bound": [ - 0, - 18446744073709551615 + 32, + 32 ], - "AVMType": "uint64" + "AVMType": "[]byte" }, { - "Name": "stateKey", - "Abbreviation": "K", + "Name": "[64]byte", + "Abbreviation": "6", "Bound": [ - 0, + 64, 64 ], "AVMType": "[]byte" }, { - "Name": "none", - "Abbreviation": "x", + "Name": "[80]byte", + "Abbreviation": "8", + "Bound": [ + 80, + 80 + ], + "AVMType": "[]byte" + }, + { + "Name": "[]byte", + "Abbreviation": "b", "Bound": [ 0, - 0 + 4096 ], - "AVMType": "none" + "AVMType": "[]byte" }, { - "Name": "method", - "Abbreviation": "M", + "Name": "address", + "Abbreviation": "A", "Bound": [ - 4, - 4 + 32, + 32 ], "AVMType": "[]byte" }, { - "Name": "boxName", - "Abbreviation": "N", + "Name": "any", + "Abbreviation": "a", "Bound": [ - 1, + 0, + 0 + ], + "AVMType": "any" + }, + { + "Name": "bigint", + "Abbreviation": "I", + "Bound": [ + 0, 64 ], "AVMType": "[]byte" @@ -57,49 +75,49 @@ "AVMType": "uint64" }, { - "Name": "bigint", - "Abbreviation": "I", + "Name": "boxName", + "Abbreviation": "N", "Bound": [ - 0, + 1, 64 ], "AVMType": "[]byte" }, { - "Name": "any", - "Abbreviation": "a", + "Name": "method", + "Abbreviation": "M", "Bound": [ - 0, - 0 + 4, + 4 ], - "AVMType": "any" + "AVMType": "[]byte" }, { - "Name": "address", - "Abbreviation": "A", + "Name": "none", + "Abbreviation": "x", "Bound": [ - 32, - 32 + 0, + 0 ], - "AVMType": "[]byte" + "AVMType": "none" }, { - "Name": "[]byte", - "Abbreviation": "b", + "Name": "stateKey", + "Abbreviation": "K", "Bound": [ 0, - 4096 + 64 ], "AVMType": "[]byte" }, { - "Name": "[32]byte", - "Abbreviation": "H", + "Name": "uint64", + "Abbreviation": "i", "Bound": [ - 32, - 32 + 0, + 18446744073709551615 ], - "AVMType": "[]byte" + "AVMType": "uint64" } ], "Ops": [ @@ -128,7 +146,7 @@ "Doc": "SHA256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -145,7 +163,7 @@ "Doc": "Keccak256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -162,7 +180,7 @@ "Doc": "SHA512_256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -170,8 +188,8 @@ "Name": "ed25519verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -182,7 +200,7 @@ "DocExtra": "The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -435,7 +453,7 @@ "Doc": "yields length of byte value A", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { diff --git a/data/transactions/logic/langspec_v10.json b/data/transactions/logic/langspec_v10.json index de938ffb72..7ee54fb98d 100644 --- a/data/transactions/logic/langspec_v10.json +++ b/data/transactions/logic/langspec_v10.json @@ -3,46 +3,64 @@ "LogicSigVersion": 9, "NamedTypes": [ { - "Name": "uint64", - "Abbreviation": "i", + "Name": "[32]byte", + "Abbreviation": "3", "Bound": [ - 0, - 18446744073709551615 + 32, + 32 ], - "AVMType": "uint64" + "AVMType": "[]byte" }, { - "Name": "stateKey", - "Abbreviation": "K", + "Name": "[64]byte", + "Abbreviation": "6", "Bound": [ - 0, + 64, 64 ], "AVMType": "[]byte" }, { - "Name": "none", - "Abbreviation": "x", + "Name": "[80]byte", + "Abbreviation": "8", + "Bound": [ + 80, + 80 + ], + "AVMType": "[]byte" + }, + { + "Name": "[]byte", + "Abbreviation": "b", "Bound": [ 0, - 0 + 4096 ], - "AVMType": "none" + "AVMType": "[]byte" }, { - "Name": "method", - "Abbreviation": "M", + "Name": "address", + "Abbreviation": "A", "Bound": [ - 4, - 4 + 32, + 32 ], "AVMType": "[]byte" }, { - "Name": "boxName", - "Abbreviation": "N", + "Name": "any", + "Abbreviation": "a", "Bound": [ - 1, + 0, + 0 + ], + "AVMType": "any" + }, + { + "Name": "bigint", + "Abbreviation": "I", + "Bound": [ + 0, 64 ], "AVMType": "[]byte" @@ -57,49 +75,49 @@ "AVMType": "uint64" }, { - "Name": "bigint", - "Abbreviation": "I", + "Name": "boxName", + "Abbreviation": "N", "Bound": [ - 0, + 1, 64 ], "AVMType": "[]byte" }, { - "Name": "any", - "Abbreviation": "a", + "Name": "method", + "Abbreviation": "M", "Bound": [ - 0, - 0 + 4, + 4 ], - "AVMType": "any" + "AVMType": "[]byte" }, { - "Name": "address", - "Abbreviation": "A", + "Name": "none", + "Abbreviation": "x", "Bound": [ - 32, - 32 + 0, + 0 ], - "AVMType": "[]byte" + "AVMType": "none" }, { - "Name": "[]byte", - "Abbreviation": "b", + "Name": "stateKey", + "Abbreviation": "K", "Bound": [ 0, - 4096 + 64 ], "AVMType": "[]byte" }, { - "Name": "[32]byte", - "Abbreviation": "H", + "Name": "uint64", + "Abbreviation": "i", "Bound": [ - 32, - 32 + 0, + 18446744073709551615 ], - "AVMType": "[]byte" + "AVMType": "uint64" } ], "Ops": [ @@ -128,7 +146,7 @@ "Doc": "SHA256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -145,7 +163,7 @@ "Doc": "Keccak256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -162,7 +180,7 @@ "Doc": "SHA512_256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -170,8 +188,8 @@ "Name": "ed25519verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -182,14 +200,14 @@ "DocExtra": "The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { "Opcode": 5, "Name": "ecdsa_verify", "Args": [ - "[]byte", + "[32]byte", "[]byte", "[]byte", "[]byte", @@ -216,7 +234,7 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -247,17 +265,17 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { "Opcode": 7, "Name": "ecdsa_pk_recover", "Args": [ - "[]byte", + "[32]byte", "uint64", - "[]byte", - "[]byte" + "[32]byte", + "[32]byte" ], "Returns": [ "[]byte", @@ -281,7 +299,7 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -534,7 +552,7 @@ "Doc": "yields length of byte value A", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2188,7 +2206,7 @@ "DocExtra": "`concat` fails if the result would be greater than 4096 bytes.", "IntroducedVersion": 2, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2255,7 +2273,7 @@ "DocExtra": "see explanation of bit ordering in setbit", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2275,7 +2293,7 @@ "DocExtra": "When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on the integer 0 yields 8, or 2^3. When A is a byte array, index 0 is the leftmost bit of the leftmost byte. Setting bits 0 through 11 to 1 in a 4-byte-array of 0s yields the byte array 0xfff00000. Setting bit 3 to 1 on the 1-byte-array 0x00 yields the byte array 0x10.", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2293,7 +2311,7 @@ "Doc": "Bth byte of A, as an integer. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2312,7 +2330,7 @@ "Doc": "Copy of A with the Bth byte set to small integer (between 0..255) C. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -3009,8 +3027,8 @@ "Name": "ed25519verify_bare", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -3020,7 +3038,7 @@ "Doc": "for (data A, signature B, pubkey C) verify the signature of the data against the pubkey =\u003e {0 or 1}", "IntroducedVersion": 7, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -3319,7 +3337,7 @@ "Doc": "SHA3_256 hash of value A, yields [32]byte", "IntroducedVersion": 7, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -4566,8 +4584,8 @@ "Name": "vrf_verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[80]byte", + "[32]byte" ], "Returns": [ "[]byte", @@ -4590,7 +4608,7 @@ ], "IntroducedVersion": 7, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -4650,7 +4668,7 @@ ], "IntroducedVersion": 10, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -4677,7 +4695,7 @@ ], "IntroducedVersion": 10, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -4704,7 +4722,7 @@ ], "IntroducedVersion": 10, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -4731,7 +4749,7 @@ ], "IntroducedVersion": 10, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -4756,7 +4774,7 @@ ], "IntroducedVersion": 10, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -4782,7 +4800,7 @@ ], "IntroducedVersion": 10, "Groups": [ - "Arithmetic" + "Cryptography" ] } ] diff --git a/data/transactions/logic/langspec_v2.json b/data/transactions/logic/langspec_v2.json index b0319cf998..b518b1a42f 100644 --- a/data/transactions/logic/langspec_v2.json +++ b/data/transactions/logic/langspec_v2.json @@ -3,46 +3,64 @@ "LogicSigVersion": 9, "NamedTypes": [ { - "Name": "uint64", - "Abbreviation": "i", + "Name": "[32]byte", + "Abbreviation": "3", "Bound": [ - 0, - 18446744073709551615 + 32, + 32 ], - "AVMType": "uint64" + "AVMType": "[]byte" }, { - "Name": "stateKey", - "Abbreviation": "K", + "Name": "[64]byte", + "Abbreviation": "6", "Bound": [ - 0, + 64, 64 ], "AVMType": "[]byte" }, { - "Name": "none", - "Abbreviation": "x", + "Name": "[80]byte", + "Abbreviation": "8", + "Bound": [ + 80, + 80 + ], + "AVMType": "[]byte" + }, + { + "Name": "[]byte", + "Abbreviation": "b", "Bound": [ 0, - 0 + 4096 ], - "AVMType": "none" + "AVMType": "[]byte" }, { - "Name": "method", - "Abbreviation": "M", + "Name": "address", + "Abbreviation": "A", "Bound": [ - 4, - 4 + 32, + 32 ], "AVMType": "[]byte" }, { - "Name": "boxName", - "Abbreviation": "N", + "Name": "any", + "Abbreviation": "a", "Bound": [ - 1, + 0, + 0 + ], + "AVMType": "any" + }, + { + "Name": "bigint", + "Abbreviation": "I", + "Bound": [ + 0, 64 ], "AVMType": "[]byte" @@ -57,49 +75,49 @@ "AVMType": "uint64" }, { - "Name": "bigint", - "Abbreviation": "I", + "Name": "boxName", + "Abbreviation": "N", "Bound": [ - 0, + 1, 64 ], "AVMType": "[]byte" }, { - "Name": "any", - "Abbreviation": "a", + "Name": "method", + "Abbreviation": "M", "Bound": [ - 0, - 0 + 4, + 4 ], - "AVMType": "any" + "AVMType": "[]byte" }, { - "Name": "address", - "Abbreviation": "A", + "Name": "none", + "Abbreviation": "x", "Bound": [ - 32, - 32 + 0, + 0 ], - "AVMType": "[]byte" + "AVMType": "none" }, { - "Name": "[]byte", - "Abbreviation": "b", + "Name": "stateKey", + "Abbreviation": "K", "Bound": [ 0, - 4096 + 64 ], "AVMType": "[]byte" }, { - "Name": "[32]byte", - "Abbreviation": "H", + "Name": "uint64", + "Abbreviation": "i", "Bound": [ - 32, - 32 + 0, + 18446744073709551615 ], - "AVMType": "[]byte" + "AVMType": "uint64" } ], "Ops": [ @@ -128,7 +146,7 @@ "Doc": "SHA256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -145,7 +163,7 @@ "Doc": "Keccak256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -162,7 +180,7 @@ "Doc": "SHA512_256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -170,8 +188,8 @@ "Name": "ed25519verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -182,7 +200,7 @@ "DocExtra": "The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -435,7 +453,7 @@ "Doc": "yields length of byte value A", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -1422,7 +1440,7 @@ "DocExtra": "`concat` fails if the result would be greater than 4096 bytes.", "IntroducedVersion": 2, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { diff --git a/data/transactions/logic/langspec_v3.json b/data/transactions/logic/langspec_v3.json index e3fe6e4938..a8bc6df0da 100644 --- a/data/transactions/logic/langspec_v3.json +++ b/data/transactions/logic/langspec_v3.json @@ -3,46 +3,64 @@ "LogicSigVersion": 9, "NamedTypes": [ { - "Name": "uint64", - "Abbreviation": "i", + "Name": "[32]byte", + "Abbreviation": "3", "Bound": [ - 0, - 18446744073709551615 + 32, + 32 ], - "AVMType": "uint64" + "AVMType": "[]byte" }, { - "Name": "stateKey", - "Abbreviation": "K", + "Name": "[64]byte", + "Abbreviation": "6", "Bound": [ - 0, + 64, 64 ], "AVMType": "[]byte" }, { - "Name": "none", - "Abbreviation": "x", + "Name": "[80]byte", + "Abbreviation": "8", + "Bound": [ + 80, + 80 + ], + "AVMType": "[]byte" + }, + { + "Name": "[]byte", + "Abbreviation": "b", "Bound": [ 0, - 0 + 4096 ], - "AVMType": "none" + "AVMType": "[]byte" }, { - "Name": "method", - "Abbreviation": "M", + "Name": "address", + "Abbreviation": "A", "Bound": [ - 4, - 4 + 32, + 32 ], "AVMType": "[]byte" }, { - "Name": "boxName", - "Abbreviation": "N", + "Name": "any", + "Abbreviation": "a", "Bound": [ - 1, + 0, + 0 + ], + "AVMType": "any" + }, + { + "Name": "bigint", + "Abbreviation": "I", + "Bound": [ + 0, 64 ], "AVMType": "[]byte" @@ -57,49 +75,49 @@ "AVMType": "uint64" }, { - "Name": "bigint", - "Abbreviation": "I", + "Name": "boxName", + "Abbreviation": "N", "Bound": [ - 0, + 1, 64 ], "AVMType": "[]byte" }, { - "Name": "any", - "Abbreviation": "a", + "Name": "method", + "Abbreviation": "M", "Bound": [ - 0, - 0 + 4, + 4 ], - "AVMType": "any" + "AVMType": "[]byte" }, { - "Name": "address", - "Abbreviation": "A", + "Name": "none", + "Abbreviation": "x", "Bound": [ - 32, - 32 + 0, + 0 ], - "AVMType": "[]byte" + "AVMType": "none" }, { - "Name": "[]byte", - "Abbreviation": "b", + "Name": "stateKey", + "Abbreviation": "K", "Bound": [ 0, - 4096 + 64 ], "AVMType": "[]byte" }, { - "Name": "[32]byte", - "Abbreviation": "H", + "Name": "uint64", + "Abbreviation": "i", "Bound": [ - 32, - 32 + 0, + 18446744073709551615 ], - "AVMType": "[]byte" + "AVMType": "uint64" } ], "Ops": [ @@ -128,7 +146,7 @@ "Doc": "SHA256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -145,7 +163,7 @@ "Doc": "Keccak256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -162,7 +180,7 @@ "Doc": "SHA512_256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -170,8 +188,8 @@ "Name": "ed25519verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -182,7 +200,7 @@ "DocExtra": "The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -435,7 +453,7 @@ "Doc": "yields length of byte value A", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -1723,7 +1741,7 @@ "DocExtra": "`concat` fails if the result would be greater than 4096 bytes.", "IntroducedVersion": 2, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -1790,7 +1808,7 @@ "DocExtra": "see explanation of bit ordering in setbit", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -1810,7 +1828,7 @@ "DocExtra": "When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on the integer 0 yields 8, or 2^3. When A is a byte array, index 0 is the leftmost bit of the leftmost byte. Setting bits 0 through 11 to 1 in a 4-byte-array of 0s yields the byte array 0xfff00000. Setting bit 3 to 1 on the 1-byte-array 0x00 yields the byte array 0x10.", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -1828,7 +1846,7 @@ "Doc": "Bth byte of A, as an integer. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -1847,7 +1865,7 @@ "Doc": "Copy of A with the Bth byte set to small integer (between 0..255) C. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { diff --git a/data/transactions/logic/langspec_v4.json b/data/transactions/logic/langspec_v4.json index 9ffb5f7419..ffc428822b 100644 --- a/data/transactions/logic/langspec_v4.json +++ b/data/transactions/logic/langspec_v4.json @@ -3,46 +3,64 @@ "LogicSigVersion": 9, "NamedTypes": [ { - "Name": "uint64", - "Abbreviation": "i", + "Name": "[32]byte", + "Abbreviation": "3", "Bound": [ - 0, - 18446744073709551615 + 32, + 32 ], - "AVMType": "uint64" + "AVMType": "[]byte" }, { - "Name": "stateKey", - "Abbreviation": "K", + "Name": "[64]byte", + "Abbreviation": "6", "Bound": [ - 0, + 64, 64 ], "AVMType": "[]byte" }, { - "Name": "none", - "Abbreviation": "x", + "Name": "[80]byte", + "Abbreviation": "8", + "Bound": [ + 80, + 80 + ], + "AVMType": "[]byte" + }, + { + "Name": "[]byte", + "Abbreviation": "b", "Bound": [ 0, - 0 + 4096 ], - "AVMType": "none" + "AVMType": "[]byte" }, { - "Name": "method", - "Abbreviation": "M", + "Name": "address", + "Abbreviation": "A", "Bound": [ - 4, - 4 + 32, + 32 ], "AVMType": "[]byte" }, { - "Name": "boxName", - "Abbreviation": "N", + "Name": "any", + "Abbreviation": "a", "Bound": [ - 1, + 0, + 0 + ], + "AVMType": "any" + }, + { + "Name": "bigint", + "Abbreviation": "I", + "Bound": [ + 0, 64 ], "AVMType": "[]byte" @@ -57,49 +75,49 @@ "AVMType": "uint64" }, { - "Name": "bigint", - "Abbreviation": "I", + "Name": "boxName", + "Abbreviation": "N", "Bound": [ - 0, + 1, 64 ], "AVMType": "[]byte" }, { - "Name": "any", - "Abbreviation": "a", + "Name": "method", + "Abbreviation": "M", "Bound": [ - 0, - 0 + 4, + 4 ], - "AVMType": "any" + "AVMType": "[]byte" }, { - "Name": "address", - "Abbreviation": "A", + "Name": "none", + "Abbreviation": "x", "Bound": [ - 32, - 32 + 0, + 0 ], - "AVMType": "[]byte" + "AVMType": "none" }, { - "Name": "[]byte", - "Abbreviation": "b", + "Name": "stateKey", + "Abbreviation": "K", "Bound": [ 0, - 4096 + 64 ], "AVMType": "[]byte" }, { - "Name": "[32]byte", - "Abbreviation": "H", + "Name": "uint64", + "Abbreviation": "i", "Bound": [ - 32, - 32 + 0, + 18446744073709551615 ], - "AVMType": "[]byte" + "AVMType": "uint64" } ], "Ops": [ @@ -128,7 +146,7 @@ "Doc": "SHA256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -145,7 +163,7 @@ "Doc": "Keccak256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -162,7 +180,7 @@ "Doc": "SHA512_256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -170,8 +188,8 @@ "Name": "ed25519verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -182,7 +200,7 @@ "DocExtra": "The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -435,7 +453,7 @@ "Doc": "yields length of byte value A", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -1845,7 +1863,7 @@ "DocExtra": "`concat` fails if the result would be greater than 4096 bytes.", "IntroducedVersion": 2, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -1912,7 +1930,7 @@ "DocExtra": "see explanation of bit ordering in setbit", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -1932,7 +1950,7 @@ "DocExtra": "When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on the integer 0 yields 8, or 2^3. When A is a byte array, index 0 is the leftmost bit of the leftmost byte. Setting bits 0 through 11 to 1 in a 4-byte-array of 0s yields the byte array 0xfff00000. Setting bit 3 to 1 on the 1-byte-array 0x00 yields the byte array 0x10.", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -1950,7 +1968,7 @@ "Doc": "Bth byte of A, as an integer. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -1969,7 +1987,7 @@ "Doc": "Copy of A with the Bth byte set to small integer (between 0..255) C. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { diff --git a/data/transactions/logic/langspec_v5.json b/data/transactions/logic/langspec_v5.json index 9c336c7d86..2b946629cc 100644 --- a/data/transactions/logic/langspec_v5.json +++ b/data/transactions/logic/langspec_v5.json @@ -3,46 +3,64 @@ "LogicSigVersion": 9, "NamedTypes": [ { - "Name": "uint64", - "Abbreviation": "i", + "Name": "[32]byte", + "Abbreviation": "3", "Bound": [ - 0, - 18446744073709551615 + 32, + 32 ], - "AVMType": "uint64" + "AVMType": "[]byte" }, { - "Name": "stateKey", - "Abbreviation": "K", + "Name": "[64]byte", + "Abbreviation": "6", "Bound": [ - 0, + 64, 64 ], "AVMType": "[]byte" }, { - "Name": "none", - "Abbreviation": "x", + "Name": "[80]byte", + "Abbreviation": "8", + "Bound": [ + 80, + 80 + ], + "AVMType": "[]byte" + }, + { + "Name": "[]byte", + "Abbreviation": "b", "Bound": [ 0, - 0 + 4096 ], - "AVMType": "none" + "AVMType": "[]byte" }, { - "Name": "method", - "Abbreviation": "M", + "Name": "address", + "Abbreviation": "A", "Bound": [ - 4, - 4 + 32, + 32 ], "AVMType": "[]byte" }, { - "Name": "boxName", - "Abbreviation": "N", + "Name": "any", + "Abbreviation": "a", "Bound": [ - 1, + 0, + 0 + ], + "AVMType": "any" + }, + { + "Name": "bigint", + "Abbreviation": "I", + "Bound": [ + 0, 64 ], "AVMType": "[]byte" @@ -57,49 +75,49 @@ "AVMType": "uint64" }, { - "Name": "bigint", - "Abbreviation": "I", + "Name": "boxName", + "Abbreviation": "N", "Bound": [ - 0, + 1, 64 ], "AVMType": "[]byte" }, { - "Name": "any", - "Abbreviation": "a", + "Name": "method", + "Abbreviation": "M", "Bound": [ - 0, - 0 + 4, + 4 ], - "AVMType": "any" + "AVMType": "[]byte" }, { - "Name": "address", - "Abbreviation": "A", + "Name": "none", + "Abbreviation": "x", "Bound": [ - 32, - 32 + 0, + 0 ], - "AVMType": "[]byte" + "AVMType": "none" }, { - "Name": "[]byte", - "Abbreviation": "b", + "Name": "stateKey", + "Abbreviation": "K", "Bound": [ 0, - 4096 + 64 ], "AVMType": "[]byte" }, { - "Name": "[32]byte", - "Abbreviation": "H", + "Name": "uint64", + "Abbreviation": "i", "Bound": [ - 32, - 32 + 0, + 18446744073709551615 ], - "AVMType": "[]byte" + "AVMType": "uint64" } ], "Ops": [ @@ -128,7 +146,7 @@ "Doc": "SHA256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -145,7 +163,7 @@ "Doc": "Keccak256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -162,7 +180,7 @@ "Doc": "SHA512_256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -170,8 +188,8 @@ "Name": "ed25519verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -182,14 +200,14 @@ "DocExtra": "The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { "Opcode": 5, "Name": "ecdsa_verify", "Args": [ - "[]byte", + "[32]byte", "[]byte", "[]byte", "[]byte", @@ -215,7 +233,7 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -245,17 +263,17 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { "Opcode": 7, "Name": "ecdsa_pk_recover", "Args": [ - "[]byte", + "[32]byte", "uint64", - "[]byte", - "[]byte" + "[32]byte", + "[32]byte" ], "Returns": [ "[]byte", @@ -278,7 +296,7 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -531,7 +549,7 @@ "Doc": "yields length of byte value A", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2061,7 +2079,7 @@ "DocExtra": "`concat` fails if the result would be greater than 4096 bytes.", "IntroducedVersion": 2, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2128,7 +2146,7 @@ "DocExtra": "see explanation of bit ordering in setbit", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2148,7 +2166,7 @@ "DocExtra": "When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on the integer 0 yields 8, or 2^3. When A is a byte array, index 0 is the leftmost bit of the leftmost byte. Setting bits 0 through 11 to 1 in a 4-byte-array of 0s yields the byte array 0xfff00000. Setting bit 3 to 1 on the 1-byte-array 0x00 yields the byte array 0x10.", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2166,7 +2184,7 @@ "Doc": "Bth byte of A, as an integer. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2185,7 +2203,7 @@ "Doc": "Copy of A with the Bth byte set to small integer (between 0..255) C. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { diff --git a/data/transactions/logic/langspec_v6.json b/data/transactions/logic/langspec_v6.json index 613d389191..20575dae5a 100644 --- a/data/transactions/logic/langspec_v6.json +++ b/data/transactions/logic/langspec_v6.json @@ -3,46 +3,64 @@ "LogicSigVersion": 9, "NamedTypes": [ { - "Name": "uint64", - "Abbreviation": "i", + "Name": "[32]byte", + "Abbreviation": "3", "Bound": [ - 0, - 18446744073709551615 + 32, + 32 ], - "AVMType": "uint64" + "AVMType": "[]byte" }, { - "Name": "stateKey", - "Abbreviation": "K", + "Name": "[64]byte", + "Abbreviation": "6", "Bound": [ - 0, + 64, 64 ], "AVMType": "[]byte" }, { - "Name": "none", - "Abbreviation": "x", + "Name": "[80]byte", + "Abbreviation": "8", + "Bound": [ + 80, + 80 + ], + "AVMType": "[]byte" + }, + { + "Name": "[]byte", + "Abbreviation": "b", "Bound": [ 0, - 0 + 4096 ], - "AVMType": "none" + "AVMType": "[]byte" }, { - "Name": "method", - "Abbreviation": "M", + "Name": "address", + "Abbreviation": "A", "Bound": [ - 4, - 4 + 32, + 32 ], "AVMType": "[]byte" }, { - "Name": "boxName", - "Abbreviation": "N", + "Name": "any", + "Abbreviation": "a", "Bound": [ - 1, + 0, + 0 + ], + "AVMType": "any" + }, + { + "Name": "bigint", + "Abbreviation": "I", + "Bound": [ + 0, 64 ], "AVMType": "[]byte" @@ -57,49 +75,49 @@ "AVMType": "uint64" }, { - "Name": "bigint", - "Abbreviation": "I", + "Name": "boxName", + "Abbreviation": "N", "Bound": [ - 0, + 1, 64 ], "AVMType": "[]byte" }, { - "Name": "any", - "Abbreviation": "a", + "Name": "method", + "Abbreviation": "M", "Bound": [ - 0, - 0 + 4, + 4 ], - "AVMType": "any" + "AVMType": "[]byte" }, { - "Name": "address", - "Abbreviation": "A", + "Name": "none", + "Abbreviation": "x", "Bound": [ - 32, - 32 + 0, + 0 ], - "AVMType": "[]byte" + "AVMType": "none" }, { - "Name": "[]byte", - "Abbreviation": "b", + "Name": "stateKey", + "Abbreviation": "K", "Bound": [ 0, - 4096 + 64 ], "AVMType": "[]byte" }, { - "Name": "[32]byte", - "Abbreviation": "H", + "Name": "uint64", + "Abbreviation": "i", "Bound": [ - 32, - 32 + 0, + 18446744073709551615 ], - "AVMType": "[]byte" + "AVMType": "uint64" } ], "Ops": [ @@ -128,7 +146,7 @@ "Doc": "SHA256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -145,7 +163,7 @@ "Doc": "Keccak256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -162,7 +180,7 @@ "Doc": "SHA512_256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -170,8 +188,8 @@ "Name": "ed25519verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -182,14 +200,14 @@ "DocExtra": "The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { "Opcode": 5, "Name": "ecdsa_verify", "Args": [ - "[]byte", + "[32]byte", "[]byte", "[]byte", "[]byte", @@ -215,7 +233,7 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -245,17 +263,17 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { "Opcode": 7, "Name": "ecdsa_pk_recover", "Args": [ - "[]byte", + "[32]byte", "uint64", - "[]byte", - "[]byte" + "[32]byte", + "[32]byte" ], "Returns": [ "[]byte", @@ -278,7 +296,7 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -531,7 +549,7 @@ "Doc": "yields length of byte value A", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2079,7 +2097,7 @@ "DocExtra": "`concat` fails if the result would be greater than 4096 bytes.", "IntroducedVersion": 2, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2146,7 +2164,7 @@ "DocExtra": "see explanation of bit ordering in setbit", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2166,7 +2184,7 @@ "DocExtra": "When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on the integer 0 yields 8, or 2^3. When A is a byte array, index 0 is the leftmost bit of the leftmost byte. Setting bits 0 through 11 to 1 in a 4-byte-array of 0s yields the byte array 0xfff00000. Setting bit 3 to 1 on the 1-byte-array 0x00 yields the byte array 0x10.", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2184,7 +2202,7 @@ "Doc": "Bth byte of A, as an integer. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2203,7 +2221,7 @@ "Doc": "Copy of A with the Bth byte set to small integer (between 0..255) C. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { diff --git a/data/transactions/logic/langspec_v7.json b/data/transactions/logic/langspec_v7.json index cb3664eb3a..d8be33960c 100644 --- a/data/transactions/logic/langspec_v7.json +++ b/data/transactions/logic/langspec_v7.json @@ -3,46 +3,64 @@ "LogicSigVersion": 9, "NamedTypes": [ { - "Name": "uint64", - "Abbreviation": "i", + "Name": "[32]byte", + "Abbreviation": "3", "Bound": [ - 0, - 18446744073709551615 + 32, + 32 ], - "AVMType": "uint64" + "AVMType": "[]byte" }, { - "Name": "stateKey", - "Abbreviation": "K", + "Name": "[64]byte", + "Abbreviation": "6", "Bound": [ - 0, + 64, 64 ], "AVMType": "[]byte" }, { - "Name": "none", - "Abbreviation": "x", + "Name": "[80]byte", + "Abbreviation": "8", + "Bound": [ + 80, + 80 + ], + "AVMType": "[]byte" + }, + { + "Name": "[]byte", + "Abbreviation": "b", "Bound": [ 0, - 0 + 4096 ], - "AVMType": "none" + "AVMType": "[]byte" }, { - "Name": "method", - "Abbreviation": "M", + "Name": "address", + "Abbreviation": "A", "Bound": [ - 4, - 4 + 32, + 32 ], "AVMType": "[]byte" }, { - "Name": "boxName", - "Abbreviation": "N", + "Name": "any", + "Abbreviation": "a", "Bound": [ - 1, + 0, + 0 + ], + "AVMType": "any" + }, + { + "Name": "bigint", + "Abbreviation": "I", + "Bound": [ + 0, 64 ], "AVMType": "[]byte" @@ -57,49 +75,49 @@ "AVMType": "uint64" }, { - "Name": "bigint", - "Abbreviation": "I", + "Name": "boxName", + "Abbreviation": "N", "Bound": [ - 0, + 1, 64 ], "AVMType": "[]byte" }, { - "Name": "any", - "Abbreviation": "a", + "Name": "method", + "Abbreviation": "M", "Bound": [ - 0, - 0 + 4, + 4 ], - "AVMType": "any" + "AVMType": "[]byte" }, { - "Name": "address", - "Abbreviation": "A", + "Name": "none", + "Abbreviation": "x", "Bound": [ - 32, - 32 + 0, + 0 ], - "AVMType": "[]byte" + "AVMType": "none" }, { - "Name": "[]byte", - "Abbreviation": "b", + "Name": "stateKey", + "Abbreviation": "K", "Bound": [ 0, - 4096 + 64 ], "AVMType": "[]byte" }, { - "Name": "[32]byte", - "Abbreviation": "H", + "Name": "uint64", + "Abbreviation": "i", "Bound": [ - 32, - 32 + 0, + 18446744073709551615 ], - "AVMType": "[]byte" + "AVMType": "uint64" } ], "Ops": [ @@ -128,7 +146,7 @@ "Doc": "SHA256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -145,7 +163,7 @@ "Doc": "Keccak256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -162,7 +180,7 @@ "Doc": "SHA512_256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -170,8 +188,8 @@ "Name": "ed25519verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -182,14 +200,14 @@ "DocExtra": "The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { "Opcode": 5, "Name": "ecdsa_verify", "Args": [ - "[]byte", + "[32]byte", "[]byte", "[]byte", "[]byte", @@ -216,7 +234,7 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -247,17 +265,17 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { "Opcode": 7, "Name": "ecdsa_pk_recover", "Args": [ - "[]byte", + "[32]byte", "uint64", - "[]byte", - "[]byte" + "[32]byte", + "[32]byte" ], "Returns": [ "[]byte", @@ -281,7 +299,7 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -534,7 +552,7 @@ "Doc": "yields length of byte value A", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2124,7 +2142,7 @@ "DocExtra": "`concat` fails if the result would be greater than 4096 bytes.", "IntroducedVersion": 2, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2191,7 +2209,7 @@ "DocExtra": "see explanation of bit ordering in setbit", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2211,7 +2229,7 @@ "DocExtra": "When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on the integer 0 yields 8, or 2^3. When A is a byte array, index 0 is the leftmost bit of the leftmost byte. Setting bits 0 through 11 to 1 in a 4-byte-array of 0s yields the byte array 0xfff00000. Setting bit 3 to 1 on the 1-byte-array 0x00 yields the byte array 0x10.", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2229,7 +2247,7 @@ "Doc": "Bth byte of A, as an integer. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2248,7 +2266,7 @@ "Doc": "Copy of A with the Bth byte set to small integer (between 0..255) C. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2889,8 +2907,8 @@ "Name": "ed25519verify_bare", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -2900,7 +2918,7 @@ "Doc": "for (data A, signature B, pubkey C) verify the signature of the data against the pubkey =\u003e {0 or 1}", "IntroducedVersion": 7, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -3093,7 +3111,7 @@ "Doc": "SHA3_256 hash of value A, yields [32]byte", "IntroducedVersion": 7, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -4216,8 +4234,8 @@ "Name": "vrf_verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[80]byte", + "[32]byte" ], "Returns": [ "[]byte", @@ -4240,7 +4258,7 @@ ], "IntroducedVersion": 7, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { diff --git a/data/transactions/logic/langspec_v8.json b/data/transactions/logic/langspec_v8.json index 1cce84389a..3b496ddcb8 100644 --- a/data/transactions/logic/langspec_v8.json +++ b/data/transactions/logic/langspec_v8.json @@ -3,46 +3,64 @@ "LogicSigVersion": 9, "NamedTypes": [ { - "Name": "uint64", - "Abbreviation": "i", + "Name": "[32]byte", + "Abbreviation": "3", "Bound": [ - 0, - 18446744073709551615 + 32, + 32 ], - "AVMType": "uint64" + "AVMType": "[]byte" }, { - "Name": "stateKey", - "Abbreviation": "K", + "Name": "[64]byte", + "Abbreviation": "6", "Bound": [ - 0, + 64, 64 ], "AVMType": "[]byte" }, { - "Name": "none", - "Abbreviation": "x", + "Name": "[80]byte", + "Abbreviation": "8", + "Bound": [ + 80, + 80 + ], + "AVMType": "[]byte" + }, + { + "Name": "[]byte", + "Abbreviation": "b", "Bound": [ 0, - 0 + 4096 ], - "AVMType": "none" + "AVMType": "[]byte" }, { - "Name": "method", - "Abbreviation": "M", + "Name": "address", + "Abbreviation": "A", "Bound": [ - 4, - 4 + 32, + 32 ], "AVMType": "[]byte" }, { - "Name": "boxName", - "Abbreviation": "N", + "Name": "any", + "Abbreviation": "a", "Bound": [ - 1, + 0, + 0 + ], + "AVMType": "any" + }, + { + "Name": "bigint", + "Abbreviation": "I", + "Bound": [ + 0, 64 ], "AVMType": "[]byte" @@ -57,49 +75,49 @@ "AVMType": "uint64" }, { - "Name": "bigint", - "Abbreviation": "I", + "Name": "boxName", + "Abbreviation": "N", "Bound": [ - 0, + 1, 64 ], "AVMType": "[]byte" }, { - "Name": "any", - "Abbreviation": "a", + "Name": "method", + "Abbreviation": "M", "Bound": [ - 0, - 0 + 4, + 4 ], - "AVMType": "any" + "AVMType": "[]byte" }, { - "Name": "address", - "Abbreviation": "A", + "Name": "none", + "Abbreviation": "x", "Bound": [ - 32, - 32 + 0, + 0 ], - "AVMType": "[]byte" + "AVMType": "none" }, { - "Name": "[]byte", - "Abbreviation": "b", + "Name": "stateKey", + "Abbreviation": "K", "Bound": [ 0, - 4096 + 64 ], "AVMType": "[]byte" }, { - "Name": "[32]byte", - "Abbreviation": "H", + "Name": "uint64", + "Abbreviation": "i", "Bound": [ - 32, - 32 + 0, + 18446744073709551615 ], - "AVMType": "[]byte" + "AVMType": "uint64" } ], "Ops": [ @@ -128,7 +146,7 @@ "Doc": "SHA256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -145,7 +163,7 @@ "Doc": "Keccak256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -162,7 +180,7 @@ "Doc": "SHA512_256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -170,8 +188,8 @@ "Name": "ed25519verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -182,14 +200,14 @@ "DocExtra": "The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { "Opcode": 5, "Name": "ecdsa_verify", "Args": [ - "[]byte", + "[32]byte", "[]byte", "[]byte", "[]byte", @@ -216,7 +234,7 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -247,17 +265,17 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { "Opcode": 7, "Name": "ecdsa_pk_recover", "Args": [ - "[]byte", + "[32]byte", "uint64", - "[]byte", - "[]byte" + "[32]byte", + "[32]byte" ], "Returns": [ "[]byte", @@ -281,7 +299,7 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -534,7 +552,7 @@ "Doc": "yields length of byte value A", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2184,7 +2202,7 @@ "DocExtra": "`concat` fails if the result would be greater than 4096 bytes.", "IntroducedVersion": 2, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2251,7 +2269,7 @@ "DocExtra": "see explanation of bit ordering in setbit", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2271,7 +2289,7 @@ "DocExtra": "When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on the integer 0 yields 8, or 2^3. When A is a byte array, index 0 is the leftmost bit of the leftmost byte. Setting bits 0 through 11 to 1 in a 4-byte-array of 0s yields the byte array 0xfff00000. Setting bit 3 to 1 on the 1-byte-array 0x00 yields the byte array 0x10.", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2289,7 +2307,7 @@ "Doc": "Bth byte of A, as an integer. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2308,7 +2326,7 @@ "Doc": "Copy of A with the Bth byte set to small integer (between 0..255) C. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -3005,8 +3023,8 @@ "Name": "ed25519verify_bare", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -3016,7 +3034,7 @@ "Doc": "for (data A, signature B, pubkey C) verify the signature of the data against the pubkey =\u003e {0 or 1}", "IntroducedVersion": 7, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -3315,7 +3333,7 @@ "Doc": "SHA3_256 hash of value A, yields [32]byte", "IntroducedVersion": 7, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -4562,8 +4580,8 @@ "Name": "vrf_verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[80]byte", + "[32]byte" ], "Returns": [ "[]byte", @@ -4586,7 +4604,7 @@ ], "IntroducedVersion": 7, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { diff --git a/data/transactions/logic/langspec_v9.json b/data/transactions/logic/langspec_v9.json index 9c4a41c780..c52d36862d 100644 --- a/data/transactions/logic/langspec_v9.json +++ b/data/transactions/logic/langspec_v9.json @@ -3,46 +3,64 @@ "LogicSigVersion": 9, "NamedTypes": [ { - "Name": "uint64", - "Abbreviation": "i", + "Name": "[32]byte", + "Abbreviation": "3", "Bound": [ - 0, - 18446744073709551615 + 32, + 32 ], - "AVMType": "uint64" + "AVMType": "[]byte" }, { - "Name": "stateKey", - "Abbreviation": "K", + "Name": "[64]byte", + "Abbreviation": "6", "Bound": [ - 0, + 64, 64 ], "AVMType": "[]byte" }, { - "Name": "none", - "Abbreviation": "x", + "Name": "[80]byte", + "Abbreviation": "8", + "Bound": [ + 80, + 80 + ], + "AVMType": "[]byte" + }, + { + "Name": "[]byte", + "Abbreviation": "b", "Bound": [ 0, - 0 + 4096 ], - "AVMType": "none" + "AVMType": "[]byte" }, { - "Name": "method", - "Abbreviation": "M", + "Name": "address", + "Abbreviation": "A", "Bound": [ - 4, - 4 + 32, + 32 ], "AVMType": "[]byte" }, { - "Name": "boxName", - "Abbreviation": "N", + "Name": "any", + "Abbreviation": "a", "Bound": [ - 1, + 0, + 0 + ], + "AVMType": "any" + }, + { + "Name": "bigint", + "Abbreviation": "I", + "Bound": [ + 0, 64 ], "AVMType": "[]byte" @@ -57,49 +75,49 @@ "AVMType": "uint64" }, { - "Name": "bigint", - "Abbreviation": "I", + "Name": "boxName", + "Abbreviation": "N", "Bound": [ - 0, + 1, 64 ], "AVMType": "[]byte" }, { - "Name": "any", - "Abbreviation": "a", + "Name": "method", + "Abbreviation": "M", "Bound": [ - 0, - 0 + 4, + 4 ], - "AVMType": "any" + "AVMType": "[]byte" }, { - "Name": "address", - "Abbreviation": "A", + "Name": "none", + "Abbreviation": "x", "Bound": [ - 32, - 32 + 0, + 0 ], - "AVMType": "[]byte" + "AVMType": "none" }, { - "Name": "[]byte", - "Abbreviation": "b", + "Name": "stateKey", + "Abbreviation": "K", "Bound": [ 0, - 4096 + 64 ], "AVMType": "[]byte" }, { - "Name": "[32]byte", - "Abbreviation": "H", + "Name": "uint64", + "Abbreviation": "i", "Bound": [ - 32, - 32 + 0, + 18446744073709551615 ], - "AVMType": "[]byte" + "AVMType": "uint64" } ], "Ops": [ @@ -128,7 +146,7 @@ "Doc": "SHA256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -145,7 +163,7 @@ "Doc": "Keccak256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -162,7 +180,7 @@ "Doc": "SHA512_256 hash of value A, yields [32]byte", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -170,8 +188,8 @@ "Name": "ed25519verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -182,14 +200,14 @@ "DocExtra": "The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { "Opcode": 5, "Name": "ecdsa_verify", "Args": [ - "[]byte", + "[32]byte", "[]byte", "[]byte", "[]byte", @@ -216,7 +234,7 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -247,17 +265,17 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { "Opcode": 7, "Name": "ecdsa_pk_recover", "Args": [ - "[]byte", + "[32]byte", "uint64", - "[]byte", - "[]byte" + "[32]byte", + "[32]byte" ], "Returns": [ "[]byte", @@ -281,7 +299,7 @@ ], "IntroducedVersion": 5, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -534,7 +552,7 @@ "Doc": "yields length of byte value A", "IntroducedVersion": 1, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2184,7 +2202,7 @@ "DocExtra": "`concat` fails if the result would be greater than 4096 bytes.", "IntroducedVersion": 2, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2251,7 +2269,7 @@ "DocExtra": "see explanation of bit ordering in setbit", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2271,7 +2289,7 @@ "DocExtra": "When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on the integer 0 yields 8, or 2^3. When A is a byte array, index 0 is the leftmost bit of the leftmost byte. Setting bits 0 through 11 to 1 in a 4-byte-array of 0s yields the byte array 0xfff00000. Setting bit 3 to 1 on the 1-byte-array 0x00 yields the byte array 0x10.", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2289,7 +2307,7 @@ "Doc": "Bth byte of A, as an integer. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -2308,7 +2326,7 @@ "Doc": "Copy of A with the Bth byte set to small integer (between 0..255) C. If B is greater than or equal to the array length, the program fails", "IntroducedVersion": 3, "Groups": [ - "Arithmetic" + "Byte Array Manipulation" ] }, { @@ -3005,8 +3023,8 @@ "Name": "ed25519verify_bare", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[64]byte", + "[32]byte" ], "Returns": [ "bool" @@ -3016,7 +3034,7 @@ "Doc": "for (data A, signature B, pubkey C) verify the signature of the data against the pubkey =\u003e {0 or 1}", "IntroducedVersion": 7, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -3315,7 +3333,7 @@ "Doc": "SHA3_256 hash of value A, yields [32]byte", "IntroducedVersion": 7, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { @@ -4562,8 +4580,8 @@ "Name": "vrf_verify", "Args": [ "[]byte", - "[]byte", - "[]byte" + "[80]byte", + "[32]byte" ], "Returns": [ "[]byte", @@ -4586,7 +4604,7 @@ ], "IntroducedVersion": 7, "Groups": [ - "Arithmetic" + "Cryptography" ] }, { diff --git a/data/transactions/logic/opcodes.go b/data/transactions/logic/opcodes.go index e005d57cf3..dc2d44bc09 100644 --- a/data/transactions/logic/opcodes.go +++ b/data/transactions/logic/opcodes.go @@ -485,17 +485,17 @@ func (spec *OpSpec) deadens() bool { // assembly-time, with ops.returns() var OpSpecs = []OpSpec{ {0x00, "err", opErr, proto(":x"), 1, detDefault()}, - {0x01, "sha256", opSHA256, proto("b:H"), 1, costly(7)}, - {0x02, "keccak256", opKeccak256, proto("b:H"), 1, costly(26)}, - {0x03, "sha512_256", opSHA512_256, proto("b:H"), 1, costly(9)}, + {0x01, "sha256", opSHA256, proto("b:3"), 1, costly(7)}, + {0x02, "keccak256", opKeccak256, proto("b:3"), 1, costly(26)}, + {0x03, "sha512_256", opSHA512_256, proto("b:3"), 1, costly(9)}, // Cost of these opcodes increases in AVM version 2 based on measured // performance. Should be able to run max hashes during stateful TEAL // and achieve reasonable TPS. Same opcode for different versions // is OK. - {0x01, "sha256", opSHA256, proto("b:H"), 2, costly(35)}, - {0x02, "keccak256", opKeccak256, proto("b:H"), 2, costly(130)}, - {0x03, "sha512_256", opSHA512_256, proto("b:H"), 2, costly(45)}, + {0x01, "sha256", opSHA256, proto("b:3"), 2, costly(35)}, + {0x02, "keccak256", opKeccak256, proto("b:3"), 2, costly(130)}, + {0x03, "sha512_256", opSHA512_256, proto("b:3"), 2, costly(45)}, /* Tabling these changes until we offer unlimited global storage as there @@ -507,12 +507,12 @@ var OpSpecs = []OpSpec{ {0x03, "sha512_256", opSHA512_256, proto("b:b"), 7, unlimitedStorage, costByLength(17, 5, 8)}, */ - {0x04, "ed25519verify", opEd25519Verify, proto("bbb:T"), 1, costly(1900).only(ModeSig)}, - {0x04, "ed25519verify", opEd25519Verify, proto("bbb:T"), 5, costly(1900)}, + {0x04, "ed25519verify", opEd25519Verify, proto("b63:T"), 1, costly(1900).only(ModeSig)}, + {0x04, "ed25519verify", opEd25519Verify, proto("b63:T"), 5, costly(1900)}, - {0x05, "ecdsa_verify", opEcdsaVerify, proto("bbbbb:T"), 5, costByField("v", &EcdsaCurves, ecdsaVerifyCosts)}, + {0x05, "ecdsa_verify", opEcdsaVerify, proto("3bbbb:T"), 5, costByField("v", &EcdsaCurves, ecdsaVerifyCosts)}, {0x06, "ecdsa_pk_decompress", opEcdsaPkDecompress, proto("b:bb"), 5, costByField("v", &EcdsaCurves, ecdsaDecompressCosts)}, - {0x07, "ecdsa_pk_recover", opEcdsaPkRecover, proto("bibb:bb"), 5, field("v", &EcdsaCurves).costs(2000)}, + {0x07, "ecdsa_pk_recover", opEcdsaPkRecover, proto("3i33:bb"), 5, field("v", &EcdsaCurves).costs(2000)}, {0x08, "+", opPlus, proto("ii:i"), 1, detDefault()}, {0x09, "-", opMinus, proto("ii:i"), 1, detDefault()}, @@ -645,7 +645,7 @@ var OpSpecs = []OpSpec{ {0x82, "pushbytess", opPushBytess, proto(":", "", "[N items]").stackExplain(opPushBytessStackChange), 8, constants(asmPushBytess, checkByteImmArgs, "bytes ...", immBytess).typed(typePushBytess).trust()}, {0x83, "pushints", opPushInts, proto(":", "", "[N items]").stackExplain(opPushIntsStackChange), 8, constants(asmPushInts, checkIntImmArgs, "uint ...", immInts).typed(typePushInts).trust()}, - {0x84, "ed25519verify_bare", opEd25519VerifyBare, proto("bbb:T"), 7, costly(1900)}, + {0x84, "ed25519verify_bare", opEd25519VerifyBare, proto("b63:T"), 7, costly(1900)}, // "Function oriented" {0x88, "callsub", opCallSub, proto(":"), 4, detBranch()}, @@ -719,7 +719,7 @@ var OpSpecs = []OpSpec{ {0xc6, "gitxnas", opGitxnas, proto("i:a"), 6, immediates("t", "f").field("f", &TxnArrayFields).only(ModeApp)}, // randomness support - {0xd0, "vrf_verify", opVrfVerify, proto("bbb:bT"), randomnessVersion, field("s", &VrfStandards).costs(5700)}, + {0xd0, "vrf_verify", opVrfVerify, proto("b83:bT"), randomnessVersion, field("s", &VrfStandards).costs(5700)}, {0xd1, "block", opBlock, proto("i:a"), randomnessVersion, field("f", &BlockFields)}, {0xe0, "ec_add", opEcAdd, proto("bb:b"), pairingVersion, diff --git a/data/transactions/logic/teal.tmLanguage.json b/data/transactions/logic/teal.tmLanguage.json index f63c91778a..56cf7b5dc8 100644 --- a/data/transactions/logic/teal.tmLanguage.json +++ b/data/transactions/logic/teal.tmLanguage.json @@ -76,7 +76,7 @@ }, { "name": "keyword.operator.teal", - "match": "^(\\!|\\!\\=|%|\u0026|\u0026\u0026|\\*|\\+|\\-|/|\\\u003c|\\\u003c\\=|\\=\\=|\\\u003e|\\\u003e\\=|\\^|addw|bitlen|btoi|concat|divmodw|divw|ec_add|ec_map_to|ec_multi_scalar_mul|ec_pairing_check|ec_scalar_mul|ec_subgroup_check|ecdsa_pk_decompress|ecdsa_pk_recover|ecdsa_verify|ed25519verify|ed25519verify_bare|exp|expw|getbit|getbyte|itob|keccak256|len|mulw|setbit|setbyte|sha256|sha3_256|sha512_256|shl|shr|sqrt|vrf_verify|\\||\\|\\||\\~|b\\!\\=|b%|b\\*|b\\+|b\\-|b/|b\\\u003c|b\\\u003c\\=|b\\=\\=|b\\\u003e|b\\\u003e\\=|bsqrt|b\u0026|b\\^|b\\||b\\~|base64_decode|extract|extract3|extract_uint16|extract_uint32|extract_uint64|json_ref|replace2|replace3|substring|substring3|gitxn|gitxna|gitxnas|itxn|itxn_begin|itxn_field|itxn_next|itxn_submit|itxna|itxnas)\\b" + "match": "^(\\!|\\!\\=|%|\u0026|\u0026\u0026|\\*|\\+|\\-|/|\\\u003c|\\\u003c\\=|\\=\\=|\\\u003e|\\\u003e\\=|\\^|addw|bitlen|btoi|divmodw|divw|exp|expw|itob|mulw|shl|shr|sqrt|\\||\\|\\||\\~|b\\!\\=|b%|b\\*|b\\+|b\\-|b/|b\\\u003c|b\\\u003c\\=|b\\=\\=|b\\\u003e|b\\\u003e\\=|bsqrt|b\u0026|b\\^|b\\||b\\~|base64_decode|concat|extract|extract3|extract_uint16|extract_uint32|extract_uint64|getbit|getbyte|json_ref|len|replace2|replace3|setbit|setbyte|substring|substring3|ec_add|ec_map_to|ec_multi_scalar_mul|ec_pairing_check|ec_scalar_mul|ec_subgroup_check|ecdsa_pk_decompress|ecdsa_pk_recover|ecdsa_verify|ed25519verify|ed25519verify_bare|keccak256|sha256|sha3_256|sha512_256|vrf_verify|gitxn|gitxna|gitxnas|itxn|itxn_begin|itxn_field|itxn_next|itxn_submit|itxna|itxnas)\\b" } ] },