miden_air/options.rs
1use winter_air::BatchingMethod;
2
3use super::{
4 ExecutionOptionsError, FieldExtension, HashFunction, WinterProofOptions, trace::MIN_TRACE_LEN,
5};
6
7// PROVING OPTIONS
8// ================================================================================================
9
10/// A set of parameters specifying how Miden VM execution proofs are to be generated.
11#[derive(Debug, Clone, Eq, PartialEq)]
12pub struct ProvingOptions {
13 exec_options: ExecutionOptions,
14 proof_options: WinterProofOptions,
15 hash_fn: HashFunction,
16}
17
18impl ProvingOptions {
19 // CONSTANTS
20 // --------------------------------------------------------------------------------------------
21
22 /// Standard proof parameters for 96-bit conjectured security in non-recursive context.
23 pub const REGULAR_96_BITS: WinterProofOptions = WinterProofOptions::new(
24 27,
25 8,
26 16,
27 FieldExtension::Quadratic,
28 8,
29 255,
30 BatchingMethod::Algebraic,
31 BatchingMethod::Algebraic,
32 );
33
34 /// Standard proof parameters for 128-bit conjectured security in non-recursive context.
35 pub const REGULAR_128_BITS: WinterProofOptions = WinterProofOptions::new(
36 27,
37 16,
38 21,
39 FieldExtension::Cubic,
40 8,
41 255,
42 BatchingMethod::Algebraic,
43 BatchingMethod::Algebraic,
44 );
45
46 /// Standard proof parameters for 96-bit conjectured security in recursive context.
47 pub const RECURSIVE_96_BITS: WinterProofOptions = WinterProofOptions::new(
48 27,
49 8,
50 16,
51 FieldExtension::Quadratic,
52 4,
53 127,
54 BatchingMethod::Algebraic,
55 BatchingMethod::Horner,
56 );
57
58 /// Standard proof parameters for 128-bit conjectured security in recursive context.
59 pub const RECURSIVE_128_BITS: WinterProofOptions = WinterProofOptions::new(
60 27,
61 16,
62 21,
63 FieldExtension::Cubic,
64 4,
65 7,
66 BatchingMethod::Horner,
67 BatchingMethod::Horner,
68 );
69
70 // CONSTRUCTORS
71 // --------------------------------------------------------------------------------------------
72
73 /// Creates a new instance of [ProvingOptions] from the specified parameters.
74 pub fn new(
75 num_queries: usize,
76 blowup_factor: usize,
77 grinding_factor: u32,
78 field_extension: FieldExtension,
79 fri_folding_factor: usize,
80 fri_remainder_max_degree: usize,
81 hash_fn: HashFunction,
82 ) -> Self {
83 let proof_options = WinterProofOptions::new(
84 num_queries,
85 blowup_factor,
86 grinding_factor,
87 field_extension,
88 fri_folding_factor,
89 fri_remainder_max_degree,
90 BatchingMethod::Algebraic,
91 BatchingMethod::Horner,
92 );
93 let exec_options = ExecutionOptions::default();
94 Self { exec_options, proof_options, hash_fn }
95 }
96
97 /// Creates a new preset instance of [ProvingOptions] targeting 96-bit security level, given
98 /// a choice of a hash function.
99 ///
100 /// If the hash function is arithmetization-friendly then proofs will be generated using
101 /// settings that are well-suited for recursive verification.
102 pub fn with_96_bit_security(hash_fn: HashFunction) -> Self {
103 let proof_options = match hash_fn {
104 HashFunction::Blake3_192 | HashFunction::Blake3_256 => Self::REGULAR_96_BITS,
105 HashFunction::Rpo256 | HashFunction::Rpx256 | HashFunction::Poseidon2 => {
106 Self::RECURSIVE_96_BITS
107 },
108 };
109 Self {
110 exec_options: ExecutionOptions::default(),
111 proof_options,
112 hash_fn,
113 }
114 }
115
116 /// Creates a new preset instance of [ProvingOptions] targeting 128-bit security level, given
117 /// a choice of a hash function, in the non-recursive setting.
118 ///
119 /// If the hash function is arithmetization-friendly then proofs will be generated using
120 /// settings that are well-suited for recursive verification.
121 pub fn with_128_bit_security(hash_fn: HashFunction) -> Self {
122 let proof_options = match hash_fn {
123 HashFunction::Blake3_192 | HashFunction::Blake3_256 => Self::REGULAR_128_BITS,
124 HashFunction::Rpo256 | HashFunction::Rpx256 | HashFunction::Poseidon2 => {
125 Self::RECURSIVE_128_BITS
126 },
127 };
128 Self {
129 exec_options: ExecutionOptions::default(),
130 proof_options,
131 hash_fn,
132 }
133 }
134
135 /// Sets [ExecutionOptions] for this [ProvingOptions].
136 ///
137 /// This sets the maximum number of cycles a program is allowed to execute as well as
138 /// the number of cycles the program is expected to execute.
139 pub fn with_execution_options(mut self, exec_options: ExecutionOptions) -> Self {
140 self.exec_options = exec_options;
141 self
142 }
143
144 // PUBLIC ACCESSORS
145 // --------------------------------------------------------------------------------------------
146
147 /// Returns the hash function to be used in STARK proof generation.
148 pub const fn hash_fn(&self) -> HashFunction {
149 self.hash_fn
150 }
151
152 /// Returns the execution options specified for this [ProvingOptions]
153 pub const fn execution_options(&self) -> &ExecutionOptions {
154 &self.exec_options
155 }
156}
157
158impl Default for ProvingOptions {
159 fn default() -> Self {
160 Self::with_96_bit_security(HashFunction::Blake3_192)
161 }
162}
163
164impl From<ProvingOptions> for WinterProofOptions {
165 fn from(options: ProvingOptions) -> Self {
166 options.proof_options
167 }
168}
169
170// EXECUTION OPTIONS
171// ================================================================================================
172
173/// A set of parameters specifying execution parameters of the VM.
174///
175/// - `max_cycles` specifies the maximum number of cycles a program is allowed to execute.
176/// - `expected_cycles` specifies the number of cycles a program is expected to execute.
177#[derive(Debug, Clone, Copy, PartialEq, Eq)]
178pub struct ExecutionOptions {
179 max_cycles: u32,
180 expected_cycles: u32,
181 enable_tracing: bool,
182 enable_debugging: bool,
183}
184
185impl Default for ExecutionOptions {
186 fn default() -> Self {
187 ExecutionOptions {
188 max_cycles: Self::MAX_CYCLES,
189 expected_cycles: MIN_TRACE_LEN as u32,
190 enable_tracing: false,
191 enable_debugging: false,
192 }
193 }
194}
195
196impl ExecutionOptions {
197 // CONSTANTS
198 // --------------------------------------------------------------------------------------------
199
200 /// The maximum number of VM cycles a program is allowed to take.
201 pub const MAX_CYCLES: u32 = 1 << 29;
202
203 // CONSTRUCTOR
204 // --------------------------------------------------------------------------------------------
205
206 /// Creates a new instance of [ExecutionOptions] from the specified parameters.
207 ///
208 /// If the `max_cycles` is `None` the maximum number of cycles will be set to 2^29.
209 pub fn new(
210 max_cycles: Option<u32>,
211 expected_cycles: u32,
212 enable_tracing: bool,
213 enable_debugging: bool,
214 ) -> Result<Self, ExecutionOptionsError> {
215 // Validate max cycles.
216 let max_cycles = if let Some(max_cycles) = max_cycles {
217 if max_cycles > Self::MAX_CYCLES {
218 return Err(ExecutionOptionsError::MaxCycleNumTooBig {
219 max_cycles,
220 max_cycles_limit: Self::MAX_CYCLES,
221 });
222 }
223 if max_cycles < MIN_TRACE_LEN as u32 {
224 return Err(ExecutionOptionsError::MaxCycleNumTooSmall {
225 max_cycles,
226 min_cycles_limit: MIN_TRACE_LEN,
227 });
228 }
229 max_cycles
230 } else {
231 Self::MAX_CYCLES
232 };
233 // Validate expected cycles.
234 if max_cycles < expected_cycles {
235 return Err(ExecutionOptionsError::ExpectedCyclesTooBig {
236 max_cycles,
237 expected_cycles,
238 });
239 }
240 // Round up the expected number of cycles to the next power of two. If it is smaller than
241 // MIN_TRACE_LEN -- pad expected number to it.
242 let expected_cycles = expected_cycles.next_power_of_two().max(MIN_TRACE_LEN as u32);
243
244 Ok(ExecutionOptions {
245 max_cycles,
246 expected_cycles,
247 enable_tracing,
248 enable_debugging,
249 })
250 }
251
252 /// Enables execution of the `trace` instructions.
253 pub fn with_tracing(mut self) -> Self {
254 self.enable_tracing = true;
255 self
256 }
257
258 /// Enables execution of programs in debug mode when the `enable_debugging` flag is set to true;
259 /// otherwise, debug mode is disabled.
260 ///
261 /// In debug mode the VM does the following:
262 /// - Executes `debug` instructions (these are ignored in regular mode).
263 /// - Records additional info about program execution (e.g., keeps track of stack state at every
264 /// cycle of the VM) which enables stepping through the program forward and backward.
265 pub fn with_debugging(mut self, enable_debugging: bool) -> Self {
266 self.enable_debugging = enable_debugging;
267 self
268 }
269
270 // PUBLIC ACCESSORS
271 // --------------------------------------------------------------------------------------------
272
273 /// Returns maximum number of cycles a program is allowed to execute for.
274 pub fn max_cycles(&self) -> u32 {
275 self.max_cycles
276 }
277
278 /// Returns the number of cycles a program is expected to take.
279 ///
280 /// This will serve as a hint to the VM for how much memory to allocate for a program's
281 /// execution trace and may result in performance improvements when the number of expected
282 /// cycles is equal to the number of actual cycles.
283 pub fn expected_cycles(&self) -> u32 {
284 self.expected_cycles
285 }
286
287 /// Returns a flag indicating whether the VM should execute `trace` instructions.
288 pub fn enable_tracing(&self) -> bool {
289 self.enable_tracing
290 }
291
292 /// Returns a flag indicating whether the VM should execute a program in debug mode.
293 pub fn enable_debugging(&self) -> bool {
294 self.enable_debugging
295 }
296}