Binary Tower Fields
Binary tower fields from GF(2) to GF(2^256) in Rust, constant-time by default, PMULL on aarch64: the math core of the Hekate engine and its chiplets.
Hekate's prover, its verifier and every chiplet compute in these fields: trace cells, sumcheck messages and challenges
are all tower elements, and System Architecture shows
them inside a proof. The crate also stands alone; its README names sumcheck, GKR-based provers and Binius protocols as
uses. Its default features are std and parallel (Rayon), and without them it builds as no_std.
§ The tower
The tower runs from GF(2^8), the AES field, to GF(2^256), each level twice the width of the one below, and Bit embeds
GF(2) as a subfield. A level adjoins a root of v² + v + βᵢ, with a fixed constant βᵢ per level, and an element is a
(low, high) pair from the level below.
| Field | Type | Extension constant β |
|---|---|---|
| GF(2) | Bit | embedded subfield |
| GF(2^8) | Block8 | base field, the AES polynomial |
| GF(2^16) | Block16 | 0x20 in Block8 |
| GF(2^32) | Block32 | 0x2000 in Block16 |
| GF(2^64) | Block64 | 0x20000000 in Block32 |
| GF(2^128) | Block128 | 0x2000000000000000 in Block64 |
| GF(2^256) | Block256 | 0x20000000000000000000000000000000 in Block128 |
§ Two bases
Each field has two representations, and the type system keeps them apart. Recursion is cheap in the tower basis, and
the carry-less multiply works in the flat basis, the polynomial basis of the field. A tower value is F, a flat value
is Flat<F>, and mixing them fails to compile. to_hardware and to_tower convert, and both bases give the same
products and sums.
§ Examples
The three programs below are the README's examples as standalone programs.
isomorphism.rsmultiplies and adds in both bases and checks that they agree.simd.rspacks four flatBlock32values into one 128-bit register throughPackableFieldand multiplies them lane by lane.fft.rsruns the additive FFT of Gao and Mateer in the Cantor basis:forward_scalarevaluates novel-basis coefficients on the 2^log_n points of a subspace, andinverse_scalarinterpolates them back.
1use ;
2
3
1use ;
2
3
10
11
1use ;
2use Error;
3
4
The transform takes Block16 through Block128, in scalar and packed forms, each with a coset variant, and buffers of
1 MiB and up run on Rayon, bit-identical to serial. ReedSolomon<F> builds a systematic Reed-Solomon code on it, whose
codeword starts with the message.
§ Constant time
The default build is constant-time, and the table-math feature trades that for speed. By default, basis conversion
runs as bit-sliced matrix multiplication whatever the input, and the carry-less multiply takes constant latency on
current microarchitectures. table-math replaces the conversions with cached lookup tables, and GF(2^8)
multiplication with log and exp tables and a zero-operand branch: keep it for public data, such as a verifier's inputs.
The README marks the constant-time property as unproved.
§ Formal verification
Verus proofs check the arithmetic kernels against a model of GF(2^k): tower multiplication and inversion, the NEON
kernels, the constant-time conversions and batch promotes, and the additive FFT. They live in
verus/, outside the crate build, and rely on axioms
the build discharges and on the transcription seams listed in
TRUSTED_AXIOMS.md.
§ Platforms
aarch64 multiplies in hardware, with PMULL and NEON, and x86_64 runs the software path. On aarch64, PMULL sits behind
the aes target feature, which aarch64-unknown-linux-gnu leaves off by default: build with
RUSTFLAGS="-C target-feature=+aes", or the flat kernels take the software path, with the same results at lower
throughput.
§ Performance
Measured on Apple M3 Max, table-math build. The default constant-time build is slower on the tower rows and identical on the flat ones. Reproduce with cargo bench --features table-math in a hekate-math checkout.
§ Block128 operations
| Operation | Basis | Latency | Implementation |
|---|---|---|---|
| Multiplication | Polynomial (flat) | 0.90 ns | PMULL, pipelined |
| Multiplication | Tower (canonical) | 16.6 ns | Basis isomorphism and PMULL |
| Addition | Any | 1.15 ns | Vectorized XOR |
| Inversion, single | Tower | 106.2 ns | Itoh-Tsujii, Fermat's little theorem |
| Inversion, batch | Tower | 15.6 ns | Montgomery's trick, SIMD |
| Basis conversion, default | Tower and flat | 40.2 ns | Bit-slicing, constant-time |
| Basis conversion, fast | Tower and flat | 3.68 ns | Lookup table, variable-time |
§ Polynomial arithmetic in GF(2^128)
| Operation | Size | Time | Throughput |
|---|---|---|---|
| Dense evaluation, tower | 2²⁰ coefficients | 23.7 ms | 675 MiB/s |
| Dense evaluation, hardware | 2²⁰ coefficients | 8.37 ms | 1.87 GiB/s |
| Batch evaluation, SIMD | 256 × 16384 | 4.44 ms | 945 Melem/s |
| Additive FFT, scalar | 2¹⁶ · Block16 | 477.7 µs | 137 Melem/s |
| Additive FFT, packed | 2¹⁶ · ×8 lanes | 386.6 µs | 1.36 Gelem/s |
| Interpolate MSM | 65536 points | 106.5 µs | 616 Melem/s |
| MLE evaluation | 20 variables | 1.00 ms | 1.04 Gelem/s |