fence
and ebreak
. The machine uses a modified Harvard architecture in which the program, data, and input-output memory segments are distinct and permissioned with respect to whether they can be read from, written to, or both.
std::process::exit(code: i32) -> !}
provided by most programming languages.
0x00-0x7F
so that prover integrations are able to identify the registers with those addresses should the prover need to consider the entire state of the machine to lie within a single address space.
0x80-0x83
and the second from 0x84-0x87
, which contain pointers to other memory locations for use by the runtime to manage input and output handling. These pointers existing in a well-known location for the runtime to access enables the zkVM to dynamically situate the input and output memory segments within the unified, linear architecture while still allowing the guest program easy access to their contents.
.rodata
segment). Before the zkVM executes the guest, this data must be loaded into a read-only segment of program memory, and after that remains unchanged during execution.
Additionally, the binary may contain read-write segments, such as the .bss
and .data
segments commonly used by programming languages to store global variables. Being writable, these segments must also be private over the course of the execution post-initialization. As such, the machine functionally treats these segments as a small part of the RAM that is non-contiguous with it, but with additional constraints to guarantee they are initialized as specified in the binary. In order to simplify management of the ‘dual-nature’ of these segments as both part of the program but also writeable, the zkVM keeps the program memory and data memory in the same address space during the first-pass tracing, but with distinct permissions for the writeable vs. read-only components. Those permissions are maintained in the unified address space of the linear memory model used in the second pass.
n
bytes prefaced by a four-byte (one 32-bit word) segment n
so that the guest program can determine the length of the input made available to it. To read the from the input the runtime invokes a custom instruction rin
. During the second tracing pass — which is the one proven — rin
is treated as a pseudoinstruction equivalent to lb
, and the offset is loaded from the first word of the well-known segment (addresses 0x80-0x83
in the unified address space of the linear memory model). During both tracing passes, the contents of the segment are read-only — the zkVM will halt if an attempt is made by the guest program to write to those memory segments.
wou
— interpreted on the second pass as sb
— and the offset is loaded from the second word of the well-known segment (addresses 0x84-0x87
in the unified address space of the linear memory model). Otherwise, the most significant difference is that the single-word exit code segment and the public output segment are write-only, rather than read-only. During the first tracing pass the public output segment can grow arbitrarily (up to addressing limits) to support additional written output. The length of the resultant output is then reserved ahead of time for the memory segment for the second and proven tracing pass.