Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions crypto/stark/src/constraints/zerofier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,36 @@ pub fn zerofier_evaluations_on_extended_domain<F: IsFFTField>(
.collect()
}

/// `1/(z^N − 1)`, the half of the zerofier that does NOT depend on the
/// constraint.
///
/// Hoisted out of [`evaluate_zerofier`] because the caller evaluates every
/// constraint of an AIR at the SAME `z` and `trace_length`: computing it inside
/// meant one extension-field `pow` and one extension-field `inv` **per
/// constraint** instead of one per AIR. Measured in the recursion guest, where
/// that loop is hot: `evaluate_zerofier` was 15.8% of the guest's cycles and
/// 88% of that was exactly this `inv` + `pow`.
pub fn zerofier_base_inv<F, E>(z: &FieldElement<E>, trace_length: usize) -> FieldElement<E>
where
F: IsSubFieldOf<E>,
E: IsField,
{
(-FieldElement::<F>::one() + z.pow(trace_length))
.inv()
.unwrap()
}

/// Evaluation of the constraint's zerofier at some point `z`, which may be in
/// a field extension.
///
/// `base_inv` is [`zerofier_base_inv`] for this `z`/`trace_length` — the caller
/// computes it once and passes it for every constraint of the AIR.
pub fn evaluate_zerofier<F, E>(
meta: &ConstraintMeta,
z: &FieldElement<E>,
trace_primitive_root: &FieldElement<F>,
trace_length: usize,
base_inv: &FieldElement<E>,
) -> FieldElement<E>
where
F: IsSubFieldOf<E>,
Expand All @@ -134,9 +157,5 @@ where
acc * -(root.clone() - z.clone())
});

// 1/(z^N − 1), times the end-exemptions correction.
(-FieldElement::<F>::one() + z.pow(trace_length))
.inv()
.unwrap()
* &end_exemptions_eval
base_inv * &end_exemptions_eval
}
14 changes: 11 additions & 3 deletions crypto/stark/src/lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,12 @@ pub struct AirWithBuses<
constraint_set: CS,
/// The LogUp layout: the framework generates the LogUp (extension)
/// constraints from this and appends them after the `constraint_set` ones.
logup: LogUpLayout,
/// Behind `Arc` for the same reason as `constraint_program`: cloning an
/// `AirWithBuses` copied the interaction list TWICE (here and in
/// `auxiliary_trace_build_data`), and the in-VM verifier clones one AIR per
/// table per epoch. Measured on the recursion guest, clone+drop of
/// `Vec<BusInteraction>` was 9.2% of its cycles while computing nothing.
logup: std::sync::Arc<LogUpLayout>,
/// Idx-ordered metadata for all transition constraints, DERIVED at
/// construction: `constraint_set.meta()` (base prefix) followed by the
/// LogUp emission's derived metadata (ext).
Expand All @@ -838,7 +843,7 @@ pub struct AirWithBuses<
/// program (16-25K nodes on the big tables) per epoch/shard instance.
constraint_program:
std::sync::OnceLock<std::sync::Arc<crate::constraint_ir::ConstraintProgram<F, E>>>,
auxiliary_trace_build_data: AuxiliaryTraceBuildData,
auxiliary_trace_build_data: std::sync::Arc<AuxiliaryTraceBuildData>,
boundary_constraint_builder: PhantomData<(B, PI)>,
/// Commitment to precomputed columns (if this is a preprocessed table)
preprocessed_commitment: Option<crate::config::Commitment>,
Expand Down Expand Up @@ -913,7 +918,10 @@ impl<
// Base-field (table) constraints come from the constraint set; LogUp
// (extension) constraints are appended by the framework from the layout.
let num_interactions = auxiliary_trace_build_data.interactions.len();
let logup = LogUpLayout::from_interactions(auxiliary_trace_build_data.interactions.clone());
let logup = std::sync::Arc::new(LogUpLayout::from_interactions(
auxiliary_trace_build_data.interactions.clone(),
));
let auxiliary_trace_build_data = std::sync::Arc::new(auxiliary_trace_build_data);
let num_term_columns = logup.num_term_columns;

// meta = constraint_set base-prefix meta + appended LogUp ext meta,
Expand Down
7 changes: 7 additions & 0 deletions crypto/stark/src/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4186,12 +4186,19 @@ pub trait IsStarkProver<

let mut denominators =
vec![FieldElement::<FieldExtension>::zero(); air.num_transition_constraints()];
// `1/(z^N - 1)` is the same for EVERY constraint of this AIR, so it is
// computed once here instead of once per constraint inside the loop.
let zerofier_base_inv = crate::constraints::zerofier::zerofier_base_inv::<
Field,
FieldExtension,
>(z, trace_length);
air.constraints_meta().iter().for_each(|m| {
denominators[m.constraint_idx] = crate::constraints::zerofier::evaluate_zerofier(
m,
z,
&domain.trace_primitive_root,
trace_length,
&zerofier_base_inv,
);
});
let transition_sum = transition_evals
Expand Down
7 changes: 7 additions & 0 deletions crypto/stark/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,12 +397,19 @@ pub trait IsStarkVerifier<

let mut denominators =
vec![FieldElement::<FieldExtension>::zero(); air.num_transition_constraints()];
// `1/(z^N - 1)` is the same for EVERY constraint of this AIR, so it is
// computed once here instead of once per constraint inside the loop.
let zerofier_base_inv = crate::constraints::zerofier::zerofier_base_inv::<
Field,
FieldExtension,
>(&challenges.z, trace_length);
air.constraints_meta().iter().for_each(|m| {
denominators[m.constraint_idx] = crate::constraints::zerofier::evaluate_zerofier(
m,
&challenges.z,
&domain.trace_primitive_root,
trace_length,
&zerofier_base_inv,
);
});

Expand Down
Loading