Crate and Module Map
1. Why this chapter exists
Before reading anything else, you need a map. The halo2 repository
is a four-crate Cargo workspace, but the names overlap with each
other and with the public Rust ecosystem (the
halo2
crate is a thin shim; the real proving system lives in
halo2_proofs).
Most newcomers waste time searching the wrong crate. By the end of
this chapter you will know which module owns each of: the
arithmetization, the prover, the verifier, the polynomial
commitment, the chips, and the dev tooling.
2. Definitions
We use the terminology that the halo2 codebase uses internally.
Definition (Workspace). A Cargo workspace is a set of crates
sharing a single Cargo.lock. The halo2 workspace is declared in
Cargo.toml
with members halo2, halo2_gadgets, halo2_poseidon,
halo2_proofs.
Definition (Crate). Each member is a Cargo crate with its own
Cargo.toml, its own version, and its own crates.io release
schedule.
Definition (PLONKish circuit). A circuit expressed as a
rectangular table of cells with rows and a fixed number
of columns, plus a set of low-degree polynomial constraints and
copy constraints over those cells. The arithmetization is defined
formally in
plonk/circuit.rs;
chapter 05 covers it in detail.
Definition (Chip vs Gadget). A chip is a Rust type that
allocates columns and gates on a ConstraintSystem and exposes
typed assignment methods. A gadget is a thin layer that calls one
or more chips through a trait, without itself owning columns. The
distinction is made precise in
halo2_gadgets/src/lib.rs.
3. The code
3.1 The workspace manifest
The workspace lists four crates and nothing else:
[workspace]
members = [
"halo2",
"halo2_gadgets",
"halo2_poseidon",
"halo2_proofs",
]
3.2 The halo2 shim crate
The crate named halo2 is a re-export shim. Its only dependency is
halo2_proofs, and its lib.rs re-exports the public surface so
users can write halo2::plonk::create_proof instead of
halo2_proofs::plonk::create_proof. Look here only if you want to
understand the public-version-vs-internal-version dance; do not put
code here.
[package]
name = "halo2"
version = "0.1.0-beta.2"
authors = [
"Jack Grigg <jack@electriccoin.co>",
]
edition = "2021"
rust-version = "1.60"
description = "[BETA] Fast zero-knowledge proof-carrying data implementation with no trusted setup"
license = "MIT OR Apache-2.0"
repository = "https://github.com/zcash/halo2"
documentation = "https://docs.rs/halo2"
readme = "../README.md"
categories = ["cryptography"]
keywords = ["halo", "proofs", "recursive", "zkp", "zkSNARKs"]
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs", "--html-in-header", "katex-header.html"]
[dependencies]
halo2_proofs = { version = "0.3", path = "../halo2_proofs", default-features = false }
[lib]
3.3 halo2_proofs: the proving system
This is the crate every other crate (and every downstream user) depends on. Its public modules:
//! # halo2_proofs
#![cfg_attr(docsrs, feature(doc_cfg))]
// The actual lints we want to disable.
#![allow(clippy::op_ref, clippy::many_single_char_names)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(missing_debug_implementations)]
#![deny(missing_docs)]
#![deny(unsafe_code)]
pub mod arithmetic;
pub mod circuit;
pub use pasta_curves as pasta;
mod multicore;
pub mod plonk;
pub mod poly;
pub mod transcript;
pub mod dev;
mod helpers;
What each module owns:
arithmetic: FFT, NTT, multi-scalar multiplication (best_multiexp), parallel helpers, and re-exports frompasta_curves::arithmetic. Covered in chapter 03.circuit:Chip,Cell,AssignedCell,Layouter,SimpleFloorPlanner,TableLayouter,Value<F>. Covered in chapter 06.plonk: the arithmetization (Circuit,ConstraintSystem,Column,Selector,Expression), keygen (keygen_vk,keygen_pk),create_proof,verify_proof, and the lookup / permutation / vanishing arguments. Covered in chapters 05, 07, 08, and 11.poly: polynomial domains (EvaluationDomain), commitments (commitment::Params), and the multiopen wrapper. Covered in chapters 04, 09, and 10.transcript: Fiat-Shamir transcripts. Covered in chapter 12.dev:MockProver,CircuitCost,CircuitGates,TracingFloorPlanner,CircuitLayout. Covered in chapter 13.
3.4 halo2_gadgets: reusable chips
//! This crate provides various common gadgets and chips for use with `halo2_proofs`.
//!
//! # Gadgets
//!
//! Gadgets are an abstraction for writing reusable and interoperable circuit logic. They
//! do not create any circuit constraints or assignments themselves, instead interacting
//! with the circuit through a defined "instruction set". A circuit developer uses gadgets
//! by instantiating them with a particular choice of chip.
//!
//! # Chips
//!
//! Chips implement the low-level circuit constraints. The same instructions may be
//! implemented by multiple chips, enabling different performance trade-offs to be made.
//! Chips can be highly optimised by their developers, as long as they conform to the
//! defined instructions.
#![cfg_attr(docsrs, feature(doc_cfg))]
// Catch documentation errors caused by code changes.
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(missing_debug_implementations)]
#![deny(missing_docs)]
#![deny(unsafe_code)]
pub mod ecc;
pub mod poseidon;
#[cfg(feature = "unstable-sha256-gadget")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-sha256-gadget")))]
pub mod sha256;
pub mod sinsemilla;
pub mod utilities;
#[cfg(test)]
mod test_circuits;
The top-level modules are intentionally narrow:
ecc: Pallas / Vesta point operations as a chip and a gadget traitEccInstructions. Chapter 14.poseidon: the in-circuit Poseidon sponge built on top of the field-onlyhalo2_poseidoncrate. Chapter 15.sinsemilla: the Sinsemilla hash and the Merkle gadget that consumes it. Chapter 15.sha256: only compiled with--features unstable-sha256-gadget. Chapter 15.utilities:cond_swap,decompose_running_sum,lookup_range_check. Frequently reused building blocks.
3.5 halo2_poseidon: a field-only specification
The Poseidon round constants, the MDS matrix, and the permutation
function in plain field arithmetic. No halo2_proofs dependency.
The in-circuit chip in halo2_gadgets::poseidon::pow5 uses this
crate as the spec it must match.
[package]
name = "halo2_poseidon"
version = "0.1.0"
authors = [
"Jack Grigg <jack@electriccoin.co>",
"Daira Emma Hopwood <daira@jacaranda.org>",
"Ying Tong Lai",
]
edition = "2021"
rust-version = "1.60"
description = "The Poseidon algebraic hash function for Halo 2"
license = "MIT OR Apache-2.0"
repository = "https://github.com/zcash/halo2"
readme = "README.md"
categories = ["cryptography"]
[dependencies]
bitvec = { version = "1", default-features = false }
ff = { version = "0.13", default-features = false }
group = "0.13"
pasta_curves = "0.5"
[features]
test-dependencies = []
4. Failure modes
- Edits in the wrong crate. Adding a new chip to
halo2_proofsrather thanhalo2_gadgetsis the single most common newcomer mistake. The rule: anything that fixes columns, defines a gate, or instantiates a chip belongs inhalo2_gadgets. Only the arithmetization itself, the prover, the verifier, the dev tooling, and the polynomial commitment scheme belong inhalo2_proofs. - Forgetting the shim. Downstream users sometimes depend on
halo2andhalo2_proofssimultaneously, ending up with two copies of every type. Pick one. - Forgetting that
halo2_poseidonis not a chip. It is a spec-only crate. Importing it does not give you a circuit; you also needhalo2_gadgets::poseidon.
5. Spec pointers
- The Halo 2 Book "Concepts" chapter describes the same workspace from a user's perspective; it is the canonical companion to this chapter.
- The PLONK paper
(eprint 2019/953)
introduces the arithmetization that
halo2_proofs::plonkimplements; section 4 (the standard PLONK arithmetization) is the most directly relevant.
6. Exercises
- Open
halo2_proofs/src/lib.rsand list eachpub mod. For each one, write a single sentence saying which chapter of this course covers it. Compare against section 3.3 above. - Find the line in
halo2_proofs/src/lib.rsthat re-exportspasta_curvesunder the namepasta. Note that the same trick lets downstream code stay decoupled from the curve crate version. - Modify the file
halo2_proofs/examples/simple-example.rsto print the workspace version ofhalo2_proofsat runtime usingenv!("CARGO_PKG_VERSION"). Runcargo run --example simple-exampleand confirm the printed version matches the value inhalo2_proofs/Cargo.toml.
Answers in the code
- Exercise 1: the public modules are listed in
halo2_proofs/src/lib.rs. - Exercise 2: the line is
pub use pasta_curves as pasta;near the top of the same file. - Exercise 3: the version is
0.3.2inhalo2_proofs/Cargo.toml.
7. Further reading
- docs.rs/halo2_proofs for the rendered API.
- docs.rs/halo2_gadgets for the gadget catalogue.