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

Split Accumulation

The last chapter kept one claim alive across a chain of proofs and left the expensive check to a single decider at the end. That worked because the accumulator carried everything the next prover needed, but it had a price, since every step had to run a complete inner product argument for the proof it verified and another for the merge.

This chapter removes those arguments from the recursive path. The idea comes from noticing that the recursive verifier never needs to read most of a proof, so we divide both the proof and the accumulator into a short part that the circuit reads and a long part that only a prover and a decider ever touch. The long part need not be short at all, which is why a step can use the non-succinct proof of chapter 09. Bünz, Chiesa, Lin, Mishra and Spooner formalized this in Proof-Carrying Data without Succinct Arguments under the name split accumulation, and it is the form the Ragu Book says Ragu implements.

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

The book gives the syntax and a simplified scheme for evaluation claims. The explicit formulas, the choice of what the toy circuit reads, and the numeric run are our own assembly of that scheme with chapter 08 and chapter 09. We could read only the abstract of the paper, so the description of the scheme here follows the book. Section 11 compares all of this with the code.

Terminology

This chapter says that claims fold into an accumulator, because the book uses "accumulation" and "folding" interchangeably for what Ragu does. A fuse is still the PCD operation of chapter 02, which contains folds. A merge still means the operation on Halo's claims from chapter 11. The book's evaluation section says "merge circuit" where its IVC section says "fuse circuit" for the same object, and we use "fuse".

1. What atomic accumulation still costs

Section 9 of chapter 11 named its scheme atomic, because the accumulator alone lets anyone produce and check the next update. To see what that property costs, count the group work in one recursive step of that scheme:

Take n=213 generators, and one step that holds one earlier accumulator and one new proof. The circuit batches the proof's claims, which takes 6 scalar multiplications, runs the proof's inner product argument up to the split, which takes 28, and then runs the merge, which takes 29, for 63 in all. Outside the circuit, the prover commits to f with 8,192 scalar multiplications and runs two inner product arguments at 32,764 each, so 73,720 at every step.

Most of this comes from the two inner product arguments. Both exist for the same reason. An accumulation verifier sits inside a circuit, so anything it reads becomes part of that circuit, and an atomic verifier reads the whole proof it is given. The proof therefore has to be short, which forces an argument at every step, and the output of each argument is one more claim about G^ for the merge to handle.

If the verifier could leave most of a proof unread, the proof could stay long, and the arguments could go. That requires some other party to check the unread part eventually, and the decider is already such a party. We therefore need to find out which parts of a proof the recursive verifier has to read, and we can do that by inspecting the verifier of chapter 09.

2. Sorting the verifier's work by what it reads

Section 16 of chapter 09 listed that verifier's steps. Here are the ones concerned with openings and the revdot product, sorted by the data each one touches:

Verifier step from chapter 09Work for 4n=213What it reads
Compute t(x,z)Two geometric sumsChallenges
Check the split of b(x)A few field operationsInstance values
Derive f(u)One inverse and a few multiplications per claimInstance values and prover messages
Compute Pˉ and v5 scalar multiplicationsInstance commitments and prover messages
Recompute S, Aˉ, Bˉ3 MSMs of size 4n, or 24,576 scalar multiplicationsWitness vectors
Compute ⟨⟨a,b⟩⟩8,192 field multiplicationsWitness vectors
Recompute Pˉ from p1 MSM of size 4n, or 8,192 scalar multiplicationsWitness vector
Evaluate p(u)8,192 field multiplicationsWitness vector

The two groups differ sharply, and the difference lines up with cost. Every step that reads a witness vector is linear, and every step that avoids one is cheap. This is the division that chapter 09 drew when it listed the instance part and the witness part of the proof. There we noted the division only as a matter of size, and now we can use it as a plan. The circuit runs the upper rows, and the lower rows wait for a decider.

The lower rows still look like several separate jobs. The last two are the evaluation check, and they concern the claims that chapter 08 knows how to batch. This chapter defers those. The revdot row needs its own folding, which is the subject of chapter 14, and the correctness of S against the circuit is the subject of chapter 15. We left the computation of s out of the table for that reason, since it is linear and reads the circuit rather than the proof. The book lists the same three subprotocols as the verifier's linear work.

3. Instances and witnesses

