Field
Our zkEVM is designed to have its execution traces encoded in a particular prime field , with . A nice property of this field is that it can represent the results of many common u32
operations. For example, (widening) u32
multiplication has a maximum value of , which is less than . In fact a u32
multiply-add has a maximum value of , so the result can be represented with a single field element, although if we were to add a carry in bit, this no longer holds.
This field also enables a very efficient reduction method. Observe that and consequently
To reduce a 128-bit number , we first rewrite as , where is 64 bits and are 32 bits each. Then
After computing , which can be done with a shift and subtraction, we add the first two terms, subtracting if overflow occurs. We then subtract , adding if underflow occurs.
At this point we have reduced to a u64
. This partial reduction is adequate for most purposes, but if we needed the result in canonical form, we would perform a final conditional subtraction.