Certifying Zero-Knowledge Circuits with Refinement Types

Junrui Liu, Ian Kretz, Hanzhi Liu, Bryan Tan, Jonathan Wang, Yi Sun

IEEE Symposium on Security and Privacy 2024 · Day 2 · Continental Ballroom 6

Overview

This technical article delves into "Certifying Zero-Knowledge Circuits with Refinement Types," a presentation by Junrui Liu, a PhD student from UC Santa Barbara, alongside a collaborative team from institutions including UD Austin and Fraser University, and industry partners Paradise Axiom and Polychain Capital. The talk addresses a critical and often overlooked vulnerability in the burgeoning field of zero-knowledge proofs (ZKPs): the functional correctness of the underlying arithmetic circuits. As ZKPs become foundational for applications ranging from anonymous voting to privacy-preserving blockchains, ensuring that these circuits accurately implement their intended computations is paramount.

Watch on YouTube

Visual summary for Certifying Zero-Knowledge Circuits with Refinement Types by Junrui Liu, Ian Kretz, Hanzhi Liu, Bryan Tan, Jonathan Wang, Yi Sun
Visual summary for Certifying Zero-Knowledge Circuits with Refinement Types by Junrui Liu, Ian Kretz, Hanzhi Liu, Bryan Tan, Jonathan Wang, Yi Sun

Key moments

  1. 0:00 Introduction: The functional correctness problem in ZK circuits
  2. 2:00 Criticality and difficulty of ZK circuit functional correctness
  3. 3:18 Introducing Coda: a DSL for verifying ZK circuits
  4. 4:04 Coda workflow: from high-level circuit to verified proof
  5. 5:08 Example: Integer comparison circuit with refinement types
  6. 6:07 Addressing proof obligations and finite field challenges
  7. 7:16 Real-world impact: discovering bugs and verifying circuits
  8. 8:00 Conclusion: Coda is open-source, check it out!

Certifying Zero-Knowledge Circuits with Refinement Types

Speakers: Junrui Liu; Ian Kretz; Hanzhi Liu; Bryan Tan; Jonathan Wang; Yi Sun

Conference: IEEE S&P

YouTube: https://www.youtube.com/watch?v=z_anDXzSc0U

Overview

This technical article delves into "Certifying Zero-Knowledge Circuits with Refinement Types," a presentation by Junrui Liu, a PhD student from UC Santa Barbara, alongside a collaborative team from institutions including UD Austin and Fraser University, and industry partners Paradise Axiom and Polychain Capital. The talk addresses a critical and often overlooked vulnerability in the burgeoning field of zero-knowledge proofs (ZKPs): the functional correctness of the underlying arithmetic circuits. As ZKPs become foundational for applications ranging from anonymous voting to privacy-preserving blockchains, ensuring that these circuits accurately implement their intended computations is paramount.

The core problem explored is the divergence between high-level program specifications and their low-level arithmetic circuit implementations. While ZKPs offer powerful privacy guarantees, this very property can mask malicious exploits stemming from functionally incorrect circuits. A prover could craft secret inputs that satisfy a flawed circuit, leading to a valid proof for an invalid computation, all without the verifier's knowledge. This presentation introduces Coda, a novel domain-specific language (DSL) designed to bridge this gap by enabling the formal verification of ZK circuits using refinement types and machine-checked proofs, thereby enhancing the security and trustworthiness of ZKP systems.

Background

▶ Watch: Introduction: The functional correctness problem in ZK circuits (0:00)

Zero-Knowledge Proofs (ZKPs) represent a cryptographic primitive where a prover can convince a verifier that a statement is true, without revealing any information beyond the veracity of the statement itself. Specifically, in the context of computation, a prover aims to demonstrate that for some computation F and input X, the result is Y, without disclosing the sensitive input X. This privacy-preserving property has propelled ZKPs to the forefront of innovation in areas like anonymous credential systems, confidential transactions in blockchain, and secure multi-party computation.

However, the practical implementation of ZKPs presents a significant challenge: the intended computation F cannot typically be expressed as a standard program. Instead, it must be encoded as an arithmetic circuit, which is a system of polynomial constraints over finite fields. This transformation from a high-level program logic to a low-level circuit representation introduces a fundamental question: does the arithmetic circuit accurately reflect the intended computation? This alignment is termed functional correctness, and its absence can lead to severe security vulnerabilities.