Chapter 03 introduced instances and witnesses for a whole statement, and the same words apply to one evaluation claim. Its instance is the triple (Cˉ,x,y) of commitment, point and value. Its witness is the polynomial behind the commitment, together with the blinding factor. The relation between them has two conditions:

⟨p,G⟩+γ⋅H=Cˉandp(x)=y.

Take the first claim of chapter 09. Its instance is (Aˉ,xz,a(xz))=((22,24), 2, 9), three values that anyone can hold. Its witness is a=(9,27,9,3,3,3,0,0) with γa​=17. Checking the claim takes both parts, since ⟨a,G⟩+17⋅H=(22,24) and a(2)=9.

The instance has a fixed size, so a circuit can read it at a fixed cost. The witness has 4n entries, and checking the first condition takes an MSM of that size. The instance alone also says nothing conclusive, because any prover can write down a triple. It becomes meaningful only when somebody with the witness runs the check.

The word "witness" here needs a warning. The book's evaluation section calls this a secret witness, held by the prover. In this chapter that describes who needs the data, which is different from a promise that the data stays hidden. Section 11 returns to the point.

4. An accumulator with two parts

Chapter 08 turned a list of evaluation claims into a single triple, and a triple is again an instance of the relation above. So the output of that reduction has the right shape to serve as an accumulator, if we keep the output polynomial with it. Following the book's definition, the accumulator has two parts:

acc.inst=(Pˉ,u,v),acc.wit=(p,γ).

The circuit reads the first part, and the second part travels beside the proof. This is what separates the scheme from chapter 11. There the polynomial gu​ could be rebuilt from public challenges, whereas here nothing in the instance's u and v determines p:

For (u,v)=(17,23), trying all 79,507 polynomials with 3 coefficients finds 1,849 that pass through this point, and each extra coefficient multiplies that count by 43. With 8 coefficients there are 437=271,818,611,107 of them. In chapter 11, by contrast, u=(15,10) gave one polynomial and only one.

The commitment does narrow this down, since a binding commitment fixes one polynomial as far as any prover can tell, but finding it from Pˉ would mean solving discrete logs. So a party who holds only the instance cannot run the next fold and cannot decide the accumulator. Whoever continues the computation has to receive the witness too. That is the price of the split, and we measure it in Section 7.

5. The three algorithms

A scheme of this kind has three algorithms. The book gives the first two in this form, and it names the decider in its description of accumulation:

AlgorithmReadsProducesRuns
Acc.P, the accumulation proverProofs and accumulators, both partsA new accumulator, both parts, and a proof pf of the updateOutside any circuit
Acc.V, the accumulation verifierInstances of the inputs, the new instance, and pfAccept or rejectInside the next circuit
Acc.Decide, the deciderOne accumulator, both partsAccept or rejectOnce, outside any circuit

The second row is the defining feature of the scheme, because a verifier that reads only instances has no need for a short witness. To turn chapter 08's reduction into these algorithms, we only have to decide what goes in the input list and which messages form pf.

The input list

A step holds an earlier accumulator and a new proof. The accumulator's instance is itself one evaluation claim, and the proof contributes the claims of chapter 09. That gives five claims about five polynomials:

(Pˉold​,uold​,vold​),(Aˉ,xz,a(xz)),(Bˉ,x,b(x)),(S,x,s(x,y)),(K,y,c).

The book's list has two more entries for the constant wire, which our toy circuit does not use. The proof in chapter 09 also carried its own batched triple (Pˉ,u,v). A recursive step has no need to batch the proof's claims separately and then fold the result, because it can place them directly in this one list.

The accumulation prover

The prover follows the steps of chapter 08 with this list. We keep that chapter's weights, in which the first claim takes the highest power of α and f takes the highest power of β. Write (Cˉi​,xi​,yi​) for the claims in order and pi​ for their polynomials, so that p0​ is the old accumulator's polynomial and p1​,…,p4​ are a, b, s(X,y) and k.

After receiving α, the prover divides and combines,

qi​(X)=X−xi​pi​(X)−yi​​,f(X)=i=0∑4​α4−iqi​(X),

and it sends Fˉ=⟨f,G⟩+γf​⋅H. After receiving u, it sends the five values pi​(u). After receiving β, it forms the new witness:

