Skip to content

BINIUS-255: compose the AND-check and shift reduction into the M4 protocol#1771

Merged
jimpo merged 5 commits into
binius-zk:mainfrom
tcoratger:thomascoratger/m4-andcheck-shift-reduction
Jul 11, 2026
Merged

BINIUS-255: compose the AND-check and shift reduction into the M4 protocol#1771
jimpo merged 5 commits into
binius-zk:mainfrom
tcoratger:thomascoratger/m4-andcheck-shift-reduction

Conversation

@tcoratger

Copy link
Copy Markdown
Contributor

Part of BINIUS-255. One step toward the M4 protocol; does not close the issue (the trace-oracle tie remains).

Chains the two batched reductions into one reduction on a shared transcript, for prover and verifier. No new cryptography — just the glue.

The problem

The batched AND-check (BatchAndCheckWitness::prove / verify_bitand_reduction) and the shift reduction (shift::prove feeding the single-instance shift::{verify, check_eval}) existed as standalone building blocks, each exercised only by its own test with hand-built inputs. Nothing composed them on one Fiat-Shamir transcript.

The idea

Run them back to back, the AND-check's output feeding the shift reduction:

   all AND rows  (A & B == C over K * n_and rows)
        │  AND-check
        ▼
   claimed A, B, C at a random row point  +  bit challenge r_z
        │  split the row point, fold the witness over instances
        ▼
   shift reduction
        ▼
   one evaluation claim about the instance-folded witness

The batch-specific step: the AND-check's row point is (constraint, instance). Split it — the constraint part r_x (low) feeds the shift reduction; the instance part r_rho (high) says how to fold the K instances into one before the shift runs.

Why this is correct given the codebase

  • It is the batched shape of the single-instance protocol (crates/verifier/src/verify.rs), which already threads bitand → shift in this order — so the Fiat-Shamir ordering is unchanged.
  • The exact threading (split r_x/r_rho, fold at r_rho, feed r_x to the shift) is precisely the wiring the existing shift.rs round-trip test already validated; the only change is that r_x, r_rho, and the operand claims now come from the shared transcript rather than being sampled by the test.
  • The existing reductions are reused unchanged; this PR only adds the glue.

Scope

  • new: m4-prover::prove_reduction, m4-verifier::verify_reduction, and their output structs.
  • only AND constraints: MUL is rejected up front (there is no batched intmul check yet), rather than silently passing a zero claim that would skip the MUL checks.
  • stops at the witness claim: binding it to the committed trace oracle — which binds r_rho and bridges the bit witness to the packed commitment via a batched ring-switch that does not exist yet — is a later step, flagged in both module docs.
  • the CRC-64 test fixture moves from shift.rs to a crate-level #[cfg(test)] mod crc64, so the shift and reduction tests share it without one test module reaching into another's.

Verification

  • cargo test -p binius-m4-prover (28) and -p binius-m4-verifier (3) — pass
  • clippy --all-targets, +nightly fmt -- --check — clean
  • reduction_round_trips: prover and verifier agree on r_rho, the challenge point, and the eval; and the reduced claim equals the true instance-folded witness evaluated at the shift point.
  • tampered_transcript_is_rejected.

Note

This branch is cut from main, which still has ValueTable2 (the rename in #1770 is open). When #1770 lands, this is a trivial ValueTable2ValueTable rename here.

🤖 Generated with Claude Code

…tocol

The batched AND-check and shift reduction existed as standalone building
blocks, each driven only by its own test with hand-built inputs. Nothing ran
them together on one transcript.

Add the composition, for both sides. The prover runs the AND-check over all
K * n_and rows, splits the resulting row point into a constraint part r_x (low)
and an instance part r_rho (high), folds the witness over the instance axis at
r_rho, and feeds the operand claims into the shift reduction at r_x. The
verifier mirrors it: AND-check, split, shift verify, public-input check. The
output is a single evaluation claim about the instance-folded witness.

This is the batched shape of the single-instance protocol's bitand-then-shift
threading, and it matches the wiring the shift round-trip test already
validated; only the challenges now come from the shared transcript rather than
being sampled by the test. The existing reductions are reused unchanged.

Only AND constraints are handled; MUL is rejected. Binding the claim to the
committed trace oracle (which binds r_rho and bridges the bit witness to the
packed commitment via a batched ring-switch) is a later step, not done here.

The CRC-64 test fixture moves from shift.rs to a crate-level test module so both
the shift and reduction tests can share it without a cross-module reach.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tcoratger tcoratger requested a review from jimpo as a code owner July 10, 2026 20:45
tcoratger and others added 2 commits July 10, 2026 22:50
The shared CRC fixture lived in a src file named `crc64.rs`, which reads like
production source. CONTRIBUTING points shared test setup at a `test_utils`
module, and the repo's convention (binius_math, arith-bench) is exactly a
dedicated test-utility file under that name. Rename the module to `test_utils`
so a reader sees at once that it is test-only support, matching that convention.

No code change; the CRC helpers and their names are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The relocated fixture carried its original prose-style docs: sentences that ran
across `///` lines and stacked several to a line. Split them one sentence per
line, and turn the per-bit CRC step description into a bullet list.

Documentation only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

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

Hell yeah! This looks super clean. A couple comments, and this'll need a rebase because of the ValueTable rename.

Comment thread crates/m4-verifier/src/reduction.rs Outdated
Comment thread crates/m4-verifier/src/reduction.rs
Comment thread crates/m4-prover/src/reduction.rs Outdated
tcoratger and others added 2 commits July 11, 2026 10:08
…lic arg

Two review follow-ups on the reduction:

- Build the shift key collection once in a setup phase rather than on every
  prove call. `prove_reduction` now takes a `&KeyCollection`, and the caller
  builds it after preparing the constraint system. The build is expensive, so
  it should be amortized across proofs of the same circuit.

- Drop the `public_words` argument from `verify_reduction`. The shared constant
  words are already on the constraint system, so the public-input check reads
  `cs.constants` directly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ndcheck-shift-reduction

# Conflicts:
#	crates/m4-prover/src/lib.rs
#	crates/m4-prover/src/shift.rs
@tcoratger

Copy link
Copy Markdown
Contributor Author

Hell yeah! This looks super clean. A couple comments, and this'll need a rebase because of the ValueTable rename.

Just fixed the comments and the conflicts with main :)

let shift = shift::verify::<B128, _>(cs, &bitand, &intmul, channel)?;

// Tie in the shared constants through the public-input consistency check.
let domain = BinarySubspace::<B8>::with_dim(Word::LOG_BITS).isomorphic::<B128>();

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.

follow-up: It would be best to pass this domain into verify_bitand_reduction too (but the pre-isomorphism version). That would ensure it's consistent between andcheck and shift, by construction. On the prover side too.

@jimpo jimpo added this pull request to the merge queue Jul 11, 2026
Merged via the queue into binius-zk:main with commit fe9457a Jul 11, 2026
8 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.

2 participants