Midnight ZK Standard Library
The Midnight ZK Standard Library (midnight-zk-stdlib) provides a high-level abstraction for building zero-knowledge circuits using the midnight-circuits and midnight-proofs crates.
WARNING: This library has not been audited. Use it at your own risk.
Overview
ZkStdLib encapsulates the functionality required by Midnight and serves as an abstraction layer, allowing developers to focus on circuit logic rather than the configuration and chip creation. Developers only need to implement the Relation trait, avoiding the boilerplate of Halo2's Circuit trait.
The architecture of ZkStdLib is configurable via the following structure:
The configuration can be defined via the Relation trait with the used_chips function. The default architecture activates only JubJub, Poseidon and sha256, and uses a single column for the pow2range chip. The maximum number of columns accepted for the pow2range chip is currently 4.
Example: Proving Knowledge of a SHA-256 Preimage
Here is a complete example showing how to build a circuit for proving knowledge of a SHA-256 preimage.
Given a public input x, we will prove that we know w ∈ {0,1}^192 such that x = SHA-256(w).
use ;
use ;
use ;
use ;
use ChaCha8Rng;
use Digest;
type F = Fq;
;
// The SRS (Structured Reference String) must match the circuit size exactly.
// `k` is the log2 of the circuit size (i.e. the circuit has 2^k rows).
// We can load an SRS that is larger than needed and downsize it automatically.
const K: u32 = 14;
let mut srs = filecoin_srs;
let relation = ShaPreImageCircuit;
// Compute the optimal k for the circuit and downsize the SRS to match.
let k = optimal_k;
srs.downsize;
// If you already know the exact k for your circuit, you can skip the above
// and load an SRS of the right size directly.
let vk = setup_vk;
let pk = setup_pk;
// Sample a random preimage as the witness.
let mut rng = from_entropy;
let witness: = from_fn;
let instance = digest.into;
let proof =
.expect;
assert!
You can find more examples in the examples directory.
Versioning
We use Semantic Versioning. To capture the changes that do not affect the API, do not add any new functionality, but are breaking changes, we increment the MAJOR version. This happens when the circuit is modified for performance or bug fixes; the modification of the verification keys break backwards compatibility.
- MAJOR: Incremented when you make incompatible API or VK changes
- MINOR: Incremented when you add functionality in a backward-compatible manner
- PATCH: Incremented when you make backward-compatible bug fixes