winter_prover/trace/trace_lde/default/
mod.rs1use alloc::vec::Vec;
7use core::marker::PhantomData;
8
9use air::{proof::Queries, PartitionOptions, TraceInfo};
10use crypto::VectorCommitment;
11use tracing::info_span;
12
13use super::{
14 ColMatrix, ElementHasher, EvaluationFrame, FieldElement, StarkDomain, TraceLde, TracePolyTable,
15};
16use crate::{RowMatrix, DEFAULT_SEGMENT_WIDTH};
17
18#[cfg(test)]
19mod tests;
20
21pub struct DefaultTraceLde<
32 E: FieldElement,
33 H: ElementHasher<BaseField = E::BaseField>,
34 V: VectorCommitment<H>,
35> {
36 main_segment_lde: RowMatrix<E::BaseField>,
38 main_segment_oracles: V,
40 aux_segment_lde: Option<RowMatrix<E>>,
42 aux_segment_oracles: Option<V>,
44 blowup: usize,
45 trace_info: TraceInfo,
46 partition_options: PartitionOptions,
47 _h: PhantomData<H>,
48}
49
50impl<E, H, V> DefaultTraceLde<E, H, V>
51where
52 E: FieldElement,
53 H: ElementHasher<BaseField = E::BaseField>,
54 V: VectorCommitment<H>,
55{
56 pub fn new(
64 trace_info: &TraceInfo,
65 main_trace: &ColMatrix<E::BaseField>,
66 domain: &StarkDomain<E::BaseField>,
67 partition_options: PartitionOptions,
68 ) -> (Self, TracePolyTable<E>) {
69 let (main_segment_lde, main_segment_vector_com, main_segment_polys) =
71 build_trace_commitment::<E, E::BaseField, H, V>(main_trace, domain, partition_options);
72
73 let trace_poly_table = TracePolyTable::new(main_segment_polys);
74 let trace_lde = DefaultTraceLde {
75 main_segment_lde,
76 main_segment_oracles: main_segment_vector_com,
77 aux_segment_lde: None,
78 aux_segment_oracles: None,
79 blowup: domain.trace_to_lde_blowup(),
80 trace_info: trace_info.clone(),
81 partition_options,
82 _h: PhantomData,
83 };
84
85 (trace_lde, trace_poly_table)
86 }
87
88 #[cfg(test)]
93 pub fn main_segment_width(&self) -> usize {
94 self.main_segment_lde.num_cols()
95 }
96
97 #[cfg(test)]
99 pub fn get_main_segment(&self) -> &RowMatrix<E::BaseField> {
100 &self.main_segment_lde
101 }
102
103 #[cfg(test)]
105 pub fn get_main_segment_column(&self, col_idx: usize) -> Vec<E::BaseField> {
106 (0..self.main_segment_lde.num_rows())
107 .map(|row_idx| self.main_segment_lde.get(col_idx, row_idx))
108 .collect()
109 }
110}
111
112impl<E, H, V> TraceLde<E> for DefaultTraceLde<E, H, V>
113where
114 E: FieldElement,
115 H: ElementHasher<BaseField = E::BaseField> + core::marker::Sync,
116 V: VectorCommitment<H> + core::marker::Sync,
117{
118 type HashFn = H;
119 type VC = V;
120
121 fn get_main_trace_commitment(&self) -> H::Digest {
123 self.main_segment_oracles.commitment()
124 }
125
126 fn set_aux_trace(
141 &mut self,
142 aux_trace: &ColMatrix<E>,
143 domain: &StarkDomain<E::BaseField>,
144 ) -> (ColMatrix<E>, H::Digest) {
145 let (aux_segment_lde, aux_segment_oracles, aux_segment_polys) =
147 build_trace_commitment::<E, E, H, Self::VC>(aux_trace, domain, self.partition_options);
148
149 assert!(
151 usize::from(self.aux_segment_lde.is_some()) < self.trace_info.num_aux_segments(),
152 "the auxiliary trace has already been added"
153 );
154 assert_eq!(
155 self.main_segment_lde.num_rows(),
156 aux_segment_lde.num_rows(),
157 "the number of rows in the auxiliary segment must be the same as in the main segment"
158 );
159
160 self.aux_segment_lde = Some(aux_segment_lde);
162 let commitment_string = aux_segment_oracles.commitment();
163 self.aux_segment_oracles = Some(aux_segment_oracles);
164
165 (aux_segment_polys, commitment_string)
166 }
167
168 fn read_main_trace_frame_into(
170 &self,
171 lde_step: usize,
172 frame: &mut EvaluationFrame<E::BaseField>,
173 ) {
174 let next_lde_step = (lde_step + self.blowup()) % self.trace_len();
176
177 frame.current_mut().copy_from_slice(self.main_segment_lde.row(lde_step));
179 frame.next_mut().copy_from_slice(self.main_segment_lde.row(next_lde_step));
180 }
181
182 fn read_aux_trace_frame_into(&self, lde_step: usize, frame: &mut EvaluationFrame<E>) {
188 let next_lde_step = (lde_step + self.blowup()) % self.trace_len();
190
191 let segment = self.aux_segment_lde.as_ref().expect("expected aux segment to be present");
193 frame.current_mut().copy_from_slice(segment.row(lde_step));
194 frame.next_mut().copy_from_slice(segment.row(next_lde_step));
195 }
196
197 fn query(&self, positions: &[usize]) -> Vec<Queries> {
200 let mut result = vec![build_segment_queries::<E::BaseField, H, V>(
202 &self.main_segment_lde,
203 &self.main_segment_oracles,
204 positions,
205 )];
206
207 if let Some(ref segment_oracles) = self.aux_segment_oracles {
209 let segment_lde =
210 self.aux_segment_lde.as_ref().expect("expected aux segment to be present");
211 result.push(build_segment_queries::<E, H, V>(segment_lde, segment_oracles, positions));
212 }
213
214 result
215 }
216
217 fn trace_len(&self) -> usize {
219 self.main_segment_lde.num_rows()
220 }
221
222 fn blowup(&self) -> usize {
224 self.blowup
225 }
226
227 fn trace_info(&self) -> &TraceInfo {
229 &self.trace_info
230 }
231}
232
233fn build_trace_commitment<E, F, H, V>(
246 trace: &ColMatrix<F>,
247 domain: &StarkDomain<E::BaseField>,
248 partition_options: PartitionOptions,
249) -> (RowMatrix<F>, V, ColMatrix<F>)
250where
251 E: FieldElement,
252 F: FieldElement<BaseField = E::BaseField>,
253 H: ElementHasher<BaseField = E::BaseField>,
254 V: VectorCommitment<H>,
255{
256 let (trace_lde, trace_polys) = {
258 let span = info_span!(
259 "extend_execution_trace",
260 num_cols = trace.num_cols(),
261 blowup = domain.trace_to_lde_blowup()
262 )
263 .entered();
264 let trace_polys = trace.interpolate_columns();
265 let trace_lde =
266 RowMatrix::evaluate_polys_over::<DEFAULT_SEGMENT_WIDTH>(&trace_polys, domain);
267 drop(span);
268
269 (trace_lde, trace_polys)
270 };
271 assert_eq!(trace_lde.num_cols(), trace.num_cols());
272 assert_eq!(trace_polys.num_rows(), trace.num_rows());
273 assert_eq!(trace_lde.num_rows(), domain.lde_domain_size());
274
275 let commitment_domain_size = trace_lde.num_rows();
277 let trace_vector_com = info_span!("compute_execution_trace_commitment", commitment_domain_size)
278 .in_scope(|| trace_lde.commit_to_rows::<H, V>(partition_options));
279 assert_eq!(trace_vector_com.domain_len(), commitment_domain_size);
280
281 (trace_lde, trace_vector_com, trace_polys)
282}
283
284fn build_segment_queries<E, H, V>(
285 segment_lde: &RowMatrix<E>,
286 segment_vector_com: &V,
287 positions: &[usize],
288) -> Queries
289where
290 E: FieldElement,
291 H: ElementHasher<BaseField = E::BaseField>,
292 V: VectorCommitment<H>,
293{
294 let trace_states =
297 positions.iter().map(|&pos| segment_lde.row(pos).to_vec()).collect::<Vec<_>>();
298
299 let trace_proof = segment_vector_com
301 .open_many(positions)
302 .expect("failed to generate a batch opening proof for trace queries");
303
304 Queries::new::<H, E, V>(trace_proof.1, trace_states)
305}