ToolszkEVMArchitectureProving system

Introduction

The **zkEVM prover** is a software component with which the zkEVM generates proofs that attest to correct execution of programs given a specific set of inputs.

The zkEVM prover is a software component with which the zkEVM generates proofs that attest to correct execution of programs given a specific set of inputs.

While the process of generating a proof is resource-intensive, the time required to verify the proof is significantly shorter, enabling verification to be carried out by a smart contract.

On a high level, the prover takes the last batch and the current state as inputs in order to calculate the new state, together with a proof that attests to the computational integrity of the state transition.

The figure below depicts a typical state transition (SiL2xSi+1L2x)\big(S_`{i}`^`{L2_x}` \to S_{i+1}^`{L2_x}`\big),

  • Taking as inputs, a batch Batchi\mathtt{Batch}_i and the current L2 state SiL2xS_`{i}`^`{L2_x}`.
  • And the output as a new L2 state Si+1L2xS_{i+1}^`{L2_x}`, together with a proof πi+1\pi_{i+1}.

Figure: Input state and batch, output new state and proof

The initial step to produce a proof involves creation of an execution matrix, which is a matrix that records all intermediate computations constituting a larger computation. Such a matrix is also called an execution trace.

This larger computation can be thought of as the state transition function, while the smaller intermediate computations are like the zkEVM instructions or opcodes.

As we will later on see, it may take one or more zkEVM opcodes to implement a single EVM opcode.

This indicates the lack of a strict one-to-one correspondence between EVM opcodes and the Polygon zkEVM's.

Typical execution matrix

Unless otherwise stated, we use a matrix with three columns; A\texttt{A}, B\texttt{B} and C\texttt{C}.

Furthermore, suppose the number of rows is bounded by some constant NN, which we will call length of the execution trace.

The columns of an execution trace are often called registers. So, the terms "column" and "register" are used interchangeably in this document.

We depict an execution trace of length NN, having three registers A\texttt{A}, B\texttt{B} and C\texttt{C}, in the figure below.

 A  B  C a0b0c0a1b1c1aNbNcN\begin{aligned} \begin{array}{|c|c|c|c|c|}\hline \bf{\texttt{ A }} & \bf{\texttt{ B }} & \bf{\texttt{ C }}\\ \hline a_0 & b_0 & c_0 \\ \hline a_1 & b_1 & c_1 \\ \hline \dots & \dots & \dots \\ \hline a_N & b_N & c_N \\ \hline \end{array} \end{aligned}

A toy example (Execution matrix)

Suppose we are given a set of three input values, x:=(x0,x1,x2)x := (x_0, x_1, x_2), and we want to use an execution trace to model the following computation:

[(x0+x1)4]x2[(x_0 +x_1)·4]·x_2

Let us also suppose that the only available instructions (or operations) are those described below:

  1. Copy inputs into cells of the execution trace.

  2. ADD\texttt{ADD} instruction: Add two values in cells on the same row, and leave the result in the first cell of the next row.

  3. TIMES4\texttt{TIMES4} instruction: Multiply a given value by a constant, and leave the result in the first cell of the next row.

  4. MUL\texttt{MUL} instruction: Multiply two values in cells on the same row, and leave the result in the first cell of the next row.

Let’s provide a specific example by setting the input xx to x:=(1,2,5)x := (1, 2, 5).

Substituting the input values in the given computation yields:

[(x0+x1)4]x2=[(1+2)4]5=60[(x0 +x1)·4]·x2 =[(1+2)·4]·5=60

The corresponding execution trace, using only the above-mentioned operations, is as follows:

Figure:_

Let’s take a step-by-step walk-through the above execution trace:

  1. First of all, we use the instruction that copies the inputs 11 and 22 into the columns A\texttt{A} and B\texttt{B}, respectively. And then invoke the ADD\texttt{ADD} instruction.
  2. After executing the ADD\texttt{ADD} instruction, the second row of register A\texttt{A} now holds the sum of 11 and 22, that is the value 33. At this point we utilize the TIMES4\texttt{TIMES4} instruction to obtain 34=123 \cdot 4 = 12, and place it in the first cell of row 3.
  3. Now, with 1212 in the third row of register A\texttt{A}, we proceed to copy the third input, 55, into register B\texttt{B}. Then the MUL\texttt{MUL} instruction is invoked to multiply the current two values in row 3. (viz. 1212 and 55). The resulting outcome (which is 6060) of the MUL\texttt{MUL} instruction is placed in the first cell of row 4.
  4. Consequently, this last outcome 6060 is in fact the final output for the entire computation.

Observe that we have only used the available instructions as proposed in our scenario.

Notice that for a specific computation, and except for the entries in the matrix, the shape of the execution matrix remains the same irrespective of the variable input values x=(x0,x1,x2)x = (x_0, x_1, x_2).

For example, if x=(5,3,2)x = (5, 3, 2) for the same program, the resulting execution matrix is as follows:

Figure: _

However, if we examine the columns in the above execution trace, we can identify two distinct types of columns:

  • Witness columns: Values in these columns depend on the input values. They change whenever different input values are used. In the above example, columns A\texttt{A} and B\texttt{B} are witness columns.
  • Fixed columns: Values in these columns remain unaffected by changes in the input values. In the above example, column C\texttt{C} is a fixed column, and it is only used to store the constant 44.

In each case of the above example, the constant 44 is used in the second step of the computation, when the TIMES4\texttt{TIMES4} instruction is invoked.

Edit on GitHub

Last updated on