p(X)γ​=β5f(X)+i=0∑4​β4−ipi​(X),=β5γf​+i=0∑4​β4−iγi​.​

Here γi​ is zero for s and k, which have no blinding factor. The messages make up the accumulation proof, pf=(Fˉ,p0​(u),…,p4​(u)), which matches the book's. The book describes it as an internal value for the circuit's prover, so it goes into the next circuit's witness and is not an output of the recursive step.

The accumulation verifier

The verifier derives what the new instance has to be, using only the old instances and pf. Its arithmetic never mentions a polynomial's coefficients:

f(u)Pˉv​=i=0∑4​α4−iu−xi​pi​(u)−yi​​,=β5⋅Fˉ+i=0∑4​β4−i⋅Cˉi​,=β5f(u)+i=0∑4​β4−ipi​(u).​

It accepts if the claimed new instance equals (Pˉ,u,v), and if u is the challenge that the transcript produced. This takes one scalar multiplication per commitment and one inverse per claim, however large n is, because no vector and no inner product argument appears in the calculation.

The two sides agree for an honest prover. Expanding the commitment to the new witness and applying linearity gives

⟨p,G⟩+γ⋅H​=β5(⟨f,G⟩+γf​⋅H)+i=0∑4​β4−i(⟨pi​,G⟩+γi​⋅H)=β5⋅Fˉ+i=0∑4​β4−i⋅Cˉi​,​

which is the verifier's Pˉ. Substituting u into the definition of p(X), and using qi​(u)=(pi​(u)−yi​)/(u−xi​) from Section 4 of chapter 08 for each term of f(u), gives the verifier's v in the same way.

The decider

The decider checks the relation of Section 3 on the accumulator, so it computes one MSM and one evaluation. It accepts if ⟨p,G⟩+γ⋅H=Pˉ and p(u)=v. Chapter 09's verifier performed this same check at the end, when it recomputed Pˉ from a revealed p. That chapter said the reveal fits how the proof will be used, and we can now say how, since the revealed polynomial is the accumulator's witness and the reveal gives the decider its input.

6. A run on the toy curve

We now run a chain with the step function F(z)=z3+z+5 from chapter 10, starting from z0​=3, with chapter 09's eight generators. All challenges are picked by hand, and all arithmetic takes place on one curve.

Two simplifications apply to this run. Each proof covers only its step's circuit, because a circuit that also holds Acc.V would be far too large for the toy curve, so the run shows the folds on their own. We also ignore the fact that a circuit over F43​ cannot do arithmetic on points whose coordinates lie in F31​, which the next chapter addresses.

The first fold has no earlier accumulator, so its list holds only the first proof's four claims. Chapter 09 already did this calculation:

Chapter 09's proof of z1​=35 gives the input list, and no accumulator exists yet. Running the fold with α=11, u=17 and β=23 repeats chapter 09's batching with no changes, so pf1​=((11,30), 42,29,35,29). The result is

acc1​.inst=((23,24), 17, 23),acc1​.wit=((17,12,34,38,23,36,30,17), 27).

So chapter 09's batch was the first accumulator all along. The second step brings a new proof and has an accumulator to fold:

The second step applies F to 35 and outputs 1. Its challenges are z=16, y=34 and x=37, so xz=33. The statement gives k(Y)=39Y3. The script confirms that this proof's revdot product and split check hold, and these are its polynomials and claims:

PolynomialCoefficients of X0,…,X7BlindingCommitmentPointValue
a(21, 4, 21, 35, 35, 35, 0, 0)17(7,25)3327
b(21, 21, 39, 40, 19, 38, 26, 37)29(27,30)3724
s(0, 0, 38, 42, 8, 34, 2, 9)0(4,25)3712
k(0, 0, 0, 39, 0, 0, 0, 0)0(28,10)3435

The list now has the five claims of Section 5. The old accumulator is acc1​, so its polynomial p1​ and its instance (Pˉ1​,u1​,v1​) come first, in the place that Section 5 calls p0​. The first stage combines the quotients:

The verifier sends α=20, whose powers give the weights in the next table. The first row divides p1​(X)−23 by X−17, which is the only difference from chapter 09's list.

