diff --git a/src/core/air/evaluation.rs b/src/core/air/evaluation.rs index c82e21cc2..77fbebd93 100644 --- a/src/core/air/evaluation.rs +++ b/src/core/air/evaluation.rs @@ -199,7 +199,8 @@ impl<'a, B: Backend> ComponentVisitor for ConstraintEvaluator<'a, B> { } } -/// Evaluates components' constraint polynomials and aggregates them into a composition polynomial. +/// Evaluates components' constraint polynomials at a single point and aggregates them into a +/// composition polynomial value. pub struct ConstraintPointEvaluator<'a> { point: CirclePoint, mask_values: slice::Iter<'a, ColumnVec>>, diff --git a/src/core/air/mod.rs b/src/core/air/mod.rs index 00c8e6c2b..0d310e7fa 100644 --- a/src/core/air/mod.rs +++ b/src/core/air/mod.rs @@ -1,4 +1,5 @@ use core::slice; +use std::collections::BTreeSet; use std::iter::zip; use std::ops::Deref; @@ -12,6 +13,7 @@ use super::backend::{Backend, CPUBackend}; use super::circle::CirclePoint; use super::fields::m31::BaseField; use super::fields::qm31::SecureField; +use super::fri::CirclePolyDegreeBound; use super::poly::circle::{CanonicCoset, CirclePoly}; use super::{ColumnVec, ComponentVec}; @@ -85,6 +87,19 @@ pub trait AirExt: Air { self.visit_components(&mut evaluator); evaluator.finalize() } + + /// Returns the log degree bounds of the quotient polynomials in descending order. + fn quotient_log_bounds(&self) -> Vec { + let mut bounds_visitor = QuotientLogBoundsVisitor::new(); + self.visit_components(&mut bounds_visitor); + let mut bounds = bounds_visitor.finalize(); + bounds.push(self.max_constraint_log_degree_bound()); + bounds + .into_iter() + .rev() + .map(CirclePolyDegreeBound::new) + .collect() + } } impl> AirExt for A {} @@ -180,6 +195,39 @@ impl ComponentVisitor for MaskPointsEvaluator { } } +struct QuotientLogBoundsVisitor { + bounds: BTreeSet, +} + +impl QuotientLogBoundsVisitor { + pub fn new() -> Self { + Self { + bounds: BTreeSet::new(), + } + } + + pub fn finalize(self) -> Vec { + self.bounds.into_iter().collect() + } +} + +impl ComponentVisitor for QuotientLogBoundsVisitor { + fn visit>(&mut self, component: &C) { + let bounds = zip( + component.mask().iter(), + &component.trace_log_degree_bounds(), + ) + .flat_map(|(trace_points, trace_bound)| { + trace_points + .iter() + .map(|_| *trace_bound) + .collect::>() + }) + .collect_vec(); + self.bounds.extend(bounds); + } +} + /// Holds the mask offsets at each column. /// Holds a vector with an entry for each column. Each entry holds the offsets /// of the mask at that column. diff --git a/src/core/oods.rs b/src/core/oods.rs index 168e6d46e..5173fa7a8 100644 --- a/src/core/oods.rs +++ b/src/core/oods.rs @@ -1,16 +1,11 @@ -use std::iter::zip; - use itertools::enumerate; -use super::air::Component; use super::backend::cpu::CPUCircleEvaluation; -use super::backend::Backend; use super::circle::CirclePoint; use super::constraints::{complex_conjugate_line, pair_vanishing, point_vanishing}; use super::fields::m31::BaseField; use super::fields::qm31::SecureField; use super::fields::ComplexConjugate; -use super::fri::CirclePolyDegreeBound; use super::poly::circle::CircleEvaluation; use super::poly::{BitReversedOrder, NaturalOrder}; use super::utils::bit_reverse_index; @@ -81,17 +76,3 @@ pub fn get_pair_oods_quotient( } CircleEvaluation::new(eval.domain, values) } - -pub fn quotient_log_bounds(component: impl Component) -> Vec { - zip( - component.mask().iter(), - &component.trace_log_degree_bounds(), - ) - .flat_map(|(trace_points, trace_bound)| { - trace_points - .iter() - .map(|_| CirclePolyDegreeBound::new(*trace_bound)) - .collect::>() - }) - .collect() -} diff --git a/src/fibonacci/mod.rs b/src/fibonacci/mod.rs index 9cdb065b5..35531a8b2 100644 --- a/src/fibonacci/mod.rs +++ b/src/fibonacci/mod.rs @@ -15,10 +15,8 @@ use crate::core::commitment_scheme::{CommitmentSchemeProver, CommitmentSchemeVer use crate::core::fields::m31::BaseField; use crate::core::fields::qm31::SecureField; use crate::core::fields::{Field, IntoSlice}; -use crate::core::fri::{ - CirclePolyDegreeBound, FriConfig, FriProof, FriProver, FriVerifier, SparseCircleEvaluation, -}; -use crate::core::oods::{get_oods_quotient, get_pair_oods_quotient, quotient_log_bounds}; +use crate::core::fri::{FriConfig, FriProof, FriProver, FriVerifier, SparseCircleEvaluation}; +use crate::core::oods::{get_oods_quotient, get_pair_oods_quotient}; use crate::core::poly::circle::{CanonicCoset, CircleEvaluation}; use crate::core::poly::BitReversedOrder; use crate::core::proof_of_work::{ProofOfWork, ProofOfWorkProof}; @@ -213,10 +211,7 @@ pub fn verify_proof(proof: FibonacciProof) -> bool { ); // TODO(AlonH): Get bounds from air. - let mut bounds = vec![CirclePolyDegreeBound::new( - fib.air.max_constraint_log_degree_bound(), - )]; - bounds.append(&mut quotient_log_bounds(fib.air.component)); + let bounds = fib.air.quotient_log_bounds(); let fri_config = FriConfig::new(LOG_LAST_LAYER_DEGREE_BOUND, LOG_BLOWUP_FACTOR, N_QUERIES); let mut fri_verifier = FriVerifier::commit(channel, fri_config, proof.fri_proof, bounds).unwrap();