ZK/SEC Research notes from zkSecurity
All posts
educative · security · zk

Why does FRI work?

The FRI protocol is a key building block for many SNARKs deployed in production today. There are plenty of great lectures out there explaining what FRI is and how it works. Among them, I highly recommend the ZK Whiteboard Session modules with Dan Boneh (S2M7, S2M8). For those who prefer a more practical introduction, I recommend following a tutorial with accompanying code, for example Part III of STARK 101 by StarkWare.

In this post, I won't rehash the contents of the amazing tutorials listed above. I want to answer the question: why is FRI secure? Why does the execution of this protocol gives us satisfactory guarantees that the prover's initial message is close to a Reed-Solomon codeword?

These questions are usually answered by the security proof of a protocol. Needless to say, the security proof of FRI is not an entry-level read. However, with co-authors Albert and Benedikt, I recently attempted to give a simpler proof (available on ePrint). This post is a summary of the ideas we used there.

I'll assume that readers are familiar with FRI and its associated tools and jargon. I'll first go through a quick recap of the mechanics of the protocol, mostly to define the notation I will use throughout. Then I'll introduce the "prover message graph", a useful tool for the security proof of FRI. After that, we will discuss a key security property of the "folding" operation used in FRI and finally argue that the protocol is secure.

FRI recap and notation

The FRI protocol is used to prove that a prover function $f_0$ is close to a given Reed-Solomon (RS) code. It works by successively "folding" the prover's function using a verifier challenge. Eventually, when the function is small enough, the verifier can read it in full and check that it is a codeword from a smaller RS code. The verifier then performs spot checks between all the prover's messages to ensure that the fold operation was computed correctly.

In this article, I will use the notation $\mathsf{RS}[\mathbb{F}, \mathcal{L}, d]$ to denote a Reed-Solomon code defined over the finite field $\mathbb{F}$ with evaluation domain $\mathcal{L} \subseteq \mathbb{F}^*$ and degree bound $d \in \mathbb{N}$. The rate of an RS code is written $\rho = d / |\mathcal{L}|$.

Concretely, I will consider the example where the initial domain $\mathcal{L}_0$ is the $16$-th roots of unity and the initial degree bound is $d_0=8$. Consecutive codes are defined over the $8$-th, $4$-th and $2$-th roots of unity with degree bounds $4$, $2$ and $1$. I'll write $f_0, f_1, f_2, f_3$ to denote the prover messages and $\alpha_1, \alpha_2, \alpha_3$ to denote the verifier's folding challenges.

Tracking prover messages

The first thing we need to be aware of in our security analysis, is that the prover might have sent a function $f_{i+1}$ that is not $\mathsf{Fold}(f_i, \alpha_{i+1})$ (i.e., the honest fold of $f_i$ using the challenge $\alpha_{i+1}$). To this end, we define the prover message graph. Each layer of the graph represents an evaluation domain and the prover message on that domain. We can draw edges between layers when the points are related: for example both the points $s$ and $-s$ in layer $0$ have an edge going to the point $s^2$ in layer $1$. The graph is illustrated below.

A prover message graph before coloring.

We can now color the graph to indicate what will happen when the verifier runs the query phase. We'll use green to indicate an accepting query and red to indicate a rejected query. To perform the coloring, we consider nodes in groups of 3: one node in layer $i$ and its two relatives in layer $i-1$. If the $\mathsf{Fold}$ operation is computed correctly on those nodes, we leave them as they are; otherwise if $\mathsf{Fold}$ is incorrect, we mark the node on layer $i$ with an $\mathbf{X}$. Concretely, using the labelling from the image above, we would consider the group $(s, -s, s^2)$, compute $\mathsf{Fold}(f_{0}, \alpha_1)(s^2)$ from $f_0(s)$ and $f_0(-s)$, and mark the node $s^2$ with an $\mathbf{X}$ if that value was not consistent with $f_1(s^2)$. This is exactly what the verifier does with its check!

