Batched Openings
The inner product argument proves one evaluation claim about one committed polynomial. A complete proof makes several such claims, about different polynomials at different points, and running the argument once per claim multiplies its cost. This chapter reduces any number of claims to a single claim, so that the argument runs only once.
The reduction has two stages. The first moves every claim to one fresh random point with the help of quotient polynomials, and the second combines the resulting claims at that point using a random linear combination. The Ragu Book calls these stages alpha batching and beta batching after their challenges, and the literature calls the whole technique a batched opening or a multi-opening.
1. Why a proof makes many claims
The next chapter assembles a complete proof, and its final step in the Ragu Book lists the claims that the verifier needs checked. We will meet these polynomials properly in that chapter. For now, the shape of the list is what matters:
That makes six claims about four polynomials at the four points , , and . Later chapters add more, because a recursive step also has to handle the claims it inherits from earlier proofs. Each separate opening carries group elements for a polynomial with coefficients, and it costs the verifier a linear amount of curve work:
Take with 32-byte values, and the six claims above. Six separate arguments carry group elements, or bytes. One batched argument carries group elements, plus the extra commitment and the scalars that this chapter introduces, for bytes. Both counts leave out the small constant number of extra values that each argument carries.
We write one claim as a triple , which says that the polynomial behind the commitment satisfies . Both parties hold the triples, and only the prover holds the polynomials. The goal is a short exchange after which both parties hold a single triple , with the property that a false input claim leads to a false output claim, except with negligible probability.
The name needs a warning, because it has a different meaning in the commitments chapter. There, was the statement point of an opening. In this chapter is a plain commitment to a polynomial , which is the Ragu Book's usage, so the statement point for the output claim would be .
2. Combining claims at different points
The random linear combinations from chapter 03 already solve the problem when all the claims use one point. If and , the verifier picks and asks about at . It can compute the commitment and the expected value alone, because commitments and evaluations combine with the same coefficients.
The method stops working when the points differ, because a combination of polynomials has no single point at which the combined claim makes sense:
Suppose the prover claims and , with the polynomials and . Take . The combination has the value at and the value at , while the combined claim is . The claimed number matches neither value, even though both claims are true, because the value at needs and nobody has said anything about that.
We therefore need some way to convert a claim at into a claim at a point shared by all the others. Since the verifier's challenge can supply such a point, we look for a way to restate as a fact that holds everywhere, so that it can be tested anywhere.
3. Writing a claim as a division
The statement says that the polynomial has a root at . Chapter 03 showed that each root gives a linear factor, so the claim holds exactly when there is a polynomial with
We call the quotient of the claim. To see how the prover computes it, and why a false claim has no quotient, write out the case . Then has coefficients , the quotient has degree 2, and we can write . Multiplying out the right side gives
Matching each power of against produces four equations:
The first three equations determine the quotient from the top coefficient down, and plays no part in them. Solving them gives , then , then . Only the last equation mentions , and rearranging it gives
So the system has a solution exactly when the claim is true. This procedure is called synthetic division, and the same pattern works for any .
Take and , so .
| Line | Formula | Value modulo 43 |
|---|---|---|
The quotient is , and the last line recovers , the value of from the commitments chapter. Multiplying out returns , which equals with coefficients reduced modulo 43.
Here is what the same computation does when the claimed value is wrong:
Suppose the prover claims instead. The first three lines of the table do not involve , so they produce the same . The last line still computes , which contradicts the claim. Expanding shows the same mismatch, since while the claim needs . No polynomial can repair this, because at the product is zero for every , whereas .
A false claim therefore has no quotient polynomial. The fraction still exists as a rational function, with a pole at that no polynomial can reproduce, and the protocol below relies on that difference.
4. Moving one claim to a new point
The equation is an identity between polynomials, so it holds at every point. For any , dividing by the nonzero number gives
This relation gives us a test at a point unrelated to . The prover commits to first, which fixes it. The verifier then picks a random , the prover sends the value , and the verifier computes what has to be from the formula. What remains are two claims at the point . The original commitment must open to the sent value, and the quotient's commitment must open to the computed value. The point appears only in the verifier's arithmetic and in no remaining opening.
Take a second polynomial , with the commitment and the claim . Division gives .
| Step | Party | Value or check |
|---|---|---|
| 1 | Prover commits to the quotient | |
| 2 | Verifier sends a challenge | |
| 3 | Prover sends the value of at | |
| 4 | Verifier derives the value of at |
The commitment must now open to at , and must open to at . Evaluating the quotient directly confirms that .
For one claim this looks like a step backward, because it replaced one opening with two. The gain appears with several claims, since every claim can use the same , and the same-point method of Section 2 then applies to all of them.
The test also has the behaviour we want for a false claim. If , whatever polynomial the prover commits to differs from the rational function, so the formula gives the wrong value at most values of . To count the exceptions, multiply through by . The formula matches only where vanishes, and this polynomial is nonzero because a false claim has no quotient. Its degree is at most , since the commitment limits to degree , so it has at most roots and the prover has at most an chance of passing.
5. Alpha batching
With claims, a separate commitment to each quotient would add curve points to the proof. Commitments add in the same way as polynomials, so the prover can send one commitment to a combination of the quotients. Our running example has three polynomials with one claim each:
| Claim | Polynomial | Point | Value | Commitment | Quotient |
|---|---|---|---|---|---|
| 0 | 9 | 37 | |||
| 1 | 5 | 20 | |||
| 2 | 2 | 41 |
The combination cannot be a plain sum, because errors at a shared point can cancel. Two false claims at the same have remainders over the same denominator, and a cheater can choose those remainders to be opposite:
The true values at are and . A cheater claims and , so both claims are false. The errors are opposite, so still has a root at and division by leaves no remainder. The result is the genuine polynomial , which the cheater can commit to and open at any point.
Giving each quotient a different random weight prevents this, which is the same reasoning as for powers of one challenge. The verifier sends a challenge after the claims are fixed, and the prover forms
For three claims this is . The first claim takes the highest power, which is the order Ragu's code uses, and Section 7 compares it with the book's order. The weights rule out the cancellation above:
With the weights and , the two errors from the previous example leave the remainder over . Trying all 43 values of finds that only removes it, and that value is the plain sum.
The prover now computes for the running example and commits to it. A quotient has degree , so fits within the generators, with a zero in the top position.
Take , so modulo 43. Each column of the next table combines one power of .
| Term | |||
|---|---|---|---|
| 32 | 32 | 3 | |
| 12 | 28 | 4 | |
| 41 | 16 | 6 | |
| 3 | 25 | 26 |
The prover commits to and sends the single point .
The commitment fixes before the next challenge. The prover has not sent any of the individual quotients, and the verifier does not need them.
6. Moving every claim to u
The verifier now sends a random point . Section 4 gave a formula for one quotient at , and because is a combination of the quotients, the same weights carry over to its value. Substituting term by term gives
The right side uses only the values together with numbers the verifier already holds, so the prover sends those values and the verifier computes for itself. The formula divides by , which would fail if landed on one of the original points. On a real curve this has negligible probability, and the compression verifier rejects if it happens.
Take . The prover sends , and , and the verifier computes each term from those values and the original claims.
| Weight | Weighted term | ||||
|---|---|---|---|---|---|
| 0 | 14 | 8 | 24 | 35 | 23 |
| 1 | 11 | 12 | 10 | 11 | 24 |
| 2 | 1 | 15 | 26 | 1 | 26 |
The last column sums to modulo 43. The prover, who holds , gets the same number by direct substitution into . The verifier has obtained this value without seeing .
The verifier now holds claims that all use the point . The commitment must open to the computed , and each must open to the sent . The obstacle from Section 2 has gone, because no remaining opening refers to the points . The original claims have not disappeared, however, since each and now sits inside the formula for , and a false makes that number wrong.
7. Beta batching
Since all the claims now use one point, a random linear combination finishes the job. The verifier sends a challenge after the prover has sent its values, and the prover forms
For three claims this is . The verifier cannot compute , but linearity gives it everything else. The commitment comes from the homomorphic property, and the value comes from substituting into the definition of :
The output is the triple , a claim of exactly the form the inner product argument proves.
Take , whose powers modulo 43 are and .
| Input | Weight | Commitment | Value at | Coefficients |
|---|---|---|---|---|
| 30 | ||||
| 14 | ||||
| 11 | ||||
| 1 | ||||
| Combined |
The verifier derives and from the first four rows, using only group operations and field arithmetic. The prover derives the coefficients of . Committing to those coefficients gives , and substituting into gives , so both agree with what the verifier computed.
The polynomial needs a weight of its own, distinct from the weight of every . If two inputs share a weight, an error in one can cancel an error in the other for every . The book's formulas leave this point open, because they do not state where the index starts:
The Ragu Book and the code differ here
The book writes and and does not state the range of . The compression verifier at commit 3219e08 gives the first claim the highest power of , gives the highest power of , and gives the last polynomial weight 1. This site follows the code. A different order of distinct weights only relabels the inputs, so the book's formula read with starting at is equally good, and that is the form the Halo 2 book uses for its final polynomial.
Reading the book's sum from would not be safe, since and would then both have weight 1. We do not suggest the authors intend this reading, and the code's distinct weights do not have this collision. The collision comes from the sum alone, so the range of the sum makes no difference to it. The toy curve shows why the index matters:
Keep the false claim , and use the sum from in both places, so that and both have weight 1 in . The cheater commits to the honest , which at is . At the derived value misses by . The cheater then sends for , a shift of . The shift changes the derived value of and the term of , and the two changes add up to exactly that miss. No power of appears in this equation, so we checked that the forged message passes for all 43 values of . The attack works at 39 of the 40 allowed values of , for a total of of the pairs . This forgery fails only at , where modulo 43.
8. The complete protocol
The following diagram shows what the two stages do to the claims, and the sequence after it lists the messages.