QuotientWeightCoefficients of X0,…,X6
qp1​​40(13, 38, 23, 32, 41, 18, 17)
qa​2(8, 34, 3, 29, 35, 0, 0)
qb​13(21, 0, 28, 2, 10, 19, 37)
qs​20(41, 29, 23, 39, 2, 34, 9)
qk​1(20, 36, 39, 0, 0, 0, 0)
f(15, 11, 26, 37, 31, 13, 8)

With the blinding factor γf​=7, the prover sends Fˉ=(20,25).

Next the prover sends the values at a fresh point:

The verifier sends u=30, and the prover sends the five values. The verifier then derives f(u) from those values and the instances:

InputValue at uClaimed valueu−xi​RatioWeightTerm
p1​28231374022
a28274014228
b422436221328
s3512369208
k16353937137

The last column sums to f(30)=37, and the prover gets the same number by evaluating f.

The first row is the fold's link to the past. The value v1​ now sits inside the formula for f(u), so a false v1​ would make this number wrong. The last stage produces the new instance:

The verifier sends β=25. Each input carries its weight into the commitment, the value and the blinding factor.

InputWeightCommitmentValue at uBlinding factor
Fˉ24(20,25)377
Pˉ1​13(23,24)2827
Aˉ16(7,25)2817
Bˉ23(27,30)4229
S25(4,25)350
K1(28,10)160
CombinedPˉ2​=(24,1)v2​=31γ2​=39

The accumulation verifier has now finished. It read no polynomial, and its recomputation gave ((24,1), 30, 31). The prover computes the new witness from the polynomials, using the same weights, which gives p2​=(24,21,24,38,4,11,26,7) and γ2​=39. This vector has 8 entries, the same as p1​.

The witness kept its length even though it absorbed a new round of claims, because each fold takes a linear combination of vectors that all have 4n entries. This is why a proof's size does not depend on the length of its history, as chapter 02 required.

The third step repeats the procedure, and the next table collects all three folds:

FoldNew proof coversInput claims(α,u,β)Accumulator instanceAccumulator witness p
135=F(3)4(11, 17, 23)((23,24), 17, 23)(17, 12, 34, 38, 23, 36, 30, 17)
21=F(35)5(20, 30, 25)((24,1), 30, 31)(24, 21, 24, 38, 4, 11, 26, 7)
37=F(1)5(24, 26, 38)((25,29), 26, 20)(5, 39, 23, 37, 39, 0, 2, 21)

Suppose the chain stops here, so that a decider takes over:

The decider receives acc3​. It computes ⟨p,G⟩+42⋅H=(25,29), which equals Pˉ3​, and it evaluates p3​(26)=20, which equals v3​. It accepts. One MSM over 8 generators and one evaluation of 8 coefficients stand in for opening all twelve polynomials of the three proofs.

The following figure shows how the two parts move through this chain.

Two lanes running left to right. In the upper lane, the accumulator's instance passes through Acc.V boxes inside circuits, with each proof's instance entering from above. In the lower lane, the accumulator's witness passes through Acc.P boxes outside circuits, with each proof's witness entering from below. Arrows run up from Acc.P to Acc.V carrying the new instance and the accumulation proof. Both lanes end at the decider.

A tree needs no new idea. A node with two children holds two accumulators and two proofs, and all of their claims go in one list, in the way chapter 10 described:

Suppose a second chain has proved 9=F(8) and reached the accumulator ((22,7), 20, 3). A node takes this one and acc2​ from its two children, along with one new proof from each side. The input list has 2+2⋅4=10 claims. With α=18, u=17 and β=32, the fold outputs ((26,23), 17, 40). The accumulation verifier accepts, and the decider accepts the witness (19,5,37,4,13,7,42,21). The proof pf grows to one point and 10 values, while the output keeps the same three-part instance and 8-entry witness.

7. What the split costs and what it saves

The next table puts the two schemes side by side for the opening work alone. Both schemes also need the commitments to the proof's polynomials, and both still have to deal with the revdot product and the wiring. Those parts are the same in both columns, so we leave them out.

For n=213 and 32-byte valuesAtomic (chapter 11)Split (this chapter)
Scalar multiplications in the circuit, one proof and one accumulator636
Scalar multiplications in the circuit, two proofs and two accumulators9911
Growth of that count with nLogarithmicNone
Prover's scalar multiplications for this opening work at each step73,7208,192, to commit to f
Accumulator data that the circuit reads448 bytes96 bytes
Proof and accumulator data handed to the next prover1,696 bytes1,049,216 bytes
How much of that is the accumulator's witnessNone262,176 bytes
Decider1 MSM of 8,1921 MSM of 8,192 and one evaluation

