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