use std_shims::{vec, String};
use thiserror::Error;
use crate::core::air::{Component, Components};
use crate::core::channel::{Channel, MerkleChannel};
use crate::core::circle::CirclePoint;
use crate::core::fields::qm31::{SecureField, SECURE_EXTENSION_DEGREE};
use crate::core::fri::FriVerificationError;
use crate::core::pcs::utils::get_lifting_log_size;
use crate::core::pcs::CommitmentSchemeVerifier;
use crate::core::proof::StarkProof;
use crate::core::vcs_lifted::verifier::MerkleVerificationError;
pub const PREPROCESSED_TRACE_IDX: usize = 0;
pub const COMPOSITION_LOG_SPLIT: u32 = 1;
pub fn verify<MC: MerkleChannel>(
components: &[&dyn Component],
channel: &mut MC::C,
commitment_scheme: &mut CommitmentSchemeVerifier<MC>,
proof: StarkProof<MC::H>,
) -> Result<(), VerificationError> {
let include_all_preprocessed_columns = false;
verify_ex(
components,
channel,
commitment_scheme,
proof,
include_all_preprocessed_columns,
)
}
pub fn verify_ex<MC: MerkleChannel>(
components: &[&dyn Component],
channel: &mut MC::C,
commitment_scheme: &mut CommitmentSchemeVerifier<MC>,
proof: StarkProof<MC::H>,
include_all_preprocessed_columns: bool,
) -> Result<(), VerificationError> {
let n_preprocessed_columns = commitment_scheme.trees[PREPROCESSED_TRACE_IDX]
.column_log_sizes
.len();
let components = Components {
components: components.to_vec(),
n_preprocessed_columns,
};
let split_composition_log_degree_bound =
components.composition_log_degree_bound() - COMPOSITION_LOG_SPLIT;
tracing::info!(
"Split composition polynomial log degree bound: {}",
split_composition_log_degree_bound
);
let lifting_log_size = get_lifting_log_size(
&commitment_scheme.config,
split_composition_log_degree_bound + commitment_scheme.config.fri_config.log_blowup_factor,
);
if include_all_preprocessed_columns {
assert!(lifting_log_size >= commitment_scheme.trees[PREPROCESSED_TRACE_IDX].height);
}
let max_log_degree_bound =
lifting_log_size - commitment_scheme.config.fri_config.log_blowup_factor;
let random_coeff = channel.draw_secure_felt();
commitment_scheme.commit(
*proof.commitments.last().unwrap(),
&[max_log_degree_bound; 2 * SECURE_EXTENSION_DEGREE],
channel,
);
let oods_point = CirclePoint::<SecureField>::get_random_point(channel);
let mut sample_points = components.mask_points(
oods_point,
max_log_degree_bound,
include_all_preprocessed_columns,
);
sample_points.push(vec![vec![oods_point]; 2 * SECURE_EXTENSION_DEGREE]);
let sample_points_by_column = sample_points.as_cols_ref().flatten();
tracing::info!("Sampling {} columns.", sample_points_by_column.len());
tracing::info!(
"Total sample points: {}.",
sample_points_by_column.into_iter().flatten().count()
);
let composition_oods_eval = proof
.extract_composition_oods_eval(oods_point, max_log_degree_bound)
.ok_or(VerificationError::InvalidStructure(
std_shims::ToString::to_string(&"Unexpected sampled_values structure"),
))?;
if composition_oods_eval
!= components.eval_composition_polynomial_at_point(
oods_point,
&proof.sampled_values,
random_coeff,
max_log_degree_bound,
)
{
return Err(VerificationError::OodsNotMatching);
}
commitment_scheme.verify_values(sample_points, proof.0, channel)
}
#[derive(Clone, Debug, Error)]
pub enum VerificationError {
#[error("Proof has invalid structure: {0}.")]
InvalidStructure(String),
#[error(transparent)]
Merkle(#[from] MerkleVerificationError),
#[error(
"The composition polynomial OODS value does not match the trace OODS values
(DEEP-ALI failure)."
)]
OodsNotMatching,
#[error(transparent)]
Fri(#[from] FriVerificationError),
#[error("Proof of work verification failed.")]
ProofOfWork,
}