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}