C-KZG-4844

April 21, 2026 ยท View on GitHub

A minimal implementation of the Polynomial Commitments API for EIP-4844 and EIP-7594, written in C.

Bindings

While the core implementation is in C, bindings are available for various high-level languages, providing convenient wrappers around C functions. These bindings are intended to be used by Ethereum clients to avoid re-implementation of crucial cryptographic functions.

LanguageLink
C#README
ElixirREADME
GoREADME
JavaREADME
NimREADME
Node.jsREADME
PythonREADME
RustREADME
ZigREADME

Interface functions

The C-KZG-4844 library provides implementations of the public KZG functions that are specified in the Polynomial Commitments API for Deneb and Fulu. The aim is to align these functions as closely as possible with the specifications.

For EIP-4844:

  • blob_to_kzg_commitment
  • compute_kzg_proof
  • compute_blob_kzg_proof
  • verify_kzg_proof
  • verify_blob_kzg_proof
  • verify_blob_kzg_proof_batch

For EIP-7594:

  • compute_cells
  • compute_cells_and_kzg_proofs
  • recover_cells_and_kzg_proofs
  • verify_cell_kzg_proof_batch

This library also provides functions for loading and freeing the trusted setup, which are not defined in the API. The loading functions are intended to be executed once during the initialization process. As the name suggests, the trusted setup file is considered to be trustworthy.

  • load_trusted_setup
  • load_trusted_setup_file
  • free_trusted_setup

Remarks

Tests

All bindings are tested against the KZG reference tests, which are defined in the consensus-spec-tests repository. Additionally, a suite of unit tests for internal C functions is located here.

Parallelization

The interface functions in C-KZG-4844 are single-threaded for simplicity, as implementing multi-threading across multiple platforms can be complex. While performance is important, these functions are already quite fast and efficient. For instance, verify_blob_kzg_proof is expected to finish in under 3ms on most systems.

Batched verification

When processing multiple blobs, verify_blob_kzg_proof_batch is more efficient than calling verify_blob_kzg_proof individually. In CI tests, verifying 64 blobs in batch is 53% faster per blob than verifying them individually. For a single blob, verify_blob_kzg_proof_batch calls verify_blob_kzg_proof, and the overhead is negligible.

Benchmarks

C-KZG-4844 provides benchmarks in the Go bindings. It is easier to write benchmarks in a high-level language and doing benchmarks in the bindings offers a more realistic performance overview, including FFI overhead. Additionally, C-KZG-4844 is not expected to be used outside the bindings.

Audits

C-KZG-4844's implementation for EIP-4844 was audited by Sigma Prime in 2023 and its implementation for EIP-7594 was audited by zkSecurity in 2025. You can find the corresponding audit reports in the audits directory.

Why C?

The primary reason for choosing C is that blst, the BLS12-381 signature library we wanted to use, is mostly written in C. Rust was a viable alternative, but it has some disadvantages. The C toolchain is ubiquitous, and it would be somewhat awkward for all the bindings to depend on another toolchain, such as Rust. Compared to Rust, C offers a lighter memory and binary footprint. Furthermore, C serves as the de facto language for FFI, so we could not have completely avoided using C anyway.

Precompute

Introduced in v2.0.0, a precompute parameter was added to the functions which load the trusted setup. When a non-zero value is provided, a fixed-base multi-scalar multiplication function (instead of Pippenger's algorithm) is used to compute cell KZG proofs. Note that the precompute parameter only affects the performance of compute_cells_and_kzg_proofs and recover_cells_and_kzg_proofs. If your application does not use these functions, we recommend using precompute=0. For applications that do, we recommend using precompute=8 or precompute=9, which offer an optimal balance between performance and memory usage.

For reference, benchmarks from a system with an Apple M1 CPU:

PrecomputeLoad TimeCompute TimeMemory Size
01.69 s311.15 ms0 KiB
11.70 s891.29 ms768 KiB
21.69 s480.85 ms1536 KiB
31.71 s344.99 ms3 MiB
41.74 s277.46 ms6 MiB
51.77 s239.71 ms12 MiB
61.82 s212.18 ms24 MiB
71.97 s196.78 ms48 MiB
82.26 s180.71 ms96 MiB
92.82 s169.72 ms192 MiB
103.95 s159.83 ms384 MiB
116.19 s155.72 ms768 MiB
1210.78 s148.54 ms1536 MiB
1319.66 s141.83 ms3 GiB
1437.83 s135.94 ms6 GiB
1574.95 s134.50 ms12 GiB