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 7,
54 BatchingMethod::Algebraic,
55 BatchingMethod::Algebraic,
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::Algebraic,
67 BatchingMethod::Algebraic,
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::Algebraic,
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.
98 ///
99 /// If `recursive` flag is set to true, proofs will be generated using an arithmetization-
100 /// friendly hash function (RPO). Such proofs are well-suited for recursive proof verification,
101 /// but may take significantly longer to generate.
102 pub fn with_96_bit_security(recursive: bool) -> Self {
103 if recursive {
104 Self {
105 exec_options: ExecutionOptions::default(),
106 proof_options: Self::RECURSIVE_96_BITS,
107 hash_fn: HashFunction::Rpo256,
108 }
109 } else {
110 Self {
111 exec_options: ExecutionOptions::default(),
112 proof_options: Self::REGULAR_96_BITS,
113 hash_fn: HashFunction::Blake3_192,
114 }
115 }
116 }
117
118 /// Creates a new preset instance of [ProvingOptions] targeting 96-bit security level,
119 /// using the RPX hashing function.
120 pub fn with_96_bit_security_rpx() -> Self {
121 Self {
122 exec_options: ExecutionOptions::default(),
123 proof_options: Self::RECURSIVE_96_BITS,
124 hash_fn: HashFunction::Rpx256,
125 }
126 }
127
128 /// Creates a new preset instance of [ProvingOptions] targeting 128-bit security level.
129 ///
130 /// If `recursive` flag is set to true, proofs will be generated using an arithmetization-
131 /// friendly hash function (RPO). Such proofs are well-suited for recursive proof verification,
132 /// but may take significantly longer to generate.
133 pub fn with_128_bit_security(recursive: bool) -> Self {
134 if recursive {
135 Self {
136 exec_options: ExecutionOptions::default(),
137 proof_options: Self::RECURSIVE_128_BITS,
138 hash_fn: HashFunction::Rpo256,
139 }
140 } else {
141 Self {
142 exec_options: ExecutionOptions::default(),
143 proof_options: Self::REGULAR_128_BITS,
144 hash_fn: HashFunction::Blake3_256,
145 }
146 }
147 }
148
149 /// Creates a new preset instance of [ProvingOptions] targeting 128-bit security level,
150 /// using the RPX hashing function.
151 pub fn with_128_bit_security_rpx() -> Self {
152 Self {
153 exec_options: ExecutionOptions::default(),
154 proof_options: Self::RECURSIVE_128_BITS,
155 hash_fn: HashFunction::Rpx256,
156 }
157 }
158
159 /// Sets [ExecutionOptions] for this [ProvingOptions].
160 ///
161 /// This sets the maximum number of cycles a program is allowed to execute as well as
162 /// the number of cycles the program is expected to execute.
163 pub fn with_execution_options(mut self, exec_options: ExecutionOptions) -> Self {
164 self.exec_options = exec_options;
165 self
166 }
167
168 // PUBLIC ACCESSORS
169 // --------------------------------------------------------------------------------------------
170
171 /// Returns the hash function to be used in STARK proof generation.
172 pub const fn hash_fn(&self) -> HashFunction {
173 self.hash_fn
174 }
175
176 /// Returns the execution options specified for this [ProvingOptions]
177 pub const fn execution_options(&self) -> &ExecutionOptions {
178 &self.exec_options
179 }
180}
181
182impl Default for ProvingOptions {
183 fn default() -> Self {
184 Self::with_96_bit_security(false)
185 }
186}
187
188impl From<ProvingOptions> for WinterProofOptions {
189 fn from(options: ProvingOptions) -> Self {
190 options.proof_options
191 }
192}
193
194// EXECUTION OPTIONS
195// ================================================================================================
196
197/// A set of parameters specifying execution parameters of the VM.
198///
199/// - `max_cycles` specifies the maximum number of cycles a program is allowed to execute.
200/// - `expected_cycles` specifies the number of cycles a program is expected to execute.
201#[derive(Debug, Clone, Copy, PartialEq, Eq)]
202pub struct ExecutionOptions {
203 max_cycles: u32,
204 expected_cycles: u32,
205 enable_tracing: bool,
206 enable_debugging: bool,
207}
208
209impl Default for ExecutionOptions {
210 fn default() -> Self {
211 ExecutionOptions {
212 max_cycles: u32::MAX,
213 expected_cycles: MIN_TRACE_LEN as u32,
214 enable_tracing: false,
215 enable_debugging: false,
216 }
217 }
218}
219
220impl ExecutionOptions {
221 // CONSTRUCTOR
222 // --------------------------------------------------------------------------------------------
223
224 /// Creates a new instance of [ExecutionOptions] from the specified parameters.
225 ///
226 /// If the `max_cycles` is `None` the maximum number of cycles will be set to `u32::MAX`
227 pub fn new(
228 max_cycles: Option<u32>,
229 expected_cycles: u32,
230 enable_tracing: bool,
231 enable_debugging: bool,
232 ) -> Result<Self, ExecutionOptionsError> {
233 let max_cycles = max_cycles.unwrap_or(u32::MAX);
234 if max_cycles < MIN_TRACE_LEN as u32 {
235 return Err(ExecutionOptionsError::MaxCycleNumTooSmall(expected_cycles));
236 }
237 if max_cycles < expected_cycles {
238 return Err(ExecutionOptionsError::ExpectedCyclesTooBig {
239 max_cycles,
240 expected_cycles,
241 });
242 }
243
244 // Round up the expected number of cycles to the next power of two. If it is smaller than
245 // MIN_TRACE_LEN -- pad expected number to it.
246 let expected_cycles = expected_cycles.next_power_of_two().max(MIN_TRACE_LEN as u32);
247
248 Ok(ExecutionOptions {
249 max_cycles,
250 expected_cycles,
251 enable_tracing,
252 enable_debugging,
253 })
254 }
255
256 /// Enables execution of the `trace` instructions.
257 pub fn with_tracing(mut self) -> Self {
258 self.enable_tracing = true;
259 self
260 }
261
262 /// Enables execution of programs in debug mode.
263 ///
264 /// In debug mode the VM does the following:
265 /// - Executes `debug` instructions (these are ignored in regular mode).
266 /// - Records additional info about program execution (e.g., keeps track of stack state at every
267 /// cycle of the VM) which enables stepping through the program forward and backward.
268 pub fn with_debugging(mut self) -> Self {
269 self.enable_debugging = true;
270 self
271 }
272
273 // PUBLIC ACCESSORS
274 // --------------------------------------------------------------------------------------------
275
276 /// Returns maximum number of cycles a program is allowed to execute for.
277 pub fn max_cycles(&self) -> u32 {
278 self.max_cycles
279 }
280
281 /// Returns the number of cycles a program is expected to take.
282 ///
283 /// This will serve as a hint to the VM for how much memory to allocate for a program's
284 /// execution trace and may result in performance improvements when the number of expected
285 /// cycles is equal to the number of actual cycles.
286 pub fn expected_cycles(&self) -> u32 {
287 self.expected_cycles
288 }
289
290 /// Returns a flag indicating whether the VM should execute `trace` instructions.
291 pub fn enable_tracing(&self) -> bool {
292 self.enable_tracing
293 }
294
295 /// Returns a flag indicating whether the VM should execute a program in debug mode.
296 pub fn enable_debugging(&self) -> bool {
297 self.enable_debugging
298 }
299}