Instructions

Most instructions are contained within a single, parameterless machine word.

Some instructions take a machine word as argument and are so considered double-word instructions. They are recognized by the form “instr + arg”.

Regarding Opcodes

An instruction's operation code, or opcode, is the machine word uniquely identifying the instruction. For reasons of efficient arithmetization, certain properties of the instruction are encoded in the opcode. Concretely, interpreting the field element in standard representation:

  • for all double-word instructions, the least significant bit is 1.
  • for all instructions shrinking the operational stack, the second-to-least significant bit is 1.
  • for all u32 instructions , the third-to-least significant bit is 1.

The first property is used by instruction skiz. The second property helps with proving consistency of the Op Stack. The third property allows efficient arithmetization of the running product for the Permutation Argument between Processor Table and U32 Table.

Op Stack Manipulation

InstructionOpcodeold op stacknew op stackDescription
pop + n3e.g., _ c b ae.g., _Pops the n top elements from the stack. 1 ⩽ n ⩽ 5
push + a1__ aPushes a onto the stack.
divine + n9e.g., _e.g., _ b aPushes n non-deterministic elements a to the stack. Interface for secret input. 1 ⩽ n ⩽ 5
dup + i17e.g., _ e d c b ae.g., _ e d c b a dDuplicates the element i positions away from the top. 0 ⩽ i < 16
swap + i25e.g., _ e d c b ae.g., _ e a c b dSwaps the ith stack element with the top of the stack. 0 < i < 16

Instruction divine n (together with divine_sibling) make Triton a virtual machine that can execute non-deterministic programs. As programs go, this concept is somewhat unusual and benefits from additional explanation. The name of the instruction is the verb (not the adjective) meaning “to discover by intuition or insight.”

From the perspective of the program, the instruction divine n makes some n elements magically appear on the stack. It is not at all specified what those elements are, but generally speaking, they have to be exactly correct, else execution fails. Hence, from the perspective of the program, it just non-deterministically guesses the correct values in a moment of divine clarity.

Looking at the entire system, consisting of the VM, the program, and all inputs – both public and secret – execution is deterministic: the divined values were supplied as and are read from secret input.

Control Flow

InstructionOpcodeold op stacknew op stackold ipnew ipold jump stacknew jump stackDescription
halt0__ipip+1__Solves the halting problem (if the instruction is reached). Indicates graceful shutdown of the VM.
nop8__ipip+1__Do nothing
skiz2_ a_ipip+s__Skip next instruction if a is zero. s ∈ {1, 2, 3} depends on a and whether the next instruction takes an argument.
call + d33__ipd__ (ip+2, d)Push (ip+2,d) to the jump stack, and jump to absolute address d
return16__ipo_ (o, d)_Pop one pair off the jump stack and jump to that pair's return address (which is the first element).
recurse24__ipd_ (o, d)_ (o, d)Peek at the top pair of the jump stack and jump to that pair's destination address (which is the second element).
assert10_ a_ipip+1__Pops a if a == 1, else crashes the virtual machine.

Memory Access

InstructionOpcodeold op stacknew op stackold RAMnew RAMDescription
read_mem + n41e.g., _ p+2e.g., _ v2 v1 v0 p-1[p: v0, p+1, v1, …][p: v0, p+1, v1, …]Reads consecutive values vi from RAM at address p and puts them onto the op stack. Decrements RAM pointer (st0) by n. 1 ⩽ n ⩽ 5
write_mem + n11e.g., _ v2 v1 v0 pe.g., _ p+3[][p: v0, p+1, v1, …]Writes op stack's n top-most values vi to RAM at the address p+i, popping the vi. Increments RAM pointer (st0) by n. 1 ⩽ n ⩽ 5

For the benefit of clarity, the effect of every possible argument is given below.

instructionold op stacknew op stackold RAMnew RAM
read_mem 1_ p_ a p-1[p: a][p: a]
read_mem 2_ p+1_ b a p-1[p: a, p+1: b][p: a, p+1: b]
read_mem 3_ p+2_ c b a p-1[p: a, p+1: b, p+2: c][p: a, p+1: b, p+2: c]
read_mem 4_ p+3_ d c b a p-1[p: a, p+1: b, p+2: c, p+3: d][p: a, p+1: b, p+2: c, p+3: d]
read_mem 5_ p+4_ e d c b a p-1[p: a, p+1: b, p+2: c, p+3: d, p+4: e][p: a, p+1: b, p+2: c, p+3: d, p+4: e]
write_mem 1_ a p_ p+1[][p: a]
write_mem 2_ b a p_ p+2[][p: a, p+1: b]
write_mem 3_ c b a p_ p+3[][p: a, p+1: b, p+2: c]
write_mem 4_ d c b a p_ p+4[][p: a, p+1: b, p+2: c, p+3: d]
write_mem 5_ e d c b a p_ p+5[][p: a, p+1: b, p+2: c, p+3: d, p+4: e]

Hashing

