Seyed Masoud Hosseini · Overview · Study log · Weekly summaries · Ideas · Search · Transcript · RSS feed
Zero Knowledge Proofs · Lecture 13 of 14 · 1:07:05
Lecture 15: Securing ZK Circuits with Formal Methods
Study guide
What this lecture covers
This lecture, given by a program-verification researcher, addresses a problem specific to zero-knowledge circuits: because a circuit consists of both witness-generation code and a separate constraint system, the two can silently diverge, letting a prover convince a verifier of something false. The lecture answers how such bugs arise, how to classify them, and how two complementary tools (an abstract-interpretation-based static analyzer and an SMT-based formal verifier) can find and eliminate them.
It sits alongside the course's other applied-security material, building on general formal-methods background from smart-contract auditing and applying it specifically to circuit correctness. After watching, you should be able to describe the difference between over-constrained and under-constrained bugs, recognize common ZK bug patterns, and understand how static analysis and SMT solving can be combined to verify a circuit is properly constrained.
Key ideas
- Abstract interpretation: a static analysis technique that computes conservative over-approximations of a program's possible states to prove the absence of certain bad behaviors, at the cost of possible false positives.
- Formal verification: proving a program matches a precise mathematical specification by reducing the question to a validity check, typically delegated to an SMT solver such as Z3.
- Witness generation vs. constraint system: a ZK circuit has two parts, the code that computes witness values and the polynomial equations that constrain them; for the circuit to be correct these two must be equivalent.
- Over-constrained bug: a valid witness computation fails to satisfy the constraints; rare in practice because it triggers an assertion failure during proving, so it is caught early.
- Under-constrained bug: some input/output pair satisfies the constraints without being a valid output of the witness computation, letting a prover fabricate accepted proofs of false statements; the more dangerous and common class.
- Circuit dependence graph: a representation of a circuit as signals (nodes) connected by data-dependency edges and constraint edges, used to query for known under-constrained bug patterns.
- Picus: a verification tool combining static analysis and SMT solving in a loop, each supplying information the other cannot derive alone, to prove a circuit is well-constrained, find a counterexample, or report unknown.
Walkthrough
Why ZK bugs matter (0:01)
The lecture opens with examples of costly blockchain bugs, including a smart-contract exploit and a bug in the original Zcash protocol that allowed counterfeit coins to be minted. It frames formal methods, ranging from testing to abstract interpretation to full formal verification, as a spectrum trading manual effort for stronger correctness guarantees.
Abstract interpretation fundamentals (3:03)
The lecture explains how abstract interpretation reasons about programs by computing over-approximations of possible states, using interval abstraction as a running example, and shows how imprecise abstractions cause false positives or false negatives. It then applies this to a classic reentrancy attack pattern in smart contracts, showing how the vulnerability can be encoded as a pattern over external calls followed by storage updates.
Formal verification fundamentals (16:14)
The lecture introduces formal verification as checking code against an explicit specification, using a verification condition generator to turn code and specification into a logical formula that an SMT solver checks for validity. It notes the tradeoffs: stronger guarantees than static analysis, but a need for manual specifications and solvers that struggle with the non-linear, finite-field arithmetic common in ZK circuits.
A taxonomy of ZK circuit bugs (26:24)
Drawing on a large-scale study of open-source ZK projects, the lecture defines the equivalence property a circuit must satisfy and categorizes real bugs found in the wild: under-constrained output signals (such as an off-by-one loop bound that leaves an output array element unconstrained), unsafe component usage where a subcircuit's output is not constrained by its caller, and mismatches between constraints and witness computations, such as a modular-inverse gadget that fails to reject division by zero.
Detecting bugs with the Vanguard static analyzer (36:35)
The lecture describes representing a circuit as a circuit dependence graph and encoding bug patterns as queries over that graph, implemented in the Vanguard framework for Circom and Halo2. Run on 258 circuits from 17 open-source projects, the tool found 32 previously unknown vulnerabilities, most acknowledged by the projects, with under-constrained signals being the most common category.
Formally verifying circuits with Picus (54:49)
The lecture presents Picus, which combines static analysis (scalable but prone to false positives) with SMT solving (precise but hard to scale) in an iterative loop: each phase grows a set of signals proven well-constrained and passes progress to the other phase until the circuit is proven safe, proven under-constrained, or the result is inconclusive. Evaluated on 163 Circom circuits, Picus outperformed either technique alone, especially as circuit complexity grew.
Open problems (1:04:57)
The lecture closes on open challenges: specifying properties involving complex cryptographic primitives, building solvers that reason efficiently about finite fields, generating concrete counterexamples when verification fails, and extending these techniques beyond Circom and Halo2 to other proof systems.
Before you watch
- Familiarity with how ZK-SNARKs turn a program into a prover and verifier, from earlier lectures in this course.
- Basic exposure to smart-contract vulnerabilities such as reentrancy attacks is helpful for the abstract-interpretation examples.
- No prior formal-methods background is assumed; the lecture defines its terms as it goes.
Check your understanding
- What is the difference between an over-constrained bug and an under-constrained bug, and why is the latter more dangerous?
- Why do over-constrained bugs tend to get caught early, while under-constrained bugs can go undetected until exploited?
- How does a circuit dependence graph help detect an under-constrained output signal?
- Why does Picus combine static analysis with SMT solving instead of relying on just one technique?
- Why do existing SMT solvers struggle with verifying ZK circuit constraints compared to typical program verification tasks?
Vocabulary
- formal methods (noun)
- Mathematical techniques used to prove software behaves correctly.
Formal methods can catch bugs before code reaches production. - abstract interpretation (noun)
- A technique that predicts a program's possible behaviors without running it exactly.
Abstract interpretation computes safe over-approximations of program states. - over-approximation (noun)
- A prediction that includes more possibilities than could really happen, to stay safe.
An over-approximation may cause false alarms but never misses a real bug. - SMT solver (noun)
- A tool that automatically checks whether a logical formula can be made true.
An SMT solver checks whether the code matches its specification. - specification (noun)
- A precise, formal description of what a program is supposed to do.
Formal verification checks code against an explicit specification. - over-constrained bug (noun)
- A bug where a valid computation fails to satisfy the circuit's rules.
An over-constrained bug is usually caught right away by an error. - under-constrained bug (noun)
- A bug where extra, invalid inputs can still pass the circuit's checks.
An under-constrained bug can let a prover fake a proof of something false. - dependence graph (noun)
- A diagram showing which parts of a program depend on which other parts.
A circuit dependence graph maps signals and their constraints. - reentrancy attack (noun)
- A hacking technique where a contract is called again before it finishes updating its state.
A reentrancy attack was a famous cause of stolen blockchain funds. - counterexample (noun)
- A specific case showing that a claim is false.
The tool can generate a counterexample when a circuit is unsafe. - equivalence (noun)
- The property of two things being logically the same or matching.
The circuit must satisfy an equivalence property between its two parts. - unsafe usage (phrase)
- Using a component in a way that skips necessary safety checks.
Unsafe component usage happens when a subcircuit's output isn't constrained. - acknowledge (verb)
- To admit or confirm that something, like a bug report, is valid.
Most of the 32 vulnerabilities found were acknowledged by the projects. - false positive (phrase)
- A warning about a problem that doesn't actually exist.
An imprecise abstraction can cause false positives during analysis. - false negative (phrase)
- A missed detection where a real problem goes unreported.
A weak analysis risks a false negative, missing a real bug. - taxonomy (noun)
- A system for classifying things into categories.
The lecture builds a taxonomy of real ZK circuit bugs. - scalable (adjective)
- Able to handle growth in size or complexity without breaking down.
Static analysis is scalable but sometimes less precise. - exploit (noun)
- A way of taking advantage of a bug to cause harm or theft.
A smart-contract exploit can drain funds from a protocol. - loop bound (phrase)
- The limit that controls how many times a loop repeats.
An off-by-one loop bound can leave a signal unconstrained. - manual specification (phrase)
- A description of correct behavior written by hand by a person.
Formal verification needs a manual specification to check code against.
Chapters
- 0:00 Introduction to ZK Security
- 2:29 Formal methods overview
- 5:10 Abstract interpretation
- 9:07 Finding bugs with abstract
- 16:13 Formal verification
- 23:08 Verification tools and trade-offs
- 26:09 ZK circuit components
- 31:59 ZK bug taxonomy
- 37:08 Detecting bugs with static analysis
- 45:44 Vanguard framework
- 53:46 Formal verification of ZK circuits
- 57:54 Picas tool and evaluation
- 1:04:51 Conclusion and future directions
From the YouTube description
Yu Feng, Zero Knowledge Proofs MOOC
← Lecture 12: zkEVM Design, Optimization and Applications · Lecture 16: Hardware Acceleration of ZKP →
