summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Jannotti <john.jannotti@algorand.com>2022-01-14 11:12:30 -0500
committerGitHub <noreply@github.com>2022-01-14 11:12:30 -0500
commita4d9d718ab7df34168d897fc8c9a6e9abb72c9ea (patch)
tree661cc819bb531d42c57ab4f0c4efd9c5d7ff9e77
parent29269c3504976ac57901eec5d402c4c37cbef607 (diff)
c2c: bsqrt, acct_params_get (#3404)
also an e2e inner appl test
-rw-r--r--THANKS.md1
-rw-r--r--cmd/opdoc/opdoc.go72
-rw-r--r--data/transactions/logic/README.md213
-rw-r--r--data/transactions/logic/README_in.md16
-rw-r--r--data/transactions/logic/TEAL_opcodes.md216
-rw-r--r--data/transactions/logic/assembler.go43
-rw-r--r--data/transactions/logic/assembler_test.go6
-rw-r--r--data/transactions/logic/doc.go212
-rw-r--r--data/transactions/logic/doc_test.go1
-rw-r--r--data/transactions/logic/eval.go116
-rw-r--r--data/transactions/logic/evalStateful_test.go32
-rw-r--r--data/transactions/logic/eval_test.go16
-rw-r--r--data/transactions/logic/fields.go120
-rw-r--r--data/transactions/logic/fields_string.go22
-rw-r--r--data/transactions/logic/fields_test.go5
-rw-r--r--data/transactions/logic/opcodes.go10
-rwxr-xr-xtest/scripts/e2e_subs/app-inner-calls.py149
-rwxr-xr-xtest/scripts/e2e_subs/goal/goal.py21
18 files changed, 818 insertions, 453 deletions
diff --git a/THANKS.md b/THANKS.md
index f0eb65981..0585b9338 100644
--- a/THANKS.md
+++ b/THANKS.md
@@ -5,6 +5,7 @@ A big thank you to everyone who has contributed to the `go-algorand` codebase.
### External Contributors
- aybehrouz
+- fionnachan
- jeapostrophe
- jecassis
- jsign
diff --git a/cmd/opdoc/opdoc.go b/cmd/opdoc/opdoc.go
index 71beaa4aa..c98a1a0f7 100644
--- a/cmd/opdoc/opdoc.go
+++ b/cmd/opdoc/opdoc.go
@@ -286,28 +286,6 @@ type LanguageSpec struct {
Ops []OpRecord
}
-func argEnum(name string) []string {
- if name == "txn" || name == "gtxn" || name == "gtxns" {
- return logic.TxnFieldNames
- }
- if name == "global" {
- return logic.GlobalFieldNames
- }
- if name == "txna" || name == "gtxna" || name == "gtxnsa" || name == "txnas" || name == "gtxnas" || name == "gtxnsas" {
- return logic.TxnaFieldNames()
- }
- if name == "asset_holding_get" {
- return logic.AssetHoldingFieldNames
- }
- if name == "asset_params_get" {
- return logic.AssetParamsFieldNames
- }
- if name == "app_params_get" {
- return logic.AppParamsFieldNames
- }
- return nil
-}
-
func typeString(types []logic.StackType) string {
out := make([]byte, len(types))
for i, t := range types {
@@ -330,27 +308,32 @@ func typeString(types []logic.StackType) string {
return string(out)
}
-func argEnumTypes(name string) string {
- if name == "txn" || name == "gtxn" || name == "gtxns" || name == "itxn" || name == "gitxn" || name == "itxn_field" {
- return typeString(logic.TxnFieldTypes)
- }
- if name == "global" {
- return typeString(logic.GlobalFieldTypes)
- }
- if name == "txna" || name == "gtxna" || name == "gtxnsa" || name == "txnas" || name == "gtxnas" || name == "gtxnsas" || name == "itxna" || name == "gitxna" {
- return typeString(logic.TxnaFieldTypes())
- }
- if name == "asset_holding_get" {
- return typeString(logic.AssetHoldingFieldTypes)
- }
- if name == "asset_params_get" {
- return typeString(logic.AssetParamsFieldTypes)
- }
- if name == "app_params_get" {
- return typeString(logic.AppParamsFieldTypes)
+func fieldsAndTypes(names []string, specs speccer) ([]string, string) {
+ types := make([]logic.StackType, len(names))
+ for i, name := range names {
+ types[i] = specs.SpecByName(name).Type()
}
+ return names, typeString(types)
+}
- return ""
+func argEnums(name string) (names []string, types string) {
+ switch name {
+ case "txn", "gtxn", "gtxns", "itxn", "gitxn", "itxn_field":
+ return fieldsAndTypes(logic.TxnFieldNames, logic.TxnFieldSpecByName)
+ case "global":
+ return
+ case "txna", "gtxna", "gtxnsa", "txnas", "gtxnas", "gtxnsas", "itxna", "gitxna":
+ // Map is the whole txn field spec map. That's fine, we only lookup the given names.
+ return fieldsAndTypes(logic.TxnaFieldNames(), logic.TxnFieldSpecByName)
+ case "asset_holding_get":
+ return fieldsAndTypes(logic.AssetHoldingFieldNames, logic.AssetHoldingFieldSpecByName)
+ case "asset_params_get":
+ return fieldsAndTypes(logic.AssetParamsFieldNames, logic.AssetParamsFieldSpecByName)
+ case "app_params_get":
+ return fieldsAndTypes(logic.AppParamsFieldNames, logic.AppParamsFieldSpecByName)
+ default:
+ return nil, ""
+ }
}
func buildLanguageSpec(opGroups map[string][]string) *LanguageSpec {
@@ -363,8 +346,7 @@ func buildLanguageSpec(opGroups map[string][]string) *LanguageSpec {
records[i].Returns = typeString(spec.Returns)
records[i].Cost = spec.Details.Cost
records[i].Size = spec.Details.Size
- records[i].ArgEnum = argEnum(spec.Name)
- records[i].ArgEnumTypes = argEnumTypes(spec.Name)
+ records[i].ArgEnum, records[i].ArgEnumTypes = argEnums(spec.Name)
records[i].Doc = logic.OpDoc(spec.Name)
records[i].DocExtra = logic.OpDocExtra(spec.Name)
records[i].ImmediateNote = logic.OpImmediateNote(spec.Name)
@@ -416,6 +398,10 @@ func main() {
fieldSpecsMarkdown(appparams, logic.AppParamsFieldNames, logic.AppParamsFieldSpecByName)
appparams.Close()
+ acctparams, _ := os.Create("acct_params_fields.md")
+ fieldSpecsMarkdown(acctparams, logic.AcctParamsFieldNames, logic.AcctParamsFieldSpecByName)
+ acctparams.Close()
+
langspecjs, _ := os.Create("langspec.json")
enc := json.NewEncoder(langspecjs)
enc.Encode(buildLanguageSpec(opGroups))
diff --git a/data/transactions/logic/README.md b/data/transactions/logic/README.md
index f7abbb58c..f81173d39 100644
--- a/data/transactions/logic/README.md
+++ b/data/transactions/logic/README.md
@@ -217,7 +217,7 @@ return stack matches the name of the input value.
| `\|\|` | A is not zero or B is not zero => {0 or 1} |
| `shl` | A times 2^B, modulo 2^64 |
| `shr` | A divided by 2^B |
-| `sqrt` | The largest integer B such that B^2 <= A |
+| `sqrt` | The largest integer I such that I^2 <= A |
| `bitlen` | The highest set bit in A. If A is a byte-array, it is interpreted as a big-endian unsigned integer. bitlen of 0 is 0, bitlen of 8 is 4 |
| `exp` | A raised to the Bth power. Fail if A == B == 0 and on overflow |
| `==` | A is equal to B => {0 or 1} |
@@ -233,26 +233,26 @@ return stack matches the name of the input value.
| `~` | bitwise invert value A |
| `mulw` | A times B as a 128-bit result in two uint64s. X is the high 64 bits, Y is the low |
| `addw` | A plus B as a 128-bit result. X is the carry-bit, Y is the low-order 64 bits. |
-| `divmodw` | Pop four uint64 values. A and B are interpreted as a uint128 dividend (A is the high word), C and D are interpreted as a uint128 divisor (C is the high word). Four uint64 values are pushed to the stack. The W and X are the quotient (W is the high uint64). Y and Z are the remainder, Y is the high bits. |
+| `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` | pop a target A (integer or byte-array), and index B. Push the Bth bit of A. |
-| `setbit` | pop a target A, index B, and bit C. Set the Bth bit of A to C, and push the result |
-| `getbyte` | pop a byte-array A and integer B. Extract the Bth byte of A and push it as an integer |
-| `setbyte` | pop a byte-array A, integer B, and small integer C (between 0..255). Set the Bth byte of A to C, and push the result |
-| `concat` | pop two byte-arrays A and B and join them, push the result |
+| `getbit` | Bth bit of (byte-array or integer) A. |
+| `setbit` | Copy of (byte-array or integer) A, with the Bth bit set to (0 or 1) C |
+| `getbyte` | Bth byte of A, as an integer |
+| `setbyte` | Copy of A with the Bth byte set to small integer (between 0..255) C |
+| `concat` | join A and B |
### Byte Array Manipulation
| Opcode | Description |
| - | -- |
-| `substring s e` | pop a byte-array A. For immediate values in 0..255 S and E: extract a range of bytes from A starting at S up to but not including E, push the substring result. If E < S, or either is larger than the array length, the program fails |
-| `substring3` | pop a byte-array A and two integers B and C. Extract a range of bytes from A starting at B up to but not including C, push the substring result. If C < B, or either is larger than the array length, the program fails |
-| `extract s l` | pop a byte-array A. For immediate values in 0..255 S and L: extract a range of bytes from A starting at S up to but not including S+L, push the substring result. 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 |
-| `extract3` | pop a byte-array A and two integers B and C. Extract a range of bytes from A starting at B up to but not including B+C, push the substring result. If B+C is larger than the array length, the program fails |
-| `extract_uint16` | pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+2, convert bytes as big endian and push the uint64 result. If B+2 is larger than the array length, the program fails |
-| `extract_uint32` | pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+4, convert bytes as big endian and push the uint64 result. If B+4 is larger than the array length, the program fails |
-| `extract_uint64` | pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+8, convert bytes as big endian and push the uint64 result. If B+8 is larger than the array length, the program fails |
-| `base64_decode e` | decode A which was base64-encoded using _encoding_ E. Fail if X is not base64 encoded with encoding E |
+| `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 |
+| `extract3` | A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails |
+| `extract_uint16` | A uint16 formed from a range of big-endian bytes from A starting at B up to but not including B+2. If B+2 is larger than the array length, the program fails |
+| `extract_uint32` | A uint32 formed from a range of big-endian bytes from A starting at B up to but not including B+4. If B+4 is larger than the array length, the program fails |
+| `extract_uint64` | A uint64 formed from a range of big-endian bytes from A starting at B up to but not including B+8. If B+8 is larger than the array length, the program fails |
+| `base64_decode e` | decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E |
The following opcodes take byte-array values that are interpreted as
big-endian unsigned integers. For mathematical operators, the
@@ -268,17 +268,18 @@ bytes on outputs.
| Opcode | Description |
| - | -- |
-| `b+` | A plus B, where A and B are byte-arrays interpreted as big-endian unsigned integers |
-| `b-` | A minus B, where A and B are byte-arrays interpreted as big-endian unsigned integers. Fail on underflow. |
-| `b/` | A divided by B (truncated division), where A and B are byte-arrays interpreted as big-endian unsigned integers. Fail if B is zero. |
-| `b*` | A times B, where A and B are byte-arrays interpreted as big-endian unsigned integers. |
-| `b<` | A is less than B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1} |
-| `b>` | A is greater than B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1} |
-| `b<=` | A is less than or equal to B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1} |
-| `b>=` | A is greater than or equal to B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1} |
-| `b==` | A is equals to B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1} |
-| `b!=` | A is not equal to B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1} |
-| `b%` | A modulo B, where A and B are byte-arrays interpreted as big-endian unsigned integers. Fail if B is zero. |
+| `b+` | A plus B. A and B are interpreted as big-endian unsigned integers |
+| `b-` | A minus B. A and B are interpreted as big-endian unsigned integers. Fail on underflow. |
+| `b/` | A divided by B (truncated division). A and B are interpreted as big-endian unsigned integers. Fail if B is zero. |
+| `b*` | A times B. A and B are interpreted as big-endian unsigned integers. |
+| `b<` | 1 if A is less than B, else 0. A and B are interpreted as big-endian unsigned integers |
+| `b>` | 1 if A is greater than B, else 0. A and B are interpreted as big-endian unsigned integers |
+| `b<=` | 1 if A is less than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers |
+| `b>=` | 1 if A is greater than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers |
+| `b==` | 1 if A is equal to B, else 0. A and B are interpreted as big-endian unsigned integers |
+| `b!=` | 0 if A is equal to B, else 1. A and B are interpreted as big-endian unsigned integers |
+| `b%` | A modulo B. A and B are interpreted as big-endian unsigned integers. Fail if B is zero. |
+| `bsqrt` | The largest integer I such that I^2 <= A. A and I are interpreted as big-endian unsigned integers |
These opcodes operate on the bits of byte-array values. The shorter
input array is interpreted as though left padded with zeros until it is the
@@ -288,9 +289,9 @@ these results may contain leading zero bytes.
| Opcode | Description |
| - | -- |
-| `b\|` | A bitwise-or B, where A and B are byte-arrays, zero-left extended to the greater of their lengths |
-| `b&` | A bitwise-and B, where A and B are byte-arrays, zero-left extended to the greater of their lengths |
-| `b^` | A bitwise-xor B, where A and B are byte-arrays, zero-left extended to the greater of their lengths |
+| `b\|` | A bitwise-or B. A and B are zero-left extended to the greater of their lengths |
+| `b&` | A bitwise-and B. A and B are zero-left extended to the greater of their lengths |
+| `b^` | A bitwise-xor B. A and B are zero-left extended to the greater of their lengths |
| `b~` | A with all bits inverted |
### Loading Values
@@ -302,59 +303,59 @@ Some of these have immediate data in the byte or bytes after the opcode.
| Opcode | Description |
| - | -- |
| `intcblock uint ...` | prepare block of uint64 constants for use by intc |
-| `intc i` | push Ith constant from intcblock to stack |
-| `intc_0` | push constant 0 from intcblock to stack |
-| `intc_1` | push constant 1 from intcblock to stack |
-| `intc_2` | push constant 2 from intcblock to stack |
-| `intc_3` | push constant 3 from intcblock to stack |
-| `pushint uint` | push immediate UINT to the stack as an integer |
+| `intc i` | Ith constant from intcblock |
+| `intc_0` | constant 0 from intcblock |
+| `intc_1` | constant 1 from intcblock |
+| `intc_2` | constant 2 from intcblock |
+| `intc_3` | constant 3 from intcblock |
+| `pushint uint` | immediate UINT |
| `bytecblock bytes ...` | prepare block of byte-array constants for use by bytec |
-| `bytec i` | push Ith constant from bytecblock to stack |
-| `bytec_0` | push constant 0 from bytecblock to stack |
-| `bytec_1` | push constant 1 from bytecblock to stack |
-| `bytec_2` | push constant 2 from bytecblock to stack |
-| `bytec_3` | push constant 3 from bytecblock to stack |
-| `pushbytes bytes` | push the following program bytes to the stack |
-| `bzero` | push a byte-array of length A, containing all zero bytes |
-| `arg n` | push Nth LogicSig argument to stack |
-| `arg_0` | push LogicSig argument 0 to stack |
-| `arg_1` | push LogicSig argument 1 to stack |
-| `arg_2` | push LogicSig argument 2 to stack |
-| `arg_3` | push LogicSig argument 3 to stack |
-| `args` | push Ath LogicSig argument to stack |
-| `txn f` | push field F of current transaction to stack |
-| `gtxn t f` | push field F of the Tth transaction in the current group |
-| `txna f i` | push Ith value of the array field F of the current transaction |
-| `txnas f` | push Ath value of the array field F of the current transaction |
-| `gtxna t f i` | push Ith value of the array field F from the Tth transaction in the current group |
-| `gtxnas t f` | push Ath value of the array field F from the Tth transaction in the current group |
-| `gtxns f` | push field F of the Ath transaction in the current group |
-| `gtxnsa f i` | push Ith value of the array field F from the Ath transaction in the current group |
-| `gtxnsas f` | pop an index A and an index B. push Bth value of the array field F from the Ath transaction in the current group |
-| `global f` | push value from globals to stack |
-| `load i` | copy a value from scratch space to the stack. All scratch spaces are 0 at program start. |
-| `loads` | copy a value from the Ath scratch space to the stack. All scratch spaces are 0 at program start. |
-| `store i` | pop value A. store A to the Ith scratch space |
-| `stores` | pop indexes A and B. store B to the Ath scratch space |
-| `gload t i` | push Ith scratch space index of the Tth transaction in the current group |
-| `gloads i` | push Ith scratch space index of the Ath transaction in the current group |
-| `gloadss` | push Bth scratch space index of the Ath transaction in the current group |
-| `gaid t` | push the ID of the asset or application created in the Tth transaction of the current group |
-| `gaids` | push the ID of the asset or application created in the Ath transaction of the current group |
+| `bytec i` | Ith constant from bytecblock |
+| `bytec_0` | constant 0 from bytecblock |
+| `bytec_1` | constant 1 from bytecblock |
+| `bytec_2` | constant 2 from bytecblock |
+| `bytec_3` | constant 3 from bytecblock |
+| `pushbytes bytes` | immediate BYTES |
+| `bzero` | zero filled byte-array of length A |
+| `arg n` | Nth LogicSig argument |
+| `arg_0` | LogicSig argument 0 |
+| `arg_1` | LogicSig argument 1 |
+| `arg_2` | LogicSig argument 2 |
+| `arg_3` | LogicSig argument 3 |
+| `args` | Ath LogicSig argument |
+| `txn f` | field F of current transaction |
+| `gtxn t f` | field F of the Tth transaction in the current group |
+| `txna f i` | Ith value of the array field F of the current transaction |
+| `txnas f` | Ath value of the array field F of the current transaction |
+| `gtxna t f i` | Ith value of the array field F from the Tth transaction in the current group |
+| `gtxnas t f` | Ath value of the array field F from the Tth transaction in the current group |
+| `gtxns f` | field F of the Ath transaction in the current group |
+| `gtxnsa f i` | Ith value of the array field F from the Ath transaction in the current group |
+| `gtxnsas f` | Bth value of the array field F from the Ath transaction in the current group |
+| `global f` | global field F |
+| `load i` | Ith scratch space value. All scratch spaces are 0 at program start. |
+| `loads` | Ath scratch space value. All scratch spaces are 0 at program start. |
+| `store i` | store A to the Ith scratch space |
+| `stores` | store B to the Ath scratch space |
+| `gload t i` | Ith scratch space value of the Tth transaction in the current group |
+| `gloads i` | Ith scratch space value of the Ath transaction in the current group |
+| `gloadss` | Bth scratch space value of the Ath transaction in the current group |
+| `gaid t` | ID of the asset or application created in the Tth transaction of the current group |
+| `gaids` | ID of the asset or application created in the Ath transaction of the current group |
**Transaction Fields**
| Index | Name | Type | In | Notes |
| - | ------ | -- | - | --------- |
| 0 | Sender | []byte | | 32 byte address |
-| 1 | Fee | uint64 | | micro-Algos |
+| 1 | Fee | uint64 | | microalgos |
| 2 | FirstValid | uint64 | | round number |
| 3 | FirstValidTime | uint64 | | Causes program to fail; reserved for future use |
| 4 | LastValid | uint64 | | round number |
| 5 | Note | []byte | | Any data up to 1024 bytes |
| 6 | Lease | []byte | | 32 byte lease value |
| 7 | Receiver | []byte | | 32 byte address |
-| 8 | Amount | uint64 | | micro-Algos |
+| 8 | Amount | uint64 | | microalgos |
| 9 | CloseRemainderTo | []byte | | 32 byte address |
| 10 | VotePK | []byte | | 32 byte address |
| 11 | SelectionPK | []byte | | 32 byte address |
@@ -418,8 +419,8 @@ Global fields are fields that are common to all the transactions in the group. I
| Index | Name | Type | In | Notes |
| - | ------ | -- | - | --------- |
-| 0 | MinTxnFee | uint64 | | micro Algos |
-| 1 | MinBalance | uint64 | | micro Algos |
+| 0 | MinTxnFee | uint64 | | microalgos |
+| 1 | MinBalance | uint64 | | microalgos |
| 2 | MaxTxnLife | uint64 | | rounds |
| 3 | ZeroAddress | []byte | | 32 byte address of all zero bytes |
| 4 | GroupSize | uint64 | | Number of transactions in this atomic transaction group. At least 1 |
@@ -478,6 +479,17 @@ App fields used in the `app_params_get` opcode.
| 8 | AppAddress | []byte | Address for which this application has authority |
+**Account Fields**
+
+Account fields used in the `acct_params_get` opcode.
+
+| Index | Name | Type | Notes |
+| - | ------ | -- | --------- |
+| 0 | AcctBalance | uint64 | Account balance in microalgos |
+| 1 | AcctMinBalance | uint64 | Minimum required blance for account, in microalgos |
+| 2 | AcctAuthAddr | []byte | Address the account is rekeyed to. |
+
+
### Flow Control
| Opcode | Description |
@@ -486,16 +498,16 @@ App fields used in the `app_params_get` opcode.
| `bnz target` | branch to TARGET if value A is not zero |
| `bz target` | branch to TARGET if value A is zero |
| `b target` | branch unconditionally to TARGET |
-| `return` | use last value on stack as success value; end |
-| `pop` | discard value A from stack |
-| `dup` | duplicate last value on stack |
-| `dup2` | duplicate two last values on stack |
-| `dig n` | push the Nth value from the top of the stack. dig 0 is equivalent to dup |
+| `return` | use A as success value; end |
+| `pop` | discard A |
+| `dup` | duplicate A |
+| `dup2` | duplicate A and B |
+| `dig n` | Nth value from the top of the stack. dig 0 is equivalent to dup |
| `cover n` | remove top of stack, and place it deeper in the stack such that N elements are above it. Fails if stack depth <= N. |
| `uncover n` | remove the value at depth N in the stack and shift above items down so the Nth deep value is on top of the stack. Fails if stack depth <= N. |
-| `swap` | swaps two last values on stack |
+| `swap` | swaps A and B on stack |
| `select` | selects one of two values based on top-of-stack: B if C != 0, else A |
-| `assert` | immediately fail unless value X is a non-zero number |
+| `assert` | immediately fail unless X is a non-zero number |
| `callsub target` | branch unconditionally to TARGET, saving the next instruction on the call stack |
| `retsub` | pop the top instruction from the call stack and branch to it |
@@ -505,19 +517,20 @@ App fields used in the `app_params_get` opcode.
| - | -- |
| `balance` | get balance for account A, in microalgos. The balance is observed after the effects of previous transactions in the group, and after the fee for the current transaction is deducted. |
| `min_balance` | get minimum required balance for account A, in microalgos. Required balance is affected by [ASA](https://developer.algorand.org/docs/features/asa/#assets-overview) and [App](https://developer.algorand.org/docs/features/asc1/stateful/#minimum-balance-requirement-for-a-smart-contract) usage. When creating or opting into an app, the minimum balance grows before the app code runs, therefore the increase is visible there. When deleting or closing out, the minimum balance decreases after the app executes. |
-| `app_opted_in` | check if account A opted in for the application B => {0 or 1} |
-| `app_local_get` | read from account A from local state of the current application key B => value |
-| `app_local_get_ex` | read from account A from local state of the application B key C => [*... stack*, value, 0 or 1] |
-| `app_global_get` | read key A from global state of a current application => value |
-| `app_global_get_ex` | read from application A global state key B => [*... stack*, value, 0 or 1] |
-| `app_local_put` | write to account specified by A to local state of a current application key B with value C |
-| `app_global_put` | write key A and value B to global state of the current application |
-| `app_local_del` | delete from account A local state key B of the current application |
-| `app_global_del` | delete key A from a global state of the current application |
-| `asset_holding_get i` | read from account A and asset B holding field X (imm arg) => {0 or 1 (top), value} |
-| `asset_params_get i` | read from asset A params field X (imm arg) => {0 or 1 (top), value} |
-| `app_params_get i` | read from app A params field X (imm arg) => {0 or 1 (top), value} |
-| `log` | write bytes to log state of the current application |
+| `app_opted_in` | 1 if account A is opted in to application B, else 0 |
+| `app_local_get` | local state of the key B in the current application in account A |
+| `app_local_get_ex` | X is the local state of application B, key C in account A. Y is 1 if key existed, else 0 |
+| `app_global_get` | global state of the key A in the current application |
+| `app_global_get_ex` | X is the global state of application A, key B. Y is 1 if key existed, else 0 |
+| `app_local_put` | write C to key B in account A's local state of the current application |
+| `app_global_put` | write B to key A in the global state of the current application |
+| `app_local_del` | delete key B from account A's local state of the current application |
+| `app_global_del` | delete key A from the global state of the current application |
+| `asset_holding_get f` | X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0 |
+| `asset_params_get f` | X is field F from asset A. Y is 1 if A exists, else 0 |
+| `app_params_get f` | X is field F from app A. Y is 1 if A exists, else 0 |
+| `acct_params_get f` | X is field F from account A. Y is 1 if A owns positive algos, else 0 |
+| `log` | write A to log state of the current application |
### Inner Transactions
@@ -541,11 +554,11 @@ with the next instruction with, for example, `balance` and
In v5, only a few of the Header fields may be set: `Type`/`TypeEnum`,
`Sender`, and `Fee`. In v6, Header fields `Note` and `RekeyTo` may
-also be set. For the specific fields of each transaction types, any
-field may be set (except `RekeyTo` in v5). This allows, for example,
-clawback transactions, asset opt-ins, and asset creates in addition to
-the more common uses of `axfer` and `acfg`. All fields default to the
-zero value, except those described under `itxn_begin`.
+also be set. For the specific (non-header) fields of each transaction
+type, any field may be set. This allows, for example, clawback
+transactions, asset opt-ins, and asset creates in addition to the more
+common uses of `axfer` and `acfg`. All fields default to the zero
+value, except those described under `itxn_begin`.
Fields may be set multiple times, but may not be read. The most recent
setting is used when `itxn_submit` executes. For this purpose `Type`
@@ -567,10 +580,10 @@ different transaction types, are rejected by `itxn_submit`.
| `itxn_next` | begin preparation of a new inner transaction in the same transaction group |
| `itxn_field f` | set field F of the current inner transaction to A |
| `itxn_submit` | execute the current inner transaction group. Fail if executing this group would exceed the inner transaction limit, or if any transaction in the group fails. |
-| `itxn f` | push field F of the last inner transaction |
-| `itxna f i` | push Ith value of the array field F of the last inner transaction |
-| `gitxn t f` | push field F of the Tth transaction in the last inner group submitted |
-| `gitxna t f i` | push Ith value of the array field F from the Tth transaction in the last inner group submitted |
+| `itxn f` | field F of the last inner transaction |
+| `itxna f i` | Ith value of the array field F of the last inner transaction |
+| `gitxn t f` | field F of the Tth transaction in the last inner group submitted |
+| `gitxna t f i` | Ith value of the array field F from the Tth transaction in the last inner group submitted |
# Assembler Syntax
diff --git a/data/transactions/logic/README_in.md b/data/transactions/logic/README_in.md
index 80bdf4b44..4b3ef750e 100644
--- a/data/transactions/logic/README_in.md
+++ b/data/transactions/logic/README_in.md
@@ -234,6 +234,12 @@ App fields used in the `app_params_get` opcode.
@@ app_params_fields.md @@
+**Account Fields**
+
+Account fields used in the `acct_params_get` opcode.
+
+@@ acct_params_fields.md @@
+
### Flow Control
@@ Flow_Control.md @@
@@ -264,11 +270,11 @@ with the next instruction with, for example, `balance` and
In v5, only a few of the Header fields may be set: `Type`/`TypeEnum`,
`Sender`, and `Fee`. In v6, Header fields `Note` and `RekeyTo` may
-also be set. For the specific fields of each transaction types, any
-field may be set (except `RekeyTo` in v5). This allows, for example,
-clawback transactions, asset opt-ins, and asset creates in addition to
-the more common uses of `axfer` and `acfg`. All fields default to the
-zero value, except those described under `itxn_begin`.
+also be set. For the specific (non-header) fields of each transaction
+type, any field may be set. This allows, for example, clawback
+transactions, asset opt-ins, and asset creates in addition to the more
+common uses of `axfer` and `acfg`. All fields default to the zero
+value, except those described under `itxn_begin`.
Fields may be set multiple times, but may not be read. The most recent
setting is used when `itxn_submit` executes. For this purpose `Type`
diff --git a/data/transactions/logic/TEAL_opcodes.md b/data/transactions/logic/TEAL_opcodes.md
index 7a4d94ca1..3a85afc72 100644
--- a/data/transactions/logic/TEAL_opcodes.md
+++ b/data/transactions/logic/TEAL_opcodes.md
@@ -247,10 +247,12 @@ Overflow is an error condition which halts execution and fails the transaction.
- Opcode: 0x1f
- Stack: ..., A: uint64, B: uint64, C: uint64, D: uint64 &rarr; ..., W: uint64, X: uint64, Y: uint64, Z: uint64
-- Pop four uint64 values. A and B are interpreted as a uint128 dividend (A is the high word), C and D are interpreted as a uint128 divisor (C is the high word). Four uint64 values are pushed to the stack. The W and X are the quotient (W is the high uint64). Y and Z are the remainder, Y is the high bits.
+- W,X = (A,B / C,D); Y,Z = (A,B modulo C,D)
- **Cost**: 20
- Availability: v4
+The notation J,K indicates that two uint64 values J and K are interpreted as a uint128 value, with J as the high uint64 and K the low.
+
## intcblock uint ...
- Opcode: 0x20 {varuint length} [{varuint value}, ...]
@@ -263,31 +265,31 @@ Overflow is an error condition which halts execution and fails the transaction.
- Opcode: 0x21 {uint8 int constant index}
- Stack: ... &rarr; ..., uint64
-- push Ith constant from intcblock to stack
+- Ith constant from intcblock
## intc_0
- Opcode: 0x22
- Stack: ... &rarr; ..., uint64
-- push constant 0 from intcblock to stack
+- constant 0 from intcblock
## intc_1
- Opcode: 0x23
- Stack: ... &rarr; ..., uint64
-- push constant 1 from intcblock to stack
+- constant 1 from intcblock
## intc_2
- Opcode: 0x24
- Stack: ... &rarr; ..., uint64
-- push constant 2 from intcblock to stack
+- constant 2 from intcblock
## intc_3
- Opcode: 0x25
- Stack: ... &rarr; ..., uint64
-- push constant 3 from intcblock to stack
+- constant 3 from intcblock
## bytecblock bytes ...
@@ -301,86 +303,86 @@ Overflow is an error condition which halts execution and fails the transaction.
- Opcode: 0x27 {uint8 byte constant index}
- Stack: ... &rarr; ..., []byte
-- push Ith constant from bytecblock to stack
+- Ith constant from bytecblock
## bytec_0
- Opcode: 0x28
- Stack: ... &rarr; ..., []byte
-- push constant 0 from bytecblock to stack
+- constant 0 from bytecblock
## bytec_1
- Opcode: 0x29
- Stack: ... &rarr; ..., []byte
-- push constant 1 from bytecblock to stack
+- constant 1 from bytecblock
## bytec_2
- Opcode: 0x2a
- Stack: ... &rarr; ..., []byte
-- push constant 2 from bytecblock to stack
+- constant 2 from bytecblock
## bytec_3
- Opcode: 0x2b
- Stack: ... &rarr; ..., []byte
-- push constant 3 from bytecblock to stack
+- constant 3 from bytecblock
## arg n
- Opcode: 0x2c {uint8 arg index N}
- Stack: ... &rarr; ..., []byte
-- push Nth LogicSig argument to stack
+- Nth LogicSig argument
- Mode: Signature
## arg_0
- Opcode: 0x2d
- Stack: ... &rarr; ..., []byte
-- push LogicSig argument 0 to stack
+- LogicSig argument 0
- Mode: Signature
## arg_1
- Opcode: 0x2e
- Stack: ... &rarr; ..., []byte
-- push LogicSig argument 1 to stack
+- LogicSig argument 1
- Mode: Signature
## arg_2
- Opcode: 0x2f
- Stack: ... &rarr; ..., []byte
-- push LogicSig argument 2 to stack
+- LogicSig argument 2
- Mode: Signature
## arg_3
- Opcode: 0x30
- Stack: ... &rarr; ..., []byte
-- push LogicSig argument 3 to stack
+- LogicSig argument 3
- Mode: Signature
## txn f
- Opcode: 0x31 {uint8 transaction field index}
- Stack: ... &rarr; ..., any
-- push field F of current transaction to stack
+- field F of current transaction
`txn` Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/)):
| Index | Name | Type | In | Notes |
| - | ------ | -- | - | --------- |
| 0 | Sender | []byte | | 32 byte address |
-| 1 | Fee | uint64 | | micro-Algos |
+| 1 | Fee | uint64 | | microalgos |
| 2 | FirstValid | uint64 | | round number |
| 3 | FirstValidTime | uint64 | | Causes program to fail; reserved for future use |
| 4 | LastValid | uint64 | | round number |
| 5 | Note | []byte | | Any data up to 1024 bytes |
| 6 | Lease | []byte | | 32 byte lease value |
| 7 | Receiver | []byte | | 32 byte address |
-| 8 | Amount | uint64 | | micro-Algos |
+| 8 | Amount | uint64 | | microalgos |
| 9 | CloseRemainderTo | []byte | | 32 byte address |
| 10 | VotePK | []byte | | 32 byte address |
| 11 | SelectionPK | []byte | | 32 byte address |
@@ -455,14 +457,14 @@ FirstValidTime causes the program to fail. The field is reserved for future use.
- Opcode: 0x32 {uint8 global field index}
- Stack: ... &rarr; ..., any
-- push value from globals to stack
+- global field F
`global` Fields:
| Index | Name | Type | In | Notes |
| - | ------ | -- | - | --------- |
-| 0 | MinTxnFee | uint64 | | micro Algos |
-| 1 | MinBalance | uint64 | | micro Algos |
+| 0 | MinTxnFee | uint64 | | microalgos |
+| 1 | MinBalance | uint64 | | microalgos |
| 2 | MaxTxnLife | uint64 | | rounds |
| 3 | ZeroAddress | []byte | | 32 byte address of all zero bytes |
| 4 | GroupSize | uint64 | | Number of transactions in this atomic transaction group. At least 1 |
@@ -482,7 +484,7 @@ FirstValidTime causes the program to fail. The field is reserved for future use.
- Opcode: 0x33 {uint8 transaction group index} {uint8 transaction field index}
- Stack: ... &rarr; ..., any
-- push field F of the Tth transaction in the current group
+- field F of the Tth transaction in the current group
for notes on transaction fields available, see `txn`. If this transaction is _i_ in the group, `gtxn i field` is equivalent to `txn field`.
@@ -490,33 +492,33 @@ for notes on transaction fields available, see `txn`. If this transaction is _i_
- Opcode: 0x34 {uint8 position in scratch space to load from}
- Stack: ... &rarr; ..., any
-- copy a value from scratch space to the stack. All scratch spaces are 0 at program start.
+- Ith scratch space value. All scratch spaces are 0 at program start.
## store i
- Opcode: 0x35 {uint8 position in scratch space to store to}
- Stack: ..., A &rarr; ...
-- pop value A. store A to the Ith scratch space
+- store A to the Ith scratch space
## txna f i
- Opcode: 0x36 {uint8 transaction field index} {uint8 transaction field array index}
- Stack: ... &rarr; ..., any
-- push Ith value of the array field F of the current transaction
+- Ith value of the array field F of the current transaction
- Availability: v2
## gtxna t f i
- Opcode: 0x37 {uint8 transaction group index} {uint8 transaction field index} {uint8 transaction field array index}
- Stack: ... &rarr; ..., any
-- push Ith value of the array field F from the Tth transaction in the current group
+- Ith value of the array field F from the Tth transaction in the current group
- Availability: v2
## gtxns f
- Opcode: 0x38 {uint8 transaction field index}
- Stack: ..., A: uint64 &rarr; ..., any
-- push field F of the Ath transaction in the current group
+- field F of the Ath transaction in the current group
- Availability: v3
for notes on transaction fields available, see `txn`. If top of stack is _i_, `gtxns field` is equivalent to `gtxn _i_ field`. gtxns exists so that _i_ can be calculated, often based on the index of the current transaction.
@@ -525,14 +527,14 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
- Opcode: 0x39 {uint8 transaction field index} {uint8 transaction field array index}
- Stack: ..., A: uint64 &rarr; ..., any
-- push Ith value of the array field F from the Ath transaction in the current group
+- Ith value of the array field F from the Ath transaction in the current group
- Availability: v3
## gload t i
- Opcode: 0x3a {uint8 transaction group index} {uint8 position in scratch space to load from}
- Stack: ... &rarr; ..., any
-- push Ith scratch space index of the Tth transaction in the current group
+- Ith scratch space value of the Tth transaction in the current group
- Availability: v4
- Mode: Application
@@ -542,7 +544,7 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
- Opcode: 0x3b {uint8 position in scratch space to load from}
- Stack: ..., A: uint64 &rarr; ..., any
-- push Ith scratch space index of the Ath transaction in the current group
+- Ith scratch space value of the Ath transaction in the current group
- Availability: v4
- Mode: Application
@@ -552,7 +554,7 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
- Opcode: 0x3c {uint8 transaction group index}
- Stack: ... &rarr; ..., uint64
-- push the ID of the asset or application created in the Tth transaction of the current group
+- ID of the asset or application created in the Tth transaction of the current group
- Availability: v4
- Mode: Application
@@ -562,7 +564,7 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
- Opcode: 0x3d
- Stack: ..., A: uint64 &rarr; ..., uint64
-- push the ID of the asset or application created in the Ath transaction of the current group
+- ID of the asset or application created in the Ath transaction of the current group
- Availability: v4
- Mode: Application
@@ -572,14 +574,14 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
- Opcode: 0x3e
- Stack: ..., A: uint64 &rarr; ..., any
-- copy a value from the Ath scratch space to the stack. All scratch spaces are 0 at program start.
+- Ath scratch space value. All scratch spaces are 0 at program start.
- Availability: v5
## stores
- Opcode: 0x3f
- Stack: ..., A: uint64, B &rarr; ...
-- pop indexes A and B. store B to the Ath scratch space
+- store B to the Ath scratch space
- Availability: v5
## bnz target
@@ -614,47 +616,47 @@ See `bnz` for details on how branches work. `b` always jumps to the offset.
- Opcode: 0x43
- Stack: ..., A: uint64 &rarr; ...
-- use last value on stack as success value; end
+- use A as success value; end
- Availability: v2
## assert
- Opcode: 0x44
- Stack: ..., A: uint64 &rarr; ...
-- immediately fail unless value X is a non-zero number
+- immediately fail unless X is a non-zero number
- Availability: v3
## pop
- Opcode: 0x48
- Stack: ..., A &rarr; ...
-- discard value A from stack
+- discard A
## dup
- Opcode: 0x49
- Stack: ..., A &rarr; ..., A, A
-- duplicate last value on stack
+- duplicate A
## dup2
- Opcode: 0x4a
- Stack: ..., A, B &rarr; ..., A, B, A, B
-- duplicate two last values on stack
+- duplicate A and B
- Availability: v2
## dig n
- Opcode: 0x4b {uint8 depth}
- Stack: ..., A, [N items] &rarr; ..., A, [N items], A
-- push the Nth value from the top of the stack. dig 0 is equivalent to dup
+- Nth value from the top of the stack. dig 0 is equivalent to dup
- Availability: v3
## swap
- Opcode: 0x4c
- Stack: ..., A, B &rarr; ..., B, A
-- swaps two last values on stack
+- swaps A and B on stack
- Availability: v3
## select
@@ -682,7 +684,7 @@ See `bnz` for details on how branches work. `b` always jumps to the offset.
- Opcode: 0x50
- Stack: ..., A: []byte, B: []byte &rarr; ..., []byte
-- pop two byte-arrays A and B and join them, push the result
+- join A and B
- Availability: v2
`concat` fails if the result would be greater than 4096 bytes.
@@ -691,21 +693,21 @@ See `bnz` for details on how branches work. `b` always jumps to the offset.
- Opcode: 0x51 {uint8 start position} {uint8 end position}
- Stack: ..., A: []byte &rarr; ..., []byte
-- pop a byte-array A. For immediate values in 0..255 S and E: extract a range of bytes from A starting at S up to but not including E, push the substring result. If E < S, or either is larger than the array length, the program fails
+- 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
- Availability: v2
## substring3
- Opcode: 0x52
- Stack: ..., A: []byte, B: uint64, C: uint64 &rarr; ..., []byte
-- pop a byte-array A and two integers B and C. Extract a range of bytes from A starting at B up to but not including C, push the substring result. If C < B, or either is larger than the array length, the program fails
+- 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
- Availability: v2
## getbit
- Opcode: 0x53
- Stack: ..., A, B: uint64 &rarr; ..., uint64
-- pop a target A (integer or byte-array), and index B. Push the Bth bit of A.
+- Bth bit of (byte-array or integer) A.
- Availability: v3
see explanation of bit ordering in setbit
@@ -714,7 +716,7 @@ see explanation of bit ordering in setbit
- Opcode: 0x54
- Stack: ..., A, B: uint64, C: uint64 &rarr; ..., any
-- pop a target A, index B, and bit C. Set the Bth bit of A to C, and push the result
+- Copy of (byte-array or integer) A, with the Bth bit set to (0 or 1) C
- Availability: v3
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.
@@ -723,56 +725,56 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Opcode: 0x55
- Stack: ..., A: []byte, B: uint64 &rarr; ..., uint64
-- pop a byte-array A and integer B. Extract the Bth byte of A and push it as an integer
+- Bth byte of A, as an integer
- Availability: v3
## setbyte
- Opcode: 0x56
- Stack: ..., A: []byte, B: uint64, C: uint64 &rarr; ..., []byte
-- pop a byte-array A, integer B, and small integer C (between 0..255). Set the Bth byte of A to C, and push the result
+- Copy of A with the Bth byte set to small integer (between 0..255) C
- Availability: v3
## extract s l
- Opcode: 0x57 {uint8 start position} {uint8 length}
- Stack: ..., A: []byte &rarr; ..., []byte
-- pop a byte-array A. For immediate values in 0..255 S and L: extract a range of bytes from A starting at S up to but not including S+L, push the substring result. 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
+- 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
- Availability: v5
## extract3
- Opcode: 0x58
- Stack: ..., A: []byte, B: uint64, C: uint64 &rarr; ..., []byte
-- pop a byte-array A and two integers B and C. Extract a range of bytes from A starting at B up to but not including B+C, push the substring result. If B+C is larger than the array length, the program fails
+- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails
- Availability: v5
## extract_uint16
- Opcode: 0x59
- Stack: ..., A: []byte, B: uint64 &rarr; ..., uint64
-- pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+2, convert bytes as big endian and push the uint64 result. If B+2 is larger than the array length, the program fails
+- A uint16 formed from a range of big-endian bytes from A starting at B up to but not including B+2. If B+2 is larger than the array length, the program fails
- Availability: v5
## extract_uint32
- Opcode: 0x5a
- Stack: ..., A: []byte, B: uint64 &rarr; ..., uint64
-- pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+4, convert bytes as big endian and push the uint64 result. If B+4 is larger than the array length, the program fails
+- A uint32 formed from a range of big-endian bytes from A starting at B up to but not including B+4. If B+4 is larger than the array length, the program fails
- Availability: v5
## extract_uint64
- Opcode: 0x5b
- Stack: ..., A: []byte, B: uint64 &rarr; ..., uint64
-- pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+8, convert bytes as big endian and push the uint64 result. If B+8 is larger than the array length, the program fails
+- A uint64 formed from a range of big-endian bytes from A starting at B up to but not including B+8. If B+8 is larger than the array length, the program fails
- Availability: v5
## base64_decode e
- Opcode: 0x5c {uint8 encoding index}
- Stack: ..., A: []byte &rarr; ..., []byte
-- decode A which was base64-encoded using _encoding_ E. Fail if X is not base64 encoded with encoding E
+- decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E
- **Cost**: 25
- Availability: v6
@@ -792,7 +794,7 @@ params: Txn.Accounts offset (or, since v4, an _available_ account address), _ava
- Opcode: 0x61
- Stack: ..., A, B: uint64 &rarr; ..., uint64
-- check if account A opted in for the application B => {0 or 1}
+- 1 if account A is opted in to application B, else 0
- Availability: v2
- Mode: Application
@@ -802,7 +804,7 @@ params: Txn.Accounts offset (or, since v4, an _available_ account address), _ava
- Opcode: 0x62
- Stack: ..., A, B: []byte &rarr; ..., any
-- read from account A from local state of the current application key B => value
+- local state of the key B in the current application in account A
- Availability: v2
- Mode: Application
@@ -812,7 +814,7 @@ params: Txn.Accounts offset (or, since v4, an _available_ account address), stat
- Opcode: 0x63
- Stack: ..., A, B: uint64, C: []byte &rarr; ..., X: any, Y: uint64
-- read from account A from local state of the application B key C => [*... stack*, value, 0 or 1]
+- X is the local state of application B, key C in account A. Y is 1 if key existed, else 0
- Availability: v2
- Mode: Application
@@ -822,7 +824,7 @@ params: Txn.Accounts offset (or, since v4, an _available_ account address), _ava
- Opcode: 0x64
- Stack: ..., A: []byte &rarr; ..., any
-- read key A from global state of a current application => value
+- global state of the key A in the current application
- Availability: v2
- Mode: Application
@@ -832,7 +834,7 @@ params: state key. Return: value. The value is zero (of type uint64) if the key
- Opcode: 0x65
- Stack: ..., A: uint64, B: []byte &rarr; ..., X: any, Y: uint64
-- read from application A global state key B => [*... stack*, value, 0 or 1]
+- X is the global state of application A, key B. Y is 1 if key existed, else 0
- Availability: v2
- Mode: Application
@@ -842,7 +844,7 @@ params: Txn.ForeignApps offset (or, since v4, an _available_ application id), st
- Opcode: 0x66
- Stack: ..., A, B: []byte, C &rarr; ...
-- write to account specified by A to local state of a current application key B with value C
+- write C to key B in account A's local state of the current application
- Availability: v2
- Mode: Application
@@ -852,7 +854,7 @@ params: Txn.Accounts offset (or, since v4, an _available_ account address), stat
- Opcode: 0x67
- Stack: ..., A: []byte, B &rarr; ...
-- write key A and value B to global state of the current application
+- write B to key A in the global state of the current application
- Availability: v2
- Mode: Application
@@ -860,7 +862,7 @@ params: Txn.Accounts offset (or, since v4, an _available_ account address), stat
- Opcode: 0x68
- Stack: ..., A, B: []byte &rarr; ...
-- delete from account A local state key B of the current application
+- delete key B from account A's local state of the current application
- Availability: v2
- Mode: Application
@@ -872,7 +874,7 @@ Deleting a key which is already absent has no effect on the application local st
- Opcode: 0x69
- Stack: ..., A: []byte &rarr; ...
-- delete key A from a global state of the current application
+- delete key A from the global state of the current application
- Availability: v2
- Mode: Application
@@ -880,11 +882,11 @@ params: state key.
Deleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)
-## asset_holding_get i
+## asset_holding_get f
- Opcode: 0x70 {uint8 asset holding field index}
- Stack: ..., A, B: uint64 &rarr; ..., X: any, Y: uint64
-- read from account A and asset B holding field X (imm arg) => {0 or 1 (top), value}
+- X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0
- Availability: v2
- Mode: Application
@@ -898,11 +900,11 @@ Deleting a key which is already absent has no effect on the application global s
params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
-## asset_params_get i
+## asset_params_get f
- Opcode: 0x71 {uint8 asset params field index}
- Stack: ..., A: uint64 &rarr; ..., X: any, Y: uint64
-- read from asset A params field X (imm arg) => {0 or 1 (top), value}
+- X is field F from asset A. Y is 1 if A exists, else 0
- Availability: v2
- Mode: Application
@@ -926,11 +928,11 @@ params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or
params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
-## app_params_get i
+## app_params_get f
- Opcode: 0x72 {uint8 app params field index}
- Stack: ..., A: uint64 &rarr; ..., X: any, Y: uint64
-- read from app A params field X (imm arg) => {0 or 1 (top), value}
+- X is field F from app A. Y is 1 if A exists, else 0
- Availability: v5
- Mode: Application
@@ -951,6 +953,14 @@ params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return:
params: Txn.ForeignApps offset or an _available_ app id. Return: did_exist flag (1 if the application existed and 0 otherwise), value.
+## acct_params_get f
+
+- Opcode: 0x73 {uint8 account params field index}
+- Stack: ..., A: uint64 &rarr; ..., X: any, Y: uint64
+- X is field F from account A. Y is 1 if A owns positive algos, else 0
+- Availability: v6
+- Mode: Application
+
## min_balance
- Opcode: 0x78
@@ -965,7 +975,7 @@ params: Txn.Accounts offset (or, since v4, an _available_ account address), _ava
- Opcode: 0x80 {varuint length} {bytes}
- Stack: ... &rarr; ..., []byte
-- push the following program bytes to the stack
+- immediate BYTES
- Availability: v3
pushbytes args are not added to the bytecblock during assembly processes
@@ -974,7 +984,7 @@ pushbytes args are not added to the bytecblock during assembly processes
- Opcode: 0x81 {varuint int}
- Stack: ... &rarr; ..., uint64
-- push immediate UINT to the stack as an integer
+- immediate UINT
- Availability: v3
pushint args are not added to the intcblock during assembly processes
@@ -1015,7 +1025,7 @@ The call stack is separate from the data stack. Only `callsub` and `retsub` mani
- Opcode: 0x92
- Stack: ..., A: uint64 &rarr; ..., uint64
-- The largest integer B such that B^2 <= A
+- The largest integer I such that I^2 <= A
- **Cost**: 4
- Availability: v4
@@ -1043,11 +1053,19 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- **Cost**: 10
- Availability: v4
+## bsqrt
+
+- Opcode: 0x96
+- Stack: ..., A: []byte &rarr; ..., []byte
+- The largest integer I such that I^2 <= A. A and I are interpreted as big-endian unsigned integers
+- **Cost**: 40
+- Availability: v6
+
## b+
- Opcode: 0xa0
- Stack: ..., A: []byte, B: []byte &rarr; ..., []byte
-- A plus B, where A and B are byte-arrays interpreted as big-endian unsigned integers
+- A plus B. A and B are interpreted as big-endian unsigned integers
- **Cost**: 10
- Availability: v4
@@ -1055,7 +1073,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xa1
- Stack: ..., A: []byte, B: []byte &rarr; ..., []byte
-- A minus B, where A and B are byte-arrays interpreted as big-endian unsigned integers. Fail on underflow.
+- A minus B. A and B are interpreted as big-endian unsigned integers. Fail on underflow.
- **Cost**: 10
- Availability: v4
@@ -1063,7 +1081,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xa2
- Stack: ..., A: []byte, B: []byte &rarr; ..., []byte
-- A divided by B (truncated division), where A and B are byte-arrays interpreted as big-endian unsigned integers. Fail if B is zero.
+- A divided by B (truncated division). A and B are interpreted as big-endian unsigned integers. Fail if B is zero.
- **Cost**: 20
- Availability: v4
@@ -1071,7 +1089,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xa3
- Stack: ..., A: []byte, B: []byte &rarr; ..., []byte
-- A times B, where A and B are byte-arrays interpreted as big-endian unsigned integers.
+- A times B. A and B are interpreted as big-endian unsigned integers.
- **Cost**: 20
- Availability: v4
@@ -1079,49 +1097,49 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xa4
- Stack: ..., A: []byte, B: []byte &rarr; ..., uint64
-- A is less than B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}
+- 1 if A is less than B, else 0. A and B are interpreted as big-endian unsigned integers
- Availability: v4
## b>
- Opcode: 0xa5
- Stack: ..., A: []byte, B: []byte &rarr; ..., uint64
-- A is greater than B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}
+- 1 if A is greater than B, else 0. A and B are interpreted as big-endian unsigned integers
- Availability: v4
## b<=
- Opcode: 0xa6
- Stack: ..., A: []byte, B: []byte &rarr; ..., uint64
-- A is less than or equal to B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}
+- 1 if A is less than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers
- Availability: v4
## b>=
- Opcode: 0xa7
- Stack: ..., A: []byte, B: []byte &rarr; ..., uint64
-- A is greater than or equal to B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}
+- 1 if A is greater than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers
- Availability: v4
## b==
- Opcode: 0xa8
- Stack: ..., A: []byte, B: []byte &rarr; ..., uint64
-- A is equals to B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}
+- 1 if A is equal to B, else 0. A and B are interpreted as big-endian unsigned integers
- Availability: v4
## b!=
- Opcode: 0xa9
- Stack: ..., A: []byte, B: []byte &rarr; ..., uint64
-- A is not equal to B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}
+- 0 if A is equal to B, else 1. A and B are interpreted as big-endian unsigned integers
- Availability: v4
## b%
- Opcode: 0xaa
- Stack: ..., A: []byte, B: []byte &rarr; ..., []byte
-- A modulo B, where A and B are byte-arrays interpreted as big-endian unsigned integers. Fail if B is zero.
+- A modulo B. A and B are interpreted as big-endian unsigned integers. Fail if B is zero.
- **Cost**: 20
- Availability: v4
@@ -1129,7 +1147,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xab
- Stack: ..., A: []byte, B: []byte &rarr; ..., []byte
-- A bitwise-or B, where A and B are byte-arrays, zero-left extended to the greater of their lengths
+- A bitwise-or B. A and B are zero-left extended to the greater of their lengths
- **Cost**: 6
- Availability: v4
@@ -1137,7 +1155,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xac
- Stack: ..., A: []byte, B: []byte &rarr; ..., []byte
-- A bitwise-and B, where A and B are byte-arrays, zero-left extended to the greater of their lengths
+- A bitwise-and B. A and B are zero-left extended to the greater of their lengths
- **Cost**: 6
- Availability: v4
@@ -1145,7 +1163,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xad
- Stack: ..., A: []byte, B: []byte &rarr; ..., []byte
-- A bitwise-xor B, where A and B are byte-arrays, zero-left extended to the greater of their lengths
+- A bitwise-xor B. A and B are zero-left extended to the greater of their lengths
- **Cost**: 6
- Availability: v4
@@ -1161,14 +1179,14 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xaf
- Stack: ..., A: uint64 &rarr; ..., []byte
-- push a byte-array of length A, containing all zero bytes
+- zero filled byte-array of length A
- Availability: v4
## log
- Opcode: 0xb0
- Stack: ..., A: []byte &rarr; ...
-- write bytes to log state of the current application
+- write A to log state of the current application
- Availability: v5
- Mode: Application
@@ -1192,7 +1210,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Availability: v5
- Mode: Application
-`itxn_field` fails if A is of the wrong type for F, including a byte array of the wrong size for use as an address when F is an address field. `itxn_field` also fails if A is an account, asset, or app that is not _available_. (Setting addresses in asset creation transactions need not be _available_.)
+`itxn_field` fails if A is of the wrong type for F, including a byte array of the wrong size for use as an address when F is an address field. `itxn_field` also fails if A is an account, asset, or app that is not _available_. (Addresses set into asset params of acfg transactions need not be _available_.)
## itxn_submit
@@ -1208,7 +1226,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xb4 {uint8 transaction field index}
- Stack: ... &rarr; ..., any
-- push field F of the last inner transaction
+- field F of the last inner transaction
- Availability: v5
- Mode: Application
@@ -1216,7 +1234,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xb5 {uint8 transaction field index} {uint8 transaction field array index}
- Stack: ... &rarr; ..., any
-- push Ith value of the array field F of the last inner transaction
+- Ith value of the array field F of the last inner transaction
- Availability: v5
- Mode: Application
@@ -1234,7 +1252,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xb7 {uint8 transaction group index} {uint8 transaction field index}
- Stack: ... &rarr; ..., any
-- push field F of the Tth transaction in the last inner group submitted
+- field F of the Tth transaction in the last inner group submitted
- Availability: v6
- Mode: Application
@@ -1242,7 +1260,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xb8 {uint8 transaction group index} {uint8 transaction field index} {uint8 transaction field array index}
- Stack: ... &rarr; ..., any
-- push Ith value of the array field F from the Tth transaction in the last inner group submitted
+- Ith value of the array field F from the Tth transaction in the last inner group submitted
- Availability: v6
- Mode: Application
@@ -1250,28 +1268,28 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xc0 {uint8 transaction field index}
- Stack: ..., A: uint64 &rarr; ..., any
-- push Ath value of the array field F of the current transaction
+- Ath value of the array field F of the current transaction
- Availability: v5
## gtxnas t f
- Opcode: 0xc1 {uint8 transaction group index} {uint8 transaction field index}
- Stack: ..., A: uint64 &rarr; ..., any
-- push Ath value of the array field F from the Tth transaction in the current group
+- Ath value of the array field F from the Tth transaction in the current group
- Availability: v5
## gtxnsas f
- Opcode: 0xc2 {uint8 transaction field index}
- Stack: ..., A: uint64, B: uint64 &rarr; ..., any
-- pop an index A and an index B. push Bth value of the array field F from the Ath transaction in the current group
+- Bth value of the array field F from the Ath transaction in the current group
- Availability: v5
## args
- Opcode: 0xc3
- Stack: ..., A: uint64 &rarr; ..., []byte
-- push Ath LogicSig argument to stack
+- Ath LogicSig argument
- Availability: v5
- Mode: Signature
@@ -1279,6 +1297,6 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
- Opcode: 0xc4
- Stack: ..., A: uint64, B: uint64 &rarr; ..., any
-- push Bth scratch space index of the Ath transaction in the current group
+- Bth scratch space value of the Ath transaction in the current group
- Availability: v6
- Mode: Application
diff --git a/data/transactions/logic/assembler.go b/data/transactions/logic/assembler.go
index f14d621d5..cdf91df68 100644
--- a/data/transactions/logic/assembler.go
+++ b/data/transactions/logic/assembler.go
@@ -1117,7 +1117,7 @@ func assembleGlobal(ops *OpStream, spec *OpSpec, args []string) error {
val := fs.field
ops.pending.WriteByte(spec.Opcode)
ops.pending.WriteByte(uint8(val))
- ops.trace("%s (%s)", fs.field.String(), fs.ftype.String())
+ ops.trace("%s (%s)", fs.field, fs.ftype)
ops.returns(fs.ftype)
return nil
}
@@ -1138,7 +1138,7 @@ func assembleAssetHolding(ops *OpStream, spec *OpSpec, args []string) error {
val := fs.field
ops.pending.WriteByte(spec.Opcode)
ops.pending.WriteByte(uint8(val))
- ops.trace("%s (%s)", fs.field.String(), fs.ftype.String())
+ ops.trace("%s (%s)", fs.field, fs.ftype)
ops.returns(fs.ftype, StackUint64)
return nil
}
@@ -1159,7 +1159,7 @@ func assembleAssetParams(ops *OpStream, spec *OpSpec, args []string) error {
val := fs.field
ops.pending.WriteByte(spec.Opcode)
ops.pending.WriteByte(uint8(val))
- ops.trace("%s (%s)", fs.field.String(), fs.ftype.String())
+ ops.trace("%s (%s)", fs.field, fs.ftype)
ops.returns(fs.ftype, StackUint64)
return nil
}
@@ -1180,7 +1180,28 @@ func assembleAppParams(ops *OpStream, spec *OpSpec, args []string) error {
val := fs.field
ops.pending.WriteByte(spec.Opcode)
ops.pending.WriteByte(uint8(val))
- ops.trace("%s (%s)", fs.field.String(), fs.ftype.String())
+ ops.trace("%s (%s)", fs.field, fs.ftype)
+ ops.returns(fs.ftype, StackUint64)
+ return nil
+}
+
+func assembleAcctParams(ops *OpStream, spec *OpSpec, args []string) error {
+ if len(args) != 1 {
+ return ops.errorf("%s expects one argument", spec.Name)
+ }
+ fs, ok := AcctParamsFieldSpecByName[args[0]]
+ if !ok {
+ return ops.errorf("%s unknown field: %#v", spec.Name, args[0])
+ }
+ if fs.version > ops.Version {
+ //nolint:errcheck // we continue to maintain typestack
+ ops.errorf("%s %s available in version %d. Missed #pragma version?", spec.Name, args[0], fs.version)
+ }
+
+ val := fs.field
+ ops.pending.WriteByte(spec.Opcode)
+ ops.pending.WriteByte(uint8(val))
+ ops.trace("%s (%s)", fs.field, fs.ftype)
ops.returns(fs.ftype, StackUint64)
return nil
}
@@ -2640,6 +2661,20 @@ func disAppParams(dis *disassembleState, spec *OpSpec) (string, error) {
return fmt.Sprintf("%s %s", spec.Name, AppParamsFieldNames[arg]), nil
}
+func disAcctParams(dis *disassembleState, spec *OpSpec) (string, error) {
+ lastIdx := dis.pc + 1
+ if len(dis.program) <= lastIdx {
+ missing := lastIdx - len(dis.program) + 1
+ return "", fmt.Errorf("unexpected %s opcode end: missing %d bytes", spec.Name, missing)
+ }
+ dis.nextpc = dis.pc + 2
+ arg := dis.program[dis.pc+1]
+ if int(arg) >= len(AcctParamsFieldNames) {
+ return "", fmt.Errorf("invalid acct params arg index %d at pc=%d", arg, dis.pc)
+ }
+ return fmt.Sprintf("%s %s", spec.Name, AcctParamsFieldNames[arg]), nil
+}
+
func disTxField(dis *disassembleState, spec *OpSpec) (string, error) {
lastIdx := dis.pc + 1
if len(dis.program) <= lastIdx {
diff --git a/data/transactions/logic/assembler_test.go b/data/transactions/logic/assembler_test.go
index 6a903be79..fd53d458b 100644
--- a/data/transactions/logic/assembler_test.go
+++ b/data/transactions/logic/assembler_test.go
@@ -350,6 +350,10 @@ base64_decode URLEncoding
int 0
dup
gloadss
+byte 0x0123456789abcd
+bsqrt
+txn Sender
+acct_params_get AcctBalance
`
var nonsense = map[uint64]string{
@@ -367,7 +371,7 @@ var compiled = map[uint64]string{
3: "032008b7a60cf8acd19181cf959a12f8acd19181cf951af8acd19181cf15f8acd191810f01020026050212340c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d024242047465737400320032013202320328292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e0102222324252104082209240a220b230c240d250e230f23102311231223132314181b1c2b171615400003290349483403350222231d4a484848482a50512a63222352410003420000432105602105612105270463484821052b62482b642b65484821052b2106662b21056721072b682b692107210570004848210771004848361c0037001a0031183119311b311d311e311f3120210721051e312131223123312431253126312731283129312a312b312c312d312e312f4478222105531421055427042106552105082106564c4d4b02210538212106391c0081e80780046a6f686e",
4: "042004010200b7a60c26040242420c68656c6c6f20776f726c6421208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292a0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f23102311231223132314181b1c28171615400003290349483403350222231d4a484848482a50512a632223524100034200004322602261222b634848222862482864286548482228236628226724286828692422700048482471004848361c0037001a0031183119311b311d311e311f312024221e312131223123312431253126312731283129312a312b312c312d312e312f44782522531422542b2355220823564c4d4b0222382123391c0081e80780046a6f686e2281d00f24231f880003420001892223902291922394239593a0a1a2a3a4a5a6a7a8a9aaabacadae23af3a00003b003c003d8164",
5: "052004010002b7a60c26050242420c68656c6c6f20776f726c6421070123456789abcd208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292b0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f23102311231223132314181b1c28171615400003290349483403350222231d4a484848482b50512a632223524100034200004322602261222704634848222862482864286548482228246628226723286828692322700048482371004848361c0037001a0031183119311b311d311e311f312023221e312131223123312431253126312731283129312a312b312c312d312e312f447825225314225427042455220824564c4d4b0222382124391c0081e80780046a6f686e2281d00f23241f880003420001892224902291922494249593a0a1a2a3a4a5a6a7a8a9aaabacadae24af3a00003b003c003d816472064e014f012a57000823810858235b235a2359b03139330039b1b200b322c01a23c1001a2323c21a23c3233e233f8120af06002a494905002a49490700b53a03",
- 6: "062004010002b7a60c26050242420c68656c6c6f20776f726c6421070123456789abcd208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292b0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f23102311231223132314181b1c28171615400003290349483403350222231d4a484848482b50512a632223524100034200004322602261222704634848222862482864286548482228246628226723286828692322700048482371004848361c0037001a0031183119311b311d311e311f312023221e312131223123312431253126312731283129312a312b312c312d312e312f447825225314225427042455220824564c4d4b0222382124391c0081e80780046a6f686e2281d00f23241f880003420001892224902291922494249593a0a1a2a3a4a5a6a7a8a9aaabacadae24af3a00003b003c003d816472064e014f012a57000823810858235b235a2359b03139330039b1b200b322c01a23c1001a2323c21a23c3233e233f8120af06002a494905002a49490700b53a03b6b7043cb8033a0c5c002349c4",
+ 6: "062004010002b7a60c26050242420c68656c6c6f20776f726c6421070123456789abcd208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292b0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f23102311231223132314181b1c28171615400003290349483403350222231d4a484848482b50512a632223524100034200004322602261222704634848222862482864286548482228246628226723286828692322700048482371004848361c0037001a0031183119311b311d311e311f312023221e312131223123312431253126312731283129312a312b312c312d312e312f447825225314225427042455220824564c4d4b0222382124391c0081e80780046a6f686e2281d00f23241f880003420001892224902291922494249593a0a1a2a3a4a5a6a7a8a9aaabacadae24af3a00003b003c003d816472064e014f012a57000823810858235b235a2359b03139330039b1b200b322c01a23c1001a2323c21a23c3233e233f8120af06002a494905002a49490700b53a03b6b7043cb8033a0c5c002349c42a9631007300",
}
func pseudoOp(opcode string) bool {
diff --git a/data/transactions/logic/doc.go b/data/transactions/logic/doc.go
index e64cd2cae..4b6972198 100644
--- a/data/transactions/logic/doc.go
+++ b/data/transactions/logic/doc.go
@@ -54,123 +54,126 @@ var opDocByName = map[string]string{
"~": "bitwise invert value A",
"shl": "A times 2^B, modulo 2^64",
"shr": "A divided by 2^B",
- "sqrt": "The largest integer B such that B^2 <= A",
+ "sqrt": "The largest integer I such that I^2 <= A",
"bitlen": "The highest set bit in A. If A is a byte-array, it is interpreted as a big-endian unsigned integer. bitlen of 0 is 0, bitlen of 8 is 4",
"exp": "A raised to the Bth power. Fail if A == B == 0 and on overflow",
"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",
"mulw": "A times B as a 128-bit result in two uint64s. X is the high 64 bits, Y is the low",
"addw": "A plus B as a 128-bit result. X is the carry-bit, Y is the low-order 64 bits.",
- "divmodw": "Pop four uint64 values. A and B are interpreted as a uint128 dividend (A is the high word), C and D are interpreted as a uint128 divisor (C is the high word). Four uint64 values are pushed to the stack. The W and X are the quotient (W is the high uint64). Y and Z are the remainder, Y is the high bits.",
+ "divmodw": "W,X = (A,B / C,D); Y,Z = (A,B modulo C,D)",
"intcblock": "prepare block of uint64 constants for use by intc",
- "intc": "push Ith constant from intcblock to stack",
- "intc_0": "push constant 0 from intcblock to stack",
- "intc_1": "push constant 1 from intcblock to stack",
- "intc_2": "push constant 2 from intcblock to stack",
- "intc_3": "push constant 3 from intcblock to stack",
- "pushint": "push immediate UINT to the stack as an integer",
+ "intc": "Ith constant from intcblock",
+ "intc_0": "constant 0 from intcblock",
+ "intc_1": "constant 1 from intcblock",
+ "intc_2": "constant 2 from intcblock",
+ "intc_3": "constant 3 from intcblock",
+ "pushint": "immediate UINT",
"bytecblock": "prepare block of byte-array constants for use by bytec",
- "bytec": "push Ith constant from bytecblock to stack",
- "bytec_0": "push constant 0 from bytecblock to stack",
- "bytec_1": "push constant 1 from bytecblock to stack",
- "bytec_2": "push constant 2 from bytecblock to stack",
- "bytec_3": "push constant 3 from bytecblock to stack",
- "pushbytes": "push the following program bytes to the stack",
-
- "bzero": "push a byte-array of length A, containing all zero bytes",
- "arg": "push Nth LogicSig argument to stack",
- "arg_0": "push LogicSig argument 0 to stack",
- "arg_1": "push LogicSig argument 1 to stack",
- "arg_2": "push LogicSig argument 2 to stack",
- "arg_3": "push LogicSig argument 3 to stack",
- "args": "push Ath LogicSig argument to stack",
- "txn": "push field F of current transaction to stack",
- "gtxn": "push field F of the Tth transaction in the current group",
- "gtxns": "push field F of the Ath transaction in the current group",
- "txna": "push Ith value of the array field F of the current transaction",
- "gtxna": "push Ith value of the array field F from the Tth transaction in the current group",
- "gtxnsa": "push Ith value of the array field F from the Ath transaction in the current group",
- "txnas": "push Ath value of the array field F of the current transaction",
- "gtxnas": "push Ath value of the array field F from the Tth transaction in the current group",
- "gtxnsas": "pop an index A and an index B. push Bth value of the array field F from the Ath transaction in the current group",
- "itxn": "push field F of the last inner transaction",
- "itxna": "push Ith value of the array field F of the last inner transaction",
- "gitxn": "push field F of the Tth transaction in the last inner group submitted",
- "gitxna": "push Ith value of the array field F from the Tth transaction in the last inner group submitted",
-
- "global": "push value from globals to stack",
- "load": "copy a value from scratch space to the stack. All scratch spaces are 0 at program start.",
- "store": "pop value A. store A to the Ith scratch space",
- "loads": "copy a value from the Ath scratch space to the stack. All scratch spaces are 0 at program start.",
- "stores": "pop indexes A and B. store B to the Ath scratch space",
- "gload": "push Ith scratch space index of the Tth transaction in the current group",
- "gloads": "push Ith scratch space index of the Ath transaction in the current group",
- "gloadss": "push Bth scratch space index of the Ath transaction in the current group",
- "gaid": "push the ID of the asset or application created in the Tth transaction of the current group",
- "gaids": "push the ID of the asset or application created in the Ath transaction of the current group",
+ "bytec": "Ith constant from bytecblock",
+ "bytec_0": "constant 0 from bytecblock",
+ "bytec_1": "constant 1 from bytecblock",
+ "bytec_2": "constant 2 from bytecblock",
+ "bytec_3": "constant 3 from bytecblock",
+ "pushbytes": "immediate BYTES",
+
+ "bzero": "zero filled byte-array of length A",
+ "arg": "Nth LogicSig argument",
+ "arg_0": "LogicSig argument 0",
+ "arg_1": "LogicSig argument 1",
+ "arg_2": "LogicSig argument 2",
+ "arg_3": "LogicSig argument 3",
+ "args": "Ath LogicSig argument",
+ "txn": "field F of current transaction",
+ "gtxn": "field F of the Tth transaction in the current group",
+ "gtxns": "field F of the Ath transaction in the current group",
+ "txna": "Ith value of the array field F of the current transaction",
+ "gtxna": "Ith value of the array field F from the Tth transaction in the current group",
+ "gtxnsa": "Ith value of the array field F from the Ath transaction in the current group",
+ "txnas": "Ath value of the array field F of the current transaction",
+ "gtxnas": "Ath value of the array field F from the Tth transaction in the current group",
+ "gtxnsas": "Bth value of the array field F from the Ath transaction in the current group",
+ "itxn": "field F of the last inner transaction",
+ "itxna": "Ith value of the array field F of the last inner transaction",
+ "gitxn": "field F of the Tth transaction in the last inner group submitted",
+ "gitxna": "Ith value of the array field F from the Tth transaction in the last inner group submitted",
+
+ "global": "global field F",
+ "load": "Ith scratch space value. All scratch spaces are 0 at program start.",
+ "store": "store A to the Ith scratch space",
+ "loads": "Ath scratch space value. All scratch spaces are 0 at program start.",
+ "stores": "store B to the Ath scratch space",
+ "gload": "Ith scratch space value of the Tth transaction in the current group",
+ "gloads": "Ith scratch space value of the Ath transaction in the current group",
+ "gloadss": "Bth scratch space value of the Ath transaction in the current group",
+ "gaid": "ID of the asset or application created in the Tth transaction of the current group",
+ "gaids": "ID of the asset or application created in the Ath transaction of the current group",
"bnz": "branch to TARGET if value A is not zero",
"bz": "branch to TARGET if value A is zero",
"b": "branch unconditionally to TARGET",
- "return": "use last value on stack as success value; end",
- "pop": "discard value A from stack",
- "dup": "duplicate last value on stack",
- "dup2": "duplicate two last values on stack",
- "dig": "push the Nth value from the top of the stack. dig 0 is equivalent to dup",
+ "return": "use A as success value; end",
+ "pop": "discard A",
+ "dup": "duplicate A",
+ "dup2": "duplicate A and B",
+ "dig": "Nth value from the top of the stack. dig 0 is equivalent to dup",
"cover": "remove top of stack, and place it deeper in the stack such that N elements are above it. Fails if stack depth <= N.",
"uncover": "remove the value at depth N in the stack and shift above items down so the Nth deep value is on top of the stack. Fails if stack depth <= N.",
- "swap": "swaps two last values on stack",
+ "swap": "swaps A and B on stack",
"select": "selects one of two values based on top-of-stack: B if C != 0, else A",
- "concat": "pop two byte-arrays A and B and join them, push the result",
- "substring": "pop a byte-array A. For immediate values in 0..255 S and E: extract a range of bytes from A starting at S up to but not including E, push the substring result. If E < S, or either is larger than the array length, the program fails",
- "substring3": "pop a byte-array A and two integers B and C. Extract a range of bytes from A starting at B up to but not including C, push the substring result. If C < B, or either is larger than the array length, the program fails",
- "getbit": "pop a target A (integer or byte-array), and index B. Push the Bth bit of A.",
- "setbit": "pop a target A, index B, and bit C. Set the Bth bit of A to C, and push the result",
- "getbyte": "pop a byte-array A and integer B. Extract the Bth byte of A and push it as an integer",
- "setbyte": "pop a byte-array A, integer B, and small integer C (between 0..255). Set the Bth byte of A to C, and push the result",
- "extract": "pop a byte-array A. For immediate values in 0..255 S and L: extract a range of bytes from A starting at S up to but not including S+L, push the substring result. 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",
- "extract3": "pop a byte-array A and two integers B and C. Extract a range of bytes from A starting at B up to but not including B+C, push the substring result. If B+C is larger than the array length, the program fails",
- "extract_uint16": "pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+2, convert bytes as big endian and push the uint64 result. If B+2 is larger than the array length, the program fails",
- "extract_uint32": "pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+4, convert bytes as big endian and push the uint64 result. If B+4 is larger than the array length, the program fails",
- "extract_uint64": "pop a byte-array A and integer B. Extract a range of bytes from A starting at B up to but not including B+8, convert bytes as big endian and push the uint64 result. If B+8 is larger than the array length, the program fails",
- "base64_decode": "decode A which was base64-encoded using _encoding_ E. Fail if X is not base64 encoded with encoding E",
+ "concat": "join A and B",
+ "substring": "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",
+ "getbit": "Bth bit of (byte-array or integer) A.",
+ "setbit": "Copy of (byte-array or integer) A, with the Bth bit set to (0 or 1) C",
+ "getbyte": "Bth byte of A, as an integer",
+ "setbyte": "Copy of A with the Bth byte set to small integer (between 0..255) C",
+ "extract": "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",
+ "extract3": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails",
+ "extract_uint16": "A uint16 formed from a range of big-endian bytes from A starting at B up to but not including B+2. If B+2 is larger than the array length, the program fails",
+ "extract_uint32": "A uint32 formed from a range of big-endian bytes from A starting at B up to but not including B+4. If B+4 is larger than the array length, the program fails",
+ "extract_uint64": "A uint64 formed from a range of big-endian bytes from A starting at B up to but not including B+8. If B+8 is larger than the array length, the program fails",
+ "base64_decode": "decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E",
"balance": "get balance for account A, in microalgos. The balance is observed after the effects of previous transactions in the group, and after the fee for the current transaction is deducted.",
"min_balance": "get minimum required balance for account A, in microalgos. Required balance is affected by [ASA](https://developer.algorand.org/docs/features/asa/#assets-overview) and [App](https://developer.algorand.org/docs/features/asc1/stateful/#minimum-balance-requirement-for-a-smart-contract) usage. When creating or opting into an app, the minimum balance grows before the app code runs, therefore the increase is visible there. When deleting or closing out, the minimum balance decreases after the app executes.",
- "app_opted_in": "check if account A opted in for the application B => {0 or 1}",
- "app_local_get": "read from account A from local state of the current application key B => value",
- "app_local_get_ex": "read from account A from local state of the application B key C => [*... stack*, value, 0 or 1]",
- "app_global_get": "read key A from global state of a current application => value",
- "app_global_get_ex": "read from application A global state key B => [*... stack*, value, 0 or 1]",
- "app_local_put": "write to account specified by A to local state of a current application key B with value C",
- "app_global_put": "write key A and value B to global state of the current application",
- "app_local_del": "delete from account A local state key B of the current application",
- "app_global_del": "delete key A from a global state of the current application",
- "asset_holding_get": "read from account A and asset B holding field X (imm arg) => {0 or 1 (top), value}",
- "asset_params_get": "read from asset A params field X (imm arg) => {0 or 1 (top), value}",
- "app_params_get": "read from app A params field X (imm arg) => {0 or 1 (top), value}",
- "assert": "immediately fail unless value X is a non-zero number",
+ "app_opted_in": "1 if account A is opted in to application B, else 0",
+ "app_local_get": "local state of the key B in the current application in account A",
+ "app_local_get_ex": "X is the local state of application B, key C in account A. Y is 1 if key existed, else 0",
+ "app_global_get": "global state of the key A in the current application",
+ "app_global_get_ex": "X is the global state of application A, key B. Y is 1 if key existed, else 0",
+ "app_local_put": "write C to key B in account A's local state of the current application",
+ "app_global_put": "write B to key A in the global state of the current application",
+ "app_local_del": "delete key B from account A's local state of the current application",
+ "app_global_del": "delete key A from the global state of the current application",
+ "asset_holding_get": "X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0",
+ "asset_params_get": "X is field F from asset A. Y is 1 if A exists, else 0",
+ "app_params_get": "X is field F from app A. Y is 1 if A exists, else 0",
+ "acct_params_get": "X is field F from account A. Y is 1 if A owns positive algos, else 0",
+ "assert": "immediately fail unless X is a non-zero number",
"callsub": "branch unconditionally to TARGET, saving the next instruction on the call stack",
"retsub": "pop the top instruction from the call stack and branch to it",
- "b+": "A plus B, where A and B are byte-arrays interpreted as big-endian unsigned integers",
- "b-": "A minus B, where A and B are byte-arrays interpreted as big-endian unsigned integers. Fail on underflow.",
- "b/": "A divided by B (truncated division), where A and B are byte-arrays interpreted as big-endian unsigned integers. Fail if B is zero.",
- "b*": "A times B, where A and B are byte-arrays interpreted as big-endian unsigned integers.",
- "b<": "A is less than B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}",
- "b>": "A is greater than B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}",
- "b<=": "A is less than or equal to B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}",
- "b>=": "A is greater than or equal to B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}",
- "b==": "A is equals to B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}",
- "b!=": "A is not equal to B, where A and B are byte-arrays interpreted as big-endian unsigned integers => { 0 or 1}",
- "b%": "A modulo B, where A and B are byte-arrays interpreted as big-endian unsigned integers. Fail if B is zero.",
- "b|": "A bitwise-or B, where A and B are byte-arrays, zero-left extended to the greater of their lengths",
- "b&": "A bitwise-and B, where A and B are byte-arrays, zero-left extended to the greater of their lengths",
- "b^": "A bitwise-xor B, where A and B are byte-arrays, zero-left extended to the greater of their lengths",
+ "b+": "A plus B. A and B are interpreted as big-endian unsigned integers",
+ "b-": "A minus B. A and B are interpreted as big-endian unsigned integers. Fail on underflow.",
+ "b/": "A divided by B (truncated division). A and B are interpreted as big-endian unsigned integers. Fail if B is zero.",
+ "b*": "A times B. A and B are interpreted as big-endian unsigned integers.",
+ "b<": "1 if A is less than B, else 0. A and B are interpreted as big-endian unsigned integers",
+ "b>": "1 if A is greater than B, else 0. A and B are interpreted as big-endian unsigned integers",
+ "b<=": "1 if A is less than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers",
+ "b>=": "1 if A is greater than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers",
+ "b==": "1 if A is equal to B, else 0. A and B are interpreted as big-endian unsigned integers",
+ "b!=": "0 if A is equal to B, else 1. A and B are interpreted as big-endian unsigned integers",
+ "b%": "A modulo B. A and B are interpreted as big-endian unsigned integers. Fail if B is zero.",
+ "b|": "A bitwise-or B. A and B are zero-left extended to the greater of their lengths",
+ "b&": "A bitwise-and B. A and B are zero-left extended to the greater of their lengths",
+ "b^": "A bitwise-xor B. A and B are zero-left extended to the greater of their lengths",
"b~": "A with all bits inverted",
- "log": "write bytes to log state of the current application",
+ "bsqrt": "The largest integer I such that I^2 <= A. A and I are interpreted as big-endian unsigned integers",
+
+ "log": "write A to log state of the current application",
"itxn_begin": "begin preparation of a new inner transaction in a new transaction group",
"itxn_next": "begin preparation of a new inner transaction in the same transaction group",
"itxn_field": "set field F of the current inner transaction to A",
@@ -223,6 +226,7 @@ var opcodeImmediateNotes = map[string]string{
"asset_holding_get": "{uint8 asset holding field index}",
"asset_params_get": "{uint8 asset params field index}",
"app_params_get": "{uint8 app params field index}",
+ "acct_params_get": "{uint8 account params field index}",
"itxn_field": "{uint8 transaction field index}",
"itxn": "{uint8 transaction field index}",
@@ -274,6 +278,7 @@ var opDocExtras = map[string]string{
"+": "Overflow is an error condition which halts execution and fails the transaction. Full precision is available from `addw`.",
"/": "`divmodw` is available to divide the two-element values produced by `mulw` and `addw`.",
"bitlen": "bitlen interprets arrays as big-endian integers, unlike setbit/getbit",
+ "divmodw": "The notation J,K indicates that two uint64 values J and K are interpreted as a uint128 value, with J as the high uint64 and K the low.",
"txn": "FirstValidTime causes the program to fail. The field is reserved for future use.",
"gtxn": "for notes on transaction fields available, see `txn`. If this transaction is _i_ in the group, `gtxn i field` is equivalent to `txn field`.",
"gtxns": "for notes on transaction fields available, see `txn`. If top of stack is _i_, `gtxns field` is equivalent to `gtxn _i_ field`. gtxns exists so that _i_ can be calculated, often based on the index of the current transaction.",
@@ -303,7 +308,7 @@ var opDocExtras = map[string]string{
"log": "`log` fails if called more than MaxLogCalls times in a program, or if the sum of logged bytes exceeds 1024 bytes.",
"itxn_begin": "`itxn_begin` initializes Sender to the application address; Fee to the minimum allowable, taking into account MinTxnFee and credit from overpaying in earlier transactions; FirstValid/LastValid to the values in the invoking transaction, and all other fields to zero or empty values.",
"itxn_next": "`itxn_next` initializes the transaction exactly as `itxn_begin` does",
- "itxn_field": "`itxn_field` fails if A is of the wrong type for F, including a byte array of the wrong size for use as an address when F is an address field. `itxn_field` also fails if A is an account, asset, or app that is not _available_. (Setting addresses in asset creation transactions need not be _available_.)",
+ "itxn_field": "`itxn_field` fails if A is of the wrong type for F, including a byte array of the wrong size for use as an address when F is an address field. `itxn_field` also fails if A is an account, asset, or app that is not _available_. (Addresses set into asset params of acfg transactions need not be _available_.)",
"itxn_submit": "`itxn_submit` resets the current transaction so that it can not be resubmitted. A new `itxn_begin` is required to prepare another inner transaction.",
"base64_decode": "Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See <a href=\"https://rfc-editor.org/rfc/rfc4648.html#section-4\">RFC 4648</a> (sections 4 and 5). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
}
@@ -319,11 +324,11 @@ func OpDocExtra(opName string) string {
var OpGroups = map[string][]string{
"Arithmetic": {"sha256", "keccak256", "sha512_256", "ed25519verify", "ecdsa_verify", "ecdsa_pk_recover", "ecdsa_pk_decompress", "+", "-", "/", "*", "<", ">", "<=", ">=", "&&", "||", "shl", "shr", "sqrt", "bitlen", "exp", "==", "!=", "!", "len", "itob", "btoi", "%", "|", "&", "^", "~", "mulw", "addw", "divmodw", "expw", "getbit", "setbit", "getbyte", "setbyte", "concat"},
"Byte Array Manipulation": {"substring", "substring3", "extract", "extract3", "extract_uint16", "extract_uint32", "extract_uint64", "base64_decode"},
- "Byte Array Arithmetic": {"b+", "b-", "b/", "b*", "b<", "b>", "b<=", "b>=", "b==", "b!=", "b%"},
+ "Byte Array Arithmetic": {"b+", "b-", "b/", "b*", "b<", "b>", "b<=", "b>=", "b==", "b!=", "b%", "bsqrt"},
"Byte Array Logic": {"b|", "b&", "b^", "b~"},
"Loading Values": {"intcblock", "intc", "intc_0", "intc_1", "intc_2", "intc_3", "pushint", "bytecblock", "bytec", "bytec_0", "bytec_1", "bytec_2", "bytec_3", "pushbytes", "bzero", "arg", "arg_0", "arg_1", "arg_2", "arg_3", "args", "txn", "gtxn", "txna", "txnas", "gtxna", "gtxnas", "gtxns", "gtxnsa", "gtxnsas", "global", "load", "loads", "store", "stores", "gload", "gloads", "gloadss", "gaid", "gaids"},
"Flow Control": {"err", "bnz", "bz", "b", "return", "pop", "dup", "dup2", "dig", "cover", "uncover", "swap", "select", "assert", "callsub", "retsub"},
- "State Access": {"balance", "min_balance", "app_opted_in", "app_local_get", "app_local_get_ex", "app_global_get", "app_global_get_ex", "app_local_put", "app_global_put", "app_local_del", "app_global_del", "asset_holding_get", "asset_params_get", "app_params_get", "log"},
+ "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"},
"Inner Transactions": {"itxn_begin", "itxn_next", "itxn_field", "itxn_submit", "itxn", "itxna", "gitxn", "gitxna"},
}
@@ -395,7 +400,7 @@ var txnFieldDocs = map[string]string{
"Type": "Transaction type as bytes",
"TypeEnum": "See table below",
"Sender": "32 byte address",
- "Fee": "micro-Algos",
+ "Fee": "microalgos",
"FirstValid": "round number",
"FirstValidTime": "Causes program to fail; reserved for future use",
"LastValid": "round number",
@@ -407,7 +412,7 @@ var txnFieldDocs = map[string]string{
"TxID": "The computed ID for this transaction. 32 bytes.",
"Receiver": "32 byte address",
- "Amount": "micro-Algos",
+ "Amount": "microalgos",
"CloseRemainderTo": "32 byte address",
"VotePK": "32 byte address",
@@ -465,8 +470,8 @@ var txnFieldDocs = map[string]string{
}
var globalFieldDocs = map[string]string{
- "MinTxnFee": "micro Algos",
- "MinBalance": "micro Algos",
+ "MinTxnFee": "microalgos",
+ "MinBalance": "microalgos",
"MaxTxnLife": "rounds",
"ZeroAddress": "32 byte address of all zero bytes",
"GroupSize": "Number of transactions in this atomic transaction group. At least 1",
@@ -531,6 +536,13 @@ var appParamsFieldDocs = map[string]string{
"AppAddress": "Address for which this application has authority",
}
+// acctParamsFieldDocs are notes on fields available in `app_params_get`
+var acctParamsFieldDocs = map[string]string{
+ "AcctBalance": "Account balance in microalgos",
+ "AcctMinBalance": "Minimum required blance for account, in microalgos",
+ "AcctAuthAddr": "Address the account is rekeyed to.",
+}
+
// EcdsaCurveDocs are notes on curves available in `ecdsa_` opcodes
var EcdsaCurveDocs = map[string]string{
"Secp256k1": "secp256k1 curve",
diff --git a/data/transactions/logic/doc_test.go b/data/transactions/logic/doc_test.go
index 705ce64b5..3287755f6 100644
--- a/data/transactions/logic/doc_test.go
+++ b/data/transactions/logic/doc_test.go
@@ -46,6 +46,7 @@ func TestOpDocs(t *testing.T) {
require.Len(t, assetHoldingFieldDocs, len(AssetHoldingFieldNames))
require.Len(t, assetParamsFieldDocs, len(AssetParamsFieldNames))
require.Len(t, appParamsFieldDocs, len(AppParamsFieldNames))
+ require.Len(t, acctParamsFieldDocs, len(AcctParamsFieldNames))
require.Len(t, TypeNameDescriptions, len(TxnTypeNames))
require.Len(t, EcdsaCurveDocs, len(EcdsaCurveNames))
}
diff --git a/data/transactions/logic/eval.go b/data/transactions/logic/eval.go
index c02846d81..05ee3ae02 100644
--- a/data/transactions/logic/eval.go
+++ b/data/transactions/logic/eval.go
@@ -1159,11 +1159,7 @@ func opLt(cx *EvalContext) {
last := len(cx.stack) - 1
prev := last - 1
cond := cx.stack[prev].Uint < cx.stack[last].Uint
- if cond {
- cx.stack[prev].Uint = 1
- } else {
- cx.stack[prev].Uint = 0
- }
+ cx.stack[prev].Uint = boolToUint(cond)
cx.stack = cx.stack[:last]
}
@@ -1186,11 +1182,7 @@ func opAnd(cx *EvalContext) {
last := len(cx.stack) - 1
prev := last - 1
cond := (cx.stack[prev].Uint != 0) && (cx.stack[last].Uint != 0)
- if cond {
- cx.stack[prev].Uint = 1
- } else {
- cx.stack[prev].Uint = 0
- }
+ cx.stack[prev].Uint = boolToUint(cond)
cx.stack = cx.stack[:last]
}
@@ -1198,11 +1190,7 @@ func opOr(cx *EvalContext) {
last := len(cx.stack) - 1
prev := last - 1
cond := (cx.stack[prev].Uint != 0) || (cx.stack[last].Uint != 0)
- if cond {
- cx.stack[prev].Uint = 1
- } else {
- cx.stack[prev].Uint = 0
- }
+ cx.stack[prev].Uint = boolToUint(cond)
cx.stack = cx.stack[:last]
}
@@ -1221,11 +1209,7 @@ func opEq(cx *EvalContext) {
} else {
cond = cx.stack[prev].Uint == cx.stack[last].Uint
}
- if cond {
- cx.stack[prev].Uint = 1
- } else {
- cx.stack[prev].Uint = 0
- }
+ cx.stack[prev].Uint = boolToUint(cond)
cx.stack[prev].Bytes = nil
cx.stack = cx.stack[:last]
}
@@ -1238,11 +1222,7 @@ func opNeq(cx *EvalContext) {
func opNot(cx *EvalContext) {
last := len(cx.stack) - 1
cond := cx.stack[last].Uint == 0
- if cond {
- cx.stack[last].Uint = 1
- } else {
- cx.stack[last].Uint = 0
- }
+ cx.stack[last].Uint = boolToUint(cond)
}
func opLen(cx *EvalContext) {
@@ -1509,6 +1489,19 @@ func opBytesMul(cx *EvalContext) {
opBytesBinOp(cx, result, result.Mul)
}
+func opBytesSqrt(cx *EvalContext) {
+ last := len(cx.stack) - 1
+
+ if len(cx.stack[last].Bytes) > MaxByteMathSize {
+ cx.err = errors.New("math attempted on large byte-array")
+ return
+ }
+
+ val := new(big.Int).SetBytes(cx.stack[last].Bytes)
+ val.Sqrt(val)
+ cx.stack[last].Bytes = val.Bytes()
+}
+
func opBytesLt(cx *EvalContext) {
last := len(cx.stack) - 1
prev := last - 1
@@ -1521,11 +1514,7 @@ func opBytesLt(cx *EvalContext) {
rhs := new(big.Int).SetBytes(cx.stack[last].Bytes)
lhs := new(big.Int).SetBytes(cx.stack[prev].Bytes)
cx.stack[prev].Bytes = nil
- if lhs.Cmp(rhs) < 0 {
- cx.stack[prev].Uint = 1
- } else {
- cx.stack[prev].Uint = 0
- }
+ cx.stack[prev].Uint = boolToUint(lhs.Cmp(rhs) < 0)
cx.stack = cx.stack[:last]
}
@@ -1556,11 +1545,7 @@ func opBytesEq(cx *EvalContext) {
rhs := new(big.Int).SetBytes(cx.stack[last].Bytes)
lhs := new(big.Int).SetBytes(cx.stack[prev].Bytes)
cx.stack[prev].Bytes = nil
- if lhs.Cmp(rhs) == 0 {
- cx.stack[prev].Uint = 1
- } else {
- cx.stack[prev].Uint = 0
- }
+ cx.stack[prev].Uint = boolToUint(lhs.Cmp(rhs) == 0)
cx.stack = cx.stack[:last]
}
@@ -2228,9 +2213,8 @@ func (cx *EvalContext) txnFieldToStack(stxn *transactions.SignedTxnWithAD, fs *t
return
}
- txnFieldType := TxnFieldTypes[fs.field]
- if !typecheck(txnFieldType, sv.argType()) {
- err = fmt.Errorf("%s expected field type is %s but got %s", fs.field.String(), txnFieldType.String(), sv.argType().String())
+ if !typecheck(fs.ftype, sv.argType()) {
+ err = fmt.Errorf("%s expected field type is %s but got %s", fs.field, fs.ftype, sv.argType())
}
return
}
@@ -3880,6 +3864,62 @@ func opAppParamsGet(cx *EvalContext) {
cx.stack = append(cx.stack, stackValue{Uint: exist})
}
+func opAcctParamsGet(cx *EvalContext) {
+ last := len(cx.stack) - 1 // acct
+
+ if cx.Ledger == nil {
+ cx.err = fmt.Errorf("ledger not available")
+ return
+ }
+
+ addr, _, err := cx.accountReference(cx.stack[last])
+ if err != nil {
+ cx.err = err
+ return
+ }
+
+ paramField := AcctParamsField(cx.program[cx.pc+1])
+ fs, ok := acctParamsFieldSpecByField[paramField]
+ if !ok || fs.version > cx.version {
+ cx.err = fmt.Errorf("invalid acct_params_get field %d", paramField)
+ return
+ }
+
+ bal, err := cx.Ledger.Balance(addr)
+ if err != nil {
+ cx.err = err
+ return
+ }
+ exist := boolToUint(bal.Raw > 0)
+
+ var value stackValue
+
+ switch fs.field {
+ case AcctBalance:
+ value.Uint = bal.Raw
+ case AcctMinBalance:
+ mbal, err := cx.Ledger.MinBalance(addr, cx.Proto)
+ if err != nil {
+ cx.err = err
+ return
+ }
+ value.Uint = mbal.Raw
+ case AcctAuthAddr:
+ auth, err := cx.Ledger.Authorizer(addr)
+ if err != nil {
+ cx.err = err
+ return
+ }
+ if auth == addr {
+ value.Bytes = zeroAddress[:]
+ } else {
+ value.Bytes = auth[:]
+ }
+ }
+ cx.stack[last] = value
+ cx.stack = append(cx.stack, stackValue{Uint: exist})
+}
+
func opLog(cx *EvalContext) {
last := len(cx.stack) - 1
diff --git a/data/transactions/logic/evalStateful_test.go b/data/transactions/logic/evalStateful_test.go
index 1124a1cc8..91dff7192 100644
--- a/data/transactions/logic/evalStateful_test.go
+++ b/data/transactions/logic/evalStateful_test.go
@@ -1072,6 +1072,29 @@ func TestAppParams(t *testing.T) {
testApp(t, source, ep)
}
+func TestAcctParams(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+ ep, tx, ledger := makeSampleEnv()
+
+ source := "int 0; acct_params_get AcctBalance; !; assert; int 0; =="
+ testApp(t, source, ep)
+
+ source = "int 0; acct_params_get AcctMinBalance; !; assert; int 1001; =="
+ testApp(t, source, ep)
+
+ ledger.NewAccount(tx.Sender, 42)
+
+ source = "int 0; acct_params_get AcctBalance; assert; int 42; =="
+ testApp(t, source, ep)
+
+ source = "int 0; acct_params_get AcctMinBalance; assert; int 1001; =="
+ testApp(t, source, ep)
+
+ source = "int 0; acct_params_get AcctAuthAddr; assert; global ZeroAddress; =="
+ testApp(t, source, ep)
+}
+
func TestAppLocalReadWriteDeleteErrors(t *testing.T) {
partitiontest.PartitionTest(t)
@@ -2102,10 +2125,12 @@ func TestEnumFieldErrors(t *testing.T) {
partitiontest.PartitionTest(t)
source := `txn Amount`
- origTxnType := TxnFieldTypes[Amount]
- TxnFieldTypes[Amount] = StackBytes
+ origSpec := txnFieldSpecByField[Amount]
+ changed := origSpec
+ changed.ftype = StackBytes
+ txnFieldSpecByField[Amount] = changed
defer func() {
- TxnFieldTypes[Amount] = origTxnType
+ txnFieldSpecByField[Amount] = origSpec
}()
testLogic(t, source, AssemblerMaxVersion, defaultEvalParams(nil), "Amount expected field type is []byte but got uint64")
@@ -2249,6 +2274,7 @@ func TestReturnTypes(t *testing.T) {
"pushint": "pushint 7272",
"pushbytes": `pushbytes "jojogoodgorilla"`,
"app_params_get": "app_params_get AppGlobalNumUint",
+ "acct_params_get": "acct_params_get AcctMinBalance",
"extract": "extract 0 2",
"txnas": "txnas ApplicationArgs",
"gtxnas": "gtxnas 0 ApplicationArgs",
diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go
index 4b4716a80..4e03c2a26 100644
--- a/data/transactions/logic/eval_test.go
+++ b/data/transactions/logic/eval_test.go
@@ -3359,6 +3359,7 @@ func BenchmarkBigMath(b *testing.B) {
{"b*", "", "byte 0x01234576; byte 0x0223627389; b*; pop", "int 1"},
{"b/", "", "byte 0x0123457673624736; byte 0x0223627389; b/; pop", "int 1"},
{"b%", "", "byte 0x0123457673624736; byte 0x0223627389; b/; pop", "int 1"},
+ {"bsqrt", "", "byte 0x0123457673624736; bsqrt; pop", "int 1"},
{"b+big", // u256 + u256
"byte 0x0123457601234576012345760123457601234576012345760123457601234576",
@@ -3380,6 +3381,10 @@ func BenchmarkBigMath(b *testing.B) {
`byte 0xa123457601234576012345760123457601234576012345760123457601234576
byte 0x34576012345760123457601234576312; b/; pop`,
"int 1"},
+ {"bsqrt-big", "",
+ `byte 0xa123457601234576012345760123457601234576012345760123457601234576
+ bsqrt; pop`,
+ "int 1"},
}
for _, bench := range benches {
b.Run(bench[0], func(b *testing.B) {
@@ -3865,6 +3870,7 @@ func testEvaluation(t *testing.T, program string, introduced uint64, tester eval
// EvalParams, so try all forward versions.
for lv := v; lv <= AssemblerMaxVersion; lv++ {
t.Run(fmt.Sprintf("lv=%d", lv), func(t *testing.T) {
+ t.Helper()
var txn transactions.SignedTxn
txn.Lsig.Logic = ops.Program
ep := defaultEvalParamsWithVersion(&txn, lv)
@@ -4315,6 +4321,16 @@ func TestBytesMath(t *testing.T) {
// Even 128 byte outputs are ok
testAccepts(t, fmt.Sprintf("byte 0x%s; byte 0x%s; b*; len; int 128; ==", effs, effs), 4)
+
+ testAccepts(t, "byte 0x00; bsqrt; byte 0x; ==; return", 6)
+ testAccepts(t, "byte 0x01; bsqrt; byte 0x01; ==; return", 6)
+ testAccepts(t, "byte 0x10; bsqrt; byte 0x04; ==; return", 6)
+ testAccepts(t, "byte 0x11; bsqrt; byte 0x04; ==; return", 6)
+ testAccepts(t, "byte 0xffffff; bsqrt; len; int 2; ==; return", 6)
+ // 64 byte long inputs are accepted, even if they produce longer outputs
+ testAccepts(t, fmt.Sprintf("byte 0x%s; bsqrt; len; int 32; ==", effs), 6)
+ // 65 byte inputs are not ok.
+ testPanics(t, fmt.Sprintf("byte 0x%s00; bsqrt; pop; int 1", effs), 6)
}
func TestBytesCompare(t *testing.T) {
diff --git a/data/transactions/logic/fields.go b/data/transactions/logic/fields.go
index 2f2794e29..a1c944ffb 100644
--- a/data/transactions/logic/fields.go
+++ b/data/transactions/logic/fields.go
@@ -21,7 +21,7 @@ import (
"github.com/algorand/go-algorand/protocol"
)
-//go:generate stringer -type=TxnField,GlobalField,AssetParamsField,AppParamsField,AssetHoldingField,OnCompletionConstType,EcdsaCurve,Base64Encoding -output=fields_string.go
+//go:generate stringer -type=TxnField,GlobalField,AssetParamsField,AppParamsField,AcctParamsField,AssetHoldingField,OnCompletionConstType,EcdsaCurve,Base64Encoding -output=fields_string.go
// TxnField is an enum type for `txn` and `gtxn`
type TxnField int
@@ -173,9 +173,6 @@ type FieldSpec interface {
// TxnFieldNames are arguments to the 'txn' and 'txnById' opcodes
var TxnFieldNames []string
-// TxnFieldTypes is StackBytes or StackUint64 parallel to TxnFieldNames
-var TxnFieldTypes []StackType
-
var txnFieldSpecByField map[TxnField]txnFieldSpec
// TxnFieldSpecByName gives access to the field specs by field name
@@ -296,17 +293,6 @@ func TxnaFieldNames() []string {
return names
}
-// TxnaFieldTypes is StackBytes or StackUint64 parallel to TxnaFieldNames
-func TxnaFieldTypes() []StackType {
- var types []StackType
- for _, fs := range txnFieldSpecs {
- if fs.array {
- types = append(types, fs.ftype)
- }
- }
- return types
-}
-
var innerTxnTypes = map[string]uint64{
string(protocol.PaymentTx): 5,
string(protocol.KeyRegistrationTx): 6,
@@ -414,9 +400,6 @@ const (
// GlobalFieldNames are arguments to the 'global' opcode
var GlobalFieldNames []string
-// GlobalFieldTypes is StackUint64 StackBytes in parallel with GlobalFieldNames
-var GlobalFieldTypes []StackType
-
type globalFieldSpec struct {
field GlobalField
ftype StackType
@@ -590,9 +573,6 @@ const (
// AssetHoldingFieldNames are arguments to the 'asset_holding_get' opcode
var AssetHoldingFieldNames []string
-// AssetHoldingFieldTypes is StackUint64 StackBytes in parallel with AssetHoldingFieldNames
-var AssetHoldingFieldTypes []StackType
-
type assetHoldingFieldSpec struct {
field AssetHoldingField
ftype StackType
@@ -669,9 +649,6 @@ const (
// AssetParamsFieldNames are arguments to the 'asset_params_get' opcode
var AssetParamsFieldNames []string
-// AssetParamsFieldTypes is StackUint64 StackBytes in parallel with AssetParamsFieldNames
-var AssetParamsFieldTypes []StackType
-
type assetParamsFieldSpec struct {
field AssetParamsField
ftype StackType
@@ -753,9 +730,6 @@ const (
// AppParamsFieldNames are arguments to the 'app_params_get' opcode
var AppParamsFieldNames []string
-// AppParamsFieldTypes is StackUint64 StackBytes in parallel with AppParamsFieldNames
-var AppParamsFieldTypes []StackType
-
type appParamsFieldSpec struct {
field AppParamsField
ftype StackType
@@ -804,18 +778,75 @@ func (s appNameSpecMap) SpecByName(name string) FieldSpec {
return &fs
}
+// AcctParamsField is an enum for `acct_params_get` opcode
+type AcctParamsField int
+
+const (
+ // AcctBalance is the blance, with pending rewards
+ AcctBalance AcctParamsField = iota
+ // AcctMinBalance is algos needed for this accounts apps and assets
+ AcctMinBalance
+ //AcctAuthAddr is the rekeyed address if any, else ZeroAddress
+ AcctAuthAddr
+
+ invalidAcctParamsField
+)
+
+// AcctParamsFieldNames are arguments to the 'acct_params_get' opcode
+var AcctParamsFieldNames []string
+
+type acctParamsFieldSpec struct {
+ field AcctParamsField
+ ftype StackType
+ version uint64
+}
+
+func (fs *acctParamsFieldSpec) Type() StackType {
+ return fs.ftype
+}
+
+func (fs *acctParamsFieldSpec) OpVersion() uint64 {
+ return 6
+}
+
+func (fs *acctParamsFieldSpec) Version() uint64 {
+ return fs.version
+}
+
+func (fs *acctParamsFieldSpec) Note() string {
+ note := acctParamsFieldDocs[fs.field.String()]
+ return note
+}
+
+var acctParamsFieldSpecs = []acctParamsFieldSpec{
+ {AcctBalance, StackUint64, 6},
+ {AcctMinBalance, StackUint64, 6},
+ {AcctAuthAddr, StackBytes, 6},
+}
+
+var acctParamsFieldSpecByField map[AcctParamsField]acctParamsFieldSpec
+
+// AcctParamsFieldSpecByName gives access to the field specs by field name
+var AcctParamsFieldSpecByName acctNameSpecMap
+
+// simple interface used by doc generator for fields versioning
+type acctNameSpecMap map[string]acctParamsFieldSpec
+
+func (s acctNameSpecMap) SpecByName(name string) FieldSpec {
+ fs := s[name]
+ return &fs
+}
+
func init() {
TxnFieldNames = make([]string, int(invalidTxnField))
for fi := Sender; fi < invalidTxnField; fi++ {
TxnFieldNames[fi] = fi.String()
}
- TxnFieldTypes = make([]StackType, int(invalidTxnField))
txnFieldSpecByField = make(map[TxnField]txnFieldSpec, len(TxnFieldNames))
for i, s := range txnFieldSpecs {
if int(s.field) != i {
panic("txnFieldSpecs disjoint with TxnField enum")
}
- TxnFieldTypes[i] = s.ftype
txnFieldSpecByField[s.field] = s
}
TxnFieldSpecByName = make(map[string]txnFieldSpec, len(TxnFieldNames))
@@ -825,15 +856,13 @@ func init() {
GlobalFieldNames = make([]string, int(invalidGlobalField))
for i := MinTxnFee; i < invalidGlobalField; i++ {
- GlobalFieldNames[int(i)] = i.String()
+ GlobalFieldNames[i] = i.String()
}
- GlobalFieldTypes = make([]StackType, len(GlobalFieldNames))
globalFieldSpecByField = make(map[GlobalField]globalFieldSpec, len(GlobalFieldNames))
for i, s := range globalFieldSpecs {
if int(s.field) != i {
panic("globalFieldSpecs disjoint with GlobalField enum")
}
- GlobalFieldTypes[i] = s.ftype
globalFieldSpecByField[s.field] = s
}
GlobalFieldSpecByName = make(gfNameSpecMap, len(GlobalFieldNames))
@@ -843,7 +872,7 @@ func init() {
EcdsaCurveNames = make([]string, int(invalidEcdsaCurve))
for i := Secp256k1; i < invalidEcdsaCurve; i++ {
- EcdsaCurveNames[int(i)] = i.String()
+ EcdsaCurveNames[i] = i.String()
}
ecdsaCurveSpecByField = make(map[EcdsaCurve]ecdsaCurveSpec, len(EcdsaCurveNames))
for _, s := range ecdsaCurveSpecs {
@@ -877,12 +906,10 @@ func init() {
AssetHoldingFieldNames = make([]string, int(invalidAssetHoldingField))
for i := AssetBalance; i < invalidAssetHoldingField; i++ {
- AssetHoldingFieldNames[int(i)] = i.String()
+ AssetHoldingFieldNames[i] = i.String()
}
- AssetHoldingFieldTypes = make([]StackType, len(AssetHoldingFieldNames))
assetHoldingFieldSpecByField = make(map[AssetHoldingField]assetHoldingFieldSpec, len(AssetHoldingFieldNames))
for _, s := range assetHoldingFieldSpecs {
- AssetHoldingFieldTypes[int(s.field)] = s.ftype
assetHoldingFieldSpecByField[s.field] = s
}
AssetHoldingFieldSpecByName = make(ahfNameSpecMap, len(AssetHoldingFieldNames))
@@ -892,12 +919,10 @@ func init() {
AssetParamsFieldNames = make([]string, int(invalidAssetParamsField))
for i := AssetTotal; i < invalidAssetParamsField; i++ {
- AssetParamsFieldNames[int(i)] = i.String()
+ AssetParamsFieldNames[i] = i.String()
}
- AssetParamsFieldTypes = make([]StackType, len(AssetParamsFieldNames))
assetParamsFieldSpecByField = make(map[AssetParamsField]assetParamsFieldSpec, len(AssetParamsFieldNames))
for _, s := range assetParamsFieldSpecs {
- AssetParamsFieldTypes[int(s.field)] = s.ftype
assetParamsFieldSpecByField[s.field] = s
}
AssetParamsFieldSpecByName = make(apfNameSpecMap, len(AssetParamsFieldNames))
@@ -907,12 +932,10 @@ func init() {
AppParamsFieldNames = make([]string, int(invalidAppParamsField))
for i := AppApprovalProgram; i < invalidAppParamsField; i++ {
- AppParamsFieldNames[int(i)] = i.String()
+ AppParamsFieldNames[i] = i.String()
}
- AppParamsFieldTypes = make([]StackType, len(AppParamsFieldNames))
appParamsFieldSpecByField = make(map[AppParamsField]appParamsFieldSpec, len(AppParamsFieldNames))
for _, s := range appParamsFieldSpecs {
- AppParamsFieldTypes[int(s.field)] = s.ftype
appParamsFieldSpecByField[s.field] = s
}
AppParamsFieldSpecByName = make(appNameSpecMap, len(AppParamsFieldNames))
@@ -920,6 +943,19 @@ func init() {
AppParamsFieldSpecByName[apfn] = appParamsFieldSpecByField[AppParamsField(i)]
}
+ AcctParamsFieldNames = make([]string, int(invalidAcctParamsField))
+ for i := AcctBalance; i < invalidAcctParamsField; i++ {
+ AcctParamsFieldNames[i] = i.String()
+ }
+ acctParamsFieldSpecByField = make(map[AcctParamsField]acctParamsFieldSpec, len(AcctParamsFieldNames))
+ for _, s := range acctParamsFieldSpecs {
+ acctParamsFieldSpecByField[s.field] = s
+ }
+ AcctParamsFieldSpecByName = make(acctNameSpecMap, len(AcctParamsFieldNames))
+ for i, apfn := range AcctParamsFieldNames {
+ AcctParamsFieldSpecByName[apfn] = acctParamsFieldSpecByField[AcctParamsField(i)]
+ }
+
txnTypeIndexes = make(map[string]uint64, len(TxnTypeNames))
for i, tt := range TxnTypeNames {
txnTypeIndexes[tt] = uint64(i)
diff --git a/data/transactions/logic/fields_string.go b/data/transactions/logic/fields_string.go
index 244979ce3..34515d78d 100644
--- a/data/transactions/logic/fields_string.go
+++ b/data/transactions/logic/fields_string.go
@@ -1,4 +1,4 @@
-// Code generated by "stringer -type=TxnField,GlobalField,AssetParamsField,AppParamsField,AssetHoldingField,OnCompletionConstType,EcdsaCurve,Base64Encoding -output=fields_string.go"; DO NOT EDIT.
+// Code generated by "stringer -type=TxnField,GlobalField,AssetParamsField,AppParamsField,AcctParamsField,AssetHoldingField,OnCompletionConstType,EcdsaCurve,Base64Encoding -output=fields_string.go"; DO NOT EDIT.
package logic
@@ -174,6 +174,26 @@ func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
+ _ = x[AcctBalance-0]
+ _ = x[AcctMinBalance-1]
+ _ = x[AcctAuthAddr-2]
+ _ = x[invalidAcctParamsField-3]
+}
+
+const _AcctParamsField_name = "AcctBalanceAcctMinBalanceAcctAuthAddrinvalidAcctParamsField"
+
+var _AcctParamsField_index = [...]uint8{0, 11, 25, 37, 59}
+
+func (i AcctParamsField) String() string {
+ if i < 0 || i >= AcctParamsField(len(_AcctParamsField_index)-1) {
+ return "AcctParamsField(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _AcctParamsField_name[_AcctParamsField_index[i]:_AcctParamsField_index[i+1]]
+}
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
_ = x[AssetBalance-0]
_ = x[AssetFrozen-1]
_ = x[invalidAssetHoldingField-2]
diff --git a/data/transactions/logic/fields_test.go b/data/transactions/logic/fields_test.go
index b60ee578f..d40ddc263 100644
--- a/data/transactions/logic/fields_test.go
+++ b/data/transactions/logic/fields_test.go
@@ -27,11 +27,6 @@ import (
"github.com/algorand/go-algorand/test/partitiontest"
)
-func TestArrayFields(t *testing.T) {
- partitiontest.PartitionTest(t)
- require.Equal(t, len(TxnaFieldNames()), len(TxnaFieldTypes()))
-}
-
// ensure v2+ fields fail in TEAL assembler and evaluator on a version before they introduced
// ensure v2+ fields error in v1 program
func TestGlobalFieldsVersions(t *testing.T) {
diff --git a/data/transactions/logic/opcodes.go b/data/transactions/logic/opcodes.go
index 40b4d77e9..80b73b189 100644
--- a/data/transactions/logic/opcodes.go
+++ b/data/transactions/logic/opcodes.go
@@ -282,10 +282,11 @@ var OpSpecs = []OpSpec{
{0x68, "app_local_del", opAppLocalDel, asmDefault, disDefault, oneAny.plus(oneBytes), nil, directRefEnabledVersion, runModeApplication, opDefault},
{0x69, "app_global_del", opAppGlobalDel, asmDefault, disDefault, oneBytes, nil, 2, runModeApplication, opDefault},
- {0x70, "asset_holding_get", opAssetHoldingGet, assembleAssetHolding, disAssetHolding, twoInts, oneAny.plus(oneInt), 2, runModeApplication, immediates("i")},
- {0x70, "asset_holding_get", opAssetHoldingGet, assembleAssetHolding, disAssetHolding, oneAny.plus(oneInt), oneAny.plus(oneInt), directRefEnabledVersion, runModeApplication, immediates("i")},
- {0x71, "asset_params_get", opAssetParamsGet, assembleAssetParams, disAssetParams, oneInt, oneAny.plus(oneInt), 2, runModeApplication, immediates("i")},
- {0x72, "app_params_get", opAppParamsGet, assembleAppParams, disAppParams, oneInt, oneAny.plus(oneInt), 5, runModeApplication, immediates("i")},
+ {0x70, "asset_holding_get", opAssetHoldingGet, assembleAssetHolding, disAssetHolding, twoInts, oneAny.plus(oneInt), 2, runModeApplication, immediates("f")},
+ {0x70, "asset_holding_get", opAssetHoldingGet, assembleAssetHolding, disAssetHolding, oneAny.plus(oneInt), oneAny.plus(oneInt), directRefEnabledVersion, runModeApplication, immediates("f")},
+ {0x71, "asset_params_get", opAssetParamsGet, assembleAssetParams, disAssetParams, oneInt, oneAny.plus(oneInt), 2, runModeApplication, immediates("f")},
+ {0x72, "app_params_get", opAppParamsGet, assembleAppParams, disAppParams, oneInt, oneAny.plus(oneInt), 5, runModeApplication, immediates("f")},
+ {0x73, "acct_params_get", opAcctParamsGet, assembleAcctParams, disAcctParams, oneInt, oneAny.plus(oneInt), 6, runModeApplication, immediates("f")},
{0x78, "min_balance", opMinBalance, asmDefault, disDefault, oneInt, oneInt, 3, runModeApplication, opDefault},
{0x78, "min_balance", opMinBalance, asmDefault, disDefault, oneAny, oneInt, directRefEnabledVersion, runModeApplication, opDefault},
@@ -306,6 +307,7 @@ var OpSpecs = []OpSpec{
{0x93, "bitlen", opBitLen, asmDefault, disDefault, oneAny, oneInt, 4, modeAny, opDefault},
{0x94, "exp", opExp, asmDefault, disDefault, twoInts, oneInt, 4, modeAny, opDefault},
{0x95, "expw", opExpw, asmDefault, disDefault, twoInts, twoInts, 4, modeAny, costly(10)},
+ {0x96, "bsqrt", opBytesSqrt, asmDefault, disDefault, oneBytes, oneBytes, 6, modeAny, costly(40)},
// Byteslice math.
{0xa0, "b+", opBytesPlus, asmDefault, disDefault, twoBytes, oneBytes, 4, modeAny, costly(10)},
diff --git a/test/scripts/e2e_subs/app-inner-calls.py b/test/scripts/e2e_subs/app-inner-calls.py
new file mode 100755
index 000000000..a027747b2
--- /dev/null
+++ b/test/scripts/e2e_subs/app-inner-calls.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+
+import os
+import sys
+from goal import Goal
+import algosdk.logic as logic
+
+from datetime import datetime
+
+stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+print(f"{os.path.basename(sys.argv[0])} start {stamp}")
+
+goal = Goal(sys.argv[1], autosend=True)
+
+joe = goal.new_account()
+
+txinfo, err = goal.pay(goal.account, joe, amt=500_000)
+assert not err, err
+
+# Turn off rewards for precise balance checking
+txinfo, err = goal.keyreg(joe, nonpart=True)
+assert not err, err
+joeb = goal.balance(joe)
+
+# When invoked, this app funds the app that was created in the txn
+# before it and invokes its start(asset) method. Of course, this app must
+# be prefunded to do so. And in real life, would want to check its
+# sender as access control
+fund_previous = """
+#pragma version 6
+ txn ApplicationID
+ bz end
+
+ itxn_begin
+ int pay
+ itxn_field TypeEnum
+
+ txn GroupIndex
+ int 1
+ -
+ gtxns CreatedApplicationID
+ dup
+ store 0
+ app_params_get AppAddress
+ assert
+ itxn_field Receiver
+
+ int 1000000
+ itxn_field Amount
+
+ itxn_next
+
+ int appl
+ itxn_field TypeEnum
+
+ load 0
+ itxn_field ApplicationID
+
+ txn GroupIndex
+ int 2
+ -
+ gtxns CreatedAssetID
+ itxn_field Assets
+
+ method "start(asset)"
+ itxn_field ApplicationArgs
+
+ byte 0x00
+ itxn_field ApplicationArgs
+ itxn_submit
+
+
+end:
+ int 1
+"""
+
+txinfo, err = goal.app_create(joe, goal.assemble(fund_previous))
+assert not err, err
+funder = txinfo['application-index']
+assert funder
+
+# Fund the funder
+txinfo, err = goal.pay(goal.account, goal.app_address(funder), amt=4_000_000)
+assert not err, err
+
+# Construct a group that creates an ASA and an app, then "starts" the
+# new app by funding and invoking "start(asset)" on it. Inside the new
+# app's start() method, there will be yet another inner transaction:
+# it opts into the supplied asset.
+
+goal.autosend = False
+create_asa = goal.asset_create(joe, total=10_000, unit_name="oz", asset_name="Gold")
+app_teal = """
+#pragma version 6
+ txn ApplicationID
+ bz end
+ txn ApplicationArgs 0
+ method "start(asset)"
+ ==
+ bz next0
+
+ itxn_begin
+
+ int axfer
+ itxn_field TypeEnum
+
+ txn ApplicationArgs 1
+ btoi
+ txnas Assets
+ itxn_field XferAsset
+
+ global CurrentApplicationAddress
+ itxn_field AssetReceiver
+
+ itxn_submit
+
+next0:
+
+end:
+ int 1
+"""
+create_app = goal.app_create(joe, goal.assemble(app_teal))
+start_app = goal.app_call(joe, funder)
+
+[asa_info, app_info, start_info], err = goal.send_group([create_asa, create_app, start_app])
+assert not err, err
+
+goal.autosend = True
+
+import json
+
+asa_id = asa_info['asset-index']
+app_id = app_info['application-index']
+assert asa_id+1 == app_id
+app_account = logic.get_application_address(app_id)
+
+# Check balance on app account is right (1m - 1 optin fee)
+assert 1_000_000-1000 == goal.balance(app_account), goal.balance(app_account)
+assert 0 == goal.balance(app_account, asa_id)
+# Check min-balance on app account is right (base + 1 asa)
+assert 200_000 == goal.min_balance(app_account), goal.min_balance(app_account)
+
+# Ensure creator can send asa to app
+txinfo, err = goal.axfer(joe, app_account, 10, asa_id)
+assert not err, err
+assert 10 == goal.balance(app_account, asa_id)
+
+
+print(f"{os.path.basename(sys.argv[0])} OK {stamp}")
diff --git a/test/scripts/e2e_subs/goal/goal.py b/test/scripts/e2e_subs/goal/goal.py
index 921d2c3ea..d21be52ad 100755
--- a/test/scripts/e2e_subs/goal/goal.py
+++ b/test/scripts/e2e_subs/goal/goal.py
@@ -156,12 +156,12 @@ class Goal:
return txid, ""
return self.confirm(txid), ""
except algosdk.error.AlgodHTTPError as e:
- return (None, str(e))
+ return (None, e)
def send_group(self, txns, confirm=True):
# Need unsigned transactions to calculate the group This pulls
- # out the unsigned tx if tx is sigged, logigsigged or
- # multisgged
+ # out the unsigned tx if tx is sigged, logicsigged or
+ # multisigged
utxns = [
tx if isinstance(tx, txn.Transaction) else tx.transaction
for tx in txns
@@ -172,14 +172,15 @@ class Goal:
tx.group = gid
else:
tx.transaction.group = gid
+ txids = [utxn.get_txid() for utxn in utxns]
try:
stxns = [self.sign(tx) for tx in txns]
- txid = self.algod.send_transactions(stxns)
+ self.algod.send_transactions(stxns)
if not confirm:
- return txid, ""
- return self.confirm(txid), ""
+ return txids, None
+ return [self.confirm(txid) for txid in txids], None
except algosdk.error.AlgodHTTPError as e:
- return (None, str(e))
+ return (txids, e)
def status(self):
return self.algod.status()
@@ -196,7 +197,7 @@ class Goal:
def wait_for_block(self, block):
"""
- Utility function to wait until the block number given has been confirmed
+ Utility function to wait until the given block has been confirmed
"""
print(f"Waiting for block {block}.")
s = self.algod.status()
@@ -322,6 +323,10 @@ class Goal:
info = self.algod.account_info(account)
return info["amount"]
+ def min_balance(self, account):
+ info = self.algod.account_info(account)
+ return info["min-balance"]
+
def holding(self, account, asa):
info = self.algod.account_info(account)
for asset in info["assets"]: