Skip to content

spec: Recursion - #943

Draft
erik-3milabs wants to merge 16 commits into
spec/mainfrom
spec/recursion
Draft

erik-3milabs wants to merge 16 commits into
spec/mainfrom
spec/recursion

Conversation

@erik-3milabs

Copy link
Copy Markdown
Collaborator

No description provided.

@erik-3milabs erik-3milabs self-assigned this Aug 21, 2026
@erik-3milabs erik-3milabs added the spec Updates and improvements to the spec document label Aug 21, 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 — Recursive verification omits the required commitment (spec/recursion.typ:105). verify accepts a commitmentSpace, but the recursive branch treats commitment_1 as a function; lines 116–118 similarly pass verifier functions directly. Use an explicitly defined specialization operation producing comm(verify'(commitment_0, commitment_1, ·)). As written, the equations are ill-typed and do not establish the claimed recursive chain.

Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated
Comment thread spec/chapters/recursion.typ Outdated
Comment on lines +215 to +225
When recursing on this process, the prover provides the verifier with this commitment.
We thus have to demonstrate the commitments the prover provides are as expected.
This is achieved by having the verification algorithm `COMMIT` (see @commit)
to the public input it is provided.
This act produces an imbalance in the LogUp-component of the proof-of-verification,
which must be balanced during verification in the _next_ recursion layer.
In later recursions, the verifier must consistently `COMMIT` to its public input
and use the _same_ public input to balance out the LogUp-component of the proof
it is provided.
This solution effectively kicks the can down the road; the final verifier has to
provide the initial input to the program as input to verify the recursive proof.

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.

  1. We may not have access to COMMIT in a future flock-fieldvm hybrid
  2. Isn't this handled by $\mathbb{c}_1 = \bar{\mathbb{x}}$ already? Since the instance $\mathbb{x}$ includes the public input?

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.

Re 2.

Do you mean that having the guest COMMIT to $\mathbb{c}_1$ is excessive, since there must be a PAGE storing it, and all PAGEs are committed to by the VM?

In that case the verifier will have to add a constraint to that specific PAGE table, constraining that it contains the commitment on the required address 🤔 or were you thinking of a different solution?

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.

There are multiple PAGEs that need to be present to correctly represent the ELF being loaded into memory, so those would be part of $\bar{\mathbb{x}}$ already. And the ELF is the public input part, potentially with the PAGEs for the commitments made by the guest program.
So in the end, we'd need these specific tables to be used already as precomputed tables (which could/would be part of a verification key that can be derived from the ELF once and not computed on every verification).

Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated

@cdesaintguilhem cdesaintguilhem 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.

Mostly minor comments!

Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated
verify': commitmentSpace^2 times {0, 1} times proofSpace: (commitment_0, commitment_1, b, proof) mapsto
cases(
verify(commitment_0, proof) &text("if") b=0,
verify(commitment_1((commitment_0, commitment_1); dot), proof) &text("if") b=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.

I can't parse what commitment_1((commitment_0, commitment_1); dot) is meant to be here.

Comment thread spec/recursion.typ Outdated
Comment thread spec/recursion.typ Outdated
are henceforth referred to as _function instances_, or simply _instances_.
Where convenient, we may also denote this as $function(input; dot) in instanceSpace$
with instance space $instanceSpace$.
We then define $relation subset.eq instanceSpace$

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 relation is actually a language.

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.

I rewrote the paragraph, as discussed. Is it correct now?

Comment thread spec/recursion.typ Outdated
Comment thread spec/chapters/recursion.typ Outdated
Comment on lines +212 to +213
Since these commitments are deterministic, the verifier can locally reconstruct
the commitments and verify any opening proofs against its own version of the 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.

As an optimisation: if the verifier has the DECODE and relevant PAGE tables in the clear, the prover does not even need to provide the corresponding openings as part of the proof string.

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.

The downside would be that you get an increased storage cost in the verifying key, where storing those tables on-chain would be very costly, compared to just merkle roots.

@RobinJadoul RobinJadoul 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.

I'm wondering whether we should choose for the $f$ function in the proof system to be the ELF proof, or if it should purely be the VM itself, and moving the ELF into public inputs.

Comment thread spec/chapters/recursion.typ Outdated
Comment thread spec/chapters/recursion.typ Outdated
@RobinJadoul
RobinJadoul force-pushed the spec/recursion branch 3 times, most recently from 8e0d8f7 to 82dcc54 Compare September 8, 2026 09:38

@RobinJadoul RobinJadoul 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.

Not paying attention to all possible typography yet, trying to get the last high-level stuff out of the way
I'll try to do another pass later this week, but this is a first go at it

Comment thread spec/chapters/recursion.typ Outdated
Comment thread spec/chapters/recursion.typ Outdated
#let (proofSpace, proof) = ($bb(Pi)$, $pi$)

#let (commitmentSpace, commitment) = ($cal(C)$, $bb(c)$)
#let commit(x) = $overline(#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
#let commit(x) = $overline(#x)$
#let commit(x) = $dash(#x)$

should work better for html export
(except there's some weird rendering issues where at least FF, and seemingly other browsers too, so maybe this should be a later effort to clean up browser rendering a bit, as chromium also seems generally quite bad atm)

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.

I'm leaving it out of the commitment-batch for now, but would be happy to switch once we've established how to fix the html support issue.


== Recursively proving proof verification
Now observe that the verifier $verify$ is itself a function in
$verifierSpace := {hat(f): commitmentSpace times proofSpace to BB} subset.eq programSpace$.

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 think that to use the proof as private input, we need to have $\hat{f}$ map from only $\mathcal{C}$, or let $\mathcal{V} \subseteq \mathbb{X}$
The former is probably the more interesting, though that kinda moves the meaning of $\hat{f}$ to "c commits to a satisfiable (/solvable?) instance"

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.

Let's discuss this in person

For example, there may exist proofs that _attest to the existence of itself_ in a finite number of recursion steps.
Such a proof would be accepted by $verify'$ even if $instance in.not language$.
In practice, one might be able to prevent this problem by including a recursion-level counter in the proof.
The existence of other soundness gaps are not ruled out by the authors.

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.

Feels a bit weird to phrase it like this, maybe something about not providing a full proof of soundness (yet)?

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.

sure. wdyt of

Suggested change
The existence of other soundness gaps are not ruled out by the authors.
The provision of a full soundness proof is deferred.

?

$program$ and input $input$ are committed to separately.
Recall that a (split) program is encoded as one or more
`DECODE` (@decode) and/or `FIELD-DECODE` (@field-decode) tables, while the
input $input$ --- and private input $witness$ and record $record$ for that matter

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.

Technically, public input is committed private input, but committed values are now available through COMMIT's PAGEs

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.

A) some committed values (namely those COMMITted by the guest program) are available through the COMMIT's PAGEs, right?

B) how would you propose the text be modified? I'm confused by the remark.

Comment thread spec/chapters/recursion.typ Outdated
Comment on lines +367 to +371
Leveraging the `COMMIT` chip is mostly useful in situations where revealing full `PAGE`
tables is unnecessarily expensive or cumbersome, e.g., when committing to small
amounts of data or to data scattered across several `PAGE` tables.
One potential limitation is that `COMMIT`ting in this way is at the discretion of the VM's
guest program.

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 think this model of COMMIT is outdated since epoch/L2G system for committing? Though I suppose a COMMIT-domain PAGE table is not strictly different from just providing the same interactions from the verifier.

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.

why would this model be outdated? I don't see how the epoch/L2G system changed this.

Comment thread spec/chapters/recursion.typ Outdated
- derives challenges from $proof$ by means of Fiat-Shamir, and assert that they
match those located in $record$ at the expected location.
- Performs the binary arithmetic steps required to verify that $proof$ attests
to $instance$ (when $b=0$) or $instance2$ (when $b != 0$#footnote[The RiscV-VM's `PAGE` tables only supports byte data. All non-zero data is treated as $b=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.

We can assert the bit-ness of b as well, alternatively

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.

You mean by including

x = EQ[b, 0];
y = EQ[b, 1];
z = x + y;
z = EQ[z; 1];

in the guest program?

Co-authored-by: Robin Jadoul <robin.jadoul@gmail.com>

== Recursively proving proof verification
Now observe that the verifier $verify$ is itself a function in
$verifierSpace := {hat(f): commitmentSpace times proofSpace to BB} subset.eq programSpace$.

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.

Let's discuss this in person

For example, there may exist proofs that _attest to the existence of itself_ in a finite number of recursion steps.
Such a proof would be accepted by $verify'$ even if $instance in.not language$.
In practice, one might be able to prevent this problem by including a recursion-level counter in the proof.
The existence of other soundness gaps are not ruled out by the authors.

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.

sure. wdyt of

Suggested change
The existence of other soundness gaps are not ruled out by the authors.
The provision of a full soundness proof is deferred.

?

For each value on the record, the "sending" half _verifies_ that it is as expected,
whilst the "receiving" half _assumes_ its correctness and resumes verification under this assumption.
One can now conclude that the proof satisfies the instance
when both algorithm-halves produce the same record for this input.

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.

A)

Suggested change
when both algorithm-halves produce the same record for this input.
when both algorithm-halves accept the same record for this input.

B) let's discuss this in person.

]