The saving and the cost both come from one change. The verifier's count falls and stops depending on n, since the Lj​ and Rj​ have gone. The prover's group work falls, since it no longer folds generators. In return, the data handed from step to step changes from a few short values to whole vectors, because the next prover needs every one of them. These byte counts describe our protocol at Ragu's polynomial size, and Ragu's own proofs have a different layout, as Section 11 shows.

Because the witness never enters a circuit, the growth affects storage and bandwidth and does not affect recursion. That trade suits a system like Ragu, where a proof stays large while it is being fused and only needs to become short when it leaves the tree.

The decider's linear work has not disappeared, and it has the same size as in chapter 11. It occurs once for a whole history in both schemes. The difference lies in what the steps before it had to do.

8. Why a NARK is enough

We can now rewrite the recursive relation of chapter 10. The circuit no longer checks the previous proof. It checks that the accumulator was updated correctly to take that proof in. Following the book's relation, with the inputs narrowed to what Acc.V reads,

public: witness: checks: ​zi+1​, acci+1​.instzi​, πi​.inst, acci​.inst, pfi+1​F(zi​)=zi+1​  and  Acc.V(acci​.inst, πi​.inst, pfi+1​, acci+1​.inst)=1.​

The book lists the whole of πi​ and acci​ in the witness, and Acc.V reads only their instance parts. The witness parts go to Acc.P, which runs outside the circuit, so a proof of this relation can be a NARK. The output handed onward is the pair (acci+1​,πi+1​). A final verifier checks πi+1​ directly and then runs the decider on acci+1​. The paper's abstract states the general result, which is that any non-interactive argument of knowledge with a split accumulation scheme yields proof-carrying data, without requiring the argument to be succinct.

The reasoning runs backward from the end, in the same way as chapter 10's walk. The final verifier establishes that the last circuit was satisfied, so Acc.V passed on the last fold. The decider establishes that the last accumulator is true. A passing fold with a true output means, except with small probability, that its inputs were true too, so the earlier accumulator and the last proof's opening claims were true. Each earlier proof has its own circuit that did the same thing for the fold before it. Section 10 examines the step in the middle of this argument.

Chapter 09 listed two linear costs as targets for this part of the site. The cost of computing G^ does not arise on the recursive path of this scheme, because that path contains no inner product argument. The other cost, computing s(x,y), remains. In the toy run the script recomputes s from the circuit, because the folds in this chapter establish what S opens to, and they establish nothing about whether S belongs to the right circuit. The wiring chapter deals with this.

The base case and the record of initial states follow chapter 10. Our run began with no accumulator at the first fold, which keeps the numbers equal to chapter 09's. The book uses a placeholder accumulator instead, while the code uses one Bootstrap step, and that chapter's warning compares them. The Merkle root of initial states in the book's PCD description has no counterpart in the code, so we leave it out.

9. Folding schemes

Nova introduced a related formalization called a folding scheme, which its abstract describes as a reduction from checking two instances of a relation to checking one. We could read only that abstract, so this section rests on it and on the book. The book says the two formalizations are equivalent for all practical purposes, and elsewhere it calls folding a related alternative that merges statements without running a proof's verifier during accumulation. The two wordings fit together once we write our scheme as a folding scheme.

Take the relation of Section 3 with Pˉ, u, v as instance and p, γ as witness. Then Section 5 reduces checking five instances of this relation to checking one instance of the same relation, with a verifier that sees only instances:

Accumulation termFolding termIn this chapter
acc.instRunning instance(Pˉ,u,v)
acc.witRunning witness(p,γ)
π.instFresh instancesThe claims about a,b,s,k
Acc.P and Acc.VFolding prover and verifierThe two sides of Section 5
pfFolding proofFˉ and the values at u
Acc.DecideChecking the final instance against its witnessThe MSM and the evaluation

So our scheme is a folding scheme for evaluation claims, and the book's phrase "without the use of any (S)NARK verifier" describes the same thing as a verifier that reads nothing of a proof beyond its instances. What differs is mainly the point of view. Accumulation starts from a proof system and asks what can be postponed, whereas folding starts from a relation and asks how to combine instances of it.

