Skip to main content

Input / Output Operations

Miden assembly provides a set of instructions for moving data between the stack and several other sources. These sources include:

  • Program code: values to be moved onto the stack can be hard-coded in a program's source code.
  • Environment: values can be moved onto the stack from environment variables. Currently, the available environment variables are stack_depth, which holds the current depth of the stack, and local_address, which stores absolute addresses of local variables. In the future, other environment variables may be added.
  • Advice stack: values can be moved onto the stack from the advice provider by popping them from the advice stack. There is no limit on the number of values in the advice stack.
  • Memory: values can be moved between the stack and random-access memory. The memory is word-addressable, meaning, four elements are located at each address, and we can read and write elements to/from memory in batches of four. Memory can be accessed via absolute memory references (i.e., via memory addresses) as well as via local procedure references (i.e., local index). The latter approach ensures that a procedure does not access locals of another procedure.

In the future several other sources such as storage and logs may be added.

Constant inputs

InstructionStack_inputStack_outputNotes
push.a
- (1-2 cycles)
push.a.b
push.a.b.c...
[ ... ][a, ... ]
[b, a, ... ]
[c, b, a, ... ]
Pushes values aa, bb, cc etc. onto the stack. Up to 1616 values can be specified. All values must be valid field elements in decimal (e.g., 123123) or hexadecimal (e.g., 0x7b0x7b) representation.

When specifying values in hexadecimal format, it is possible to omit the periods between individual values as long as total number of specified bytes is a multiple of 88. That is, the following are semantically equivalent:

push.0x1234.0xabcd
push.0x0000000000001234000000000000abcd

In both case the values must still encode valid field elements.

Environment inputs

InstructionStack_inputStack_outputNotes
sdepth
- (1 cycle)
[ ... ][d, ... ]dstack.depth()d \leftarrow stack.depth()
Pushes the current depth of the stack onto the stack.
caller
- (1 cycle)
[ A, b, ... ][H, b, ... ]Hcontext.fn_hash()H \leftarrow context.fn\_hash()
Overwrites the top four stack items with the hash of a function which initiated the current SYSCALL.
Executing this instruction outside of SYSCALL context will fail.
locaddr.i
- (2 cycles)
[ ... ][a, ... ]aaddress_of(i)a \leftarrow address\_of(i)
Pushes the absolute memory address of local memory at index ii onto the stack.
clk
- (1 cycle)
[ ... ][t, ... ]tclock_value()t \leftarrow clock\_value()
Pushes the current value of the clock cycle counter onto the stack.

Non-deterministic inputs

InstructionStack_inputStack_outputNotes
adv_push.n
- (n cycles)
[ ... ][a, ... ]astack.pop()a \leftarrow stack.pop()
Pops nn values from the advice stack and pushes them onto the operand stack. Valid for n{1,...,16}n \in \{1, ..., 16\}.
Fails if the advice stack has fewer than nn values.
adv_loadw
- (1 cycle)
[0, 0, 0, 0, ... ][A, ... ]Astack.pop(4)A \leftarrow stack.pop(4)
Pop the next word (4 elements) from the advice stack and overwrites the first word of the operand stack (4 elements) with them.
Fails if the advice stack has fewer than 44 values.
adv_pipe
- (2 cycles)
[S2, S1, S0, a, ... ][T2, T1, T0, b, ... ][T0,T1,T2]permute(S0,stack.pop(4),stack.pop(4))[T_0, T_1, T_2] \leftarrow permute(S_0, stack.pop(4), stack.pop(4))
ba+2b \leftarrow a + 2
Pops the next two words (8 elements) from the advice stack, inserts them into memory at address aa sequentially, overwrites these top 8 elements onto the operand stack, and performs a Rescue Prime Optimized permutation to the top 12 elements of the operand stack. At the end of the operation, the address is incremented by 22.
Fails if the advice stack has fewer than 88 values.

Note: The opcodes above always push data onto the operand stack so that the first element is placed deepest in the stack. For example, if the data on the stack is a,b,c,d and you use the opcode adv_push.4, the data will be d,c,b,a on your stack. This is also the behavior of the other opcodes.

