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}