More formally, we define
$v_0, v_1: instanceSpace times proofSpace to recordSpace$ as a valid _split_ of

@erik-3milabs erik-3milabs Sep 22, 2026

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.

like this, you mean, right?

Suggested change
$v_0, v_1: instanceSpace times proofSpace to recordSpace$ as a valid _split_ of
$v_0, v_1: commitmentSpace times proofSpace to recordSpace$ as a valid _split_ of

$
where $recordSpace$ denotes the communication record space.
That is, the two halves agree if and only if the instance-proof verifies succesfully.
By applying the Kronecker delta function $delta$ #footnote("https://en.wikipedia.org/wiki/Kronecker_delta"),

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.

I included it, as I've encountered a wild variety of notation for the delta function and wanted to point the reader to the exact definition I'm using here. We could alternatively derive it in the document and keep it self-contained. wdyt?

Comment on lines +367 to +371
Leveraging the `COMMIT` chip is mostly useful in situations where revealing full `PAGE`
tables is unnecessarily expensive or cumbersome, e.g., when committing to small
amounts of data or to data scattered across several `PAGE` tables.
One potential limitation is that `COMMIT`ting in this way is at the discretion of the VM's
guest program.

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.

why would this model be outdated? I don't see how the epoch/L2G system changed this.

- derives challenges from $proof$ by means of Fiat-Shamir, and assert that they
match those located in $record$ at the expected location.
- Performs the binary arithmetic steps required to verify that $proof$ attests
to $instance$ (when $b=0$) or $instance2$ (when $b != 0$#footnote[The RiscV-VM's `PAGE` tables only supports byte data. All non-zero data is treated as $b=1$.]),

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.

You mean by including

x = EQ[b, 0];
y = EQ[b, 1];
z = x + y;
z = EQ[z; 1];

in the guest program?

Comment thread spec/book.typ Outdated

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.

hmmm, this should be removed, no?

#let (proofSpace, proof) = ($bb(Pi)$, $pi$)

#let (commitmentSpace, commitment) = ($cal(C)$, $bb(c)$)
#let commit(x) = $overline(#x)$

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.

I'm leaving it out of the commitment-batch for now, but would be happy to switch once we've established how to fix the html support issue.

$program$ and input $input$ are committed to separately.
Recall that a (split) program is encoded as one or more
`DECODE` (@decode) and/or `FIELD-DECODE` (@field-decode) tables, while the
input $input$ --- and private input $witness$ and record $record$ for that matter

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.

A) some committed values (namely those COMMITted by the guest program) are available through the COMMIT's PAGEs, right?

B) how would you propose the text be modified? I'm confused by the remark.

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.

3 participants