The Complete Proof
The last five chapters each built one part of a proof. This chapter puts them together and runs the result on the statement with , with every commitment computed on the toy curve and every check carried out.
The result is called a NARK, a non-interactive argument of knowledge. The name leaves out the S of SNARK because this proof is not succinct, and we look closely at where its size and its verification cost come from. Those costs are what the rest of the site works to remove, so the chapter ends with an exact list of the verifier steps that remain linear.
1. What the complete proof has to do
The earlier chapters supply these parts:
| Chapter | What it supplies |
|---|---|
| Arithmetization | One equation, , that a valid witness satisfies |
| Polynomial Encoding | The polynomials , , and behind those vectors, and a protocol written in terms of oracles |
| Polynomial Commitments | A short commitment to take the place of each oracle |
| The Inner Product Argument | A short proof of one evaluation claim |
| Batched Openings | A reduction from many evaluation claims to one |
| Statements and Challenges | Fiat–Shamir, which replaces the verifier's challenges with hashes |
Assembling them raises three questions that no single chapter answered. The first is the order of the messages, since each challenge has to come after the data it tests. The second is how the verifier knows that the commitments it holds describe the right polynomials. The third is how much of each polynomial the verifier needs to see. The Ragu Book's NARK answers the third question by sending several whole polynomials in the clear. We follow that construction first, and Section 17 shows the shorter proof that the same parts can produce.
Reconstructed from code at commit 3219e08, not confirmed by the authors
This chapter's protocol comes from the book. We found no standalone NARK in the code at this commit, and the word appears in the crates only as part of "SNARK". The closest code is verify_uncompressed, which holds a proof's polynomials and checks them directly, as the NARK does. It covers a much larger object, the proof of a recursive step, and its documentation calls it a test oracle and sends production verification through compression. Section 18 compares them.
Notation
This chapter reuses three names, so we fix their meanings here. Following the book, and are the left and right factors of the product, while and remain the gate wires, which appear only inside . The polynomial is the one that the polynomial encoding chapter called , because now means the combined quotient of Batched Openings. The letter means the random evaluation point here, and we say "the witness with " when we mean the secret input.
2. The running example
The circuit is the one from the arithmetization chapter, with gates, so every polynomial has coefficients. We reuse that chapter's challenges, and , and the witness with . These are the polynomials the protocol works with:
| Polynomial | Coefficients of | Who can compute it |
|---|---|---|
| (0, 0, 0, 30, 0, 0, 0, 0) | Both, from the statement | |
| (9, 27, 9, 3, 3, 3, 0, 0) | Prover | |
| (0, 0, 6, 42, 37, 7, 42, 36) | Both, after | |
| (0, 0, 0, 0, 0, 0, 32, 24) | Both, after | |
| (9, 6, 10, 31, 26, 1, 0, 0) | Prover | |
| (9, 6, 16, 30, 20, 8, 31, 17) | Prover |
A commitment to 8 coefficients needs 8 generators, and the toy curve's public parameters have only four. We add four more points at unused -coordinates, so that the generators are together with the existing and :
| Name | Point |
|---|---|
3. Choosing how to check the revdot product
The protocol from the polynomial encoding chapter checks the revdot product by splitting the product into and . That split keeps every polynomial within the degree limit, but the prover pays for it, because computing a product of this size takes FFTs:
The book counts at least 3 FFTs, over a domain with at least points. For , that is at least points, and the next power of two is .
There is a blunter alternative. If the prover sends the two vectors, the verifier can compute the revdot product itself with one multiplication per entry, and no product polynomial ever exists. This makes the proof much larger and removes the FFTs. The book chooses this direct check for its NARK and keeps the split for the places in the PCD tree where succinctness matters.
A shortcut that tests at a random point against one committed polynomial does not work, for the reason from Section 11 of the encoding chapter. The product has degree up to , and the generators limit commitments to degree below .
4. Committing before the challenges
The consolidated equation only means something if is fixed before and are known, as the arithmetization chapter showed. So the first message commits to the trace, and it also commits to the public input polynomial:
The bar marks a hiding commitment with a blinding factor. The book blinds the polynomials that hold witness data and leaves the public ones unblinded, which is the same as using a blinding factor of zero. Section 13 discusses how much this blinding achieves.
The public input polynomial is , so . The trace commitment with the blinding factor is . Without the blinding term the same vector would commit to .
Tying K to the statement
The oracle protocol treated as shared knowledge, whereas the NARK has the prover send . A verifier who wants to know about the public value 35 therefore has to connect to that value, and the book's list of steps does not say how. Checking the evaluation claims about does not do the job on its own, since those claims say only that is consistent with itself:
A prover with can commit to instead of , which is the instance of the statement . Its differs from the correct , while the claims about are all true, and every other check passes. The proof is valid for and says nothing about , so a verifier that accepts without comparing it would be misled.
In our run the verifier closes this gap by recomputing from the statement. We add this as an explicit step.
The Ragu Book and the code differ here
The book's NARK has the prover commit to and then opens the commitment at and . In the code at commit 3219e08, the uncompressed verifier computes from the output header itself, and a comment on the circuit code says that the verifier sets . This chapter keeps the book's , so that the run has the same shape as the book's protocol, and it adds the comparison above. The code's route needs no such comparison, because the prover never supplies the instance.
The verifier now sends the challenges and .
5. Building the two multiplicands
The challenges turn the bivariate polynomials into univariate ones, so the prover can now compute the wiring polynomial and the right factor. It sends a commitment to each of these, together with the claimed revdot value:
It also sends , the commitment to the left factor. In a standalone NARK the left factor is the trace, so and . This looks redundant, and the book says so in a footnote. The two names exist because during recursion they differ. There, holds one step's trace, and holds an aggregate of many revdot claims.
With the vectors from Section 2, the prover computes with no blinding, , and modulo 43. It also sets .
The verifier could compute alone, so sending it may look pointless as well. The reason is that the next stages make claims about commitments, and has to be a commitment for those claims to include it. Later chapters reach a verifier that no longer sees the polynomials and holds only commitments, and these objects prepare for that.
6. Checking the wiring and the revdot product directly
The prover now sends the three vectors , and , along with the blinding factors and . This is the step that makes the proof long. In return, the verifier's checks need no cryptographic argument, since it can recompute everything it was told:
- It computes from the circuit and , and compares. The book calls this the wiring consistency protocol.
- It checks that , because in this standalone protocol the book defines to be . The book's verifier steps do not list this comparison, so we state it. Without it, a prover could pick a new after seeing and , and the early commitment would constrain nothing.
- It recomputes , and from the vectors, which shows that the vectors are the ones the prover committed to.
- It computes and compares it with . The book calls this the revdot product protocol.
| Check | Left | Right |
|---|---|---|
| Recompute from the circuit and | Sent is identical | |
| Commit to the sent | ||
| Compare with the earlier | ||
| Commit to the sent with | ||
| Commit to the sent with | ||
The order of the messages matters here even though the check looks like arithmetic on public data. The prover sent before it knew and , and the comparison together with the recomputation of shows that the vector is the one behind that early commitment.
7. Tying b back to the trace
The revdot check accepts any that produces the right number, and a prover can always find such a vector, since one linear equation leaves most of the entries free. Nothing so far requires to be the specific vector . In polynomial form, the requirement is
This is an identity between polynomials of degree below , so a test at one random point catches a difference, in the way the encoding chapter described. The prover has already fixed all three commitments, so the verifier can send a random . The prover sends the three values, and the verifier computes alone and checks
The verifier sends , so modulo 43. The prover sends , and . The verifier computes alone and checks .
The dilation works as it did in the encoding chapter, with the value of at coming from the same polynomial at the point . No separate commitment to the dilated trace exists, so a prover cannot substitute a different trace in the right factor.
The verifier already holds , and , so it could compare them coefficient by coefficient, and a standalone NARK has no need for a random evaluation here. The book keeps the evaluation form because it is what survives in recursion, where the vectors are gone and only commitments and evaluation claims travel forward.
8. Batching the evaluation claims
The three values just sent, and the value , are claims about committed polynomials. Taken with the recomputations in Section 6 they are redundant here, but we check them through the machinery that recursion will rely on, since the accumulation chapters work on claims of exactly this form. The list has four claims, each about its own polynomial:
| Claim | Commitment | Point | Value | Quotient , coefficients of |
|---|---|---|---|---|
| 0 | 2 | 9 | ||
| 1 | 9 | 35 | ||
| 2 | 9 | 23 | ||
| 3 | 7 | 13 |
The book's list has two further claims, about and , which tie down a constant wire our toy circuit does not have. Section 14 adds that wire and shows the six-claim form that Batched Openings previewed.
Now we apply that chapter's reduction, using its weights, in which the first claim takes the highest power of and takes the highest power of . The quotients above come from synthetic division, which ignores the claimed value. The verifier sends and the prover commits to the combined quotient:
With , the powers are , , and . The combination has coefficients , and with the blinding factor its commitment is .
The verifier sends a new point , the prover sends one value per polynomial, and the verifier derives from those values and the original claims:
At the prover sends , , and . The verifier fills in the next table.
| Value at | Claimed value | Weight | Term | |||
|---|---|---|---|---|---|---|
| 0 | 42 | 9 | 15 | 28 | 41 | 30 |
| 1 | 29 | 35 | 8 | 10 | 35 | 6 |
| 2 | 35 | 23 | 8 | 23 | 11 | 38 |
| 3 | 29 | 13 | 10 | 36 | 1 | 36 |
The last column sums to , and the prover gets the same number by evaluating .
Finally the verifier sends , and both parties combine the five inputs. The verifier computes and from public data, while the prover computes the polynomial and its blinding factor:
The polynomials and have no blinding factor, so they contribute nothing to .
Take . Each input carries its weight into the commitment, the value and the blinding factor.
| Input | Weight | Commitment | Value at | Blinding factor |
|---|---|---|---|---|
| 40 | 24 | 5 | ||
| 41 | 42 | 17 | ||
| 13 | 29 | 29 | ||
| 23 | 35 | 0 | ||
| 1 | 29 | 0 | ||
| Combined |
All the evaluation claims now rest on the single claim .
9. Revealing p
Batched Openings noted that the book finishes its NARK by having the prover send in full, and it promised to return to that choice. The final step is:
The prover sends and . Committing gives , which equals , and evaluating gives , which equals .
We built an inner product argument for this exact kind of claim, so it is reasonable to ask why the NARK does not use one. The argument would prove the same thing with a logarithmic number of points, but in this protocol that saving is small, because the proof already contains other full vectors:
For , the witness part is bytes with revealed. Replacing the reveal with an argument of points and one scalar brings it to bytes, because the vectors , and remain.
The verifier's work would not improve in growth either, since the argument leaves it with one MSM over all the generators, the same size as recomputing from .
The reveal also fits how the proof will be used. Sending places this polynomial in the witness part of the proof (Section 12), and the split accumulation chapter separates a proof's instance from its witness so that the expensive check on can be postponed. The inner product argument comes back at the end of the recursion, when compression ends with one IPA opening on each curve. Section 17 runs the same replacement on our example, along with the replacements for the other vectors, which is where the saving appears.
10. The whole protocol
Here is the sequence of messages. The prover's reveals are grouped with the checks that use them.
The complete run on the toy curve is:
| Step | Party | Value or check |
|---|---|---|
| 0 | Both | Hold the circuit, which gives and , and the statement, which gives |
| 1 | Prover sends | , |
| 2 | Verifier checks | commits to the of the statement |
| 3 | Verifier sends | , |
| 4 | Prover sends | , , , |
| 5 | Prover sends | , , , , |
| 6 | Verifier checks | Recomputes and , checks , recomputes and , and finds |
| 7 | Verifier sends | |
| 8 | Prover sends | , , |
| 9 | Verifier checks | |
| 10 | Verifier sends | |
| 11 | Prover sends | |
| 12 | Verifier sends | |
| 13 | Prover sends | Values at : |
| 14 | Verifier sends | |
| 15 | Verifier derives | , , |
| 16 | Prover sends | , |
| 17 | Verifier checks | and |
Each check in this table is an assertion in the script behind this chapter. The honest prover should also pass at every challenge, not only the ones we picked, so we tested that too:
We ran the whole protocol for all pairs at two values of , moving whenever it would land on a claim point. The verifier accepted all 3698 runs.
11. Removing the interaction
The N in NARK means non-interactive, and the book treats this step as a direct replacement of each challenge with a hash. The Fiat–Shamir section of chapter 03 explains the transform, and the only thing this protocol adds is the list of what goes into the transcript. Each challenge must depend on every message that it tests, so the list follows the table above. The vectors , , and do not need to be absorbed, because the commitments already fix them, and does not either, because it must equal the absorbed .
Here is a full run using the toy Poseidon sponge from chapter 03, starting from the tag . The same witness and blinding factors now produce different challenges, so all the later values change:
| Messages absorbed | Values | Challenge squeezed |
|---|---|---|
| , | , | |
| Nothing new | ||
| , , | , , | |
| , , | , , | |
| Values at | , , , |
The verifier replays the same absorptions from the proof, obtains the same six challenges, and accepts. Changing only the blinding factor of from to changes the first absorbed message, and the six challenges become .
Repeated trials still apply, since a cheater can try many blinding factors privately and look for a lucky set of challenges. The toy field's 43 outputs make that easy, and a 255-bit field does not.
12. The proof's two parts
Collecting the prover's messages, the book divides the proof into an instance part of constant size and a witness part of linear size. The linear witness is why this is a NARK and not a SNARK.
| Part | Item | Value in our run |
|---|---|---|
| Instance | , , , , | |
| Instance | 13 | |
| Instance | ||
| Instance | , , | |
| Witness | ||
| Witness | ||
| Witness | ||
| Witness | ||
| Witness | ||
| Witness | Values at | |
| Witness | , |
The challenges do not appear, because the verifier replays them from the transcript. The sizes are very different:
Take with 32-byte values, the size the Ragu Book's analysis gives for its preferred threshold. The instance holds 6 points and 6 scalars, or bytes. The witness holds four vectors of entries and 8 more values, or bytes, which is about 1 MB.
The division is not only a way of counting. The split accumulation chapter builds a verifier that reads the instance and leaves the witness to a later check.
The book's lists differ slightly
The book's step 9 sends "the aggregated blinding factors", but its witness list has no such entry. That list also writes with no bar, while the PCS aggregation chapter writes with a blinding factor. This site includes in the witness and blinds , as chapter 08 did. If were unblinded, the verifier could compute from and , which may be the intended reading.
13. Hiding commitments and what the proof reveals
The commitments , , and carry blinding factors so that a commitment alone reveals nothing, for the reason given in chapter 06. The difference is visible on our trace:
An observer who holds the unblinded commitment can build the trace for every candidate input and compare. Trying all 43 inputs gives exactly one match, . An observer who holds only gets no such answer, because each of the 43 candidate traces has exactly one blinding factor that fits this point.
This protection does not last, because the proof then sends the vectors:
In our run the proof contains . The layout from the arithmetization chapter puts the wire at position 3, so anyone can read the secret input straight from the proof.
So this NARK hides nothing. The book says this openly, and it describes the omission as intentional, since Ragu intends to prevent leakage through rerandomization and not by making this NARK zero knowledge. It also says that a fold-level randomizer is still needed for that. This agrees with the status recorded in chapter 02, where neither the book nor the code yet establishes zero knowledge. The blinding factors in the book's protocol therefore do not provide privacy in this standalone form.
The Ragu Book and the code differ here
The book's NARK uses the blinding factors above. At commit 3219e08, as chapter 06 recorded, the IPA module omits Pedersen blinding. The compression module also states that a compressed proof is not hiding, because its openings are evaluations of the witness polynomials. The value in the wire that Section 14 introduces does not supply hiding either, and the book's local wiring chapter says this directly. Its purpose is to keep combinations of commitments away from the identity point. Our toy run follows the book, so that the reader can see where blinding factors go.
14. The constant wire
So far the toy circuit has moved its constant 5 into the instance. A real circuit needs constants inside its constraints, and the arithmetization chapter mentioned how Ragu provides them, with a wire that holds the value 1. This wire is what the book's two extra claims are about, so we now add it, which requires one more gate. Our becomes 3, and the polynomials have 12 coefficients, so this section uses four further generators, to , which the script lists.
The Ragu Book and the code differ here
Chapter 05 recorded that the NARK chapter checks , while the code and the local wiring chapter have and , which gives . This site follows the code, as chapter 05 did, so our claim about has the value 0. Chapter 08's preview quoted the book's form with the value 1. We found no opening of at 0 in verify_uncompressed, and the local wiring chapter explains that the gate equations already force once , so we keep the claim here only to match the shape of the book's list.
The system gate takes position 0, and the other two gates move up by one:
Gate 0 holds , , and , and gates 1 and 2 are the two gates from the arithmetization chapter. The first constraint says , and the second becomes , so the constant 5 is now a multiple of the wire. The instance is , and the trace is . Its constant coefficient is , and its top coefficient is . Checking all 1849 challenge pairs confirms that the consolidated equation holds at every one.
The wire sits at the top of the trace, position , and its partner in the revdot product is position 0, so the constraint puts the coefficient 1 on in with . This gives the identity , which the book states as well and which the script confirms.
The claims list now has the six entries of chapter 08's preview, on four polynomials, so one value per polynomial still suffices at . Here again, and the weights run from down to 1:
| Claim | Polynomial | Point | Value | Weight |
|---|---|---|---|---|
| 0 | 0 | 0 | 16 | |
| 1 | 2 | 14 | 21 | |
| 2 | 9 | 22 | 41 | |
| 3 | 9 | 39 | 35 | |
| 4 | 0 | 1 | 11 | |
| 5 | 7 | 31 | 1 |
With the same challenges as before, the prover sends and four values at , namely . The verifier derives and , the revealed matches both, and the proof is accepted.
The claim does real work. The wire is only constrained to equal , so without a check on , a prover can give the constant a different value and change the meaning of every constraint that uses it:
Take , which is false for the real statement, since modulo 43. A cheater sets and commits to . Then , so every gate and constraint holds, and the consolidated equation holds at all 1849 challenge pairs. If the two constant claims are dropped from the list, the verifier accepts this proof. With the claims in the list, the false claim remains. Keeping the other challenges fixed, the verifier rejects for 42 of the 43 values of , and it accepts only at , which removes from .
A verifier that computes from the public data with , as the code does, rejects the same proof, because the cheater's differs from that value at every .
From here on we return to the two-gate circuit.
15. Why cheating fails
The argument relies on the following assumptions, and it is informal. Nobody knows a relation among the generators, which is the discrete log relation assumption. Each challenge is uniform and comes after the messages it tests, which for a non-interactive proof means treating the transcript hash as a random oracle. The verifier has also tied to the statement, as in Section 4.
We take the false witness with and consider what its prover can try. All of the counts below come from running the same verifier function that accepted the run in Section 10.
The prover follows every instruction
Take the false witness with , so , and let the prover follow every instruction. At and the verifier computes , while , so the revdot check fails. Counting all pairs of challenges finds 43 of the 1849 where the two numbers happen to agree, the same count as in the arithmetization chapter.
The prover changes b
To reach the right revdot value, the prover has to send some vector other than the honest .
The revdot check only looks at , so the cheater can replace it with , where is any vector with . The most direct choice puts one entry at position 4, the partner of , giving . The revdot check now passes. The check then compares two polynomials that differ by , which has only the root . Running the whole protocol at all 43 values of gives one acceptance, at .
The cheater does better by spreading the difference over all eight coefficients. Let be a multiple of , scaled so that , which gives . Running the whole protocol at all 43 values of gives acceptance at exactly , which is 7 out of 43. A polynomial with 8 coefficients has at most 7 roots, so no choice of can do better, and for on a field of about elements the same limit gives a probability below .
The prover lies about an evaluation
Outside those roots, the only way past the check in Section 7 is to send a false value.
At this polynomial is not zero, since . The cheater can still pass the check by sending in place of the true , but that value is then a false evaluation claim about . The batching of the previous chapter catches it. Running all 43 values of with honest values at gives one acceptance, at , where the derived drops out of .
Chapter 08 counted what the cheater gains by also shifting values at or by committing to a different , and its reasoning applies to these claims unchanged. In this standalone NARK the verifier could also find the false value by evaluating the it holds. The count above measures the batched check alone because that is the check recursion keeps.
The prover knows a challenge early
Every count above assumes the message order. The order is what stops a prover from solving for its messages:
Suppose the prover knows and before it sends . Starting from the false trace, it changes entry 0 by to get , a value found by solving the one quadratic equation. This vector is not a valid trace, because its gates do not hold. It still satisfies the consolidated equation at this one pair, and the verifier accepts the whole proof. The same vector, committed honestly before the challenges, passes the revdot check at only 44 of the 1849 pairs.
This is the reason each challenge has to depend on the commitments before it, and chapter 03 shows what happens if a transcript leaves them out.
The prover knows a relation among the generators
Fixing first only helps if the commitment really fixes the vector. Here is the same attack, carried out after the challenges by a prover that can open a commitment in two ways:
Suppose the prover commits to the false trace first, so , and only then learns and . Because it knows the discrete logs of the toy generators, it can change entries 0 and 1 by and without moving the commitment. One such change gives , which commits to the same point and satisfies the consolidated equation at this pair. The verifier accepts, because each of its recomputations finds what it expects.
On a real curve this requires solving discrete log, and the toy curve's small size is what makes it possible here.
16. What the verifier pays
Now we can go through the verifier's work, one step at a time. The next table gives each step's cost, and for sizes it uses :
| Verifier step | Work | Growth |
|---|---|---|
| Compute from the circuit | One term per wire in each constraint | Linear |
| Recompute , , | 3 MSMs of size , or scalar multiplications | Linear |
| Compute | , or field multiplications | Linear |
| Compute | Two geometric sums, using repeated squaring | Logarithmic |
| Compute or compare | One term per public input | Size of the instance |
| Derive | One inverse and a few multiplications per claim | Constant |
| Compute and | Five scalar multiplications and field operations | Constant |
| Recompute from | 1 MSM of size , or scalar multiplications | Linear |
| Evaluate | , or field multiplications | Linear |
The value can be computed quickly because the sums in its definition are geometric. To see this, start from the definition and split it into two sums:
Substituting turns the exponents into , and . Factoring out the parts that do not depend on gives
which matches the book's form for nonzero . Each geometric sum has a closed form that takes multiplications, by repeated squaring.
At , and , the first sum is and the second is . The formula gives , so , which matches the direct sum over the entries of .
The wiring vector has no comparable shortcut, since its entries come from an arbitrary circuit:
Our circuit has 8 nonzero wiring coefficients across its four constraints. Each contributes one term , and at , those terms are , which sum to . A circuit with more wiring has more terms, and no term can be skipped.
The MSMs can be merged, though this only saves a constant factor. The verifier can pick a random and check that one combined vector commits to the same combination of the commitments, in place of recomputing each one. If any vector does not match its commitment, the difference is a nonzero polynomial in , so a random exposes it. The code's uncompressed verifier does this.
For our run take and the four vectors . The combined vector is with blinding factor , and it commits to , the same point as . One MSM of size did the work of four.
A verifier of this form is fine as a final check, but it cannot be placed inside a recursive proof at reasonable cost, because each of its linear steps would become part of a circuit. The next chapter explains this problem in detail. The book groups the linear work into three subprotocols, namely wiring consistency, the revdot product and the evaluation check.
17. A short proof from the same parts
We already have replacements for two of those three. The revdot product can use the split from chapter 05, at the cost of the prover's FFTs, and the evaluation check can use the inner product argument. Applying both shows what the third item leaves behind. The verifier never receives here, because it only needs the single value , which it computes alone. We no longer need , or , so the claims concern only , and .
Reconstructed from code at commit 3219e08, not confirmed by the authors
This section is our own assembly of the oracle protocol in the book with the batching and IPA chapters. It omits blinding, as the IPA at this commit does, and it uses the symmetric IPA of chapter 07. Ragu does not run this exact protocol. Its compression follows the same pattern on a larger set of folded claims.
The first thirteen steps mostly repeat chapter 05 and chapter 08, and now every oracle has become a commitment:
| Step | Party | Value or check |
|---|---|---|
| 1 | Prover sends | |
| 2 | Verifier sends | , |
| 3 | Prover sends | and , the commitments to and |
| 4 | Verifier sends | , so and |
| 5 | Prover sends | , , , , |
| 6 | Verifier computes | , , |
| 7 | Verifier checks | The split, and , and the target, |
| 8 | Verifier sends | |
| 9 | Prover sends | , the commitment to the combined quotient |
| 10 | Verifier sends | |
| 11 | Prover sends | Values at : , , |
| 12 | Verifier sends | |
| 13 | Verifier derives | , , |
The prover now has to prove the claim without revealing :
The polynomial behind has coefficients . The statement point for the argument is .
The inner product argument takes rounds for 8 coefficients. Its round challenges are unrelated to the batching point , and we pick them by hand. At each round the prover sends and , and both sides fold, as chapter 07 explained:
| Round | Folded point | Folded | |||
|---|---|---|---|---|---|
| 1 | 15 | ||||
| 2 | 10 | ||||
| 3 | 3 |
The prover sends the final scalar . The verifier computes the coefficients of from the three challenges, which are , then and from one MSM over all eight generators. The left side of the check is , and , so the verifier accepts.
The proof is now short:
For this proof holds points and scalars, or bytes at 32 bytes each, in place of about 1 MB.
The verifier has not improved as much as the proof has. Here is its work:
| Verifier step | Work for | Growth |
|---|---|---|
| Compute | One term per nonzero wiring coefficient | Linear |
| Compute | Two geometric sums | Logarithmic |
| Compute | One term per public input | Size of the instance |
| Split and target checks | A few field operations | Constant |
| Derive , and | 5 inverses and 4 scalar multiplications | Constant |
| Combine the and | scalar multiplications | Logarithmic |
| Compute | squarings and factor multiplications | Logarithmic |
| Compute the coefficients of | About field multiplications | Linear |
| Compute | 1 MSM of scalar multiplications | Linear |
The rows marked linear come down to two costs, once we treat the coefficients of as part of computing :
- Computing . The verifier has to read the whole circuit, because the wiring has no structure it can exploit.
- Computing , where is the coefficient vector of . The generators have no structure either, as chapter 07 explained.
The book writes for what this site calls . These two steps are the targets of what follows. The accumulation chapter postpones , and the chapter on wiring and the registry handles . The revdot folding chapter covers how most steps avoid the split and its FFTs.
18. The NARK in Ragu
As Section 1 noted, the code has no type or function for this standalone protocol, since Ragu's real proofs cover a recursive step with many polynomials. Several of its checks can still be located in the uncompressed verifier. The revdot check, step 6 of our run, appears for each claim the proof carries, here from crates/ragu_pcd/src/verify.rs at commit 3219e08:
let native_revdot_claims = {
native::ky_values::<C::Profile, _>(&native_ky)
.zip(builder.a.iter().zip(builder.b.iter()))
.all(|(ky, (a, b))| Verifier::<B>::sparse_revdot(a, b) == ky)
};
Reconstructed from code at commit 3219e08, not confirmed by the authors
- The factors. The proof stores polynomials named
AbAandAbBapart from its traces, which matches the separation of from that the book explains. We return to this in revdot folding. - The commitments. The batched check compares the stored commitments with their polynomials, and it includes the polynomial , as our step 17 does.
- The instance. The verifier computes itself, as Section 4 described.
- Derived values. The module documentation says that and are derived from the polynomials and never read from the proof, whereas the book's instance lists them as prover messages.
- The status of this path. The same documentation calls this verifier a test oracle, available only with the
test-utilsfeature. Production proofs go through compression, which the chapter on recursion in Ragu covers.
19. Where this chapter leaves us
This chapter took the following steps:
- The prover commits to the instance and the trace before it sees and , and the verifier ties to the statement.
- The prover commits to and to the right factor , then sends the vectors, so that the verifier can recompute the wiring, recompute the commitments and compute the revdot product directly.
- A check at a random ties to the trace, wiring and gate polynomials.
- The evaluation claims batch into one claim , which the book's NARK finishes by revealing .
- The resulting proof has a constant-size instance and a linear-size witness, and it hides nothing, despite its blinding factors.
- A cheater can pass only at rare challenges, as long as each challenge follows the messages it tests and nobody knows a relation among the generators.
- Replacing the direct checks with the split and the inner product argument makes the proof logarithmic in size, and it leaves the verifier two linear steps, computing and computing .
A verifier with linear steps can check a proof, but it cannot fit inside the next proof at reasonable cost. The next chapter takes up proofs about verifiers, and shows why the two steps above block them.