pub fn verify_values(
&self,
sampled_points: TreeVec<ColumnVec<Vec<CirclePoint<SecureField>>>>,
proof: CommitmentSchemeProof<MC::H>,
channel: &mut MC::C,
) -> Result<(), VerificationError> {
channel.mix_felts(&proof.sampled_values.clone().flatten_cols());
let random_coeff = channel.draw_secure_felt();
let bounds = self
.column_log_sizes()
.flatten()
.into_iter()
.sorted()
.rev()
.dedup()
.map(|log_size| {
CirclePolyDegreeBound::new(log_size - self.config.fri_config.log_blowup_factor)
})
.collect_vec();
// FRI commitment phase on OODS quotients.
let mut fri_verifier =
FriVerifier::<MC>::commit(channel, self.config.fri_config, proof.fri_proof, bounds)?;
// Verify proof of work.
channel.mix_u64(proof.proof_of_work);
if channel.trailing_zeros() < self.config.pow_bits {
return Err(VerificationError::ProofOfWork);
}
// Get FRI query positions.
let query_positions_per_log_size = fri_verifier.sample_query_positions(channel);
// Verify merkle decommitments.
self.trees
.as_ref()
.zip_eq(proof.decommitments)
.zip_eq(proof.queried_values.clone())
.map(|((tree, decommitment), queried_values)| {
tree.verify(&query_positions_per_log_size, queried_values, decommitment)
})
.0
.into_iter()
.collect::<Result<(), _>>()?;
// Answer FRI queries.
let samples = sampled_points.zip_cols(proof.sampled_values).map_cols(
|(sampled_points, sampled_values)| {
zip(sampled_points, sampled_values)
.map(|(point, value)| PointSample { point, value })
.collect_vec()
},
);
let n_columns_per_log_size = self.trees.as_ref().map(|tree| &tree.n_columns_per_log_size);
let fri_answers = fri_answers(
self.column_log_sizes(),
samples,
random_coeff,
&query_positions_per_log_size,
proof.queried_values,
n_columns_per_log_size,
)?;
fri_verifier.decommit(fri_answers)?;
Ok(())
}