Ragu & Tachyon
Home
  • Scaling Zcash
  • An Introduction to Proof-Carrying Data
  • Statements and Challenges
  • Arithmetization
  • QAP and Polynomial Encoding
  • Polynomial Commitments
  • The Inner Product Argument
  • Batched Openings
  • The Complete Proof
  • Recursive Proofs
  • Accumulation
  • Split Accumulation
  • Curve Cycles
  • Revdot Folding
  • Wiring and the Registry
  • Endoscalars
  • Staging
  • Recursion in Ragu
  • Notes, Nullifiers, and Tachygrams
  • Pool State and Anchors
  • Oblivious Sync
  • The Proof Tree
  • Aggregation and Bundles
Final Recap
  • Notation
  • Glossary
  • Curves
Home
  • Scaling Zcash
  • An Introduction to Proof-Carrying Data
  • Statements and Challenges
  • Arithmetization
  • QAP and Polynomial Encoding
  • Polynomial Commitments
  • The Inner Product Argument
  • Batched Openings
  • The Complete Proof
  • Recursive Proofs
  • Accumulation
  • Split Accumulation
  • Curve Cycles
  • Revdot Folding
  • Wiring and the Registry
  • Endoscalars
  • Staging
  • Recursion in Ragu
  • Notes, Nullifiers, and Tachygrams
  • Pool State and Anchors
  • Oblivious Sync
  • The Proof Tree
  • Aggregation and Bundles
Final Recap
  • Notation
  • Glossary
  • Curves
  • Scaling Zcash
  • An Introduction to Proof-Carrying Data
  • Statements and Challenges
  • Arithmetization
  • QAP and Polynomial Encoding
  • Polynomial Commitments
  • The Inner Product Argument
  • Batched Openings
  • The Complete Proof
  • Recursive Proofs
  • Accumulation
  • Split Accumulation
  • Curve Cycles
  • Revdot Folding
  • Wiring and the Registry
  • Endoscalars
  • Staging
  • Recursion in Ragu
  • Notes, Nullifiers, and Tachygrams
  • Pool State and Anchors
  • Oblivious Sync
  • The Proof Tree
  • Aggregation and Bundles
  • Final Recap
  • Appendix

    • Notation
    • Glossary
    • Curves

Accumulation

The chapter on recursive proofs sets up the goal of a proof that verifies an earlier proof, and a verifier with linear steps blocks that goal. Chapter 09 identified the two linear steps in our verifier. This chapter removes one of them, the multi-scalar multiplication that computes G^ at the end of the inner product argument.

The technique does not make that computation cheaper. It postpones the computation, and it lets many postponed computations collapse into one. A prover states the output as a claim, each recursive step merges the new claim with the old one using a random spot check, and one party does the expensive work once, at the very end. The technique comes from Halo, and Bünz, Chiesa, Mishra and Spooner later gave it foundations under the name accumulation scheme.

Reconstructed from code at commit 3219e08, not confirmed by the authors

The merge protocol in this chapter is our own assembly. We built it from the Ragu Book's description of Halo, the Halo 2 book's recursion page, and the argument in chapter 07, and we checked its algebra with the script behind this page. It teaches the idea, and it may differ in detail from the protocols in the two papers, of which we could read only the abstracts. Ragu does not run it, as Section 11 explains, because Ragu's recursion uses a later variant.

Terminology

This chapter says that claims merge, following the book's wording for Halo. A merge combines two claims into one. It is a different thing from a fuse, the PCD operation from chapter 02, although a fuse would contain merges if a system used this technique.

1. The step that remains

Recall the final check of the inner product argument from chapter 07:

P+j=1∑k​(uj−2​⋅Lj​+uj2​⋅Rj​)=a^⋅(G^+b^⋅U).

The left side takes 2k scalar multiplications. On the right side, b^=g(x) takes about k field multiplications, because g is a product of k factors. Only G^ costs a linear amount, because computing it takes one MSM over all n generators, G^=⟨s,G⟩.

Section 8 of chapter 07 also showed what this point is. The coefficients of g are the entries of s, so G^ is the Pedersen commitment to the polynomial g. From here on we write gu​ to show that this polynomial depends on the challenges u=(u1​,…,uk​), and gu​ for its coefficient vector, which is the s of chapter 07:

