1#![no_std]
2
3#[macro_use]
4extern crate alloc;
5
6#[cfg(feature = "std")]
7extern crate std;
8
9use alloc::vec::Vec;
10
11use vm_core::{
12 ExtensionOf, ONE, ProgramInfo, StackInputs, StackOutputs, ZERO,
13 utils::{ByteReader, ByteWriter, Deserializable, Serializable},
14};
15use winter_air::{
16 Air, AirContext, Assertion, EvaluationFrame, ProofOptions as WinterProofOptions, TraceInfo,
17 TransitionConstraintDegree,
18};
19use winter_prover::matrix::ColMatrix;
20
21mod constraints;
22pub use constraints::stack;
23use constraints::{chiplets, range};
24
25pub mod trace;
26pub use trace::rows::RowIndex;
27use trace::*;
28
29mod errors;
30mod options;
31mod proof;
32
33mod utils;
34pub use errors::ExecutionOptionsError;
37pub use options::{ExecutionOptions, ProvingOptions};
38pub use proof::{ExecutionProof, HashFunction};
39use utils::TransitionConstraintRange;
40pub use vm_core::{
41 Felt, FieldElement, StarkField,
42 utils::{DeserializationError, ToElements},
43};
44pub use winter_air::{AuxRandElements, FieldExtension, PartitionOptions};
45
46pub struct ProcessorAir {
51 context: AirContext<Felt>,
52 stack_inputs: StackInputs,
53 stack_outputs: StackOutputs,
54 constraint_ranges: TransitionConstraintRange,
55}
56
57impl ProcessorAir {
58 pub fn last_step(&self) -> usize {
60 self.trace_length() - self.context().num_transition_exemptions()
61 }
62}
63
64impl Air for ProcessorAir {
65 type BaseField = Felt;
66 type PublicInputs = PublicInputs;
67
68 fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: WinterProofOptions) -> Self {
69 let mut main_degrees = vec![
71 TransitionConstraintDegree::new(1), ];
73
74 let mut stack_degrees = stack::get_transition_constraint_degrees();
76 main_degrees.append(&mut stack_degrees);
77
78 let mut range_checker_degrees = range::get_transition_constraint_degrees();
80 main_degrees.append(&mut range_checker_degrees);
81
82 let aux_degrees = range::get_aux_transition_constraint_degrees();
83
84 let mut chiplets_degrees = chiplets::get_transition_constraint_degrees();
86 main_degrees.append(&mut chiplets_degrees);
87
88 let constraint_ranges = TransitionConstraintRange::new(
90 1,
91 stack::get_transition_constraint_count(),
92 range::get_transition_constraint_count(),
93 chiplets::get_transition_constraint_count(),
94 );
95
96 let num_main_assertions = 2 + stack::NUM_ASSERTIONS + range::NUM_ASSERTIONS;
99
100 let num_aux_assertions = stack::NUM_AUX_ASSERTIONS + range::NUM_AUX_ASSERTIONS;
102
103 let context = AirContext::new_multi_segment(
106 trace_info,
107 main_degrees,
108 aux_degrees,
109 num_main_assertions,
110 num_aux_assertions,
111 options,
112 )
113 .set_num_transition_exemptions(2);
114
115 Self {
116 context,
117 stack_inputs: pub_inputs.stack_inputs,
118 stack_outputs: pub_inputs.stack_outputs,
119 constraint_ranges,
120 }
121 }
122
123 fn get_periodic_column_values(&self) -> Vec<Vec<Felt>> {
128 chiplets::get_periodic_column_values()
129 }
130
131 #[allow(clippy::vec_init_then_push)]
135 fn get_assertions(&self) -> Vec<Assertion<Felt>> {
136 let mut result = Vec::new();
137
138 result.push(Assertion::single(CLK_COL_IDX, 0, ZERO));
141
142 result.push(Assertion::single(FMP_COL_IDX, 0, Felt::new(2u64.pow(30))));
144
145 stack::get_assertions_first_step(&mut result, &*self.stack_inputs);
147
148 range::get_assertions_first_step(&mut result);
150
151 let last_step = self.last_step();
153
154 stack::get_assertions_last_step(&mut result, last_step, &self.stack_outputs);
156
157 range::get_assertions_last_step(&mut result, last_step);
159
160 result
161 }
162
163 fn get_aux_assertions<E: FieldElement<BaseField = Self::BaseField>>(
164 &self,
165 _aux_rand_elements: &AuxRandElements<E>,
166 ) -> Vec<Assertion<E>> {
167 let mut result: Vec<Assertion<E>> = Vec::new();
168
169 stack::get_aux_assertions_first_step(&mut result);
173
174 range::get_aux_assertions_first_step::<E>(&mut result);
176
177 let last_step = self.last_step();
179
180 stack::get_aux_assertions_last_step(&mut result, last_step);
182
183 range::get_aux_assertions_last_step::<E>(&mut result, last_step);
185
186 result
187 }
188
189 fn evaluate_transition<E: FieldElement<BaseField = Felt>>(
193 &self,
194 frame: &EvaluationFrame<E>,
195 periodic_values: &[E],
196 result: &mut [E],
197 ) {
198 let current = frame.current();
199 let next = frame.next();
200
201 result[0] = next[CLK_COL_IDX] - (current[CLK_COL_IDX] + E::ONE);
204
205 stack::enforce_constraints::<E>(
207 frame,
208 select_result_range!(result, self.constraint_ranges.stack),
209 );
210
211 range::enforce_constraints::<E>(
213 frame,
214 select_result_range!(result, self.constraint_ranges.range_checker),
215 );
216
217 chiplets::enforce_constraints::<E>(
219 frame,
220 periodic_values,
221 select_result_range!(result, self.constraint_ranges.chiplets),
222 );
223 }
224
225 fn evaluate_aux_transition<F, E>(
226 &self,
227 main_frame: &EvaluationFrame<F>,
228 aux_frame: &EvaluationFrame<E>,
229 _periodic_values: &[F],
230 aux_rand_elements: &AuxRandElements<E>,
231 result: &mut [E],
232 ) where
233 F: FieldElement<BaseField = Felt>,
234 E: FieldElement<BaseField = Felt> + ExtensionOf<F>,
235 {
236 range::enforce_aux_constraints::<F, E>(
238 main_frame,
239 aux_frame,
240 aux_rand_elements.rand_elements(),
241 result,
242 );
243 }
244
245 fn context(&self) -> &AirContext<Felt> {
246 &self.context
247 }
248}
249
250#[derive(Debug)]
254pub struct PublicInputs {
255 program_info: ProgramInfo,
256 stack_inputs: StackInputs,
257 stack_outputs: StackOutputs,
258}
259
260impl PublicInputs {
261 pub fn new(
262 program_info: ProgramInfo,
263 stack_inputs: StackInputs,
264 stack_outputs: StackOutputs,
265 ) -> Self {
266 Self {
267 program_info,
268 stack_inputs,
269 stack_outputs,
270 }
271 }
272}
273
274impl vm_core::ToElements<Felt> for PublicInputs {
275 fn to_elements(&self) -> Vec<Felt> {
276 let mut result = self.program_info.to_elements();
277 result.append(&mut self.stack_inputs.to_vec());
278 result.append(&mut self.stack_outputs.to_vec());
279 result
280 }
281}
282
283impl Serializable for PublicInputs {
287 fn write_into<W: ByteWriter>(&self, target: &mut W) {
288 self.program_info.write_into(target);
289 self.stack_inputs.write_into(target);
290 self.stack_outputs.write_into(target);
291 }
292}
293
294impl Deserializable for PublicInputs {
295 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
296 let program_info = ProgramInfo::read_from(source)?;
297 let stack_inputs = StackInputs::read_from(source)?;
298 let stack_outputs = StackOutputs::read_from(source)?;
299
300 Ok(PublicInputs {
301 program_info,
302 stack_inputs,
303 stack_outputs,
304 })
305 }
306}