Skip to content

spike(stark): builder-rewrite (Plan B) constraint capture → IR [compare vs #737]#739

Draft
MauroToscano wants to merge 2 commits into
mainfrom
spike/constraint-ir-builder
Draft

spike(stark): builder-rewrite (Plan B) constraint capture → IR [compare vs #737]#739
MauroToscano wants to merge 2 commits into
mainfrom
spike/constraint-ir-builder

Conversation

@MauroToscano

Copy link
Copy Markdown
Contributor

What

Plan B (explicit builder rewrite) for capturing transition constraints into a flat IR —
the counterpart to #737 (Plan A, symbolic field), so the two capture approaches can be
compared side by side. Same motivation: get constraint eval onto the GPU to keep the prove
pipeline data-resident (avoid round-tripping the LDE trace off-device).

Both PRs produce the same IR and use the same interpreter — they differ only in the
capture front-end:

  • spike(stark): symbolic-field capture of transition constraints → flat IR (CPU) #737 (A): a recording "symbolic field" — running a constraint's existing evaluate
    over SymField records the IR. Zero constraint-body edits, but leaves a fake IsField
    (unimplemented!() stubs, eq → false) + a thread-local arena in the codebase.
  • This PR (B): an explicit IrBuilder + per-constraint capture(&mut IrBuilder). No
    fake field, no arena; each constraint spells out its IR. Cost: rewriting constraint bodies.

What's in it

New module crypto/stark/src/constraint_ir/:

  • ir.rs, interp.rsreused verbatim from the Plan A spike (the IR types + CPU
    interpreter are identical across approaches).
  • builder.rsIrBuilder (hash-conses nodes on (Op, Dim), dedups base constants by
    value, dim-join (D1,D1)->D1 else D3) + Expr { id, dim }.
  • mod.rs — object-safe Capture { fn capture(&self, &mut IrBuilder); } trait.

Constraint capture impls (added alongside the existing evaluate, which is untouched —
non-destructive, so the old path stays as the diff oracle): IsBitConstraint,
AddConstraint (incl. AddOperand/AddLinearTerm lo/hi-limb mapping with i64 coeffs and
the inv_2_32 constant), ProductZeroConstraint.

Test (prover/src/tests/constraint_ir_tests.rs): same scope and structure as #737 — captures
each constraint via the builder and asserts the IR interpreter matches the real evaluate
bit-for-bit over 1000 random rows.

Results

  • stark + lambda-vm-prover build; cargo fmt/clippy clean (no new warnings).
  • ✅ Diff test 4/4 — cargo test -p lambda-vm-prover constraint_ir_tests.
  • Node counts (vs spike(stark): symbolic-field capture of transition constraints → flat IR (CPU) #737): product_zero 4, is_bit_uncond 5, is_bit_cond 7,
    add_carry_0 14, add_carry_1 21 — much smaller than A's 66–78, because the builder
    only emits leaves for columns actually read (A padded 64 unused column leaves). add_carry_1
    reuses the whole carry_0 subtree via CSE.

A vs B — what to compare

#737 (A, symbolic field) this PR (B, builder)
Constraint bodies unchanged rewritten to capture() (here: 3 structs; full set = ~33)
Permanent scaffolding fake IsField + thread-local arena none
Capture style implicit (record evaluate) explicit (spell out the IR)
Captured IR size padded (66–78) minimal (4–21)
IR + interpreter + GPU work identical identical

Scope / follow-ons (same as #737)

Minimal CPU-only spike: base-field algebraic constraints, main columns, single step. Out of
scope: LogUp constraints, aux/next-row, wiring into evaluate_transitions, and the GPU kernel.
Design docs + the full phased plan live in #737 (thoughts/gpu-constraint-eval/).

Draft / spike — not for merge as-is; this exists so we can pick A vs B before scaling to the
full constraint set.

…nts into the IR

Counterpart to PR #737 (symbolic field) for comparing the two capture front-ends. Reuses the same IR + CPU interpreter; adds an explicit IrBuilder + object-safe Capture trait, with capture() implemented on IsBit/Add/ProductZero ALONGSIDE their unchanged evaluate (non-destructive). Diff test matches real evaluate bit-for-bit over 1000 random rows; captured node counts 4-21 (vs A's 66-78, since the builder only emits leaves for columns actually read). CPU-only minimal spike, same scope as #737.
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