gu​(X)=j=1∏k​(uj−1​+uj​X2k−j),G^=⟨gu​,G⟩.

Two features of this equation make accumulation possible. The polynomial has a description of only k scalars, even though it has n coefficients, so anyone can evaluate it at a point with logarithmic work. The commitment is also linearly homomorphic, as chapter 06 showed, so a combination of such points commits to the same combination of polynomials. The sections below use both.

2. Splitting off the expensive step

The verifier only needs G^ as an input to one equation, so it can test that equation with a value that somebody else computed. Let the prover supply the point. The verifier then does all the logarithmic work, runs the final check with the supplied G^, and stops short of the MSM. What it has left is one unverified statement:

claim (G^,u):G^=⟨gu​,G⟩.

The verifier's conclusion now has a condition attached. It has established that the evaluation claim holds provided that this statement is true. The claim is small, at one point and k scalars, even though it speaks about all n generators.

Here is the split applied to the run of chapter 07, with u=(15,10). The prover sends G^=(20,25) along with the proof.

Verifier stepComputationResult
Combine the cross termsP+∑j​(uj−2​⋅Lj​+uj2​⋅Rj​)(14,22)
Evaluate gu​ at x=934⋅17, one factor per roundb^=19
Final check with the supplied point4⋅((20,25)+19⋅U)(14,22)
OutputThe claim (G^,u)((20,25), (15,10))

The condition matters, because a prover who chooses G^ has real power over the final check. All of the argument's protection against a false value now depends on the claim:

Take the false value y=38 from chapter 07, where the true value is 37. The statement point now carries an extra 1⋅U, and honest folding keeps it, so the folded point is (7,6). With the true G^=(20,25) the final check fails. The prover keeps a^=4 and instead supplies G^∗=G^+11⋅U=(26,23), where 11 is the inverse of 4 modulo 43. The right side becomes 4⋅((26,23)+19⋅U)=(7,6), so the check passes. Only the claim is wrong, because ⟨gu​,G⟩=(20,25) and not (26,23).

So a passing final check proves nothing unless somebody eventually confirms the claim. The rest of the chapter arranges for that confirmation to happen once, however many claims arise.

3. Deciding a claim

The direct way to confirm a claim is to run the postponed computation. Multiply out the factors of gu​, compute the MSM, and compare the result with G^. We call the party who does this the decider, and we call the check itself deciding.

For the claim ((20,25), (15,10)), the factors (23+15X2)(13+10X) multiply out to the coefficients (41,15,23,21), and the MSM with G gives (20,25), so the decider accepts. For the forged claim from the last section, the same MSM gives the same point, which differs from (26,23), so the decider rejects.

Moving the MSM out of the verifier helps a recursive proof, because the decider runs outside any circuit. It does not reduce the total work, though. A chain of recursive proofs creates a new claim at every step, and each one would have to be carried in the statement until a decider dealt with it:

With n=213 and a hypothetical 1,000 steps, checking every claim directly takes 1,000 MSMs of 8,192 terms, or 8,192,000 scalar multiplications. The statement would also carry 1,000 points and 13,000 challenges.

The statement must stay a fixed size for recursion to work, so we need to turn several claims into one claim, cheaply enough to do inside a circuit.

4. Testing a claim at one point

We start with one claim and look for a test cheaper than the MSM. The claim says that the point G^ commits to a particular polynomial, and the earlier chapters already show how to query a committed polynomial. If the verifier picks a random point x, it can ask the prover to open G^ at x using an inner product argument, and then compare the opened value with gu​(x).

The comparison is available to the verifier because the product form of gu​ takes only logarithmic work, however large n is:

Take the claim from chapter 07 and the point x=29. The two factors of gu​ are 23+15⋅292=39 and 13+10⋅29=2, and their product is 35. Evaluating the four coefficients (41,15,23,21) directly gives 35 as well, but that route needs all n of them, while the factors need only k terms.

The test catches a false claim for the reason given in chapter 03. Suppose G^ actually commits to some other polynomial h of degree below n. The difference h−gu​ is then a nonzero polynomial with at most n−1 roots, so the opened value matches at no more than n−1 points out of q, provided the prover fixes G^ before it learns x.

