Skip to main content

stwo_gpu/core/
verifier.rs

1use std_shims::{vec, String};
2use thiserror::Error;
3
4use crate::core::air::{Component, Components};
5use crate::core::channel::{Channel, MerkleChannel};
6use crate::core::circle::CirclePoint;
7use crate::core::fields::qm31::{SecureField, SECURE_EXTENSION_DEGREE};
8use crate::core::fri::FriVerificationError;
9use crate::core::pcs::CommitmentSchemeVerifier;
10use crate::core::proof::StarkProof;
11use crate::core::vcs_lifted::verifier::MerkleVerificationError;
12pub const PREPROCESSED_TRACE_IDX: usize = 0;
13
14// TODO(Leo): remove this once the composition poly split can be dependant on a config instead of
15// being hardcoded.
16pub const COMPOSITION_LOG_SPLIT: u32 = 1;
17
18pub fn verify<MC: MerkleChannel>(
19    components: &[&dyn Component],
20    channel: &mut MC::C,
21    commitment_scheme: &mut CommitmentSchemeVerifier<MC>,
22    proof: StarkProof<MC::H>,
23) -> Result<(), VerificationError> {
24    let n_preprocessed_columns = commitment_scheme.trees[PREPROCESSED_TRACE_IDX]
25        .column_log_sizes
26        .len();
27
28    let components = Components {
29        components: components.to_vec(),
30        n_preprocessed_columns,
31    };
32    let composition_log_size = components.composition_log_degree_bound();
33    tracing::info!(
34        "Composition polynomial log degree bound: {}",
35        composition_log_size
36    );
37    let random_coeff = channel.draw_secure_felt();
38
39    // Read composition polynomial commitment.
40    commitment_scheme.commit(
41        *proof.commitments.last().unwrap(),
42        &[composition_log_size - 1; 2 * SECURE_EXTENSION_DEGREE],
43        channel,
44    );
45
46    // Draw OODS point.
47    let oods_point = CirclePoint::<SecureField>::get_random_point(channel);
48    // The max degree of a committed polynomial is equal to the degree of the composition poly /
49    // 2^COMPOSITION_LOG_SPLIT.
50    let max_log_degree_bound = composition_log_size - COMPOSITION_LOG_SPLIT;
51    // Get mask sample points relative to oods point.
52    let mut sample_points = components.mask_points(oods_point, max_log_degree_bound, false);
53    // Add the composition polynomial mask points.
54    sample_points.push(vec![vec![oods_point]; 2 * SECURE_EXTENSION_DEGREE]);
55
56    let sample_points_by_column = sample_points.as_cols_ref().flatten();
57    tracing::info!("Sampling {} columns.", sample_points_by_column.len());
58    tracing::info!(
59        "Total sample points: {}.",
60        sample_points_by_column.into_iter().flatten().count()
61    );
62
63    let composition_oods_eval = proof
64        .extract_composition_oods_eval(oods_point, composition_log_size)
65        .ok_or(VerificationError::InvalidStructure(
66            std_shims::ToString::to_string(&"Unexpected sampled_values structure"),
67        ))?;
68
69    if composition_oods_eval
70        != components.eval_composition_polynomial_at_point(
71            oods_point,
72            &proof.sampled_values,
73            random_coeff,
74            max_log_degree_bound,
75        )
76    {
77        return Err(VerificationError::OodsNotMatching);
78    }
79
80    commitment_scheme.verify_values(sample_points, proof.0, channel)
81}
82
83#[derive(Clone, Debug, Error)]
84pub enum VerificationError {
85    #[error("Proof has invalid structure: {0}.")]
86    InvalidStructure(String),
87    #[error(transparent)]
88    Merkle(#[from] MerkleVerificationError),
89    #[error(
90        "The composition polynomial OODS value does not match the trace OODS values
91    (DEEP-ALI failure)."
92    )]
93    OodsNotMatching,
94    #[error(transparent)]
95    Fri(#[from] FriVerificationError),
96    #[error("Proof of work verification failed.")]
97    ProofOfWork,
98}