Once we've considered all groups of three, we can assign colors. All paths that start from a leaf in layer $0$ and terminate with an $\mathbf{X}$ are marked red (excluding the $\mathbf{X}$). We do this to reflect the fact that starting from such leaves, the verifier will inevitably arrive to the $\mathbf{X}$ and notice the inconsistency. All other nodes are colored green. An example is given below.

A prover message graph with coloring.

At this point, I would like to highlight some important intuition about the colored graph:

  1. If the verifier queries layer 0 at a red node, it will reject. Therefore, the fraction of green nodes is exactly the probability that the verifier accepts.

  2. Red propagates upward from an $\mathbf{X}$. This means that prover does not gain an advantage by folding dishonestly. In addition, we see that the later it does so (e.g., at the final round), the more it reduces the probability of getting accepted.

  3. The set of green nodes represents the sets where all folds are performed honestly.

Now the key question remains: why can we deduce that $f_0$ was close to $\mathsf{RS}[\mathbb{F}, \mathcal{L}_0, d_0]$ when there is a large fraction of green nodes in layer $0$? As we will see next, this is due to the fact that the verifier checks that the final function is in the final code and from an important security property of $\mathsf{Fold}$.

Key property of $\mathsf{Fold}$

At the end of the FRI interaction, the verifier reads the final function in full and checks that it is in the final code. In our example, the verifier reads $f_3: \mathcal{L}_3 \to \mathbb{F}$ and checks that it is a constant polynomial. Ideally, this observation could "bubble up" through the prover message graph. We can state an ideal property as follows:

  • (ideal property) if there exists a codeword $u_i \in \mathsf{RS}[ \mathbb{F}, {\mathcal{L}_i}, {d_i} ]$ that agrees with $f_i$ on green nodes, then there exists a codeword $u_{i-1} \in \mathsf{RS}[ \mathbb{F}, {\mathcal{L}_{i-1}}, {d_{i-1}} ]$ that agrees with $f_{i-1}$ on green nodes.

With such a property our task would be solved! We would inductively apply the property working our way up the graph and find that the fraction of green nodes in layer $0$ is at least the agreement between $f_0$ and a codeword. Unfortunately, things are not so simple. The ideal property does not always hold.

What we can do on the other hand is to relax this property and only require that it holds with high probability over the verifier's folding challenges. The yields the following real property:

  • (real property) if (a) there is a large fraction of green nodes and (b) there exists a codeword $u_i \in \mathsf{RS}[\mathbb{F}, {\mathcal{L}_i}, {d_i}]$ that agrees with $f_i$ on green nodes, then with high probability over the verifier message $\alpha_i$ there exists a codeword $u_{i-1} \in \mathsf{RS}[\mathbb{F}, {\mathcal{L}_{i-1}}, {d_{i-1}}]$ that agrees with $f_{i-1}$ on green nodes.

The notion of what is a "large fraction" of green nodes is intentionally loose. Let's denote $\mathsf{B}^\star$ to be the measure of "large enough". Ideally we want $\mathsf{B}^\star$ to be low as we will see in our argument later (see Final argument, case 1). Currently, we have satisfactory results for the case $\mathsf{B}^\star = \frac{1+\rho}{2}$. There are private drafts making the rounds that prove the property for $\mathsf{B}^\star = \sqrt{\rho}$ and we even conjecture that this fraction can be as small as $\mathsf{B}^\star = \rho$ (recall that $\rho < 1$ and therefore $\rho < \sqrt{\rho}$). Proving this property for small bounds is an open problem for which the Ethereum Foundation is setting up to one million dollars (!!) in prizes.

Final argument