Random access memory

As mentioned above, there are two ways to access memory in Miden VM. The first way is via memory addresses using the instructions listed below. The addresses are absolute - i.e., they don't depend on the procedure context. Memory addresses can be in the range [0,232)[0, 2^{32}).

Memory is guaranteed to be initialized to zeros. Thus, when reading from memory address which hasn't been written to previously, zero elements will be returned.

InstructionStack_inputStack_outputNotes
mem_load
- (1 cycle)
mem_load.a
- (2 cycles)
[a, ... ][v, ... ]vmem[a][0]v \leftarrow mem[a][0]
Reads a word (4 elements) from memory at address a, and pushes the first element of the word onto the stack. If aa is provided via the stack, it is removed from the stack first.
Fails if a232a \ge 2^{32}
mem_loadw
- (1 cycle)
mem_loadw.a
- (2 cycles)
[a, 0, 0, 0, 0, ... ][A, ... ]Amem[a]A \leftarrow mem[a]
Reads a word from memory at address aa and overwrites top four stack elements with it. If aa is provided via the stack, it is removed from the stack first.
Fails if a232a \ge 2^{32}
mem_store
- (2 cycles)
mem_store.a
- (3-4 cycles)
[a, v, ... ][ ... ]vmem[a][0]v \rightarrow mem[a][0]
Pops the top element off the stack and stores it as the first element of the word in memory at address aa. All other elements of the word are not affected. If aa is provided via the stack, it is removed from the stack first.
Fails if a232a \ge 2^{32}
mem_storew
- (1 cycle)
mem_storew.a
- (2-3 cycles)
[a, A, ... ][A, ... ]Amem[a]A \rightarrow mem[a]
Stores the top four elements of the stack in memory at address aa. If aa is provided via the stack, it is removed from the stack first.
Fails if a232a \ge 2^{32}
mem_stream
- (2 cycles)
[S2, S1, S0, a, ...][T2, T1, T0, b, ...][T0,T1,T2]permute(S0,mem[a],mem[a+1])[T_0, T_1, T_2] \leftarrow permute(S_0, mem[a], mem[a+1])
ba+2b \leftarrow a + 2
Loads two words from memory starting at the address aa, overwrites the top 8 elements of the stack with them, and applies Rescue Prime Optimized permutation to the top 12 elements of the stack. At the end of the operation the address is incremented by 22.

The second way to access memory is via procedure locals using the instructions listed below. These instructions are available only in procedure context. The number of locals available to a given procedure must be specified at procedure declaration time, and trying to access more locals than was declared will result in a compile-time error. The number of locals per procedure is not limited, but the total number of locals available to all procedures at runtime must be smaller than 2322^{32}.

InstructionStack_inputStack_outputNotes
loc_load.i
- (3-4 cycles)
[ ... ][v, ... ]vlocal[i][0]v \leftarrow local[i][0]
Reads a word (4 elements) from local memory at index i, and pushes the first element of the word onto the stack.
loc_loadw.i
- (3-4 cycles)
[0, 0, 0, 0, ... ][A, ... ]Alocal[i]A \leftarrow local[i]
Reads a word from local memory at index ii and overwrites top four stack elements with it.
loc_store.i
- (4-5 cycles)
[v, ... ][ ... ]vlocal[i][0]v \rightarrow local[i][0]
Pops the top element off the stack and stores it as the first element of the word in local memory at index ii. All other elements of the word are not affected.
loc_storew.i
- (3-4 cycles)
[A, ... ][A, ... ]Alocal[i]A \rightarrow local[i]
Stores the top four elements of the stack in local memory at index ii.

Unlike regular memory, procedure locals are not guaranteed to be initialized to zeros. Thus, when working with locals, one must assume that before a local memory address has been written to, it contains "garbage".

Internally in the VM, procedure locals are stored at memory offset stating at 2302^{30}. Thus, every procedure local has an absolute address in regular memory. The locaddr.i instruction is provided specifically to map an index of a procedure's local to an absolute address so that it can be passed to downstream procedures, when needed.