Skip to content

Commit

Permalink
Add eval order and interpolate to SecureEvaluation (#794)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewmilson authored Aug 21, 2024
1 parent 61e6c27 commit f976890
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 105 deletions.
21 changes: 11 additions & 10 deletions crates/prover/src/core/backend/cpu/fri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::core::fri::{fold_circle_into_line, fold_line, FriOps};
use crate::core::poly::circle::SecureEvaluation;
use crate::core::poly::line::LineEvaluation;
use crate::core::poly::twiddles::TwiddleTree;
use crate::core::poly::BitReversedOrder;

// TODO(spapini): Optimized these functions as well.
impl FriOps for CpuBackend {
Expand All @@ -18,14 +19,16 @@ impl FriOps for CpuBackend {
}
fn fold_circle_into_line(
dst: &mut LineEvaluation<Self>,
src: &SecureEvaluation<Self>,
src: &SecureEvaluation<Self, BitReversedOrder>,
alpha: SecureField,
_twiddles: &TwiddleTree<Self>,
) {
fold_circle_into_line(dst, src, alpha)
}

fn decompose(eval: &SecureEvaluation<Self>) -> (SecureEvaluation<Self>, SecureField) {
fn decompose(
eval: &SecureEvaluation<Self, BitReversedOrder>,
) -> (SecureEvaluation<Self, BitReversedOrder>, SecureField) {
let lambda = Self::decomposition_coefficient(eval);
let mut g_values = unsafe { SecureColumnByCoords::<Self>::uninitialized(eval.len()) };

Expand All @@ -43,10 +46,7 @@ impl FriOps for CpuBackend {
g_values.set(i, val);
}

let g = SecureEvaluation {
domain: eval.domain,
values: g_values,
};
let g = SecureEvaluation::new(eval.domain, g_values);
(g, lambda)
}
}
Expand All @@ -67,7 +67,7 @@ impl CpuBackend {
/// This function assumes the blowupfactor is 2
///
/// [`CirclePoly`]: crate::core::poly::circle::CirclePoly
fn decomposition_coefficient(eval: &SecureEvaluation<Self>) -> SecureField {
fn decomposition_coefficient(eval: &SecureEvaluation<Self, BitReversedOrder>) -> SecureField {
let domain_size = 1 << eval.domain.log_size();
let half_domain_size = domain_size / 2;

Expand Down Expand Up @@ -96,6 +96,7 @@ mod tests {
use crate::core::fields::secure_column::SecureColumnByCoords;
use crate::core::fri::FriOps;
use crate::core::poly::circle::{CanonicCoset, SecureEvaluation};
use crate::core::poly::BitReversedOrder;
use crate::m31;

#[test]
Expand All @@ -121,10 +122,10 @@ mod tests {
values.values.clone(),
],
};
let secure_eval = SecureEvaluation::<CpuBackend> {
let secure_eval = SecureEvaluation::<CpuBackend, BitReversedOrder>::new(
domain,
values: secure_column.clone(),
};
secure_column.clone(),
);

let (g, lambda) = CpuBackend::decompose(&secure_eval);

Expand Down
4 changes: 2 additions & 2 deletions crates/prover/src/core/backend/cpu/quotients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl QuotientOps for CpuBackend {
random_coeff: SecureField,
sample_batches: &[ColumnSampleBatch],
_log_blowup_factor: u32,
) -> SecureEvaluation<Self> {
) -> SecureEvaluation<Self, BitReversedOrder> {
let mut values = unsafe { SecureColumnByCoords::uninitialized(domain.size()) };
let quotient_constants = quotient_constants(sample_batches, random_coeff, domain);

Expand All @@ -36,7 +36,7 @@ impl QuotientOps for CpuBackend {
);
values.set(row, row_value);
}
SecureEvaluation { domain, values }
SecureEvaluation::new(domain, values)
}
}

Expand Down
39 changes: 15 additions & 24 deletions crates/prover/src/core/backend/simd/fri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::core::poly::circle::SecureEvaluation;
use crate::core::poly::line::LineEvaluation;
use crate::core::poly::twiddles::TwiddleTree;
use crate::core::poly::utils::domain_line_twiddles_from_tree;
use crate::core::poly::BitReversedOrder;

impl FriOps for SimdBackend {
fn fold_line(
Expand Down Expand Up @@ -57,7 +58,7 @@ impl FriOps for SimdBackend {

fn fold_circle_into_line(
dst: &mut LineEvaluation<Self>,
src: &SecureEvaluation<Self>,
src: &SecureEvaluation<Self, BitReversedOrder>,
alpha: SecureField,
twiddles: &TwiddleTree<Self>,
) {
Expand Down Expand Up @@ -96,7 +97,9 @@ impl FriOps for SimdBackend {
}
}

fn decompose(eval: &SecureEvaluation<Self>) -> (SecureEvaluation<Self>, SecureField) {
fn decompose(
eval: &SecureEvaluation<Self, BitReversedOrder>,
) -> (SecureEvaluation<Self, BitReversedOrder>, SecureField) {
let lambda = decomposition_coefficient(eval);
let broadcasted_lambda = PackedSecureField::broadcast(lambda);
let mut g_values = SecureColumnByCoords::<Self>::zeros(eval.len());
Expand All @@ -112,18 +115,17 @@ impl FriOps for SimdBackend {
unsafe { g_values.set_packed(i, val) }
}

let g = SecureEvaluation {
domain: eval.domain,
values: g_values,
};
let g = SecureEvaluation::new(eval.domain, g_values);
(g, lambda)
}
}

/// See [`decomposition_coefficient`].
///
/// [`decomposition_coefficient`]: crate::core::backend::cpu::CpuBackend::decomposition_coefficient
fn decomposition_coefficient(eval: &SecureEvaluation<SimdBackend>) -> SecureField {
fn decomposition_coefficient(
eval: &SecureEvaluation<SimdBackend, BitReversedOrder>,
) -> SecureField {
let cols = &eval.values.columns;
let [mut x_sum, mut y_sum, mut z_sum, mut w_sum] = [PackedBaseField::zero(); 4];

Expand Down Expand Up @@ -167,6 +169,7 @@ mod tests {
use crate::core::fri::FriOps;
use crate::core::poly::circle::{CanonicCoset, CirclePoly, PolyOps, SecureEvaluation};
use crate::core::poly::line::{LineDomain, LineEvaluation};
use crate::core::poly::BitReversedOrder;
use crate::qm31;

#[test]
Expand Down Expand Up @@ -206,10 +209,7 @@ mod tests {
);
CpuBackend::fold_circle_into_line(
&mut cpu_fold,
&SecureEvaluation {
domain: circle_domain,
values: values.iter().copied().collect(),
},
&SecureEvaluation::new(circle_domain, values.iter().copied().collect()),
alpha,
&CpuBackend::precompute_twiddles(line_domain.coset()),
);
Expand All @@ -220,10 +220,7 @@ mod tests {
);
SimdBackend::fold_circle_into_line(
&mut simd_fold,
&SecureEvaluation {
domain: circle_domain,
values: values.iter().copied().collect(),
},
&SecureEvaluation::new(circle_domain, values.iter().copied().collect()),
alpha,
&SimdBackend::precompute_twiddles(line_domain.coset()),
);
Expand All @@ -250,16 +247,10 @@ mod tests {
values.values.clone(),
],
};
let avx_eval = SecureEvaluation {
domain,
values: avx_column.clone(),
};
let cpu_eval = SecureEvaluation::<CpuBackend> {
domain,
values: avx_eval.to_cpu(),
};
let avx_eval = SecureEvaluation::new(domain, avx_column.clone());
let cpu_eval =
SecureEvaluation::<CpuBackend, BitReversedOrder>::new(domain, avx_eval.to_cpu());
let (cpu_g, cpu_lambda) = CpuBackend::decompose(&cpu_eval);

let (avx_g, avx_lambda) = SimdBackend::decompose(&avx_eval);

assert_eq!(avx_lambda, cpu_lambda);
Expand Down
7 changes: 2 additions & 5 deletions crates/prover/src/core/backend/simd/quotients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl QuotientOps for SimdBackend {
random_coeff: SecureField,
sample_batches: &[ColumnSampleBatch],
log_blowup_factor: u32,
) -> SecureEvaluation<Self> {
) -> SecureEvaluation<Self, BitReversedOrder> {
// Split the domain into a subdomain and a shift coset.
// TODO(spapini): Move to the caller when Columns support slices.
let (subdomain, mut subdomain_shifts) = domain.split(log_blowup_factor);
Expand Down Expand Up @@ -74,10 +74,7 @@ impl QuotientOps for SimdBackend {
}
span.exit();

SecureEvaluation {
domain,
values: extended_eval,
}
SecureEvaluation::new(domain, extended_eval)
}
}

Expand Down
66 changes: 20 additions & 46 deletions crates/prover/src/core/fri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pub trait FriOps: FieldOps<BaseField> + PolyOps + Sized + FieldOps<SecureField>
// TODO(andrew): Fold directly into FRI layer to prevent allocation.
fn fold_circle_into_line(
dst: &mut LineEvaluation<Self>,
src: &SecureEvaluation<Self>,
src: &SecureEvaluation<Self, BitReversedOrder>,
alpha: SecureField,
twiddles: &TwiddleTree<Self>,
);
Expand All @@ -119,7 +119,9 @@ pub trait FriOps: FieldOps<BaseField> + PolyOps + Sized + FieldOps<SecureField>
/// FRI-space: polynomials of total degree n/2.
/// Based on lemma #12 from the CircleStark paper: f(P) = g(P)+ lambda * alternating(P),
/// where lambda is the cosset diff of eval, and g is a polynomial in the fft-space.
fn decompose(eval: &SecureEvaluation<Self>) -> (SecureEvaluation<Self>, SecureField);
fn decompose(
eval: &SecureEvaluation<Self, BitReversedOrder>,
) -> (SecureEvaluation<Self, BitReversedOrder>, SecureField);
}
/// A FRI prover that applies the FRI protocol to prove a set of polynomials are of low degree.
pub struct FriProver<B: FriOps + MerkleOps<MC::H>, MC: MerkleChannel> {
Expand Down Expand Up @@ -154,7 +156,7 @@ impl<B: FriOps + MerkleOps<MC::H>, MC: MerkleChannel> FriProver<B, MC> {
pub fn commit(
channel: &mut MC::C,
config: FriConfig,
columns: &[SecureEvaluation<B>],
columns: &[SecureEvaluation<B, BitReversedOrder>],
twiddles: &TwiddleTree<B>,
) -> Self {
let _span = span!(Level::INFO, "FRI commitment").entered();
Expand Down Expand Up @@ -186,11 +188,12 @@ impl<B: FriOps + MerkleOps<MC::H>, MC: MerkleChannel> FriProver<B, MC> {
fn commit_inner_layers(
channel: &mut MC::C,
config: FriConfig,
columns: &[SecureEvaluation<B>],
columns: &[SecureEvaluation<B, BitReversedOrder>],
twiddles: &TwiddleTree<B>,
) -> (Vec<FriLayerProver<B, MC::H>>, LineEvaluation<B>) {
// Returns the length of the [LineEvaluation] a [CircleEvaluation] gets folded into.
let folded_len = |e: &SecureEvaluation<B>| e.len() >> CIRCLE_TO_LINE_FOLD_STEP;
let folded_len =
|e: &SecureEvaluation<B, BitReversedOrder>| e.len() >> CIRCLE_TO_LINE_FOLD_STEP;

let first_layer_size = folded_len(&columns[0]);
let first_layer_domain = LineDomain::new(Coset::half_odds(first_layer_size.ilog2()));
Expand Down Expand Up @@ -538,21 +541,6 @@ fn get_opening_positions(
positions
}

pub trait FriChannel {
type Digest;

type Field;

/// Reseeds the channel with a commitment to an inner FRI layer.
fn reseed_with_inner_layer(&mut self, commitment: &Self::Digest);

/// Reseeds the channel with the FRI last layer polynomial.
fn reseed_with_last_layer(&mut self, last_layer: &LinePoly);

/// Draws a random field element.
fn draw(&mut self) -> Self::Field;
}

#[derive(Clone, Copy, Debug, Error)]
pub enum FriVerificationError {
#[error("proof contains an invalid number of FRI layers")]
Expand Down Expand Up @@ -876,10 +864,7 @@ impl SparseCircleEvaluation {
let mut buffer = LineEvaluation::new_zero(buffer_domain);
fold_circle_into_line(
&mut buffer,
&SecureEvaluation {
domain: e.domain,
values: e.values.into_iter().collect(),
},
&SecureEvaluation::new(e.domain, e.values.into_iter().collect()),
alpha,
);
buffer.values.at(0)
Expand Down Expand Up @@ -957,7 +942,7 @@ pub fn fold_line(
/// See [`FriOps::fold_circle_into_line`].
pub fn fold_circle_into_line(
dst: &mut LineEvaluation<CpuBackend>,
src: &SecureEvaluation<CpuBackend>,
src: &SecureEvaluation<CpuBackend, BitReversedOrder>,
alpha: SecureField,
) {
assert_eq!(src.len() >> CIRCLE_TO_LINE_FOLD_STEP, dst.len());
Expand Down Expand Up @@ -993,19 +978,18 @@ mod tests {

use super::{get_opening_positions, FriVerificationError, SparseCircleEvaluation};
use crate::core::backend::cpu::{CpuCircleEvaluation, CpuCirclePoly};
use crate::core::backend::{Col, Column, ColumnOps, CpuBackend};
use crate::core::backend::{ColumnOps, CpuBackend};
use crate::core::circle::{CirclePointIndex, Coset};
use crate::core::fields::m31::BaseField;
use crate::core::fields::qm31::SecureField;
use crate::core::fields::secure_column::SecureColumnByCoords;
use crate::core::fields::Field;
use crate::core::fri::{
fold_circle_into_line, fold_line, CirclePolyDegreeBound, FriConfig,
CIRCLE_TO_LINE_FOLD_STEP,
};
use crate::core::poly::circle::{CircleDomain, PolyOps, SecureEvaluation};
use crate::core::poly::line::{LineDomain, LineEvaluation, LinePoly};
use crate::core::poly::NaturalOrder;
use crate::core::poly::{BitReversedOrder, NaturalOrder};
use crate::core::queries::{Queries, SparseSubCircleDomain};
use crate::core::test_utils::test_channel;
use crate::core::utils::bit_reverse_index;
Expand Down Expand Up @@ -1089,10 +1073,10 @@ mod tests {
fn committing_evaluation_from_invalid_domain_fails() {
let invalid_domain = CircleDomain::new(Coset::new(CirclePointIndex::generator(), 3));
assert!(!invalid_domain.is_canonic(), "must be an invalid domain");
let evaluation = SecureEvaluation {
domain: invalid_domain,
values: vec![SecureField::one(); 1 << 4].into_iter().collect(),
};
let evaluation = SecureEvaluation::new(
invalid_domain,
vec![SecureField::one(); 1 << 4].into_iter().collect(),
);

FriProver::commit(
&mut test_channel(),
Expand Down Expand Up @@ -1388,22 +1372,12 @@ mod tests {
fn polynomial_evaluation(
log_degree: u32,
log_blowup_factor: u32,
) -> SecureEvaluation<CpuBackend> {
) -> SecureEvaluation<CpuBackend, BitReversedOrder> {
let poly = CpuCirclePoly::new(vec![BaseField::one(); 1 << log_degree]);
let coset = Coset::half_odds(log_degree + log_blowup_factor - 1);
let domain = CircleDomain::new(coset);
let values = poly.evaluate(domain);
SecureEvaluation {
domain,
values: SecureColumnByCoords {
columns: [
values.values,
Col::<CpuBackend, BaseField>::zeros(1 << (log_degree + log_blowup_factor)),
Col::<CpuBackend, BaseField>::zeros(1 << (log_degree + log_blowup_factor)),
Col::<CpuBackend, BaseField>::zeros(1 << (log_degree + log_blowup_factor)),
],
},
}
SecureEvaluation::new(domain, values.into_iter().map(SecureField::from).collect())
}

/// Returns the log degree bound of a polynomial.
Expand All @@ -1415,7 +1389,7 @@ mod tests {

// TODO: Remove after SubcircleDomain integration.
fn query_polynomial(
polynomial: &SecureEvaluation<CpuBackend>,
polynomial: &SecureEvaluation<CpuBackend, BitReversedOrder>,
queries: &Queries,
) -> SparseCircleEvaluation {
let polynomial_log_size = polynomial.domain.log_size();
Expand All @@ -1425,7 +1399,7 @@ mod tests {
}

fn open_polynomial(
polynomial: &SecureEvaluation<CpuBackend>,
polynomial: &SecureEvaluation<CpuBackend, BitReversedOrder>,
positions: &SparseSubCircleDomain,
) -> SparseCircleEvaluation {
let coset_evals = positions
Expand Down
2 changes: 1 addition & 1 deletion crates/prover/src/core/pcs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub use self::utils::TreeVec;
pub use self::verifier::CommitmentSchemeVerifier;
use super::fri::FriConfig;

#[derive(Copy, Debug, Clone)]
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
pub struct TreeColumnSpan {
pub tree_index: usize,
pub col_start: usize,
Expand Down
Loading

0 comments on commit f976890

Please sign in to comment.