A and B transitioning from one state to the next based on sequential instructions.

- The former part is more like the ‘software’ of the state machine, as it is concerned with interpreting program instructions and correctly generating the execution trace. A novel language dubbed the zero-knowledge Assembly (zkASM) language is used in this part.
- But the latter part is more like the ‘hardware’ as it consists of a set of arithmetic constraints (or their equivalent, polynomial identities) that every correctly generated execution trace must satisfy. Since these arithmetic constraints are transformed into polynomial identities (via an interpolation process), they are described in a novel language called the Polynomial Identity Language (PIL).
Generic SM executor
As seen with the mFibonacci SM, the SM executor takes certain inputs together with the description of the SM, in order to produce the execution trace specifically corresponding to these inputs.
A to register B, to computing some linear combination of several register values.

State machine instructions
We continue with the model shown in Figure 1: a state machine with two registers (A and B) executing computations as specified by a program.
Here is an example of a program containing four instructions, expressed in the zkASM language,
(A, B) = (0, 0). The SM executor sequentially executes each instruction as follows,
- Firstly,
${getAFreeInput()} => Arequests a free input value and places it into registerA. - Secondly,
3 => Bplaces the constant value3into registerB. - Thirdly,
:ADDcomputesA + Band stores the result intoA. - Lastly,
:ENDresetsAandBto their initial values in the next state to achieve cyclic behaviour.
Execution trace
In addition to carrying out computations as per instructions in programs, the executor must also generate the trace of all state transitions, called the execution trace. Consider, as an example, the execution trace the executor produces for the above program of four instructions. Suppose the free input value used is7. The generated execution trace can be depicted in tabular form as shown below.
| Instruction | FREE | CONST | A | A’ | B | B’ |
|---|---|---|---|---|---|---|
${getAFreeInput()} => A | 7 | 0 | 0 | 7 | 0 | 0 |
3 => B | 0 | 3 | 7 | 7 | 0 | 3 |
:ADD | 0 | 0 | 7 | 10 | 3 | 3 |
:END | 0 | 0 | 10 | 0 | 3 | 0 |
A and B, as well as the columns for the constant CONST and the free input FREE, are a bit obvious. But the reason for having the other two columns, A' and B', may not be so apparent.
The reason there are two extra columns, instead of only four, is the need to capture each state transition in full, and per instruction. The column labelled A' therefore denotes the next state of register A, and similarly, B' denotes the next state of register B. This ensures that each row of the execution trace reflects the entire state transition pertaining to each specific instruction.
The execution trace is therefore read row-by-row as follows,
- The first row (per
${getAFreeInput()} => A) gets the free input value7and sets the nextAvalue to7. - The second row (per
3 => B) moves the constant value3into registerBas its next value, andAremains at7as expected. - The third row (per
:ADD) computes the sum of register values inAandB(i.e.7 + 3 = 10) and moves the output10into registerAas its next value. - The last row (per
:END) resets registersAandBto zeros (their initial values) as their next values.
7 to another number would obviously yield a different execution trace, yet without violating the first instruction.