A structured learning journey for implementing Zero-Knowledge Proof (ZKP) systems in Rust. This repository progresses from basic logic to sophisticated shielded pool circuits similar to those used in privacy-preserving blockchains.
An introduction to the fundamental concepts of Zero-Knowledge:
- Statement vs. Witness: Distinguishing between what is publicly known and what is hidden.
- Verification Logic: Understanding how a verifier checks a proof without knowing the secret.
- Note: This level intentionally uses plain Rust logic without cryptography to demonstrate the flow.
Implementation of the classic Schnorr protocol using the curve25519-dalek crate:
-
Discrete Log Proofs: Proving knowledge of a secret
$x$ such that$X = x \cdot G$ . - Interactive Protocol: Commitment, Challenge, and Response.
- Fiat-Shamir Transform: Converting interactive proofs into non-interactive ones using hashing.
Using Bulletproofs to prove value properties without revealing the values:
- Pedersen Commitments: Hiding values while binding them to a public point.
-
Range Proofs: Proving a secret value
$v$ is in the range$[0, 2^n)$ to prevent overflow/underflow attacks in financial systems.
Exploring R1CS (Rank-1 Constraint Systems) with the arkworks ecosystem:
-
Basic R1CS: Implementing a simple multiplication circuit (
$a \cdot b = c$ ). - Confidential Transfer Concept: A circuit enforcing "Conservation of Value" (input = output + fee) with integrated range checks using bit decomposition.
Building the off-chain and on-chain state models required for a shielded pool:
- Append-only Merkle Tree: Tracking note commitments to prove existence.
- Nullifier Set: A mechanism to prevent double-spending by revealing a unique "spent" identifier.
- Wallet Scanning: Using X25519 Diffie-Hellman and AEAD encryption to allow receivers to discover their incoming shielded notes.
Combining everything into a complete ZK Spend Circuit:
- Merkle Membership Proof: Proving in-circuit that a spent note’s commitment exists in the Merkle root.
- Nullifier Derivation: Proving the nullifier was derived correctly from the wallet’s secret key and the note’s randomness.
- Algebraic Hashing: Using MiMC-lite as a ZK-friendly hash function for constraints.
- One-to-Two Spend: A circuit that consumes one input note and creates two new output notes (e.g., payment + change).
To run the tests for all levels:
cargo testTo run tests for a specific level:
cargo test -p shielded-pool-spend-05- Elliptic Curves:
curve25519-dalek,ark-bls12-381 - ZK Frameworks:
bulletproofs,arkworks(ark-groth16, ark-r1cs-std) - Encryption/Hashing:
blake3,x25519-dalek,chacha20poly1305