InstructionOpcodeold op stacknew op stackDescription
hash18_ jihgfedcba_ yxwvuHashes the stack's 10 top-most elements and puts their digest onto the stack, shrinking the stack by 5.
divine_sibling32_ i edcbae.g., _ (i div 2) edcba zyxwvHelps traversing a Merkle tree during authentication path verification. See extended description below.
assert_vector26_ edcba edcba_ edcbaAssert equality of st(i) to st(i+5) for 0 <= i < 4. Crashes the VM if any pair is unequal. Pops the 5 top-most elements.
sponge_init40__Initializes (resets) the Sponge's state. Must be the first Sponge instruction executed.
sponge_absorb34_ _jihgfedcba_Absorbs the stack's ten top-most elements into the Sponge state.
sponge_squeeze48__ zyxwvutsrqSqueezes the Sponge and pushes the 10 squeezed elements onto the stack.

The instruction hash works as follows. The stack's 10 top-most elements (jihgfedcba) are popped from the stack, reversed, and concatenated with six zeros, resulting in abcdefghij000000. The Tip5 permutation is applied to abcdefghij000000, resulting in αβγδεζηθικuvwxyz. The first five elements of this result, i.e., αβγδε, are reversed and pushed to the stack. For example, the old stack was _ jihgfedcba and the new stack is _ εδγβα.

The instruction divine_sibling works as follows. The 6th element of the stack i is taken as the node index for a Merkle tree that is claimed to include data whose digest is the content of stack registers st4 through st0, i.e., edcba. The sibling digest of edcba is zyxwv and is read from the input interface of secret data. The least-significant bit of i indicates whether edcba is the digest of a left leaf or a right leaf of the Merkle tree's base level. Depending on this least significant bit of i, divine_sibling either

  1. (i = 0 mod 2, i.e., current node is left sibling) lets edcba remain in registers st0 through st4 and puts zyxwv into registers st5 through st9, or
  2. (i = 1 mod 2, i.e., current node is right sibling) moves edcba into registers st5 through st9 and puts zyxwv into registers st0 through st4.

In either case, 6th register i is shifted by 1 bit to the right, i.e., the least-significant bit is dropped, and moved into the 11th register. In conjunction with instruction hash and assert_vector, the instruction divine_sibling allows to efficiently verify a Merkle authentication path.

The instructions sponge_init, sponge_absorb, and sponge_squeeze are the interface for using the Tip5 permutation in a Sponge construction. The capacity is never accessible to the program that's being executed by Triton VM. At any given time, at most one Sponge state exists. Only instruction sponge_init resets the state of the Sponge, and only the three Sponge instructions influence the Sponge's state. Notably, executing instruction hash does not modify the Sponge's state. When using the Sponge instructions, it is the programmer's responsibility to take care of proper input padding: Triton VM cannot know the number of elements that will be absorbed.

Base Field Arithmetic on Stack

InstructionOpcodeold op stacknew op stackDescription
add42_ b a_ cComputes the sum (c) of the top two elements of the stack (b and a) over the field.
mul50_ b a_ cComputes the product (c) of the top two elements of the stack (b and a) over the field.
invert56_ a_ bComputes the multiplicative inverse (over the field) of the top of the stack. Crashes the VM if the top of the stack is 0.
eq58_ b a_ (a == b)Tests the top two stack elements for equality.

Bitwise Arithmetic on Stack

InstructionOpcodeold op stacknew op stackDescription
split4_ a_ hi loDecomposes the top of the stack into the lower 32 bits and the upper 32 bits.
lt6_ b a_ a<b“Less than” of the stack's two top-most elements. Crashes the VM if a or b is not u32.
and14_ b a_ a&bBitwise and of the stack's two top-most elements. Crashes the VM if a or b is not u32.
xor22_ b a_ a^bBitwise exclusive or of the stack's two top-most elements. Crashes the VM if a or b is not u32.
log_2_floor12_ a_ ⌊log₂(a)⌋The number of bits in a minus 1, i.e., . Crashes the VM if a is 0 or not u32.
pow30_ e b_ b**eThe top of the stack to the power of the stack's runner up. Crashes the VM if exponent e is not u32.
div_mod20_ d n_ q rDivision with remainder of numerator n by denominator d. Guarantees the properties n == q·d + r and r < d. Crashes the VM if n or d is not u32 or if d is 0.
pop_count28_ a_ wComputes the hamming weight or “population count” of a. Crashes the VM if a is not u32.

Extension Field Arithmetic on Stack

InstructionOpcodeold op stacknew op stackDescription
xxadd66_ z y x b c a_ w v uAdds the two extension field elements encoded by field elements z y x and b c a.
xxmul74_ z y x b c a_ w v uMultiplies the two extension field elements encoded by field elements z y x and b c a.
xinvert64_ z y x_ w v uInverts the extension field element encoded by field elements z y x in-place. Crashes the VM if the extension field element is 0.
xbmul82_ z y x a_ w v uScalar multiplication of the extension field element encoded by field elements z y x with field element a. Overwrites z y x with the result.

Input/Output

InstructionOpcodeold op stacknew op stackDescription
read_io + n49e.g., _e.g., _ c b aReads n B-Field elements from standard input and pushes them to the stack. 1 ⩽ n ⩽ 5
write_io + n19e.g., _ c b ae.g., _Pops n elements from the stack and writes them to standard output. 1 ⩽ n ⩽ 5