The soundness of the protocol depends on the order of these messages, as Section 9 explains. Under Fiat–Shamir, each challenge becomes a hash of a transcript that has absorbed everything before it, including the claims themselves. The worked examples here use chosen challenges so that the numbers stay readable.
Here is the whole run, gathered from the previous sections. For the last step, the prover reveals , and the verifier checks it directly:
| Step | Party | Value or check |
|---|---|---|
| 0 | Both hold the claims | , , |
| 1 | Verifier sends a challenge | |
| 2 | Prover commits to | |
| 3 | Verifier sends a challenge | |
| 4 | Prover sends the values at | |
| 5 | Verifier sends a challenge | |
| 6 | Verifier derives | |
| 7 | Verifier derives the output claim | , |
| 8 | Prover reveals | |
| 9 | Verifier checks the commitment | , which equals |
| 10 | Verifier checks the value | , which equals |
Steps 8 to 10 are the expensive ones. The Ragu Book's NARK really does finish this way, with the prover sending in full, and the next chapter returns to that choice. A succinct proof replaces those three steps with one inner product argument for , as compression does in the code.
9. Why cheating fails
The argument below relies on three assumptions. Commitments are binding under the discrete log relation assumption, the final opening is sound, and Fiat–Shamir challenges behave like uniform random values that nobody can predict before the preceding messages are fixed, which is the random oracle assumption.
Take one false claim in the running example. We follow what a cheater can try at each stage, and we count its success on the toy field by trying every challenge.
The cheater commits to the quotients and reports true values
A cheater who runs the honest division gets a perfectly good polynomial , because division ignores . The false value only shows up later, inside the verifier's formula.
The cheater claims , whereas the true value is . It computes the quotients by the division table, which ignores , and commits to the same , then reports true values at . The false enters the verifier's formula, and at the derived value is while , a gap of . We tried every pair of challenges, with 40 allowed values of and 43 of . The gap is nonzero at all 40 values of , and the only passing runs are the 40 that have .
The gap is never zero here, because it equals a nonzero weight times a nonzero remainder, divided by . The check at passes only because then removes from altogether, and a random avoids that value except with probability .
The cheater lies about a value at u
To close the gap, the cheater can change a value that it sends at . This moves the error from the formula for into the term for , where catches it instead:
At the cheater sends for in place of the true , a shift of chosen so that the derived value equals . In effect it reports values of , a polynomial that does satisfy the false claim, while its commitment still holds . The output claim now carries that shift. With , the value and the true differ by , so the check fails. Of the 43 values of , only passes.
The cheater can also spread its lies across all the values. Let be the error in the derived , and let be the error in the sent . The difference between and the true value of at is
which is a polynomial in of degree at most . All of its coefficients are fixed before is chosen. If any of them is nonzero, at most values of make it vanish.
Fix and as above. The cheater can send any of triples of values. Trying all of them against all 43 values of shows that no triple passes for more than values of , which agrees with the fact that the error is a nonzero polynomial of degree at most 3 in .
The cheater commits to a different polynomial
The remaining option is to commit to something other than the quotients, chosen so that the formula holds with true values at as many points as possible. Suppose the claims use distinct points. Clearing denominators by multiplying through by the product of the for those points turns the requirement into a polynomial equation in of degree at most . It is not identically zero as long as the combined fraction has a pole. The cheater therefore matches at most values of . In our example only one claim is false, which leaves one pole, and the count is :
The cheater can make the committed polynomial match the verifier's formula at a few values of by interpolation. Through the four points it gets , with commitment . If the challenge lands on one of these four values, the cheater reports true values and passes for every . If it lands anywhere else among the 40 allowed values, this polynomial does not match. We tried all polynomials of degree at most 3. None matches the formula at more than points, and exactly reach , one for each choice of four points.
The numbers on the toy field are large only because the field has 43 elements:
Combining the counts bounds the best cheater on the toy curve. It wins on at most of the 40 values of outright and on at most of the 43 values of at each of the other , which is at most of the pairs of challenges.
The cheater hopes for a cancelling alpha
Section 5 showed that false claims at a shared point can cancel for one particular . If they do, the combined fraction has no pole, and the cheater holds a genuine that passes everything afterwards. With claims, the leftover remainder at a point is a nonzero polynomial in of degree at most , so at most values of remove it.
Adding the three stages gives a bound of , where is the number of polynomials. The running example has , and Section 10 covers claims that share a polynomial, for which is smaller.
For , with the six claims, four points and four polynomials from Section 1, the three bounds add up to . For a field of about elements, as with the Pasta curves, this is below . The fuse step draws from a 143-bit endoscalar, as Section 13 notes, and with that range the term alone is about and dominates the sum.
Fiat–Shamir lets a cheater retry privately, so as chapter 03 explains, the chance grows with the number of attempts. We make no claim about Ragu's overall security level here.
Each challenge has to come after the message it tests
All of these counts assume the cheater does not know a challenge when it sends the message that the challenge tests. The protocol fails if any challenge arrives early:
Suppose the cheater learns before it makes its two claims at the point . It claims and , whose errors and satisfy modulo 43. Both claims are false, yet is divisible by , which gives the genuine polynomial . This cheater passes for all 42 values of and all 43 values of , a total of of runs.
Suppose the cheater learns before it commits. The interpolated polynomial from earlier in this section matches the formula at that point, so the cheater commits to it, reports true values, and passes for all 43 values of .
Suppose the cheater learns before sending the values at . It sends for , with the shift solved from the one linear equation that makes the total error vanish at this . The check passes. Moving to makes the same message fail.
Binding at the end
The check on means something only because can be opened in one way. Every polynomial above was fixed by its commitment, and a prover who knows a relation among the generators loses that restriction:
Using the known discrete logs of the toy generators, a prover can adjust entries 0 and 1 of to get . This vector commits to the same and evaluates to at , not . A prover with this ability could satisfy the final check for a wrong , which is why the discrete log relation assumption is necessary.
10. Claims that share a polynomial or a point
The running example gave each claim its own polynomial, while Section 1 listed two claims each about and . The protocol needs only a small change for this. The prover's values at depend on the polynomial and not on the original point, so it sends one value per polynomial, and each claim about that polynomial reuses the value. As a result the formula for still has one term per claim, whereas has one term per polynomial. Writing for the number of polynomials and for the polynomial that claim refers to, the formulas become
This explains the proof-size count in Section 1, since six claims need only four values.
Add a fourth claim, . This claim reuses and also shares the point with claim 2. The quotient polynomial gains one term, with , and becomes with commitment at . The prover still sends only the three values , because both claims about use the same number when the verifier derives . The output at is and , and opening confirms both.
Two claims may also share a point, as claims 2 and 3 do here. The verifier then needs only one inverse of , and the weights keep the claims apart as Section 5 showed. Two claims about the same polynomial at the same point with different values cannot both be true, and the code rejects such a list before batching.
The Ragu Book and the code differ here
The book notes that only one evaluation per polynomial is needed, but its formulas for and still index by claim. The prover at commit 3219e08 loops over polynomials, so each polynomial appears once in . This site follows the code.
11. Blinding factors
The book's protocol uses hiding commitments, written and with blinding factors and . Blinding factors combine with the same weights as the polynomials, as chapter 06 showed, so the prover sets , and the verifier's formula for the commitment does not change in form.
Take blinding factors and . The blinded commitments are , , and . The verifier combines them into . The prover computes modulo 43, and , the same point.
The warning in chapter 06 applies here as well. At commit 3219e08 the IPA code omits this term, and the fuse step commits to with no blinding factor.
12. Relation to SHPLONK and Halo 2
The Ragu Book credits this technique to SHPLONK, by Boneh, Drake, Fisch and Gabizon. That paper works with KZG commitments and treats polynomials opened at sets of points. In its second scheme, the prover commits to
where vanishes on the point set of , and interpolates the claimed values on that set. When each set holds one point, is the constant and is , so is our with the weights in a different order.
The two protocols then part ways. SHPLONK's verifier sends a random , and instead of receiving values there it builds a commitment to a polynomial that must vanish at . In the one-point case with distinct points, with the set of all points and its vanishing polynomial, that polynomial is
Every coefficient here is a number the verifier can compute, so it can derive the commitment to from the input commitments and the commitment to . Dividing the formula by and setting gives the same relation as Section 6, which shows that for honest polynomials. The paper finishes with one KZG opening of at . We can run this form on our example, taking a Pedersen commitment to a constant as and using with our weights:
In our run , and the construction gives . Substituting gives , and the combination of , and gives the commitment , which matches directly. The prover sent no values at for this check.
Ragu instead has the prover send the values at and combines them under . This matches the multipoint opening in Halo 2, which also forms a combination of quotients, evaluates it at a fresh challenge using the opened polynomials' values, and adds the result to those polynomials under one more challenge. Halo 2 first groups polynomials by their set of query points and interpolates over each set, whereas Ragu gives every claim its own term and needs no interpolation.
This comparison is our own reading of these sources, except that we could not retrieve the SHPLONK paper's text when checking this chapter, so the formulas for and above are unverified against it. Neither the Ragu Book nor the code explains why Ragu sends the values instead of using SHPLONK's .
13. Batching in Ragu
The clearest place to see this protocol in the code is the compression path, whose module comment describes the same steps. The prover divides by without using the claimed value, as Section 3 predicted, then writes , squeezes , writes the values, and squeezes . The verifier computes and by Horner's rule, which is how the weights from Section 7 arise. This excerpt comes from compress/batch/verifier.rs at commit 3219e08:
let mut f_at_u = C::Scalar::ZERO;
for claim in claims {
let denominator = (u - claim.point)
.invert()
.ok_or_else(|| Error::InvalidWitness("u lands on a query point".into()))?;
f_at_u = f_at_u * alpha + (batch.evaluations[claim.poly] - claim.value) * denominator;
}
let mut value = f_at_u;
for &evaluation in &batch.evaluations {
value = value * beta + evaluation;
}
Each pass through the first loop multiplies everything so far by , so the first claim ends up with the highest power. The second loop starts from , which therefore gets the highest power of . The index claim.poly is the of Section 10.
Reconstructed from code at commit 3219e08, not confirmed by the authors
The fuse step runs the same reduction with the same weights, spread across _08_f.rs, _09_eval.rs and _10_p.rs, with the verifier's arithmetic in the compute_v circuit. It differs from the description above in two ways that later chapters cover. The values at go into a committed stage rather than being sent directly, which is the subject of staging. The challenge is also derived from a 143-bit endoscalar rather than taken as a full field element, which is the subject of endoscalars.
The chapter on split accumulation wraps this protocol so that the output triple becomes a running accumulator, and the chapter on curve cycles divides its arithmetic between two circuits. We stop before both, since each depends on recursion, which we have not reached.
14. Where this chapter leaves us
This chapter took the following steps:
- A claim holds exactly when is divisible by , so a true claim has a quotient polynomial and a false one does not.
- The relation moves a claim from to a new point , because the verifier can compute the quotient's value from the value of .
- Alpha batching commits to one combination of all the quotients, with random weights that stop errors at a shared point from cancelling.
- The prover sends one value per polynomial at a random , and the verifier derives from those values and the original claims.
- Beta batching combines and the polynomials at into one triple , and every input needs a distinct weight.
- A false claim survives only if a challenge lands on one of a small number of bad values, provided that each challenge comes after the message it tests.
Together with the inner product argument, this gives a single short opening for all of a proof's evaluation claims. The next chapter assembles the arithmetization, the polynomial encoding, the commitments and this batching into one complete proof.