We can now finish our security analysis using the "real property" that allows to bubble up agreement through large enough sets of green nodes in the prover message graph. The only subtlety is that we need to deal with the case where there is less than a $\mathsf{B}^\star$-fraction of green nodes at any layer of the graph. We argue by separating two cases:

  1. Case 1, there is a layer $i$ which has less than a $\mathsf{B}^\star$-fraction of green nodes.

  2. Case 2, all layers have at least a $\mathsf{B}^\star$-fraction of green nodes.

Case 1: small fraction of honest folds

We first consider the case where there is at least one layer where the real property cannot be applied. That is, the $i$-th layer has less than a $\mathsf{B}^\star$-fraction of green nodes. Equivalently, this layer must have at least a $(1- \mathsf{B}^\star)$-fraction of red nodes. The figure below shows an example of "case 1".

Recall that by our graph coloring rules, all paths that lead to an $\mathbf{X}$ are marked red. From this rule, it is easy to establish that "red always propagates upwards". Therefore, we can show that if there is a layer where there is at least a $(1- \mathsf{B}^\star)$-fraction of red nodes, all layers above it will also have at least a $(1- \mathsf{B}^\star)$-fraction of red nodes. In particular, layer $0$ has at least a $(1- \mathsf{B}^\star)$-fraction of red nodes.

From this discussion, we conclude that layer $0$ has at most a $\mathsf{B}^\star$-fraction of green nodes and that the verifier will accept with probability $\mathsf{B}^\star$. In practice, we want to reject provers that behave as in case 1 and therefore want $\mathsf{B}^\star$ to be as small as possible.

Case 2: large fraction of honest folds

For case 2, we can refer to the illustration given in Figure 2. Since the sets of green nodes are large enough, we can apply our "real property" and conclude that agreement bubbles up assuming that all folding challenges were "good". Therefore, conditioned on having only "good" challenges, the agreement between $f_0$ and the initial code $\mathsf{RS}[\mathbb{F}, \mathcal{L}_0, d_0]$ is at least the fraction of green nodes in the top layer. Alternatively, in terms of distance (rather than agreement) we have shown that the verifier's acceptance probability is at most $1-\delta$, where $\delta = \Delta(f_0, \mathsf{RS}[\mathbb{F}, \mathcal{L}_0, d_0])$ is the relative distance between $f_0$ and the initial code.

Conclusion

This concludes our overview of how FRI works! The argument stems from an important property of the $\mathsf{Fold}$ function: "agreement bubbles up the graph" when there is a large enough fraction of honest folds. We deal with the case where the fraction of honest folds is not large enough by arguing that there must be a large fraction of dishonest folds. In such a case, the verifier is likely to query them and reject.

There is ongoing research on proving that the property holds for a notion of "large" that is as small as possible. This allows us to stay in case 1 as much as possible and gives us a tighter security bound. In return, tighter bounds allow us to have shorter proofs and do less prover and verifier work for the same level of security.

Acknowledgements

Thank you to Varun Thakore, 0xteddav (David), Albert Garreta and Kobi Gurkan for carefully proof-reading this article and sharing many helpful questions, corrections and suggestions.

Keep reading
Latest

Variants of KZG: Part III, Multilinear Commitments with Zeromorph

In this blog post, we extend univariate KZG commitments to multilinear polynomials through Zeromorph. We introduce the univariatization map, encode the multilinear quotient identity as a univariate identity, and explain why the quotient encodings require degree checks. We then show how Zeromorph batches these checks into a single degree-bounded KZG opening and walk through its end-to-end opening protocol. We conclude by examining its proof size, prover cost, and verifier cost.

Varun Thakore · August 04, 2026

Variants of KZG: Part II, Multilinear Commitments with PST

In this blog post, we extend the ideas behind univariate KZG commitments to multilinear polynomials through the PST commitment scheme. We derive the multilinear quotient identity, explain how PST commits to and opens multilinear polynomials using a specialized multilinear setup and walk through its opening protocol. We conclude by examining the proof size, prover and verifier costs, and the limitations that motivate other multilinear polynomial commitment schemes.

Varun Thakore · July 28, 2026