Suppose that the point in a claim commits to h with coefficients (19,37,37,22) instead of gu​. We chose the difference h−gu​=(X−2)(X−7)(X−20) to have as many roots as a cubic can. Testing all 43 points, the two polynomials agree at x∈{2,7,20} and nowhere else, so the spot check catches this claim at 40 of the 43 points.

The opening has two properties that differ from the openings of earlier chapters. First, its witness is public. The vector being opened is the coefficient vector of gu​, which anyone can compute from u, so the prover needs no secret and no stored data to run this argument. It pays a linear cost to multiply out the factors and fold, but it does this outside the circuit.

Second, this opening is itself an inner product argument, so its verifier faces its own final check with its own G^. Splitting that check as in Section 2 produces a new claim (G^′,u′). For a single claim we have therefore traded one claim for another, plus some logarithmic work, and that looks like no progress. The gain appears when two claims share one opening.

5. Merging two claims

Suppose we hold two claims (G^1​,u1​) and (G^2​,u2​), and write g1​ and g2​ for their polynomials. We would like one opening to test both. A random linear combination from chapter 03 can do this, so take a challenge α and combine the points:

CM​=G^1​+α⋅G^2​.

If both claims are true, homomorphism tells us what this point commits to:

CM​​=⟨g1​,G⟩+α⋅⟨g2​,G⟩=⟨g1​+αg2​,G⟩,​

which is the commitment to the polynomial g1​(X)+αg2​(X). Evaluating that polynomial at a random point xM​ gives a value the verifier can compute by itself, since it holds both sets of challenges:

vM​=g1​(xM​)+αg2​(xM​).

The statement to prove is now an ordinary evaluation claim, that CM​ opens at xM​ to vM​. The verifier computed every part of that statement from the two input claims, and the prover computes the witness vector from the same public data:

aM​=g1​+αg2​.

Each challenge has a separate job. The point xM​ exposes a wrong polynomial, as in Section 4. The weight α stops two wrong polynomials from cancelling each other. Without it, a prover could make g1​ too large by some polynomial and g2​ too small by the same polynomial, and the sum would be correct at every point.

The argument needs one more ingredient, which chapter 07 introduced. The input points come from the prover, so they could contain a hidden multiple of U, and a fixed U would let that term stand in for part of the value. We therefore weight U by a third challenge τ, sampled after the input points, and we use τ⋅U as the value generator in every round. Section 8 shows the attack that this stops. The statement point for the argument is

PM​=CM​+(τvM​)⋅U.

The prover now runs the inner product argument of chapter 07 on aM​ with fresh round challenges uM​, and the verifier splits off the final check as in Section 2. With the supplied point G^M​ and b^M​=guM​​(xM​), that check reads

PM​+j=1∑k​(uj−2​⋅Lj​+uj2​⋅Rj​)=a^M​⋅(G^M​+(τb^M​)⋅U).

The result of all this is one claim, (G^M​,uM​), with the same form as each input. The order of messages keeps the prover from choosing anything after it sees the challenge that tests it:

The same construction handles any number of claims, by using powers of α. For claims 0 to m−1,

CM​=i=0∑m−1​αi⋅G^i​,vM​=i=0∑m−1​αigi​(xM​).

The verifier's work grows by one scalar multiplication and k factor multiplications for each extra claim.

6. A complete merge on the toy curve

We need two claims to merge. The first comes from the run in chapter 07. The second comes from a fresh run of the same argument, on chapter 06's other vector at a different point. Both runs use chapter 07's fixed U, because the numbers for the first run then match that chapter exactly. All challenges are picked by hand.

Claim 1Claim 2
Polynomial opened(7,2,5,3) at x1​=9(3,1,8,4) at x2​=5
Value3720
First round cross termsL=(22,7), R=(30,8)L=(4,6), R=(9,9)
Second round cross termsL=(28,21), R=(14,9)L=(9,9), R=(23,7)
Challengesu1​=(15,10)u2​=(3,5)
Final scalar442
Supplied pointG^1​=(20,25)G^2​=(9,22)
Final check, both sides(14,22)(16,10)

