Legacy documentation: You are viewing version CURRENT; the latest available is LATEST.
Go to latest →Virtual Machine Specification
- Introduction
- Versioning
- Program format
- Execution context
- VM state
- Operations
- Instruction cost
- Value types
- Failure conditions
- Instructions
- References
Introduction
The Chain Protocol uses a bytecode language to express short programs used to authenticate blockchain activity. Programs are used in two contexts: transactions and blocks.
Programs are executed in a stack-based virtual machine.
- First, the program arguments are pushed on the stack one after the other (so that the last argument is on the top of the stack).
- Then the VM executes the actual predicate program (control program, issuance program or consensus program) encoded as a sequence of opcodes.
- If execution halts early (because of a disabled opcode, FAIL, a VERIFY failure, or exceeding the run limit), validation fails.
- If execution completes successfully, the top stack value is inspected. If it’s zero, validation fails, otherwise validation succeeds.
Each instruction has a built-in run cost that counts against a built-in run limit to protect the network from resource exhaustion. Currently, the protocol mandates a specific run limit. Future VM versions will provide more fine-grained control over run limit by operators and users of the network.
Versioning
Virtual machines for control and issuance programs inside transactions are versioned to enable future improvements using varint-encoded version number in the commitment strings where these programs are specified. Program arguments are not explicitly versioned, their semantics are defined by the VM version of the associated issuance and control program.
Nodes ignore programs with unknown versions, treating them like “anyone can issue/spend.” To discourage use of unassigned versions, block signers refuse to include transactions that use unassigned VM versions.
Blocks do not specify VM version explicitly. Consensus programs use VM version 1 with additional block-context restrictions applied to some instructions. Upgrades to block authentication can be made via additional fields in the block header.
Program format
A program comprises a sequence of zero or more instructions. Each instruction contains a one-byte opcode followed by zero or more continuation bytes, determined by the operation. Data in this format is informally known as bytecode.
Instructions that push arbitrary data onto the stack use one of the PUSHDATA opcode followed by a variable-length binary string to be placed on stack. The length of the string is either encoded within the opcode itself, or prepended to the string.
All other instructions are encoded simply by a single-byte opcode. The protocol reserves unassigned opcodes for future extensions.
Execution context
A program executes in a context, either a block or a transaction. Some instructions have different meaning based on the context.
Transactions use control programs to define predicates governing spending of an asset in a later transaction, issuance programs for predicates authenticating issuance of an asset, and program arguments to provide input data for the predicates in output and issuance programs.
Blocks use consensus programs to define predicates for signing the next block and program arguments to provide input data for the predicate in the previous block. Consensus programs have restricted functionality and do not use version tags. Some instructions (such as ASSET or CHECKOUTPUT) that do not make sense within the context of signing a block are disabled and cause an immediate validation failure.
Block context
Block context is defined by the block necessary for BLOCKHASH, NEXTPROGRAM and BLOCKTIME execution.
Instruction PROGRAM behaves differently than in transaction context.
Execution of any of the following instructions results in immediate failure:
Transaction context
Transaction context is defined by the pair of the entire transaction and a “current entry” that contains the evaluated predicate (e.g. a spend, issuance or mux).
Execution of any of the following instructions results in immediate failure:
VM state
VM State is a tuple consisting of:
- Program
- Program Counter (PC)
- Data Stack
- Alt Stack
- Run Limit
- Expansion Flag
- Execution Context: a. Block b. (Transaction, Current Entry)
Initial State has empty stacks, uninitialized program, PC set to zero, and run limit set to 10,000.
Program is a sequence of instructions, encoded as bytecode.
PC is a 32-bit unsigned integer used as a pointer to an opcode within a program.
Data Stack and Alt Stack are stacks of binary strings.
Run Limit is a built-in 64-bit integer specifying remaining total cost of execution. Run limit is decreased by the cost of each instruction and also affected by data added to and removed from the data stack and alt stack. Every byte added to either stack costs 1 unit, and every byte removed from either stack refunds 1 unit. (This includes explicit additions and removals by stack-manipulating instructions such as PUSHDATA and DROP, and also implicit additions and removals as when other instructions consume arguments and produce results.)
Expansion Flag indicates whether the expansion opcodes are allowed in the program or not. If the flag is off, these opcodes immediately fail the program execution.
Execution Context is either a block context or transaction context.
Operations
The VM has two high-level operations: Prepare VM and Verify Predicate.
Prepare VM
Places program arguments on the data stack one after another so that last argument is on the top of the stack. Additions to the stack are counted against the run limit using the standard memory cost function.
Verify predicate
Initializes VM with a predicate program and begins its execution with PC set to zero.
At the beginning of each execution step, the PC is checked. If it is less than the length of the program, VM reads the opcode at that byte position in the program and executes a corresponding instruction. Instructions are executed as described in the Instructions section. The run limit is decreased or increased according to the instruction’s run cost. If the instruction’s run cost exceeds the current run limit, the instruction is not executed and execution fails immediately.
If the PC is equal to or greater than the length of the program at the beginning of an execution step, execution is complete, and the top value of the data stack is checked and interpreted as a boolean. If it is false
, or if the data stack is empty, verification fails; otherwise, verification succeeds. (Note: The data stack may contain any number of elements when execution finishes; there is no “clean stack” requirement. The alt stack also can be non-empty upon completion.)
After each step, the PC is incremented by the size of the current instruction.
Instruction cost
Every instruction has a cost that affects VM run limit. Total instruction cost consists of execution cost and memory cost. Execution cost always reduces remaining run limit, while memory usage cost can be refunded (increasing the run limit) when previously used memory is released during VM execution.
Execution cost
Every instruction has a constant or variable execution cost. Simple instructions such as ADD have constant execution cost. More complex instructions like SHA3 or CHECKSIG have cost depending on amount of data that must be processed.
In order to account for spikes in memory usage some instructions (e.g. CAT) define a cost and a refund: before execution begins the cost is applied to the run limit, then after completion refund is applied together with run limit changes due to memory usage.
Memory cost
Memory cost is incurred when additional memory is allocated. This cost is fully refundable when the memory is released. Most operations allocate and release memory by using the data stack, but some others also use the alt stack (TOALTSTACK, FROMALTSTACK) and the system memory for new VM instances (CHECKPREDICATE).
Standard memory cost
Most instructions use only the data stack by removing some items and then placing some items back on the stack. For these operations, we define the standard memory cost applied as follows:
- Instruction’s memory cost value is set to zero.
- For each item removed from the data stack, instruction’s memory cost is decreased by 8+L where L is the length of the item in bytes.
- For each item added to the data stack the cost is increased by 8+L where L is the length of the item in bytes.
Value types
All items on the data and alt stacks are binary strings. Some instructions accept or return items of other types. When values of those types are pushed to or popped from the data stack, they are coerced to and from strings in accordance with the rules specified below.
In the stack diagrams accompanying the definition of each operation, x
and y
denote numbers, m
and n
denote non-negative numbers, and p
and q
denote booleans. If coercion fails (or if stack items designated as m
or n
coerce to negative numbers), the operation fails.
VM String
An ordered sequence of 0 or more bytes.
In this document, single bytes are represented in hexadecimal form with a 0x
base prefix, i.e. 0x00
or 0xff
.
In this document, strings are represented as sequences of unprefixed hexadecimal bytes, separated by spaces, and enclosed in double quotation marks, i.e. ""
, "01"
, or "ff ff"
.
VM Boolean
A boolean value (true
or false
).
String to Boolean
Any string can be coerced to a boolean.
Strings coerce to true
if and only if they contain any non-zero bytes. Therefore, for example, ""
, "00"
, and "00 00"
coerce to false
.
Boolean to String
false
coerces to an empty string ""
(the same representation as the number 0), true
coerces to a one-byte string "01"
(the same representation as the number 1).
VM Number
An integer greater than or equal to –263, and less than 263.
Certain arithmetic operations use conservative bounds checks (explicitly specified below) on their inputs to prevent the output from being outside the legal range. If one of these bounds checks fails, execution fails.
String to Number
- If the string is longer than 8 bytes, fail execution.
- If the string is shorter than 8 bytes, right-pad it by appending
0x00
bytes to get an 8-byte string. - Interpret the 8-byte string as a little-endian 64-bit integer, using two’s complement representation.
Number to String
- Create an 8-byte string matching the representation of the number as a little-endian 64-bit integer, using two’s complement representation for negative integers.
- Trim the string by removing any
0x00
bytes from the right side.
Value | String (hexadecimal) | Size in bytes |
---|---|---|
0 | “” |
0 |
1 | “01” |
1 |
–1 | “ff ff ff ff ff ff ff ff” |
8 |
2^63 - 1 (max) | “ff ff ff ff ff ff ff 7f” |
8 |
-2^63 (min) | “00 00 00 00 00 00 00 80” |
8 |
Failure conditions
Validation fails when:
- an instruction is executed that expects more elements on the stack than are present (see stack diagrams below under Instructions)
- a VERIFY instruction fails
- a FAIL instruction is executed
- the run limit is below the value required by the current instruction
- an invalid encoding is detected for keys or signatures
- coercion fails for numbers
- a bounds check fails for one of the splice or numeric instructions
- the program execution finishes with an empty data stack
- the program execution finishes with a false item on the top of the data stack
- an instruction specifies that it fails (see below)
Instructions
This section specifies the behavior of every instruction. Each instruction has a name and a run cost that modifies the VM’s run limit.
The cost of an instruction may be fixed or variable based on the amount of data being processed. In the tables below, the notation L or Lx is used to indicate the length in bytes of a given binary string. Positive cost increases reduces (“consumes”) run limit, negative cost increases (“refunds”) run limit.
When the instruction cost is specified as a single value, it is applied to the run limit before the instruction is executed. If two values represent a cost (such as 1; -1
or 1; standard memory cost
) that means that the first value is applied before executing the instruction and the second value is applied after.
Execution immediately halts if the run limit is insufficient to apply the cost of the instruction. In such case, the run limit is left unchanged (instead of becoming negative) and the execution halts. If the instruction defines two cost values (before and after the execution), and the first one did not cause the VM to halt, then its effects are not reversed. E.g. if the instruction cost is defined as 2;6
and the run limit is 5, then the first cost (2) is applied successfully (run limit becomes 3) and the second cost (6) halts execution leaving the run limit at 3. This value then can be refunded to the parent VM of a CHECKPREDICATE instruction.
Stack diagrams tell how top items of the data stack are replaced with new items. E.g. a stack diagram (a b → c d)
says that the topmost item b
and preceding item a
are removed from the data stack and items c
and d
are pushed one after another.
Non-executed instructions
Typically, all instructions must be executed in order for the execution to succeed. However, JUMP and JUMPIF instructions may cause the program to skip some of the instructions by “jumping over” them. If that happens, those instructions are not executed. This also means, that if those instructions are unassigned and reserved for future expansion, they do not cause the execution to fail even if expansion flag is off.
Instructions pushing data on stack
FALSE
Alias: OP_0
.
Code | Stack Diagram | Cost |
---|---|---|
0x00 | (∅ → 0) | 1; standard memory cost |
Pushes an empty string (the VM number 0) to the data stack.
PUSHDATA
Code | Stack Diagram | Cost |
---|---|---|
0x01 to 0x4e | (∅ → a) | 1 + standard memory cost |
Each opcode 0x00 ≤ n ≤ 0x4b is followed by n
bytes of data to be pushed onto the data stack as a single VM string. So opcode 0x01 is followed by 1 byte of data, 0x09 by 9 bytes, and so on up to 0x4b (75 bytes).
Opcode 0x4c is followed by a 1-byte length prefix encoding a length n
, then n
bytes of data to push (supports up to 255 bytes).
Opcode 0x4d is followed by a 2-byte little-endian length prefix encoding a length n
, then n
bytes of data to push (supports up to 65535 bytes).
Opcode 0x4e is followed by a 4-byte little-endian length prefix encoding a length n
, then n
bytes of data to push (supports up to 4294967295 bytes).
Each of these operations fails if they are not followed by the expected number of bytes of data.
1NEGATE
Code | Stack Diagram | Cost |
---|---|---|
0x4f | (∅ → –1) | 1 + standard memory cost |
Pushes "ff ff ff ff ff ff ff ff"
(the VM number -1) onto the data stack.
OP_1 to OP_16
Name | Code | Stack Diagram | Cost | Description |
---|---|---|---|---|
OP_1 | 0x51 | (∅ → 1) | 1 + standard memory cost | Pushes number 1 on the data stack. |
OP_2 | 0x52 | (∅ → 2) | 1 + standard memory cost | Pushes number 2 on the data stack. |
OP_3 | 0x53 | (∅ → 3) | 1 + standard memory cost | Pushes number 3 on the data stack. |
OP_4 | 0x54 | (∅ → 4) | 1 + standard memory cost | Pushes number 4 on the data stack. |
OP_5 | 0x55 | (∅ → 5) | 1 + standard memory cost | Pushes number 5 on the data stack. |
OP_6 | 0x56 | (∅ → 6) | 1 + standard memory cost | Pushes number 6 on the data stack. |
OP_7 | 0x57 | (∅ → 7) | 1 + standard memory cost | Pushes number 7 on the data stack. |
OP_8 | 0x58 | (∅ → 8) | 1 + standard memory cost | Pushes number 8 on the data stack. |
OP_9 | 0x59 | (∅ → 9) | 1 + standard memory cost | Pushes number 9 on the data stack. |
OP_10 | 0x5a | (∅ → 10) | 1 + standard memory cost | Pushes number 10 on the data stack. |
OP_11 | 0x5b | (∅ → 11) | 1 + standard memory cost | Pushes number 11 on the data stack. |
OP_12 | 0x5c | (∅ → 12) | 1 + standard memory cost | Pushes number 12 on the data stack. |
OP_13 | 0x5d | (∅ → 13) | 1 + standard memory cost | Pushes number 13 on the data stack. |
OP_14 | 0x5e | (∅ → 14) | 1 + standard memory cost | Pushes number 14 on the data stack. |
OP_15 | 0x5f | (∅ → 15) | 1 + standard memory cost | Pushes number 15 on the data stack. |
OP_16 | 0x60 | (∅ → 16) | 1 + standard memory cost | Pushes number 16 on the data stack. |
Control Flow Operators
JUMP
Code | Stack Diagram | Cost |
---|---|---|
0x63 | (∅ → ∅) | 1 |
Followed by a 4-byte unsigned integer address
.
Sets the PC to address
.
Fails if not followed by 4 bytes.
Note: this opcode may cause some instructions to not be executed.
JUMPIF
Code | Stack Diagram | Cost |
---|---|---|
0x64 | (p → ∅) | 1; standard memory cost |
Followed by a 4-byte unsigned integer address
.
Pops a boolean from the data stack. If it is true
, sets the PC to address
. If it is false
, does nothing.
Fails if not followed by 4 bytes.
Note: this opcode may cause some instructions to not be executed.
VERIFY
Code | Stack Diagram | Cost |
---|---|---|
0x69 | (p → ∅) | 1; standard memory cost |
Fails execution if the top item on the data stack is false. Otherwise, removes the top item.
FAIL
Code | Stack Diagram | Cost |
---|---|---|
0x6a | (∅ → ∅) | 1 |
Fails execution unconditionally.
CHECKPREDICATE
Code | Stack Diagram | Cost |
---|---|---|
0xc0 | (n predicate limit → q) | 256 + limit; standard memory cost – 256 + 64 – leftover |
If the remaining run limit is less than 256, execution fails immediately.
- Pops 3 items from the data stack:
limit
,predicate
andn
. - Coerces
limit
to an integer. - Coerces
n
to an integer. - If
limit
equals zero, sets it to the VM’s remaining run limit minus 256. - Reduces VM’s run limit by
256 + limit
. - Instantiates a new VM instance (“child VM”) with its run limit set to
limit
. - Moves the top
n
items from the parent VM’s data stack to the child VM’s data stack without incurring run limit refund or charge of their standard memory cost in either VM. The order of the moved items is unchanged. The memory cost of these items will be refunded when the child VM pops them, or when the child VM is destroyed and its parent VM is refunded. - Child VM evaluates the predicate and pushes
true
to the parent VM data stack if the evaluation did not fail and the child VM’s data stack is non-empty with atrue
value on top (this implements the same semantics as for the top-level verify predicate operation). It pushesfalse
otherwise. Note that the parent VM does not fail when the child VM exhausts its run limit or otherwise fails. - After the child VM finishes execution (normally or due to a failure), the parent VM’s run limit is refunded with a
leftover
value computed as a sum of the following values:- Remaining run limit of the child VM.
- Standard memory cost of all items left on the child VM’s data stack.
- Standard memory cost of all items left on the child VM’s alt stack.
- The total post-execution cost is then calculated as a sum of the following values:
- Refund of the standard memory cost of the top three items on the parent’s data stack (
limit
,predicate
,n
). - –256 (refunds cost of allocating memory for the child VM).
- +64 (cost of creating the child VM).
–leftover
(refund for the unused run limit and released memory within the child VM).
- Refund of the standard memory cost of the top three items on the parent’s data stack (
Failure conditions:
n
is not a non-negative number, or- there are less than
n+3
items on the data stack (includingn
,predicate
,limit
), or limit
is not a non-negative number, or- the run limit is less than 256, or
- the run limit is less than
256+limit
.
Stack control operators
TOALTSTACK
Code | Stack Diagram | Cost |
---|---|---|
0x6b | (a → ∅) | 2 |
Moves the top item from the data stack to the alt stack.
FROMALTSTACK
Code | Stack Diagram | Cost |
---|---|---|
0x6c | (∅ → a) | 2 |
Moves the top item from the alt stack to the data stack.
Fails if the alt stack is empty.
2DROP
Code | Stack Diagram | Cost |
---|---|---|
0x6d | (a b → ∅) | 2 + standard memory cost |
Removes top 2 items from the data stack.
2DUP
Code | Stack Diagram | Cost |
---|---|---|
0x6e | (a b → a b a b) | 2 + standard memory cost |
Duplicates top 2 items on the data stack.
3DUP
Code | Stack Diagram | Cost |
---|---|---|
0x6f | (a b c → a b c a b c) | 3 + standard memory cost |
Duplicates top 3 items on the data stack.
2OVER
Code | Stack Diagram | Cost |
---|---|---|
0x70 | (a b c d → a b c d a b) | 2 + standard memory cost |
Duplicates two items below the top two items on the data stack.
2ROT
Code | Stack Diagram | Cost |
---|---|---|
0x71 | (a b c d e f → c d e f a b) | 2 |
Moves 2 items below the top 4 items on the data stack to the top of the stack.
2SWAP
Code | Stack Diagram | Cost |
---|---|---|
0x72 | (a b c d → c d a b) | 2 |
Moves 2 items below the top 2 items on the data stack to the top of the stack.
IFDUP
Code | Stack Diagram | Cost |
---|---|---|
0x73 | (a → a | a a) | 1 + standard memory cost |
Duplicates the top item only if it’s not false.
DEPTH
Code | Stack Diagram | Cost |
---|---|---|
0x74 | (∅ → x) | 1; standard memory cost |
Adds the size of the data stack encoded as a VM number.
DROP
Code | Stack Diagram | Cost |
---|---|---|
0x75 | (a → ∅) | 1; standard memory cost |
Removes the top item from the data stack.
DUP
Code | Stack Diagram | Cost |
---|---|---|
0x76 | (a → a a) | 1 + standard memory cost |
Duplicates the top item on the data stack.
NIP
Code | Stack Diagram | Cost |
---|---|---|
0x77 | (a b → b) | 1 + standard memory cost |
Removes the item below the top one on the data stack.
OVER
Code | Stack Diagram | Cost |
---|---|---|
0x78 | (a b → a b a) | 1 + standard memory cost |
Copies the second from the top item to the top of the data stack.
PICK
Code | Stack Diagram | Cost |
---|---|---|
0x79 | (an … a1 a0 n → an … a1 a0 an) | 2 + standard memory cost |
Copies n+2
th item from the top to the top of the data stack.
Fails if the top item is not a valid non-negative number or there are fewer than n+2
items on the stack.
ROLL
Code | Stack Diagram | Cost |
---|---|---|
0x7a | (an … a1 a0 n → an-1 … a1 a0 an) | 2 + standard memory cost |
Moves n+2
th item from the top to the top of the data stack.
Fails if the top item is not a valid non-negative number or there are fewer than n+2
items on the stack.
ROT
Code | Stack Diagram | Cost |
---|---|---|
0x7b | (a b c → b c a) | 2 |
Moves the third item from the top to the top of the data stack.
SWAP
Code | Stack Diagram | Cost |
---|---|---|
0x7c | (a b → b a) | 1 |
Swaps top two items on the data stack.
TUCK
Code | Stack Diagram | Cost |
---|---|---|
0x7d | (a b → b a b) | 1 + standard memory cost |
Tucks the second item from the top of the data stack with two copies of the top item.
Splice operators
CAT
Code | Stack Diagram | Cost |
---|---|---|
0x7e | (“a” “b” → “ab”) | 4 + La + Lb; –(La + Lb) + standard memory cost |
Concatenates top two items on the data stack.
SUBSTR
Code | Stack Diagram | Cost |
---|---|---|
0x7f | (string m n → substring) | 4 + size; –size + standard memory cost |
Extracts a substring of string
of a given size n
at a given offset m
.
Failure conditions:
n
is not a VM number, orn
is negative, orn
is greater than the byte size of thestring
, orm
is not a VM number, orm
is not in range of [0, Lstring – size].
LEFT
Code | Stack Diagram | Cost |
---|---|---|
0x80 | (string n → prefix) | 4 + size; –size + standard memory cost |
Extracts a prefix of string
with the given size n
.
Failure conditions:
n
is not a VM number, orn
is negative, orn
is greater than the byte size of thestring
.
RIGHT
Code | Stack Diagram | Cost |
---|---|---|
0x81 | (string n → suffix) | 4 + size; –size + standard memory cost |
Extracts a suffix of string
with the given size n
.
Failure conditions:
n
is negative, orn
is greater than the byte size of thestring
.
SIZE
Code | Stack Diagram | Cost |
---|---|---|
0x82 | (string → string n) | 1; standard memory cost |
Pushes the size of string
encoded as a number n
without removing string
from the data stack.
CATPUSHDATA
Code | Stack Diagram | Cost |
---|---|---|
0x89 | (“a” “b” → “a pushdata(b)”) | 4 + La + Lb; –(La + Lb) + standard memory cost |
Appends second string encoded as the most compact PUSHDATA instruction. This is used for building new programs piecewise.
Bitwise operators
INVERT
Code | Stack Diagram | Cost |
---|---|---|
0x83 | (a → ~a) | 1 + Lx |
Inverts bits in the first item on the data stack.
AND
Code | Stack Diagram | Cost |
---|---|---|
0x84 | (a b → a&b) | 1 + min(La,Lb); standard memory cost |
Bitwise AND operation. Longer item is truncated, keeping the prefix.
OR
Code | Stack Diagram | Cost |
---|---|---|
0x85 | (a b → a|b) | 1 + max(La,Lb); standard memory cost |
Bitwise OR operation. Shorter item is zero-padded to the right.
XOR
Code | Stack Diagram | Cost |
---|---|---|
0x86 | (a b → a^b) | 1 + max(La,Lb); standard memory cost |
Bitwise XOR operation. Shorter item is zero-padded to the right.
EQUAL
Code | Stack Diagram | Cost |
---|---|---|
0x87 | (a b → a == b) | 1 + min(La,Lb); standard memory cost |
Pops two strings from the stack and compares them byte-by-byte. Pushes true if the strings are equal, false otherwise.
EQUALVERIFY
Code | Stack Diagram | Cost |
---|---|---|
0x88 | (a b → ∅) | 1 + min(La,Lb); standard memory cost |
Same as EQUAL VERIFY. Pops two strings from the stack, compares them byte-by-byte, and fails execution if they are not equal.
Logical and numeric operators
1ADD
Code | Stack Diagram | Cost |
---|---|---|
0x8b | (x → x+1) | 2; standard memory cost |
Pops a number from the data stack, adds 1 to it, and pushes the result to the data stack.
Fails if either of x
or x+1
is not a valid VM number.
1SUB
Code | Stack Diagram | Cost |
---|---|---|
0x8c | (x → x–1) | 2; standard memory cost |
Pops a number from the data stack, subtracts 1 from it, and pushes the result to the data stack.
Fails if either of x
or x-1
is not a valid VM number.
NEGATE
Code | Stack Diagram | Cost |
---|---|---|
0x8f | (x → –x) | 2; standard memory cost |
Pops a number from the data stack, negates it, and pushes the result to the data stack.
Fails if either of x
or -x
is not a valid VM number.
ABS
Code | Stack Diagram | Cost |
---|---|---|
0x90 | (x → abs(x)) | 2; standard memory cost |
Pops a number from the data stack, negates it if it is less than 0, and pushes the result to the data stack.
Fails if either of x
or abs(x)
is not a valid VM number.
NOT
Code | Stack Diagram | Cost |
---|---|---|
0x91 | (p → ~p) | 2; standard memory cost |
Pops a boolean from the data stack, negates it, and pushes the result to the data stack.
0NOTEQUAL
Code | Stack Diagram | Cost |
---|---|---|
0x92 | (x → x ≠ 0) | 2; standard memory cost |
Pops a number from the data stack, and results in false
if the number is equal to 0 and true
otherwise. Pushes the result to the data stack.
Fails if x
is not a valid VM number.
ADD
Code | Stack Diagram | Cost |
---|---|---|
0x93 | (x y → x+y) | 2; standard memory cost |
Pops two numbers from the data stack, adds them, and pushes the result to the data stack.
Fails if any of x
, y
, or x+y
is not a valid VM number.
SUB
Code | Stack Diagram | Cost |
---|---|---|
0x94 | (x y → x–y) | 2; standard memory cost |
Pops two numbers from the data stack, takes their difference, and pushes the result to the data stack.
Fails if any of x
, y
, or x-y
is not a valid VM number.
MUL
Code | Stack Diagram | Cost |
---|---|---|
0x95 | (x y → x·y) | 8; standard memory cost |
Pops two numbers from the data stack, multiplies them, and pushes the result to the data stack.
Fails if any of x
, y
, or x·y
is not a valid VM number.
DIV
Code | Stack Diagram | Cost |
---|---|---|
0x96 | (x y → x/y) | 8; standard memory cost |
Pops two numbers from the data stack, divides them rounding toward zero to an integer, and pushes the result to the data stack.
Fails if either of x
or y
is not a valid VM number, or if y
is zero.
MOD
Code | Stack Diagram | Cost |
---|---|---|
0x97 | (x y → x mod y) | 8; standard memory cost |
Pops two numbers from their data stack, determines the remainder of x
divided by y
, and pushes the result to the data stack. A non-zero result has the same sign as the divisor.
Example | Result |
---|---|
12 mod 10 | 2 |
–12 mod 10 | 8 |
12 mod –10 | –8 |
–12 mod –10 | –2 |
Fails if either of x
or y
is not a valid VM number, or if y
is zero.
LSHIFT
Code | Stack Diagram | Cost |
---|---|---|
0x98 | (x y → x << y) | 8; standard memory cost |
Pops two numbers from the data stack, multiplies x
by 2**y
(i.e., an arithmetic left shift with sign extension), coerces the result to a string, and pushes it to the data stack.
Example | Result |
---|---|
5 << 1 | 10 |
5 << 2 | 20 |
-5 << 1 | -10 |
Fails if any of x
, y
or x * 2**y
is not a valid VM number, or if y
is less than zero.
RSHIFT
Code | Stack Diagram | Cost |
---|---|---|
0x99 | (x y → x >> y) | 8; standard memory cost |
Pops two numbers from the data stack, divides x
by 2**y
rounding to an integer toward negative infinity (i.e., an arithmetic right shift with sign extension), and pushes the result to the stack.
Example | Result |
---|---|
10 >> 1 | 5 |
10 >> 2 | 2 |
1 >> 1 | 0 |
-1 >> 1 | -1 |
-10 >> 2 | -3 |
Fails if either of x
or y
is not a valid VM number, or if y
is less than zero.
BOOLAND
Code | Stack Diagram | Cost |
---|---|---|
0x9a | (p q → p && q) | 2; standard memory cost |
Pops two booleans from the data stack. Pushes true
to the data stack if both are true
, and pushes false
otherwise.
BOOLOR
Code | Stack Diagram | Cost |
---|---|---|
0x9b | (p q → p || q) | 2; standard memory cost |
Pops two booleans from the data stack. Pushes false
to the data stack if both are false
and pushes true
otherwise.
NUMEQUAL
Code | Stack Diagram | Cost |
---|---|---|
0x9c | (x y → x == y) | 2; standard memory cost |
Pops two numbers from the data stack. Pushes true
to the data stack if they are equal and pushes false
otherwise.
Note that two strings representing the same number may differ due to redundant leading zeros.
Fails if either of x
or y
is not a valid VM number.
NUMEQUALVERIFY
Code | Stack Diagram | Cost |
---|---|---|
0x9d | (x y → ∅) | 2; standard memory cost |
Equivalent to NUMEQUAL VERIFY.
Pops two numbers from the data stack, and fails if they are not equal.
Fails if either of x
or y
is not a valid VM number, or if they are not numerically equal.
NUMNOTEQUAL
Code | Stack Diagram | Cost |
---|---|---|
0x9e | (x y → x ≠ y) | 2; standard memory cost |
Pops two numbers from the data stack, results in false
if they are equal and in true
otherwise, and pushes the result to the data stack.
Note that two strings representing the same number may differ due to redundant leading zeros.
Fails if either of x
or y
is not a valid VM number.
LESSTHAN
Code | Stack Diagram | Cost |
---|---|---|
0x9f | (x y → x < y) | 2; standard memory cost |
Pops two numbers from the data stack, results in true
if x
is less than y
and false
otherwise, and pushes the result to the data stack.
Fails if either of x
or y
is not a valid VM number.
GREATERTHAN
Code | Stack Diagram | Cost |
---|---|---|
0xa0 | (x y → x > y) | 2; standard memory cost |
Pops two numbers from the data stack, results in true
if x
is greater than y
and in false
otherwise, and pushes the result to the data stack.
Fails if either of x
or y
is not a valid VM number.
LESSTHANOREQUAL
Code | Stack Diagram | Cost |
---|---|---|
0xa1 | (x y → x ≤ y) | 2; standard memory cost |
Pops two numbers from the data stack, results in true
if x
is less than or equal to y
and in false
otherwise, and pushes the result to the data stack.
Fails if either of x
or y
is not a valid VM number.
GREATERTHANOREQUAL
Code | Stack Diagram | Cost |
---|---|---|
0xa2 | (x y → x ≥ y) | 2; standard memory cost |
Pops two numbers from the data stack, results in true
if x
is greater than or equal to y
and in false
otherwise, and pushes the result to the data stack.
Fails if either of x
or y
is not a valid VM number.
MIN
Code | Stack Diagram | Cost |
---|---|---|
0xa3 | (x y → min(x,y)) | 2; standard memory cost |
Pops two numbers from the data stack, results in x
if x
is less than or equal to y
and in y
otherwise, and pushes the result to the data stack.
Fails if either of x
or y
is not a valid VM number.
MAX
Code | Stack Diagram | Cost |
---|---|---|
0xa4 | (x y → max(x,y)) | 2; standard memory cost |
Pops two numbers from the stack, results in x
if x
is greater than or equal to y
and in y
otherwise, and pushes the result to the data stack.
Fails if any of x
, y
, or z
is not a valid VM number.
WITHIN
Code | Stack Diagram | Cost |
---|---|---|
0xa5 | (x y z → y ≤ x < z) | 4; standard memory cost |
Pops two numbers from the stack, results in true if x
is greater or equal to the mininum value y
and less than the maximum value z
, and pushes the result to the stack.
Fails if any of x
, y
, or z
is not a valid VM number.
Cryptographic instructions
SHA256
Code | Stack Diagram | Cost |
---|---|---|
0xa8 | (a → SHA-256(a)) | max(64, 4·La) + standard memory cost |
Replaces top stack item with its SHA-256 hash value.
SHA3
Code | Stack Diagram | Cost |
---|---|---|
0xaa | (a → SHA3-256(a)) | max(64, 4·La) + standard memory cost |
Replaces top stack item with its SHA3-256 hash value.
CHECKSIG
Code | Stack Diagram | Cost |
---|---|---|
0xac | (sig hash pubkey → q) | 1024; standard memory cost |
Pops the top three items on the data stack, verifies the signature sig
of the hash
with a given public key pubkey
and pushes true
if the signature is valid; pushes false
if it is not.
Fails if hash
is not a 32-byte string.
CHECKMULTISIG
Code | Stack Diagram | Cost |
---|---|---|
0xad | (sigm-1 … sig0 hash pubkeyn-1 … pubkey0 m n → q) | 1024·n; standard memory cost |
- Pops non-negative numbers
n
andm
from the data stack. - If
n
is positive, verifies thatm
is also positive. - Pops
n
public keys. - Pops
hash
from the data stack. - Pops
m
signatures. - Verifies signatures one by one against the public keys and the given
hash
. Signatures must be in the same order as public keys and no two signatures are verified with the same public key. - Pushes
true
if all of the signatures are valid, andfalse
otherwise.
Failure conditions:
- there are fewer than
m+n+3
items on the data stack, or - the top item (
n
) is not a number, or n
is negative, or- the second from the top item (
m
) is not a number, or m
is negative, orm
is greater thann
, orm
is zero andn
is positive.
TXSIGHASH
Code | Stack Diagram | Cost |
---|---|---|
0xae | (∅ → hash) | 256 + standard memory cost |
Computes the transaction signature hash corresponding to the current entry. Equals SHA3-256 of the concatenation of the current entry ID and transaction ID:
TXSIGHASH = SHA3-256(entryID || txID)
This instruction is typically used with CHECKSIG or CHECKMULTISIG.
Fails if executed in the block context.
BLOCKHASH
Code | Stack Diagram | Cost |
---|---|---|
0xaf | (∅ → hash) | 1 + standard memory cost |
Returns the block ID.
Typically used with CHECKSIG or CHECKMULTISIG.
Fails if executed in the transaction context.
Introspection instructions
The following instructions are defined within a transaction context. In the block context these instructions cause VM to halt immediately and return false.
Note: standard memory cost is applied after the instruction is executed in order to determine the exact size of the encoded data (this also applies to ASSET, even though the result is always 32 bytes long).
CHECKOUTPUT
Code | Stack Diagram | Cost |
---|---|---|
0xc1 | (index data amount assetid version prog → q) | 16; standard memory cost |
- Pops 6 items from the data stack:
index
,data
,amount
,assetid
,version
,prog
. - Fails if
index
is negative or not a valid number. - Fails if
amount
is not a non-negative number. - Fails if
version
is not a non-negative number. - If the current entry is a Mux1:
- Finds a destination entry at the given
index
. Fails if there is no entry atindex
. - If the entry satisfies all of the following conditions pushes true on the data stack; otherwise pushes false:
- the destination entry is an Output1 or a Retirement1,
- if the destination is an output:
- output program bytecode equals
prog
, - output VM version equals
version
.
- output program bytecode equals
- if the destination is a retirement:
version
equals 1,prog
begins with a FAIL instruction.
- asset ID equals
assetid
, - amount equals
amount
, data
is an empty string or it matches the 32-byte data string in the destination entry.
- Finds a destination entry at the given
- If the entry is an Issuance1 or a Spend1:
- If the destination entry is a Mux1, performs checks as described in step 5.
- If the destination entry is an Output1 or a Retirement1:
- If
index
is not zero, pushes false on the data stack. - Otherwise, performs checks as described in step 5.2.
- If
Fails if executed in the block context.
Fails if the entry is not a Mux1, an Issuance1 or a Spend1.
ASSET
Code | Stack Diagram | Cost |
---|---|---|
0xc2 | (∅ → assetid) | 1; standard memory cost |
- If the current entry is an Issuance1, pushes
Value.AssetID
. - If the current entry is a Spend1, pushes the
SpentOutput.Source.Value.AssetID
of that entry. - If the current entry is a Nonce entry:
Fails if executed in the block context.
Fails if the entry is not a Nonce, an Issuance1 or a Spend1.
AMOUNT
Code | Stack Diagram | Cost |
---|---|---|
0xc3 | (∅ → amount) | 1; standard memory cost |
- If the current entry is an Issuance1, pushes
Value.Amount
. - If the current entry is a Spend1, pushes the
SpentOutput.Source.Value.Amount
of that entry. - If the current entry is a Nonce entry:
Fails if executed in the block context.
Fails if the entry is not a Nonce, an Issuance1 or a Spend1.
PROGRAM
Code | Stack Diagram | Cost |
---|---|---|
0xc4 | (∅ → program) | 1; standard memory cost |
Pushes a program based on a type of current entry and the context:
Entry Type | Program |
---|---|
Block header | Current consensus program being executed (specified in the previous block header) |
Nonce | Nonce program |
Issuance1 | Issuance program for the asset ID |
Spend1 | Control program of the output being spent |
Mux1 | Mux program |
MINTIME
Code | Stack Diagram | Cost |
---|---|---|
0xc5 | (∅ → timestamp) | 1; standard memory cost |
Pushes the transaction header mintime in milliseconds on the data stack. If the value is greater than 263–1, pushes 263–1 (encoded as VM number 0xffffffffffffff7f).
Fails if executed in the block context.
MAXTIME
Code | Stack Diagram | Cost |
---|---|---|
0xc6 | (∅ → timestamp) | 1; standard memory cost |
Pushes the transaction header maxtime in milliseconds on the data stack. If the value is zero or greater than 263–1, pushes 263–1 (encoded as VM number 0xffffffffffffff7f).
Fails if executed in the block context.
TXDATA
Code | Stack Diagram | Cost |
---|---|---|
0xc7 | (∅ → string32) | 1; standard memory cost |
Pushes the transaction’s data string as stored in the transaction header.
Fails if executed in the block context.
ENTRYDATA
Code | Stack Diagram | Cost |
---|---|---|
0xc8 | (∅ → string32) | 1; standard memory cost |
Pushes the data string as stored in the current entry.
Fails if executed in the block context.
Fails if the current entry is not an issuance, a spend, an output or a retirement.
INDEX
Code | Stack Diagram | Cost |
---|---|---|
0xc9 | (∅ → index) | 1; standard memory cost |
Pushes the ValueDestination.position of the current entry on the data stack.
Fails if executed in the block context.
Fails if the current entry is not an issuance or a spend.
ENTRYID
Code | Stack Diagram | Cost |
---|---|---|
0xca | (∅ → entryid) | 1; standard memory cost |
Pushes the current entry ID on the data stack (e.g. a spend, an issuance or a nonce).
Fails if executed in the block context.
OUTPUTID
Code | Stack Diagram | Cost |
---|---|---|
0xcb | (∅ → outputid) | 1; standard memory cost |
Pushes the spent output ID on the data stack.
Fails if executed in the block context.
Fails if the current entry is not a spend.
NONCE
Code | Stack Diagram | Cost |
---|---|---|
0xcc | (∅ → nonce) | 1; standard memory cost |
Pushes the anchor ID of the issuance entry on the data stack.
Fails if executed in the block context.
Fails if the current entry is not an issuance.
NEXTPROGRAM
Code | Stack Diagram | Cost |
---|---|---|
0xcd | (∅ → program) | 1; standard memory cost |
Pushes the next consensus program specified in the current block header.
Fails if executed in the transaction context.
BLOCKTIME
Code | Stack Diagram | Cost |
---|---|---|
0xce | (∅ → timestamp) | 1; standard memory cost |
Pushes the block timestamp in milliseconds on the data stack.
Fails if executed in the transaction context.
Expansion opcodes
Code | Stack Diagram | Cost |
---|---|---|
0x50, 0x61, 0x62, 0x65, 0x66, 0x67, 0x68, 0x8a, 0x8d, 0x8e, 0xa6, 0xa7, 0xa9, 0xab, 0xb0..0xbf, 0xcf, 0xd0..0xff | (∅ → ∅) | 1 |
The unassigned codes are reserved for future expansion.
If the expansion flag is on, these opcodes have no effect on the state of the VM except from reducing run limit by 1 and incrementing the program counter.
If the expansion flag is off, these opcodes immediately fail the program when encountered during execution.