Keccak-f state machine
The Keccak-F state machine is one of the secondary zkProver state machines. It computes message string hashes and validates the accuracy of those computations u
The Keccak-F state machine is one of the secondary zkProver state machines. It computes message string hashes and validates the accuracy of those computations upon the request of Main SM.
Although the architecture of the original Keccak hash function is simple, the Keccak-F SM is not just a state machine or a simple automated version of the cryptographic hash function.
First, a gates state machine is used to implement the Keccak-F SM. A binary circuit that operates on a bit-by-bit basis.
Second, with regard to the Main SM, the Padding-KK SM, the Padding-KK-Bit SM, and the Bits2Field SM together provide a framework within which the Keccak-F SM is realized.
Thirdly, the Keccak-F circuit is constructed in such a way that executing it once is effectively equivalent to operating forty-four () hashing circuits simultaneously, particularly in the first version of the zkEVM public testnet. For further information on how this parallelism technique is applied, see the Bits2Field SM.
The Keccak-F circuit is briefly described in this article, along with a thorough explanation of the widely used Keccak-256 hash function and its specific parameters as they apply to the Polygon zkEVM implementation.
Keccak-F circuit
The Keccak-F circuit has two types of gates, types and , corresponding to the two binary operations it performs, the and .
The Keccak-F executor builds the constant polynomials, , and , and these are to be tested if they match their corresponding polynomials, , and .
Also, for any we have,
The bits are loaded into the state machine as -bit chunks.
In keccakf.pil, each committed polynomial is expressed in terms of 4 chunks, where each is bits long. The corresponding a -bit array can be expressed as,
where for each .
The verification involves a copy constraint
and a Plookup as,
for each .
This covers the Keccak-F circuit in a nutshell together with its PIL code. See the codes of sm_keccakf.js and keccakf.pil on GitHub.
Keccak-256 hash function
There are seven Keccak-F permutation functions, each indicated by -, where is the size of the internal state of the hash function, for .
The zkProver's Keccak state machine is a verifiable automisation of a Keccak-F permutation function, which amounts to an irreversible scrambling of bits of a string , where .
The EVM utilises the Keccak-256 hash function, which is a sponge construction with capacity bits, and denoted by Keccak. That is, the Keccak-256 notation puts emphasis on the -bit security level, while the Keccak notation seeks to depict the actual capacity of bits.
Bitrate and capacity
Although the internal state is bits, Keccak-F intakes a fixed number of bits as input, called the (or simply, ) and it is denoted by . In our specific case, the bitrate , whilst the capacity, .
The size of a single output is bits. However, users can choose their required length by truncating the output, which is of length , where , for some positive integer .
The Keccak-F permutation used in Keccak is Keccak- (see NIST SHA-3 Standard).
Thus, given an input bit string and a output length , Keccak outputs a -bit string following the previous sponge construction description.
Keccak-F padding rule
The Keccak-F permutation operates on a state of width bits (or bytes) and a bitrate
But not every input string comes with this tailored bit-length.
Therefore, every input string is split into -bit chunks, where padding is applied to the tail-end chunk with bits or lesser.
The last ingredient we need to define in order to completely specify the hash function is the padding rule.
In Keccak , the padding is used. If we define , where is the length of the input in bits, then the padding we have to append to the original input message is,
It should be noted that our construction does not follow the FIPS-202 based standard (a.k.a SHA-3).
According to the NIST specification, the SHA3 padding has been changed to
The difference is the additional bits being appended to the original message, which were not present in the original Keccak specification.
Keccak-F's internal state
The -bit (post-padding) chunks are provided sequentially, and one chunk at a time, into the Keccak-F permutation function, to be -ed with a given initialization vector or intermediate states. The capacity bits are typically initialised to zero bits and are not affected by any external bits.
However, instead of a plain bit-string of length bits, a state in the Keccak SM is best visualised in 3D form as follows;
- Each bit is imagined as a cube,
- The entire -bit state is thought of as a 3D array of cubes (bits): . That is, sixty-four ()-blocks of bits (cubes).
See the below figure for a -bit state array, displaying;
-
The 64-bit lane shown in orange, consisting of bits, to , and
-
The 5-bit column shown in green, consisting of bits, to .

A bit in the state can be denoted by as an element of the 3D-array state, but as to indicate its location in position with respect to the Cartesian coordinate system.
The mapping between the bits of the state , when written as a linear array of bits, and the bits when is expressed as a 3D array, is given by,
So then, the bit at coordinate is in fact the one-thousand-and-ninety-second bit of , because . This bit, , is represented in the above figure by the blue cube. See more examples of this correspondence in the table provided below.
Consider computing the of all the 5 bits in the column . If its bits are as given below,
then the of the column bits, denoted by , is .
In our notation, a column is identified by the fixed - and - values. Hence the of all the 5 bits in a column is denoted by . That is,
Keccak-F rounds
The Keccak-F state machine runs 24 rounds, each of which is a composition of five step mappings; , , , , and , denoted by
where is the round index, and in our case, .
These step mappings are individually described in the subsections below. The following table illustrates how the output state of each step mapping is relayed to the next step mapping as its input state.
Therefore, given a state value, the next value of the bit is denoted by . The code shown on the right side of the table is keccakf.cpp.
Mapping Theta
The first step mapping, , referred to as in keccak_f.cpp, can be described in three sub-steps;
- Compute the of the bits in the -column,
and the of the bits in the -column,
- Calculate the of the two column s;
- Compute the of and the bit of the current state value;
See the below figure, for an illustration of the step mapping applied on one bit. The diagram is taken from Keccak Reference 3.0 guide.
The code of the step mapping is found here: keccak_theta.cpp

