winter_prover/constraints/commitment/
default.rs1use alloc::vec::Vec;
7use core::marker::PhantomData;
8
9use air::{proof::Queries, PartitionOptions};
10use crypto::{ElementHasher, VectorCommitment};
11use math::FieldElement;
12use tracing::info_span;
13
14use super::{ConstraintCommitment, RowMatrix};
15use crate::{CompositionPoly, CompositionPolyTrace, StarkDomain, DEFAULT_SEGMENT_WIDTH};
16
17pub struct DefaultConstraintCommitment<
27 E: FieldElement,
28 H: ElementHasher<BaseField = E::BaseField>,
29 V: VectorCommitment<H>,
30> {
31 evaluations: RowMatrix<E>,
32 vector_commitment: V,
33 _h: PhantomData<H>,
34}
35
36impl<E, H, V> DefaultConstraintCommitment<E, H, V>
37where
38 E: FieldElement,
39 H: ElementHasher<BaseField = E::BaseField>,
40 V: VectorCommitment<H>,
41{
42 pub fn new(
45 composition_poly_trace: CompositionPolyTrace<E>,
46 num_constraint_composition_columns: usize,
47 domain: &StarkDomain<E::BaseField>,
48 partition_options: PartitionOptions,
49 ) -> (Self, CompositionPoly<E>) {
50 let (evaluations, commitment, composition_poly) = build_constraint_commitment::<E, H, V>(
52 composition_poly_trace,
53 num_constraint_composition_columns,
54 domain,
55 partition_options,
56 );
57
58 assert_eq!(
59 evaluations.num_rows(),
60 commitment.domain_len(),
61 "number of rows in constraint evaluation matrix must be the same as the size \
62 of the vector commitment domain"
63 );
64
65 let commitment = Self {
66 evaluations,
67 vector_commitment: commitment,
68 _h: PhantomData,
69 };
70
71 (commitment, composition_poly)
72 }
73}
74
75impl<E, H, V> ConstraintCommitment<E> for DefaultConstraintCommitment<E, H, V>
76where
77 E: FieldElement,
78 H: ElementHasher<BaseField = E::BaseField> + core::marker::Sync,
79 V: VectorCommitment<H> + core::marker::Sync,
80{
81 type HashFn = H;
82 type VC = V;
83
84 fn commitment(&self) -> H::Digest {
86 self.vector_commitment.commitment()
87 }
88
89 fn query(self, positions: &[usize]) -> Queries {
92 let opening_proof = self
94 .vector_commitment
95 .open_many(positions)
96 .expect("failed to generate a batch opening proof for constraint queries");
97
98 let mut evaluations = Vec::new();
100 for &position in positions {
101 let row = self.evaluations.row(position).to_vec();
102 evaluations.push(row);
103 }
104
105 Queries::new::<H, E, V>(opening_proof.1, evaluations)
106 }
107}
108
109fn build_constraint_commitment<E, H, V>(
110 composition_poly_trace: CompositionPolyTrace<E>,
111 num_constraint_composition_columns: usize,
112 domain: &StarkDomain<E::BaseField>,
113 partition_options: PartitionOptions,
114) -> (RowMatrix<E>, V, CompositionPoly<E>)
115where
116 E: FieldElement,
117 H: ElementHasher<BaseField = E::BaseField>,
118 V: VectorCommitment<H>,
119{
120 let composition_poly = info_span!(
125 "build_composition_poly_columns",
126 num_columns = num_constraint_composition_columns
127 )
128 .in_scope(|| {
129 CompositionPoly::new(composition_poly_trace, domain, num_constraint_composition_columns)
130 });
131 assert_eq!(composition_poly.num_columns(), num_constraint_composition_columns);
132 assert_eq!(composition_poly.column_degree(), domain.trace_length() - 1);
133
134 let domain_size = domain.lde_domain_size();
136 let composed_evaluations = info_span!("evaluate_composition_poly_columns").in_scope(|| {
137 RowMatrix::evaluate_polys_over::<DEFAULT_SEGMENT_WIDTH>(composition_poly.data(), domain)
138 });
139 assert_eq!(composed_evaluations.num_cols(), num_constraint_composition_columns);
140 assert_eq!(composed_evaluations.num_rows(), domain_size);
141
142 let commitment = info_span!(
144 "compute_constraint_evaluation_commitment",
145 log_domain_size = domain_size.ilog2()
146 )
147 .in_scope(|| composed_evaluations.commit_to_rows::<H, V>(partition_options));
148
149 (composed_evaluations, commitment, composition_poly)
150}