Both final checks pass, so the verifier has two claims and has not yet done any linear work. It now starts the merge:

The verifier sends xM​=29 and α=16, then computes the merged commitment and value from public data:

QuantityComputationResult
g1​(xM​)39⋅235
g2​(xM​)15⋅4228
vM​35+16⋅2810
CM​(20,25)+16⋅(9,22)(16,21)

The prover computes the two coefficient vectors from the public challenges, namely g1​=(41,15,23,21) and g2​=(23,16,35,15), and combines them into aM​=g1​+16g2​=(22,13,24,3). Committing to this vector directly gives (16,21), and evaluating it at 29 gives 10, so the claim is true.

The verifier then sends τ=22. Both sides form the statement point PM​=CM​+(τvM​)⋅U=(16,21)+5⋅U=(8,22), and the rounds use τ⋅U=(27,30) as the value generator.

The rest is the inner product argument with aM​ as the folded vector, even though nothing about it is secret here. The prover folds, and the verifier updates the statement point after each round:

Round jLj​Rj​uj​Folded point
1(20,25)(7,25)8(23,24)
2(24,1)(7,25)12(9,9)

The prover sends a^M​=17 and supplies G^M​=(22,7). The verifier computes b^M​=gM​(29)=4⋅22=2 from the challenges uM​=(8,12), and the final check is

(9,9)=17⋅((22,7)+(22⋅2)⋅U).

Both sides are the same point, so the verifier accepts and outputs the single claim ((22,7), (8,12)).

The folded generator is the same point we would get from multiplying out gM​, because it depends only on the round challenges and never on the vector being opened. Now suppose this is the last claim, so that a decider takes over:

The decider multiplies out gM​ to get the coefficients (13,23,15,10), computes the MSM with G, and gets (22,7), so it accepts. This one MSM is the only linear group work outside the prover. We can also check what it vouches for by running the two MSMs it replaced, which give ⟨g1​,G⟩=(20,25) and ⟨g2​,G⟩=(9,22), the two input points.

7. Keeping a running accumulator

A merge turns two claims into one claim of the same form, so we can repeat it. We call the object that carries the current claim forward the accumulator, written acc. Each step produces one new claim from the proof it just verified, and merges that claim into the accumulator. The first step has no earlier accumulator, which is one of the base cases that the recursive proofs chapter handles.

A row of merge boxes. Each merge takes the previous accumulator from the left and a new IPA claim from above, and passes a new accumulator to the right. A decider at the end performs one MSM of size n.

The next table continues the run with two more claims, each from a fresh inner product argument on a new polynomial:

InputsxM​αNew G^New u
1 and 22916(22,7)(8,12)
Accumulator and claim 3, ((9,9), (7,16))213(17,24)(12,18)
Accumulator and claim 4, ((7,25), (2,17))2610(4,25)(3,8)

The decider computes one MSM for the last row, gets (4,25), and accepts. That single check covers all four input claims.

One recursive step

Here is how this fits inside the step that the previous chapter describes. The previous proof's statement contains the accumulator acci​. The step's circuit then does the following:

  1. It runs the previous proof's verifier up to the split of Section 2, which yields a new claim from the previous proof's own inner product argument.
  2. It derives xM​, α and τ from a transcript that contains acci​ and the new claim, and it computes CM​ and vM​.
  3. It checks the merge's inner product argument up to the split, using a merge proof that the prover computed outside the circuit and supplied as a witness.
  4. It places the resulting claim in its own statement as acci+1​.

Each of these takes logarithmic work, so the circuit stays small and its size does not depend on how many steps came before. Once a step has proved this, later steps have no use for the old merge proof, because the new proof vouches for the check. The circuit's group operations raise a further problem, because the curve's points do not live in the circuit's field. The curve cycles chapter deals with that, and we ignore it here.

Proof-carrying data has a tree in place of a chain, so a step with two children holds two accumulators and two new claims. The formula with powers of α from Section 5 covers this case. Here is an example with three inputs at once:

Merging claims 1, 2 and 4 in one step with the same challenges gives vM​=17 and CM​=(6,8). The final check passes, and the output point is (22,7). The output point depends only on uM​, so it matches the two-claim merge above, and the inputs affect the proof only through CM​, vM​, the cross terms and the final scalar.

What each party pays

The verifier's side of a merge is now small, and the prover takes on the linear work:

Work for one merge of two claims, n=213WhoAmount
Evaluate g1​ and g2​ at xM​Verifier12 squarings and 26 factor multiplications
Compute CM​Verifier1 scalar multiplication
Combine the Lj​ and Rj​Verifier26 scalar multiplications
Evaluate gM​ at xM​Verifier13 factor multiplications, reusing the squarings
Final checkVerifier2 scalar multiplications
Multiply out g1​ and g2​Proverabout 16,384 field multiplications
Compute all the Lj​, Rj​ and fold GProver32,764 scalar multiplications

The prover's count comes from the rounds. A round on a vector of length m takes m scalar multiplications for L and R and another m for the two weights on each entry of the folded G, and the lengths halve from n down to 2.

Over the same hypothetical 1,000 claims, the group work that a verifier must do drops from 8,192,000 scalar multiplications to 29 per merge plus one decider MSM of 8,192. The accumulator stays at one point and 13 challenges, or 448 bytes at 32 bytes each, and each merge proof holds 26 points and one scalar, or 864 bytes.

Deciding needs no help from the prover. Anyone who holds the final accumulator and the public generators can run it, and the Halo 2 book describes this as one linear-time computation that settles an entire batch.

8. Why cheating fails

Nothing inside the chain runs the MSM, so we need to see why a false claim cannot disappear along the way. A cheater wants some input claim to be false while the final accumulator is true.

The counts below need some care. On the toy curve every point is a known multiple of every other, so the toy curve itself allows forgeries, as chapter 07 showed. To model a real curve, the script also runs the protocol in a formal group, where each point is a list of its coefficients on G0​,…,G3​ and U, and where two points are equal only if the lists are. It also repeats the first count below on the toy curve at a sample of weights, with the same result.

A false input

Take the case where the prover holds a real polynomial behind a wrong point, and folds honestly from then on:

Take the false point from Section 4, which commits to h, and merge it with the true claim 2. For each of the 1,806 pairs of xM​ and nonzero α, run the merge with the prover folding its real vector and supplying its honest folded generator. The check passes for 126 pairs, and these are exactly the pairs with xM​∈{2,7,20}, the roots of h−g1​. The weight α plays no part, because only one input is wrong.

Two false inputs

With two false inputs there is a chance that the errors cancel, which is the case that α exists to handle:

Now make claim 2 false as well, with h2​−g2​ having the coefficients (1,40,0,2). A pair (xM​,α) passes when (h1​−g1​)(xM​)+α(h2​−g2​)(xM​)=0. Running all 1,806 pairs gives 39 that pass, against the bound of 4⋅43=172 from the multivariate root count, since the expression has total degree at most 4. To see what α prevents, let the second error be the exact negative of the first. With α fixed at 1 the errors cancel, and all 43 values of xM​ pass. With α random, the 166 passing pairs are those 43 pairs with α=1 and the pairs at the three roots.

For a real curve the same reasoning gives a bound of n divided by q, which is negligible for n=213 and a field of about 2254 elements.

A false claim moves forward

A cheater can also lie about the output. Section 2 showed that a supplied point can absorb an error in the final check, and the merge's final check has a supplied point too. When an input is false, the merged evaluation claim is false at almost every xM​, so the merge's final check can pass only with a false output point:

The forged claim from Section 2 is ((26,23), (15,10)), and its point hides 11⋅U. Merge it with the true claim 2, using the challenges of Section 6. The commitment becomes (4,6), and the honest fold reaches G^M​=(22,7), but the check fails, since the left side is (22,24) and the right side is (9,9). The script repeats this in the formal group for all 1,806 pairs and five values of τ, with no acceptances. To continue, the prover has to repeat its trick and supply G^M∗​=G^M​+31⋅U=(8,22). That passes the final check, so the false claim has moved to the output. The decider then computes (22,7), sees that it differs from (8,22), and rejects.

