Skip to content

Extend split-recursion to multiple proof systems - #1018

Draft
RobinJadoul wants to merge 5 commits into
spec/mainfrom
spec/split-recursion
Draft

RobinJadoul wants to merge 5 commits into
spec/mainfrom
spec/split-recursion

Conversation

@RobinJadoul

Copy link
Copy Markdown
Collaborator

No description provided.

@RobinJadoul RobinJadoul self-assigned this Oct 13, 2026
@RobinJadoul RobinJadoul added the spec Updates and improvements to the spec document label Oct 13, 2026
@github-actions

Copy link
Copy Markdown

Kimi Code Review

⚠️ Review failed: Kimi API request failed with status 401


Automated review by Kimi (Moonshot AI)

@github-actions

Copy link
Copy Markdown

Codex Code Review

  • Medium — Incorrect challenge-binding requirement (recursion.typ:271): The specification requires committing to [x, r] before revealing z, but the checksum compares witnesses [π, r]. Binding the public instance x leaves π adaptable after the challenge, invalidating the random-checksum soundness argument. Require both witness commitments c₀ and c₁ to be fixed before deriving the same z, and include both in the Fiat–Shamir transcript.

The diff changes only the specification; no executable-code issues were found.

@erik-3milabs erik-3milabs left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

general remarks:

  • replace pi by proof
  • replace r by record
  • you're opted to write $v(x; w)$ rather than $v(x,w)$. This is, however, contrary to all other notation in this document. Not saying it is wrong, but it should be clarified somewhere

Comment thread spec/chapters/recursion.typ Outdated
we will write $comm(x)$ and $comm2(x)$ as the (deterministic) commitments to $x$
in the proof system of $verify_0$ and $verify_1$ respectively.

If we write $verify'_(b)([c_x, c_w]; w)$ to be an adaptation of $verify_(b)(c_x; w)$ that additionally gives has a public commitment to the private witness,#footnote[

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • $v_b$ is not yet defined at this point. Or do you mean to use it as a variable that can be either 0 or 1? Eitherway, we should probably define this. Also, I don't know if $b$ is the right choice here.
  • Also, $v'$ was already used in 36.1.2, so we're somewhat overloading things here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

b is indeed just a generic bit here

Comment thread spec/chapters/recursion.typ Outdated
we will write $comm(x)$ and $comm2(x)$ as the (deterministic) commitments to $x$
in the proof system of $verify_0$ and $verify_1$ respectively.

If we write $verify'_(b)([c_x, c_w]; w)$ to be an adaptation of $verify_(b)(c_x; w)$ that additionally gives has a public commitment to the private witness,#footnote[

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If we write $verify'_(b)([c_x, c_w]; w)$ to be an adaptation of $verify_(b)(c_x; w)$ that additionally gives has a public commitment to the private witness,#footnote[
If we write $verify'_(b)([c_x, c_w]; w)$ to be an adaptation of $verify_(b)(c_x; w)$ that is additionally given a public commitment to the private witness,#footnote[

?

Comment thread spec/chapters/recursion.typ Outdated

The first two statements would follow naturally from proving $verify_(b)$ or the derived $verify'_(b)$.
To integrate the last statement, we introduce a "checksum" of the witness, which will be checked by both halves of the split:
$ verify^*_(b)([x, s]; w) = verify'_(b)(x; w) dot (serif("cksum")(w) =^? s). $

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$v^*$ is used for a different purpose later on: we're overloading here.

Comment thread spec/chapters/recursion.typ Outdated

- $serif("cksum")(x) = serif("Hash")(x)$: compute a hash in both halves, at the cost of needing to evaluate a hash in a proof system that is likely not a good fit for that hash.
- $serif("cksum")(x) = comm2(x)$: recompute the commitment $comm2(x)$ as part of $verify^*_0$, and let $verify^*_1$ simply check that the checksum equals the public commitment.
In practice, this would come at the cost of evaluating a Reed-Solomon blowup over the field of $verify_0$ and computing a merkle tree, both inside $verify^*_0$.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In practice, this would come at the cost of evaluating a Reed-Solomon blowup over the field of [...]