Ensuring functional correctness in ZK circuits is uniquely critical and arduous. It is critical because a functionally incorrect circuit can be exploited by a malicious prover. Due to the zero-knowledge property, the verifier cannot inspect the secret inputs or intermediate states to detect such an exploit. The prover could carefully construct hidden inputs that satisfy the flawed circuit, generating a valid proof for a computation that deviates from its specification. This allows for silent exploitation, where the verifier remains oblivious to the integrity breach. The difficulty arises because developers often resort to low-level languages, such as Circom (one of the most popular ZKP programming languages), to achieve maximum performance. As demonstrated in the talk with a simple integer comparison, even basic computations can translate into highly complex circuits in these languages. This complexity, combined with the low-level nature, makes circuits highly susceptible to subtle bugs. The presenter highlighted a real-world example of an integer comparison circuit in Circom that contained a "tiny bug," which, if exploited, could silently compromise any library transitively depending on it. This combination of high criticality and inherent difficulty underscores the urgent need for robust verification methodologies in the ZKP domain, which this work directly addresses through the application of formal verification.

Key Findings

▶ Watch: Introducing Coda: a DSL for verifying ZK circuits (3:18)

The central contribution of this research is the development of Coda, a verification-friendly domain-specific language (DSL) specifically tailored for programming zero-knowledge circuits. Coda aims to simplify the complex task of ensuring the functional correctness of ZK circuits, a problem fraught with the risks of silent exploitation due to the zero-knowledge property. The key findings revolve around Coda's innovative design and its demonstrated effectiveness in real-world scenarios.

Coda's design incorporates three pivotal features. First, it empowers developers to concisely specify the functional correctness of their circuits using refinement types. These types act as formal contracts, allowing developers to precisely define the expected behavior and properties of circuit inputs, outputs, and intermediate values. This high-level specification contrasts sharply with the intricate, low-level details typically found in raw arithmetic circuit implementations.

Second, Coda provides a high level of assurance through machine-checked proofs. By integrating with interactive theorem provers, Coda ensures that the verification process is rigorous and leaves no room for human error in the proof steps. This commitment to formal methods elevates the confidence in a circuit's correctness far beyond what manual inspection or traditional testing could achieve.

Third, Coda significantly facilitates the proving process by combining interactive proving with automation. While some properties require expert guidance, Coda reduces the burden on developers by automatically discharging many verification tasks and providing reusable tactics for common, complex challenges, particularly those involving finite field arithmetic.

The practical efficacy of Coda was rigorously tested and validated. The research team utilized Coda to verify 77 real-world ZK circuits drawn from popular ZKP libraries. This extensive evaluation yielded significant results: Coda successfully identified six previously unknown functional correctness bugs. These bugs, which could have been silently exploited, highlight the critical need for formal verification in the ZKP ecosystem. Furthermore, the team not only discovered these vulnerabilities but also patched the affected circuits, making them fully verifiable. Their proactive engagement led to these patches being merged into some of the original repositories, demonstrating Coda's tangible impact on improving the security posture of existing ZK infrastructure. This practical validation underscores Coda's potential as an indispensable tool for developing secure and reliable zero-knowledge applications.

Technical Deep Dive

▶ Watch: Example: Integer comparison circuit with refinement types (5:08)

At the heart of this work is Coda, a domain-specific language (DSL) engineered to make the development and verification of zero-knowledge circuits more accessible and robust. Coda's design philosophy is to allow developers to express their intended computations in a high-level language that closely resembles normal programming, thereby abstracting away much of the low-level complexity inherent in arithmetic circuits. This conciseness is critical for readability and maintainability, but more importantly, it forms the basis for formal verification.

The cornerstone of Coda's verification capabilities lies in its use of refinement types. Unlike standard type systems that might only specify that a variable is an integer, refinement types augment these basic types with logical predicates that define precise properties or invariants. For instance, in the example of an integer comparison circuit, a refinement type might specify that inputs A and B are "binary arrays of field elements" (implying they represent integers in a specific format), and that the circuit's return value "must also be a binary field element that indicates whether A is less than B as big integers." This formal contract serves as a precise, machine-readable specification of the circuit's intended functional correctness.

The Coda type checker is the engine that consumes these refinement type contracts. It operates by breaking down the complex circuit and its high-level specification into a series of smaller, independent verification tasks known as proof obligations. These obligations represent properties that the type checker cannot automatically establish on its own and thus require explicit proof. Crucially, these proof obligations are then encoded into an interactive theorem prover, specifically Coq. Coq is a formal proof management system that allows developers to incrementally construct proofs to discharge these obligations.