The false claim therefore survives from merge to merge, and at each merge it has a small chance of turning into a true one through a lucky xM​. If it survives to the end it meets the decider, which computes the MSM and catches it. This is the sense in which one decider check covers everything before it. A true final accumulator means that, except with small probability at each merge, every input claim was true too. A verifier who skips the decider has no such assurance, because every step before the decider may be carrying a false claim.

The prover could also send altered Lj​ and Rj​ in the merge, instead of folding honestly. Chapter 07's gap argument covers this, and it allows at most 4 surviving challenges per round. On the toy curve that fraction is large, but on a real curve it is negligible.

The order of the messages

The bound on false inputs depends on the prover fixing its points before it sees xM​:

Suppose the prover learns xM​=29 before it fixes its point. It picks h=g1​+5(X−29), whose coefficients are (25,20,23,21), and sends the commitment (18,21), which is not G^1​. Since h(29)=g1​(29), the merge passes, and every later step is honest. If instead the point is fixed first and xM​ varies over all 43 values, the merge passes only at xM​=29.

In a non-interactive proof, this means that the transcript has to absorb both input claims in full before it produces xM​, α and τ, for the reason given in chapter 03. The challenges u belong to the claim as much as the point does, because a prover who could change them after xM​ was fixed could change the polynomial that the check compares against.

The weight on U

A prover can also hide a multiple of U in an input point, and arrange the G part and the U part of the point to offset each other at every xM​ at once:

Take the point G^1​+6⋅G0​+6⋅U=(27,1), so that the prover holds g1​+6 and the hidden 6⋅U pays for the extra value. With τ fixed at 1, the merge passes for all 1,806 pairs (xM​,α), although the claim is false. At our xM​ and α, running all 42 nonzero values of τ gives acceptance at τ=1 only.

This particular false point does not by itself let an honestly folding prover pass a false value in chapter 07's final check, because the supplied point would add a multiple of G0​ to the right side, and nothing on the left side matches it. It still breaks the reasoning above, which needs a passing merge to mean that the input claim is literally true. The weight τ restores that link at the cost of one more challenge.

Assumptions

This reasoning relies on the following, and it is informal and not a security proof. The discrete log relation assumption holds for G together with U. The prover builds its points from the generators with coefficients it knows. Challenges are uniform and come after the data they test, which in a non-interactive proof means treating the transcript hash as a random oracle. The decider's MSM runs honestly on the final accumulator.

Recursion adds a further layer that we have not analysed, because each step's statement relies on proofs that themselves rely on earlier proofs. The abstract of the accumulation scheme paper notes that Halo's authors outlined their approach without details or security proofs, and it presents foundations for that approach as the paper's purpose.

9. Atomic accumulation

We can now give the general pattern a name. An accumulation scheme has three parts, and the book's IVC section uses the symbols below for the last two:

PartJobIn this chapter
Accumulation proverProduce a new accumulator and a proof that it was formed correctlyCompute aM​, run the argument, supply G^M​
Accumulation verifier, Acc.VCheck the update cheaplyCompute CM​ and vM​, and run the final check with the supplied point
Decider, Acc.DecideCheck the final accumulator, possibly at great expenseCompute ⟨gu​,G⟩ and compare

The scheme in this chapter has a special property, which is that the accumulator is all that anybody needs. The polynomial behind (G^,u) can be rebuilt from u, so the prover of the next merge needs no extra data, and neither does the decider. The book calls this form atomic accumulation, and it describes this as the original formalization, in which the accumulator alone lets a party produce and check each insertion.

The atomic form has a cost that explains why later work moved on from it. Every proof placed into an atomic accumulator has to be partly verified inside the circuit, so that proof must already be short and its verifier sublinear, apart from the deferred part. In our setting, that means running a full inner product argument for each proof at every step, and then one more for the merge, which puts this linear work on the prover of every step.

The next chapter relaxes this by letting the accumulator have a separate witness that only the prover and decider hold. That permits a long proof with no inner product argument during recursion, and it is the form that Ragu uses.

10. The other linear step

Chapter 09 listed two linear steps, and so far we have dealt only with G^. The other is computing s(x,y), which requires reading the whole circuit. The test we used here relies on gu​ having a short product form, and the wiring polynomial has none. The verifier cannot evaluate it cheaply at a random point, so the spot check of Section 4 does not carry over directly.

