Skip to main content
Version: 0.11 (stable)

Cryptographic operations

In this section we describe the AIR constraints for Miden VM cryptographic operations.

Cryptographic operations in Miden VM are performed by the Hash chiplet. Communication between the stack and the hash chiplet is accomplished via the chiplet bus bchipb_{chip}. To make requests to and to read results from the chiplet bus we need to divide its current value by the value representing the request.

Thus, to describe AIR constraints for the cryptographic operations, we need to define how to compute these input and output values within the stack. We do this in the following sections.

HPERM

The HPERM operation applies Rescue Prime Optimized permutation to the top 1212 elements of the stack. The stack is assumed to be arranged so that the 88 elements of the rate are at the top of the stack. The capacity word follows, with the number of elements to be hashed at the deepest position in stack. The diagram below illustrates this graphically.

hperm

In the above, rr (located in the helper register h0h_0) is the row address from the hash chiplet set by the prover non-deterministically.

For the HPERM operation, we define input and output values as follows:

vinput=α0+α1oplinhash+α2h0+j=011(αj+4s11j)v_{input} = \alpha_0 + \alpha_1 \cdot op_{linhash} + \alpha_2 \cdot h_0 + \sum_{j=0}^{11} (\alpha_{j+4} \cdot s_{11-j}) voutput=α0+α1opretstate+α2(h0+7)+j=011(αj+4s11j)v_{output} = \alpha_0 + \alpha_1 \cdot op_{retstate} + \alpha_2 \cdot (h_0 + 7) + \sum_{j=0}^{11} (\alpha_{j+4} \cdot s_{11-j}')

In the above, oplinhashop_{linhash} and opretstateop_{retstate} are the unique operation labels for initiating a linear hash and reading the full state of the hasher respectively. Also note that the term for α3\alpha_3 is missing from the above expressions because for Rescue Prime Optimized permutation computation the index column is expected to be set to 00.

Using the above values, we can describe the constraint for the chiplet bus column as follows:

bchipvinputvoutput=bchip | degree=3b_{chip}' \cdot v_{input} \cdot v_{output} = b_{chip} \text{ | degree} = 3

The above constraint enforces that the specified input and output rows must be present in the trace of the hash chiplet, and that they must be exactly 77 rows apart.

The effect of this operation on the rest of the stack is:

  • No change starting from position 1212.

MPVERIFY

The MPVERIFY operation verifies that a Merkle path from the specified node resolves to the specified root. This operation can be used to prove that the prover knows a path in the specified Merkle tree which starts with the specified node.

Prior to the operation, the stack is expected to be arranged as follows (from the top):

  • Value of the node, 4 elements (VV in the below image)
  • Depth of the path, 1 element (dd in the below image)
  • Index of the node, 1 element (ii in the below image)
  • Root of the tree, 4 elements (RR in the below image)

The Merkle path itself is expected to be provided by the prover non-deterministically (via the advice provider). If the prover is not able to provide the required path, the operation fails. Otherwise, the state of the stack does not change. The diagram below illustrates this graphically.

mpverify

In the above, rr (located in the helper register h0h_0) is the row address from the hash chiplet set by the prover non-deterministically.

For the MPVERIFY operation, we define input and output values as follows:

vinput=α0+α1opmpver+α2h0+α3s5+j=03αj+8s3jv_{input} = \alpha_0 + \alpha_1 \cdot op_{mpver} + \alpha_2 \cdot h_0 + \alpha_3 \cdot s_5 + \sum_{j=0}^3 \alpha_{j+8} \cdot s_{3 - j} voutput=α0+α1oprethash+α2(h0+8s41)+j=03αj+8s9jv_{output} = \alpha_0 + \alpha_1 \cdot op_{rethash} + \alpha_2 \cdot (h_0 + 8 \cdot s_4 - 1) + \sum_{j=0}^3\alpha_{j + 8} \cdot s_{9 - j}

In the above, opmpverop_{mpver} and oprethashop_{rethash} are the unique operation labels for initiating a Merkle path verification computation and reading the hash result respectively. The sum expression for inputs computes the value of the leaf node, while the sum expression for the output computes the value of the tree root.

Using the above values, we can describe the constraint for the chiplet bus column as follows:

bchipvinputvoutput=bchip | degree=3b_{chip}' \cdot v_{input} \cdot v_{output} = b_{chip} \text{ | degree} = 3

The above constraint enforces that the specified input and output rows must be present in the trace of the hash chiplet, and that they must be exactly 8d18 \cdot d - 1 rows apart, where dd is the depth of the node.

The effect of this operation on the rest of the stack is:

  • No change starting from position 00.

MRUPDATE

The MRUPDATE operation computes a new root of a Merkle tree where a node at the specified position is updated to the specified value.

The stack is expected to be arranged as follows (from the top):

  • old value of the node, 4 element (VV in the below image)
  • depth of the node, 1 element (dd in the below image)
  • index of the node, 1 element (ii in the below image)
  • current root of the tree, 4 elements (RR in the below image)
  • new value of the node, 4 element (NVNV in the below image)

The Merkle path for the node is expected to be provided by the prover non-deterministically (via merkle sets). At the end of the operation, the old node value is replaced with the new root value computed based on the provided path. Everything else on the stack remains the same. The diagram below illustrates this graphically.

mrupdate

In the above, rr (located in the helper register h0h_0) is the row address from the hash chiplet set by the prover non-deterministically.

For the MRUPDATE operation, we define input and output values as follows:

vinputold=α0+α1opmruold+α2h0+α3s5+j=03αj+8s3jv_{inputold} = \alpha_0 + \alpha_1 \cdot op_{mruold} + \alpha_2 \cdot h_0 + \alpha_3 \cdot s_5 + \sum_{j=0}^3\alpha_{j + 8} \cdot s_{3 - j} voutputold=α0+α1oprethash+α2(h0+8s41)+j=03αj+8s9jv_{outputold} = \alpha_0 + \alpha_1 \cdot op_{rethash} + \alpha_2 \cdot (h_0 + 8 \cdot s_4 - 1) + \sum_{j=0}^3\alpha_{j + 8} \cdot s_{9 - j} vinputnew=α0+α1opmrunew+α2(h0+8s4)+α3s5+j=03αj+8s13jv_{inputnew} = \alpha_0 + \alpha_1 \cdot op_{mrunew} + \alpha_2 \cdot (h_0 + 8 \cdot s_4) + \alpha_3 \cdot s_5 + \sum_{j=0}^3\alpha_{j + 8} \cdot s_{13 - j} voutputnew=α0+α1oprethash+α2(h0+28s41)+j=03αj+8s3jv_{outputnew} = \alpha_0 + \alpha_1 \cdot op_{rethash} + \alpha_2 \cdot (h_0 + 2 \cdot 8 \cdot s_4 - 1) + \sum_{j=0}^3\alpha_{j + 8} \cdot s_{3 - j}'

In the above, the first two expressions correspond to inputs and outputs for verifying the Merkle path between the old node value and the old tree root, while the last two expressions correspond to inputs and outputs for verifying the Merkle path between the new node value and the new tree root. The hash chiplet ensures the same set of sibling nodes are used in both of these computations.

The opmruoldop_{mruold}, opmrunewop_{mrunew}, and oprethashop_{rethash} are the unique operation labels used by the above computations.

bchipvinputoldvoutputoldvinputnewvoutputnew=bchip | degree=5b_{chip}' \cdot v_{inputold} \cdot v_{outputold} \cdot v_{inputnew} \cdot v_{outputnew} = b_{chip} \text{ | degree} = 5

The above constraint enforces that the specified input and output rows for both, the old and the new node/root combinations, must be present in the trace of the hash chiplet, and that they must be exactly 8d18 \cdot d - 1 rows apart, where dd is the depth of the node. It also ensures that the computation for the old node/root combination is immediately followed by the computation for the new node/root combination.

The effect of this operation on the rest of the stack is:

  • No change for positions starting from 44.

FRIE2F4

The FRIE2F4 operation performs FRI layer folding by a factor of 4 for FRI protocol executed in a degree 2 extension of the base field. It also performs several computations needed for checking correctness of the folding from the previous layer as well as simplifying folding of the next FRI layer.

The stack for the operation is expected to be arranged as follows:

  • The first 88 stack elements contain 44 query points to be folded. Each point is represented by two field elements because points to be folded are in the extension field. We denote these points as q0=(v0,v1)q_0 = (v_0, v_1), q1=(v2,v3)q_1 = (v_2, v_3), q2=(v4,v5)q_2 = (v_4, v_5), q3=(v6,v7)q_3 = (v_6, v_7).
  • The next element f_posf\_pos is the query position in the folded domain. It can be computed as posmodnpos \mod n, where pospos is the position in the source domain, and nn is size of the folded domain.
  • The next element d_segd\_seg is a value indicating domain segment from which the position in the original domain was folded. It can be computed as posn\lfloor \frac{pos}{n} \rfloor. Since the size of the source domain is always 44 times bigger than the size of the folded domain, possible domain segment values can be 00, 11, 22, or 33.
  • The next element poepoe is a power of initial domain generator which aids in a computation of the domain point xx.
  • The next two elements contain the result of the previous layer folding - a single element in the extension field denoted as pe=(pe0,pe1)pe = (pe_0, pe_1).
  • The next two elements specify a random verifier challenge α\alpha for the current layer defined as α=(a0,a1)\alpha = (a_0, a_1).
  • The last element on the top of the stack (cptrcptr) is expected to be a memory address of the layer currently being folded.

The diagram below illustrates stack transition for FRIE2F4 operation.

frie2f4

At the high-level, the operation does the following:

  • Computes the domain value xx based on values of poepoe and d_segd\_seg.
  • Using xx and α\alpha, folds the query values q0,...,q3q_0, ..., q_3 into a single value rr.
  • Compares the previously folded value pepe to the appropriate value of q0,...,q3q_0, ..., q_3 to verify that the folding of the previous layer was done correctly.
  • Computes the new value of poepoe as poe=poe4poe' = poe^4 (this is done in two steps to keep the constraint degree low).
  • Increments the layer address pointer by 88.
  • Shifts the stack by 11 to the left. This moves an element from the stack overflow table into the last position on the stack top.

To keep the degree of the constraints low, a number of intermediate values are used. Specifically, the operation relies on all 66 helper registers, and also uses the first 1010 elements of the stack at the next state for degree reduction purposes. Thus, once the operation has been executed, the top 1010 elements of the stack can be considered to be "garbage".

TODO: add detailed constraint descriptions. See discussion here.

The effect on the rest of the stack is:

  • Left shift starting from position 1616.

HORNERBASE

The HORNERBASE operation performs 88 steps of the Horner method for evaluating a polynomial with coefficients over the base field at a point in the quadratic extension field. More precisely, it performs the following update to the accumulator on the stack tmp=(((accα+a7)α+a6)α+a5)α+a4\mathsf{tmp} = (((\mathsf{acc} \cdot \alpha + a_7) \cdot \alpha + a_6) \cdot \alpha + a_5) \cdot \alpha + a_4

acc=(((tmpα+a3)α+a2)α+a1)α+a0\mathsf{acc}^{'} = (((\mathsf{tmp} \cdot \alpha + a_3) \cdot \alpha + a_2) \cdot \alpha + a_1) \cdot \alpha + a_0 where aia_i are the coefficients of the polynomial, α\alpha the evaluation point, acc\mathsf{acc} the current accumulator value, acc\mathsf{acc}^{'} the updated accumulator value, and tmp\mathsf{tmp} is a helper variable used for constraint degree reduction.

The stack for the operation is expected to be arranged as follows:

  • The first 88 stack elements are the 88 base field elements a0,,a7a_0,\cdots , a_7 representing the current 8-element batch of coefficients for the polynomial being evaluated.
  • The next 55 stack elements are irrelevant for the operation and unaffected by it.
  • The next stack element contains the value of the memory pointer alpha_ptr to the evaluation point α\alpha. The word address containing α=(α0,α1)\alpha = (\alpha_0, \alpha_1) is expected to have layout [α0,α1,k0,k1][\alpha_0, \alpha_1, k_0, k_1] where [k0,k1][k_0, k_1] is the second half of the memory word containing α\alpha. Note that, in the context of the above expressions, we only care about the first half i.e., [α0,α1][\alpha_0, \alpha_1], but providing the second half of the word in order to be able to do a one word memory read is more optimal than doing two element memory reads.
  • The next 22 stack elements contain the value of the current accumulator acc=(acc0,acc1)\textsf{acc} = (\textsf{acc}_0, \textsf{acc}_1).

The diagram below illustrates the stack transition for HORNERBASE operation.

horner_eval_base

After calling the operation:

  • Helper registers hih_i will contain the values [α0,α1,k0,k1,tmp0,tmp1][\alpha_0, \alpha_1, k_0, k_1, \mathsf{tmp}_0, \mathsf{tmp}_1].
  • Stack elements 1414 and 1515 will contain the value of the updated accumulator i.e., acc\mathsf{acc}^{'}.

More specifically, the stack transition for this operation must satisfy the following constraints:

tmp0=acc0α048acc1α03α112acc0α02α1212acc1α02α128acc0α0α13+8acc1α0α13+2acc0α14+6acc1α14+s7α036s7α0α122s7α13+s6α022s6α12+s5α0+s4 | degree=5\begin{align*} \mathsf{tmp}_0 &= \mathsf{acc}_0 \cdot \alpha_0^4 - 8 \cdot \mathsf{acc}_1 \cdot \alpha_0^3 \cdot \alpha_1 - 12 \cdot \mathsf{acc}_0 \cdot \alpha_0^2 \cdot \alpha_1^2 &- 12 \cdot \mathsf{acc}_1 \cdot \alpha_0^2 \cdot \alpha_1^2 - 8 \cdot \mathsf{acc}_0 \cdot \alpha_0 \cdot \alpha_1^3 &+ 8 \cdot \mathsf{acc}_1\cdot\alpha_0\cdot\alpha_1^3 + 2\cdot\mathsf{acc}_0\cdot\alpha_1^4 &+ 6\cdot\mathsf{acc}_1\cdot\alpha_1^4 + s_7\cdot\alpha_0^3 - 6 \cdot s_7\cdot\alpha_0\cdot\alpha_1^2 &- 2 \cdot s_7\cdot\alpha_1^3 + s_6\cdot\alpha_0^2 - 2\cdot s_6\cdot\alpha_1^2 + s_5\cdot\alpha_0 + s_4 \text{ | degree} = 5 \end{align*} tmp1=acc1α04+4acc0α03α1+4acc1α03α1+6acc0α02α126acc1α02α124acc0α0α1312acc1α0α133acc0α14acc1α14+3s7α02α1+3s7α0α12s7α13+2s6α0α1+s6α12+s5α1 | degree=5\begin{align*} \mathsf{tmp}_1 &= \mathsf{acc}_1 \cdot \alpha_0^4 + 4 \cdot \mathsf{acc}_0 \cdot \alpha_0^3 \cdot \alpha_1 + 4 \cdot \mathsf{acc}_1 \cdot \alpha_0^3 \cdot \alpha_1 &+ 6 \cdot \mathsf{acc}_0 \cdot \alpha_0^2 \cdot \alpha_1^2 - 6 \cdot \mathsf{acc}_1 \cdot \alpha_0^2 \cdot \alpha_1^2 &- 4 \cdot \mathsf{acc}_0 \cdot \alpha_0\cdot\alpha_1^3 - 12 \cdot \mathsf{acc}_1 \cdot \alpha_0 \cdot \alpha_1^3 & - 3 \cdot\mathsf{acc}_0 \cdot \alpha_1^4 - \mathsf{acc}_1 \cdot \alpha_1^4 + 3 \cdot s_7 \cdot \alpha_0^2\cdot\alpha_1 &+ 3 \cdot s_7 \cdot \alpha_0\cdot\alpha_1^2 - s_7 \cdot\alpha_1^3 + 2\cdot s_6\cdot\alpha_0\cdot\alpha_1 + s_6\cdot\alpha_1^2 + s_5\cdot\alpha_1 \text{ | degree} = 5 \end{align*} acc0=tmp0α048tmp1α03α112tmp0α02α1212tmp1α02α128tmp0α0α13+8tmp1α0α13+2tmp0α14+6tmp1α14+s3α036s3α0α122s3α13+s2α022s2α12+s1α0+s0 | degree=5\begin{align*} \mathsf{acc}_0^{'} &= \mathsf{tmp}_0\cdot\alpha_0^4 - 8 \cdot\mathsf{tmp}_1\cdot\alpha_0^3\cdot\alpha_1 - 12 \cdot\mathsf{tmp}_0\cdot\alpha_0^2\cdot\alpha_1^2 &- 12\cdot\mathsf{tmp}_1\cdot\alpha_0^2\cdot\alpha_1^2 - 8\cdot\mathsf{tmp}_0\cdot\alpha_0\cdot\alpha_1^3 + 8\cdot\mathsf{tmp}_1\cdot\alpha_0\cdot\alpha_1^3 &+ 2\cdot\mathsf{tmp}_0\cdot\alpha_1^4 + 6\cdot\mathsf{tmp}_1\cdot\alpha_1^4 + s_3\cdot\alpha_0^3 - 6\cdot s_3\cdot\alpha_0\cdot\alpha_1^2 &- 2\cdot s_3\cdot\alpha_1^3 + s_2\cdot\alpha_0^2 - 2\cdot s_2\cdot\alpha_1^2 + s_1\cdot\alpha_0 + s_0 \text{ | degree} = 5 \end{align*} acc1=tmp1α04+4tmp0α03α1+4tmp1α03α1+6tmp0α02α126tmp1α02α124tmp0α0α1312tmp1α0α133tmp0α14tmp1α14+3s3α02α1+3s3α0α12s3α13+2s2α0α1+s2α12+s1α1 | degree=5\begin{align*} \mathsf{acc}_1^{'} &= \mathsf{tmp}_1\cdot\alpha_0^4 + 4\cdot\mathsf{tmp}_0\cdot\alpha_0^3\cdot\alpha_1 + 4\cdot\mathsf{tmp}_1\cdot\alpha_0^3\cdot\alpha_1 + 6\cdot\mathsf{tmp}_0\cdot\alpha_0^2\cdot\alpha_1^2 &- 6\cdot\mathsf{tmp}_1\cdot\alpha_0^2\cdot\alpha_1^2 - 4 \cdot \mathsf{tmp}_0\cdot\alpha_0\cdot\alpha_1^3 -12\cdot\mathsf{tmp}_1\cdot\alpha_0\cdot\alpha_1^3 &- 3\cdot\mathsf{tmp}_0\cdot\alpha_1^4 - \mathsf{tmp}_1\cdot\alpha_1^4 + 3\cdot s_3\cdot\alpha_0^2\cdot\alpha_1 &+ 3\cdot s_3\cdot\alpha_0\cdot\alpha_1^2 - s_3\cdot\alpha_1^3 + 2\cdot s_2\cdot\alpha_0\cdot\alpha_1 + s_2\cdot\alpha_1^2 + s_1\cdot\alpha_1 \text{ | degree} = 5 \end{align*}

The effect on the rest of the stack is:

  • No change.

The HORNERBASE makes one memory access request:

umem=α0+α1opmem_readword+α2ctx+α3s13+α4clk+α5h0+α6h1+α7h3+α8h4u_{mem} = \alpha_0 + \alpha_1 \cdot op_{mem\_readword} + \alpha_2 \cdot ctx + \alpha_3 \cdot s_{13} + \alpha_4 \cdot clk + \alpha_{5} \cdot h_{0} + \alpha_{6} \cdot h_{1} + \alpha_{7} \cdot h_{3} + \alpha_{8} \cdot h_{4}

HORNEREXT

The HORNEREXT operation performs 44 steps of the Horner method for evaluating a polynomial with coefficients over the quadratic extension field at a point in the quadratic extension field. More precisely, it performs the following update to the accumulator on the stack tmp=(accα+a3)α+a2\mathsf{tmp} = (\mathsf{acc} \cdot \alpha + a_3) \cdot \alpha + a_2 acc=(tmpα+a1)α+a0\mathsf{acc}^{'} = (\mathsf{tmp} \cdot \alpha + a_1) \cdot \alpha + a_0

where aia_i are the coefficients of the polynomial, α\alpha the evaluation point, acc\mathsf{acc} the current accumulator value, acc\mathsf{acc}^{'} the updated accumulator value, and tmp\mathsf{tmp} is a helper variable used for constraint degree reduction.

The stack for the operation is expected to be arranged as follows:

  • The first 88 stack elements contain 88 base field elements that make up the current 4-element batch of coefficients, in the quadratic extension field, for the polynomial being evaluated.
  • The next 55 stack elements are irrelevant for the operation and unaffected by it.
  • The next stack element contains the value of the memory pointer alpha_ptr to the evaluation point α\alpha. The word address containing α=(α0,α1)\alpha = (\alpha_0, \alpha_1) is expected to have layout [α0,α1,k0,k1][\alpha_0, \alpha_1, k_0, k_1] where [k0,k1][k_0, k_1] is the second half of the memory word containing α\alpha. Note that, in the context of the above expressions, we only care about the first half i.e., [α0,α1][\alpha_0, \alpha_1], but providing the second half of the word in order to be able to do a one word memory read is more optimal than doing two element memory reads.
  • The next 22 stack elements contain the value of the current accumulator acc=(acc0,acc1)\textsf{acc} = (\textsf{acc}_0, \textsf{acc}_1).

The diagram below illustrates the stack transition for HORNEREXT operation.

horner_eval_ext

After calling the operation:

  • Helper registers hih_i will contain the values [α0,α1,k0,k1,tmp0,tmp1][\alpha_0, \alpha_1, k_0, k_1, \mathsf{tmp}_0, \mathsf{tmp}_1].
  • Stack elements 1414 and 1515 will contain the value of the updated accumulator i.e., acc\mathsf{acc}^{'}.

More specifically, the stack transition for this operation must satisfy the following constraints:

tmp0=acc0α024acc1α0α12acc0α122acc1α12+s6α02s7α1+s4 | degree=3\begin{align*} \mathsf{tmp}_0 &= \mathsf{acc}_0\cdot \alpha_0^2 - 4\cdot \mathsf{acc}_1\cdot \alpha_0\cdot \alpha_1 - 2\cdot \mathsf{acc}_0\cdot \alpha_1^2 &- 2\cdot \mathsf{acc}_1\cdot \alpha_1^2 + s_6\cdot \alpha_0 -2\cdot s_7\cdot \alpha_1 + s_4 \text{ | degree} = 3 \end{align*} tmp1=acc1α02+2acc0α0α1+2acc1α0α1+acc0α12acc1α12+s7α0+s6α1+s7α1+s5 | degree=3\begin{align*} \mathsf{tmp}_1 &= \mathsf{acc}_1\cdot \alpha_0^2 + 2\cdot \mathsf{acc}_0\cdot \alpha_0\cdot \alpha_1 + 2\cdot \mathsf{acc}_1\cdot \alpha_0\cdot \alpha_1 &+ \mathsf{acc}_0\cdot \alpha_1^2 - \mathsf{acc}_1\cdot \alpha_1^2 + s_7\cdot \alpha_0 + s_6\cdot \alpha_1 + s_7\cdot \alpha_1 + s_5 \text{ | degree} = 3 \end{align*} acc0=tmp0α024tmp1α0α12tmp0α122tmp1α12+s2α02s3α1+s0 | degree=3\begin{align*} \mathsf{acc}_0^{'} &= \mathsf{tmp}_0\cdot \alpha_0^2 - 4\cdot \mathsf{tmp}_1\cdot \alpha_0\cdot \alpha_1 - 2\cdot \mathsf{tmp}_0\cdot \alpha_1^2 & - 2\cdot \mathsf{tmp}_1\cdot \alpha_1^2 + s_2\cdot \alpha_0 - 2\cdot s_3\cdot \alpha_1 + s_0 \text{ | degree} = 3 \end{align*} acc1=tmp1α02+2tmp0α0α1+2tmp1α0α1+tmp0α12tmp1α12+s3α0+s2α1+s3α1+s1 | degree=3\begin{align*} \mathsf{acc}_1^{'} &= \mathsf{tmp}_1\cdot \alpha_0^2 + 2\cdot \mathsf{tmp}_0\cdot \alpha_0\cdot \alpha_1 + 2\cdot \mathsf{tmp}_1\cdot \alpha_0\cdot \alpha_1 & + \mathsf{tmp}_0\cdot \alpha_1^2 - \mathsf{tmp}_1\cdot \alpha_1^2 + s_3\cdot \alpha_0 + s_2\cdot \alpha_1 + s_3\cdot \alpha_1 + s_1 \text{ | degree} = 3 \end{align*}

The effect on the rest of the stack is:

  • No change.

The HORNEREXT makes one memory access request:

umem=α0+α1opmem_readword+α2ctx+α3s13+α4clk+α5h0+α6h1+α7h3+α8h4u_{mem} = \alpha_0 + \alpha_1 \cdot op_{mem\_readword} + \alpha_2 \cdot ctx + \alpha_3 \cdot s_{13} + \alpha_4 \cdot clk + \alpha_{5} \cdot h_{0} + \alpha_{6} \cdot h_{1} + \alpha_{7} \cdot h_{3} + \alpha_{8} \cdot h_{4}

EVALCIRCUIT

The EVALCIRCUIT operation evaluates an arithmetic circuit, given its circuit description and a set of input values, using the ACE chiplet and asserts that the evaluation is equal to zero.

The stack is expected to be arranged as follows (from the top):

  • A pointer to the circuit description with the expected layout by the ACE chiplet.
  • The number of quadratic extension field elements that are read during the READ phase of circuit evaluation.
  • The number of base field elements representing the encodings of instructions that make up the circuit being evaluated during the EVAL phase of circuit evaluation.

The diagram below illustrates this graphically.

evalcircuit

Calling the operation has no effect on the stack or on helper registers. Instead, the operation makes a request to the ACE chiplet using the chiplets' bus. More precisely, let

vace=α0+ACE_LABELα1+ctxα2+ptrα3+clkα4+nreadα5+nevalα6.v_{ace} = \alpha_0 + \mathsf{ACE\_LABEL}\cdot\alpha_1 + ctx \cdot\alpha_2 + ptr\cdot\alpha_3 + clk\cdot\alpha_4 + n_{read}\cdot\alpha_5 + n_{eval}\cdot\alpha_6.

where:

  • ACE_LABEL\mathsf{ACE\_LABEL} is the unique operation labels for initiating a circuit evaluation request to the ACE chiplet,
  • ctxctx is the memory context from which the operation was initiated,
  • clkclk is the clock cycle at which the operation was initiated,
  • ptrptr, nreadn_{read} and nevaln_{eval} are as above.

Then, using the above value, we can describe the constraint for the chiplets' bus column as follows:

bchipvace=bchip | degree=2b_{chip}' \cdot v_{ace} = b_{chip} \text{ | degree} = 2