From 5d43adfeda9b82bc3b3acd7b33d352b31eb5bc1c Mon Sep 17 00:00:00 2001 From: Alon Haramati Date: Sun, 16 Jun 2024 11:13:22 +0300 Subject: [PATCH] Add lookup final boundary constraints. --- crates/prover/src/core/air/air_ext.rs | 13 ++- crates/prover/src/core/air/mod.rs | 9 +- crates/prover/src/core/fields/cm31.rs | 11 ++ crates/prover/src/core/fields/qm31.rs | 11 ++ crates/prover/src/core/mod.rs | 26 ++++- crates/prover/src/core/prover/mod.rs | 36 +++++- .../src/examples/fibonacci/component.rs | 8 +- crates/prover/src/examples/fibonacci/mod.rs | 9 +- crates/prover/src/examples/poseidon/mod.rs | 8 +- .../src/examples/wide_fibonacci/component.rs | 40 ++++++- .../wide_fibonacci/constraint_eval.rs | 108 +++++++++++++++++- .../prover/src/examples/wide_fibonacci/mod.rs | 8 +- .../src/examples/wide_fibonacci/simd.rs | 8 +- .../prover/src/trace_generation/registry.rs | 3 +- 14 files changed, 277 insertions(+), 21 deletions(-) diff --git a/crates/prover/src/core/air/air_ext.rs b/crates/prover/src/core/air/air_ext.rs index 0de231025..abc47b960 100644 --- a/crates/prover/src/core/air/air_ext.rs +++ b/crates/prover/src/core/air/air_ext.rs @@ -10,7 +10,7 @@ use crate::core::pcs::{CommitmentTreeProver, TreeVec}; use crate::core::poly::circle::SecureCirclePoly; use crate::core::vcs::blake2_merkle::Blake2sMerkleHasher; use crate::core::vcs::ops::MerkleOps; -use crate::core::{ColumnVec, InteractionElements}; +use crate::core::{ColumnVec, InteractionElements, LookupValues}; pub trait AirExt: Air { fn composition_log_degree_bound(&self) -> u32 { @@ -56,6 +56,7 @@ pub trait AirExt: Air { mask_values: &Vec>>>, random_coeff: SecureField, interaction_elements: &InteractionElements, + lookup_values: &LookupValues, ) -> SecureField { let mut evaluation_accumulator = PointEvaluationAccumulator::new(random_coeff); zip_eq(self.components(), mask_values).for_each(|(component, mask)| { @@ -64,6 +65,7 @@ pub trait AirExt: Air { mask, &mut evaluation_accumulator, interaction_elements, + lookup_values, ) }); evaluation_accumulator.finalize() @@ -133,6 +135,7 @@ pub trait AirProverExt: AirProver { random_coeff: SecureField, component_traces: &[ComponentTrace<'_, B>], interaction_elements: &InteractionElements, + lookup_values: &LookupValues, ) -> SecureCirclePoly { let total_constraints: usize = self .prover_components() @@ -149,10 +152,18 @@ pub trait AirProverExt: AirProver { trace, &mut accumulator, interaction_elements, + lookup_values, ) }); accumulator.finalize() } + + fn lookup_values(&self, component_traces: &[ComponentTrace<'_, B>]) -> LookupValues { + let mut values = LookupValues::default(); + zip_eq(self.prover_components(), component_traces) + .for_each(|(component, trace)| values.extend(component.lookup_values(trace))); + values + } } impl> AirProverExt for A {} diff --git a/crates/prover/src/core/air/mod.rs b/crates/prover/src/core/air/mod.rs index f77bece2e..91ddbc714 100644 --- a/crates/prover/src/core/air/mod.rs +++ b/crates/prover/src/core/air/mod.rs @@ -7,7 +7,7 @@ use super::fields::qm31::SecureField; use super::pcs::TreeVec; use super::poly::circle::{CircleEvaluation, CirclePoly}; use super::poly::BitReversedOrder; -use super::{ColumnVec, InteractionElements}; +use super::{ColumnVec, InteractionElements, LookupValues}; pub mod accumulation; mod air_ext; @@ -67,13 +67,14 @@ pub trait Component { /// Returns the ids of the interaction elements used by the component. fn interaction_element_ids(&self) -> Vec; - /// Evaluates the constraint quotients combination of the component, given the mask values. + /// Evaluates the constraint quotients combination of the component at a point. fn evaluate_constraint_quotients_at_point( &self, point: CirclePoint, mask: &TreeVec>>, evaluation_accumulator: &mut PointEvaluationAccumulator, interaction_elements: &InteractionElements, + lookup_values: &LookupValues, ); } @@ -93,7 +94,11 @@ pub trait ComponentProver: Component { trace: &ComponentTrace<'_, B>, evaluation_accumulator: &mut DomainEvaluationAccumulator, interaction_elements: &InteractionElements, + lookup_values: &LookupValues, ); + + /// Returns the values needed to evaluate the components lookup boundary constraints. + fn lookup_values(&self, _trace: &ComponentTrace<'_, B>) -> LookupValues; } /// A component trace is a set of polynomials for each column on that component. diff --git a/crates/prover/src/core/fields/cm31.rs b/crates/prover/src/core/fields/cm31.rs index 9154972f7..d58cea4cf 100644 --- a/crates/prover/src/core/fields/cm31.rs +++ b/crates/prover/src/core/fields/cm31.rs @@ -52,6 +52,17 @@ impl Mul for CM31 { } } +impl TryInto for CM31 { + type Error = (); + + fn try_into(self) -> Result { + if self.1 != M31::zero() { + return Err(()); + } + Ok(self.0) + } +} + impl FieldExpOps for CM31 { fn inverse(&self) -> Self { assert!(!self.is_zero(), "0 has no inverse"); diff --git a/crates/prover/src/core/fields/qm31.rs b/crates/prover/src/core/fields/qm31.rs index 54cee0d4f..42eeca2df 100644 --- a/crates/prover/src/core/fields/qm31.rs +++ b/crates/prover/src/core/fields/qm31.rs @@ -66,6 +66,17 @@ impl Mul for QM31 { } } +impl TryInto for QM31 { + type Error = (); + + fn try_into(self) -> Result { + if self.1 != CM31::zero() { + return Err(()); + } + self.0.try_into() + } +} + impl FieldExpOps for QM31 { fn inverse(&self) -> Self { assert!(!self.is_zero(), "0 has no inverse"); diff --git a/crates/prover/src/core/mod.rs b/crates/prover/src/core/mod.rs index 499738c18..256ce9067 100644 --- a/crates/prover/src/core/mod.rs +++ b/crates/prover/src/core/mod.rs @@ -1,6 +1,8 @@ use std::collections::BTreeMap; use std::ops::{Deref, DerefMut, Index}; +use fields::m31::BaseField; + use self::fields::qm31::SecureField; pub mod air; @@ -61,7 +63,7 @@ impl DerefMut for ComponentVec { } } -#[derive(Default)] +#[derive(Default, Debug)] pub struct InteractionElements(BTreeMap); impl InteractionElements { @@ -82,3 +84,25 @@ impl Index<&str> for InteractionElements { &self.0[index] } } + +#[derive(Default, Debug)] +pub struct LookupValues(BTreeMap); + +impl LookupValues { + pub fn new(values: BTreeMap) -> Self { + Self(values) + } + + pub fn extend(&mut self, other: Self) { + self.0.extend(other.0); + } +} + +impl Index<&str> for LookupValues { + type Output = BaseField; + + fn index(&self, index: &str) -> &Self::Output { + // TODO(AlonH): Return an error if the key is not found. + &self.0[index] + } +} diff --git a/crates/prover/src/core/prover/mod.rs b/crates/prover/src/core/prover/mod.rs index 72d0d1994..8b27bd813 100644 --- a/crates/prover/src/core/prover/mod.rs +++ b/crates/prover/src/core/prover/mod.rs @@ -10,7 +10,7 @@ use super::pcs::{CommitmentSchemeProof, TreeVec}; use super::poly::circle::{CanonicCoset, SecureCirclePoly, MAX_CIRCLE_DOMAIN_LOG_SIZE}; use super::poly::twiddles::TwiddleTree; use super::proof_of_work::ProofOfWorkVerificationError; -use super::{ColumnVec, InteractionElements}; +use super::{ColumnVec, InteractionElements, LookupValues}; use crate::core::air::{Air, AirExt, AirProverExt}; use crate::core::backend::CpuBackend; use crate::core::channel::{Blake2sChannel, Channel as ChannelTrait}; @@ -38,6 +38,7 @@ pub const N_QUERIES: usize = 3; #[derive(Debug)] pub struct StarkProof { pub commitments: TreeVec<::Hash>, + pub lookup_values: LookupValues, pub commitment_scheme_proof: CommitmentSchemeProof, } @@ -91,14 +92,24 @@ pub fn generate_proof>( twiddles: &TwiddleTree, commitment_scheme: &mut CommitmentSchemeProver, ) -> Result { + let component_traces = air.component_traces(&commitment_scheme.trees); + let lookup_values = air.lookup_values(&component_traces); + channel.mix_felts( + &lookup_values + .0 + .values() + .map(|v| SecureField::from(*v)) + .collect_vec(), + ); + // Evaluate and commit on composition polynomial. let random_coeff = channel.draw_felt(); - let span = span!(Level::INFO, "Composition generation").entered(); let composition_polynomial_poly = air.compute_composition_polynomial( random_coeff, - &air.component_traces(&commitment_scheme.trees), + &component_traces, interaction_elements, + &lookup_values, ); span.exit(); @@ -127,6 +138,7 @@ pub fn generate_proof>( &trace_oods_values, random_coeff, interaction_elements, + &lookup_values, ) { return Err(ProvingError::ConstraintsNotSatisfied); @@ -134,6 +146,7 @@ pub fn generate_proof>( Ok(StarkProof { commitments: commitment_scheme.roots(), + lookup_values, commitment_scheme_proof, }) } @@ -198,6 +211,14 @@ pub fn verify( commitment_scheme.commit(proof.commitments[1], &column_log_sizes[1], channel); } + channel.mix_felts( + &proof + .lookup_values + .0 + .values() + .map(|v| SecureField::from(*v)) + .collect_vec(), + ); let random_coeff = channel.draw_felt(); // Read composition polynomial commitment. @@ -228,6 +249,7 @@ pub fn verify( &trace_oods_values, random_coeff, &interaction_elements, + &proof.lookup_values, ) { return Err(VerificationError::OodsNotMatching); @@ -332,7 +354,7 @@ mod tests { use crate::core::poly::BitReversedOrder; use crate::core::prover::{prove, ProvingError}; use crate::core::test_utils::test_channel; - use crate::core::{ColumnVec, InteractionElements}; + use crate::core::{ColumnVec, InteractionElements, LookupValues}; use crate::qm31; struct TestAir> { @@ -410,6 +432,7 @@ mod tests { _mask: &TreeVec>>, evaluation_accumulator: &mut PointEvaluationAccumulator, _interaction_elements: &InteractionElements, + _lookup_values: &LookupValues, ) { evaluation_accumulator.accumulate(qm31!(0, 0, 0, 1)) } @@ -431,9 +454,14 @@ mod tests { _trace: &ComponentTrace<'_, CpuBackend>, _evaluation_accumulator: &mut DomainEvaluationAccumulator, _interaction_elements: &InteractionElements, + _lookup_values: &LookupValues, ) { // Does nothing. } + + fn lookup_values(&self, _trace: &ComponentTrace<'_, CpuBackend>) -> LookupValues { + LookupValues::default() + } } // Ignored because it takes too long and too much memory (in the CI) to run. diff --git a/crates/prover/src/examples/fibonacci/component.rs b/crates/prover/src/examples/fibonacci/component.rs index b4352f90e..d799f8a24 100644 --- a/crates/prover/src/examples/fibonacci/component.rs +++ b/crates/prover/src/examples/fibonacci/component.rs @@ -15,7 +15,7 @@ use crate::core::pcs::TreeVec; use crate::core::poly::circle::{CanonicCoset, CircleEvaluation}; use crate::core::poly::BitReversedOrder; use crate::core::utils::bit_reverse_index; -use crate::core::{ColumnVec, InteractionElements}; +use crate::core::{ColumnVec, InteractionElements, LookupValues}; pub struct FibonacciComponent { pub log_size: u32, @@ -110,6 +110,7 @@ impl Component for FibonacciComponent { mask: &TreeVec>>, evaluation_accumulator: &mut PointEvaluationAccumulator, _interaction_elements: &InteractionElements, + _lookup_values: &LookupValues, ) { evaluation_accumulator.accumulate( self.step_constraint_eval_quotient_by_mask(point, &mask[0][0][..].try_into().unwrap()), @@ -137,6 +138,7 @@ impl ComponentProver for FibonacciComponent { trace: &ComponentTrace<'_, CpuBackend>, evaluation_accumulator: &mut DomainEvaluationAccumulator, _interaction_elements: &InteractionElements, + _lookup_values: &LookupValues, ) { let poly = &trace.polys[0][0]; let trace_domain = CanonicCoset::new(self.log_size); @@ -166,4 +168,8 @@ impl ComponentProver for FibonacciComponent { } } } + + fn lookup_values(&self, _trace: &ComponentTrace<'_, CpuBackend>) -> LookupValues { + LookupValues::default() + } } diff --git a/crates/prover/src/examples/fibonacci/mod.rs b/crates/prover/src/examples/fibonacci/mod.rs index 5c9cdda12..338e3131b 100644 --- a/crates/prover/src/examples/fibonacci/mod.rs +++ b/crates/prover/src/examples/fibonacci/mod.rs @@ -110,7 +110,6 @@ impl MultiFibonacci { #[cfg(test)] mod tests { use std::assert_matches::assert_matches; - use std::collections::BTreeMap; use std::iter::zip; use itertools::Itertools; @@ -129,7 +128,7 @@ mod tests { use crate::core::prover::VerificationError; use crate::core::queries::Queries; use crate::core::utils::bit_reverse; - use crate::core::InteractionElements; + use crate::core::{InteractionElements, LookupValues}; use crate::{m31, qm31}; pub fn generate_test_queries(n_queries: usize, trace_length: usize) -> Vec { @@ -159,7 +158,8 @@ mod tests { let composition_polynomial_poly = fib.air.compute_composition_polynomial( random_coeff, &component_traces, - &InteractionElements::new(BTreeMap::new()), + &InteractionElements::default(), + &LookupValues::default(), ); // Evaluate this polynomial at another point out of the evaluation domain and compare to @@ -181,7 +181,8 @@ mod tests { point, &TreeVec::new(vec![mask_values]), &mut evaluation_accumulator, - &InteractionElements::new(BTreeMap::new()), + &InteractionElements::default(), + &LookupValues::default(), ); let oods_value = evaluation_accumulator.finalize(); diff --git a/crates/prover/src/examples/poseidon/mod.rs b/crates/prover/src/examples/poseidon/mod.rs index a301bbbe0..368fbbb50 100644 --- a/crates/prover/src/examples/poseidon/mod.rs +++ b/crates/prover/src/examples/poseidon/mod.rs @@ -26,7 +26,7 @@ use crate::core::fields::{FieldExpOps, FieldOps}; use crate::core::pcs::TreeVec; use crate::core::poly::circle::{CanonicCoset, CircleEvaluation, PolyOps}; use crate::core::poly::BitReversedOrder; -use crate::core::{ColumnVec, InteractionElements}; +use crate::core::{ColumnVec, InteractionElements, LookupValues}; const N_LOG_INSTANCES_PER_ROW: usize = 3; const N_INSTANCES_PER_ROW: usize = 1 << N_LOG_INSTANCES_PER_ROW; @@ -124,6 +124,7 @@ impl Component for PoseidonComponent { mask: &TreeVec>>, evaluation_accumulator: &mut PointEvaluationAccumulator, _interaction_elements: &InteractionElements, + _lookup_values: &LookupValues, ) { let constraint_zero_domain = CanonicCoset::new(self.log_column_size()).coset; let denom = coset_vanishing(constraint_zero_domain, point); @@ -402,6 +403,7 @@ impl ComponentProver for PoseidonComponent { trace: &ComponentTrace<'_, SimdBackend>, evaluation_accumulator: &mut DomainEvaluationAccumulator, _interaction_elements: &InteractionElements, + _lookup_values: &LookupValues, ) { assert_eq!(trace.polys[0].len(), self.n_columns()); let eval_domain = CanonicCoset::new(self.log_column_size() + LOG_EXPAND).circle_domain(); @@ -461,6 +463,10 @@ impl ComponentProver for PoseidonComponent { assert_eq!(evaluator.constraint_index, n_constraints); } } + + fn lookup_values(&self, _trace: &ComponentTrace<'_, SimdBackend>) -> LookupValues { + LookupValues::default() + } } #[cfg(test)] diff --git a/crates/prover/src/examples/wide_fibonacci/component.rs b/crates/prover/src/examples/wide_fibonacci/component.rs index 47fd6dcc9..d9ce2cb96 100644 --- a/crates/prover/src/examples/wide_fibonacci/component.rs +++ b/crates/prover/src/examples/wide_fibonacci/component.rs @@ -15,7 +15,7 @@ use crate::core::pcs::TreeVec; use crate::core::poly::circle::{CanonicCoset, CircleEvaluation, SecureCirclePoly}; use crate::core::poly::BitReversedOrder; use crate::core::utils::shifted_secure_combination; -use crate::core::{ColumnVec, InteractionElements}; +use crate::core::{ColumnVec, InteractionElements, LookupValues}; use crate::examples::wide_fibonacci::trace_gen::write_lookup_column; pub const LOG_N_COLUMNS: usize = 8; @@ -23,6 +23,10 @@ pub const N_COLUMNS: usize = 1 << LOG_N_COLUMNS; pub const ALPHA_ID: &str = "wide_fibonacci_alpha"; pub const Z_ID: &str = "wide_fibonacci_z"; +pub const LOOKUP_VALUE_0_ID: &str = "wide_fibonacci_0"; +pub const LOOKUP_VALUE_1_ID: &str = "wide_fibonacci_1"; +pub const LOOKUP_VALUE_N_MINUS_2_ID: &str = "wide_fibonacci_n-2"; +pub const LOOKUP_VALUE_N_MINUS_1_ID: &str = "wide_fibonacci_n-1"; /// Component that computes 2^`self.log_n_instances` instances of fibonacci sequences of size /// 2^`self.log_fibonacci_size`. The numbers are computes over [N_COLUMNS] trace columns. The @@ -48,6 +52,30 @@ impl WideFibComponent { N_COLUMNS } + fn evaluate_trace_boundary_constraints_at_point( + &self, + point: CirclePoint, + mask: &TreeVec>>, + evaluation_accumulator: &mut PointEvaluationAccumulator, + constraint_zero_domain: Coset, + lookup_values: &LookupValues, + ) { + let numerator = mask[0][0][0] - lookup_values[LOOKUP_VALUE_0_ID]; + let denom = point_vanishing(constraint_zero_domain.at(0), point); + evaluation_accumulator.accumulate(numerator / denom); + let numerator = mask[0][1][0] - lookup_values[LOOKUP_VALUE_1_ID]; + evaluation_accumulator.accumulate(numerator / denom); + + let numerator = mask[0][self.n_columns() - 2][0] - lookup_values[LOOKUP_VALUE_N_MINUS_2_ID]; + let denom = point_vanishing( + constraint_zero_domain.at(constraint_zero_domain.size() - 1), + point, + ); + evaluation_accumulator.accumulate(numerator / denom); + let numerator = mask[0][self.n_columns() - 1][0] - lookup_values[LOOKUP_VALUE_N_MINUS_1_ID]; + evaluation_accumulator.accumulate(numerator / denom); + } + fn evaluate_trace_step_constraints_at_point( &self, point: CirclePoint, @@ -135,7 +163,7 @@ impl Air for WideFibAir { impl Component for WideFibComponent { fn n_constraints(&self) -> usize { - self.n_columns() + self.n_columns() + 4 } fn max_constraint_log_degree_bound(&self) -> u32 { @@ -174,8 +202,16 @@ impl Component for WideFibComponent { mask: &TreeVec>>, evaluation_accumulator: &mut PointEvaluationAccumulator, interaction_elements: &InteractionElements, + lookup_values: &LookupValues, ) { let constraint_zero_domain = CanonicCoset::new(self.log_column_size()).coset; + self.evaluate_trace_boundary_constraints_at_point( + point, + mask, + evaluation_accumulator, + constraint_zero_domain, + lookup_values, + ); self.evaluate_lookup_step_constraints_at_point( point, mask, diff --git a/crates/prover/src/examples/wide_fibonacci/constraint_eval.rs b/crates/prover/src/examples/wide_fibonacci/constraint_eval.rs index 08e607e7a..394adb403 100644 --- a/crates/prover/src/examples/wide_fibonacci/constraint_eval.rs +++ b/crates/prover/src/examples/wide_fibonacci/constraint_eval.rs @@ -3,7 +3,10 @@ use std::collections::BTreeMap; use itertools::{zip_eq, Itertools}; use num_traits::Zero; -use super::component::{Input, WideFibAir, WideFibComponent, ALPHA_ID, Z_ID}; +use super::component::{ + Input, WideFibAir, WideFibComponent, ALPHA_ID, LOOKUP_VALUE_0_ID, LOOKUP_VALUE_1_ID, + LOOKUP_VALUE_N_MINUS_1_ID, LOOKUP_VALUE_N_MINUS_2_ID, Z_ID, +}; use super::trace_gen::write_trace_row; use crate::core::air::accumulation::{ColumnAccumulator, DomainEvaluationAccumulator}; use crate::core::air::{ @@ -23,7 +26,7 @@ use crate::core::poly::BitReversedOrder; use crate::core::utils::{ bit_reverse, previous_bit_reversed_circle_domain_index, shifted_secure_combination, }; -use crate::core::{ColumnVec, InteractionElements}; +use crate::core::{ColumnVec, InteractionElements, LookupValues}; use crate::examples::wide_fibonacci::component::LOG_N_COLUMNS; // TODO(AlonH): Rename file to `cpu.rs`. @@ -58,6 +61,63 @@ impl AirProver for WideFibAir { } impl WideFibComponent { + fn evaluate_trace_boundary_constraints( + &self, + trace_evals: &TreeVec>>, + trace_eval_domain: CircleDomain, + zero_domain: Coset, + accum: &mut ColumnAccumulator<'_, CpuBackend>, + lookup_values: &LookupValues, + ) { + let max_constraint_degree = self.max_constraint_log_degree_bound(); + let mut first_point_denoms = vec![]; + let mut last_point_denoms = vec![]; + for point in trace_eval_domain.iter() { + // TODO(AlonH): Use `point_vanishing_fraction` instead of `point_vanishing` everywhere. + first_point_denoms.push(point_vanishing(zero_domain.at(0), point)); + last_point_denoms.push(point_vanishing( + zero_domain.at(zero_domain.size() - 1), + point, + )); + } + bit_reverse(&mut first_point_denoms); + bit_reverse(&mut last_point_denoms); + let mut first_point_denom_inverses = vec![BaseField::zero(); 1 << (max_constraint_degree)]; + let mut last_point_denom_inverses = vec![BaseField::zero(); 1 << (max_constraint_degree)]; + BaseField::batch_inverse(&first_point_denoms, &mut first_point_denom_inverses); + BaseField::batch_inverse(&last_point_denoms, &mut last_point_denom_inverses); + let mut first_point_numerators = vec![SecureField::zero(); 1 << (max_constraint_degree)]; + let mut last_point_numerators = vec![SecureField::zero(); 1 << (max_constraint_degree)]; + + #[allow(clippy::needless_range_loop)] + for i in 0..trace_eval_domain.size() { + first_point_numerators[i] = accum.random_coeff_powers[self.n_columns() + 3] + * (trace_evals[0][0][i] - lookup_values[LOOKUP_VALUE_0_ID]) + + accum.random_coeff_powers[self.n_columns() + 2] + * (trace_evals[0][1][i] - lookup_values[LOOKUP_VALUE_1_ID]); + last_point_numerators[i] = accum.random_coeff_powers[self.n_columns() + 1] + * (trace_evals[0][self.n_columns() - 2][i] + - lookup_values[LOOKUP_VALUE_N_MINUS_2_ID]) + + accum.random_coeff_powers[self.n_columns()] + * (trace_evals[0][self.n_columns() - 1][i] + - lookup_values[LOOKUP_VALUE_N_MINUS_1_ID]); + } + for (i, (num, denom_inverse)) in first_point_numerators + .iter() + .zip(first_point_denom_inverses.iter()) + .enumerate() + { + accum.accumulate(i, *num * *denom_inverse); + } + for (i, (num, denom_inverse)) in last_point_numerators + .iter() + .zip(last_point_denom_inverses.iter()) + .enumerate() + { + accum.accumulate(i, *num * *denom_inverse); + } + } + fn evaluate_trace_step_constraints( &self, trace_evals: &TreeVec>>, @@ -200,6 +260,7 @@ impl ComponentProver for WideFibComponent { trace: &ComponentTrace<'_, CpuBackend>, evaluation_accumulator: &mut DomainEvaluationAccumulator, interaction_elements: &InteractionElements, + lookup_values: &LookupValues, ) { let max_constraint_degree = self.max_constraint_log_degree_bound(); let trace_eval_domain = CanonicCoset::new(max_constraint_degree).circle_domain(); @@ -208,6 +269,13 @@ impl ComponentProver for WideFibComponent { let [mut accum] = evaluation_accumulator.columns([(max_constraint_degree, self.n_constraints())]); + self.evaluate_trace_boundary_constraints( + trace_evals, + trace_eval_domain, + zero_domain, + &mut accum, + lookup_values, + ); self.evaluate_trace_step_constraints( trace_evals, trace_eval_domain, @@ -229,6 +297,42 @@ impl ComponentProver for WideFibComponent { interaction_elements, ) } + + fn lookup_values(&self, trace: &ComponentTrace<'_, CpuBackend>) -> LookupValues { + let domain = CanonicCoset::new(self.log_column_size()); + let trace_poly = &trace.polys[0]; + let values = BTreeMap::from_iter([ + ( + LOOKUP_VALUE_0_ID.to_string(), + trace_poly[0] + .eval_at_point(domain.at(0).into_ef()) + .try_into() + .unwrap(), + ), + ( + LOOKUP_VALUE_1_ID.to_string(), + trace_poly[1] + .eval_at_point(domain.at(0).into_ef()) + .try_into() + .unwrap(), + ), + ( + LOOKUP_VALUE_N_MINUS_2_ID.to_string(), + trace_poly[self.n_columns() - 2] + .eval_at_point(domain.at(domain.size() - 1).into_ef()) + .try_into() + .unwrap(), + ), + ( + LOOKUP_VALUE_N_MINUS_1_ID.to_string(), + trace_poly[self.n_columns() - 1] + .eval_at_point(domain.at(domain.size() - 1).into_ef()) + .try_into() + .unwrap(), + ), + ]); + LookupValues::new(values) + } } /// Generates the trace for the wide Fibonacci example. diff --git a/crates/prover/src/examples/wide_fibonacci/mod.rs b/crates/prover/src/examples/wide_fibonacci/mod.rs index 4e1ea77c6..befc6ec0e 100644 --- a/crates/prover/src/examples/wide_fibonacci/mod.rs +++ b/crates/prover/src/examples/wide_fibonacci/mod.rs @@ -192,7 +192,13 @@ mod tests { ]), }; - wide_fib.evaluate_constraint_quotients_on_domain(&trace, &mut acc, &interaction_elements); + let lookup_values = wide_fib.lookup_values(&trace); + wide_fib.evaluate_constraint_quotients_on_domain( + &trace, + &mut acc, + &interaction_elements, + &lookup_values, + ); let res = acc.finalize(); let poly = res.0[0].clone(); diff --git a/crates/prover/src/examples/wide_fibonacci/simd.rs b/crates/prover/src/examples/wide_fibonacci/simd.rs index 2f34b6d78..866bbb1c4 100644 --- a/crates/prover/src/examples/wide_fibonacci/simd.rs +++ b/crates/prover/src/examples/wide_fibonacci/simd.rs @@ -23,7 +23,7 @@ use crate::core::fields::{FieldExpOps, FieldOps}; use crate::core::pcs::TreeVec; use crate::core::poly::circle::{CanonicCoset, CircleEvaluation}; use crate::core::poly::BitReversedOrder; -use crate::core::{ColumnVec, InteractionElements}; +use crate::core::{ColumnVec, InteractionElements, LookupValues}; use crate::examples::wide_fibonacci::component::{ALPHA_ID, N_COLUMNS, Z_ID}; // TODO(AlonH): Remove this once the Cpu and Simd implementations are aligned. @@ -116,6 +116,7 @@ impl Component for SimdWideFibComponent { mask: &TreeVec>>, evaluation_accumulator: &mut PointEvaluationAccumulator, _interaction_elements: &InteractionElements, + _lookup_values: &LookupValues, ) { let constraint_zero_domain = CanonicCoset::new(self.log_column_size()).coset; let denom = coset_vanishing(constraint_zero_domain, point); @@ -176,6 +177,7 @@ impl ComponentProver for SimdWideFibComponent { trace: &ComponentTrace<'_, SimdBackend>, evaluation_accumulator: &mut DomainEvaluationAccumulator, _interaction_elements: &InteractionElements, + _lookup_values: &LookupValues, ) { assert_eq!(trace.polys[0].len(), self.n_columns()); // TODO(spapini): Steal evaluation from commitment. @@ -228,6 +230,10 @@ impl ComponentProver for SimdWideFibComponent { } } } + + fn lookup_values(&self, _trace: &ComponentTrace<'_, SimdBackend>) -> LookupValues { + LookupValues::default() + } } #[cfg(test)] diff --git a/crates/prover/src/trace_generation/registry.rs b/crates/prover/src/trace_generation/registry.rs index 916397f82..e81577655 100644 --- a/crates/prover/src/trace_generation/registry.rs +++ b/crates/prover/src/trace_generation/registry.rs @@ -44,7 +44,7 @@ mod tests { use crate::core::pcs::TreeVec; use crate::core::poly::circle::CircleEvaluation; use crate::core::poly::BitReversedOrder; - use crate::core::{ColumnVec, InteractionElements}; + use crate::core::{ColumnVec, InteractionElements, LookupValues}; use crate::m31; use crate::trace_generation::TraceGenerator; pub struct ComponentA { @@ -85,6 +85,7 @@ mod tests { _mask: &TreeVec>>, _evaluation_accumulator: &mut PointEvaluationAccumulator, _interaction_elements: &InteractionElements, + _lookup_values: &LookupValues, ) { todo!() }