The Ragu Book describes how Halo handled this case. The prover supplies a claimed commitment to s(X,y), and a parallel protocol reduces such claims together by random spot validation, using a consistency check across variables. Ragu has its own treatment in the chapter on wiring and the registry, so we leave the details to that chapter.

11. Accumulation in Ragu

The code at commit 3219e08 contains the exact objects of this chapter, in crates/ragu_pcd/src/ipa/verifier.rs:

pub struct Accumulator<C: Affine> {
    /// The claimed output of the linear-time polycommit opening protocol
    pub g: C,

    /// A vector of challenges u_0, ..., u_{k - 1} sampled by the verifier, to
    /// be used in computing G'_0.
    pub u: Vec<C::Scalar>,
}

The field g is our G^, and u holds our u, in the one-sided convention of chapter 07, so the polynomial behind it is ∏j​(1+wj​X2k−j). The method Guard::use_g is the split of Section 2, since it takes a supplied point and returns this type. The method Guard::use_challenges is the direct route, which adds the whole vector to the MSM.

Reconstructed from code at commit 3219e08, not confirmed by the authors

The deferral is not in use. Our search finds use_g and compute_g called only from one IPA test, and we found no code that merges two such accumulators. The IPA runs at compression, and the compression verifier calls use_challenges, so it computes the full MSM.

What Ragu accumulates instead. The fuse accumulates a polynomial p(X) with a claim p(u)=v, which is a batched evaluation claim of the form in chapter 08, and the proof keeps the polynomial itself. That is split accumulation, the subject of the next chapter. The same file has a private type also named Accumulator, which is unrelated to the IPA type above.

Planned use. The aggregator profile foresees circuits that verify a compressed proof, and those circuits would face this same MSM. They have not landed, and we found nothing that says whether they would use use_g, so this remains unsettled.

The book and the code describe this differently

Ragu Book: the appendix on SNARKs says that the NARK's instance contains "the IPA accumulator state", and its comparison table lists IPA verification as linear time, deferred via accumulation.

Code at 3219e08: as above, a proof's accumulated state is a batched polynomial claim and not a point with its IPA challenges, and the IPA's MSM is computed in full at compression. The doc comment on Accumulator also calls it "an evaluation claim and a proof", while its fields are one point and the challenges.

This site follows the code. The book's general statement that Ragu's scheme descends from Halo's is consistent with both, since the next chapter builds directly on these ideas.

Names differ across sources as well. The book's Halo passage writes the claim as (G,u) with polynomial gu​, its IPA section writes G0​, and the code writes G0′​, while this site writes G^. The Halo 2 book's recursion page uses factors of the form ui​+ui−1​X2i−1, so compare the placement of the inverse and the order of the rounds before you move a formula between sources.

12. Where this chapter leaves us

This chapter took the following steps:

  1. The verifier can take G^ from the prover and finish everything else with logarithmic work, which leaves the claim (G^,u) that G^ commits to gu​.
  2. A decider can confirm a claim with one MSM, but claims would pile up if each one had to be decided separately.
  3. Opening G^ at a random point tests the claim, because the verifier can evaluate gu​ with k factors, and two different polynomials rarely agree at a random point.
  4. A random combination of two claims is an evaluation claim that the verifier can state on its own, and the prover's witness is public. Proving it with one inner product argument yields a single new claim.
  5. Repeating this keeps one fixed-size accumulator across any number of steps, with logarithmic verifier work per merge and one MSM for the decider.
  6. A false input passes only at rare challenges, and otherwise it forces a false output, so the false claim travels to the decider. The chain establishes nothing until the decider has run.
  7. The accumulator here is all that the next prover needs, which makes this atomic accumulation. Ragu's code contains the claim type, but its recursion uses a different form.

Atomic accumulation still runs a complete inner product argument at every step. The next chapter separates each accumulator into a public instance and a private witness, which removes that argument from the recursive path and lets the steps use a proof without any succinctness at all.

Last Updated: 11/4/26, 12:56 PM
Contributors: Hanh
Prev
Recursive Proofs
Next
Split Accumulation