Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stark: Remove degree adjustment from composition poly #563

Merged
merged 9 commits into from
Sep 21, 2023
59 changes: 12 additions & 47 deletions provers/stark/src/constraints/evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ impl<F: IsFFTField, A: AIR + AIR<Field = F>> ConstraintEvaluator<F, A> {
&self,
lde_trace: &TraceTable<F>,
domain: &Domain<F>,
alpha_and_beta_transition_coefficients: &[(FieldElement<F>, FieldElement<F>)],
alpha_and_beta_boundary_coefficients: &[(FieldElement<F>, FieldElement<F>)],
transition_coefficients: &[FieldElement<F>],
boundary_coefficients: &[FieldElement<F>],
rap_challenges: &A::RAPChallenges,
) -> ConstraintEvaluationTable<F>
where
Expand Down Expand Up @@ -72,14 +72,6 @@ impl<F: IsFFTField, A: AIR + AIR<Field = F>> ConstraintEvaluator<F, A> {
.collect::<Vec<Vec<FieldElement<F>>>>();

let trace_length = self.air.trace_length();
let composition_poly_degree_bound = self.air.composition_poly_degree_bound();
let boundary_term_degree_adjustment = composition_poly_degree_bound - trace_length;
// Maybe we can do this more efficiently by taking the offset's power and then using successors for roots of unity
let d_adjustment_power = domain
.lde_roots_of_unity_coset
.iter()
.map(|d| d.pow(boundary_term_degree_adjustment))
.collect::<Vec<FieldElement<F>>>();

#[cfg(all(debug_assertions, not(feature = "parallel")))]
let boundary_polys: Vec<Polynomial<FieldElement<F>>> = Vec::new();
Expand Down Expand Up @@ -108,13 +100,12 @@ impl<F: IsFFTField, A: AIR + AIR<Field = F>> ConstraintEvaluator<F, A> {
let boundary_eval_iter = 0..domain.lde_roots_of_unity_coset.len();

let boundary_evaluation = boundary_eval_iter
.zip(&d_adjustment_power)
.map(|(i, d)| {
.map(|i| {
(0..number_of_b_constraints)
.zip(alpha_and_beta_boundary_coefficients)
.fold(FieldElement::zero(), |acc, (index, (alpha, beta))| {
.zip(boundary_coefficients)
.fold(FieldElement::zero(), |acc, (index, beta)| {
acc + &boundary_zerofiers_inverse_evaluations[index][i]
* (alpha * d + beta)
* beta
* &boundary_polys_evaluations[index][i]
})
})
Expand All @@ -136,28 +127,6 @@ impl<F: IsFFTField, A: AIR + AIR<Field = F>> ConstraintEvaluator<F, A> {
let transition_exemptions_evaluations =
evaluate_transition_exemptions(transition_exemptions, domain);
let num_exemptions = self.air.context().num_transition_exemptions;
let context = self.air.context();
let max_transition_degree = *context.transition_degrees.iter().max().unwrap();

#[cfg(feature = "parallel")]
let degree_adjustments_iter = (1..=max_transition_degree).into_par_iter();

#[cfg(not(feature = "parallel"))]
let degree_adjustments_iter = 1..=max_transition_degree;

let degree_adjustments: Vec<Vec<FieldElement<F>>> = degree_adjustments_iter
.map(|transition_degree| {
domain
.lde_roots_of_unity_coset
.iter()
.map(|d| {
let degree_adjustment = composition_poly_degree_bound
- (trace_length * (transition_degree - 1));
d.pow(degree_adjustment)
})
.collect()
})
.collect();

let blowup_factor_order = u64::from(blowup_factor.trailing_zeros());

Expand Down Expand Up @@ -212,22 +181,20 @@ impl<F: IsFFTField, A: AIR + AIR<Field = F>> ConstraintEvaluator<F, A> {
.iter()
.zip(&self.air.context().transition_exemptions)
.zip(&self.air.context().transition_degrees)
.zip(alpha_and_beta_transition_coefficients)
.zip(transition_coefficients)
.fold(
FieldElement::zero(),
|acc, (((eval, exemption), degree), (alpha, beta))| {
|acc, (((eval, exemption), _), beta)| {
#[cfg(feature = "parallel")]
let zerofier = zerofier.clone();

if *exemption == 0 {
acc + zerofier
* (alpha * &degree_adjustments[degree - 1][i] + beta)
* eval
acc + zerofier * beta * eval
} else {
//TODO: change how exemptions are indexed!
if num_exemptions == 1 {
acc + zerofier
* (alpha * &degree_adjustments[degree - 1][i] + beta)
* beta
* eval
* &transition_exemptions_evaluations[0][i]
} else {
Expand All @@ -247,7 +214,7 @@ impl<F: IsFFTField, A: AIR + AIR<Field = F>> ConstraintEvaluator<F, A> {
.expect("is there");

acc + zerofier
* (alpha * &degree_adjustments[degree - 1][i] + beta)
* beta
* eval
* &transition_exemptions_evaluations[index][i]
}
Expand Down Expand Up @@ -295,9 +262,7 @@ impl<F: IsFFTField, A: AIR + AIR<Field = F>> ConstraintEvaluator<F, A> {
.zip(constraint_coeffs)
.fold(
FieldElement::<F>::zero(),
|acc, (((ev, degree), inv), (alpha, beta))| {
acc + ev * (alpha * degree + beta) * inv
},
|acc, (((ev, _), inv), (_, beta))| acc + ev * beta * inv,
)
}
}
Expand Down
35 changes: 8 additions & 27 deletions provers/stark/src/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,8 @@ fn round_2_compute_composition_polynomial<F, A>(
air: &A,
domain: &Domain<F>,
round_1_result: &Round1<F, A>,
transition_coeffs: &[(FieldElement<F>, FieldElement<F>)],
boundary_coeffs: &[(FieldElement<F>, FieldElement<F>)],
transition_coefficients: &[FieldElement<F>],
boundary_coefficients: &[FieldElement<F>],
) -> Round2<F>
where
F: IsFFTField,
Expand All @@ -241,8 +241,8 @@ where
let constraint_evaluations = evaluator.evaluate(
&round_1_result.lde_trace,
domain,
transition_coeffs,
boundary_coeffs,
transition_coefficients,
boundary_coefficients,
&round_1_result.rap_challenges,
);

Expand Down Expand Up @@ -641,42 +641,23 @@ where
#[cfg(feature = "instruments")]
let timer2 = Instant::now();

// <<<< Receive challenges: 𝛼_j^B
let boundary_coeffs_alphas = batch_sample_challenges(
air.boundary_constraints(&round_1_result.rap_challenges)
.constraints
.len(),
&mut transcript,
);
// <<<< Receive challenges: 𝛽_j^B
let boundary_coeffs_betas = batch_sample_challenges(
let boundary_coefficients = batch_sample_challenges(
air.boundary_constraints(&round_1_result.rap_challenges)
.constraints
.len(),
&mut transcript,
);
// <<<< Receive challenges: 𝛼_j^T
let transition_coeffs_alphas =
batch_sample_challenges(air.context().num_transition_constraints, &mut transcript);
// <<<< Receive challenges: 𝛽_j^T
let transition_coeffs_betas =
let transition_coefficients =
batch_sample_challenges(air.context().num_transition_constraints, &mut transcript);

let boundary_coeffs: Vec<_> = boundary_coeffs_alphas
.into_iter()
.zip(boundary_coeffs_betas)
.collect();
let transition_coeffs: Vec<_> = transition_coeffs_alphas
.into_iter()
.zip(transition_coeffs_betas)
.collect();

let round_2_result = round_2_compute_composition_polynomial(
&air,
&domain,
&round_1_result,
&transition_coeffs,
&boundary_coeffs,
&transition_coefficients,
&boundary_coefficients,
);

// >>>> Send commitments: [H₁], [H₂]
Expand Down
63 changes: 12 additions & 51 deletions provers/stark/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ where
A: AIR<Field = F>,
{
z: FieldElement<F>,
boundary_coeffs: Vec<(FieldElement<F>, FieldElement<F>)>,
transition_coeffs: Vec<(FieldElement<F>, FieldElement<F>)>,
boundary_coeffs: Vec<FieldElement<F>>,
transition_coeffs: Vec<FieldElement<F>>,
trace_term_coeffs: Vec<Vec<FieldElement<F>>>,
gamma_even: FieldElement<F>,
gamma_odd: FieldElement<F>,
Expand Down Expand Up @@ -88,31 +88,14 @@ where
// ===================================

// These are the challenges alpha^B_j and beta^B_j
// >>>> Send challenges: 𝛼_j^B
let boundary_coeffs_alphas = batch_sample_challenges(
air.boundary_constraints(&rap_challenges).constraints.len(),
transcript,
);
// >>>> Send challenges: 𝛽_j^B
let boundary_coeffs_betas = batch_sample_challenges(
let boundary_coeffs = batch_sample_challenges(
air.boundary_constraints(&rap_challenges).constraints.len(),
transcript,
);
// >>>> Send challenges: 𝛼_j^T
let transition_coeffs_alphas =
batch_sample_challenges(air.context().num_transition_constraints, transcript);
// >>>> Send challenges: 𝛽_j^T
let transition_coeffs_betas =
let transition_coeffs =
batch_sample_challenges(air.context().num_transition_constraints, transcript);
let boundary_coeffs: Vec<_> = boundary_coeffs_alphas
.into_iter()
.zip(boundary_coeffs_betas)
.collect();

let transition_coeffs: Vec<_> = transition_coeffs_alphas
.into_iter()
.zip(transition_coeffs_betas)
.collect();

// <<<< Receive commitments: [H₁], [H₂]
transcript.append(&proof.composition_poly_root);
Expand Down Expand Up @@ -221,8 +204,6 @@ fn step_2_verify_claimed_composition_polynomial<F: IsFFTField, A: AIR<Field = F>
//let n_trace_cols = air.context().trace_columns;
// special cases.
let trace_length = air.trace_length();
let composition_poly_degree_bound = air.composition_poly_degree_bound();
let boundary_term_degree_adjustment = composition_poly_degree_bound - trace_length;
let number_of_b_constraints = boundary_constraints.constraints.len();

// Following naming conventions from https://www.notamonadtutorial.com/diving-deep-fri/
Expand Down Expand Up @@ -251,12 +232,11 @@ fn step_2_verify_claimed_composition_polynomial<F: IsFFTField, A: AIR<Field = F>

FieldElement::inplace_batch_inverse(&mut boundary_c_i_evaluations_den).unwrap();

let boundary_degree_z = challenges.z.pow(boundary_term_degree_adjustment);
let boundary_quotient_ood_evaluation: FieldElement<F> = boundary_c_i_evaluations_num
.iter()
.zip(&boundary_c_i_evaluations_den)
.zip(&challenges.boundary_coeffs)
.map(|((num, den), (alpha, beta))| num * den * (alpha * &boundary_degree_z + beta))
.map(|((num, den), beta)| num * den * beta)
.fold(FieldElement::<F>::zero(), |acc, x| acc + x);

let transition_ood_frame_evaluations = air.compute_transition(
Expand All @@ -276,38 +256,19 @@ fn step_2_verify_claimed_composition_polynomial<F: IsFFTField, A: AIR<Field = F>
.map(|poly| poly.evaluate(&challenges.z))
.collect::<Vec<FieldElement<F>>>();

let max_degree = air
.context()
.transition_degrees()
.iter()
.max()
.expect("has maximum degree");
let degree_adjustments = (1..=*max_degree)
.map(|transition_degree| {
let degree_adjustment =
composition_poly_degree_bound - (trace_length * (transition_degree - 1));
challenges.z.pow(degree_adjustment)
})
.collect::<Vec<FieldElement<F>>>();
let unity = &FieldElement::one();
let transition_c_i_evaluations_sum = transition_ood_frame_evaluations
.iter()
.zip(&air.context().transition_degrees)
.zip(&air.context().transition_exemptions)
.zip(&challenges.transition_coeffs)
.fold(
FieldElement::zero(),
|acc, (((eval, degree), except), (alpha, beta))| {
let except = except
.checked_sub(1)
.map(|i| &exemption[i])
.unwrap_or(unity);
acc + &denominator
* eval
* (alpha * &degree_adjustments[degree - 1] + beta)
* except
},
);
.fold(FieldElement::zero(), |acc, (((eval, _), except), beta)| {
let except = except
.checked_sub(1)
.map(|i| &exemption[i])
.unwrap_or(unity);
acc + &denominator * eval * beta * except
});

let composition_poly_ood_evaluation =
&boundary_quotient_ood_evaluation + transition_c_i_evaluations_sum;
Expand Down