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::vec::Vec;
11
12use miden_core::{
13 ExtensionOf, ONE, ProgramInfo, StackInputs, StackOutputs, 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 constraint_ranges: TransitionConstraintRange,
66}
67
68impl ProcessorAir {
69 pub fn last_step(&self) -> usize {
71 self.trace_length() - self.context().num_transition_exemptions()
72 }
73}
74
75impl Air for ProcessorAir {
76 type BaseField = Felt;
77 type PublicInputs = PublicInputs;
78
79 fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: WinterProofOptions) -> Self {
80 let mut main_degrees = vec![
82 TransitionConstraintDegree::new(1), ];
84
85 if IS_FULL_CONSTRAINT_SET {
86 let mut stack_degrees = stack::get_transition_constraint_degrees();
89 main_degrees.append(&mut stack_degrees);
90
91 let mut range_checker_degrees = range::get_transition_constraint_degrees();
94 main_degrees.append(&mut range_checker_degrees);
95
96 let mut chiplets_degrees = chiplets::get_transition_constraint_degrees();
98 main_degrees.append(&mut chiplets_degrees);
99 }
100
101 let aux_degrees = range::get_aux_transition_constraint_degrees();
102
103 let constraint_ranges = TransitionConstraintRange::new(
105 1,
106 stack::get_transition_constraint_count(),
107 range::get_transition_constraint_count(),
108 chiplets::get_transition_constraint_count(),
109 );
110
111 let num_main_assertions = if IS_FULL_CONSTRAINT_SET {
114 2 + stack::NUM_ASSERTIONS + range::NUM_ASSERTIONS
115 } else {
116 1
117 };
118
119 let num_aux_assertions = if IS_FULL_CONSTRAINT_SET {
121 stack::NUM_AUX_ASSERTIONS + range::NUM_AUX_ASSERTIONS
122 } else {
123 1
124 };
125
126 let context = AirContext::new_multi_segment(
129 trace_info,
130 main_degrees,
131 aux_degrees,
132 num_main_assertions,
133 num_aux_assertions,
134 options,
135 )
136 .set_num_transition_exemptions(2);
137
138 Self {
139 context,
140 stack_inputs: pub_inputs.stack_inputs,
141 stack_outputs: pub_inputs.stack_outputs,
142 constraint_ranges,
143 }
144 }
145
146 fn get_periodic_column_values(&self) -> Vec<Vec<Felt>> {
151 chiplets::get_periodic_column_values()
152 }
153
154 fn get_assertions(&self) -> Vec<Assertion<Felt>> {
158 let mut result = vec![Assertion::single(CLK_COL_IDX, 0, ZERO)];
161
162 if IS_FULL_CONSTRAINT_SET {
163 result.push(Assertion::single(FMP_COL_IDX, 0, Felt::new(2u64.pow(30))));
165
166 stack::get_assertions_first_step(&mut result, &*self.stack_inputs);
168
169 range::get_assertions_first_step(&mut result);
171
172 let last_step = self.last_step();
175
176 stack::get_assertions_last_step(&mut result, last_step, &self.stack_outputs);
178
179 range::get_assertions_last_step(&mut result, last_step);
181 }
182
183 result
184 }
185
186 fn get_aux_assertions<E: FieldElement<BaseField = Self::BaseField>>(
187 &self,
188 _aux_rand_elements: &AuxRandElements<E>,
189 ) -> Vec<Assertion<E>> {
190 let mut result: Vec<Assertion<E>> = Vec::new();
191
192 if IS_FULL_CONSTRAINT_SET {
194 stack::get_aux_assertions_first_step(&mut result);
196
197 range::get_aux_assertions_first_step::<E>(&mut result);
199
200 let last_step = self.last_step();
203
204 stack::get_aux_assertions_last_step(&mut result, last_step);
206 }
207 let last_step = self.last_step();
209 range::get_aux_assertions_last_step::<E>(&mut result, last_step);
210
211 result
212 }
213
214 fn evaluate_transition<E: FieldElement<BaseField = Felt>>(
218 &self,
219 frame: &EvaluationFrame<E>,
220 periodic_values: &[E],
221 result: &mut [E],
222 ) {
223 let current = frame.current();
224 let next = frame.next();
225
226 result[0] = next[CLK_COL_IDX] - (current[CLK_COL_IDX] + E::ONE);
229
230 if IS_FULL_CONSTRAINT_SET {
231 stack::enforce_constraints::<E>(
234 frame,
235 select_result_range!(result, self.constraint_ranges.stack),
236 );
237
238 range::enforce_constraints::<E>(
241 frame,
242 select_result_range!(result, self.constraint_ranges.range_checker),
243 );
244
245 chiplets::enforce_constraints::<E>(
247 frame,
248 periodic_values,
249 select_result_range!(result, self.constraint_ranges.chiplets),
250 );
251 }
252 }
253
254 fn evaluate_aux_transition<F, E>(
255 &self,
256 main_frame: &EvaluationFrame<F>,
257 aux_frame: &EvaluationFrame<E>,
258 _periodic_values: &[F],
259 aux_rand_elements: &AuxRandElements<E>,
260 result: &mut [E],
261 ) where
262 F: FieldElement<BaseField = Felt>,
263 E: FieldElement<BaseField = Felt> + ExtensionOf<F>,
264 {
265 range::enforce_aux_constraints::<F, E>(
267 main_frame,
268 aux_frame,
269 aux_rand_elements.rand_elements(),
270 result,
271 );
272 }
273
274 fn context(&self) -> &AirContext<Felt> {
275 &self.context
276 }
277
278 fn get_aux_rand_elements<E, R>(
279 &self,
280 public_coin: &mut R,
281 ) -> Result<AuxRandElements<E>, RandomCoinError>
282 where
283 E: FieldElement<BaseField = Self::BaseField>,
284 R: RandomCoin<BaseField = Self::BaseField>,
285 {
286 let num_elements = self.trace_info().get_num_aux_segment_rand_elements();
287 let mut rand_elements = Vec::with_capacity(num_elements);
288 let max_message_length = num_elements - 1;
289
290 let alpha = public_coin.draw()?;
291 let beta = public_coin.draw()?;
292
293 let betas = get_power_series(beta, max_message_length);
294
295 rand_elements.push(alpha);
296 rand_elements.extend_from_slice(&betas);
297
298 Ok(AuxRandElements::new(rand_elements))
299 }
300}
301
302#[derive(Debug)]
306pub struct PublicInputs {
307 program_info: ProgramInfo,
308 stack_inputs: StackInputs,
309 stack_outputs: StackOutputs,
310}
311
312impl PublicInputs {
313 pub fn new(
314 program_info: ProgramInfo,
315 stack_inputs: StackInputs,
316 stack_outputs: StackOutputs,
317 ) -> Self {
318 Self {
319 program_info,
320 stack_inputs,
321 stack_outputs,
322 }
323 }
324}
325
326impl miden_core::ToElements<Felt> for PublicInputs {
327 fn to_elements(&self) -> Vec<Felt> {
328 let mut result = self.stack_inputs.to_vec();
329 result.append(&mut self.stack_outputs.to_vec());
330 result.append(&mut self.program_info.to_elements());
331 result
332 }
333}
334
335impl Serializable for PublicInputs {
339 fn write_into<W: ByteWriter>(&self, target: &mut W) {
340 self.program_info.write_into(target);
341 self.stack_inputs.write_into(target);
342 self.stack_outputs.write_into(target);
343 }
344}
345
346impl Deserializable for PublicInputs {
347 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
348 let program_info = ProgramInfo::read_from(source)?;
349 let stack_inputs = StackInputs::read_from(source)?;
350 let stack_outputs = StackOutputs::read_from(source)?;
351
352 Ok(PublicInputs {
353 program_info,
354 stack_inputs,
355 stack_outputs,
356 })
357 }
358}