sp1_sdk/cuda/prove.rs
1//! # CUDA Proving
2//!
3//! This module provides a builder for proving a program on the CUDA.
4
5use anyhow::Result;
6use sp1_core_machine::io::SP1Stdin;
7use sp1_prover::{components::CpuProverComponents, SP1ProvingKey};
8
9use super::CudaProver;
10use crate::{Prover, SP1ProofMode, SP1ProofWithPublicValues};
11
12/// A builder for proving a program on the CUDA.
13///
14/// This builder provides a typed interface for configuring the SP1 RISC-V prover. The builder is
15/// used for only the [`crate::cuda::CudaProver`] client type.
16pub struct CudaProveBuilder<'a> {
17 pub(crate) prover: &'a CudaProver,
18 pub(crate) mode: SP1ProofMode,
19 pub(crate) pk: &'a SP1ProvingKey,
20 pub(crate) stdin: SP1Stdin,
21}
22
23impl CudaProveBuilder<'_> {
24 /// Set the proof kind to [`SP1ProofMode::Core`] mode.
25 ///
26 /// # Details
27 /// This is the default mode for the prover. The proofs grow linearly in size with the number
28 /// of cycles.
29 ///
30 /// # Example
31 /// ```rust,no_run
32 /// use sp1_sdk::{include_elf, Prover, ProverClient, SP1Stdin};
33 ///
34 /// let elf = &[1, 2, 3];
35 /// let stdin = SP1Stdin::new();
36 ///
37 /// let client = ProverClient::builder().cuda().build();
38 /// let (pk, vk) = client.setup(elf);
39 /// let builder = client.prove(&pk, &stdin).core().run();
40 /// ```
41 #[must_use]
42 pub fn core(mut self) -> Self {
43 self.mode = SP1ProofMode::Core;
44 self
45 }
46
47 /// Set the proof kind to [`SP1ProofMode::Compressed`] mode.
48 ///
49 /// # Details
50 /// This mode produces a proof that is of constant size, regardless of the number of cycles. It
51 /// takes longer to prove than [`SP1ProofMode::Core`] due to the need to recursively aggregate
52 /// proofs into a single proof.
53 ///
54 /// # Example
55 /// ```rust,no_run
56 /// use sp1_sdk::{include_elf, Prover, ProverClient, SP1Stdin};
57 ///
58 /// let elf = &[1, 2, 3];
59 /// let stdin = SP1Stdin::new();
60 ///
61 /// let client = ProverClient::builder().cuda().build();
62 /// let (pk, vk) = client.setup(elf);
63 /// let builder = client.prove(&pk, &stdin).compressed().run();
64 /// ```
65 #[must_use]
66 pub fn compressed(mut self) -> Self {
67 self.mode = SP1ProofMode::Compressed;
68 self
69 }
70
71 /// Set the proof mode to [`SP1ProofMode::Plonk`] mode.
72 ///
73 /// # Details
74 /// This mode produces a const size PLONK proof that can be verified on chain for roughly ~300k
75 /// gas. This mode is useful for producing a maximally small proof that can be verified on
76 /// chain. For more efficient SNARK wrapping, you can use the [`SP1ProofMode::Groth16`] mode but
77 /// this mode is more .
78 ///
79 /// # Example
80 /// ```rust,no_run
81 /// use sp1_sdk::{include_elf, Prover, ProverClient, SP1Stdin};
82 ///
83 /// let elf = &[1, 2, 3];
84 /// let stdin = SP1Stdin::new();
85 ///
86 /// let client = ProverClient::builder().cuda().build();
87 /// let (pk, vk) = client.setup(elf);
88 /// let builder = client.prove(&pk, &stdin).plonk().run();
89 /// ```
90 #[must_use]
91 pub fn plonk(mut self) -> Self {
92 self.mode = SP1ProofMode::Plonk;
93 self
94 }
95
96 /// Set the proof mode to [`SP1ProofMode::Groth16`] mode.
97 ///
98 /// # Details
99 /// This mode produces a Groth16 proof that can be verified on chain for roughly ~100k gas. This
100 /// mode is useful for producing a proof that can be verified on chain with minimal gas.
101 ///
102 /// # Example
103 /// ```rust,no_run
104 /// use sp1_sdk::{include_elf, Prover, ProverClient, SP1Stdin};
105 ///
106 /// let elf = &[1, 2, 3];
107 /// let stdin = SP1Stdin::new();
108 ///
109 /// let client = ProverClient::builder().cuda().build();
110 /// let (pk, vk) = client.setup(elf);
111 /// let builder = client.prove(&pk, &stdin).groth16().run();
112 /// ```
113 #[must_use]
114 pub fn groth16(mut self) -> Self {
115 self.mode = SP1ProofMode::Groth16;
116 self
117 }
118
119 /// Set the proof mode to the given [`SP1ProofMode`].
120 ///
121 /// # Details
122 /// This method is useful for setting the proof mode to a custom mode.
123 ///
124 /// # Example
125 /// ```rust,no_run
126 /// use sp1_sdk::{include_elf, Prover, ProverClient, SP1ProofMode, SP1Stdin};
127 ///
128 /// let elf = &[1, 2, 3];
129 /// let stdin = SP1Stdin::new();
130 ///
131 /// let client = ProverClient::builder().cuda().build();
132 /// let (pk, vk) = client.setup(elf);
133 /// let builder = client.prove(&pk, &stdin).mode(SP1ProofMode::Groth16).run();
134 /// ```
135 #[must_use]
136 pub fn mode(mut self, mode: SP1ProofMode) -> Self {
137 self.mode = mode;
138 self
139 }
140
141 /// Run the prover with the built arguments.
142 ///
143 /// # Details
144 /// This method will run the prover with the built arguments. If the prover fails to run, the
145 /// method will return an error.
146 ///
147 /// # Example
148 /// ```rust,no_run
149 /// use sp1_sdk::{include_elf, Prover, ProverClient, SP1Stdin};
150 ///
151 /// let elf = &[1, 2, 3];
152 /// let stdin = SP1Stdin::new();
153 ///
154 /// let client = ProverClient::builder().cuda().build();
155 /// let (pk, vk) = client.setup(elf);
156 /// let proof = client.prove(&pk, &stdin).run().unwrap();
157 /// ```
158 pub fn run(self) -> Result<SP1ProofWithPublicValues> {
159 let Self { prover, mode: kind, pk, stdin } = self;
160
161 // Dump the program and stdin to files for debugging if `SP1_DUMP` is set.
162 crate::utils::sp1_dump(&pk.elf, &stdin);
163
164 Prover::<CpuProverComponents>::prove(prover, pk, &stdin, kind)
165 }
166}