Not every relation folds as cleanly as this one, and the reason explains why pf can take different forms. The book says that an accumulation proof contains the cross terms the verifier needs. Evaluation claims at one point combine linearly and need no such term, which is why our pf only has to bring the claims to a common point. A relation with a product does not combine linearly. Suppose the claim is ⟨a,b⟩=c, and we fold two instances with a challenge r. Multiplying out gives

⟨a1​+ra2​,b1​+rb2​⟩​=⟨a1​,b1​⟩+r(⟨a1​,b2​⟩+⟨a2​,b1​⟩)+r2⟨a2​,b2​⟩=c1​+rE+r2c2​,​

where the middle term E is the cross term. The verifier cannot compute it from instances, so the prover has to supply it.

Take a1​=(2,5), b1​=(7,3) with c1​=29, and a2​=(4,6), b2​=(1,8) with c2​=9. At r=9 the folded vectors are (38,16) and (16,32), and their inner product is 2. The two old values give only c1​+r2c2​=27. The prover supplies the cross term E=2 before it learns r, and c1​+rE+r2c2​=2 matches.

Nova's folding of R1CS is commonly described with a term of this kind, although its abstract does not mention one and we have not checked this against the paper. Ragu's revdot claims have the same structure, so chapter 14 develops this example into a complete protocol.

10. Why cheating fails

A prover in this scheme can lie in more places than in chapter 08, because the verifier no longer sees any polynomial. We go through what it can try. The toy curve permits forgeries, since every discrete log is known, so the counts below model a prover who holds real polynomials and does not exploit those relations, except in the last example, which shows what happens if it does.

Altering the output

The verifier recomputes the new instance from the inputs, so the prover has little freedom in stating it:

At the second fold, we replaced Pˉ2​ with each of the 42 other group elements, replaced v2​ with each of the 42 other values, and separately replaced Fˉ with each of the 42 other group elements while keeping the output. We also shifted each of the five values at u by each of the 42 nonzero amounts while keeping the output, which makes 210 more cases. The accumulation verifier rejected 294 of the 336 altered runs. The other 42 are shifts of the value for a. At these particular challenges the effect on the derived f(u) and the effect on that polynomial's own term happen to cancel, so the output stays the same true claim and the prover gains nothing.

The instance is therefore a function of the inputs and of the prover's messages. The prover keeps the freedom to change those messages consistently, and the verifier cannot detect that:

For example, a prover can send Fˉ∗=(5,29) and output the matching point (16,10). The accumulation verifier recomputes that same point and accepts. This happens for all 42 false values of Fˉ, because the verifier has no way to see what Fˉ commits to. With the honest witness, the decider rejects all 42.

This shows the limit of what Acc.V does. It confirms the arithmetic of the update and says nothing about whether the new claim is true. The decider has to confirm that, and for a false Fˉ the decider can reject because it recomputes the commitment from the vector.

A false claim travels to the decider

Now suppose an input is false. Say the prover states the old accumulator's value as vold​+δ, where vold​ is the true value, and it otherwise follows the protocol, including honest division, which ignores claimed values. The polynomials and Fˉ stay honest, so Pˉ commits to the true p. The error enters at one place, which is the first term of the formula for f(u):

α4⋅u−uold​p0​(u)−vold​−δ​=α4⋅u−uold​p0​(u)−vold​​−α4⋅u−uold​δ​.

The derived f(u) is therefore off by the last term, and its weight in v is β5. That gives the gap between the stated value and the true value of p at u:

v−p(u)=−β5α4⋅u−uold​δ​.

Every factor is nonzero as long as α and β are nonzero, so a false input produces a false output. Each later fold repeats this calculation, with the previous gap in place of δ:

Take the run of Section 6, but let the prover state v1​=24 where the true value is 23. Every later step is honest, with the same challenges.

AccumulatorPˉuStated vTrue p(u)Gap
acc1​(23,24)1724231
acc2​(24,1)30203132
acc3​(25,29)2692032

The accumulation verifier accepts both folds, because the output instance is what it recomputes. The decider rejects the last accumulator, since its value differs from the polynomial's.

