diff --git a/README.md b/README.md index b166e4748..f54d45db8 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,6 @@ Over time, we hope extend the library with additional features: **Perfect zero-knowledge.** The current implementation provides succinct proofs but NOT perfect zero-knowledge. This means that, in its current form, the library may not be suitable for use cases where proofs must not leak any info about secret inputs. -**Auxiliary GKR proofs.** It will be possible to attach auxiliary GKR-based proofs to the base STARK proofs. This will enable powerful new ways of defining constraints and optimizing prover performance. ### Project structure The project is organized into several crates like so: diff --git a/air/src/air/aux.rs b/air/src/air/aux.rs index 01f59035a..19914d090 100644 --- a/air/src/air/aux.rs +++ b/air/src/air/aux.rs @@ -3,132 +3,22 @@ // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. -use alloc::{string::ToString, vec::Vec}; - -use crypto::{ElementHasher, RandomCoin, RandomCoinError}; -use math::FieldElement; -use utils::Deserializable; - -use super::lagrange::LagrangeKernelRandElements; +use alloc::vec::Vec; /// Holds the randomly generated elements necessary to build the auxiliary trace. -/// -/// Specifically, [`AuxRandElements`] currently supports 3 types of random elements: -/// - the ones needed to build the Lagrange kernel column (when using GKR to accelerate LogUp), -/// - the ones needed to build the "s" auxiliary column (when using GKR to accelerate LogUp), -/// - the ones needed to build all the other auxiliary columns #[derive(Debug, Clone)] pub struct AuxRandElements { rand_elements: Vec, - gkr: Option>, } impl AuxRandElements { - /// Creates a new [`AuxRandElements`], where the auxiliary trace doesn't contain a Lagrange - /// kernel column. + /// Creates a new [`AuxRandElements`]. pub fn new(rand_elements: Vec) -> Self { - Self { rand_elements, gkr: None } - } - - /// Creates a new [`AuxRandElements`], where the auxiliary trace contains columns needed when - /// using GKR to accelerate LogUp (i.e. a Lagrange kernel column and the "s" column). - pub fn new_with_gkr(rand_elements: Vec, gkr: GkrRandElements) -> Self { - Self { rand_elements, gkr: Some(gkr) } + Self { rand_elements } } - /// Returns the random elements needed to build all columns other than the two GKR-related ones. + /// Returns the random elements needed to build all columns. pub fn rand_elements(&self) -> &[E] { &self.rand_elements } - - /// Returns the random elements needed to build the Lagrange kernel column. - pub fn lagrange(&self) -> Option<&LagrangeKernelRandElements> { - self.gkr.as_ref().map(|gkr| &gkr.lagrange) - } - - /// Returns the random values used to linearly combine the openings returned from the GKR proof. - /// - /// These correspond to the lambdas in our documentation. - pub fn gkr_openings_combining_randomness(&self) -> Option<&[E]> { - self.gkr.as_ref().map(|gkr| gkr.openings_combining_randomness.as_ref()) - } -} - -/// Holds all the random elements needed when using GKR to accelerate LogUp. -/// -/// This consists of two sets of random values: -/// 1. The Lagrange kernel random elements (expanded on in [`LagrangeKernelRandElements`]), and -/// 2. The "openings combining randomness". -/// -/// After the verifying the LogUp-GKR circuit, the verifier is left with unproven claims provided -/// nondeterministically by the prover about the evaluations of the MLE of the main trace columns at -/// the Lagrange kernel random elements. Those claims are (linearly) combined into one using the -/// openings combining randomness. -#[derive(Clone, Debug)] -pub struct GkrRandElements { - lagrange: LagrangeKernelRandElements, - openings_combining_randomness: Vec, -} - -impl GkrRandElements { - /// Constructs a new [`GkrRandElements`] from [`LagrangeKernelRandElements`], and the openings - /// combining randomness. - /// - /// See [`GkrRandElements`] for a more detailed description. - pub fn new( - lagrange: LagrangeKernelRandElements, - openings_combining_randomness: Vec, - ) -> Self { - Self { lagrange, openings_combining_randomness } - } - - /// Returns the random elements needed to build the Lagrange kernel column. - pub fn lagrange_kernel_rand_elements(&self) -> &LagrangeKernelRandElements { - &self.lagrange - } - - /// Returns the random values used to linearly combine the openings returned from the GKR proof. - pub fn openings_combining_randomness(&self) -> &[E] { - &self.openings_combining_randomness - } -} - -/// A trait for verifying a GKR proof. -/// -/// Specifically, the use case in mind is proving the constraints of a LogUp bus using GKR, as -/// described in [Improving logarithmic derivative lookups using -/// GKR](https://eprint.iacr.org/2023/1284.pdf). -pub trait GkrVerifier { - /// The GKR proof. - type GkrProof: Deserializable; - /// The error that can occur during GKR proof verification. - type Error: ToString; - - /// Verifies the GKR proof, and returns the random elements that were used in building - /// the Lagrange kernel auxiliary column. - fn verify( - &self, - gkr_proof: Self::GkrProof, - public_coin: &mut impl RandomCoin, - ) -> Result, Self::Error> - where - E: FieldElement, - Hasher: ElementHasher; -} - -impl GkrVerifier for () { - type GkrProof = (); - type Error = RandomCoinError; - - fn verify( - &self, - _gkr_proof: Self::GkrProof, - _public_coin: &mut impl RandomCoin, - ) -> Result, Self::Error> - where - E: FieldElement, - Hasher: ElementHasher, - { - Ok(GkrRandElements::new(LagrangeKernelRandElements::default(), Vec::new())) - } } diff --git a/air/src/air/coefficients.rs b/air/src/air/coefficients.rs index c49a31a0d..1042be270 100644 --- a/air/src/air/coefficients.rs +++ b/air/src/air/coefficients.rs @@ -32,16 +32,8 @@ use math::{get_power_series, get_power_series_with_offset, FieldElement}; pub struct ConstraintCompositionCoefficients { pub transition: Vec, pub boundary: Vec, - pub lagrange: Option>, } -/// Stores the constraint composition coefficients for the Lagrange kernel transition and boundary -/// constraints. -#[derive(Debug, Clone)] -pub struct LagrangeConstraintsCompositionCoefficients { - pub transition: Vec, - pub boundary: E, -} // DEEP COMPOSITION COEFFICIENTS // ================================================================================================ /// Coefficients used in construction of DEEP composition polynomial. @@ -83,33 +75,12 @@ pub struct LagrangeConstraintsCompositionCoefficients { /// Theorem 8 of https://eprint.iacr.org/2022/1216. /// 3. The error will depend on the batching used in building the DEEP polynomial. More precisely, /// when using algebraic batching there is a loss of log_2(k + m - 1) bits of soundness. -/// -/// In the case when the trace polynomials contain a trace polynomial corresponding to a Lagrange -/// kernel column, the above expression of $Y(x)$ includes the additional term given by -/// -/// $$ -/// \gamma \cdot \frac{T_l(x) - p_S(x)}{Z_S(x)} -/// $$ -/// -/// where: -/// -/// 1. $\gamma$ is the composition coefficient for the Lagrange kernel trace polynomial. -/// 2. $T_l(x) is the evaluation of the Lagrange trace polynomial at $x$. -/// 3. $S$ is the set of opening points for the Lagrange kernel i.e., -/// $S := {z, z.g, z.g^2, ..., z.g^{2^{log_2(\nu) - 1}}}$. -/// 4. $p_S(X)$ is the polynomial of minimal degree interpolating the set ${(a, T_l(a)): a \in S}$. -/// 5. $Z_S(X)$ is the polynomial of minimal degree vanishing over the set $S$. -/// -/// Note that, if a Lagrange kernel trace polynomial is present, then the agreement parameter needs -/// to be adapted accordingly. #[derive(Debug, Clone)] pub struct DeepCompositionCoefficients { /// Trace polynomial composition coefficients $\alpha_i$. pub trace: Vec, /// Constraint column polynomial composition coefficients $\beta_j$. pub constraints: Vec, - /// Lagrange kernel trace polynomial composition coefficient $\gamma$. - pub lagrange: Option, } impl DeepCompositionCoefficients { @@ -133,7 +104,6 @@ impl DeepCompositionCoefficients { Ok(DeepCompositionCoefficients { trace: t_coefficients, constraints: c_coefficients, - lagrange: None, }) } @@ -162,7 +132,6 @@ impl DeepCompositionCoefficients { Ok(DeepCompositionCoefficients { trace: t_coefficients, constraints: c_coefficients, - lagrange: None, }) } } diff --git a/air/src/air/context.rs b/air/src/air/context.rs index 09341afe3..95268ba4e 100644 --- a/air/src/air/context.rs +++ b/air/src/air/context.rs @@ -21,7 +21,6 @@ pub struct AirContext { pub(super) aux_transition_constraint_degrees: Vec, pub(super) num_main_assertions: usize, pub(super) num_aux_assertions: usize, - pub(super) lagrange_kernel_aux_column_idx: Option, pub(super) ce_blowup_factor: usize, pub(super) trace_domain_generator: B, pub(super) lde_domain_generator: B, @@ -62,7 +61,6 @@ impl AirContext { Vec::new(), num_assertions, 0, - None, options, ) } @@ -95,7 +93,6 @@ impl AirContext { aux_transition_constraint_degrees: Vec, num_main_assertions: usize, num_aux_assertions: usize, - lagrange_kernel_aux_column_idx: Option, options: ProofOptions, ) -> Self { assert!( @@ -124,15 +121,6 @@ impl AirContext { ); } - // validate Lagrange kernel aux column, if any - if let Some(lagrange_kernel_aux_column_idx) = lagrange_kernel_aux_column_idx { - assert!( - lagrange_kernel_aux_column_idx == trace_info.get_aux_segment_width() - 1, - "Lagrange kernel column should be the last column of the auxiliary trace: index={}, but aux trace width is {}", - lagrange_kernel_aux_column_idx, trace_info.get_aux_segment_width() - ); - } - // determine minimum blowup factor needed to evaluate transition constraints by taking // the blowup factor of the highest degree constraint let mut ce_blowup_factor = 0; @@ -165,7 +153,6 @@ impl AirContext { aux_transition_constraint_degrees, num_main_assertions, num_aux_assertions, - lagrange_kernel_aux_column_idx, ce_blowup_factor, trace_domain_generator: B::get_root_of_unity(trace_length.ilog2()), lde_domain_generator: B::get_root_of_unity(lde_domain_size.ilog2()), @@ -209,8 +196,7 @@ impl AirContext { self.trace_info.length() * self.options.blowup_factor() } - /// Returns the number of transition constraints for a computation, excluding the Lagrange - /// kernel transition constraints, which are managed separately. + /// Returns the number of transition constraints for a computation. /// /// The number of transition constraints is defined by the total number of transition constraint /// degree descriptors (for both the main and the auxiliary trace constraints). This number is @@ -230,18 +216,7 @@ impl AirContext { self.aux_transition_constraint_degrees.len() } - /// Returns the index of the auxiliary column which implements the Lagrange kernel, if any - pub fn lagrange_kernel_aux_column_idx(&self) -> Option { - self.lagrange_kernel_aux_column_idx - } - - /// Returns true if the auxiliary trace segment contains a Lagrange kernel column - pub fn has_lagrange_kernel_aux_column(&self) -> bool { - self.lagrange_kernel_aux_column_idx().is_some() - } - - /// Returns the total number of assertions defined for a computation, excluding the Lagrange - /// kernel assertion, which is managed separately. + /// Returns the total number of assertions defined for a computation. /// /// The number of assertions consists of the assertions placed against the main segment of an /// execution trace as well as assertions placed against the auxiliary trace segment. @@ -287,11 +262,6 @@ impl AirContext { /// if the highest constraint degree is equal to `5`, the constraint composition polynomial will /// require four columns and if the highest constraint degree is equal to `7`, it will require /// six columns to store. - /// - /// Note that the Lagrange kernel constraints require only 1 column, since the degree of the - /// numerator is `trace_len - 1` for all transition constraints (i.e. the base degree is 1). - /// Hence, no matter what the degree of the divisor is for each, the degree of the fraction will - /// be at most `trace_len - 1`. pub fn num_constraint_composition_columns(&self) -> usize { let mut highest_constraint_degree = 0_usize; for degree in self diff --git a/air/src/air/divisor.rs b/air/src/air/divisor.rs index 858e24949..391e21921 100644 --- a/air/src/air/divisor.rs +++ b/air/src/air/divisor.rs @@ -49,9 +49,7 @@ impl ConstraintDivisor { /// and $k$ is the number of exemption points. The default value for $k$ is $1$. /// /// The above divisor specifies that transition constraints must hold on all steps of the - /// constraint enforcement domain except for the last $k$ steps. The constraint enforcement - /// domain is the entire trace in the case of transition constraints, but only a subset of the - /// trace for Lagrange kernel transition constraints. + /// constraint enforcement domain except for the last $k$ steps. pub fn from_transition( constraint_enforcement_domain_size: usize, num_exemptions: usize, diff --git a/air/src/air/lagrange/boundary.rs b/air/src/air/lagrange/boundary.rs deleted file mode 100644 index 5d1954615..000000000 --- a/air/src/air/lagrange/boundary.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. -// -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -use math::FieldElement; - -use crate::{LagrangeKernelEvaluationFrame, LagrangeKernelRandElements}; - -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct LagrangeKernelBoundaryConstraint -where - E: FieldElement, -{ - assertion_value: E, - composition_coefficient: E, -} - -impl LagrangeKernelBoundaryConstraint -where - E: FieldElement, -{ - /// Creates a new Lagrange kernel boundary constraint. - pub fn new( - composition_coefficient: E, - lagrange_kernel_rand_elements: &LagrangeKernelRandElements, - ) -> Self { - Self { - assertion_value: Self::assertion_value(lagrange_kernel_rand_elements), - composition_coefficient, - } - } - - /// Returns the evaluation of the boundary constraint at `x`, multiplied by the composition - /// coefficient. - /// - /// `frame` is the evaluation frame of the Lagrange kernel column `c`, starting at `c(x)` - pub fn evaluate_at(&self, x: E, frame: &LagrangeKernelEvaluationFrame) -> E { - let numerator = self.evaluate_numerator_at(frame); - let denominator = self.evaluate_denominator_at(x); - - numerator / denominator - } - - /// Returns the evaluation of the boundary constraint numerator, multiplied by the composition - /// coefficient. - /// - /// `frame` is the evaluation frame of the Lagrange kernel column `c`, starting at `c(x)` for - /// some `x` - pub fn evaluate_numerator_at(&self, frame: &LagrangeKernelEvaluationFrame) -> E { - let trace_value = frame.inner()[0]; - let constraint_evaluation = trace_value - self.assertion_value; - - constraint_evaluation * self.composition_coefficient - } - - /// Returns the evaluation of the boundary constraint denominator at point `x`. - pub fn evaluate_denominator_at(&self, x: E) -> E { - x - E::ONE - } - - /// Computes the assertion value given the provided random elements. - pub fn assertion_value(lagrange_kernel_rand_elements: &LagrangeKernelRandElements) -> E { - let mut assertion_value = E::ONE; - for &rand_ele in lagrange_kernel_rand_elements.as_ref() { - assertion_value *= E::ONE - rand_ele; - } - - assertion_value - } -} diff --git a/air/src/air/lagrange/frame.rs b/air/src/air/lagrange/frame.rs deleted file mode 100644 index d0ffc4fa4..000000000 --- a/air/src/air/lagrange/frame.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. -// -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -use alloc::vec::Vec; - -use math::{polynom, FieldElement, StarkField}; - -/// The evaluation frame for the Lagrange kernel. -/// -/// The Lagrange kernel's evaluation frame is different from [`crate::EvaluationFrame`]. -/// Specifically, -/// - it only contains evaluations from the Lagrange kernel column compared to all columns in the -/// case of [`crate::EvaluationFrame`]) -/// - The column is evaluated at points `x`, `gx`, `g^2 x`, ..., `g^(2^(v-1)) x`, where `x` is an -/// arbitrary point, and `g` is the trace domain generator -#[derive(Debug, Clone)] -pub struct LagrangeKernelEvaluationFrame { - frame: Vec, -} - -impl LagrangeKernelEvaluationFrame { - // CONSTRUCTORS - // -------------------------------------------------------------------------------------------- - - /// Constructs a Lagrange kernel evaluation frame from the raw column polynomial evaluations. - pub fn new(frame: Vec) -> Self { - Self { frame } - } - - /// Constructs an empty Lagrange kernel evaluation frame from the raw column polynomial - /// evaluations. The frame can subsequently be filled using [`Self::frame_mut`]. - pub fn new_empty() -> Self { - Self { frame: Vec::new() } - } - - /// Constructs the frame from the Lagrange kernel column trace polynomial coefficients for an - /// evaluation point. - pub fn from_lagrange_kernel_column_poly(lagrange_kernel_col_poly: &[E], z: E) -> Self { - let log_trace_len = lagrange_kernel_col_poly.len().ilog2(); - let g = E::from(E::BaseField::get_root_of_unity(log_trace_len)); - - let mut frame = Vec::with_capacity(log_trace_len as usize + 1); - - // push c(x) - frame.push(polynom::eval(lagrange_kernel_col_poly, z)); - - // push c(z * g), c(z * g^2), c(z * g^4), ..., c(z * g^(2^(v-1))) - let mut g_exp = g; - for _ in 0..log_trace_len { - let x = g_exp * z; - let lagrange_poly_at_x = polynom::eval(lagrange_kernel_col_poly, x); - - frame.push(lagrange_poly_at_x); - - // takes on the values `g`, `g^2`, `g^4`, `g^8`, ... - g_exp *= g_exp; - } - - Self { frame } - } - - // MUTATORS - // -------------------------------------------------------------------------------------------- - - /// Returns a mutable reference to the inner frame. - pub fn frame_mut(&mut self) -> &mut Vec { - &mut self.frame - } - - // ACCESSORS - // -------------------------------------------------------------------------------------------- - - /// Returns a reference to the inner frame. - pub fn inner(&self) -> &[E] { - &self.frame - } - - /// Returns the number of rows in the frame. - /// - /// This is equal to `log(trace_length) + 1`. - pub fn num_rows(&self) -> usize { - self.frame.len() - } -} diff --git a/air/src/air/lagrange/mod.rs b/air/src/air/lagrange/mod.rs deleted file mode 100644 index fed5897f3..000000000 --- a/air/src/air/lagrange/mod.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. -// -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -mod boundary; -use alloc::vec::Vec; -use core::ops::Deref; - -pub use boundary::LagrangeKernelBoundaryConstraint; - -mod frame; -pub use frame::LagrangeKernelEvaluationFrame; - -mod transition; -use math::FieldElement; -pub use transition::LagrangeKernelTransitionConstraints; - -use crate::LagrangeConstraintsCompositionCoefficients; - -/// Represents the Lagrange kernel transition and boundary constraints. -pub struct LagrangeKernelConstraints { - pub transition: LagrangeKernelTransitionConstraints, - pub boundary: LagrangeKernelBoundaryConstraint, - pub lagrange_kernel_col_idx: usize, -} - -impl LagrangeKernelConstraints { - /// Constructs a new [`LagrangeKernelConstraints`]. - pub fn new( - lagrange_composition_coefficients: LagrangeConstraintsCompositionCoefficients, - lagrange_kernel_rand_elements: &LagrangeKernelRandElements, - lagrange_kernel_col_idx: usize, - ) -> Self { - Self { - transition: LagrangeKernelTransitionConstraints::new( - lagrange_composition_coefficients.transition, - ), - boundary: LagrangeKernelBoundaryConstraint::new( - lagrange_composition_coefficients.boundary, - lagrange_kernel_rand_elements, - ), - lagrange_kernel_col_idx, - } - } -} - -/// Holds the randomly generated elements needed to build the Lagrange kernel auxiliary column. -/// -/// The Lagrange kernel consists of evaluating the function $eq(x, r)$, where $x$ is the binary -/// decomposition of the row index, and $r$ is some random point. The "Lagrange kernel random -/// elements" refer to this (multidimensional) point $r$. -#[derive(Debug, Clone, Default)] -pub struct LagrangeKernelRandElements { - elements: Vec, -} - -impl LagrangeKernelRandElements { - /// Creates a new [`LagrangeKernelRandElements`]. - pub fn new(elements: Vec) -> Self { - Self { elements } - } -} - -impl Deref for LagrangeKernelRandElements { - type Target = Vec; - - fn deref(&self) -> &Self::Target { - &self.elements - } -} - -impl AsRef<[E]> for LagrangeKernelRandElements { - fn as_ref(&self) -> &[E] { - &self.elements - } -} - -impl From> for Vec { - fn from(lagrange_rand_elements: LagrangeKernelRandElements) -> Self { - lagrange_rand_elements.elements - } -} diff --git a/air/src/air/lagrange/transition.rs b/air/src/air/lagrange/transition.rs deleted file mode 100644 index 18bdfa9be..000000000 --- a/air/src/air/lagrange/transition.rs +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. -// -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -use alloc::vec::Vec; - -use math::{ExtensionOf, FieldElement}; - -use crate::{ConstraintDivisor, LagrangeKernelEvaluationFrame}; - -/// Represents the transition constraints for the Lagrange kernel column, as well as the random -/// coefficients used to linearly combine all the constraints. -/// -/// There are `log(trace_len)` constraints, each with its own divisor, as described in -/// [this issue](https://github.com/facebook/winterfell/issues/240). -pub struct LagrangeKernelTransitionConstraints { - lagrange_constraint_coefficients: Vec, - divisors: Vec>, -} - -impl LagrangeKernelTransitionConstraints { - /// Creates a new [`LagrangeKernelTransitionConstraints`], which represents the Lagrange kernel - /// transition constraints as well as the random coefficients necessary to combine the - /// constraints together. - pub fn new(lagrange_constraint_coefficients: Vec) -> Self { - let num_lagrange_kernel_transition_constraints = lagrange_constraint_coefficients.len(); - - let divisors = { - let mut divisors = Vec::with_capacity(num_lagrange_kernel_transition_constraints); - for i in 0..num_lagrange_kernel_transition_constraints { - let constraint_domain_size = 2_usize.pow(i as u32); - let divisor = ConstraintDivisor::from_transition(constraint_domain_size, 0); - - divisors.push(divisor); - } - divisors - }; - - Self { - lagrange_constraint_coefficients, - divisors, - } - } - - /// Evaluates the numerator of the `constraint_idx`th transition constraint. - pub fn evaluate_ith_numerator( - &self, - lagrange_kernel_column_frame: &LagrangeKernelEvaluationFrame, - lagrange_kernel_rand_elements: &[E], - constraint_idx: usize, - ) -> E - where - F: FieldElement, - E: ExtensionOf, - { - let c = lagrange_kernel_column_frame.inner(); - let v = c.len() - 1; - let r = lagrange_kernel_rand_elements; - let k = constraint_idx + 1; - - let eval = (r[v - k] * c[0]) - ((E::ONE - r[v - k]) * c[v - k + 1]); - - self.lagrange_constraint_coefficients[constraint_idx].mul_base(eval) - } - - /// Evaluates the divisor of the `constraint_idx`th transition constraint. - pub fn evaluate_ith_divisor(&self, constraint_idx: usize, x: F) -> E - where - F: FieldElement, - E: ExtensionOf, - { - self.divisors[constraint_idx].evaluate_at(x.into()) - } - - /// Evaluates the transition constraints over the specificed Lagrange kernel evaluation frame, - /// and combines them. - /// - /// By "combining transition constraints evaluations", we mean computing a linear combination of - /// each transition constraint evaluation, where each transition evaluation is divided by its - /// corresponding divisor. - pub fn evaluate_and_combine( - &self, - lagrange_kernel_column_frame: &LagrangeKernelEvaluationFrame, - lagrange_kernel_rand_elements: &[E], - x: F, - ) -> E - where - F: FieldElement, - E: ExtensionOf, - { - let numerators = self - .evaluate_numerators::(lagrange_kernel_column_frame, lagrange_kernel_rand_elements); - - numerators - .iter() - .zip(self.divisors.iter()) - .fold(E::ZERO, |acc, (&numerator, divisor)| { - let z = divisor.evaluate_at(x); - - acc + (numerator / z.into()) - }) - } - - /// Returns the number of constraints. - pub fn num_constraints(&self) -> usize { - self.lagrange_constraint_coefficients.len() - } - - // HELPERS - // --------------------------------------------------------------------------------------------- - - /// Evaluates the transition constraints' numerators over the specified Lagrange kernel - /// evaluation frame. - fn evaluate_numerators( - &self, - lagrange_kernel_column_frame: &LagrangeKernelEvaluationFrame, - lagrange_kernel_rand_elements: &[E], - ) -> Vec - where - F: FieldElement, - E: ExtensionOf, - { - let log2_trace_len = lagrange_kernel_column_frame.num_rows() - 1; - let mut transition_evals = vec![E::ZERO; log2_trace_len]; - - let c = lagrange_kernel_column_frame.inner(); - let v = c.len() - 1; - let r = lagrange_kernel_rand_elements; - - for k in 1..v + 1 { - transition_evals[k - 1] = (r[v - k] * c[0]) - ((E::ONE - r[v - k]) * c[v - k + 1]); - } - - transition_evals - .into_iter() - .zip(self.lagrange_constraint_coefficients.iter()) - .map(|(transition_eval, &coeff)| coeff.mul_base(transition_eval)) - .collect() - } -} diff --git a/air/src/air/mod.rs b/air/src/air/mod.rs index 0ad8941ed..db35bb277 100644 --- a/air/src/air/mod.rs +++ b/air/src/air/mod.rs @@ -11,7 +11,7 @@ use math::{fft, ExtensibleField, ExtensionOf, FieldElement, StarkField, ToElemen use crate::{BatchingMethod, ProofOptions}; mod aux; -pub use aux::{AuxRandElements, GkrRandElements, GkrVerifier}; +pub use aux::AuxRandElements; mod trace_info; pub use trace_info::TraceInfo; @@ -28,21 +28,11 @@ pub use boundary::{BoundaryConstraint, BoundaryConstraintGroup, BoundaryConstrai mod transition; pub use transition::{EvaluationFrame, TransitionConstraintDegree, TransitionConstraints}; -mod lagrange; -pub use lagrange::{ - LagrangeKernelBoundaryConstraint, LagrangeKernelConstraints, LagrangeKernelEvaluationFrame, - LagrangeKernelRandElements, LagrangeKernelTransitionConstraints, -}; - mod coefficients; -pub use coefficients::{ - ConstraintCompositionCoefficients, DeepCompositionCoefficients, - LagrangeConstraintsCompositionCoefficients, -}; +pub use coefficients::{ConstraintCompositionCoefficients, DeepCompositionCoefficients}; mod divisor; pub use divisor::ConstraintDivisor; -use utils::{Deserializable, Serializable}; #[cfg(test)] mod tests; @@ -194,12 +184,6 @@ pub trait Air: Send + Sync { /// This could be any type as long as it can be serialized into a sequence of field elements. type PublicInputs: ToElements + Send; - /// An GKR proof object. If not needed, set to `()`. - type GkrProof: Serializable + Deserializable + Send; - - /// A verifier for verifying GKR proofs. If not needed, set to `()`. - type GkrVerifier: GkrVerifier; - // REQUIRED METHODS // -------------------------------------------------------------------------------------------- @@ -288,8 +272,7 @@ pub trait Air: Send + Sync { /// segments. That is, assertion against column 0, is an assertion against the first column of /// auxiliary trace segment. /// - /// `aux_rand_elements` holds the random elements used to build all auxiliary columns except for - /// the Lagrange kernel column. + /// `aux_rand_elements` holds the random elements used to build all auxiliary columns. /// /// When the protocol is executed using an extension field, auxiliary assertions are defined /// over the extension field. This is in contrast with the assertions returned from @@ -303,23 +286,10 @@ pub trait Air: Send + Sync { Vec::new() } - // AUXILIARY PROOF VERIFIER - // -------------------------------------------------------------------------------------------- - - /// Returns the [`GkrVerifier`] to be used to verify the GKR proof. - /// - /// Leave unimplemented if the `Air` doesn't use a GKR proof. - fn get_gkr_proof_verifier>( - &self, - ) -> Self::GkrVerifier { - unimplemented!("`get_auxiliary_proof_verifier()` must be implemented when the proof contains a GKR proof"); - } - // PROVIDED METHODS // -------------------------------------------------------------------------------------------- - /// Returns a vector of field elements required for construction of the auxiliary trace segment - /// (except the Lagrange kernel column, if any). + /// Returns a vector of field elements required for construction of the auxiliary trace segment. /// /// The elements are drawn uniformly at random from the provided public coin. fn get_aux_rand_elements(&self, public_coin: &mut R) -> Result, RandomCoinError> @@ -335,22 +305,6 @@ pub trait Air: Send + Sync { Ok(rand_elements) } - /// Returns a new [`LagrangeKernelConstraints`] if a Lagrange kernel auxiliary column is present - /// in the trace, or `None` otherwise. - fn get_lagrange_kernel_constraints>( - &self, - lagrange_composition_coefficients: LagrangeConstraintsCompositionCoefficients, - lagrange_kernel_rand_elements: &LagrangeKernelRandElements, - ) -> Option> { - self.context().lagrange_kernel_aux_column_idx().map(|col_idx| { - LagrangeKernelConstraints::new( - lagrange_composition_coefficients, - lagrange_kernel_rand_elements, - col_idx, - ) - }) - } - /// Returns values for all periodic columns used in the computation. /// /// These values will be used to compute column values at specific states of the computation @@ -545,26 +499,9 @@ pub trait Air: Send + Sync { b_coefficients.push(public_coin.draw()?); } - let lagrange = if self.context().has_lagrange_kernel_aux_column() { - let mut lagrange_kernel_t_coefficients = Vec::new(); - for _ in 0..self.context().trace_len().ilog2() { - lagrange_kernel_t_coefficients.push(public_coin.draw()?); - } - - let lagrange_kernel_boundary = public_coin.draw()?; - - Some(LagrangeConstraintsCompositionCoefficients { - transition: lagrange_kernel_t_coefficients, - boundary: lagrange_kernel_boundary, - }) - } else { - None - }; - Ok(ConstraintCompositionCoefficients { transition: t_coefficients, boundary: b_coefficients, - lagrange, }) } diff --git a/air/src/air/tests.rs b/air/src/air/tests.rs index bd646e7a8..c90b99350 100644 --- a/air/src/air/tests.rs +++ b/air/src/air/tests.rs @@ -225,8 +225,6 @@ impl MockAir { impl Air for MockAir { type BaseField = BaseElement; type PublicInputs = (); - type GkrProof = (); - type GkrVerifier = (); fn new(trace_info: TraceInfo, _pub_inputs: (), _options: ProofOptions) -> Self { let num_assertions = trace_info.meta()[0] as usize; diff --git a/air/src/air/trace_info.rs b/air/src/air/trace_info.rs index 99ff4aa6d..8dcc6cc77 100644 --- a/air/src/air/trace_info.rs +++ b/air/src/air/trace_info.rs @@ -16,10 +16,10 @@ use utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serial /// Information about a specific execution trace. /// /// Trace info consists of the number of columns for all trace segments, trace length, the number of -/// random elements needed to generate the auxiliary segment (excluding the Lagrange kernel column), -/// and optional custom metadata. Currently, a trace can consist of at most two segments: the main -/// segment and one auxiliary segment. Metadata is just a vector of bytes and can store any values -/// up to 64KB in size. +/// random elements needed to generate the auxiliary segment and optional custom metadata. +/// +/// Currently, a trace can consist of at most two segments: the main segment and one auxiliary +/// segment. Metadata is just a vector of bytes and can store any values up to 64KB in size. #[derive(Debug, Clone, Eq, PartialEq)] pub struct TraceInfo { main_segment_width: usize, @@ -70,9 +70,6 @@ impl TraceInfo { /// Creates a new [TraceInfo] with main and auxiliary segments. /// - /// Note: `num_aux_segment_rands` refers to the random elements needed to generate all auxiliary - /// columns other than the Lagrange kernel one. - /// /// # Panics /// Panics if: /// * The width of the first trace segment is zero. @@ -203,8 +200,7 @@ impl TraceInfo { self.aux_segment_width } - /// Returns the number of random elements needed to build all auxiliary columns, except for the - /// Lagrange kernel column. + /// Returns the number of random elements needed to build all auxiliary columns. pub fn get_num_aux_segment_rand_elements(&self) -> usize { self.num_aux_segment_rands } diff --git a/air/src/lib.rs b/air/src/lib.rs index ec76e1afd..9d43daa90 100644 --- a/air/src/lib.rs +++ b/air/src/lib.rs @@ -44,9 +44,6 @@ mod air; pub use air::{ Air, AirContext, Assertion, AuxRandElements, BoundaryConstraint, BoundaryConstraintGroup, BoundaryConstraints, ConstraintCompositionCoefficients, ConstraintDivisor, - DeepCompositionCoefficients, EvaluationFrame, GkrRandElements, GkrVerifier, - LagrangeConstraintsCompositionCoefficients, LagrangeKernelBoundaryConstraint, - LagrangeKernelConstraints, LagrangeKernelEvaluationFrame, LagrangeKernelRandElements, - LagrangeKernelTransitionConstraints, TraceInfo, TransitionConstraintDegree, + DeepCompositionCoefficients, EvaluationFrame, TraceInfo, TransitionConstraintDegree, TransitionConstraints, }; diff --git a/air/src/proof/mod.rs b/air/src/proof/mod.rs index 750c15554..56e7b561e 100644 --- a/air/src/proof/mod.rs +++ b/air/src/proof/mod.rs @@ -43,10 +43,6 @@ mod tests; /// also contains basic metadata for the computation, but neither the definition of the computation /// itself, nor public inputs consumed by the computation are contained in a proof. /// -/// Optionally, it may contain a GKR proof. The GKR proof object gives the possibility to prove some -/// auxiliary trace constraints using GKR, as described in [Improving logarithmic derivative lookups -/// using GKR](https://eprint.iacr.org/2023/1284.pdf). -/// /// A proof can be serialized into a sequence of bytes using [to_bytes()](Proof::to_bytes) function, /// and deserialized from a sequence of bytes using [from_bytes()](Proof::from_bytes) function. /// @@ -73,8 +69,6 @@ pub struct Proof { pub fri_proof: FriProof, /// Proof-of-work nonce for query seed grinding. pub pow_nonce: u64, - /// Optionally, an auxiliary (non-STARK) proof that was generated during auxiliary trace generation. - pub gkr_proof: Option>, } impl Proof { @@ -158,7 +152,6 @@ impl Proof { ood_frame: OodFrame::default(), fri_proof: FriProof::new_dummy(), pow_nonce: 0, - gkr_proof: None, } } } @@ -176,7 +169,6 @@ impl Serializable for Proof { self.ood_frame.write_into(target); self.fri_proof.write_into(target); self.pow_nonce.write_into(target); - self.gkr_proof.write_into(target); } } @@ -200,7 +192,6 @@ impl Deserializable for Proof { ood_frame: OodFrame::read_from(source)?, fri_proof: FriProof::read_from(source)?, pow_nonce: source.read_u64()?, - gkr_proof: Option::>::read_from(source)?, }; Ok(proof) } diff --git a/air/src/proof/ood_frame.rs b/air/src/proof/ood_frame.rs index ca9e896f6..629175710 100644 --- a/air/src/proof/ood_frame.rs +++ b/air/src/proof/ood_frame.rs @@ -11,7 +11,7 @@ use utils::{ ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, SliceReader, }; -use crate::{EvaluationFrame, LagrangeKernelEvaluationFrame}; +use crate::EvaluationFrame; // OUT-OF-DOMAIN FRAME // ================================================================================================ @@ -21,8 +21,6 @@ use crate::{EvaluationFrame, LagrangeKernelEvaluationFrame}; /// This struct contains the following evaluations: /// * Evaluations of all trace polynomials at *z*. /// * Evaluations of all trace polynomials at *z * g*. -/// * Evaluations of Lagrange kernel trace polynomial (if any) at *z*, *z * g*, *z * g^2*, ..., -/// *z * g^(2^(v-1))*, where `v == log(trace_len)` /// * Evaluations of constraint composition column polynomials at *z*. /// /// where *z* is an out-of-domain point and *g* is the generator of the trace domain. @@ -32,7 +30,6 @@ use crate::{EvaluationFrame, LagrangeKernelEvaluationFrame}; #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct OodFrame { trace_states: Vec, - lagrange_kernel_trace_states: Vec, evaluations: Vec, } @@ -67,26 +64,15 @@ impl OodFrame { { assert!(self.trace_states.is_empty(), "trace sates have already been set"); - // save the evaluations of the current and then next evaluations for each polynomial - let (main_and_aux_trace_states, lagrange_trace_states) = trace_ood_frame.to_trace_states(); + // save the evaluations with the current and next evaluations interleaved for each polynomial + let main_and_aux_trace_states = trace_ood_frame.to_trace_states(); // there are 2 frames: current and next let frame_size: u8 = 2; self.trace_states.write_u8(frame_size); self.trace_states.write_many(&main_and_aux_trace_states); - // save the Lagrange kernel evaluation frame (if any) - { - // trace states length will be smaller than u8::MAX, since it is `== log2(trace_len) + 1` - debug_assert!(lagrange_trace_states.len() < u8::MAX.into()); - self.lagrange_kernel_trace_states.write_u8(lagrange_trace_states.len() as u8); - self.lagrange_kernel_trace_states.write_many(&lagrange_trace_states); - }; - - let elements_to_hash: Vec = - main_and_aux_trace_states.into_iter().chain(lagrange_trace_states).collect(); - - H::hash_elements(&elements_to_hash) + H::hash_elements(&main_and_aux_trace_states) } /// Updates constraint evaluation portion of this out-of-domain frame. @@ -125,20 +111,6 @@ impl OodFrame { assert!(main_trace_width > 0, "trace width cannot be zero"); assert!(num_evaluations > 0, "number of evaluations cannot be zero"); - // parse Lagrange kernel column trace, if any - let mut reader = SliceReader::new(&self.lagrange_kernel_trace_states); - let lagrange_kernel_frame_size = reader.read_u8()? as usize; - let lagrange_kernel_frame = if lagrange_kernel_frame_size > 0 { - let lagrange_kernel_trace = reader.read_many(lagrange_kernel_frame_size)?; - - Some(LagrangeKernelEvaluationFrame::new(lagrange_kernel_trace)) - } else { - None - }; - - // if there is a Lagrange kernel, we treat its associated entries separately above - let aux_trace_width = aux_trace_width - (lagrange_kernel_frame.is_some() as usize); - // parse main and auxiliary trace evaluation frames. This does the reverse operation done in // `set_trace_states()`. let (current_row, next_row) = { @@ -162,10 +134,7 @@ impl OodFrame { return Err(DeserializationError::UnconsumedBytes); } - Ok(( - TraceOodFrame::new(current_row, next_row, main_trace_width, lagrange_kernel_frame), - evaluations, - )) + Ok((TraceOodFrame::new(current_row, next_row, main_trace_width), evaluations)) } } @@ -179,10 +148,6 @@ impl Serializable for OodFrame { target.write_u16(self.trace_states.len() as u16); target.write_bytes(&self.trace_states); - // write Lagrange kernel column trace rows - target.write_u16(self.lagrange_kernel_trace_states.len() as u16); - target.write_bytes(&self.lagrange_kernel_trace_states); - // write constraint evaluations row target.write_u16(self.evaluations.len() as u16); target.write_bytes(&self.evaluations) @@ -204,19 +169,11 @@ impl Deserializable for OodFrame { let num_trace_state_bytes = source.read_u16()? as usize; let trace_states = source.read_vec(num_trace_state_bytes)?; - // read Lagrange kernel column trace rows - let num_lagrange_state_bytes = source.read_u16()? as usize; - let lagrange_kernel_trace_states = source.read_vec(num_lagrange_state_bytes)?; - // read constraint evaluations row let num_constraint_evaluation_bytes = source.read_u16()? as usize; let evaluations = source.read_vec(num_constraint_evaluation_bytes)?; - Ok(OodFrame { - trace_states, - lagrange_kernel_trace_states, - evaluations, - }) + Ok(OodFrame { trace_states, evaluations }) } } @@ -227,33 +184,18 @@ impl Deserializable for OodFrame { /// /// Stores the trace evaluations at `z` and `gz`, where `z` is a random Field element in /// `current_row` and `next_row`, respectively. -/// -/// If the Air contains a Lagrange kernel auxiliary column, then that column interpolated polynomial -/// will be evaluated at `z`, `gz`, `g^2 z`, ... `g^(2^(v-1)) z`, where `v == log(trace_len)`, and -/// stored in `lagrange_kernel_frame`. pub struct TraceOodFrame { current_row: Vec, next_row: Vec, main_trace_width: usize, - lagrange_kernel_frame: Option>, } impl TraceOodFrame { - /// Creates a new [`TraceOodFrame`] from current, next and optionally Lagrange kernel frames. - pub fn new( - current_row: Vec, - next_row: Vec, - main_trace_width: usize, - lagrange_kernel_frame: Option>, - ) -> Self { + /// Creates a new [`TraceOodFrame`] from current, next. + pub fn new(current_row: Vec, next_row: Vec, main_trace_width: usize) -> Self { assert_eq!(current_row.len(), next_row.len()); - Self { - current_row, - next_row, - main_trace_width, - lagrange_kernel_frame, - } + Self { current_row, next_row, main_trace_width } } /// Returns the number of columns for the current and next frames. @@ -291,37 +233,26 @@ impl TraceOodFrame { } } - /// Hashes the main, auxiliary and Lagrange kernel frame in a manner consistent with + /// Hashes the main, auxiliary frames in a manner consistent with /// [`OodFrame::set_trace_states`], with the purpose of reseeding the public coin. pub fn hash>(&self) -> H::Digest { - let (mut trace_states, mut lagrange_trace_states) = self.to_trace_states(); - trace_states.append(&mut lagrange_trace_states); + let trace_states = self.to_trace_states(); H::hash_elements(&trace_states) } - /// Returns the Lagrange kernel frame, if any. - pub fn lagrange_kernel_frame(&self) -> Option<&LagrangeKernelEvaluationFrame> { - self.lagrange_kernel_frame.as_ref() - } - /// Returns true if an auxiliary frame is present fn has_aux_frame(&self) -> bool { self.current_row.len() > self.main_trace_width } - /// Returns the main/aux frame and Lagrange kernel frame as element vectors as described in - /// [`OodFrame::set_trace_states`]. - fn to_trace_states(&self) -> (Vec, Vec) { + /// Returns the main/aux frames as element vectors. Specifically, the main and auxiliary frames + /// are interleaved, as described in [`OodFrame::set_trace_states`]. + fn to_trace_states(&self) -> Vec { let mut main_and_aux_frame_states = Vec::new(); main_and_aux_frame_states.extend_from_slice(&self.current_row); main_and_aux_frame_states.extend_from_slice(&self.next_row); - let lagrange_frame_states = match self.lagrange_kernel_frame { - Some(ref lagrange_kernel_frame) => lagrange_kernel_frame.inner().to_vec(), - None => Vec::new(), - }; - - (main_and_aux_frame_states, lagrange_frame_states) + main_and_aux_frame_states } } diff --git a/examples/src/fibonacci/fib2/air.rs b/examples/src/fibonacci/fib2/air.rs index 9e5d75a48..7b0b866f5 100644 --- a/examples/src/fibonacci/fib2/air.rs +++ b/examples/src/fibonacci/fib2/air.rs @@ -21,8 +21,6 @@ pub struct FibAir { impl Air for FibAir { type BaseField = BaseElement; type PublicInputs = BaseElement; - type GkrProof = (); - type GkrVerifier = (); // CONSTRUCTOR // -------------------------------------------------------------------------------------------- diff --git a/examples/src/fibonacci/fib8/air.rs b/examples/src/fibonacci/fib8/air.rs index 4d7aef9ba..136978f6c 100644 --- a/examples/src/fibonacci/fib8/air.rs +++ b/examples/src/fibonacci/fib8/air.rs @@ -22,8 +22,6 @@ pub struct Fib8Air { impl Air for Fib8Air { type BaseField = BaseElement; type PublicInputs = BaseElement; - type GkrProof = (); - type GkrVerifier = (); // CONSTRUCTOR // -------------------------------------------------------------------------------------------- diff --git a/examples/src/fibonacci/fib_small/air.rs b/examples/src/fibonacci/fib_small/air.rs index 66580c872..9a6a8bddb 100644 --- a/examples/src/fibonacci/fib_small/air.rs +++ b/examples/src/fibonacci/fib_small/air.rs @@ -21,8 +21,6 @@ pub struct FibSmall { impl Air for FibSmall { type BaseField = BaseElement; type PublicInputs = BaseElement; - type GkrProof = (); - type GkrVerifier = (); // CONSTRUCTOR // -------------------------------------------------------------------------------------------- diff --git a/examples/src/fibonacci/mulfib2/air.rs b/examples/src/fibonacci/mulfib2/air.rs index 3190d2e41..b7d408833 100644 --- a/examples/src/fibonacci/mulfib2/air.rs +++ b/examples/src/fibonacci/mulfib2/air.rs @@ -23,8 +23,6 @@ pub struct MulFib2Air { impl Air for MulFib2Air { type BaseField = BaseElement; type PublicInputs = BaseElement; - type GkrProof = (); - type GkrVerifier = (); // CONSTRUCTOR // -------------------------------------------------------------------------------------------- diff --git a/examples/src/fibonacci/mulfib8/air.rs b/examples/src/fibonacci/mulfib8/air.rs index bbbe1dea0..8ba25e115 100644 --- a/examples/src/fibonacci/mulfib8/air.rs +++ b/examples/src/fibonacci/mulfib8/air.rs @@ -23,8 +23,6 @@ pub struct MulFib8Air { impl Air for MulFib8Air { type BaseField = BaseElement; type PublicInputs = BaseElement; - type GkrProof = (); - type GkrVerifier = (); // CONSTRUCTOR // -------------------------------------------------------------------------------------------- diff --git a/examples/src/lamport/aggregate/air.rs b/examples/src/lamport/aggregate/air.rs index 29b6e2372..ce14e6ea5 100644 --- a/examples/src/lamport/aggregate/air.rs +++ b/examples/src/lamport/aggregate/air.rs @@ -46,8 +46,6 @@ pub struct LamportAggregateAir { impl Air for LamportAggregateAir { type BaseField = BaseElement; type PublicInputs = PublicInputs; - type GkrProof = (); - type GkrVerifier = (); // CONSTRUCTOR // -------------------------------------------------------------------------------------------- diff --git a/examples/src/lamport/threshold/air.rs b/examples/src/lamport/threshold/air.rs index 41983c743..9fd749b4a 100644 --- a/examples/src/lamport/threshold/air.rs +++ b/examples/src/lamport/threshold/air.rs @@ -51,8 +51,6 @@ pub struct LamportThresholdAir { impl Air for LamportThresholdAir { type BaseField = BaseElement; type PublicInputs = PublicInputs; - type GkrProof = (); - type GkrVerifier = (); // CONSTRUCTOR // -------------------------------------------------------------------------------------------- diff --git a/examples/src/merkle/air.rs b/examples/src/merkle/air.rs index e0c8b177c..ac7ff2d89 100644 --- a/examples/src/merkle/air.rs +++ b/examples/src/merkle/air.rs @@ -32,8 +32,6 @@ pub struct MerkleAir { impl Air for MerkleAir { type BaseField = BaseElement; type PublicInputs = PublicInputs; - type GkrProof = (); - type GkrVerifier = (); // CONSTRUCTOR // -------------------------------------------------------------------------------------------- diff --git a/examples/src/rescue/air.rs b/examples/src/rescue/air.rs index a9d3d5ebb..5e806297a 100644 --- a/examples/src/rescue/air.rs +++ b/examples/src/rescue/air.rs @@ -59,8 +59,6 @@ pub struct RescueAir { impl Air for RescueAir { type BaseField = BaseElement; type PublicInputs = PublicInputs; - type GkrProof = (); - type GkrVerifier = (); // CONSTRUCTOR // -------------------------------------------------------------------------------------------- diff --git a/examples/src/rescue_raps/air.rs b/examples/src/rescue_raps/air.rs index 6fb5321b1..d7d7c1f8f 100644 --- a/examples/src/rescue_raps/air.rs +++ b/examples/src/rescue_raps/air.rs @@ -59,8 +59,6 @@ pub struct RescueRapsAir { impl Air for RescueRapsAir { type BaseField = BaseElement; type PublicInputs = PublicInputs; - type GkrProof = (); - type GkrVerifier = (); // CONSTRUCTOR // -------------------------------------------------------------------------------------------- @@ -80,7 +78,6 @@ impl Air for RescueRapsAir { aux_degrees, 8, 2, - None, options, ), result: pub_inputs.result, diff --git a/examples/src/vdf/exempt/air.rs b/examples/src/vdf/exempt/air.rs index 9254e4e0a..bac93c30d 100644 --- a/examples/src/vdf/exempt/air.rs +++ b/examples/src/vdf/exempt/air.rs @@ -37,8 +37,6 @@ pub struct VdfAir { impl Air for VdfAir { type BaseField = BaseElement; type PublicInputs = VdfInputs; - type GkrProof = (); - type GkrVerifier = (); fn new(trace_info: TraceInfo, pub_inputs: VdfInputs, options: ProofOptions) -> Self { let degrees = vec![TransitionConstraintDegree::new(3)]; diff --git a/examples/src/vdf/regular/air.rs b/examples/src/vdf/regular/air.rs index b434c1478..813f7261d 100644 --- a/examples/src/vdf/regular/air.rs +++ b/examples/src/vdf/regular/air.rs @@ -37,8 +37,6 @@ pub struct VdfAir { impl Air for VdfAir { type BaseField = BaseElement; type PublicInputs = VdfInputs; - type GkrProof = (); - type GkrVerifier = (); fn new(trace_info: TraceInfo, pub_inputs: VdfInputs, options: ProofOptions) -> Self { let degrees = vec![TransitionConstraintDegree::new(3)]; diff --git a/math/Cargo.toml b/math/Cargo.toml index 987dc6da4..55d5343bd 100644 --- a/math/Cargo.toml +++ b/math/Cargo.toml @@ -27,10 +27,6 @@ harness = false name = "polynom" harness = false -[[bench]] -name = "poly_div_lagrange" -harness = false - [features] concurrent = ["utils/concurrent", "std"] default = ["std"] diff --git a/math/benches/poly_div_lagrange.rs b/math/benches/poly_div_lagrange.rs deleted file mode 100644 index beffba262..000000000 --- a/math/benches/poly_div_lagrange.rs +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. -// -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -use std::time::Duration; - -use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; -use rand_utils::{rand_value, rand_vector}; -use winter_math::{ - fields::{f64::BaseElement, QuadExtension}, - polynom::{self, eval_many, syn_div_roots_in_place}, - ExtensionOf, StarkField, -}; - -const TRACE_LENS: [usize; 4] = [2_usize.pow(16), 2_usize.pow(18), 2_usize.pow(20), 2_usize.pow(22)]; - -fn polynomial_division_naive(c: &mut Criterion) { - let mut group = c.benchmark_group("Naive polynomial division"); - group.sample_size(10); - group.measurement_time(Duration::from_secs(20)); - - for &trace_len in TRACE_LENS.iter() { - group.bench_function(BenchmarkId::new("prover", trace_len), |b| { - let poly: Vec> = rand_vector(trace_len); - let z: QuadExtension = rand_value(); - let log_trace_len = trace_len.ilog2(); - let g: BaseElement = BaseElement::get_root_of_unity(log_trace_len); - let mut xs = Vec::with_capacity(log_trace_len as usize + 1); - - // push z - xs.push(z); - - // compute the values (z * g), (z * g^2), (z * g^4), ..., (z * g^(2^(v-1))) - let mut g_exp = g; - for _ in 0..log_trace_len { - let x = z.mul_base(g_exp); - xs.push(x); - g_exp *= g_exp; - } - let ood_evaluations = eval_many(&poly, &xs); - - let p_s = polynom::interpolate(&xs, &ood_evaluations, true); - let numerator = polynom::sub(&poly, &p_s); - let z_s = polynom::poly_from_roots(&xs); - - b.iter_batched( - || { - let numerator = numerator.clone(); - let z_s = z_s.clone(); - (numerator, z_s) - }, - |(numerator, z_s)| polynom::div(&numerator, &z_s), - BatchSize::SmallInput, - ) - }); - } -} - -fn polynomial_division_synthetic(c: &mut Criterion) { - let mut group = c.benchmark_group("Synthetic polynomial division"); - group.sample_size(10); - group.measurement_time(Duration::from_secs(20)); - - for &trace_len in TRACE_LENS.iter() { - group.bench_function(BenchmarkId::new("prover", trace_len), |b| { - let poly: Vec> = rand_vector(trace_len); - let z: QuadExtension = rand_value(); - let log_trace_len = trace_len.ilog2(); - let g: BaseElement = BaseElement::get_root_of_unity(log_trace_len); - let mut xs = Vec::with_capacity(log_trace_len as usize + 1); - - // push z - xs.push(z); - - // compute the values (z * g), (z * g^2), (z * g^4), ..., (z * g^(2^(v-1))) - let mut g_exp = g; - for _ in 0..log_trace_len { - let x = z.mul_base(g_exp); - xs.push(x); - g_exp *= g_exp; - } - let ood_evaluations = eval_many(&poly, &xs); - - let p_s = polynom::interpolate(&xs, &ood_evaluations, true); - let numerator = polynom::sub(&poly, &p_s); - - b.iter_batched( - || { - let numerator = numerator.clone(); - let xs = xs.clone(); - (numerator, xs) - }, - |(mut numerator, xs)| syn_div_roots_in_place(&mut numerator, &xs), - BatchSize::SmallInput, - ) - }); - } -} - -criterion_group!(poly_division, polynomial_division_naive, polynomial_division_synthetic); -criterion_main!(poly_division); diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 1011c3504..dd2a4ce3b 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -19,10 +19,6 @@ bench = false name = "row_matrix" harness = false -[[bench]] -name = "lagrange_kernel" -harness = false - [features] async = ["maybe_async/async"] concurrent = ["crypto/concurrent", "math/concurrent", "fri/concurrent", "utils/concurrent", "std"] diff --git a/prover/benches/lagrange_kernel.rs b/prover/benches/lagrange_kernel.rs deleted file mode 100644 index bef5de366..000000000 --- a/prover/benches/lagrange_kernel.rs +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. -// -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -use std::time::Duration; - -use air::{ - Air, AirContext, Assertion, AuxRandElements, BatchingMethod, ConstraintCompositionCoefficients, - EvaluationFrame, FieldExtension, GkrRandElements, LagrangeKernelRandElements, PartitionOptions, - ProofOptions, TraceInfo, TransitionConstraintDegree, -}; -use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; -use crypto::{hashers::Blake3_256, DefaultRandomCoin, MerkleTree, RandomCoin}; -use math::{fields::f64::BaseElement, ExtensionOf, FieldElement}; -use winter_prover::{ - matrix::ColMatrix, CompositionPoly, CompositionPolyTrace, DefaultConstraintCommitment, - DefaultConstraintEvaluator, DefaultTraceLde, Prover, ProverGkrProof, StarkDomain, Trace, - TracePolyTable, -}; - -const TRACE_LENS: [usize; 2] = [2_usize.pow(16), 2_usize.pow(20)]; -const AUX_TRACE_WIDTH: usize = 2; - -fn prove_with_lagrange_kernel(c: &mut Criterion) { - let mut group = c.benchmark_group("Lagrange kernel column"); - group.sample_size(10); - group.measurement_time(Duration::from_secs(20)); - - for &trace_len in TRACE_LENS.iter() { - group.bench_function(BenchmarkId::new("prover", trace_len), |b| { - let trace = LagrangeTrace::new(trace_len, AUX_TRACE_WIDTH); - let prover = LagrangeProver::new(AUX_TRACE_WIDTH); - b.iter_batched( - || trace.clone(), - |trace| prover.prove(trace).unwrap(), - BatchSize::SmallInput, - ) - }); - } -} - -criterion_group!(lagrange_kernel_group, prove_with_lagrange_kernel); -criterion_main!(lagrange_kernel_group); - -// TRACE -// ================================================================================================= - -#[derive(Clone, Debug)] -struct LagrangeTrace { - // dummy main trace - main_trace: ColMatrix, - info: TraceInfo, -} - -impl LagrangeTrace { - fn new(trace_len: usize, aux_segment_width: usize) -> Self { - assert!(trace_len < u32::MAX.try_into().unwrap()); - - let main_trace_col: Vec = - (0..trace_len).map(|idx| BaseElement::from(idx as u32)).collect(); - - Self { - main_trace: ColMatrix::new(vec![main_trace_col]), - info: TraceInfo::new_multi_segment(1, aux_segment_width, 0, trace_len, vec![]), - } - } - - fn len(&self) -> usize { - self.main_trace.num_rows() - } -} - -impl Trace for LagrangeTrace { - type BaseField = BaseElement; - - fn info(&self) -> &TraceInfo { - &self.info - } - - fn main_segment(&self) -> &ColMatrix { - &self.main_trace - } - - fn read_main_frame(&self, row_idx: usize, frame: &mut air::EvaluationFrame) { - let next_row_idx = row_idx + 1; - assert_ne!(next_row_idx, self.len()); - - self.main_trace.read_row_into(row_idx, frame.current_mut()); - self.main_trace.read_row_into(next_row_idx, frame.next_mut()); - } -} - -// AIR -// ================================================================================================= - -struct LagrangeKernelAir { - context: AirContext, -} - -impl Air for LagrangeKernelAir { - type BaseField = BaseElement; - type GkrProof = (); - type GkrVerifier = (); - - type PublicInputs = (); - - fn new(trace_info: TraceInfo, _pub_inputs: Self::PublicInputs, options: ProofOptions) -> Self { - Self { - context: AirContext::new_multi_segment( - trace_info, - vec![TransitionConstraintDegree::new(1)], - vec![TransitionConstraintDegree::new(1)], - 1, - 1, - Some(0), - options, - ), - } - } - - fn context(&self) -> &AirContext { - &self.context - } - - fn evaluate_transition>( - &self, - frame: &EvaluationFrame, - _periodic_values: &[E], - result: &mut [E], - ) { - let current = frame.current()[0]; - let next = frame.next()[0]; - - // increments by 1 - result[0] = next - current - E::ONE; - } - - fn get_assertions(&self) -> Vec> { - vec![Assertion::single(0, 0, BaseElement::ZERO)] - } - - fn evaluate_aux_transition( - &self, - _main_frame: &EvaluationFrame, - _aux_frame: &EvaluationFrame, - _periodic_values: &[F], - _aux_rand_elements: &AuxRandElements, - _result: &mut [E], - ) where - F: FieldElement, - E: FieldElement + ExtensionOf, - { - // do nothing - } - - fn get_aux_assertions>( - &self, - _aux_rand_elements: &AuxRandElements, - ) -> Vec> { - vec![Assertion::single(1, 0, E::ZERO)] - } -} - -// LagrangeProver -// ================================================================================================ - -struct LagrangeProver { - aux_trace_width: usize, - options: ProofOptions, -} - -impl LagrangeProver { - fn new(aux_trace_width: usize) -> Self { - Self { - aux_trace_width, - options: ProofOptions::new(1, 2, 0, FieldExtension::None, 2, 1, BatchingMethod::Linear), - } - } -} - -impl Prover for LagrangeProver { - type BaseField = BaseElement; - type Air = LagrangeKernelAir; - type Trace = LagrangeTrace; - type HashFn = Blake3_256; - type VC = MerkleTree>; - type RandomCoin = DefaultRandomCoin; - type TraceLde> = - DefaultTraceLde; - type ConstraintCommitment> = - DefaultConstraintCommitment; - type ConstraintEvaluator<'a, E: FieldElement> = - DefaultConstraintEvaluator<'a, LagrangeKernelAir, E>; - - fn get_pub_inputs(&self, _trace: &Self::Trace) -> <::Air as Air>::PublicInputs { - } - - fn options(&self) -> &ProofOptions { - &self.options - } - - fn new_trace_lde( - &self, - trace_info: &TraceInfo, - main_trace: &ColMatrix, - domain: &StarkDomain, - partition_option: PartitionOptions, - ) -> (Self::TraceLde, TracePolyTable) - where - E: math::FieldElement, - { - DefaultTraceLde::new(trace_info, main_trace, domain, partition_option) - } - - fn build_constraint_commitment>( - &self, - composition_poly_trace: CompositionPolyTrace, - num_constraint_composition_columns: usize, - domain: &StarkDomain, - partition_options: PartitionOptions, - ) -> (Self::ConstraintCommitment, CompositionPoly) { - DefaultConstraintCommitment::new( - composition_poly_trace, - num_constraint_composition_columns, - domain, - partition_options, - ) - } - - fn new_evaluator<'a, E>( - &self, - air: &'a Self::Air, - aux_rand_elements: Option>, - composition_coefficients: ConstraintCompositionCoefficients, - ) -> Self::ConstraintEvaluator<'a, E> - where - E: math::FieldElement, - { - DefaultConstraintEvaluator::new(air, aux_rand_elements, composition_coefficients) - } - - fn generate_gkr_proof( - &self, - main_trace: &Self::Trace, - public_coin: &mut Self::RandomCoin, - ) -> (ProverGkrProof, GkrRandElements) - where - E: FieldElement, - { - let main_trace = main_trace.main_segment(); - let lagrange_kernel_rand_elements = { - let log_trace_len = main_trace.num_rows().ilog2() as usize; - let mut rand_elements = Vec::with_capacity(log_trace_len); - for _ in 0..log_trace_len { - rand_elements.push(public_coin.draw().unwrap()); - } - - LagrangeKernelRandElements::new(rand_elements) - }; - - ((), GkrRandElements::new(lagrange_kernel_rand_elements, Vec::new())) - } - - fn build_aux_trace( - &self, - main_trace: &Self::Trace, - aux_rand_elements: &AuxRandElements, - ) -> ColMatrix - where - E: FieldElement, - { - let main_trace = main_trace.main_segment(); - let mut columns = Vec::new(); - - let lagrange_kernel_rand_elements = aux_rand_elements - .lagrange() - .expect("expected lagrange kernel random elements to be present."); - - // first build the Lagrange kernel column - { - let r = lagrange_kernel_rand_elements; - let mut lagrange_col = Vec::with_capacity(main_trace.num_rows()); - - for row_idx in 0..main_trace.num_rows() { - let mut row_value = E::ONE; - for (bit_idx, &r_i) in r.iter().enumerate() { - if row_idx & (1 << bit_idx) == 0 { - row_value *= E::ONE - r_i; - } else { - row_value *= r_i; - } - } - lagrange_col.push(row_value); - } - - columns.push(lagrange_col); - } - - // Then all other auxiliary columns - let rand_summed = lagrange_kernel_rand_elements.iter().fold(E::ZERO, |acc, &r| acc + r); - for _ in 1..self.aux_trace_width { - // building a dummy auxiliary column - let column = main_trace - .get_column(0) - .iter() - .map(|row_val| rand_summed.mul_base(*row_val)) - .collect(); - - columns.push(column); - } - - ColMatrix::new(columns) - } -} diff --git a/prover/src/channel.rs b/prover/src/channel.rs index db82f5095..ab8ff0daa 100644 --- a/prover/src/channel.rs +++ b/prover/src/channel.rs @@ -182,7 +182,6 @@ where constraint_queries: Queries, fri_proof: FriProof, num_query_positions: usize, - gkr_proof: Option>, ) -> Proof { assert!(num_query_positions <= u8::MAX as usize, "num_query_positions too big"); @@ -195,7 +194,6 @@ where fri_proof, pow_nonce: self.pow_nonce, num_unique_queries: num_query_positions as u8, - gkr_proof, } } } diff --git a/prover/src/composer/mod.rs b/prover/src/composer/mod.rs index 5d463d331..74bb15c9b 100644 --- a/prover/src/composer/mod.rs +++ b/prover/src/composer/mod.rs @@ -7,7 +7,7 @@ use alloc::vec::Vec; use air::{proof::TraceOodFrame, DeepCompositionCoefficients}; use math::{ add_in_place, fft, mul_acc, - polynom::{self, syn_div_roots_in_place}, + polynom::{self}, ExtensionOf, FieldElement, StarkField, }; use utils::iter_mut; @@ -58,20 +58,9 @@ impl DeepCompositionPoly { /// - Then, combine together all T'_i(x) and T''_i(x) polynomials using a random linear /// combination as T(x) = sum((T'_i(x) + T''_i(x)) * cc_i) for all i, where cc_i is /// the coefficient for the random linear combination drawn from the public coin. - /// - If a Lagrange kernel is present, combine one additional term defined as - /// (T_l(x) - p_S(x)) / Z_S(x), where: - /// - /// 1. $T_l(x) is the evaluation of the Lagrange trace polynomial at $x$. - /// 2. $S$ is the set of opening points for the Lagrange kernel i.e., - /// $S := {z, z.g, z.g^2, ..., z.g^{2^{log_2(\nu) - 1}}}$. - /// 3. $p_S(X)$ is the polynomial of minimal degree interpolating the set - /// ${(a, T_l(a)): a \in S}$. - /// 4. $Z_S(X)$ is the polynomial of minimal degree vanishing over the set $S$. /// /// Note that evaluations of T_i(z) and T_i(z * g) are passed in via the `ood_trace_state` /// parameter. - /// If a Lagrange kernel is present, the evaluations of $T_l$ over the set $S$ are provided - /// separately via `ood_trace_state`. pub fn add_trace_polys( &mut self, trace_polys: TracePolyTable, @@ -142,47 +131,9 @@ impl DeepCompositionPoly { // divide the composition polynomials by (x - z) and (x - z * g), respectively, // and add the resulting polynomials together; the output of this step // is a single trace polynomial T(x) and deg(T(x)) = trace_length - 2. - let mut trace_poly = + let trace_poly = merge_trace_compositions(vec![t1_composition, t2_composition], vec![self.z, next_z]); - // finally compose the final term associated to the Lagrange kernel trace polynomial if - // there is one present. - // TODO: Investigate using FFT to speed up this block (see #281). - if let Some(poly) = trace_polys.lagrange_kernel_poly() { - let ood_eval_frame = ood_trace_states.lagrange_kernel_frame().expect( - "should contain OOD values for Lagrange kernel trace polynomial if we are here", - ); - - let log_trace_len = poly.len().ilog2(); - let g = E::from(E::BaseField::get_root_of_unity(log_trace_len)); - let mut xs = Vec::with_capacity(log_trace_len as usize + 1); - - // push z - xs.push(self.z); - - // compute the values (z * g), (z * g^2), (z * g^4), ..., (z * g^(2^(v-1))) - let mut g_exp = g; - for _ in 0..log_trace_len { - let x = g_exp * self.z; - xs.push(x); - g_exp *= g_exp; - } - - // compute the numerator - let p_s = polynom::interpolate(&xs, ood_eval_frame.inner(), true); - let mut numerator = polynom::sub(poly, &p_s); - - // divide by the zero polynomial of the set S - syn_div_roots_in_place(&mut numerator, &xs); - - // multiply by constraint composition randomness - let quotient = numerator; - let scaled_with_randomness = - polynom::mul_by_scalar("ient, self.cc.lagrange.unwrap()); - - trace_poly = polynom::add(&scaled_with_randomness, &trace_poly); - }; - // set the coefficients of the DEEP composition polynomial self.coefficients = trace_poly; assert_eq!(self.poly_size() - 2, self.degree()); diff --git a/prover/src/constraints/evaluator/default.rs b/prover/src/constraints/evaluator/default.rs index a8ded6412..f9129ef79 100644 --- a/prover/src/constraints/evaluator/default.rs +++ b/prover/src/constraints/evaluator/default.rs @@ -13,9 +13,8 @@ use utils::iter_mut; use utils::{iterators::*, rayon}; use super::{ - super::EvaluationTableFragment, lagrange::LagrangeKernelConstraintsBatchEvaluator, - BoundaryConstraints, CompositionPolyTrace, ConstraintEvaluationTable, ConstraintEvaluator, - PeriodicValueTable, StarkDomain, TraceLde, + super::EvaluationTableFragment, BoundaryConstraints, CompositionPolyTrace, + ConstraintEvaluationTable, ConstraintEvaluator, PeriodicValueTable, StarkDomain, TraceLde, }; // CONSTANTS @@ -40,7 +39,6 @@ pub struct DefaultConstraintEvaluator<'a, A: Air, E: FieldElement, transition_constraints: TransitionConstraints, - lagrange_constraints_evaluator: Option>, aux_rand_elements: Option>, periodic_values: PeriodicValueTable, } @@ -116,16 +114,7 @@ where #[cfg(debug_assertions)] evaluation_table.validate_transition_degrees(); - // combine all constraint evaluations into a single column, including the evaluations of the - // Lagrange kernel constraints (if present) - let combined_evaluations = { - let mut constraints_evaluations = evaluation_table.combine(); - self.evaluate_lagrange_kernel_constraints(trace, domain, &mut constraints_evaluations); - - constraints_evaluations - }; - - CompositionPolyTrace::new(combined_evaluations) + CompositionPolyTrace::new(evaluation_table.combine()) } } @@ -158,28 +147,10 @@ where &composition_coefficients.boundary, ); - let lagrange_constraints_evaluator = if air.context().has_lagrange_kernel_aux_column() { - let aux_rand_elements = - aux_rand_elements.as_ref().expect("expected aux rand elements to be present"); - let lagrange_rand_elements = aux_rand_elements - .lagrange() - .expect("expected lagrange rand elements to be present"); - Some(LagrangeKernelConstraintsBatchEvaluator::new( - air, - lagrange_rand_elements.clone(), - composition_coefficients - .lagrange - .expect("expected Lagrange kernel composition coefficients to be present"), - )) - } else { - None - }; - DefaultConstraintEvaluator { air, boundary_constraints, transition_constraints, - lagrange_constraints_evaluator, aux_rand_elements, periodic_values, } @@ -295,29 +266,6 @@ where } } - /// If present, evaluates the Lagrange kernel constraints over the constraint evaluation domain. - /// The evaluation of each constraint (both boundary and transition) is divided by its divisor, - /// multiplied by its composition coefficient, the result of which is added to - /// `combined_evaluations_accumulator`. - /// - /// Specifically, `combined_evaluations_accumulator` is a buffer whose length is the size of the - /// constraint evaluation domain, where each index contains combined evaluations of other - /// constraints in the system. - fn evaluate_lagrange_kernel_constraints>( - &self, - trace: &T, - domain: &StarkDomain, - combined_evaluations_accumulator: &mut [E], - ) { - if let Some(ref lagrange_constraints_evaluator) = self.lagrange_constraints_evaluator { - lagrange_constraints_evaluator.evaluate_constraints( - trace, - domain, - combined_evaluations_accumulator, - ) - } - } - // TRANSITION CONSTRAINT EVALUATORS // -------------------------------------------------------------------------------------------- diff --git a/prover/src/constraints/evaluator/lagrange.rs b/prover/src/constraints/evaluator/lagrange.rs deleted file mode 100644 index 89d07f62c..000000000 --- a/prover/src/constraints/evaluator/lagrange.rs +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. -// -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -use alloc::vec::Vec; - -use air::{ - Air, LagrangeConstraintsCompositionCoefficients, LagrangeKernelConstraints, - LagrangeKernelEvaluationFrame, LagrangeKernelRandElements, -}; -use math::{batch_inversion, FieldElement}; - -use crate::{StarkDomain, TraceLde}; - -/// Contains a specific strategy for evaluating the Lagrange kernel boundary and transition -/// constraints where the divisors' evaluation is batched. -/// -/// Specifically, [`batch_inversion`] is used to reduce the number of divisions performed. -pub struct LagrangeKernelConstraintsBatchEvaluator { - lagrange_kernel_constraints: LagrangeKernelConstraints, - rand_elements: LagrangeKernelRandElements, -} - -impl LagrangeKernelConstraintsBatchEvaluator { - /// Constructs a new [`LagrangeConstraintsBatchEvaluator`]. - pub fn new( - air: &A, - lagrange_kernel_rand_elements: LagrangeKernelRandElements, - lagrange_composition_coefficients: LagrangeConstraintsCompositionCoefficients, - ) -> Self - where - E: FieldElement, - { - Self { - lagrange_kernel_constraints: air - .get_lagrange_kernel_constraints( - lagrange_composition_coefficients, - &lagrange_kernel_rand_elements, - ) - .expect("expected Lagrange kernel constraints to be present"), - rand_elements: lagrange_kernel_rand_elements, - } - } - - /// Evaluates the transition and boundary constraints. Specifically, the constraint evaluations - /// are divided by their corresponding divisors, and the resulting terms are linearly combined - /// using the composition coefficients. - /// - /// Writes the evaluations in `combined_evaluations_acc` at the corresponding (constraint - /// evaluation) domain index. - pub fn evaluate_constraints( - &self, - trace: &T, - domain: &StarkDomain, - combined_evaluations_acc: &mut [E], - ) where - T: TraceLde, - { - let lde_shift = domain.ce_to_lde_blowup().trailing_zeros(); - let trans_constraints_divisors = LagrangeKernelTransitionConstraintsDivisor::new( - self.lagrange_kernel_constraints.transition.num_constraints(), - domain, - ); - let boundary_divisors_inv = self.compute_boundary_divisors_inv(domain); - - let mut frame = LagrangeKernelEvaluationFrame::new_empty(); - - for step in 0..domain.ce_domain_size() { - // compute Lagrange kernel frame - trace.read_lagrange_kernel_frame_into( - step << lde_shift, - self.lagrange_kernel_constraints.lagrange_kernel_col_idx, - &mut frame, - ); - - // Compute the combined transition and boundary constraints evaluations for this row - let combined_evaluations = { - let mut combined_evaluations = E::ZERO; - - // combine transition constraints - for trans_constraint_idx in - 0..self.lagrange_kernel_constraints.transition.num_constraints() - { - let numerator = self - .lagrange_kernel_constraints - .transition - .evaluate_ith_numerator(&frame, &self.rand_elements, trans_constraint_idx); - let inv_divisor = trans_constraints_divisors - .get_inverse_divisor_eval(trans_constraint_idx, step); - - combined_evaluations += numerator * inv_divisor; - } - - // combine boundary constraints - { - let boundary_numerator = - self.lagrange_kernel_constraints.boundary.evaluate_numerator_at(&frame); - - combined_evaluations += boundary_numerator * boundary_divisors_inv[step]; - } - - combined_evaluations - }; - - combined_evaluations_acc[step] += combined_evaluations; - } - } - - // HELPERS - // --------------------------------------------------------------------------------------------- - - /// Computes the inverse boundary divisor at every point of the constraint evaluation domain. - /// That is, returns a vector of the form `[1 / div_0, ..., 1 / div_n]`, where `div_i` is the - /// divisor for the Lagrange kernel boundary constraint at the i'th row of the constraint - /// evaluation domain. - fn compute_boundary_divisors_inv(&self, domain: &StarkDomain) -> Vec { - let mut boundary_denominator_evals = Vec::with_capacity(domain.ce_domain_size()); - for step in 0..domain.ce_domain_size() { - let domain_point = domain.get_ce_x_at(step); - let boundary_denominator = self - .lagrange_kernel_constraints - .boundary - .evaluate_denominator_at(domain_point.into()); - boundary_denominator_evals.push(boundary_denominator); - } - - batch_inversion(&boundary_denominator_evals) - } -} - -/// Holds all the transition constraint inverse divisor evaluations over the constraint evaluation -/// domain. -/// -/// [`LagrangeKernelTransitionConstraintsDivisor`] takes advantage of some structure in the -/// divisors' evaluations. Recall that the divisor for the i'th transition constraint is `x^(2^i) - -/// 1`. When substituting `x` for each value of the constraint evaluation domain, for constraints -/// `i>0`, the divisor evaluations "wrap-around" such that some values repeat. For example, -/// -/// i=0: no repetitions -/// i=1: the first half of the buffer is equal to the second half -/// i=2: each 1/4th of the buffer are equal -/// i=3: each 1/8th of the buffer are equal -/// ... -/// Therefore, we only compute the non-repeating section of the buffer in each iteration, and index -/// into it accordingly. -struct LagrangeKernelTransitionConstraintsDivisor { - divisor_evals_inv: Vec, - - // Precompute the indices into `divisors_evals_inv` of the slices that correspond to each - // transition constraint. - // - // For example, for a CE domain size `n=8`, `slice_indices_precomputes = [0, 8, 12, 14]`, such - // that transition constraint `idx` owns the range: - // idx=0: [0, 8) - // idx=1: [8, 12) - // idx=2: [12, 14) - slice_indices_precomputes: Vec, -} - -impl LagrangeKernelTransitionConstraintsDivisor { - pub fn new( - num_lagrange_transition_constraints: usize, - domain: &StarkDomain, - ) -> Self { - let divisor_evals_inv = { - let divisor_evaluator = TransitionDivisorEvaluator::::new( - num_lagrange_transition_constraints, - domain.offset(), - ); - - // The number of divisor evaluations is - // `ce_domain_size + ce_domain_size/2 + ce_domain_size/4 + ... + ce_domain_size/(log(ce_domain_size)-1)`, - // which is slightly smaller than `ce_domain_size * 2` - let mut divisor_evals: Vec = Vec::with_capacity(domain.ce_domain_size() * 2); - - for trans_constraint_idx in 0..num_lagrange_transition_constraints { - let num_non_repeating_denoms = - domain.ce_domain_size() / 2_usize.pow(trans_constraint_idx as u32); - - for step in 0..num_non_repeating_denoms { - let divisor_eval = - divisor_evaluator.evaluate_ith_divisor(trans_constraint_idx, domain, step); - - divisor_evals.push(divisor_eval.into()); - } - } - - batch_inversion(&divisor_evals) - }; - - let slice_indices_precomputes = { - let num_indices = num_lagrange_transition_constraints + 1; - let mut slice_indices_precomputes = Vec::with_capacity(num_indices); - - slice_indices_precomputes.push(0); - - let mut current_slice_len = domain.ce_domain_size(); - for i in 1..num_indices { - let next_precompute_index = slice_indices_precomputes[i - 1] + current_slice_len; - slice_indices_precomputes.push(next_precompute_index); - - current_slice_len /= 2; - } - - slice_indices_precomputes - }; - - Self { - divisor_evals_inv, - slice_indices_precomputes, - } - } - - /// Returns the evaluation `1 / divisor`, where `divisor` is the divisor for the given - /// transition constraint, at the given row of the constraint evaluation domain - pub fn get_inverse_divisor_eval(&self, trans_constraint_idx: usize, row_idx: usize) -> E { - let inv_divisors_slice_for_constraint = - self.get_transition_constraint_slice(trans_constraint_idx); - - inv_divisors_slice_for_constraint[row_idx % inv_divisors_slice_for_constraint.len()] - } - - // HELPERS - // --------------------------------------------------------------------------------------------- - - /// Returns a slice containing all the inverse divisor evaluations for the given transition - /// constraint. - fn get_transition_constraint_slice(&self, trans_constraint_idx: usize) -> &[E] { - let start = self.slice_indices_precomputes[trans_constraint_idx]; - let end = self.slice_indices_precomputes[trans_constraint_idx + 1]; - - &self.divisor_evals_inv[start..end] - } -} - -/// Encapsulates the efficient evaluation of the Lagrange kernel transition constraints divisors. -/// -/// `s` stands for the domain offset (i.e. coset shift element). The key concept in this -/// optimization is to realize that the computation of the first transition constraint divisor can -/// be reused for all the other divisors (call the evaluations `d`). -/// -/// Specifically, each subsequent transition constraint divisor evaluation is equivalent to -/// multiplying an element `d` by a fixed number. For example, the multiplier for the transition -/// constraints are: -/// -/// - transition constraint 1's multiplier: s -/// - transition constraint 2's multiplier: s^3 -/// - transition constraint 3's multiplier: s^7 -/// - transition constraint 4's multiplier: s^15 -/// - ... -/// -/// This is what `s_precomputes` stores. -/// -/// Finally, recall that the ith Lagrange kernel divisor is `x^(2^i) - 1`. -/// [`TransitionDivisorEvaluator`] is only concerned with values of `x` in the constraint evaluation -/// domain, where the j'th element is `s * g^j`, where `g` is the group generator. To understand the -/// implementation of [`Self::evaluate_ith_divisor`], plug in `x = s * g^j` into `x^(2^i) - 1`. -pub struct TransitionDivisorEvaluator { - s_precomputes: Vec, -} - -impl TransitionDivisorEvaluator { - /// Constructs a new [`TransitionDivisorEvaluator`] - pub fn new(num_lagrange_transition_constraints: usize, domain_offset: E::BaseField) -> Self { - let s_precomputes = { - // s_precomputes = [1, s, s^3, s^7, s^15, ...] (where s = domain_offset) - let mut s_precomputes = Vec::with_capacity(num_lagrange_transition_constraints); - - let mut s_exp = E::BaseField::ONE; - for _ in 0..num_lagrange_transition_constraints { - s_precomputes.push(s_exp); - s_exp = s_exp * s_exp * domain_offset; - } - - s_precomputes - }; - - Self { s_precomputes } - } - - /// Evaluates the divisor of the `trans_constraint_idx`'th transition constraint. See - /// [`TransitionDivisorEvaluator`] for a more in-depth description of the algorithm. - pub fn evaluate_ith_divisor( - &self, - trans_constraint_idx: usize, - domain: &StarkDomain, - ce_domain_step: usize, - ) -> E::BaseField { - let domain_idx = ((1 << trans_constraint_idx) * ce_domain_step) % domain.ce_domain_size(); - - self.s_precomputes[trans_constraint_idx] * domain.get_ce_x_at(domain_idx) - - E::BaseField::ONE - } -} diff --git a/prover/src/constraints/evaluator/mod.rs b/prover/src/constraints/evaluator/mod.rs index da8a166c2..2ffaa5f1f 100644 --- a/prover/src/constraints/evaluator/mod.rs +++ b/prover/src/constraints/evaluator/mod.rs @@ -14,8 +14,6 @@ pub use default::DefaultConstraintEvaluator; mod boundary; use boundary::BoundaryConstraints; -mod lagrange; - mod periodic_table; use periodic_table::PeriodicValueTable; diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 906fac8ec..d5329058e 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -45,10 +45,9 @@ extern crate alloc; pub use air::{ proof, proof::Proof, Air, AirContext, Assertion, BoundaryConstraint, BoundaryConstraintGroup, ConstraintCompositionCoefficients, ConstraintDivisor, DeepCompositionCoefficients, - EvaluationFrame, FieldExtension, LagrangeKernelRandElements, ProofOptions, TraceInfo, - TransitionConstraintDegree, + EvaluationFrame, FieldExtension, ProofOptions, TraceInfo, TransitionConstraintDegree, }; -use air::{AuxRandElements, GkrRandElements, PartitionOptions}; +use air::{AuxRandElements, PartitionOptions}; pub use crypto; use crypto::{ElementHasher, RandomCoin, VectorCommitment}; use fri::FriProver; @@ -101,9 +100,6 @@ pub mod tests; // this segment width seems to give the best performance for small fields (i.e., 64 bits) const DEFAULT_SEGMENT_WIDTH: usize = 8; -/// Accesses the `GkrProof` type in a [`Prover`]. -pub type ProverGkrProof

