risc0_zkvm/host/client/prove/
opts.rs

1// Copyright 2025 RISC Zero, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Module containing the [ProverOpts] struct and related functionality.
16
17#[cfg(feature = "prove")]
18use anyhow::Result;
19use risc0_circuit_recursion::control_id::ALLOWED_CONTROL_IDS;
20use risc0_zkp::core::digest::Digest;
21use serde::{Deserialize, Serialize};
22
23use crate::receipt::DEFAULT_MAX_PO2;
24
25/// Options to configure a [Prover][super::Prover].
26#[derive(Clone, Debug, Serialize, Deserialize)]
27#[non_exhaustive]
28pub struct ProverOpts {
29    /// Identifier of the hash function to use for the STARK proving protocol.
30    pub hashfn: String,
31
32    /// When false, only prove execution sessions that end in a successful
33    /// [crate::ExitCode] (i.e. `Halted(0)` or `Paused(0)`).
34    /// When set to true, any completed execution session will be proven, including indicated
35    /// errors (e.g. `Halted(1)`) and sessions ending in `Fault`.
36    pub prove_guest_errors: bool,
37
38    /// Kind of receipt to be generated by the prover.
39    pub receipt_kind: ReceiptKind,
40
41    /// List of control IDs to enable for recursion proving.
42    ///
43    /// This list is used to construct the control root, which commits to the set of recursion
44    /// programs that are allowed to run and is a key field in the
45    /// [SuccinctReceiptVerifierParameters][crate::SuccinctReceiptVerifierParameters].
46    pub control_ids: Vec<Digest>,
47
48    /// Maximum cycle count, as a power of two (po2) that these prover options support.
49    pub(crate) max_segment_po2: usize,
50
51    /// Whether or not dev-mode is enabled. If enabled, fake receipts may be generated, and fake
52    /// receipts will verify successfully.
53    pub(crate) dev_mode: bool,
54}
55
56/// An enumeration of receipt kinds that can be requested to be generated.
57#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
58#[non_exhaustive]
59pub enum ReceiptKind {
60    /// Request that a [CompositeReceipt][crate::CompositeReceipt] be generated.
61    ///
62    /// Composite receipts are made up of a receipt for every segment in a zkVM execution, and
63    /// every assumption. They are linear in size with respect to the execution length.
64    Composite,
65
66    /// Request that a [SuccinctReceipt][crate::SuccinctReceipt] be generated.
67    ///
68    /// Succinct receipts are constant in size, with respect to the execution length.
69    ///
70    Succinct,
71
72    /// Request that a [Groth16Receipt][crate::Groth16Receipt] be generated.
73    ///
74    /// Groth16 receipts are proven using Groth16, are constant in size, and are the smallest
75    /// available receipt format. A Groth16 receipt can be serialized to a few hundred bytes.
76    Groth16,
77}
78
79impl Default for ProverOpts {
80    /// Return [ProverOpts] that are intended to work for most applications.
81    ///
82    /// Proof generated with these options may be linear in size with the execution length, but
83    /// can be compressed using the [Prover::compress][super::Prover::compress] methods.
84    fn default() -> Self {
85        Self {
86            hashfn: "poseidon2".to_string(),
87            prove_guest_errors: false,
88            receipt_kind: ReceiptKind::Composite,
89            control_ids: ALLOWED_CONTROL_IDS.to_vec(),
90            max_segment_po2: DEFAULT_MAX_PO2,
91            dev_mode: crate::is_dev_mode_enabled_via_environment(),
92        }
93    }
94}
95
96impl ProverOpts {
97    /// Construct a [ProverOpts] ready to prove segments with up to the given max cycle count as a
98    /// power of two (po2). All fields are equal to the default expect where they need to be
99    /// adjusted to support a larger po2.
100    ///
101    /// NOTE: If the po2 used to prove is greater than the targeted verifier supports,
102    /// [DEFAULT_MAX_PO2] by default, receipts will be rejected by the verifier.
103    #[stability::unstable]
104    pub fn from_max_po2(po2_max: usize) -> Self {
105        Self {
106            hashfn: "poseidon2".to_string(),
107            prove_guest_errors: false,
108            receipt_kind: ReceiptKind::Composite,
109            control_ids: crate::receipt::succinct::allowed_control_ids("poseidon2", po2_max)
110                .unwrap()
111                .collect(),
112            max_segment_po2: po2_max,
113            dev_mode: crate::is_dev_mode_enabled_via_environment(),
114        }
115    }
116
117    /// Construct a verifier context that will accept receipts with control any of the default
118    /// control ID associated with cycle counts of all supported powers of two (po2).
119    #[stability::unstable]
120    pub fn all_po2s() -> Self {
121        Self::from_max_po2(risc0_zkp::MAX_CYCLES_PO2)
122    }
123
124    /// Choose the fastest prover options. Receipt will be linear in length of the execution,
125    ///
126    /// This is an alias for [ProverOpts::composite].
127    pub fn fast() -> Self {
128        Self::composite()
129    }
130
131    /// Choose the prover that generates composite receipts, linear in the length of the execution,
132    /// and supports compression via recursion.
133    pub fn composite() -> Self {
134        Self {
135            hashfn: "poseidon2".to_string(),
136            prove_guest_errors: false,
137            receipt_kind: ReceiptKind::Composite,
138            control_ids: ALLOWED_CONTROL_IDS.to_vec(),
139            max_segment_po2: DEFAULT_MAX_PO2,
140            dev_mode: crate::is_dev_mode_enabled_via_environment(),
141        }
142    }
143
144    /// Choose the prover that generates succinct receipts, which are constant size in the length
145    /// of execution.
146    pub fn succinct() -> Self {
147        Self {
148            hashfn: "poseidon2".to_string(),
149            prove_guest_errors: false,
150            receipt_kind: ReceiptKind::Succinct,
151            control_ids: ALLOWED_CONTROL_IDS.to_vec(),
152            max_segment_po2: DEFAULT_MAX_PO2,
153            dev_mode: crate::is_dev_mode_enabled_via_environment(),
154        }
155    }
156
157    /// Choose the prover that generates Groth16 receipts which are constant size in the length of
158    /// the execution and small enough to verify on blockchains, like Ethereum.
159    ///
160    /// Only supported with Docker installed.
161    pub fn groth16() -> Self {
162        Self {
163            hashfn: "poseidon2".to_string(),
164            prove_guest_errors: false,
165            receipt_kind: ReceiptKind::Groth16,
166            control_ids: ALLOWED_CONTROL_IDS.to_vec(),
167            max_segment_po2: DEFAULT_MAX_PO2,
168            dev_mode: crate::is_dev_mode_enabled_via_environment(),
169        }
170    }
171
172    /// Return [ProverOpts] with the hashfn set to the given value.
173    pub fn with_hashfn(self, hashfn: String) -> Self {
174        Self {
175            hashfn: hashfn.to_owned(),
176            ..self
177        }
178    }
179
180    /// Return [ProverOpts] with prove_guest_errors set to the given value.
181    pub fn with_prove_guest_errors(self, prove_guest_errors: bool) -> Self {
182        Self {
183            prove_guest_errors,
184            ..self
185        }
186    }
187
188    /// Return [ProverOpts] with the receipt_kind set to the given value.
189    pub fn with_receipt_kind(self, receipt_kind: ReceiptKind) -> Self {
190        Self {
191            receipt_kind,
192            ..self
193        }
194    }
195
196    /// Return [ProverOpts] with the control_ids set to the given value.
197    pub fn with_control_ids(self, control_ids: Vec<Digest>) -> Self {
198        Self {
199            control_ids,
200            ..self
201        }
202    }
203
204    /// Return [ProverOpts] with the max_segment_po2 set to the given value.
205    #[stability::unstable]
206    pub fn with_segment_po2_max(self, max_segment_po2: usize) -> Self {
207        Self {
208            max_segment_po2,
209            ..self
210        }
211    }
212
213    /// Return [ProverOpts] with dev_mode enabled or disabled.
214    pub fn with_dev_mode(self, dev_mode: bool) -> Self {
215        if cfg!(feature = "disable-dev-mode") && dev_mode {
216            panic!("zkVM: Inconsistent settings -- please resolve. \
217                The RISC0_DEV_MODE environment variable is set but dev mode has been disabled by feature flag.");
218        }
219        Self { dev_mode, ..self }
220    }
221
222    /// Returns `true` if dev-mode is enabled.
223    pub fn dev_mode(&self) -> bool {
224        self.dev_mode
225    }
226
227    #[cfg(feature = "prove")]
228    pub(crate) fn hash_suite(
229        &self,
230    ) -> Result<risc0_zkp::core::hash::HashSuite<risc0_zkp::field::baby_bear::BabyBear>> {
231        risc0_zkp::core::hash::hash_suite_from_name(&self.hashfn)
232            .ok_or_else(|| anyhow::anyhow!("unsupported hash suite: {}", self.hashfn))
233    }
234}