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::{
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;
39pub use errors::ExecutionOptionsError;
42pub use options::{ExecutionOptions, ProvingOptions};
43pub use proof::{ExecutionProof, HashFunction};
44use utils::TransitionConstraintRange;
45pub use vm_core::{
46 Felt, FieldElement, StarkField,
47 utils::{DeserializationError, ToElements},
48};
49pub use winter_air::{AuxRandElements, FieldExtension, PartitionOptions};
50
51const IS_FULL_CONSTRAINT_SET: bool = false;
54
55pub struct ProcessorAir {
60 context: AirContext<Felt>,
61 stack_inputs: StackInputs,
62 stack_outputs: StackOutputs,
63 constraint_ranges: TransitionConstraintRange,
64}
65
66impl ProcessorAir {
67 pub fn last_step(&self) -> usize {
69 self.trace_length() - self.context().num_transition_exemptions()
70 }
71}
72
73impl Air for ProcessorAir {
74 type BaseField = Felt;
75 type PublicInputs = PublicInputs;
76
77 fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: WinterProofOptions) -> Self {
78 let mut main_degrees = vec![
80 TransitionConstraintDegree::new(1), ];
82
83 if IS_FULL_CONSTRAINT_SET {
84 let mut stack_degrees = stack::get_transition_constraint_degrees();
87 main_degrees.append(&mut stack_degrees);
88
89 let mut range_checker_degrees = range::get_transition_constraint_degrees();
92 main_degrees.append(&mut range_checker_degrees);
93
94 let mut chiplets_degrees = chiplets::get_transition_constraint_degrees();
96 main_degrees.append(&mut chiplets_degrees);
97 }
98
99 let aux_degrees = range::get_aux_transition_constraint_degrees();
100
101 let constraint_ranges = TransitionConstraintRange::new(
103 1,
104 stack::get_transition_constraint_count(),
105 range::get_transition_constraint_count(),
106 chiplets::get_transition_constraint_count(),
107 );
108
109 let num_main_assertions = if IS_FULL_CONSTRAINT_SET {
112 2 + stack::NUM_ASSERTIONS + range::NUM_ASSERTIONS
113 } else {
114 1
115 };
116
117 let num_aux_assertions = if IS_FULL_CONSTRAINT_SET {
119 stack::NUM_AUX_ASSERTIONS + range::NUM_AUX_ASSERTIONS
120 } else {
121 1
122 };
123
124 let context = AirContext::new_multi_segment(
127 trace_info,
128 main_degrees,
129 aux_degrees,
130 num_main_assertions,
131 num_aux_assertions,
132 options,
133 )
134 .set_num_transition_exemptions(2);
135
136 Self {
137 context,
138 stack_inputs: pub_inputs.stack_inputs,
139 stack_outputs: pub_inputs.stack_outputs,
140 constraint_ranges,
141 }
142 }
143
144 fn get_periodic_column_values(&self) -> Vec<Vec<Felt>> {
149 chiplets::get_periodic_column_values()
150 }
151
152 fn get_assertions(&self) -> Vec<Assertion<Felt>> {
156 let mut result = vec![Assertion::single(CLK_COL_IDX, 0, ZERO)];
159
160 if IS_FULL_CONSTRAINT_SET {
161 result.push(Assertion::single(FMP_COL_IDX, 0, Felt::new(2u64.pow(30))));
163
164 stack::get_assertions_first_step(&mut result, &*self.stack_inputs);
166
167 range::get_assertions_first_step(&mut result);
169
170 let last_step = self.last_step();
173
174 stack::get_assertions_last_step(&mut result, last_step, &self.stack_outputs);
176
177 range::get_assertions_last_step(&mut result, last_step);
179 }
180
181 result
182 }
183
184 fn get_aux_assertions<E: FieldElement<BaseField = Self::BaseField>>(
185 &self,
186 _aux_rand_elements: &AuxRandElements<E>,
187 ) -> Vec<Assertion<E>> {
188 let mut result: Vec<Assertion<E>> = Vec::new();
189
190 if IS_FULL_CONSTRAINT_SET {
192 stack::get_aux_assertions_first_step(&mut result);
194
195 range::get_aux_assertions_first_step::<E>(&mut result);
197
198 let last_step = self.last_step();
201
202 stack::get_aux_assertions_last_step(&mut result, last_step);
204 }
205 let last_step = self.last_step();
207 range::get_aux_assertions_last_step::<E>(&mut result, last_step);
208
209 result
210 }
211
212 fn evaluate_transition<E: FieldElement<BaseField = Felt>>(
216 &self,
217 frame: &EvaluationFrame<E>,
218 periodic_values: &[E],
219 result: &mut [E],
220 ) {
221 let current = frame.current();
222 let next = frame.next();
223
224 result[0] = next[CLK_COL_IDX] - (current[CLK_COL_IDX] + E::ONE);
227
228 if IS_FULL_CONSTRAINT_SET {
229 stack::enforce_constraints::<E>(
232 frame,
233 select_result_range!(result, self.constraint_ranges.stack),
234 );
235
236 range::enforce_constraints::<E>(
239 frame,
240 select_result_range!(result, self.constraint_ranges.range_checker),
241 );
242
243 chiplets::enforce_constraints::<E>(
245 frame,
246 periodic_values,
247 select_result_range!(result, self.constraint_ranges.chiplets),
248 );
249 }
250 }
251
252 fn evaluate_aux_transition<F, E>(
253 &self,
254 main_frame: &EvaluationFrame<F>,
255 aux_frame: &EvaluationFrame<E>,
256 _periodic_values: &[F],
257 aux_rand_elements: &AuxRandElements<E>,
258 result: &mut [E],
259 ) where
260 F: FieldElement<BaseField = Felt>,
261 E: FieldElement<BaseField = Felt> + ExtensionOf<F>,
262 {
263 range::enforce_aux_constraints::<F, E>(
265 main_frame,
266 aux_frame,
267 aux_rand_elements.rand_elements(),
268 result,
269 );
270 }
271
272 fn context(&self) -> &AirContext<Felt> {
273 &self.context
274 }
275
276 fn get_aux_rand_elements<E, R>(
277 &self,
278 public_coin: &mut R,
279 ) -> Result<AuxRandElements<E>, RandomCoinError>
280 where
281 E: FieldElement<BaseField = Self::BaseField>,
282 R: RandomCoin<BaseField = Self::BaseField>,
283 {
284 let num_elements = self.trace_info().get_num_aux_segment_rand_elements();
285 let mut rand_elements = Vec::with_capacity(num_elements);
286 let max_message_length = num_elements - 1;
287
288 let alpha = public_coin.draw()?;
289 let beta = public_coin.draw()?;
290
291 let betas = get_power_series(beta, max_message_length);
292
293 rand_elements.push(alpha);
294 rand_elements.extend_from_slice(&betas);
295
296 Ok(AuxRandElements::new(rand_elements))
297 }
298}
299
300#[derive(Debug)]
304pub struct PublicInputs {
305 program_info: ProgramInfo,
306 stack_inputs: StackInputs,
307 stack_outputs: StackOutputs,
308}
309
310impl PublicInputs {
311 pub fn new(
312 program_info: ProgramInfo,
313 stack_inputs: StackInputs,
314 stack_outputs: StackOutputs,
315 ) -> Self {
316 Self {
317 program_info,
318 stack_inputs,
319 stack_outputs,
320 }
321 }
322}
323
324impl vm_core::ToElements<Felt> for PublicInputs {
325 fn to_elements(&self) -> Vec<Felt> {
326 let mut result = self.stack_inputs.to_vec();
327 result.append(&mut self.stack_outputs.to_vec());
328 result.append(&mut self.program_info.to_elements());
329 result
330 }
331}
332
333impl Serializable for PublicInputs {
337 fn write_into<W: ByteWriter>(&self, target: &mut W) {
338 self.program_info.write_into(target);
339 self.stack_inputs.write_into(target);
340 self.stack_outputs.write_into(target);
341 }
342}
343
344impl Deserializable for PublicInputs {
345 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
346 let program_info = ProgramInfo::read_from(source)?;
347 let stack_inputs = StackInputs::read_from(source)?;
348 let stack_outputs = StackOutputs::read_from(source)?;
349
350 Ok(PublicInputs {
351 program_info,
352 stack_inputs,
353 stack_outputs,
354 })
355 }
356}