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 utils::{ByteReader, ByteWriter, Deserializable, Serializable},
13 ExtensionOf, ProgramInfo, StackInputs, StackOutputs, ONE, ZERO,
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 utils::{DeserializationError, ToElements},
42 Felt, FieldElement, StarkField,
43};
44pub use winter_air::{
45 AuxRandElements, FieldExtension, LagrangeKernelEvaluationFrame, PartitionOptions,
46};
47
48pub struct ProcessorAir {
53 context: AirContext<Felt>,
54 stack_inputs: StackInputs,
55 stack_outputs: StackOutputs,
56 constraint_ranges: TransitionConstraintRange,
57}
58
59impl ProcessorAir {
60 pub fn last_step(&self) -> usize {
62 self.trace_length() - self.context().num_transition_exemptions()
63 }
64}
65
66impl Air for ProcessorAir {
67 type GkrProof = ();
68 type GkrVerifier = ();
69 type BaseField = Felt;
70 type PublicInputs = PublicInputs;
71
72 fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: WinterProofOptions) -> Self {
73 let mut main_degrees = vec![
75 TransitionConstraintDegree::new(1), ];
77
78 let mut stack_degrees = stack::get_transition_constraint_degrees();
80 main_degrees.append(&mut stack_degrees);
81
82 let mut range_checker_degrees = range::get_transition_constraint_degrees();
84 main_degrees.append(&mut range_checker_degrees);
85
86 let aux_degrees = range::get_aux_transition_constraint_degrees();
87
88 let mut chiplets_degrees = chiplets::get_transition_constraint_degrees();
90 main_degrees.append(&mut chiplets_degrees);
91
92 let constraint_ranges = TransitionConstraintRange::new(
94 1,
95 stack::get_transition_constraint_count(),
96 range::get_transition_constraint_count(),
97 chiplets::get_transition_constraint_count(),
98 );
99
100 let num_main_assertions = 2 + stack::NUM_ASSERTIONS + range::NUM_ASSERTIONS;
103
104 let num_aux_assertions = stack::NUM_AUX_ASSERTIONS + range::NUM_AUX_ASSERTIONS;
106
107 let context = AirContext::new_multi_segment(
110 trace_info,
111 main_degrees,
112 aux_degrees,
113 num_main_assertions,
114 num_aux_assertions,
115 None,
116 options,
117 )
118 .set_num_transition_exemptions(2);
119
120 Self {
121 context,
122 stack_inputs: pub_inputs.stack_inputs,
123 stack_outputs: pub_inputs.stack_outputs,
124 constraint_ranges,
125 }
126 }
127
128 fn get_periodic_column_values(&self) -> Vec<Vec<Felt>> {
133 chiplets::get_periodic_column_values()
134 }
135
136 #[allow(clippy::vec_init_then_push)]
140 fn get_assertions(&self) -> Vec<Assertion<Felt>> {
141 let mut result = Vec::new();
142
143 result.push(Assertion::single(CLK_COL_IDX, 0, ZERO));
146
147 result.push(Assertion::single(FMP_COL_IDX, 0, Felt::new(2u64.pow(30))));
149
150 stack::get_assertions_first_step(&mut result, &*self.stack_inputs);
152
153 range::get_assertions_first_step(&mut result);
155
156 let last_step = self.last_step();
158
159 stack::get_assertions_last_step(&mut result, last_step, &self.stack_outputs);
161
162 range::get_assertions_last_step(&mut result, last_step);
164
165 result
166 }
167
168 fn get_aux_assertions<E: FieldElement<BaseField = Self::BaseField>>(
169 &self,
170 _aux_rand_elements: &AuxRandElements<E>,
171 ) -> Vec<Assertion<E>> {
172 let mut result: Vec<Assertion<E>> = Vec::new();
173
174 stack::get_aux_assertions_first_step(&mut result);
178
179 range::get_aux_assertions_first_step::<E>(&mut result);
181
182 let last_step = self.last_step();
184
185 stack::get_aux_assertions_last_step(&mut result, last_step);
187
188 range::get_aux_assertions_last_step::<E>(&mut result, last_step);
190
191 result
192 }
193
194 fn evaluate_transition<E: FieldElement<BaseField = Felt>>(
198 &self,
199 frame: &EvaluationFrame<E>,
200 periodic_values: &[E],
201 result: &mut [E],
202 ) {
203 let current = frame.current();
204 let next = frame.next();
205
206 result[0] = next[CLK_COL_IDX] - (current[CLK_COL_IDX] + E::ONE);
209
210 stack::enforce_constraints::<E>(
212 frame,
213 select_result_range!(result, self.constraint_ranges.stack),
214 );
215
216 range::enforce_constraints::<E>(
218 frame,
219 select_result_range!(result, self.constraint_ranges.range_checker),
220 );
221
222 chiplets::enforce_constraints::<E>(
224 frame,
225 periodic_values,
226 select_result_range!(result, self.constraint_ranges.chiplets),
227 );
228 }
229
230 fn evaluate_aux_transition<F, E>(
231 &self,
232 main_frame: &EvaluationFrame<F>,
233 aux_frame: &EvaluationFrame<E>,
234 _periodic_values: &[F],
235 aux_rand_elements: &AuxRandElements<E>,
236 result: &mut [E],
237 ) where
238 F: FieldElement<BaseField = Felt>,
239 E: FieldElement<BaseField = Felt> + ExtensionOf<F>,
240 {
241 range::enforce_aux_constraints::<F, E>(
243 main_frame,
244 aux_frame,
245 aux_rand_elements.rand_elements(),
246 result,
247 );
248 }
249
250 fn context(&self) -> &AirContext<Felt> {
251 &self.context
252 }
253}
254
255#[derive(Debug)]
259pub struct PublicInputs {
260 program_info: ProgramInfo,
261 stack_inputs: StackInputs,
262 stack_outputs: StackOutputs,
263}
264
265impl PublicInputs {
266 pub fn new(
267 program_info: ProgramInfo,
268 stack_inputs: StackInputs,
269 stack_outputs: StackOutputs,
270 ) -> Self {
271 Self {
272 program_info,
273 stack_inputs,
274 stack_outputs,
275 }
276 }
277}
278
279impl vm_core::ToElements<Felt> for PublicInputs {
280 fn to_elements(&self) -> Vec<Felt> {
281 let mut result = self.program_info.to_elements();
282 result.append(&mut self.stack_inputs.to_vec());
283 result.append(&mut self.stack_outputs.to_vec());
284 result
285 }
286}
287
288impl Serializable for PublicInputs {
292 fn write_into<W: ByteWriter>(&self, target: &mut W) {
293 self.program_info.write_into(target);
294 self.stack_inputs.write_into(target);
295 self.stack_outputs.write_into(target);
296 }
297}
298
299impl Deserializable for PublicInputs {
300 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
301 let program_info = ProgramInfo::read_from(source)?;
302 let stack_inputs = StackInputs::read_from(source)?;
303 let stack_outputs = StackOutputs::read_from(source)?;
304
305 Ok(PublicInputs {
306 program_info,
307 stack_inputs,
308 stack_outputs,
309 })
310 }
311}