For the fold above, the formula gives −255⋅204⋅1/(30−17)=32, which matches the table. We also ran all 68,796 choices of nonzero α, nonzero β and an allowed u out of 39 values, with the gap computed directly and compared with the formula. The gap is zero in none of them.

The gap therefore survives every fold and reaches the decider. A chain that never runs the decider has established nothing about its openings, which was also the conclusion of chapter 11.

A prover can do better than stay honest after the lie, for example by altering the values at u or by committing to something other than the true quotients. Chapter 08 counted these options in full, and the same bounds apply to each fold, because the fold is that protocol with the accumulator as one more claim. For a real field each fold's chance of hiding a false claim is negligible, and the chances add across folds and grow with private retries under Fiat–Shamir.

Dropping the accumulator

A prover with a false accumulator might try to avoid carrying it at all, by folding some other accumulator in its place. Nothing in the fold's arithmetic forbids this:

Suppose the prover holds the false acc1​ from above and wants to be rid of it. It folds an unrelated true accumulator ((22,7), 20, 3) in its place, and gets the output ((28,21), 30, 2). If the circuit reads the swapped instance, the accumulation verifier accepts and the decider accepts. Run against the instance of the false acc1​, the same output fails.

The fold cannot detect this by itself, so the protection has to come from the circuit. The old accumulator's instance has to be part of the public statement of the previous proof, which ties it to that proof through k(Y). This is the same shared-wire requirement that chapter 10 met for the state z1​, where the inner proof's public input is computed from the wire the step reads. Here the wires for acci​.inst in the next circuit must feed both Acc.V and that computation.

The order of the messages

Chapter 08 showed that each challenge must follow the message it tests, and in a non-interactive proof this means the transcript has to absorb everything the challenges depend on. The accumulator's instance belongs on that list. It is the one input that chapter 08 did not have, so it is the easiest to forget:

Suppose the transcript leaves out the accumulator, so that the prover knows α=20, u=30 and β=25 before it fixes v1​. It states the false value v1​=26, an error of 3, and it sends 24 in place of the true p1​(30)=28, a shift of 39 that solves one linear equation. The two errors cancel in v2​, so the output is the true claim ((24,1), 30, 31). The accumulation verifier accepts and the decider accepts, although acc1​ was false. If instead the prover must fix these messages before β arrives, then trying all 43 values of β finds 2 that pass, namely 0,25.

The pass at β=0 is the case chapter 08 described, in which βm removes the error along with almost everything else, and a random β avoids it.

Binding at the decider

The decider's check means something only because Pˉ can be opened in one way. The argument above assumed this throughout:

Using the known discrete logs of the toy generators, a prover can state the false v2​=32 and present the witness (36,21,42,38,4,11,26,7). This vector commits to the same Pˉ2​=(24,1), and it evaluates to 32 at u=30, so the decider accepts it.

On a real curve, such a witness would give a discrete log relation among the generators.

Assumptions

This reasoning is informal and is not a security proof. It relies on the discrete log relation assumption for the generators, and it treats the transcript hash as a random oracle, with each challenge drawn after the data it tests. It assumes that the circuit ties each input instance to the previous proof, and that the decider runs honestly on the final accumulator. The paper's abstract says its construction is proved secure in the random oracle model under the hardness of discrete logarithms. The recursion adds the further concerns that chapter 10 listed, and we do not analyse Ragu's scheme here.

11. Split accumulation in Ragu

The code at commit 3219e08 has a proof type that contains this accumulator, and its fuse folds it in the way Section 5 describes, with the claims about the children's accumulators at the head of the list. In the first excerpt below, from internal/native/circuits/compute_v.rs, the three entries are the value at u, the child's stored v, and the inverse of u−uold​. The second, from fuse/_10_p.rs, adds the child's polynomial and commitment to the running combination.

