diff --git a/evm/spec/instructions.tex b/evm/spec/instructions.tex index ea096982..d177d22a 100644 --- a/evm/spec/instructions.tex +++ b/evm/spec/instructions.tex @@ -1,8 +1,52 @@ \section{Privileged instructions} \label{privileged-instructions} -\begin{enumerate} - \item[0xFB.] \texttt{MLOAD\_GENERAL}. Returns - \item[0xFC.] \texttt{MSTORE\_GENERAL}. Returns - \item[TODO.] \texttt{STACK\_SIZE}. Returns +To ease and speed-up proving time, the zkEVM supports custom, privileged instructions that can only be executed by the kernel. +Any appearance of those privileged instructions in a contract bytecode for instance would result in an unprovable state. + +In what follows, we denote by $p_{BN}$ the characteristic of the BN254 curve base field, curve for which Ethereum supports the +ecAdd, ecMul and ecPairing precompiles. + +\begin{enumerate}[align=left] + \item[0x0C.] \texttt{ADDFP254}. Pops 2 elements from the stack interpreted as BN254 base field elements, and pushes their addition modulo $p_{BN}$ onto the stack. + + \item[0x0D.] \texttt{MULFP254}. Pops 2 elements from the stack interpreted as BN254 base field elements, and pushes their product modulo $p_{BN}$ onto the stack. + + \item[0x0E.] \texttt{SUBFP254}. Pops 2 elements from the stack interpreted as BN254 base field elements, and pushes their difference modulo $p_{BN}$ onto the stack. + This instruction behaves similarly to the SUB (0x03) opcode, in that we subtract the second element of the stack from the initial (top) one. + + \item[0x0F.] \texttt{SUBMOD}. Pops 3 elements from the stack, and pushes the modular difference of the first two elements of the stack by the third one. + It is similar to the SUB instruction, with an extra pop for the custom modulus. + + \item[0x21.] \texttt{KECCAK\_GENERAL}. Pops 4 elements (successively the context, segment, and offset portions of a Memory address, followed by a length $\ell$) + and pushes the hash of the memory portion starting at the constructed address and of length $\ell$. It is similar to KECCAK256 (0x20) instruction, but can be applied to + any memory section (i.e. even privileged ones). + + \item[0x49.] \texttt{PROVER\_INPUT}. Pushes a single prover input onto the stack. + + \item[0xC0-0xDF.] \texttt{MSTORE\_32BYTES}. Pops 4 elements from the stack (successively the context, segment, and offset portions of a Memory address, and then a value), and pushes + a new offset' onto the stack. The value is being decomposed into bytes and written to memory, starting from the reconstructed address. The new offset being pushed is computed as the + initial address offset + the length of the byte sequence being written to memory. Note that similarly to PUSH (0x60-0x7F) instructions there are 31 MSTORE\_32BYTES instructions, each + corresponding to a target byte length (length 0 is ignored, for the same reasons as MLOAD\_32BYTES, see below). Writing to memory an integer fitting in $n$ bytes with a length $\ell < n$ will + result in the integer being truncated. On the other hand, specifying a length $\ell$ greater than the byte size of the value being written will result in padding with zeroes. This + process is heavily used when resetting memory sections (by calling MSTORE\_32BYTES\_32 with the value 0). + + \item[0xF6.] \texttt{GET\_CONTEXT}. Pushes the current context onto the stack. The kernel always has context 0. + + \item[0xF7.] \texttt{SET\_CONTEXT}. Pops the top element of the stack and updates the current context to this value. It is usually used when calling another contract or precompile, + to distinguish the caller from the callee. + + \item[0xF8.] \texttt{MLOAD\_32BYTES}. Pops 4 elements from the stack (successively the context, segment, and offset portions of a Memory address, and then a length $\ell$), and pushes + a value onto the stack. The pushed value corresponds to the U256 integer read from the big-endian sequence of length $\ell$ from the memory address being reconstructed. Note that an + empty length is not valid, nor is a length greater than 32 (as a U256 consists in at most 32 bytes). Missing these conditions will result in an unverifiable proof. + + \item[0xF9.] \texttt{EXIT\_KERNEL}. Pops 1 element from the stack. This instruction is used at the end of a syscall, before proceeding to the rest of the execution logic. + The popped element, \textit{kexit\_info}, contains several informations like the current program counter, current gas used, and if we are in kernel (i.e. privileged) mode. + + \item[0xFB.] \texttt{MLOAD\_GENERAL}. Pops 3 elements (successively the context, segment, and offset portions of a Memory address), and pushes the value stored at this memory + address onto the stack. It can read any memory location, general (similarly to MLOAD (0x51) instruction) or privileged. + + \item[0xFC.] \texttt{MSTORE\_GENERAL}. Pops 4 elements (successively a value, then the context, segment, and offset portions of a Memory address), and writes the popped value from + the stack at the reconstructed address. It can write to any memory location, general (similarly to MSTORE (0x52) / MSTORE8 (0x53) instructions) or privileged. + \end{enumerate} diff --git a/evm/spec/zkevm.pdf b/evm/spec/zkevm.pdf index 6aaed5e3..3f957a0e 100644 Binary files a/evm/spec/zkevm.pdf and b/evm/spec/zkevm.pdf differ diff --git a/evm/spec/zkevm.tex b/evm/spec/zkevm.tex index 2927e7a5..71f944ef 100644 --- a/evm/spec/zkevm.tex +++ b/evm/spec/zkevm.tex @@ -8,6 +8,7 @@ \usepackage{makecell} \usepackage{mathtools} \usepackage{tabularx} +\usepackage{enumitem} \usepackage[textwidth=1.25in]{todonotes} % Scale for DRAFT watermark.