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 vm_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::matrix::ColMatrix;
21
22mod constraints;
23pub use constraints::stack;
24use constraints::{chiplets, range};
25
26pub mod trace;
27pub use trace::rows::RowIndex;
28use trace::*;
29
30mod errors;
31mod options;
32mod proof;
33
34mod utils;
35pub use errors::ExecutionOptionsError;
38pub use options::{ExecutionOptions, ProvingOptions};
39pub use proof::{ExecutionProof, HashFunction};
40use utils::TransitionConstraintRange;
41pub use vm_core::{
42 Felt, FieldElement, StarkField,
43 utils::{DeserializationError, ToElements},
44};
45pub use winter_air::{AuxRandElements, FieldExtension, PartitionOptions};
46
47const IS_FULL_CONSTRAINT_SET: bool = false;
50
51pub struct ProcessorAir {
56 context: AirContext<Felt>,
57 stack_inputs: StackInputs,
58 stack_outputs: StackOutputs,
59 constraint_ranges: TransitionConstraintRange,
60}
61
62impl ProcessorAir {
63 pub fn last_step(&self) -> usize {
65 self.trace_length() - self.context().num_transition_exemptions()
66 }
67}
68
69impl Air for ProcessorAir {
70 type BaseField = Felt;
71 type PublicInputs = PublicInputs;
72
73 fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: WinterProofOptions) -> Self {
74 let mut main_degrees = vec![
76 TransitionConstraintDegree::new(1), ];
78
79 if IS_FULL_CONSTRAINT_SET {
80 let mut stack_degrees = stack::get_transition_constraint_degrees();
83 main_degrees.append(&mut stack_degrees);
84
85 let mut range_checker_degrees = range::get_transition_constraint_degrees();
88 main_degrees.append(&mut range_checker_degrees);
89
90 let mut chiplets_degrees = chiplets::get_transition_constraint_degrees();
92 main_degrees.append(&mut chiplets_degrees);
93 }
94
95 let aux_degrees = range::get_aux_transition_constraint_degrees();
96
97 let constraint_ranges = TransitionConstraintRange::new(
99 1,
100 stack::get_transition_constraint_count(),
101 range::get_transition_constraint_count(),
102 chiplets::get_transition_constraint_count(),
103 );
104
105 let num_main_assertions = if IS_FULL_CONSTRAINT_SET {
108 2 + stack::NUM_ASSERTIONS + range::NUM_ASSERTIONS
109 } else {
110 1
111 };
112
113 let num_aux_assertions = if IS_FULL_CONSTRAINT_SET {
115 stack::NUM_AUX_ASSERTIONS + range::NUM_AUX_ASSERTIONS
116 } else {
117 1
118 };
119
120 let context = AirContext::new_multi_segment(
123 trace_info,
124 main_degrees,
125 aux_degrees,
126 num_main_assertions,
127 num_aux_assertions,
128 options,
129 )
130 .set_num_transition_exemptions(2);
131
132 Self {
133 context,
134 stack_inputs: pub_inputs.stack_inputs,
135 stack_outputs: pub_inputs.stack_outputs,
136 constraint_ranges,
137 }
138 }
139
140 fn get_periodic_column_values(&self) -> Vec<Vec<Felt>> {
145 chiplets::get_periodic_column_values()
146 }
147
148 #[allow(clippy::vec_init_then_push)]
152 fn get_assertions(&self) -> Vec<Assertion<Felt>> {
153 let mut result = Vec::new();
154
155 result.push(Assertion::single(CLK_COL_IDX, 0, ZERO));
158
159 if IS_FULL_CONSTRAINT_SET {
160 result.push(Assertion::single(FMP_COL_IDX, 0, Felt::new(2u64.pow(30))));
162
163 stack::get_assertions_first_step(&mut result, &*self.stack_inputs);
165
166 range::get_assertions_first_step(&mut result);
168
169 let last_step = self.last_step();
172
173 stack::get_assertions_last_step(&mut result, last_step, &self.stack_outputs);
175
176 range::get_assertions_last_step(&mut result, last_step);
178 }
179
180 result
181 }
182
183 fn get_aux_assertions<E: FieldElement<BaseField = Self::BaseField>>(
184 &self,
185 _aux_rand_elements: &AuxRandElements<E>,
186 ) -> Vec<Assertion<E>> {
187 let mut result: Vec<Assertion<E>> = Vec::new();
188
189 if IS_FULL_CONSTRAINT_SET {
191 stack::get_aux_assertions_first_step(&mut result);
193
194 range::get_aux_assertions_first_step::<E>(&mut result);
196
197 let last_step = self.last_step();
200
201 stack::get_aux_assertions_last_step(&mut result, last_step);
203 }
204 let last_step = self.last_step();
206 range::get_aux_assertions_last_step::<E>(&mut result, last_step);
207
208 result
209 }
210
211 fn evaluate_transition<E: FieldElement<BaseField = Felt>>(
215 &self,
216 frame: &EvaluationFrame<E>,
217 periodic_values: &[E],
218 result: &mut [E],
219 ) {
220 let current = frame.current();
221 let next = frame.next();
222
223 result[0] = next[CLK_COL_IDX] - (current[CLK_COL_IDX] + E::ONE);
226
227 if IS_FULL_CONSTRAINT_SET {
228 stack::enforce_constraints::<E>(
231 frame,
232 select_result_range!(result, self.constraint_ranges.stack),
233 );
234
235 range::enforce_constraints::<E>(
238 frame,
239 select_result_range!(result, self.constraint_ranges.range_checker),
240 );
241
242 chiplets::enforce_constraints::<E>(
244 frame,
245 periodic_values,
246 select_result_range!(result, self.constraint_ranges.chiplets),
247 );
248 }
249 }
250
251 fn evaluate_aux_transition<F, E>(
252 &self,
253 main_frame: &EvaluationFrame<F>,
254 aux_frame: &EvaluationFrame<E>,
255 _periodic_values: &[F],
256 aux_rand_elements: &AuxRandElements<E>,
257 result: &mut [E],
258 ) where
259 F: FieldElement<BaseField = Felt>,
260 E: FieldElement<BaseField = Felt> + ExtensionOf<F>,
261 {
262 range::enforce_aux_constraints::<F, E>(
264 main_frame,
265 aux_frame,
266 aux_rand_elements.rand_elements(),
267 result,
268 );
269 }
270
271 fn context(&self) -> &AirContext<Felt> {
272 &self.context
273 }
274}
275
276#[derive(Debug)]
280pub struct PublicInputs {
281 program_info: ProgramInfo,
282 stack_inputs: StackInputs,
283 stack_outputs: StackOutputs,
284}
285
286impl PublicInputs {
287 pub fn new(
288 program_info: ProgramInfo,
289 stack_inputs: StackInputs,
290 stack_outputs: StackOutputs,
291 ) -> Self {
292 Self {
293 program_info,
294 stack_inputs,
295 stack_outputs,
296 }
297 }
298}
299
300impl vm_core::ToElements<Felt> for PublicInputs {
301 fn to_elements(&self) -> Vec<Felt> {
302 let mut result = self.stack_inputs.to_vec();
303 result.append(&mut self.stack_outputs.to_vec());
304 result.append(&mut self.program_info.to_elements());
305 result
306 }
307}
308
309impl Serializable for PublicInputs {
313 fn write_into<W: ByteWriter>(&self, target: &mut W) {
314 self.program_info.write_into(target);
315 self.stack_inputs.write_into(target);
316 self.stack_outputs.write_into(target);
317 }
318}
319
320impl Deserializable for PublicInputs {
321 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
322 let program_info = ProgramInfo::read_from(source)?;
323 let stack_inputs = StackInputs::read_from(source)?;
324 let stack_outputs = StackOutputs::read_from(source)?;
325
326 Ok(PublicInputs {
327 program_info,
328 stack_inputs,
329 stack_outputs,
330 })
331 }
332}