# 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 **, which is a similarly extended version of the main source code repository for Rust.**

`rslang`

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

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.

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

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.