Conversation
Raphsolt
force-pushed
the
feat/reconstruct-batch-lookups
branch
from
September 15, 2026 23:31
51831a3 to
49f744a
Compare
…where replay_batch_layer_transcript and the FRI and WHIR backends each derived every table's lookups again straight after reconstructing or trusting its tables. They now read the lookups the reconstruction returns, so the derivation lives only in reconstruct_batch_tables and trusted_batch_tables. No behaviour change: each removed derivation called the same function with the same arguments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
Since opening this, (If CI's clippy job fails, it's Happy to close this if you'd rather keep the derivations where they are. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Exposes a
lookups: Vec<Lookups<Val<SC>>>field onReconstructedBatchTables, derived insidereconstruct_batch_tablesdirectly from the reconstructed AIRs, and consumed byverify_p3_batch_proof_circuitinstead of being derived a second time there.Why
BatchStarkProofintentionally omits lookup contexts from its serializedstark_common, because the verifier rebuilds them from the AIRs reconstructed from proof metadata.verify_p3_batch_proof_circuit's own comment gives the reason to prefer the rebuild: a malformed or malicious lookup set is ignored rather than believed.That rebuild was reachable only from inside the crate:
reconstruct_batch_tablesreturnedairs,trace_lensandpublic_values, but not the lookups.CircuitTablesAir::to_table_airis crate-private, so an external caller cannot pass those AIRs intolookups_for_circuit_table_air.So an external caller had no way to rebuild
CommonDatafor a proof deserialized from bytes, and every entry point that takes one was closed to them.replay_batch_stark_transcriptis the one that prompted this: it recovers the challenger state and the commitment/opening-point list a proof was produced under, which a recursive verifier needs before it can restore query paths.Returning
Lookups<Val<SC>>rather than a flattenedVec<Lookup<_>>preserves the newtypeCommonData::newaccepts.Lookupshas private fields and noFrom/FromIterator, so a flattened field could not be converted back and would be usable only by the one consumer whose target type happens to want that shape.Changes
pub lookups: Vec<Lookups<Val<SC>>>toReconstructedBatchTables, documented with rustdoc.reconstruct_batch_tablesvialookups_for_circuit_table_air, moving the existing comment about not trusting the proof-supplied set to where the decision is now made.verify_p3_batch_proof_circuitto consumetables.lookups, flattening withto_vec()only at that one target site.backend/transcript.rsfor the new field.SymbolicExpressionExtalgebra where-clause toreconstruct_batch_tablesand its callers inprepared/input.rs.Testing
cargo check -p p3-recursionpasses.cargo test -p p3-recursionpasses.Exercised downstream by a recursive verifier that rebuilds
CommonDatafor deserialised proofs, which is what surfaced the gap.Risk
Low, and additive. Verification behaviour is unchanged: the lookups the verifier uses are identical to the ones it derived before, computed once rather than twice.
The API additions are a public field on
ReconstructedBatchTables, so anyone constructing one literally needs the extra initialiser, and a where-clause onreconstruct_batch_tables—SymbolicExpressionExt<Val<SC>, SC::Challenge>: Algebra<SymbolicExpression<Val<SC>>> + Algebra<SC::Challenge>. That bound was always required by the derivation; moving the derivation moves it. Callers reaching this throughverify_p3_batch_proof_circuitalready satisfy it.No performance work. The change removes one duplicated derivation and is otherwise identical; nothing was measured because nothing was expected to move.
Review notes
Why native
Lookupsand notVec<Lookup<_>>: covered above — the flattened form is a one-way door, sinceLookups' only public constructor isfrom_air.Alternative considered: making
to_table_airpublic instead. Returning the lookups is preferred because the audited derivation then stays in one place rather than becoming something each external caller reimplements — and reimplementing it wrongly means trusting a lookup set the proof supplied.Sibling: same shape as Plonky3#2119 — a symbol needed by downstream consumers that was reachable only inside the crate.
Update:
replay_batch_layer_transcript(added to main after this was opened) and the FRI and WHIR backends now also readReconstructedBatchTables::lookupsrather than re-deriving it, so the derivation lives only inreconstruct_batch_tables/trusted_batch_tables.