This is an implementation detail not described anywhere else in the document.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair, it is mostly meant as a remark to argue why it's not a good/performant approach

Comment thread spec/chapters/recursion.typ Outdated
Finally, we consider the instantiation $serif("chsum")(x) = chevron.l x, z chevron.r$ for a random zero-evader $z$.
This could be implemented by having an additional public input provided to $verify^*_(b)$, or by having $verify^*_(b)$ itself
derive it from the public inputs and context as a Fiat-Shamir challenge.
In either case, $z$ should not be known to the (recursion) prover before being bound to $[x, r]$ via its public commitment.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't the prover also commit to the proof it will be verifying first?

Comment thread spec/chapters/recursion.typ Outdated
the verification cost of computing $z$ and the soundness error of the zero-evader.
Where needed, multiple independent $z$ can be used to amplify soundnes.
In settings where both $verify^*_(b)$ are in the same proof system, with the same commitment scheme, but different representations of the committed data
(e.g. representing $pi$ as a sequence of committed bytes and as a sequence of extension field elemens),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(e.g. representing $pi$ as a sequence of committed bytes and as a sequence of extension field elemens),
(e.g. representing $pi$ as a sequence of committed bytes and as a sequence of extension field elements),

Comment thread spec/chapters/recursion.typ Outdated
A larger $[pi, r]$ comes at a cost --- whether a cost of soundness or a cost of deriving more independent random $alpha_i$ ---
and as such should be kept as short as possible.
Since values that only one $verify^*_(b)$ reads or writes cannot lead to a differing result, the checksummed data need only
be the subsequence of elements of $[pi, r]$ that is read or written by both $verify^*_0$ and $verify^*_1$.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
be the subsequence of elements of $[pi, r]$ that is read or written by both $verify^*_0$ and $verify^*_1$.
be the subsequence of elements of $[pi, r]$ that is accessed by both $verify^*_0$ and $verify^*_1$.

or "interacted"?
Reason I'm proposing this, is to avoid the ambiguous interpretation that one need only include values that are either read by both or written by both (where in practice we see values being "written" by one and read by the other)

Comment thread spec/chapters/recursion.typ Outdated
Comment on lines +242 to +243
To enable recursion from a split verifier, we start by considering that each part of the split may
be prove in a different proof system, and with a different commitment scheme.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To enable recursion from a split verifier, we start by considering that each part of the split may
be prove in a different proof system, and with a different commitment scheme.
To enable recursion from a split verifier, we start by considering that either part may
be proven in a different proof system, each using a different commitment scheme.

Comment thread spec/chapters/recursion.typ Outdated
Comment on lines +244 to +245
For a split verifier $(verify_0, verify_1, d_verify)$ to be recursively proven,
we will write $comm(x)$ and $comm2(x)$ as the (deterministic) commitments to $x$

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
For a split verifier $(verify_0, verify_1, d_verify)$ to be recursively proven,
we will write $comm(x)$ and $comm2(x)$ as the (deterministic) commitments to $x$
We write $comm(x)$ and $comm2(x)$ as the (deterministic) commitments to $x$

Comment thread spec/chapters/recursion.typ Outdated
Comment on lines +252 to +256
our goal then becomes to prove the following statements in parallel:

1. $verify'_0([comm(bb(x)), c_0]; [pi, r]) = 1$
2. $verify'_1([comm2(bb(x)), c_1]; [pi, r]) = 1$
3. $exists pi, r: comm([pi, r]) = c_0 and comm2([pi, r]) = c_1$

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't flow right for me just yet. At this point we have just introduced $v'_i$ as taking one more argument than $v_i$ (but haven't bound it to anything). As a result, step 3 feels useless: we have to ensure the commitments given to both $v'_i$ match the same thing. But both $v'_i$ don't actually do anything with that parameter at this point?

Perhaps we should start with

  1. $v_0(x, [\pi, r]) = 1$
  2. $v_1(x, [\pi', r']) = 1$
  3. show that $(\pi, r) = (\pi', r')$

then introduce $v'_b([x, s], [\pi, r]) = v_b(x, [\pi, r]) = 1 \wedge comm_b(x, \pi, r) = s$

and then transition to

  1. $v' _0([x, s0], [\pi, r]) = 1$
  2. $v'_1([x, s1], [\pi', r']) = 1$
  3. $\exists \pi, r: comm_0(x, pi, r) = s0 \wedge comm_1(x, pi, r) = s1$

wdyt?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but haven't bound it to anything

I felt like that was implied by the (informal) definition of the v'_b, and that elaborating that more formally would needlessly take up extra space.

Comment thread spec/chapters/recursion.typ Outdated
#aside[Minimizing the length of $z$][
A larger $[pi, r]$ comes at a cost --- whether a cost of soundness or a cost of deriving more independent random $alpha_i$ ---
and as such should be kept as short as possible.
Since values that only one $verify^*_(b)$ reads or writes cannot lead to a differing result, the checksummed data need only

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarify what you mean by "differing result". What result?

Comment thread spec/chapters/recursion.typ Resolved
Co-authored-by: Erik <159244975+erik-3milabs@users.noreply.github.com>
@erik-3milabs
erik-3milabs self-requested a review October 19, 2026 12:47

@erik-3milabs erik-3milabs left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the core comment of this review.

we will write $comm(x)$ and $comm2(x)$ for a (deterministic) commitment to $x$
in the $prove_0$ and $prove_1$ scheme respectively.

To then coherently prove the original verifier $verify$, our goal becomes:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To then coherently prove the original verifier $verify$, our goal becomes:
To then coherently prove the original verifier $verify$, our goal becomes to prove that:

- $serif("cksum")(x) = serif("Hash")(x)$: compute a hash in both halves, at the cost of needing to evaluate a hash in a proof system that is likely not a good fit for that hash.
- $serif("cksum")(x) = comm2(x)$: recompute the commitment $comm2(x)$ as part of $verify^*_0$, and let $verify^*_1$ simply check that the checksum equals the public commitment.

Finally, we consider the instantiation $serif("chsum")(x) = chevron.l x, z chevron.r$ for a random zero-evader $z$.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Finally, we consider the instantiation $serif("chsum")(x) = chevron.l x, z chevron.r$ for a random zero-evader $z$.
Finally, we consider the instantiation $serif("cksum")(x) = chevron.l x, z chevron.r$ for a random zero-evader $z$.

The former has a soundness loss linear in the size of $x$, while the latter will require more computational
work to derive independent challenges inside of the verifier.
As a tradeoff, one could consider the mixture of both, through
$z = (alpha_1, alpha_1^2, ..., alpha_1^ell, alpha_2, alpha_2^2, ..., alpha_(lr(|x|)/ell)^ell)$, with a soundness loss $ell$ but only

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re:

... with a soundness loss $ell$ ...

is this $ell$ bits? or bits linear in $ell$? Or something else? The absence of a unit is a touch confusing to me.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe "soundness error $\frac\ell{|\mathbf{F}|}$ is more clear

As such, it is possible to construct a split verifier for this combined proof system, and enable full split recursion.

= Split recursion
With proof recursion and split verification formalized, we now combine both concepts into a unified system.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
With proof recursion and split verification formalized, we now combine both concepts into a unified system.
With proof recursion, split proving, and split verification formalized, we now combine the three concepts into a unified system.

We consider the case for a valid split verifier $(verify_0, verify_1, d_verify)$
with proof functions $prove_0$ and $prove_1$.
Since these proof systems can potentially use different commitments,
we will write $comm(x)$ and $comm2(x)$ for a (deterministic) commitment to $x$

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This overloads $\stackrel{-}{x}$.

I think this is a problem. Later on, you write

With the right choice of proof system and commitment scheme $comm(x)$, ...

I think you want this to convey that $\stackrel{-}{x} := (\stackrel{-}{x}, \hat{x})$. The recursive definition might stump the reader, right at a crucial step that already requires some mental gymnastics to understand.


= Split proving
#et("todo")
To enable recursion with a split verifier, we start by considering that each part of the split may

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need split proving to achieve recursion w/ a split verifier.

Suggested change
To enable recursion with a split verifier, we start by considering that each part of the split may
To accelerate recursion with a split verifier, we now discuss how each part of the split may

We briefly present a few trivial instantiations, before bringing the cost down further.

- $serif("cksum")(x) = serif("Hash")(x)$: compute a hash in both halves, at the cost of needing to evaluate a hash in a proof system that is likely not a good fit for that hash.
- $serif("cksum")(x) = comm2(x)$: recompute the commitment $comm2(x)$ as part of $verify^*_0$, and let $verify^*_1$ simply check that the checksum equals the public commitment.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$v^*_b$ is not defined.

Comment on lines +257 to +258
To integrate the last statement, we introduce a "checksum" of the witness, which will be checked by both halves of the split:
$ verify'_(b)([x, s], w) = verify_(b)(x, w) dot (serif("cksum")(w) =^? s). $

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we suddenly talking about witness and using $w$, rather than proof and $\pi$?

Comment on lines +285 to +287
In settings where both $verify'_(b)$ are in the same proof system, with the same commitment scheme, but different representations of the committed data
(e.g. representing $proof$ as a sequence of committed bytes and as a sequence of extension field elements),
one can even use a permutation argument such as in @logup to check equality of the data.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This subsection starts as

To enable recursion with a split verifier, we start by considering that each part of the split may be proven in a different proof system.

These sentences here related to a different situation, namely that of a single proof system. Yet, below, (after the aside) we continue with the split proof system discussion.

So, either:

  • we don't start by considering [...], but we just consider [...] (and these sentences are superfluous), or
  • we do in fact start with a split proof system, and this is a return to the joint proof system (which would be a weird order. Why not start with this?), but then the next paragraph should be moved up above here.
  • It is even different, and I don't get it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe s/considering/realizing at the start?
The start is justifying why we're introducing two potentially distinct proof systems into the discussion, whereas this sentence is clarifying what can we can do if they are not distinct.

Comment on lines -251 to +315
We can now use this selector to define $verify^*$ --- a variation to $verify'$ --- as follows:
We can now use this selector to define $verify^*$ as a variation on $verify'$.
With the right choice of proof system and commitment scheme $comm(x)$, $verify'$ and by extension
$verify^*$ can be applied directly to a proof string $pi$ that is either the output of a base proof,
or a recursive proof that is potentially split as in the previous section.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have given it some thought, and think I know why this doesn't work as we would like it to: the split-proving section is missing some stuff.

The story up to this point has been:

  • we start this chapter with introducing recursion,
  • we bypass a growing instance, by introducing $v'$,
  • split verification: we show how to convert a verifier into a split verifier.
  • split proving: we show how to accelerate a split verifier by means of proving each split in different VMs

I would now expect this section to combine $v'$ and split-verification+split-proving. But that doesn't happen.

In fact, we don't yet have the tools to do this: the $v'$-transformation shows how to morph the verifier of a proof system $(p,v)$ into one that can prove that one of two instances is satisfied. In the split proving section, we just pull two proof system provers p0 and p1 out of thin air and don't introduce the accompanying verifiers $v0$ and $v1$ (note: I'm overloading notation here). Neither do we show how one can merge $v0$ and $v1$ into the single verifier $V$ (that can verify proofs that consist of two halves from different proof systems).

Only once we have established those things, can we

  1. apply the $v'$ transformation to $V$ (allowing it to verify two instances), creating $V'$, and
  2. then split $V'$ into $(V_0', V_1', d_{V'})$

before we arrive at a split verifier that can verify proofs for two instances using two verifiers proven by two distinct provers.

Right now, we're essentially asking the reader to take all those mental steps in these two sentences. That is too much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

spec Updates and improvements to the spec document

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants