summaryrefslogtreecommitdiff
path: root/data/transactions/logic/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'data/transactions/logic/README.md')
-rw-r--r--data/transactions/logic/README.md134
1 files changed, 108 insertions, 26 deletions
diff --git a/data/transactions/logic/README.md b/data/transactions/logic/README.md
index c2344409c..530a01b13 100644
--- a/data/transactions/logic/README.md
+++ b/data/transactions/logic/README.md
@@ -1,17 +1,23 @@
# Transaction Execution Approval Language (TEAL)
TEAL is a bytecode based stack language that executes inside Algorand transactions. TEAL programs can be used to check the parameters of the transaction and approve the transaction as if by a signature. This use of TEAL is called a _LogicSig_. Starting with v2, TEAL programs may
-also execute as _Applications_ which are invoked with explicit application call transactions. Programs have read-only access to the transaction they are attached to, transactions in their atomic transaction group, and a few global values. In addition, _Application_ programs have access to limited state that is global to the application and per-account local state for each account that has opted-in to the application. Programs cannot modify or create transactions, only reject or approve them. For both types of program, approval is signaled by finishing with the stack containing a single non-zero uint64 value.
+also execute as _Applications_ which are invoked with explicit application call transactions. Programs have read-only access to the transaction they are attached to, transactions in their atomic transaction group, and a few global values. In addition, _Application_ programs have access to limited state that is global to the application and per-account local state for each account that has opted-in to the application. For both types of program, approval is signaled by finishing with the stack containing a single non-zero uint64 value.
## The Stack
-The stack starts empty and contains values of either uint64 or bytes (`bytes` are implemented in Go as a []byte slice). Most operations act on the stack, popping arguments from it and pushing results to it.
+The stack starts empty and contains values of either uint64 or bytes
+(`bytes` are implemented in Go as a []byte slice and may not exceed
+4096 bytes in length). Most operations act on the stack, popping
+arguments from it and pushing results to it.
The maximum stack depth is currently 1000.
## Scratch Space
-In addition to the stack there are 256 positions of scratch space, also uint64-bytes union values, accessed by the `load` and `store` ops moving data from or to scratch space, respectively.
+In addition to the stack there are 256 positions of scratch space,
+also uint64-bytes union values, each initialized as uint64
+zero. Scratch space is acccesed by the `load(s)` and `store(s)` ops
+moving data from or to scratch space, respectively.
## Execution Modes
@@ -30,14 +36,14 @@ TEAL LogicSigs run in Algorand nodes as part of testing a proposed transaction t
If an authorized program executes and finishes with a single non-zero uint64 value on the stack then that program has validated the transaction it is attached to.
-The TEAL program has access to data from the transaction it is attached to (`txn` op), any transactions in a transaction group it is part of (`gtxn` op), and a few global values like consensus parameters (`global` op). Some "Args" may be attached to a transaction being validated by a TEAL program. Args are an array of byte strings. A common pattern would be to have the key to unlock some contract as an Arg. Args are recorded on the blockchain and publicly visible when the transaction is submitted to the network.
+The TEAL program has access to data from the transaction it is attached to (`txn` op), any transactions in a transaction group it is part of (`gtxn` op), and a few global values like consensus parameters (`global` op). Some "Args" may be attached to a transaction being validated by a TEAL program. Args are an array of byte strings. A common pattern would be to have the key to unlock some contract as an Arg. Args are recorded on the blockchain and publicly visible when the transaction is submitted to the network. These LogicSig Args are _not_ signed.
A program can either authorize some delegated action on a normal private key signed or multisig account or be wholly in charge of a contract account.
* If the account has signed the program (an ed25519 signature on "Program" concatenated with the program bytes) then if the program returns true the transaction is authorized as if the account had signed it. This allows an account to hand out a signed program so that other users can carry out delegated actions which are approved by the program.
* If the SHA512_256 hash of the program (prefixed by "Program") is equal to the transaction Sender address then this is a contract account wholly controlled by the program. No other signature is necessary or possible. The only way to execute a transaction against the contract account is for the program to approve it.
-The TEAL bytecode plus the length of any Args must add up to less than 1000 bytes (consensus parameter LogicSigMaxSize). Each TEAL op has an associated cost and the program cost must total less than 20000 (consensus parameter LogicSigMaxCost). Most ops have a cost of 1, but a few slow crypto ops are much higher. Prior to v4, the program's cost was estimated as the static sum of all the opcode costs in the program (whether they were actually executed or not). Beginning with v4, the program's cost is tracked dynamically, while being evaluated. If the program exceeds its budget, it fails.
+The TEAL bytecode plus the length of all Args must add up to no more than 1000 bytes (consensus parameter LogicSigMaxSize). Each TEAL op has an associated cost and the program cost must total no more than 20000 (consensus parameter LogicSigMaxCost). Most ops have a cost of 1, but a few slow crypto ops are much higher. Prior to v4, the program's cost was estimated as the static sum of all the opcode costs in the program (whether they were actually executed or not). Beginning with v4, the program's cost is tracked dynamically, while being evaluated. If the program exceeds its budget, it fails.
## Constants
@@ -86,7 +92,7 @@ Many programs need only a few dozen instructions. The instruction set has some o
This summary is supplemented by more detail in the [opcodes document](TEAL_opcodes.md).
-Some operations 'panic' and immediately end execution of the program.
+Some operations 'panic' and immediately fail the program.
A transaction checked by a program that panics is not valid.
A contract account governed by a buggy program might not have a way to get assets back out of it. Code carefully.
@@ -104,10 +110,13 @@ For three-argument ops, `A` is the element two below the top, `B` is the penulti
| `keccak256` | Keccak256 hash of value X, yields [32]byte |
| `sha512_256` | SHA512_256 hash of value X, yields [32]byte |
| `ed25519verify` | for (data A, signature B, pubkey C) verify the signature of ("ProgData" \|\| program_hash \|\| data) against the pubkey => {0 or 1} |
-| `+` | A plus B. Panic on overflow. |
-| `-` | A minus B. Panic if B > A. |
-| `/` | A divided by B (truncated division). Panic if B == 0. |
-| `*` | A times B. Panic on overflow. |
+| `ecdsa_verify v` | for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1} |
+| `ecdsa_pk_recover v` | for (data A, recovery id B, signature C, D) recover a public key => [*... stack*, X, Y] |
+| `ecdsa_pk_decompress v` | decompress pubkey A into components X, Y => [*... stack*, X, Y] |
+| `+` | A plus B. Fail on overflow. |
+| `-` | A minus B. Fail if B > A. |
+| `/` | A divided by B (truncated division). Fail if B == 0. |
+| `*` | A times B. Fail on overflow. |
| `<` | A less than B => {0 or 1} |
| `>` | A greater than B => {0 or 1} |
| `<=` | A less than or equal to B => {0 or 1} |
@@ -118,14 +127,14 @@ For three-argument ops, `A` is the element two below the top, `B` is the penulti
| `shr` | A divided by 2^B |
| `sqrt` | The largest integer B such that B^2 <= X |
| `bitlen` | The highest set bit in X. If X 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. Panic if A == B == 0 and on overflow |
+| `exp` | A raised to the Bth power. Fail if A == B == 0 and on overflow |
| `==` | A is equal to B => {0 or 1} |
| `!=` | A is not equal to B => {0 or 1} |
| `!` | X == 0 yields 1; else 0 |
| `len` | yields length of byte value X |
| `itob` | converts uint64 X to big endian bytes |
| `btoi` | converts bytes X as big endian to uint64 |
-| `%` | A modulo B. Panic if B == 0. |
+| `%` | A modulo B. Fail if B == 0. |
| `\|` | A bitwise-or B |
| `&` | A bitwise-and B |
| `^` | A bitwise-xor B |
@@ -133,13 +142,28 @@ For three-argument ops, `A` is the element two below the top, `B` is the penulti
| `mulw` | A times B out to 128-bit long result as low (top) and high uint64 values on the stack |
| `addw` | A plus B out to 128-bit long result as sum (top) and carry-bit uint64 values on the stack |
| `divmodw` | Pop four uint64 values. The deepest two are interpreted as a uint128 dividend (deepest value is high word), the top two are interpreted as a uint128 divisor. Four uint64 values are pushed to the stack. The deepest two are the quotient (deeper value is the high uint64). The top two are the remainder, low bits on top. |
-| `expw` | A raised to the Bth power as a 128-bit long result as low (top) and high uint64 values on the stack. Panic if A == B == 0 or if the results exceeds 2^128-1 |
+| `expw` | A raised to the Bth power as a 128-bit long result as low (top) and high uint64 values on the stack. 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 |
+These opcodes return portions of byte arrays, accessed by position, in
+various sizes.
+
+### Byte Array Manipulation
+
+| Op | 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 |
+
These opcodes take byte-array values that are interpreted as
big-endian unsigned integers. For mathematical operators, the
returned values are the shortest byte-array that can represent the
@@ -155,8 +179,8 @@ bytes on outputs.
| Op | 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. Panic on underflow. |
-| `b/` | A divided by B (truncated division), where A and B are byte-arrays interpreted as big-endian unsigned integers. Panic if B is zero. |
+| `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} |
@@ -164,10 +188,10 @@ bytes on outputs.
| `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. Panic if B is zero. |
+| `b%` | A modulo B, where A and B are byte-arrays interpreted as big-endian unsigned integers. Fail if B is zero. |
These opcodes operate on the bits of byte-array values. The shorter
-array is interpeted as though left padded with zeros until it is the
+array is interpreted as though left padded with zeros until it is the
same length as the other input. The returned values are the same
length as the longest input. Therefore, unlike array arithmetic,
these results may contain leading zero bytes.
@@ -179,7 +203,6 @@ these results may contain leading zero bytes.
| `b^` | A bitwise-xor B, where A and B are byte-arrays, zero-left extended to the greater of their lengths |
| `b~` | X with all bits inverted |
-
### Loading Values
Opcodes for getting data onto the stack.
@@ -208,15 +231,21 @@ Some of these have immediate data in the byte or bytes after the opcode.
| `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 Xth 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 Xth 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 Xth value of the array field F from the Tth transaction in the current group |
| `gtxns f` | push field F of the Xth transaction in the current group |
| `gtxnsa f i` | push Ith value of the array field F from the Xth 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 |
-| `store i` | pop a value from the stack and store to scratch space |
+| `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 Xth scratch space to the stack. All scratch spaces are 0 at program start. |
+| `store i` | pop value X. store X 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 Xth transaction in the current group |
| `gaid t` | push the ID of the asset or application created in the Tth transaction of the current group |
@@ -283,6 +312,11 @@ Some of these have immediate data in the byte or bytes after the opcode.
| 54 | LocalNumUint | uint64 | Number of local state integers in ApplicationCall. LogicSigVersion >= 3. |
| 55 | LocalNumByteSlice | uint64 | Number of local state byteslices in ApplicationCall. LogicSigVersion >= 3. |
| 56 | ExtraProgramPages | uint64 | Number of additional pages for each of the application's approval and clear state programs. An ExtraProgramPages of 1 means 2048 more total bytes, or 1024 for each program. LogicSigVersion >= 4. |
+| 57 | Nonparticipation | uint64 | Marks an account nonparticipating for rewards. LogicSigVersion >= 5. |
+| 58 | Logs | []byte | Log messages emitted by an application call (itxn only). LogicSigVersion >= 5. |
+| 59 | NumLogs | uint64 | Number of Logs (itxn only). LogicSigVersion >= 5. |
+| 60 | CreatedAssetID | uint64 | Asset ID allocated by the creation of an ASA (itxn only). LogicSigVersion >= 5. |
+| 61 | CreatedApplicationID | uint64 | ApplicationID allocated by the creation of an application (itxn only). LogicSigVersion >= 5. |
Additional details in the [opcodes document](TEAL_opcodes.md#txn) on the `txn` op.
@@ -301,8 +335,10 @@ Global fields are fields that are common to all the transactions in the group. I
| 5 | LogicSigVersion | uint64 | Maximum supported TEAL version. LogicSigVersion >= 2. |
| 6 | Round | uint64 | Current round number. LogicSigVersion >= 2. |
| 7 | LatestTimestamp | uint64 | Last confirmed block UNIX timestamp. Fails if negative. LogicSigVersion >= 2. |
-| 8 | CurrentApplicationID | uint64 | ID of current application executing. Fails if no such application is executing. LogicSigVersion >= 2. |
+| 8 | CurrentApplicationID | uint64 | ID of current application executing. Fails in LogicSigs. LogicSigVersion >= 2. |
| 9 | CreatorAddress | []byte | Address of the creator of the current application. Fails if no such application is executing. LogicSigVersion >= 3. |
+| 10 | CurrentApplicationAddress | []byte | Address that the current application controls. Fails in LogicSigs. LogicSigVersion >= 5. |
+| 11 | GroupID | []byte | ID of the transaction group. 32 zero bytes if the transaction is not part of a group. LogicSigVersion >= 5. |
**Asset Fields**
@@ -328,7 +364,7 @@ Asset fields include `AssetHolding` and `AssetParam` fields that are used in the
| 8 | AssetReserve | []byte | Reserve address |
| 9 | AssetFreeze | []byte | Freeze address |
| 10 | AssetClawback | []byte | Clawback address |
-| 11 | AssetCreator | []byte | Creator address |
+| 11 | AssetCreator | []byte | Creator address. LogicSigVersion >= 5. |
**App Fields**
@@ -345,13 +381,14 @@ App fields used in the `app_params_get` opcode.
| 5 | AppLocalNumByteSlice | uint64 | Number of byte array values allowed in Local State |
| 6 | AppExtraProgramPages | uint64 | Number of Extra Program Pages of code space |
| 7 | AppCreator | []byte | Creator address |
+| 8 | AppAddress | []byte | Address for which this application has authority |
### Flow Control
| Op | Description |
| --- | --- |
-| `err` | Error. Panic immediately. This is primarily a fencepost against accidental zero bytes getting compiled into programs. |
+| `err` | Error. Fail immediately. This is primarily a fencepost against accidental zero bytes getting compiled into programs. |
| `bnz target` | branch to TARGET if value X is not zero |
| `bz target` | branch to TARGET if value X is zero |
| `b target` | branch unconditionally to TARGET |
@@ -360,8 +397,8 @@ App fields used in the `app_params_get` opcode.
| `dup` | duplicate last value on stack |
| `dup2` | duplicate two last values on stack: A, B -> A, B, A, B |
| `dig n` | push the Nth value from the top of the stack. dig 0 is equivalent to dup |
-| `cover n` | remove top of stack, and place it down the stack such that N elements are above it |
-| `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 |
+| `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: A, B -> B, A |
| `select` | selects one of two values based on top-of-stack: A, B, C -> (if C != 0 then B else A) |
| `assert` | immediately fail unless value X is a non-zero number |
@@ -388,6 +425,52 @@ App fields used in the `app_params_get` opcode.
| `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 |
+### Inner Transactions
+
+The following opcodes allow for "inner transactions". Inner
+transactions allow stateful applications to have many of the effects
+of a true top-level transaction, programatically. However, they are
+different in significant ways. The most important differences are
+that they are not signed, duplicates are not rejected, and they do not
+appear in the block in the usual away. Instead, their effects are
+noted in metadata associated with the associated top-level application
+call transaction. An inner transaction's `Sender` must be the
+SHA512_256 hash of the application ID (prefixed by "appID"), or an
+account that has been rekeyed to that hash.
+
+Currently, inner transactions may perform `pay`, `axfer`, `acfg`, and
+`afrz` effects. After executing an inner transaction with
+`itxn_submit`, the effects of the transaction are visible begining
+with the next instruction with, for example, `balance` and
+`min_balance` checks.
+
+Of the transaction Header fields, only a few fields may be set:
+`Type`/`TypeEnum`, `Sender`, and `Fee`. For the specific fields of
+each transaction types, any field, except `RekeyTo` may be set. This
+allows, for example, clawback transactions, asset opt-ins, and asset
+creates in addtion 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`
+and `TypeEnum` are considered to be the same field.) `itxn_field`
+fails immediately for unsupported fields, unsupported transaction
+types, or improperly typed values for a particular field. `itxn_field`
+makes aceptance decisions entirely from the field and value provided,
+never considering previously set fields. Illegal interactions between
+fields, such as setting fields that belong to two different
+transaction types, are rejected by `itxn_submit`.
+
+| Op | Description |
+| --- | --- |
+| `itxn_begin` | Begin preparation of a new inner transaction |
+| `itxn_field f` | Set field F of the current inner transaction to X |
+| `itxn_submit` | Execute the current inner transaction. Fail if 16 inner transactions have already been executed, or if the transaction itself fails. |
+| `itxn f` | push field F of the last inner transaction to stack |
+| `itxna f i` | push Ith value of the array field F of the last inner transaction to stack |
+
+
# Assembler Syntax
The assembler parses line by line. Ops that just use the stack appear on a line by themselves. Ops that take arguments are the op and then whitespace and then any argument or arguments.
@@ -458,7 +541,6 @@ A '[proto-buf style variable length unsigned int](https://developers.google.com/
Design and implementation limitations to be aware of with various versions of TEAL.
-* TEAL cannot create or change a transaction, only approve or reject.
* Stateless TEAL cannot lookup balances of Algos or other assets. (Standard transaction accounting will apply after TEAL has run and authorized a transaction. A TEAL-approved transaction could still be invalid by other accounting rules just as a standard signed transaction could be invalid. e.g. I can't give away money I don't have.)
* TEAL cannot access information in previous blocks. TEAL cannot access most information in other transactions in the current block. (TEAL can access fields of the transaction it is attached to and the transactions in an atomic transaction group.)
* TEAL cannot know exactly what round the current transaction will commit in (but it is somewhere in FirstValid through LastValid).