diff --git a/evm/src/prover.rs b/evm/src/prover.rs index 414b8d50de..6d8bfd315b 100644 --- a/evm/src/prover.rs +++ b/evm/src/prover.rs @@ -4,10 +4,11 @@ use anyhow::{ensure, Result}; use itertools::Itertools; use once_cell::sync::Lazy; use plonky2::field::extension::Extendable; +use plonky2::field::fft::ifft; use plonky2::field::packable::Packable; use plonky2::field::packed::PackedField; use plonky2::field::polynomial::{PolynomialCoeffs, PolynomialValues}; -use plonky2::field::types::Field; +use plonky2::field::types::{Field, SmallPowers}; use plonky2::field::zero_poly_coset::ZeroPolyOnCoset; use plonky2::fri::oracle::PolynomialBatch; use plonky2::hash::hash_types::RichField; @@ -498,11 +499,29 @@ where // When opening the `Z`s polys at the "next" point, need to look at the point `next_step` steps away. let next_step = 1 << quotient_degree_bits; - // Evaluation of the first Lagrange polynomial on the LDE domain. - let lagrange_first = PolynomialValues::selector(degree, 0).lde_onto_coset(quotient_degree_bits); - // Evaluation of the last Lagrange polynomial on the LDE domain. - let lagrange_last = - PolynomialValues::selector(degree, degree - 1).lde_onto_coset(quotient_degree_bits); + // Evaluation of the first Lagrange polynomial on the LDE domain, with custom lde_onto_coset. + let lagrange_first = PolynomialValues::::selector(degree, 0); + let coeffs = ifft(lagrange_first).lde(quotient_degree_bits); + let powers_vec = SmallPowers::::new(F::coset_shift().to_noncanonical_u64() as u32) + .take(degree << quotient_degree_bits) + .collect_vec(); + let modified_poly: PolynomialCoeffs = powers_vec + .iter() + .zip(&coeffs.coeffs) + .map(|(&r, &c)| r * c) + .collect::>() + .into(); + let lagrange_first = modified_poly.fft_with_options(None, None); + // Evaluation of the last Lagrange polynomial on the LDE domain, with custom lde_onto_coset. + let lagrange_last = PolynomialValues::::selector(degree, degree - 1); + let coeffs = ifft(lagrange_last).lde(quotient_degree_bits); + let modified_poly: PolynomialCoeffs = powers_vec + .iter() + .zip(&coeffs.coeffs) + .map(|(&r, &c)| r * c) + .collect::>() + .into(); + let lagrange_last = modified_poly.fft_with_options(None, None); let z_h_on_coset = ZeroPolyOnCoset::::new(degree_bits, quotient_degree_bits); diff --git a/plonky2/src/fri/oracle.rs b/plonky2/src/fri/oracle.rs index dca3202ac1..7397fbf954 100644 --- a/plonky2/src/fri/oracle.rs +++ b/plonky2/src/fri/oracle.rs @@ -2,7 +2,7 @@ use alloc::format; use alloc::vec::Vec; use itertools::Itertools; -use plonky2_field::types::Field; +use plonky2_field::types::{Field, SmallPowers}; use plonky2_maybe_rayon::*; use crate::field::extension::Extendable; @@ -112,8 +112,17 @@ impl, C: GenericConfig, const D: usize> .par_iter() .map(|p| { assert_eq!(p.len(), degree, "Polynomial degrees inconsistent"); - p.lde(rate_bits) - .coset_fft_with_options(F::coset_shift(), Some(rate_bits), fft_root_table) + let poly = p.lde(rate_bits); + + // Custom coset_fft with small shift + let modified_poly: PolynomialCoeffs = + SmallPowers::::new(F::coset_shift().to_noncanonical_u64() as u32) + .zip(&poly.coeffs) + .map(|(r, &c)| r * c) + .collect::>() + .into(); + modified_poly + .fft_with_options(Some(rate_bits), fft_root_table) .values }) .chain( @@ -197,10 +206,18 @@ impl, C: GenericConfig, const D: usize> } let lde_final_poly = final_poly.lde(fri_params.config.rate_bits); + + // Custom coset_fft with small shift + let modified_poly: PolynomialCoeffs = + SmallPowers::::new(F::coset_shift().to_noncanonical_u64() as u32) + .zip(&lde_final_poly.coeffs) + .map(|(r, &c)| r * c) + .collect::>() + .into(); let lde_final_values = timed!( timing, &format!("perform final FFT {}", lde_final_poly.len()), - lde_final_poly.coset_fft(F::coset_shift().into()) + modified_poly.fft_with_options(None, None) ); let fri_proof = fri_proof::( diff --git a/starky/src/prover.rs b/starky/src/prover.rs index 62a5987d2f..c3e13be012 100644 --- a/starky/src/prover.rs +++ b/starky/src/prover.rs @@ -4,10 +4,11 @@ use core::iter::once; use anyhow::{ensure, Result}; use itertools::Itertools; use plonky2::field::extension::Extendable; +use plonky2::field::fft::ifft; use plonky2::field::packable::Packable; use plonky2::field::packed::PackedField; use plonky2::field::polynomial::{PolynomialCoeffs, PolynomialValues}; -use plonky2::field::types::Field; +use plonky2::field::types::{Field, SmallPowers}; use plonky2::field::zero_poly_coset::ZeroPolyOnCoset; use plonky2::fri::oracle::PolynomialBatch; use plonky2::hash::hash_types::RichField; @@ -227,12 +228,29 @@ where // When opening the `Z`s polys at the "next" point, need to look at the point `next_step` steps away. let next_step = 1 << quotient_degree_bits; - // Evaluation of the first Lagrange polynomial on the LDE domain. - let lagrange_first = PolynomialValues::selector(degree, 0).lde_onto_coset(quotient_degree_bits); - // Evaluation of the last Lagrange polynomial on the LDE domain. - let lagrange_last = - PolynomialValues::selector(degree, degree - 1).lde_onto_coset(quotient_degree_bits); - + // Evaluation of the first Lagrange polynomial on the LDE domain, with custom lde_onto_coset. + let lagrange_first = PolynomialValues::::selector(degree, 0); + let coeffs = ifft(lagrange_first).lde(quotient_degree_bits); + let powers_vec = SmallPowers::::new(F::coset_shift().to_noncanonical_u64() as u32) + .take(degree << quotient_degree_bits) + .collect_vec(); + let modified_poly: PolynomialCoeffs = powers_vec + .iter() + .zip(&coeffs.coeffs) + .map(|(&r, &c)| r * c) + .collect::>() + .into(); + let lagrange_first = modified_poly.fft_with_options(None, None); + // Evaluation of the last Lagrange polynomial on the LDE domain, with custom lde_onto_coset. + let lagrange_last = PolynomialValues::::selector(degree, degree - 1); + let coeffs = ifft(lagrange_last).lde(quotient_degree_bits); + let modified_poly: PolynomialCoeffs = powers_vec + .iter() + .zip(&coeffs.coeffs) + .map(|(&r, &c)| r * c) + .collect::>() + .into(); + let lagrange_last = modified_poly.fft_with_options(None, None); let z_h_on_coset = ZeroPolyOnCoset::::new(degree_bits, quotient_degree_bits); // Retrieve the LDE values at index `i`.