From 01a5a3cd6a680c43711c25cd9790dfdbd1430b1d Mon Sep 17 00:00:00 2001 From: Alon Haramati Date: Thu, 29 Feb 2024 12:16:42 +0200 Subject: [PATCH] Split CP into 4 BaseField columns. --- src/core/air/evaluation.rs | 16 +++++++++------- src/core/air/mod.rs | 4 ++-- src/core/poly/circle.rs | 35 +++++++++++++++++++++++++++++++++++ src/fibonacci/mod.rs | 21 +++++++++++++++------ src/lib.rs | 3 ++- 5 files changed, 63 insertions(+), 16 deletions(-) diff --git a/src/core/air/evaluation.rs b/src/core/air/evaluation.rs index bb4622b9e..604bca509 100644 --- a/src/core/air/evaluation.rs +++ b/src/core/air/evaluation.rs @@ -12,13 +12,16 @@ use crate::core::circle::CirclePoint; use crate::core::fields::m31::BaseField; use crate::core::fields::qm31::SecureField; use crate::core::fields::{Col, Column, ExtensionOf, Field}; -use crate::core::poly::circle::{CircleDomain, CirclePoly}; +use crate::core::poly::circle::{CircleDomain, CirclePoly, SecureCirclePoly}; use crate::core::utils::IteratorMutExt; use crate::core::{ColumnVec, ComponentVec}; +pub const SECURE_EXTENSION_DEGREE: usize = + >::EXTENSION_DEGREE; + // TODO(spapini): find a better place for this pub struct SecureColumn { - pub cols: [Col; >::EXTENSION_DEGREE], + pub cols: [Col; SECURE_EXTENSION_DEGREE], } impl SecureColumn { @@ -156,7 +159,7 @@ impl DomainEvaluationAccumulator { impl DomainEvaluationAccumulator { /// Computes f(P) as coefficients. - pub fn finalize(self) -> CirclePoly { + pub fn finalize(self) -> SecureCirclePoly { let mut res_coeffs = SecureColumn::::zeros(1 << self.log_size()); let res_log_size = self.log_size(); let res_size = 1 << res_log_size; @@ -179,7 +182,7 @@ impl DomainEvaluationAccumulator { .coeffs }), }; - // Add poly.coeffs into coeffs, elementwise, inplace. + // Add column coefficients into result coefficients, element-wise, in-place. let multiplier = self.random_coeff.pow(*n_cols as u128); for i in 0..res_size { let res_coeff = res_coeffs.at(i) * multiplier + coeffs.at(i); @@ -187,8 +190,7 @@ impl DomainEvaluationAccumulator { } } - // TODO(spapini): Return multiple polys instead. - CirclePoly::new((0..res_size).map(|i| res_coeffs.at(i)).collect::>()) + SecureCirclePoly(res_coeffs.cols.map(CirclePoly::new)) } } @@ -222,7 +224,7 @@ impl<'a> ConstraintEvaluator<'a, CPUBackend> { } } - pub fn finalize(self) -> CirclePoly { + pub fn finalize(self) -> SecureCirclePoly { self.evaluation_accumulator.finalize() } } diff --git a/src/core/air/mod.rs b/src/core/air/mod.rs index 2bc1a765c..669adc7d1 100644 --- a/src/core/air/mod.rs +++ b/src/core/air/mod.rs @@ -14,7 +14,7 @@ use super::circle::CirclePoint; use super::fields::m31::BaseField; use super::fields::qm31::SecureField; use super::fri::CirclePolyDegreeBound; -use super::poly::circle::{CanonicCoset, CirclePoly}; +use super::poly::circle::{CanonicCoset, CirclePoly, SecureCirclePoly}; use super::{ColumnVec, ComponentVec}; pub mod evaluation; @@ -40,7 +40,7 @@ pub trait AirExt: Air { &self, random_coeff: SecureField, component_traces: &[ComponentTrace<'_, CPUBackend>], - ) -> CirclePoly { + ) -> SecureCirclePoly { let mut evaluator = ConstraintEvaluator::new( component_traces, self.max_constraint_log_degree_bound(), diff --git a/src/core/poly/circle.rs b/src/core/poly/circle.rs index b5a36a734..4ebf4a842 100644 --- a/src/core/poly/circle.rs +++ b/src/core/poly/circle.rs @@ -4,9 +4,12 @@ use std::marker::PhantomData; use std::ops::{Deref, Index}; use super::{BitReversedOrder, NaturalOrder}; +use crate::core::air::evaluation::SECURE_EXTENSION_DEGREE; use crate::core::backend::cpu::CPUCircleEvaluation; +use crate::core::backend::CPUBackend; use crate::core::circle::{CirclePoint, CirclePointIndex, Coset, CosetIterator}; use crate::core::fields::m31::BaseField; +use crate::core::fields::qm31::SecureField; use crate::core::fields::{Col, Column, ExtensionOf, FieldOps}; use crate::core::utils::bit_reverse_index; @@ -400,6 +403,38 @@ impl> crate::core::backend::cpu::CPUCirclePoly { } } +pub struct SecureCirclePoly(pub [CirclePoly; SECURE_EXTENSION_DEGREE]); + +impl SecureCirclePoly { + pub fn eval_at_point(&self, point: CirclePoint) -> SecureField { + let mut res = self.0[0].eval_at_point(point); + res += self.0[1].eval_at_point(point) * SecureField::from_u32_unchecked(0, 1, 0, 0); + res += self.0[2].eval_at_point(point) * SecureField::from_u32_unchecked(0, 0, 1, 0); + res += self.0[3].eval_at_point(point) * SecureField::from_u32_unchecked(0, 0, 0, 1); + res + } + + // TODO(AlonH): Remove this temporary function. + pub fn to_circle_poly(&self) -> CirclePoly { + let coeffs_len = self[0].coeffs.len(); + let mut coeffs = Col::::zeros(coeffs_len); + #[allow(clippy::needless_range_loop)] + for index in 0..coeffs_len { + coeffs[index] = + SecureField::from_m31_array(std::array::from_fn(|i| self[i].coeffs[index])); + } + CirclePoly::new(coeffs) + } +} + +impl Deref for SecureCirclePoly { + type Target = [CirclePoly; SECURE_EXTENSION_DEGREE]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + #[derive(Clone, Debug)] pub struct PointMapping> { pub points: Vec>, diff --git a/src/fibonacci/mod.rs b/src/fibonacci/mod.rs index 0c4f861cf..505c525b9 100644 --- a/src/fibonacci/mod.rs +++ b/src/fibonacci/mod.rs @@ -7,6 +7,7 @@ use self::component::FibonacciComponent; use crate::commitment_scheme::blake2_hash::Blake2sHasher; use crate::commitment_scheme::hasher::Hasher; use crate::commitment_scheme::merkle_decommitment::MerkleDecommitment; +use crate::core::air::evaluation::SECURE_EXTENSION_DEGREE; use crate::core::air::{AirExt, ComponentTrace}; use crate::core::backend::CPUBackend; use crate::core::channel::{Blake2sChannel, Channel as ChannelTrait}; @@ -53,7 +54,7 @@ pub struct FibonacciProof { pub trace_commitments: Vec<::Hash>, pub trace_decommitments: Vec>, pub composition_polynomial_commitment: ::Hash, - pub composition_polynomial_decommitment: MerkleDecommitment, + pub composition_polynomial_decommitment: MerkleDecommitment, pub trace_oods_values: ComponentVec>, pub composition_polynomial_opened_values: Vec, pub trace_opened_values: Vec, @@ -116,8 +117,8 @@ impl Fibonacci { .air .compute_composition_polynomial(random_coeff, &component_traces); let composition_polynomial_commitment_scheme = CommitmentSchemeProver::new( - vec![composition_polynomial_poly], - vec![self.composition_polynomial_commitment_domain], + composition_polynomial_poly.to_vec(), + [self.composition_polynomial_commitment_domain; SECURE_EXTENSION_DEGREE].to_vec(), channel, ); @@ -127,16 +128,24 @@ impl Fibonacci { .air .mask_points_and_values(oods_point, &component_traces); let composition_polynomial_oods_value = - composition_polynomial_commitment_scheme.polynomials[0].eval_at_point(oods_point); + composition_polynomial_poly.eval_at_point(oods_point); // Calculate a quotient polynomial for each trace mask item and one for the composition // polynomial. let mut oods_quotients = Vec::with_capacity(trace_oods_points.len() + 1); + // TODO(AlonH): Remove this and use efficient evaluation. + let composition_polynomial_evaluation = composition_polynomial_poly + .to_circle_poly() + .evaluate( + self.composition_polynomial_commitment_domain + .circle_domain(), + ) + .bit_reverse(); oods_quotients.push( get_oods_quotient( oods_point, composition_polynomial_oods_value, - &composition_polynomial_commitment_scheme.evaluations[0], + &composition_polynomial_evaluation, ) .bit_reverse(), ); @@ -162,7 +171,7 @@ impl Fibonacci { // Decommit and get the values in the opening positions. let composition_polynomial_opened_values = composition_polynomial_decommitment_positions .iter() - .map(|p| composition_polynomial_commitment_scheme.evaluations[0].values[*p]) + .map(|p| composition_polynomial_evaluation.values[*p]) .collect(); let trace_opened_values = trace_decommitment_positions .iter() diff --git a/src/lib.rs b/src/lib.rs index 1c860b95b..4ee4907df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,8 @@ new_uninit, slice_group_by, stdsimd, - get_many_mut + get_many_mut, + int_roundings )] pub mod commitment_scheme; pub mod core;