refactor(lifted-stark): replace bus-identity reduction with general eval_external + flat external_public_inputs#992
Draft
refactor(lifted-stark): replace bus-identity reduction with general eval_external + flat external_public_inputs#992
Conversation
… flat external_public_inputs
Generalize the bus-identity check into per-AIR external assertions and
simplify the public-input plumbing.
API changes on `LiftedAir`:
- `reduced_aux_values()` -> `eval_external()`, returning `Vec<EF>` of
scalar assertions that must each equal zero (in place of the bus-shaped
`(prod, sum)` reduction).
- `num_var_len_public_inputs()` is gone; external inputs are now a flat
`&[F]` slice with no framework-imposed shape. The AIR owns the schema
and reports decode errors via `ReductionError`.
Type changes:
- `VarLenPublicInputs<'a, F> = &'a [&'a [F]]` -> `ExternalPublicInputs<'a, F> = &'a [F]`.
- `AirInstance` / `AirWitness` now carry `external_public_inputs: &[F]`.
- `auxiliary/values.rs` (the `ReducedAuxValues` type) is deleted.
Verifier:
- Each entry of every AIR's assertion list is checked individually against
zero (no Horner / alpha fold). A non-zero entry returns
`ExternalAssertionFailed { caller_instance, assertion }`, naming the
caller's original instance index and the assertion's position in the
AIR's returned vector.
Validation:
- The framework no longer pre-checks shape on external inputs; the AIR's
decoder is responsible. `InstanceValidationError::VarLen*` variants are
removed; the `validate_inputs` and `check_constraints_multi` blocks for
matrix-shape validation are dropped.
Fiat-Shamir:
- Caller absorption simplifies to a single `observe_slice(external_public_inputs)`.
7 tasks
adr1anh
commented
May 9, 2026
| /// Default: returns identity (correct for AIRs without buses). | ||
| fn reduced_aux_values( | ||
| /// Default: no external assertions (correct for AIRs that do not need them). | ||
| fn eval_external( |
Contributor
Author
There was a problem hiding this comment.
We should relax the bounds to allow symbolic representation of these constraints.
| /// Implementors of [`reduced_aux_values`](Self::reduced_aux_values) should verify | ||
| /// that `var_len_public_inputs` contains exactly this many slices, returning | ||
| /// [`ReductionError`] otherwise. | ||
| fn num_var_len_public_inputs(&self) -> usize; |
Contributor
Author
There was a problem hiding this comment.
This could be replaced by has_external_inputs, in which case the eval_external function is a constant circuit.
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
Generalizes the cross-AIR bus-identity check (
ReducedAuxValues { prod, sum }) into per-AIR external assertions, and simplifies the variable-length public-input plumbing into a flat&[F]slice that the AIR decodes itself.Motivation
The previous design baked two assumptions into the trait surface:
(product, sum)pair representing a multiset/logup bus identity. This is fine for those bus shapes but doesn't generalize to other assertions over aux values + challenges + public inputs.num_var_len_public_inputs()and validated them on every instance. This was extra plumbing for callers without buying flexibility: AIRs that wanted heterogeneous inputs (length-prefixed sublists, scalar headers, etc.) couldn't express them.Both pieces are folded into a single, narrower contract: the AIR returns a vector of scalar assertions and decodes its inputs from a flat slice.
API changes
LiftedAirfn reduced_aux_values(...) -> Result<ReducedAuxValues<EF>, ReductionError>fn eval_external(...) -> Result<Vec<EF>, ReductionError>fn num_var_len_public_inputs() -> usizeeval_externalreturns a list of extension-field values that must each equal zero. The verifier checks them individually (no Horner/alphafold) so a non-zero entry is reported with its caller-original instance index and assertion position:Instance / witness types
var_len_public_inputs: &[&[F]]external_public_inputs: &[F]AirInstance,AirWitness,prove_single, andverify_singlenow take a flat slice. The AIR is responsible for any decode/length checks and reports failures viaReductionError.Removed
ReducedAuxValues<EF>type and theauxiliary/values.rsmoduleInstanceValidationError::VarLenPublicInputsMismatchInstanceValidationError::VarLenPublicInputWidthMismatchinstance::validate_inputsanddebug::check_constraints_multiVerifierError::InvalidReducedAuxFiat-Shamir
Caller absorption simplifies to a single line:
Both prover and verifier MUST absorb the same slice.
AIR migration
For an AIR that previously did:
The equivalent now is:
Note the multiset assertion is rewritten to
prod - 1 == 0(each entry is its own zero-equation; there's no separate "identity" form anymore).Test plan
cargo test -p miden-lifted-stark --lib— 73/73 pass, including:bus_identity_check(positive case)bus_wrong_external_pi_fails(mismatched value →ExternalAssertionFailed)bus_short_external_inputs_fails(truncated input →Reduction(_)from the AIR's decoder)cargo clippy -p miden-lifted-air -p miden-lifted-stark -p miden-bench --all-targetscleancargo checkclean across all three affected cratesNotes for reviewers
EFvalues. The fold was bookkeeping, not adding any cryptographic guarantee.external_public_inputs. If the caller and AIR disagree on encoding, the AIR's decoder fails (returningReductionError), which yieldsVerifierError::Reduction(_)rather than a panic.