miden_air/
options.rs

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