1use alloc::vec::Vec;
2
3use miden_air::trace::{
4 AUX_TRACE_RAND_ELEMENTS, AUX_TRACE_WIDTH, DECODER_TRACE_OFFSET, MIN_TRACE_LEN,
5 PADDED_TRACE_WIDTH, STACK_TRACE_OFFSET, TRACE_WIDTH,
6 decoder::{NUM_USER_OP_HELPERS, USER_OP_HELPERS_OFFSET},
7 main_trace::MainTrace,
8};
9use miden_core::{ProgramInfo, StackInputs, StackOutputs, Word, ZERO, stack::MIN_STACK_DEPTH};
10use winter_prover::{EvaluationFrame, Trace, TraceInfo, crypto::RandomCoin};
11
12use super::{
13 ColMatrix, Felt, FieldElement, Process, chiplets::AuxTraceBuilder as ChipletsAuxTraceBuilder,
14 crypto::RpoRandomCoin, decoder::AuxTraceBuilder as DecoderAuxTraceBuilder,
15 range::AuxTraceBuilder as RangeCheckerAuxTraceBuilder,
16 stack::AuxTraceBuilder as StackAuxTraceBuilder,
17};
18
19mod utils;
20pub use utils::{AuxColumnBuilder, ChipletsLengths, TraceFragment, TraceLenSummary};
21
22#[cfg(test)]
23mod tests;
24#[cfg(test)]
25use super::EMPTY_WORD;
26
27pub const NUM_RAND_ROWS: usize = 1;
32
33#[derive(Debug)]
37pub struct AuxTraceBuilders {
38 pub(crate) decoder: DecoderAuxTraceBuilder,
39 pub(crate) stack: StackAuxTraceBuilder,
40 pub(crate) range: RangeCheckerAuxTraceBuilder,
41 pub(crate) chiplets: ChipletsAuxTraceBuilder,
42}
43
44#[derive(Debug)]
52pub struct ExecutionTrace {
53 meta: Vec<u8>,
54 trace_info: TraceInfo,
55 main_trace: MainTrace,
56 aux_trace_builders: AuxTraceBuilders,
57 program_info: ProgramInfo,
58 stack_outputs: StackOutputs,
59 trace_len_summary: TraceLenSummary,
60}
61
62impl ExecutionTrace {
63 pub const NUM_RAND_ROWS: usize = NUM_RAND_ROWS;
68
69 pub fn new(process: Process, stack_outputs: StackOutputs) -> Self {
73 let program_hash = process.decoder.program_hash().into();
78 let rng = RpoRandomCoin::new(program_hash);
79
80 let kernel = process.kernel().clone();
82 let program_info = ProgramInfo::new(program_hash, kernel);
83 let (main_trace, aux_trace_builders, trace_len_summary) = finalize_trace(process, rng);
84 let trace_info = TraceInfo::new_multi_segment(
85 PADDED_TRACE_WIDTH,
86 AUX_TRACE_WIDTH,
87 AUX_TRACE_RAND_ELEMENTS,
88 main_trace.num_rows(),
89 vec![],
90 );
91
92 Self {
93 meta: Vec::new(),
94 trace_info,
95 aux_trace_builders,
96 main_trace,
97 program_info,
98 stack_outputs,
99 trace_len_summary,
100 }
101 }
102
103 pub fn program_info(&self) -> &ProgramInfo {
108 &self.program_info
109 }
110
111 pub fn program_hash(&self) -> &Word {
113 self.program_info.program_hash()
114 }
115
116 pub fn stack_outputs(&self) -> &StackOutputs {
118 &self.stack_outputs
119 }
120
121 pub fn init_stack_state(&self) -> StackInputs {
123 let mut result = [ZERO; MIN_STACK_DEPTH];
124 for (i, result) in result.iter_mut().enumerate() {
125 *result = self.main_trace.get_column(i + STACK_TRACE_OFFSET)[0];
126 }
127 result.into()
128 }
129
130 pub fn last_stack_state(&self) -> StackOutputs {
132 let last_step = self.last_step();
133 let mut result = [ZERO; MIN_STACK_DEPTH];
134 for (i, result) in result.iter_mut().enumerate() {
135 *result = self.main_trace.get_column(i + STACK_TRACE_OFFSET)[last_step];
136 }
137 result.into()
138 }
139
140 pub fn get_user_op_helpers_at(&self, clk: u32) -> [Felt; NUM_USER_OP_HELPERS] {
142 let mut result = [ZERO; NUM_USER_OP_HELPERS];
143 for (i, result) in result.iter_mut().enumerate() {
144 *result = self.main_trace.get_column(DECODER_TRACE_OFFSET + USER_OP_HELPERS_OFFSET + i)
145 [clk as usize];
146 }
147 result
148 }
149
150 pub fn get_trace_len(&self) -> usize {
152 self.main_trace.num_rows()
153 }
154
155 pub fn trace_len_summary(&self) -> &TraceLenSummary {
157 &self.trace_len_summary
158 }
159
160 pub fn meta(&self) -> &[u8] {
162 &self.meta
163 }
164
165 fn last_step(&self) -> usize {
170 self.length() - NUM_RAND_ROWS - 1
171 }
172
173 #[cfg(feature = "std")]
176 #[allow(dead_code)]
177 pub fn print(&self) {
178 let mut row = [ZERO; PADDED_TRACE_WIDTH];
179 for i in 0..self.length() {
180 self.main_trace.read_row_into(i, &mut row);
181 std::println!(
182 "{:?}",
183 row.iter().take(TRACE_WIDTH).map(|v| v.as_int()).collect::<Vec<_>>()
184 );
185 }
186 }
187
188 #[cfg(test)]
189 pub fn test_finalize_trace(process: Process) -> (MainTrace, AuxTraceBuilders, TraceLenSummary) {
190 let rng = RpoRandomCoin::new(EMPTY_WORD);
191 finalize_trace(process, rng)
192 }
193
194 pub fn build_aux_trace<E>(&self, rand_elements: &[E]) -> Option<ColMatrix<E>>
195 where
196 E: FieldElement<BaseField = Felt>,
197 {
198 let decoder_aux_columns = self
200 .aux_trace_builders
201 .decoder
202 .build_aux_columns(&self.main_trace, rand_elements);
203
204 let stack_aux_columns =
206 self.aux_trace_builders.stack.build_aux_columns(&self.main_trace, rand_elements);
207
208 let range_aux_columns =
210 self.aux_trace_builders.range.build_aux_columns(&self.main_trace, rand_elements);
211
212 let chiplets = self
214 .aux_trace_builders
215 .chiplets
216 .build_aux_columns(&self.main_trace, rand_elements);
217
218 let mut aux_columns = decoder_aux_columns
220 .into_iter()
221 .chain(stack_aux_columns)
222 .chain(range_aux_columns)
223 .chain(chiplets)
224 .collect::<Vec<_>>();
225
226 let mut rng = RpoRandomCoin::new(*self.program_hash());
228 for i in self.length() - NUM_RAND_ROWS..self.length() {
229 for column in aux_columns.iter_mut() {
230 column[i] = rng.draw().expect("failed to draw a random value");
231 }
232 }
233
234 Some(ColMatrix::new(aux_columns))
235 }
236}
237
238impl Trace for ExecutionTrace {
242 type BaseField = Felt;
243
244 fn length(&self) -> usize {
245 self.main_trace.num_rows()
246 }
247
248 fn main_segment(&self) -> &ColMatrix<Felt> {
249 &self.main_trace
250 }
251
252 fn read_main_frame(&self, row_idx: usize, frame: &mut EvaluationFrame<Felt>) {
253 let next_row_idx = (row_idx + 1) % self.length();
254 self.main_trace.read_row_into(row_idx, frame.current_mut());
255 self.main_trace.read_row_into(next_row_idx, frame.next_mut());
256 }
257
258 fn info(&self) -> &TraceInfo {
259 &self.trace_info
260 }
261}
262
263fn finalize_trace(
275 process: Process,
276 mut rng: RpoRandomCoin,
277) -> (MainTrace, AuxTraceBuilders, TraceLenSummary) {
278 let (system, decoder, stack, mut range, chiplets) = process.into_parts();
279
280 let clk = system.clk();
281
282 assert_eq!(clk.as_usize(), system.trace_len(), "inconsistent system trace lengths");
284 assert_eq!(clk.as_usize(), decoder.trace_len(), "inconsistent decoder trace length");
285 assert_eq!(clk.as_usize(), stack.trace_len(), "inconsistent stack trace lengths");
286
287 chiplets.append_range_checks(&mut range);
289
290 let range_table_len = range.get_number_range_checker_rows();
292
293 let max_len = range_table_len.max(clk.into()).max(chiplets.trace_len());
295
296 let trace_len = (max_len + NUM_RAND_ROWS).next_power_of_two();
299 assert!(
300 trace_len >= MIN_TRACE_LEN,
301 "trace length must be at least {MIN_TRACE_LEN}, but was {trace_len}",
302 );
303
304 let trace_len_summary =
306 TraceLenSummary::new(clk.into(), range_table_len, ChipletsLengths::new(&chiplets));
307
308 let system_trace = system.into_trace(trace_len, NUM_RAND_ROWS);
310 let decoder_trace = decoder.into_trace(trace_len, NUM_RAND_ROWS);
311 let stack_trace = stack.into_trace(trace_len, NUM_RAND_ROWS);
312 let chiplets_trace = chiplets.into_trace(trace_len, NUM_RAND_ROWS);
313
314 let range_check_trace = range.into_trace_with_table(range_table_len, trace_len, NUM_RAND_ROWS);
316
317 let padding = vec![vec![ZERO; trace_len]; PADDED_TRACE_WIDTH - TRACE_WIDTH];
319
320 let mut trace = system_trace
321 .into_iter()
322 .chain(decoder_trace.trace)
323 .chain(stack_trace.trace)
324 .chain(range_check_trace.trace)
325 .chain(chiplets_trace.trace)
326 .chain(padding)
327 .collect::<Vec<_>>();
328
329 for i in trace_len - NUM_RAND_ROWS..trace_len {
331 for column in trace.iter_mut().take(TRACE_WIDTH) {
332 column[i] = rng.draw().expect("failed to draw a random value");
333 }
334 }
335
336 let aux_trace_hints = AuxTraceBuilders {
337 decoder: decoder_trace.aux_builder,
338 stack: StackAuxTraceBuilder,
339 range: range_check_trace.aux_builder,
340 chiplets: chiplets_trace.aux_builder,
341 };
342
343 let main_trace = MainTrace::new(ColMatrix::new(trace), clk);
344
345 (main_trace, aux_trace_hints, trace_len_summary)
346}