A significant technical challenge in verifying ZK circuits, and a point where Coda offers a substantial advantage, is the ubiquitous reliance on properties of finite fields. Reasoning about arithmetic over finite fields is notoriously difficult for automated provers and often requires deep mathematical insight. To mitigate this burden on developers, Coda provides a rich set of reusable tactics. These tactics are pre-packaged proof strategies within Coq that automate common finite field manipulations and proofs, significantly reducing the amount of manual proof scripting required. This combination of automation for simpler cases and tactical assistance for complex finite field properties makes the interactive proving process far more manageable.

The overall workflow with Coda proceeds as follows:

  1. High-level Circuit Definition: Developers express their circuit logic using Coda's high-level syntax.
  2. Refinement Type Annotations: They augment the circuit definition with refinement types to specify its functional correctness.
  3. Type Checking and Obligation Generation: The Coda type checker analyzes the circuit and its annotations, automatically verifying straightforward properties and generating proof obligations for more complex ones.
  4. Interactive Proof Discharge: Developers use Coq, aided by Coda's reusable tactics, to prove the generated obligations.
  5. Guaranteed Correctness and Compilation: Once all obligations are successfully proven, Coda formally guarantees the overall functional correctness of the circuit. It can then compile the verified circuit into various backend constraint systems, such as R1CS (Rank-1 Constraint Systems), which are standard for ZKP implementations.

This detailed technical approach ensures that the verified circuits are not only cryptographically sound but also functionally correct, addressing a critical gap in the security assurances of zero-knowledge applications.

Demo / Proof of Concept

▶ Watch: Addressing proof obligations and finite field challenges (6:07)

While the presentation did not feature a live, interactive code demonstration in the traditional sense, the speaker effectively illustrated Coda's capabilities and workflow through a conceptual demonstration and, more importantly, through the tangible results of its application. The primary "proof of concept" for Coda is its ability to successfully identify and rectify real-world vulnerabilities.

The conceptual demonstration centered on the integer comparison circuit, which was previously identified as containing a subtle bug when implemented in a low-level language like Circom. The speaker showcased how this same computation would be encoded in Coda. The key takeaway from this illustration was Coda's ability to represent complex logic more concisely, resembling normal programming paradigms, which inherently reduces the likelihood of introducing certain classes of errors. Crucially, the example highlighted the application of refinement types to this circuit. For instance, inputs A and B could be specified as binary arrays, and the output as a binary field element representing A < B when interpreted as big integers. This process effectively demonstrated how Coda's language features allow for precise, formal specification of functional correctness directly within the circuit definition.

The subsequent stages of Coda's workflow were then elaborated: how the type checker consumed these refinement types, decomposed the specification into proof obligations, and encoded these into Coq. The role of reusable tactics in simplifying the proofs for finite field properties was also explained, showing how Coda facilitates the otherwise arduous interactive proving process.

The most compelling evidence of Coda's efficacy as a "proof of concept" lies in its application to 77 real-world ZK circuits from popular libraries. The discovery of six previously unknown functional correctness bugs in these actively used circuits unequivocally validates Coda's utility. These were not theoretical flaws but practical vulnerabilities that could have been silently exploited due to the zero-knowledge property. The fact that the research team not only found these bugs but also patched them and had their pull requests merged into upstream repositories serves as a powerful testament to Coda's practical value and its potential to significantly enhance the security posture of the ZKP ecosystem. This real-world impact far outweighs any single live code demonstration, firmly establishing Coda as a valuable tool for formal verification in ZK circuit development.

Defensive Implications

▶ Watch: Conclusion: Coda is open-source, check it out! (8:00)

The findings presented in "Certifying Zero-Knowledge Circuits with Refinement Types" carry significant defensive implications for anyone involved in the design, development, deployment, or auditing of zero-knowledge proof systems. The core message is clear: functional correctness is a critical security property in ZKPs, and traditional methods are insufficient to guarantee it.

For ZKP Developers and Engineers, the primary implication is the urgent need to adopt formal verification methodologies. Relying solely on manual review or conventional testing for ZK circuits is demonstrably insufficient, as evidenced by the discovery of six previously unknown bugs in popular libraries. Developers should:

  • Embrace DSLs like Coda: Where possible, utilize domain-specific languages that are designed with verification in mind, as they simplify both circuit expression and the application of formal methods.
  • Integrate Refinement Types: Learn to specify intended circuit behavior using formal contracts, such as refinement types. This shifts from merely writing code to formally specifying its properties, enabling machine-checked guarantees.
  • Invest in Formal Methods Training: As ZKPs become more prevalent, expertise in formal verification tools and techniques (like interactive theorem provers and proof tactics) will become indispensable for building secure systems.

