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}