winter_prover/constraints/commitment/
default.rsuse alloc::vec::Vec;
use core::marker::PhantomData;
use air::{proof::Queries, PartitionOptions};
use crypto::{ElementHasher, VectorCommitment};
use math::FieldElement;
use tracing::info_span;
use super::{ConstraintCommitment, RowMatrix};
use crate::{CompositionPoly, CompositionPolyTrace, StarkDomain, DEFAULT_SEGMENT_WIDTH};
pub struct DefaultConstraintCommitment<
E: FieldElement,
H: ElementHasher<BaseField = E::BaseField>,
V: VectorCommitment<H>,
> {
evaluations: RowMatrix<E>,
vector_commitment: V,
_h: PhantomData<H>,
}
impl<E, H, V> DefaultConstraintCommitment<E, H, V>
where
E: FieldElement,
H: ElementHasher<BaseField = E::BaseField>,
V: VectorCommitment<H>,
{
pub fn new(
composition_poly_trace: CompositionPolyTrace<E>,
num_constraint_composition_columns: usize,
domain: &StarkDomain<E::BaseField>,
partition_options: PartitionOptions,
) -> (Self, CompositionPoly<E>) {
let (evaluations, commitment, composition_poly) = build_constraint_commitment::<E, H, V>(
composition_poly_trace,
num_constraint_composition_columns,
domain,
partition_options,
);
assert_eq!(
evaluations.num_rows(),
commitment.domain_len(),
"number of rows in constraint evaluation matrix must be the same as the size \
of the vector commitment domain"
);
let commitment = Self {
evaluations,
vector_commitment: commitment,
_h: PhantomData,
};
(commitment, composition_poly)
}
}
impl<E, H, V> ConstraintCommitment<E> for DefaultConstraintCommitment<E, H, V>
where
E: FieldElement,
H: ElementHasher<BaseField = E::BaseField> + core::marker::Sync,
V: VectorCommitment<H> + core::marker::Sync,
{
type HashFn = H;
type VC = V;
fn commitment(&self) -> H::Digest {
self.vector_commitment.commitment()
}
fn query(self, positions: &[usize]) -> Queries {
let opening_proof = self
.vector_commitment
.open_many(positions)
.expect("failed to generate a batch opening proof for constraint queries");
let mut evaluations = Vec::new();
for &position in positions {
let row = self.evaluations.row(position).to_vec();
evaluations.push(row);
}
Queries::new::<H, E, V>(opening_proof.1, evaluations)
}
}
fn build_constraint_commitment<E, H, V>(
composition_poly_trace: CompositionPolyTrace<E>,
num_constraint_composition_columns: usize,
domain: &StarkDomain<E::BaseField>,
partition_options: PartitionOptions,
) -> (RowMatrix<E>, V, CompositionPoly<E>)
where
E: FieldElement,
H: ElementHasher<BaseField = E::BaseField>,
V: VectorCommitment<H>,
{
let composition_poly = info_span!(
"build_composition_poly_columns",
num_columns = num_constraint_composition_columns
)
.in_scope(|| {
CompositionPoly::new(composition_poly_trace, domain, num_constraint_composition_columns)
});
assert_eq!(composition_poly.num_columns(), num_constraint_composition_columns);
assert_eq!(composition_poly.column_degree(), domain.trace_length() - 1);
let domain_size = domain.lde_domain_size();
let composed_evaluations = info_span!("evaluate_composition_poly_columns").in_scope(|| {
RowMatrix::evaluate_polys_over::<DEFAULT_SEGMENT_WIDTH>(composition_poly.data(), domain)
});
assert_eq!(composed_evaluations.num_cols(), num_constraint_composition_columns);
assert_eq!(composed_evaluations.num_rows(), domain_size);
let commitment = info_span!(
"compute_constraint_evaluation_commitment",
log_domain_size = domain_size.ilog2()
)
.in_scope(|| composed_evaluations.commit_to_rows::<H, V>(partition_options));
(composed_evaluations, commitment, composition_poly)
}