Threshold ECDSA: Building CGGMP from scratch

A step-by-step build of CGGMP, an n-of-n threshold ECDSA scheme where parties jointly produce a signature without ever reconstructing the private key. We start from the multiplicative-to-additive (MtA) protocol and a semi-honest version of the signing protocol, then harden it into a maliciously secure one by layering in zero-knowledge proofs at each step. Along the way we cover the auxiliary Ring-Pedersen and Paillier parameters and the proofs that make them safe to use.

Samuel Tang · July 27, 2026
Recommended

Proximity Gaps: What Happened and How Does It Affect our SNARKs

A series of recent papers just disproved the proximity gaps conjecture, which has everyone wondering if hash-based SNARKs are in trouble. We break down what actually happened using some helpful visuals. Think of it as understanding which parameter choices are safe versus which ones are now confirmed to be risky. The post walks you through the different security zones (proven safe, conjectured safe, and definitely not safe), explains how these new results connect to other open math problems, and shows what it means for real-world SNARKs in terms of proof sizes and performance trade-offs.

Nicolas Mohnblatt · November 14, 2025

Lean4 formalization of "A Simplified Round-by-round Soundness Proof of FRI"

A Lean4 formalization of the paper "A Simplified Round-by-round Soundness Proof of FRI" by Albert Garreta, Nicolas Mohnblatt, and Benedikt Wagner, completed using Harmonic's Aristotle agent and Claude Code. Welcome to the strange world of machine-led formalization of cryptography.

Yoichi Hirai · January 26, 2026

Circle STARKs: Part I, Mersenne

Discover the intriguing world of Circle STARKs and how they can supercharge zero-knowledge proofs. This blog post sets the stage for a fascinating series about utilizing Mersenne prime fields to achieve lightning-fast arithmetic operations in STARK systems. You'll explore recent breakthroughs that make these fields more practical despite their previous limitations, and you'll get a sneak peek at what’s to come, including delving into group structures and implementing circle FFTs. If you're keen on cryptography and zero-knowledge proofs, this series will unveil how modern advancements are pushing the boundaries of what's possible.

Mathias Hall-Andersen · June 03, 2024
More to explore

Uncovering the Phantom Challenge Soundness Bug in Solana's ZK ElGamal Proof Program

In June 2025, we uncovered a serious soundness issue in Solana's ZK ElGamal Proof Program that could let attackers manipulate confidential token transfers undetected. We worked with the Anza team to quickly address the flaw by pausing and disabling vulnerable components. This post dives into the root cause, which was a subtle mistake in handling prover-generated challenges within sigma OR proofs, revealing broader lessons in zero-knowledge protocol security. If you're interested in cryptographic protocol design, this could provide valuable insights.

Suneal Gong · June 26, 2025

ZK programmability adds a whole new layer to worry about

Zero-knowledge (ZK) programs are revolutionizing how developers can build secure systems by proving execution without exposing data, making them incredibly useful for privacy and security. However, they come with their own set of challenges. In this blog, we delve into these security implications and offer practical strategies to help developers navigate the risks. From understanding private inputs to the intricacies of proof systems and trusted setups, we unpack the complexities and provide insights on how to address potential pitfalls, ensuring you're well-prepared to harness the power of ZK programs effectively.

David Wong · May 31, 2023

Projects That Shaped Modern zkVMs, Part 1

Curious about how zero-knowledge virtual machines (zkVMs) make computing more secure without the hassle? We delve into the fascinating world of zkVMs, where you can program in high-level languages like Rust or C and let cryptography handle the complexity. We'll explore the evolution of these innovative systems through projects like Cairo and RISC Zero, while touching on the unique benefits and technical insights each brings. Plus, learn about groundbreaking techniques for optimizing zkVMs with projects like Jolt, and discover a range of other influential zkVM initiatives. Get ready for an enlightening journey into secure computation!

Marco Besier, David Wong · February 26, 2025