= <

::Air as Air>::GkrProof; - /// Defines a STARK prover for a computation. /// /// A STARK prover can be used to generate STARK proofs. The prover contains definitions of a @@ -229,20 +225,6 @@ pub trait Prover { // PROVIDED METHODS // -------------------------------------------------------------------------------------------- - /// Builds the GKR proof. If the [`Air`] doesn't use a GKR proof, leave unimplemented. - #[allow(unused_variables)] - #[maybe_async] - fn generate_gkr_proof( - &self, - main_trace: &Self::Trace, - public_coin: &mut Self::RandomCoin, - ) -> (ProverGkrProof, GkrRandElements) - where - E: FieldElement, - { - unimplemented!("`Prover::generate_gkr_proof` needs to be implemented when the auxiliary trace has a Lagrange kernel column.") - } - /// Builds and returns the auxiliary trace. #[allow(unused_variables)] #[maybe_async] @@ -263,14 +245,11 @@ pub trait Prover { /// /// The returned [Proof] attests that the specified `trace` is a valid execution trace of the /// computation described by [Self::Air](Prover::Air) and generated using some set of secret and - /// public inputs. It may also contain a GKR proof, further documented in [`Proof`]. - /// Public inputs must match the value returned from - /// [Self::get_pub_inputs()](Prover::get_pub_inputs) for the provided trace. + /// public inputs. #[maybe_async] fn prove(&self, trace: Self::Trace) -> Result where ::PublicInputs: Send, - ::GkrProof: Send, { // figure out which version of the generic proof generation procedure to run. this is a sort // of static dispatch for selecting two generic parameter: extension field and hash @@ -304,7 +283,6 @@ pub trait Prover { where E: FieldElement, ::PublicInputs: Send, - ::GkrProof: Send, { // 0 ----- instantiate AIR and prover channel --------------------------------------------- @@ -343,25 +321,11 @@ pub trait Prover { // build the auxiliary trace segment, and append the resulting segments to trace commitment // and trace polynomial table structs let aux_trace_with_metadata = if air.trace_info().is_multi_segment() { - let (gkr_proof, aux_rand_elements) = if air.context().has_lagrange_kernel_aux_column() { - let (gkr_proof, gkr_rand_elements) = - maybe_await!(self.generate_gkr_proof(&trace, channel.public_coin())); - - let rand_elements = air - .get_aux_rand_elements(channel.public_coin()) - .expect("failed to draw random elements for the auxiliary trace segment"); + let rand_elements = air + .get_aux_rand_elements(channel.public_coin()) + .expect("failed to draw random elements for the auxiliary trace segment"); - let aux_rand_elements = - AuxRandElements::new_with_gkr(rand_elements, gkr_rand_elements); - - (Some(gkr_proof), aux_rand_elements) - } else { - let rand_elements = air - .get_aux_rand_elements(channel.public_coin()) - .expect("failed to draw random elements for the auxiliary trace segment"); - - (None, AuxRandElements::new(rand_elements)) - }; + let aux_rand_elements = AuxRandElements::new(rand_elements); let aux_trace = maybe_await!(self.build_aux_trace(&trace, &aux_rand_elements)); @@ -380,10 +344,9 @@ pub trait Prover { aux_segment_polys }; - trace_polys - .add_aux_segment(aux_segment_polys, air.context().lagrange_kernel_aux_column_idx()); + trace_polys.add_aux_segment(aux_segment_polys); - Some(AuxTraceWithMetadata { aux_trace, aux_rand_elements, gkr_proof }) + Some(AuxTraceWithMetadata { aux_trace, aux_rand_elements }) } else { None }; @@ -395,9 +358,9 @@ pub trait Prover { trace.validate(&air, aux_trace_with_metadata.as_ref()); // Destructure `aux_trace_with_metadata`. - let (aux_trace, aux_rand_elements, gkr_proof) = match aux_trace_with_metadata { - Some(atm) => (Some(atm.aux_trace), Some(atm.aux_rand_elements), atm.gkr_proof), - None => (None, None, None), + let (aux_trace, aux_rand_elements) = match aux_trace_with_metadata { + Some(atm) => (Some(atm.aux_trace), Some(atm.aux_rand_elements)), + None => (None, None), }; // drop the main trace and aux trace segment as they are no longer needed @@ -435,9 +398,7 @@ pub trait Prover { // evaluate trace and constraint polynomials at the OOD point z, and send the results to // the verifier. the trace polynomials are actually evaluated over two points: z and z * - // g, where g is the generator of the trace domain. Additionally, if the Lagrange kernel - // auxiliary column is present, we also evaluate that column over the points: z, z * g, - // z * g^2, z * g^4, ..., z * g^(2^(v-1)), where v = log(trace_len). + // g, where g is the generator of the trace domain. let ood_trace_states = trace_polys.get_ood_frame(z); channel.send_ood_trace_states(&ood_trace_states); @@ -525,7 +486,6 @@ pub trait Prover { constraint_queries, fri_proof, query_positions.len(), - gkr_proof.map(|gkr_proof| gkr_proof.to_bytes()), ); drop(span); diff --git a/prover/src/tests/mod.rs b/prover/src/tests/mod.rs index 159e4dcad..cf4fbed34 100644 --- a/prover/src/tests/mod.rs +++ b/prover/src/tests/mod.rs @@ -75,8 +75,6 @@ impl MockAir { impl Air for MockAir { type BaseField = BaseElement; type PublicInputs = (); - type GkrProof = (); - type GkrVerifier = (); fn new(trace_info: TraceInfo, _pub_inputs: (), _options: ProofOptions) -> Self { let context = build_context(trace_info, 8, 1); diff --git a/prover/src/trace/mod.rs b/prover/src/trace/mod.rs index 26b383a3b..9b93a71ec 100644 --- a/prover/src/trace/mod.rs +++ b/prover/src/trace/mod.rs @@ -3,7 +3,7 @@ // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. -use air::{Air, AuxRandElements, EvaluationFrame, LagrangeKernelBoundaryConstraint, TraceInfo}; +use air::{Air, AuxRandElements, EvaluationFrame, TraceInfo}; use math::{polynom, FieldElement, StarkField}; use super::ColMatrix; @@ -20,20 +20,13 @@ pub use trace_table::{TraceTable, TraceTableFragment}; #[cfg(test)] mod tests; -/// Defines an [`AuxTraceWithMetadata`] type where the type arguments use their equivalents in an -/// [`Air`]. -type AirAuxTraceWithMetadata = AuxTraceWithMetadata::GkrProof>; - // AUX TRACE WITH METADATA // ================================================================================================ -/// Holds the auxiliary trace, the random elements used when generating the auxiliary trace, and -/// optionally, a GKR proof. See [`crate::Proof`] for more information about the auxiliary -/// proof. -pub struct AuxTraceWithMetadata { +/// Holds the auxiliary trace, the random elements used when generating the auxiliary trace. +pub struct AuxTraceWithMetadata { pub aux_trace: ColMatrix, pub aux_rand_elements: AuxRandElements, - pub gkr_proof: Option, } // TRACE TRAIT @@ -90,11 +83,8 @@ pub trait Trace: Sized { /// Checks if this trace is valid against the specified AIR, and panics if not. /// /// NOTE: this is a very expensive operation and is intended for use only in debug mode. - fn validate( - &self, - air: &A, - aux_trace_with_metadata: Option<&AirAuxTraceWithMetadata>, - ) where + fn validate(&self, air: &A, aux_trace_with_metadata: Option<&AuxTraceWithMetadata>) + where A: Air, E: FieldElement, { @@ -139,21 +129,6 @@ pub trait Trace: Sized { ); }); } - - // then, check the Lagrange kernel assertion, if any - if let Some(lagrange_kernel_col_idx) = air.context().lagrange_kernel_aux_column_idx() { - let boundary_constraint_assertion_value = - LagrangeKernelBoundaryConstraint::assertion_value( - aux_rand_elements - .lagrange() - .expect("expected Lagrange kernel rand elements to be present"), - ); - - assert_eq!( - boundary_constraint_assertion_value, - aux_trace.get(lagrange_kernel_col_idx, 0) - ); - } } // --- 2. make sure this trace satisfies all transition constraints ----------------------- @@ -223,40 +198,6 @@ pub trait Trace: Sized { // update x coordinate of the domain x *= g; } - - // evaluate transition constraints for Lagrange kernel column (if any) and make sure - // they all evaluate to zeros - if let Some(col_idx) = air.context().lagrange_kernel_aux_column_idx() { - let aux_trace_with_metadata = - aux_trace_with_metadata.expect("expected aux trace to be present"); - let aux_trace = &aux_trace_with_metadata.aux_trace; - let aux_rand_elements = &aux_trace_with_metadata.aux_rand_elements; - - let c = aux_trace.get_column(col_idx); - let v = self.length().ilog2() as usize; - let r = aux_rand_elements.lagrange().expect("expected Lagrange column to be present"); - - // Loop over every constraint - for constraint_idx in 1..v + 1 { - let domain_step = 2_usize.pow((v - constraint_idx + 1) as u32); - let domain_half_step = 2_usize.pow((v - constraint_idx) as u32); - - // Every transition constraint has a different enforcement domain (i.e. the rows to which it applies). - let enforcement_dom_len = self.length() / domain_step; - for dom_idx in 0..enforcement_dom_len { - let x_current = dom_idx * domain_step; - let x_next = x_current + domain_half_step; - - let evaluation = (r[v - constraint_idx] * c[x_current]) - - ((E::ONE - r[v - constraint_idx]) * c[x_next]); - - assert!( - evaluation == E::ZERO, - "Lagrange transition constraint {constraint_idx} did not evaluate to ZERO at step {x_current}" - ); - } - } - } } } diff --git a/prover/src/trace/poly_table.rs b/prover/src/trace/poly_table.rs index 87fec88d4..b5d1c6df1 100644 --- a/prover/src/trace/poly_table.rs +++ b/prover/src/trace/poly_table.rs @@ -5,7 +5,7 @@ use alloc::vec::Vec; -use air::{proof::TraceOodFrame, LagrangeKernelEvaluationFrame}; +use air::proof::TraceOodFrame; use math::{FieldElement, StarkField}; use crate::{matrix::ColumnIter, ColMatrix}; @@ -16,13 +16,11 @@ use crate::{matrix::ColumnIter, ColMatrix}; /// Trace polynomials in coefficient from for all segments of the execution trace. /// /// Coefficients of the polynomials for the main trace segment are always in the base field. -/// However, coefficients of the polynomials for the auxiliary trace segment (including -/// the Lagrange kernel polynomial when present) may be either in the base field, or in -/// the extension field, depending on whether extension field is being used. +/// However, coefficients of the polynomials for the auxiliary trace segment may be either in +/// the base field, or in the extension field, depending on whether extension field is being used. pub struct TracePolyTable { main_trace_polys: ColMatrix, aux_trace_polys: Option>, - lagrange_kernel_poly: Option>, } impl TracePolyTable { @@ -30,22 +28,14 @@ impl TracePolyTable { // -------------------------------------------------------------------------------------------- /// Creates a new table of trace polynomials from the provided main trace segment polynomials. pub fn new(main_trace_polys: ColMatrix) -> Self { - Self { - main_trace_polys, - aux_trace_polys: None, - lagrange_kernel_poly: None, - } + Self { main_trace_polys, aux_trace_polys: None } } // STATE MUTATORS // -------------------------------------------------------------------------------------------- /// Adds the provided auxiliary segment polynomials to this polynomial table. - pub fn add_aux_segment( - &mut self, - aux_trace_polys: ColMatrix, - lagrange_kernel_column_idx: Option, - ) { + pub fn add_aux_segment(&mut self, aux_trace_polys: ColMatrix) { assert!(self.aux_trace_polys.is_none()); assert_eq!( self.main_trace_polys.num_rows(), @@ -53,10 +43,6 @@ impl TracePolyTable { "polynomials in auxiliary segment must be of the same size as in the main segment" ); - let mut aux_trace_polys = aux_trace_polys; - if let Some(index) = lagrange_kernel_column_idx { - self.lagrange_kernel_poly = Some(aux_trace_polys.remove_column(index)); - } self.aux_trace_polys = Some(aux_trace_polys); } @@ -79,26 +65,14 @@ impl TracePolyTable { /// Returns an out-of-domain evaluation frame constructed by evaluating trace polynomials for /// all columns at points z and z * g, where g is the generator of the trace domain. - /// Additionally, if the Lagrange kernel auxiliary column is present, we also evaluate that - /// column over the points: z, z * g, z * g^2, z * g^4, ..., z * g^(2^(v-1)), where v = - /// log(trace_len). pub fn get_ood_frame(&self, z: E) -> TraceOodFrame { let log_trace_len = self.poly_size().ilog2(); let g = E::from(E::BaseField::get_root_of_unity(log_trace_len)); let current_row = self.evaluate_at(z); let next_row = self.evaluate_at(z * g); - - let lagrange_kernel_frame = - self.lagrange_kernel_poly.as_ref().map(|lagrange_kernel_col_poly| { - LagrangeKernelEvaluationFrame::from_lagrange_kernel_column_poly( - lagrange_kernel_col_poly, - z, - ) - }); - let main_trace_width = self.main_trace_polys.num_cols(); - TraceOodFrame::new(current_row, next_row, main_trace_width, lagrange_kernel_frame) + TraceOodFrame::new(current_row, next_row, main_trace_width) } /// Returns an iterator over the polynomials of the main trace segment. @@ -114,12 +88,6 @@ impl TracePolyTable { } } - /// Returns the polynomial of the auxiliary trace segment corresponding to the Lagrange kernel, - /// if any. - pub fn lagrange_kernel_poly(&self) -> Option<&[E]> { - self.lagrange_kernel_poly.as_deref() - } - // TEST HELPERS // -------------------------------------------------------------------------------------------- diff --git a/prover/src/trace/trace_lde/default/mod.rs b/prover/src/trace/trace_lde/default/mod.rs index afc3734a6..ab7c4e765 100644 --- a/prover/src/trace/trace_lde/default/mod.rs +++ b/prover/src/trace/trace_lde/default/mod.rs @@ -6,7 +6,7 @@ use alloc::vec::Vec; use core::marker::PhantomData; -use air::{proof::Queries, LagrangeKernelEvaluationFrame, PartitionOptions, TraceInfo}; +use air::{proof::Queries, PartitionOptions, TraceInfo}; use crypto::VectorCommitment; use tracing::info_span; @@ -194,29 +194,6 @@ where frame.next_mut().copy_from_slice(segment.row(next_lde_step)); } - fn read_lagrange_kernel_frame_into( - &self, - lde_step: usize, - lagrange_kernel_aux_column_idx: usize, - frame: &mut LagrangeKernelEvaluationFrame, - ) { - let frame = frame.frame_mut(); - frame.truncate(0); - - let aux_segment = - self.aux_segment_lde.as_ref().expect("expected aux segment to be present"); - - frame.push(aux_segment.get(lagrange_kernel_aux_column_idx, lde_step)); - - let frame_length = self.trace_info.length().ilog2() as usize + 1; - for i in 0..frame_length - 1 { - let shift = self.blowup() * (1 << i); - let next_lde_step = (lde_step + shift) % self.trace_len(); - - frame.push(aux_segment.get(lagrange_kernel_aux_column_idx, next_lde_step)); - } - } - /// Returns trace table rows at the specified positions along with an opening proof to these /// rows againt the already computed commitment. fn query(&self, positions: &[usize]) -> Vec { diff --git a/prover/src/trace/trace_lde/mod.rs b/prover/src/trace/trace_lde/mod.rs index dbce21491..331cd8300 100644 --- a/prover/src/trace/trace_lde/mod.rs +++ b/prover/src/trace/trace_lde/mod.rs @@ -5,7 +5,7 @@ use alloc::vec::Vec; -use air::{proof::Queries, LagrangeKernelEvaluationFrame, TraceInfo}; +use air::{proof::Queries, TraceInfo}; use crypto::{ElementHasher, Hasher, VectorCommitment}; use super::{ColMatrix, EvaluationFrame, FieldElement, TracePolyTable}; @@ -61,18 +61,6 @@ pub trait TraceLde: Sync { /// Reads current and next rows from the auxiliary trace segment into the specified frame. fn read_aux_trace_frame_into(&self, lde_step: usize, frame: &mut EvaluationFrame); - /// Populates the provided Lagrange kernel frame starting at the current row (as defined by - /// `lde_step`). - /// - /// Note that unlike [`EvaluationFrame`], the Lagrange kernel frame includes only the Lagrange - /// kernel column (as opposed to all columns). - fn read_lagrange_kernel_frame_into( - &self, - lde_step: usize, - col_idx: usize, - frame: &mut LagrangeKernelEvaluationFrame, - ); - /// Returns trace table rows at the specified positions along with an opening proof to these /// rows. fn query(&self, positions: &[usize]) -> Vec; diff --git a/verifier/src/channel.rs b/verifier/src/channel.rs index 1425d86aa..e15aa8314 100644 --- a/verifier/src/channel.rs +++ b/verifier/src/channel.rs @@ -50,7 +50,6 @@ pub struct VerifierChannel< ood_constraint_evaluations: Option>, // query proof-of-work pow_nonce: u64, - gkr_proof: Option>, } impl VerifierChannel @@ -75,7 +74,6 @@ where ood_frame, fri_proof, pow_nonce, - gkr_proof, } = proof; // make sure AIR and proof base fields are the same @@ -149,7 +147,6 @@ where ood_constraint_evaluations: Some(ood_constraint_evaluations), // query seed pow_nonce, - gkr_proof, }) } @@ -189,11 +186,6 @@ where self.pow_nonce } - /// Returns the serialized GKR proof, if any. - pub fn read_gkr_proof(&self) -> Option<&Vec> { - self.gkr_proof.as_ref() - } - /// Returns trace states at the specified positions of the LDE domain. This also checks if /// the trace states are valid against the trace commitment sent by the prover. /// diff --git a/verifier/src/composer.rs b/verifier/src/composer.rs index 5f10ef79f..9db569083 100644 --- a/verifier/src/composer.rs +++ b/verifier/src/composer.rs @@ -5,10 +5,8 @@ use alloc::vec::Vec; -use air::{ - proof::Table, Air, DeepCompositionCoefficients, EvaluationFrame, LagrangeKernelEvaluationFrame, -}; -use math::{batch_inversion, polynom, FieldElement}; +use air::{proof::Table, Air, DeepCompositionCoefficients, EvaluationFrame}; +use math::{batch_inversion, FieldElement}; // DEEP COMPOSER // ================================================================================================ @@ -17,8 +15,6 @@ pub struct DeepComposer { cc: DeepCompositionCoefficients, x_coordinates: Vec, z: [E; 2], - g_trace: E::BaseField, - lagrange_kernel_column_idx: Option, } impl DeepComposer { @@ -42,8 +38,6 @@ impl DeepComposer { cc, x_coordinates, z: [z, z * E::from(g_trace)], - g_trace, - lagrange_kernel_column_idx: air.context().lagrange_kernel_aux_column_idx(), } } @@ -57,28 +51,15 @@ impl DeepComposer { /// - Then, combine all T'_i(x) and T''_i(x) values together by computing /// T(x) = sum((T'_i(x) + T''_i(x)) * cc_i) for all i, where cc_i is the coefficient for /// for the random linear combination drawn from the public coin. - /// - If a Lagrange kernel is present, combine one additional term defined as - /// (T_l(x) - p_S(x)) / Z_S(x), where: - /// - /// 1. $T_l(x) is the evaluation of the Lagrange trace polynomial at $x$. - /// 2. $S$ is the set of opening points for the Lagrange kernel i.e., - /// $S := {z, z.g, z.g^2, ..., z.g^{2^{log_2(\nu) - 1}}}$. - /// 3. $p_S(X)$ is the polynomial of minimal degree interpolating the set - /// ${(a, T_l(a)): a \in S}$. - /// 4. $Z_S(X)$ is the polynomial of minimal degree vanishing over the set $S$. /// /// Note that values of T_i(z) and T_i(z * g) are received from the prover and passed into /// this function via the `ood_main_frame` and `ood_aux_frame` parameters. - /// - /// If a Lagrange kernel is present, the evaluations of $T_l$ over the set $S$ are received - /// from the prover and passed separately via `ood_lagrange_kernel_frame`. pub fn compose_trace_columns( &self, queried_main_trace_states: Table, queried_aux_trace_states: Option>, ood_main_frame: EvaluationFrame, ood_aux_frame: Option>, - ood_lagrange_kernel_frame: Option<&LagrangeKernelEvaluationFrame>, ) -> Vec { let ood_main_trace_states = [ood_main_frame.current(), ood_main_frame.next()]; @@ -124,17 +105,12 @@ impl DeepComposer { // consumed some number of composition coefficients already. let cc_offset = queried_main_trace_states.num_columns(); - // we treat the Lagrange column separately if present - let lagrange_ker_col_idx = - self.lagrange_kernel_column_idx.unwrap_or(ood_aux_trace_states[0].len()); - for ((j, row), &x) in (0..n).zip(queried_aux_trace_states.rows()).zip(&self.x_coordinates) { let mut t1_num = E::ZERO; let mut t2_num = E::ZERO; - let row = &row[..lagrange_ker_col_idx]; for (i, &value) in row.iter().enumerate() { // compute the numerator of T'_i(x) as (T_i(x) - T_i(z)), multiply it by a // composition coefficient, and add the result to the numerator aggregator @@ -151,49 +127,6 @@ impl DeepComposer { let t2_den = x - self.z[1]; result_num[j] += t1_num * t2_den + t2_num * t1_den; } - - // if a Lagrange kernel trace polynomial is present, we include its associated term - // separately. Note that, for performance reasons, we divide by Z_{S^{'}} instead of - // Z_S, where $S^{'} := {z.g^2, ..., z.g^{2^{log_2(\nu) - 1}}}$. This is done as - // the final linear combination is divided by `(x - z) . (x - z.g)`. - if let Some(ood_lagrange_kernel_frame) = ood_lagrange_kernel_frame { - let mut result_lag_num = Vec::::with_capacity(n); - let mut result_lag_den = Vec::::with_capacity(n); - - let log_trace_len_plus_1 = ood_lagrange_kernel_frame.num_rows(); - let mut xs = Vec::with_capacity(log_trace_len_plus_1); - let mut ys = Vec::with_capacity(log_trace_len_plus_1); - - xs.push(self.z[0]); - ys.push(ood_lagrange_kernel_frame.inner()[0]); - - let mut g_exp = self.g_trace; - for i in 0..(log_trace_len_plus_1 - 1) { - let x = self.z[0].mul_base(g_exp); - let lagrange_poly_at_x = ood_lagrange_kernel_frame.inner()[i + 1]; - - xs.push(x); - ys.push(lagrange_poly_at_x); - - // takes on the values `g`, `g^2`, `g^4`, `g^8`, ... - g_exp *= g_exp; - } - let p_s = polynom::interpolate(&xs, &ys, true); - let z_s_prime = polynom::poly_from_roots(&xs[2..]); - - for (row, &x) in queried_aux_trace_states.rows().zip(&self.x_coordinates) { - let value = row[lagrange_ker_col_idx]; - let cc = self.cc.lagrange.unwrap(); - - result_lag_num.push((value - polynom::eval(&p_s, x)) * cc); - result_lag_den.push(polynom::eval(&z_s_prime, x)); - } - - result_lag_den = batch_inversion(&result_lag_den); - for (j, res) in result_num.iter_mut().enumerate() { - *res += result_lag_num[j] * result_lag_den[j]; - } - } } result_den = batch_inversion(&result_den); diff --git a/verifier/src/errors.rs b/verifier/src/errors.rs index fadaee1fa..63a6e5eb8 100644 --- a/verifier/src/errors.rs +++ b/verifier/src/errors.rs @@ -13,8 +13,6 @@ use core::fmt; /// Represents an error returned by the verifier during an execution of the protocol. #[derive(Debug, Clone, PartialEq, Eq)] pub enum VerifierError { - /// This error occurs when verifying the GKR proof failed. - GkrProofVerificationFailed(String), /// This error occurs when base field read by a verifier from a proof does not match the /// base field of AIR with which the verifier was instantiated. InconsistentBaseField, @@ -59,9 +57,6 @@ impl fmt::Display for VerifierError { #[rustfmt::skip] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::GkrProofVerificationFailed(reason) => { - write!(f, "aux trace verification failed: {}", reason) - } Self::InconsistentBaseField => { write!(f, "base field of the proof does not match base field of the specified AIR") } diff --git a/verifier/src/evaluator.rs b/verifier/src/evaluator.rs index 10910a555..9628cb7f9 100644 --- a/verifier/src/evaluator.rs +++ b/verifier/src/evaluator.rs @@ -5,10 +5,7 @@ use alloc::vec::Vec; -use air::{ - Air, AuxRandElements, ConstraintCompositionCoefficients, EvaluationFrame, - LagrangeKernelEvaluationFrame, -}; +use air::{Air, AuxRandElements, ConstraintCompositionCoefficients, EvaluationFrame}; use math::{polynom, FieldElement}; // CONSTRAINT EVALUATION @@ -20,7 +17,6 @@ pub fn evaluate_constraints>( composition_coefficients: ConstraintCompositionCoefficients, main_trace_frame: &EvaluationFrame, aux_trace_frame: &Option>, - lagrange_kernel_frame: Option<&LagrangeKernelEvaluationFrame>, aux_rand_elements: Option<&AuxRandElements>, x: E, ) -> E { @@ -86,36 +82,5 @@ pub fn evaluate_constraints>( } } - // 3 ----- evaluate Lagrange kernel constraints ------------------------------------ - - if let Some(lagrange_kernel_column_frame) = lagrange_kernel_frame { - let lagrange_coefficients = composition_coefficients - .lagrange - .expect("expected Lagrange kernel composition coefficients to be present"); - let lagrange_kernel_aux_rand_elements = { - let aux_rand_elements = - aux_rand_elements.expect("expected aux rand elements to be present"); - - aux_rand_elements - .lagrange() - .expect("expected lagrange rand elements to be present") - }; - - let lagrange_constraints = air - .get_lagrange_kernel_constraints( - lagrange_coefficients, - lagrange_kernel_aux_rand_elements, - ) - .expect("expected Lagrange kernel constraints to be present"); - - result += lagrange_constraints.transition.evaluate_and_combine::( - lagrange_kernel_column_frame, - lagrange_kernel_aux_rand_elements, - x, - ); - - result += lagrange_constraints.boundary.evaluate_at(x, lagrange_kernel_column_frame); - } - result } diff --git a/verifier/src/lib.rs b/verifier/src/lib.rs index ecb7e9c75..656551aae 100644 --- a/verifier/src/lib.rs +++ b/verifier/src/lib.rs @@ -31,15 +31,15 @@ #[macro_use] extern crate alloc; -use alloc::{string::ToString, vec::Vec}; +use alloc::vec::Vec; use core::cmp; +use air::AuxRandElements; pub use air::{ proof::Proof, Air, AirContext, Assertion, BoundaryConstraint, BoundaryConstraintGroup, ConstraintCompositionCoefficients, ConstraintDivisor, DeepCompositionCoefficients, EvaluationFrame, FieldExtension, ProofOptions, TraceInfo, TransitionConstraintDegree, }; -use air::{AuxRandElements, GkrVerifier}; pub use crypto; use crypto::{ElementHasher, Hasher, RandomCoin, VectorCommitment}; use fri::FriVerifier; @@ -176,36 +176,13 @@ where // process auxiliary trace segments (if any), to build a set of random elements for each segment let aux_trace_rand_elements = if air.trace_info().is_multi_segment() { - if air.context().has_lagrange_kernel_aux_column() { - let gkr_proof = { - let gkr_proof_serialized = channel - .read_gkr_proof() - .expect("Expected an a GKR proof because trace has lagrange kernel column"); - - Deserializable::read_from_bytes(gkr_proof_serialized) - .map_err(|err| VerifierError::ProofDeserializationError(err.to_string()))? - }; - let gkr_rand_elements = air - .get_gkr_proof_verifier::() - .verify::(gkr_proof, &mut public_coin) - .map_err(|err| VerifierError::GkrProofVerificationFailed(err.to_string()))?; - - let rand_elements = air.get_aux_rand_elements(&mut public_coin).expect( - "failed to generate the random elements needed to build the auxiliary trace", - ); - - public_coin.reseed(trace_commitments[AUX_TRACE_IDX]); - - Some(AuxRandElements::new_with_gkr(rand_elements, gkr_rand_elements)) - } else { - let rand_elements = air.get_aux_rand_elements(&mut public_coin).expect( - "failed to generate the random elements needed to build the auxiliary trace", - ); - - public_coin.reseed(trace_commitments[AUX_TRACE_IDX]); - - Some(AuxRandElements::new(rand_elements)) - } + let rand_elements = air + .get_aux_rand_elements(&mut public_coin) + .expect("failed to generate the random elements needed to build the auxiliary trace"); + + public_coin.reseed(trace_commitments[AUX_TRACE_IDX]); + + Some(AuxRandElements::new(rand_elements)) } else { None }; @@ -235,13 +212,11 @@ where let ood_trace_frame = channel.read_ood_trace_frame(); let ood_main_trace_frame = ood_trace_frame.main_frame(); let ood_aux_trace_frame = ood_trace_frame.aux_frame(); - let ood_lagrange_kernel_frame = ood_trace_frame.lagrange_kernel_frame(); let ood_constraint_evaluation_1 = evaluate_constraints( &air, constraint_coeffs, &ood_main_trace_frame, &ood_aux_trace_frame, - ood_lagrange_kernel_frame, aux_trace_rand_elements.as_ref(), z, ); @@ -328,7 +303,6 @@ where queried_aux_trace_states, ood_main_trace_frame, ood_aux_trace_frame, - ood_lagrange_kernel_frame, ); let c_composition = composer .compose_constraint_evaluations(queried_constraint_evaluations, ood_constraint_evaluations); diff --git a/winterfell/src/lib.rs b/winterfell/src/lib.rs index 743218985..b31e662d3 100644 --- a/winterfell/src/lib.rs +++ b/winterfell/src/lib.rs @@ -150,7 +150,7 @@ //! ```no_run //! use winterfell::{ //! math::{fields::f128::BaseElement, FieldElement, ToElements}, -//! Air, AirContext, Assertion, GkrVerifier, EvaluationFrame, +//! Air, AirContext, Assertion, EvaluationFrame, //! ProofOptions, TraceInfo, TransitionConstraintDegree, //! crypto::{hashers::Blake3_256, DefaultRandomCoin, MerkleTree}, //! }; @@ -182,8 +182,6 @@ //! // the public inputs must look like. //! type BaseField = BaseElement; //! type PublicInputs = PublicInputs; -//! type GkrProof = (); -//! type GkrVerifier = (); //! //! // Here, we'll construct a new instance of our computation which is defined by 3 //! // parameters: starting value, number of steps, and the end result. Another way to @@ -291,8 +289,6 @@ //! # impl Air for WorkAir { //! # type BaseField = BaseElement; //! # type PublicInputs = PublicInputs; -//! # type GkrProof = (); -//! # type GkrVerifier = (); //! # //! # fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: ProofOptions) -> Self { //! # assert_eq!(1, trace_info.width()); @@ -459,8 +455,6 @@ //! # impl Air for WorkAir { //! # type BaseField = BaseElement; //! # type PublicInputs = PublicInputs; -//! # type GkrProof = (); -//! # type GkrVerifier = (); //! # //! # fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: ProofOptions) -> Self { //! # assert_eq!(1, trace_info.width()); @@ -633,14 +627,14 @@ #[cfg(test)] extern crate std; -pub use air::{AuxRandElements, BatchingMethod, GkrVerifier, PartitionOptions}; +pub use air::{AuxRandElements, BatchingMethod, PartitionOptions}; pub use prover::{ crypto, iterators, math, matrix, Air, AirContext, Assertion, AuxTraceWithMetadata, BoundaryConstraint, BoundaryConstraintGroup, CompositionPoly, CompositionPolyTrace, ConstraintCompositionCoefficients, ConstraintDivisor, ConstraintEvaluator, DeepCompositionCoefficients, DefaultConstraintCommitment, DefaultConstraintEvaluator, DefaultTraceLde, EvaluationFrame, FieldExtension, Proof, ProofOptions, Prover, ProverError, - ProverGkrProof, StarkDomain, Trace, TraceInfo, TraceLde, TracePolyTable, TraceTable, - TraceTableFragment, TransitionConstraintDegree, + StarkDomain, Trace, TraceInfo, TraceLde, TracePolyTable, TraceTable, TraceTableFragment, + TransitionConstraintDegree, }; pub use verifier::{verify, AcceptableOptions, ByteWriter, VerifierError};