Mapping Rho
The step mapping does not change the value of the input bit, but simply moves it to another position along the -axis. Since all operations along the -axis are worked out modulo 64, the mapping is therefore cyclic, and amounts to rotating each of the 64 bits in the same lane along the -axis. It does this in three sub-steps;
- Set ,
- For ranging from to , set ,
- Set .
Basically, modifies the coordinate of each bit, , by subtracting a specific offset constant modulo 64, where . See the below table for these offset constants used for rotation.
The 24 constants in the above table are first permuted and then set as fixed offsets corresponding to each bit of the 3D state array.
\begin{array}{|l|c|c|c|c|c|c|} \hline \texttt{y} \big{\\ } \texttt{x} & 3 & 4 & 0 & 1 & 2\\ \hline 2 & 25 & 39 & 3 & 10 & 43\\ \hline 1 & 55 & 20 & 36 & 44 & 6\\ \hline 0 & 28 & 27 & 0 & 1 & 62\\ \hline 4 & 56 & 14 & 18 & 2 & 61\\ \hline 3 & 21 & 8 & 41 & 45 & 15\\ \hline \end{array}Note that all bits such that and correspond to a zero offset constant. Consequently, the origin and all the other 63 bits along the lane remain unmoved by .
Although the effect of is a rotation of bits along the -axis, it actually operates on each 25-bit -slice of the state 3D-array. Hence the 25 offset constants (and not 64), including the zero offset of the origin lane .
Example
Here's an example of how maps two different lanes.
-
For all , where , the bits are always off-set by and mapped as follows,
-
Similarly, the bits are always off-set by and mapped as follows,
The code of the step mapping is found here: keccak_rho.cpp
Mapping Pi
The step mapping is literally a shuffle of the 25 bits in each -slice. For each , where , it is defined as the mapping,
Note that fixes each of the bits , including the bit at the origin, . Also, for all bits in the 3D-array, does not change the -component. That is, all bits remain in their original -slice. To this extend, it suffices to describe in terms of the images of the pairs alone, as in the table below.
Below diagram, showing the -slices, depicts the shuffling of the bits in accordance with the above table. This figure is in fact the mapping displayed in Figure 2.3 of the Keccak Reference 3.0 [Page 20; 2011].

The code of the step mapping is found here: keccak_pi.cpp
Mapping Chi
The step mapping is the non-linear layer of Keccak-F, and it can be thought of as a parallel application of S-boxes operating on -bit rows.
How Chi operates on rows
For a fixed and , the step mapping takes as its input the -bit row,
It then computes a non-linear combination of each bit in , with the next two consecutive bits and also in . In order to change the bit, ,
-
takes as input to a -gate.
-
Then takes the output, , together with , as inputs to an -gate.
-
Finally, it XOR-es the output of the -gate with the bit being changed, .
That is, for each 5-bit row, , can be summarized as the mapping of each bit, , as;
where .
Overall, the step mapping can be depicted as a "circuit" of gates as in the below diagram, taken from FIPS PUB 202, August 2015 (Figure 6, Page 15).

The code of the step mapping is found here: keccak_chi.cpp
Mapping Iota
The step mapping adds 64-bit round-constants, , so as to disrupt any symmetry in the computation of the round outputs. Note that is the round index, . Hence, 24 distinct round-constants are required, and are denoted in array notation as,
The round-constants are XOR-ed only to a single lane of the state, in particular, the origin lane (i.e., the 64 bits where ).
Iota operating the origin lane
Here's how operates on the origin lane,
Firstly, the derivation of the round-constants . As shown in the algorithm of , the round-constant is initialized to at the beginning of each round of . After which, 7 specific bit-places of the round-constant are set to the bits . Meanwhile, the rest of the bits remain as zeros.
The derivation of the 7 bits, , is explained below.
Secondly, each round of simply XOR-es the corresponding 64-bit round-constant to the 64-bit lane, . Since only 7 bits of the round-constant are set, each round of therefore alters at most 7 bits of origin lane.
In our implementation , and thus .
The code of the step mapping is found here: keccak_iota.cpp
Generation of 7 bits for round-constants
In order to ensure that these round-constants differ from round-to-round, a linear feedback shift register (LFSR) of maximal length is used to generate them. The algorithm for generating these round-constants is given below.
The LFSR can run for 255 clocks before resetting to , and has 8 registers; .
At , it is initialised to . A state transition (or a shift) consists of;
-
A push of a bit into the first register while shifting the bit in register to for each , where .
-
XOR of the bit from register with register .
-
XOR of the bit from register with register .
-
XOR of the bit from register with register .
-
XOR of the bit from register with register .
-
Output the bit in the first register as .
After every 7 consecutive state transitions, the LFSR produces enough bits to form the corresponding round-constant . The 7 bits map to their bit places in according to the above shown table.

Example
Since the LFSR is initialised to at , its state at the end of 7 state transitions is . So . After the 8-th state transition the state of the LFSR is , and thus . The next table displays generation of the 7 bits needed to construct the second round-constant, . That is, the LFSR's state transitions for to .
It can be observed, on the right-hand side of the above table, that the and are the same. That is,
This results in the round-constant,
All 24 round constants , where each is bits long, are given in their hexadecimal format below.

The C++ code for the LFSR can be found in the zkEVM Prover repository here: keccak_rc.cpp
All these step mappings are consolidated in the keccakf.cpp code, which calls them as functions.
Last updated on
Bits2Field state machine
The Bits2Field state machine is one of the auxiliary state machines used specifically for parallelizing the implementation of KECCAK-F SM. Its source code is av
Poseidon state machine
The Poseidon state machine is one of the zkProver's 14 state machines. It is a secondary state machine that receives instructions from the Main state machine of