Skip to main content

Key components and tools

zkLLVM Components

The architecture of zkLLVM is modular and extendable. It can be divided into two main components.

Frontends

Frontends parse high-level languages, generate abstract syntax trees (ASTs), and output intermediate representations (IRs) of circuits. Presently, zkLLVM supports C++ and Rust as frontends based on clang and rustc, respectively.

clang is taken from circifier, which is an extended fork of the original LLVM project. In turn, rustc is contained within rslang, which is a similarly extended version of the main source code repository for Rust.

As a result, in comparison to the vanilla LLVM project frontends, zkLLVM frontends generate IRs that are extended with custom types and instructions.

Assigner

assigner transforms an IR into two products.

  • The assignment table
  • Arithmetization-specific constraints
info

Constraints flatten a computation into an arithmetization (e.g., R1CS or PLONK). An arithmitization is a set of constraints imposed by a proof system input type.

It is only necessary to generate constraints once per every circuit/input type pair. In contrast, the assignment table needs to be regenerated whenever dynamic inputs change.

Together, these products ensure that the circuit can be proven with dynamic inputs.

Click here to learn more about assigner extendibility

The core of assigner is an LLVM IR parser, which can be ported into any programming language. To access its current implementation, click here. This implementation is written in C++ and supports only the PLONK arithmetization.

assigner can be extended to support any other arithmetization. This process involves implementing the LLVM IR parser and following these steps.

  • Find a suitable components library for the chosen arithmetization (such as halo2 for Rust)
  • Use the components library to implement assignment table generation
  • Use the components library to implement constraints generation and serialization

Note that the zkLLVM frontends output IRs that are modified compared to the IRs generated by the vanilla LLVM project. As a result, any external tool that uses the original LLVMIRParser from LLVM will be unable to parse IRs from zkLLVM.

When extending assigner, simply reusing an external parser will not work: it will need to be adapted to fully parse the modified IRs supplied by frontends.

Proof system components

There are two additional components provided by a proof system rather than zkLLVM.

  • A prover used for generating circuit-specific proofs
  • A verifier used for verifying circuit-specific proofs

By default, zkLLVM uses the circuit components from the blueprint module and the PLONKish arithmetization supported by the Placeholder proof system.

To adapt zkLLVM to other arithmetizations and proof systems, extend the assigner component as described above.

Verifier

Depending on the proof system, a verifier can be located either on-chain or off-chain.

Proof systems and arithmetizations

Note that the same arithmetization can be used by several different proof systems. As a result, constraints generated by assigner for one arithmetization can be freely reused across various proof systems.