1#![no_std]
2#![allow(dead_code)]
3
4#[macro_use]
5extern crate alloc;
6
7#[cfg(feature = "std")]
8extern crate std;
9
10use alloc::{borrow::ToOwned, vec::Vec};
11
12use miden_core::{
13 ExtensionOf, ONE, ProgramInfo, StackInputs, StackOutputs, Word, ZERO,
14 utils::{ByteReader, ByteWriter, Deserializable, Serializable},
15};
16use winter_air::{
17 Air, AirContext, Assertion, EvaluationFrame, ProofOptions as WinterProofOptions, TraceInfo,
18 TransitionConstraintDegree,
19};
20use winter_prover::{
21 crypto::{RandomCoin, RandomCoinError},
22 math::get_power_series,
23 matrix::ColMatrix,
24};
25
26mod constraints;
27pub use constraints::stack;
28use constraints::{chiplets, range};
29
30pub mod trace;
31pub use trace::rows::RowIndex;
32use trace::*;
33
34mod errors;
35mod options;
36mod proof;
37
38mod utils;
39
40pub use errors::ExecutionOptionsError;
44pub use miden_core::{
45 Felt, FieldElement, StarkField,
46 utils::{DeserializationError, ToElements},
47};
48pub use options::{ExecutionOptions, ProvingOptions};
49pub use proof::{ExecutionProof, HashFunction};
50use utils::TransitionConstraintRange;
51pub use winter_air::{AuxRandElements, FieldExtension, PartitionOptions};
52
53const IS_FULL_CONSTRAINT_SET: bool = false;
56
57pub struct ProcessorAir {
62 context: AirContext<Felt>,
63 stack_inputs: StackInputs,
64 stack_outputs: StackOutputs,
65 program_digest: Word,
66 kernel_digests: Vec<Word>,
67 constraint_ranges: TransitionConstraintRange,
68}
69
70impl ProcessorAir {
71 pub fn last_step(&self) -> usize {
73 self.trace_length() - self.context().num_transition_exemptions()
74 }
75}
76
77impl Air for ProcessorAir {
78 type BaseField = Felt;
79 type PublicInputs = PublicInputs;
80
81 fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: WinterProofOptions) -> Self {
82 let mut main_degrees = vec![
84 TransitionConstraintDegree::new(1), ];
86
87 if IS_FULL_CONSTRAINT_SET {
88 let mut stack_degrees = stack::get_transition_constraint_degrees();
91 main_degrees.append(&mut stack_degrees);
92
93 let mut range_checker_degrees = range::get_transition_constraint_degrees();
96 main_degrees.append(&mut range_checker_degrees);
97
98 let mut chiplets_degrees = chiplets::get_transition_constraint_degrees();
100 main_degrees.append(&mut chiplets_degrees);
101 }
102
103 let aux_degrees = range::get_aux_transition_constraint_degrees();
104
105 let constraint_ranges = TransitionConstraintRange::new(
107 1,
108 stack::get_transition_constraint_count(),
109 range::get_transition_constraint_count(),
110 chiplets::get_transition_constraint_count(),
111 );
112
113 let num_main_assertions = if IS_FULL_CONSTRAINT_SET {
116 2 + stack::NUM_ASSERTIONS + range::NUM_ASSERTIONS
117 } else {
118 1
119 };
120
121 let num_aux_assertions = if IS_FULL_CONSTRAINT_SET {
123 stack::NUM_AUX_ASSERTIONS + range::NUM_AUX_ASSERTIONS
124 } else {
125 3
126 };
127
128 let context = AirContext::new_multi_segment(
131 trace_info,
132 main_degrees,
133 aux_degrees,
134 num_main_assertions,
135 num_aux_assertions,
136 options,
137 )
138 .set_num_transition_exemptions(2);
139
140 Self {
141 context,
142 stack_inputs: pub_inputs.stack_inputs,
143 stack_outputs: pub_inputs.stack_outputs,
144 constraint_ranges,
145 program_digest: pub_inputs.program_info.program_hash().to_owned(),
146 kernel_digests: pub_inputs.program_info.kernel_procedures().to_owned(),
147 }
148 }
149
150 fn get_periodic_column_values(&self) -> Vec<Vec<Felt>> {
155 chiplets::get_periodic_column_values()
156 }
157
158 fn get_assertions(&self) -> Vec<Assertion<Felt>> {
162 let mut result = vec![Assertion::single(CLK_COL_IDX, 0, ZERO)];
165
166 if IS_FULL_CONSTRAINT_SET {
167 result.push(Assertion::single(FMP_COL_IDX, 0, Felt::new(2u64.pow(30))));
169
170 stack::get_assertions_first_step(&mut result, &*self.stack_inputs);
172
173 range::get_assertions_first_step(&mut result);
175
176 let last_step = self.last_step();
179
180 stack::get_assertions_last_step(&mut result, last_step, &self.stack_outputs);
182
183 range::get_assertions_last_step(&mut result, last_step);
185 }
186
187 result
188 }
189
190 fn get_aux_assertions<E: FieldElement<BaseField = Self::BaseField>>(
191 &self,
192 aux_rand_elements: &AuxRandElements<E>,
193 ) -> Vec<Assertion<E>> {
194 let mut result: Vec<Assertion<E>> = Vec::new();
195
196 range::get_aux_assertions_first_step::<E>(&mut result);
198
199 chiplets::get_aux_assertions_first_step::<E>(
201 &mut result,
202 &self.kernel_digests,
203 aux_rand_elements,
204 );
205
206 if IS_FULL_CONSTRAINT_SET {
208 stack::get_aux_assertions_first_step(&mut result);
210
211 let last_step = self.last_step();
214
215 stack::get_aux_assertions_last_step(&mut result, last_step);
217 }
218 let last_step = self.last_step();
220 range::get_aux_assertions_last_step::<E>(&mut result, last_step);
221
222 result
223 }
224
225 fn evaluate_transition<E: FieldElement<BaseField = Felt>>(
229 &self,
230 frame: &EvaluationFrame<E>,
231 periodic_values: &[E],
232 result: &mut [E],
233 ) {
234 let current = frame.current();
235 let next = frame.next();
236
237 result[0] = next[CLK_COL_IDX] - (current[CLK_COL_IDX] + E::ONE);
240
241 if IS_FULL_CONSTRAINT_SET {
242 stack::enforce_constraints::<E>(
245 frame,
246 select_result_range!(result, self.constraint_ranges.stack),
247 );
248
249 range::enforce_constraints::<E>(
252 frame,
253 select_result_range!(result, self.constraint_ranges.range_checker),
254 );
255
256 chiplets::enforce_constraints::<E>(
258 frame,
259 periodic_values,
260 select_result_range!(result, self.constraint_ranges.chiplets),
261 );
262 }
263 }
264
265 fn evaluate_aux_transition<F, E>(
266 &self,
267 main_frame: &EvaluationFrame<F>,
268 aux_frame: &EvaluationFrame<E>,
269 _periodic_values: &[F],
270 aux_rand_elements: &AuxRandElements<E>,
271 result: &mut [E],
272 ) where
273 F: FieldElement<BaseField = Felt>,
274 E: FieldElement<BaseField = Felt> + ExtensionOf<F>,
275 {
276 range::enforce_aux_constraints::<F, E>(
278 main_frame,
279 aux_frame,
280 aux_rand_elements.rand_elements(),
281 result,
282 );
283 }
284
285 fn context(&self) -> &AirContext<Felt> {
286 &self.context
287 }
288
289 fn get_aux_rand_elements<E, R>(
290 &self,
291 public_coin: &mut R,
292 ) -> Result<AuxRandElements<E>, RandomCoinError>
293 where
294 E: FieldElement<BaseField = Self::BaseField>,
295 R: RandomCoin<BaseField = Self::BaseField>,
296 {
297 let num_elements = self.trace_info().get_num_aux_segment_rand_elements();
298 let mut rand_elements = Vec::with_capacity(num_elements);
299 let max_message_length = num_elements - 1;
300
301 let alpha = public_coin.draw()?;
302 let beta = public_coin.draw()?;
303
304 let betas = get_power_series(beta, max_message_length);
305
306 rand_elements.push(alpha);
307 rand_elements.extend_from_slice(&betas);
308
309 Ok(AuxRandElements::new(rand_elements))
310 }
311}
312
313#[derive(Debug)]
317pub struct PublicInputs {
318 program_info: ProgramInfo,
319 stack_inputs: StackInputs,
320 stack_outputs: StackOutputs,
321}
322
323impl PublicInputs {
324 pub fn new(
325 program_info: ProgramInfo,
326 stack_inputs: StackInputs,
327 stack_outputs: StackOutputs,
328 ) -> Self {
329 Self {
330 program_info,
331 stack_inputs,
332 stack_outputs,
333 }
334 }
335}
336
337impl miden_core::ToElements<Felt> for PublicInputs {
338 fn to_elements(&self) -> Vec<Felt> {
339 let mut result = self.stack_inputs.to_vec();
340 result.append(&mut self.stack_outputs.to_vec());
341 result.append(&mut self.program_info.to_elements());
342 result
343 }
344}
345
346impl Serializable for PublicInputs {
350 fn write_into<W: ByteWriter>(&self, target: &mut W) {
351 self.program_info.write_into(target);
352 self.stack_inputs.write_into(target);
353 self.stack_outputs.write_into(target);
354 }
355}
356
357impl Deserializable for PublicInputs {
358 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
359 let program_info = ProgramInfo::read_from(source)?;
360 let stack_inputs = StackInputs::read_from(source)?;
361 let stack_outputs = StackOutputs::read_from(source)?;
362
363 Ok(PublicInputs {
364 program_info,
365 stack_inputs,
366 stack_outputs,
367 })
368 }
369}