StaticFQuery::LeftP => (&eval.left.p_poly, &preamble.left.unified.v, &d.left.u),
StaticFQuery::RightP => (&eval.right.p_poly, &preamble.right.unified.v, &d.right.u),
acc.acc(proof.native_p_poly(), proof.native_p_commitment());

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

  • Where the witness lives. The code has no separate accumulator object for this claim. The Proof struct keeps the polynomial p as a field, and Proof::v computes v by evaluating it at u, so instance and witness travel together as one value.
  • Which claims. The static query list has 20 entries, and compute_f then adds more for each stage polynomial of each child, so a fuse folds far more than our five claims. The children's p take the first two places in that list and therefore the highest powers of α, as in our run. In the β combination they come after each child's other polynomials, which only relabels the weights.
  • The accumulation proof. The polynomial f is marked as ephemeral, used only during the fuse step, which matches the book's description of pf as internal. The values at u go into a committed stage that the proof keeps, which chapter 17 explains.
  • The tie to the previous proof. A child's v is a slot of the unified instance, whose fields are written in k(Y) order, and the k(y) computation covers that instance. We read this as the protection that Section 10 asked for.
  • The decider. The documentation of verify_uncompressed says that this verifier is the decider, and calls it a test oracle rather than a production path. It checks commitments against polynomials in one batch per curve, including P against p. In production, compression restates those checks over commitments and openings, among them an opening of P at u to v, and finishes with one IPA per curve. The inner product argument of chapter 07 therefore comes back once, at the point where a proof leaves the tree. As chapter 11 found, the IPA verifier at this commit computes its MSM in full.

The Ragu Book and the code differ here

Blinding. The book's accumulator has a blinding factor γ. The code's proof stores p with its commitment and no such factor, in line with chapter 08's note on f. Our run includes γ so that its numbers match chapter 09.

Claim list. The book's list has claims about Aˉ, Bˉ, S and K. The code's list has claims about the folded a and b, about registry polynomials in place of S, and about stage polynomials. We found no commitment to a polynomial k among its inputs, and circuits compute k(y) directly.

What the accumulator holds. The book gives the accumulator on one curve as (S,Aˉ,Bˉ,c,Pˉ,u,v). The code's unified instance has no field named S, and it also holds bridge commitments and every challenge of the step.

Number of circuits. The book's accumulation chapter has one fuse circuit per curve, while the code has many internal circuits, and the circuit that recomputes v is only one of them.

This site follows the code. The simplified single-curve scheme remains the book's own way of conveying the core idea, and this chapter uses it in that spirit.

The fold itself differs from Section 5 in two further ways, which we leave to later chapters. A circuit cannot compute Pˉ cheaply, so Ragu divides the fold between two circuits on a curve cycle, as the next chapter describes. Those circuits have to agree on their challenges, which the endoscalars chapter covers.

The witness also raises a question about privacy, because a proof that carries polynomials in the clear reveals what they contain. Neither the book nor the code claims otherwise at this commit. The book states that the current construction does not yet establish zero knowledge, in part because it lacks a randomizer at the level of the fold, which is the operation of this chapter. Chapter 02 records the same status. Tachyon, which has not activated on mainnet and whose design is still changing, depends on fusing proofs of this kind through a different Ragu revision.

12. Where this chapter leaves us

This chapter took the following steps:

  1. Atomic accumulation forces an inner product argument at every step, because its verifier reads the whole of what it is given.
  2. Sorting the verifier's opening and revdot steps shows that every linear one reads a witness vector and every cheap one reads only the instance.
  3. An evaluation claim divides into an instance (Cˉ,x,y) and a witness (p,γ), and so does an accumulator, which is a claim of the same form.
  4. Acc.P runs chapter 08's reduction on the old accumulator and the new proof's claims, Acc.V recomputes the new instance from instances and the accumulation proof, and Acc.Decide runs one MSM and one evaluation.
  5. The witness keeps a fixed length across any number of folds, and the circuit's work on the instance is constant in n, while the data handed between provers grows to the size of the polynomials.
  6. Since the witness never enters a circuit, each step can use a NARK, and the opening claims of a whole history rest on one decider.
  7. Written as a reduction between instances of one relation, this scheme is a folding scheme. Relations with products also need cross terms in the accumulation proof.
  8. A false input leads to a false output at all but a few challenges, so it reaches the decider. This depends on the circuit tying each input instance to the previous proof and on the transcript absorbing the accumulator.

We set aside one problem throughout, which is that Acc.V performs group operations on points whose coordinates live in a different field from the circuit's wires. The next chapter introduces a pair of curves that removes that mismatch, and it shows which circuit folds what.

Last Updated: 11/4/26, 10:49 AM
Contributors: Hanh
Prev
Accumulation
Next
Curve Cycles