For ZKP Users, Auditors, and System Integrators, the implications are equally profound. The zero-knowledge property, while beneficial for privacy, actively masks functional correctness exploits, making it impossible for a verifier to detect a malicious prover's actions post-factum. Therefore:

  • Demand Verified Circuits: Users and auditors should increasingly demand that ZK circuits, especially those handling sensitive data or high-value transactions, undergo rigorous formal verification. A cryptographic proof's soundness is only as good as the underlying circuit's functional correctness.
  • Expand Auditing Scope: Audits of ZKP systems must extend beyond cryptographic soundness and performance to include a thorough examination of the circuit's functional correctness, ideally supported by formal proofs.
  • Be Aware of Supply Chain Risks: Since libraries can transitively depend on flawed circuits, it's crucial to understand the provenance and verification status of all components within a ZKP application's supply chain.

At a broader Ecosystem Level, this work highlights a crucial gap that needs addressing:

  • Promote Research and Development: Continued investment in research and development of verification-friendly languages, automated proof tools, and specialized tactics for finite field arithmetic is essential to scale formal verification across the ZKP domain.
  • Foster Best Practices: The ZKP community needs to establish and promote best practices for circuit development that prioritize formal verification from the outset, rather than treating it as an afterthought.

In essence, the defensive posture against functional correctness bugs in ZKPs must evolve beyond traditional software security. The unique properties of zero-knowledge proofs necessitate a proactive, formal approach to circuit validation, making tools like Coda vital for ensuring the integrity and trustworthiness of future privacy-preserving applications.

Key Takeaways

  • Functional correctness is a critical and uniquely challenging security property in Zero-Knowledge Proof (ZKP) circuits. The zero-knowledge property, while providing privacy, paradoxically hides malicious exploits stemming from functionally incorrect circuits, making detection by the verifier impossible.
  • Developing ZK circuits in low-level languages (e.g., Circom) is prone to subtle, exploitable bugs, even for simple computations. This complexity, combined with the difficulty of reasoning about finite field arithmetic, makes manual verification highly unreliable.
  • Coda is a novel domain-specific language (DSL) designed to simplify ZK circuit development and enable rigorous formal verification. It allows developers to express circuits concisely and specify their intended behavior using formal contracts.
  • Coda leverages refinement types to specify functional correctness and employs a machine-checked proof workflow. This involves a type checker generating proof obligations, which are then discharged using an interactive theorem prover (Coq) aided by reusable tactics for finite field properties.
  • Coda's practical application successfully identified six previously unknown functional correctness bugs in 77 real-world ZK circuits from popular libraries. These discoveries led to patches being merged into upstream repositories, demonstrating Coda's tangible impact on ZKP security.
  • Formal verification is an essential and indispensable tool for building trustworthy and secure zero-knowledge applications. It provides a higher level of assurance for functional correctness than traditional testing or auditing alone, mitigating the risk of silent exploits.

About the Speaker(s)

The primary presenter for this work was Junrui Liu, a PhD student affiliated with UC Santa Barbara. This research represents a collaborative effort, undertaken jointly with a team of individuals from various academic and industry organizations. The co-authors include Ian Kretz, Hanzhi Liu, Bryan Tan, Jonathan Wang, and Yi Sun, who are associated with institutions such as UD Austin, Fraser University, and industry partners Paradise Axiom and Polychain Capital. The presentation itself focused on the technical contributions of this interdisciplinary team in advancing the formal verification of zero-knowledge circuits.

Reviews

Dr. Zero (Offensive Security Researcher) — MUST SEE

This research addresses a critical, often overlooked security gap in zero-knowledge proofs: the functional correctness of underlying arithmetic circuits. Coda, a novel DSL leveraging refinement types and machine-checked proofs, provides a robust solution. The discovery of six previously unknown, exploitable bugs in popular ZKP libraries unequivocally demonstrates its immediate and profound impact on ZKP security.

Heather Calloway (CISO) — STRONG ACCEPT

This research exposes a critical, silent vulnerability in zero-knowledge proof systems: the functional correctness of underlying circuits. Coda offers a tangible solution through formal verification, demonstrating its efficacy by identifying real-world exploitable bugs. This work provides a necessary path to institutional accountability for ZKP integrity.

→ Top-rated talks at IEEE Symposium on Security and Privacy 2024

All talks from IEEE Symposium on Security and Privacy 2024