Skip to content

formal: the statement records are the circuit inputs, projected off the proof - #379

Merged
martyall merged 3 commits into
mainfrom
pickles/records-as-values
Sep 19, 2026
Merged

martyall merged 3 commits into
mainfrom
pickles/records-as-values

Conversation

@martyall

Copy link
Copy Markdown
Member

Stacked on #378 (which is stacked on #377).

The fixture drivers fed the pickles gadgets through flat cell bundles (FopInput, GroupStepInput, …): every layout spelled twice, offset arithmetic in three places, and a proof reaching a gadget through a vector that was neither its wire form nor the gadget's record. The gadget records could not be the input type because their cell type was hard-wired to FVar F and their round-indexed fields were Lists.

The records

Three commits.

  1. The records are polymorphic in their cell type and indexed by their sizes. PlonkInCircuit f sf, DeferredValues k f sf, UnfinalizedProof k f bc sf, the wrap statement family, AllEvals f, PlonkClaims f, IvpInput k f bc sf, BulletproofOpening k f sf, CheckBulletproofInput k f sf: f is a field element in a value and FVar F in a circuit (PureScript's letter; F stays the field), bc the boolean cell, and the round challenges, (L, R) pairs and mask are Vectors at their static sizes — PureScript's shape. Use sites say (FVar F) (BoolVar F) where they said F; no gadget or proof changed beyond .toList where a list is consumed, and GroupHalf carries the round index its claims have. Pickles.Encoding derives every record's CircuitType from its product decomposition, with the reading lemmas the gate demands.
  2. The fop lanes run on StepFop k/WrapFop k, products of the gadgets' records; the driver projects them off the wrap statement and the checked proof. FopInput.lean is gone; the flat 151/148 harnesses stay for the dump comparison, which is byte-level against those layouts.
  3. The group halves likewise: the step statement packs too (StepStatement.packed, its x_hat walk, beside WrapStatement.packed, with a boolean packed kind and packLeavesOf shared), StepGroup/WrapGroup are products of the statements, the unfinalized proof, IvpProof (a proof's commitments and opening, sized) and the sg_old points; ivpInputOf lays them out as the gadget's input with the key as constants. The wrap side reads its keep bits off the branch data and its booleanity checks off the packing. Group.lean loses its two bundles and their projections; the driver unpacks each statement once (wrapStatementOf, stepStatementOf) and every lane projects off them.

Not done

IvpInput's commitment lists stay List (the batch-order proofs use them at ~330 sites), so the group half's proof part is the sized tuple IvpProof beside the record rather than the record itself. Layout.lean's offset readers and Fop.lean's flat harnesses stay for check_cs.

Verified

Full build, check-cs (54 circuits), check-halves 37/37 on the records, dead-code, readings, shake on the CI list, runLinter on Pickles and PicklesFixture, style (the three long carry-lane lines belong to #378).

🤖 Generated with Claude Code

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@martyall
martyall force-pushed the pickles/accumulator-carry branch from 594000a to bfa50b0 Compare September 18, 2026 07:26
martyall and others added 3 commits September 18, 2026 00:26
…indexed by their sizes

`PlonkInCircuit f sf`, `DeferredValues k f sf`, `UnfinalizedProof k f bc sf`, the wrap
statement family, `AllEvals f`, `PlonkClaims f`, `IvpInput k f bc sf`, `BulletproofOpening
k f sf`, `CheckBulletproofInput k f sf`: the cell type `f` (a field element in a value,
`FVar F` in a circuit) and the boolean cell `bc` are parameters instead of being derived
from the field, and the round challenges, the `(L, R)` pairs, the mask and the slots are
vectors at their static sizes (`k` rounds, `MaxProofsVerified`) instead of lists — the
shape PureScript's records have had all along. Every use site says `(FVar F) (BoolVar F)`
where it said `F`; no field, gadget or proof changes beyond `.toList` where a list is
consumed, and `GroupHalf` gains the round index its claims carry.

`Pickles.Encoding`: the `CircuitType` instance of every record, derived from its product
decomposition (`CircuitType.ofEquiv`), with the reading lemmas the readings gate demands —
a value record is seeded and a bundle allocated the way any input is, and the bundle IS the
gadget's record.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ojected off the proof

`StepFop k` and `WrapFop k` (PicklesFixture.Fop) are products of the gadgets' own records
— the unfinalized proof, the evaluations, the mask, the previous-challenge vectors, the
domain — and the harnesses hand the allocated bundle to `finalizeOtherProofStep`/`Wrap` as
it is. The driver projects them off the wrap statement's cells and the checked proof
(`stepFopInput`, `wrapFopInput`, `allEvalsOf`); the named flat bundles (`FopInput`,
`FopWrapInput`) and their layout arithmetic go. The flat 151/148-cell harnesses stay for
the dump comparison, which is byte-level against those layouts. `bench-fop` runs on the
records and imports `Snarky.Compile` itself.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… projected off the proof

The step statement packs too: `StepStatement.packed` is its `x_hat` walk (PS
`PackedStepPublicInput`) beside `WrapStatement.packed`, with a boolean packed kind for the
parity and `should_finalize` cells and `packLeavesOf` shared by both statements; the step
statement is indexed by its slot count, and `Pickles.Encoding` covers it.

`StepGroup` and `WrapGroup` (PicklesFixture.Group) are products of the gadgets' records — the
two statements, the unfinalized proof, the proof's commitments and opening (`IvpProof`),
the `sg_old` points — and `ivpInputOf` lays them out as the gadget's input with the key as
constants. The wrap side reads its keep bits off the wrap statement's branch data and its
booleanity checks off the step statement's packing. The named flat bundles, their instances
and their offset projections go; the dump comparison builds `IvpProof` from its offsets.

The driver unpacks the two statements once (`wrapStatementOf`, `stepStatementOf`) and every
lane projects off them and the checked proof (`ivpProofOf`, `sgOldOf`).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@martyall
martyall force-pushed the pickles/records-as-values branch from 9ca9707 to 34e1d8d Compare September 18, 2026 07:29
@martyall
martyall changed the base branch from pickles/accumulator-carry to main September 19, 2026 00:49
@martyall
martyall merged commit c00f640 into main Sep 19, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant