Skip to main content

sp1_sdk/blocking/prover/
prove.rs

1use super::Prover;
2use crate::{SP1ProofMode, SP1ProofWithPublicValues, StatusCode};
3use sp1_core_executor::SP1ContextBuilder;
4use sp1_core_machine::io::SP1Stdin;
5
6/// A unified collection of methods for all prover types.
7pub trait ProveRequest<'a, P>
8where
9    Self: Sized,
10    P: Prover + 'a,
11{
12    /// Get the base request for the prover.
13    fn base(&mut self) -> &mut BaseProveRequest<'a, P>;
14
15    /// Run the prove request.
16    fn run(self) -> Result<SP1ProofWithPublicValues, P::Error>;
17
18    /// Set the proof mode to the given [`SP1ProofKind`].
19    ///
20    /// # Details
21    /// This method is useful for setting the proof mode to a custom mode.
22    ///
23    /// # Example
24    /// ```rust,no_run
25    /// use sp1_sdk::blocking::{Elf, ProveRequest, Prover, ProverClient, SP1ProofMode, SP1Stdin};
26    ///
27    /// let elf = Elf::Static(&[1, 2, 3]);
28    /// let stdin = SP1Stdin::new();
29    ///
30    /// let client = ProverClient::builder().cpu().build();
31    /// let pk = client.setup(elf).unwrap();
32    /// let proof = client.prove(&pk, stdin).mode(SP1ProofMode::Groth16).run().unwrap();
33    /// ```
34    #[must_use]
35    fn mode(mut self, mode: SP1ProofMode) -> Self {
36        self.base().mode(mode);
37        self
38    }
39
40    /// Set the proof kind to [`SP1ProofKind::Compressed`] mode.
41    ///
42    /// # Details
43    /// This mode produces a proof that is of constant size, regardless of the number of cycles. It
44    /// takes longer to prove than [`SP1ProofKind::Core`] due to the need to recursively aggregate
45    /// proofs into a single proof.
46    ///
47    /// # Example
48    /// ```rust,no_run
49    /// use sp1_sdk::blocking::{Elf, ProveRequest, Prover, ProverClient, SP1ProofMode, SP1Stdin};
50    ///
51    /// let elf = Elf::Static(&[1, 2, 3]);
52    /// let stdin = SP1Stdin::new();
53    ///
54    /// let client = ProverClient::builder().cpu().build();
55    /// let pk = client.setup(elf).unwrap();
56    /// let proof = client.prove(&pk, stdin).compressed().run().unwrap();
57    /// ```
58    #[must_use]
59    fn compressed(mut self) -> Self {
60        self.base().compressed();
61        self
62    }
63
64    /// Set the proof mode to [`SP1ProofKind::Plonk`] mode.
65    ///
66    /// # Details
67    /// This mode produces a const size PLONK proof that can be verified on chain for roughly ~300k
68    /// gas. This mode is useful for producing a maximally small proof that can be verified on
69    /// chain. For more efficient SNARK wrapping, you can use the [`SP1ProofKind::Groth16`] mode but
70    /// this mode is more .
71    ///
72    /// # Example
73    /// ```rust,no_run
74    /// use sp1_sdk::blocking::{Elf, ProveRequest, Prover, ProverClient, SP1ProofMode, SP1Stdin};
75    ///
76    /// let elf = Elf::Static(&[1, 2, 3]);
77    /// let stdin = SP1Stdin::new();
78    ///
79    /// let client = ProverClient::builder().cpu().build();
80    /// let pk = client.setup(elf).unwrap();
81    /// let proof = client.prove(&pk, stdin).plonk().run().unwrap();
82    /// ```
83    #[must_use]
84    fn plonk(mut self) -> Self {
85        self.base().plonk();
86        self
87    }
88
89    /// Set the proof mode to [`SP1ProofKind::Groth16`] mode.
90    ///
91    /// # Details
92    /// This mode produces a Groth16 proof that can be verified on chain for roughly ~100k gas. This
93    /// mode is useful for producing a proof that can be verified on chain with minimal gas.
94    ///
95    /// # Example
96    /// ```rust,no_run
97    /// use sp1_sdk::blocking::{Elf, ProveRequest, Prover, ProverClient, SP1ProofMode, SP1Stdin};
98    ///
99    /// let elf = Elf::Static(&[1, 2, 3]);
100    /// let stdin = SP1Stdin::new();
101    ///
102    /// let client = ProverClient::builder().cpu().build();
103    /// let pk = client.setup(elf).unwrap();
104    /// let builder = client.prove(&pk, stdin).groth16().run();
105    /// ```
106    #[must_use]
107    fn groth16(mut self) -> Self {
108        self.base().groth16();
109        self
110    }
111
112    /// Set the proof kind to [`SP1ProofKind::Core`] mode.
113    ///
114    /// # Details
115    /// This is the default mode for the prover. The proofs grow linearly in size with the number
116    /// of cycles.
117    ///
118    /// # Example
119    /// ```rust,no_run
120    /// use sp1_sdk::blocking::{Elf, ProveRequest, Prover, ProverClient, SP1ProofMode, SP1Stdin};
121    ///
122    /// let elf = Elf::Static(&[1, 2, 3]);
123    /// let stdin = SP1Stdin::new();
124    ///
125    /// let client = ProverClient::builder().cpu().build();
126    /// let pk = client.setup(elf).unwrap();
127    /// let builder = client.prove(&pk, stdin).core().run();
128    /// ```
129    #[must_use]
130    fn core(mut self) -> Self {
131        self.base().core();
132        self
133    }
134
135    /// Set the maximum number of cpu cycles to use for execution.
136    ///
137    /// # Details
138    /// If the cycle limit is exceeded, execution will return
139    /// [`sp1_core_executor::ExecutionError::ExceededCycleLimit`].
140    ///
141    /// # Example
142    /// ```rust,no_run
143    /// use sp1_sdk::blocking::{Elf, ProveRequest, Prover, ProverClient, SP1ProofMode, SP1Stdin};
144    ///
145    /// let elf = Elf::Static(&[1, 2, 3]);
146    /// let stdin = SP1Stdin::new();
147    ///
148    /// let client = ProverClient::builder().cpu().build();
149    /// let pk = client.setup(elf).unwrap();
150    /// let builder = client.prove(&pk, stdin).cycle_limit(1000000).run();
151    /// ```
152    #[must_use]
153    fn cycle_limit(mut self, cycle_limit: u64) -> Self {
154        self.base().cycle_limit(cycle_limit);
155        self
156    }
157
158    /// Whether to enable deferred proof verification in the executor.
159    ///
160    /// # Arguments
161    /// * `value` - Whether to enable deferred proof verification in the executor.
162    ///
163    /// # Details
164    /// Default: `true`. If set to `false`, the executor will skip deferred proof verification.
165    /// This is useful for reducing the execution time of the program and optimistically assuming
166    /// that the deferred proofs are correct. Can also be used for mock proof setups that require
167    /// verifying mock compressed proofs.
168    ///
169    /// # Example
170    /// ```rust,no_run
171    /// use sp1_sdk::blocking::{Elf, ProveRequest, Prover, ProverClient, SP1ProofMode, SP1Stdin};
172    ///
173    /// let elf = Elf::Static(&[1, 2, 3]);
174    /// let stdin = SP1Stdin::new();
175    ///
176    /// let client = ProverClient::builder().cpu().build();
177    /// let pk = client.setup(elf).unwrap();
178    /// let proof = client.prove(&pk, stdin).deferred_proof_verification(false).run().unwrap();
179    /// ```
180    #[must_use]
181    fn deferred_proof_verification(mut self, value: bool) -> Self {
182        self.base().deferred_proof_verification(value);
183        self
184    }
185
186    /// Set the expected exit code of the program.
187    ///
188    /// # Arguments
189    /// * `code` - The expected exit code of the program.
190    #[must_use]
191    fn expected_exit_code(mut self, code: StatusCode) -> Self {
192        self.base().expected_exit_code(code);
193        self
194    }
195
196    /// Set the proof nonce for this execution.
197    ///
198    /// The nonce ensures each proof is unique even for identical programs and inputs.
199    /// If not provided, will default to 0.
200    ///
201    /// # Arguments
202    /// * `nonce` - A 4-element array representing 128 bits of nonce data.
203    #[must_use]
204    fn with_proof_nonce(mut self, nonce: [u32; 4]) -> Self {
205        self.base().context_builder.proof_nonce(nonce);
206        self
207    }
208}
209
210/// The base prove request for a prover.
211///
212/// This exposes all the options that are shared across different prover types.
213pub struct BaseProveRequest<'a, P: Prover> {
214    pub(crate) prover: &'a P,
215    pub(crate) pk: &'a P::ProvingKey,
216    pub(crate) stdin: SP1Stdin,
217    pub(crate) mode: SP1ProofMode,
218    pub(crate) context_builder: SP1ContextBuilder<'static>,
219}
220
221impl<'a, P: Prover> BaseProveRequest<'a, P> {
222    /// Create a new [`BaseProveRequest`] with the given prover, proving key, and stdin.
223    ///
224    /// # Arguments
225    /// * `prover` - The prover to use.
226    /// * `pk` - The proving key to use.
227    /// * `stdin` - The stdin to use.
228    pub const fn new(prover: &'a P, pk: &'a P::ProvingKey, stdin: SP1Stdin) -> Self {
229        Self {
230            prover,
231            pk,
232            stdin,
233            mode: SP1ProofMode::Core,
234            context_builder: SP1ContextBuilder::new(),
235        }
236    }
237
238    /// See [`ProveRequest::compressed`].
239    pub fn compressed(&mut self) {
240        self.mode = SP1ProofMode::Compressed;
241    }
242
243    /// See [`ProveRequest::plonk`].
244    pub fn plonk(&mut self) {
245        self.mode = SP1ProofMode::Plonk;
246    }
247
248    /// See [`ProveRequest::groth16`].
249    pub fn groth16(&mut self) {
250        self.mode = SP1ProofMode::Groth16;
251    }
252
253    /// See [`ProveRequest::core`].
254    pub fn core(&mut self) {
255        self.mode = SP1ProofMode::Core;
256    }
257
258    /// See [`ProveRequest::mode`].
259    pub fn mode(&mut self, mode: SP1ProofMode) {
260        self.mode = mode;
261    }
262
263    /// See [`ProveRequest::cycle_limit`].
264    pub fn cycle_limit(&mut self, cycle_limit: u64) {
265        self.context_builder.max_cycles(cycle_limit);
266    }
267
268    /// See [`ProveRequest::deferred_proof_verification`].
269    pub fn deferred_proof_verification(&mut self, value: bool) {
270        self.context_builder.set_deferred_proof_verification(value);
271    }
272
273    /// See [`ProveRequest::expected_exit_code`].
274    pub fn expected_exit_code(&mut self, code: StatusCode) {
275        self.context_builder.expected_exit_code(code);
276    }
277
278    pub fn with_nonce(&mut self, nonce: [u32; 4]) {
279        self.context_builder.proof_nonce(nonce);
280    }
281}