sp1_sdk/client.rs
1//! # SP1 Prover Client
2//!
3//! A client for interacting with the prover for the SP1 RISC-V zkVM.
4
5use sp1_core_machine::riscv::RiscvAir;
6use sp1_hypercube::Machine;
7use sp1_primitives::SP1Field;
8
9use crate::{
10 cpu::builder::CpuProverBuilder, env::EnvProver, light::builder::LightProverBuilder,
11 mock::builder::MockProverBuilder,
12};
13
14#[cfg(feature = "cuda")]
15use crate::cuda::builder::CudaProverBuilder;
16
17#[cfg(feature = "network")]
18use crate::network::{builder::NetworkProverBuilder, NetworkMode};
19
20/// An entrypoint for interacting with the prover for the SP1 RISC-V zkVM.
21///
22/// IMPORTANT: `ProverClient` only needs to be initialized ONCE and can be reused for subsequent
23/// proving operations, all provers types are cheap to clone and share across threads.
24///
25/// Note that the initialization may be slow as it loads necessary proving parameters and sets up
26/// the environment.
27pub struct ProverClient;
28
29impl ProverClient {
30 /// Builds an [`EnvProver`], which loads the mode and any settings from the environment.
31 ///
32 /// # Usage
33 /// ```no_run
34 /// use sp1_sdk::{Elf, ProveRequest, Prover, ProverClient, SP1Stdin};
35 ///
36 /// tokio_test::block_on(async {
37 /// std::env::set_var("SP1_PROVER", "network");
38 /// std::env::set_var("NETWORK_PRIVATE_KEY", "...");
39 /// let prover = ProverClient::from_env().await;
40 ///
41 /// let elf = Elf::Static(&[1, 2, 3]);
42 /// let stdin = SP1Stdin::new();
43 ///
44 /// let pk = prover.setup(elf).await.unwrap();
45 /// let proof = prover.prove(&pk, stdin).compressed().await.unwrap();
46 /// });
47 /// ```
48 #[must_use]
49 pub async fn from_env() -> EnvProver {
50 Self::from_env_with_machine(RiscvAir::machine()).await
51 }
52
53 /// Same as `from_env` but with a custom machine.
54 #[must_use]
55 pub async fn from_env_with_machine(
56 machine: Machine<SP1Field, RiscvAir<SP1Field>>,
57 ) -> EnvProver {
58 EnvProver::new_with_machine(machine).await
59 }
60
61 /// Creates a new [`ProverClientBuilder`] so that you can configure the prover client.
62 #[must_use]
63 pub fn builder() -> ProverClientBuilder {
64 Self::builder_with_machine(RiscvAir::machine())
65 }
66
67 /// Creates a new [`ProverClientBuilder`] with a given machine.
68 #[must_use]
69 pub fn builder_with_machine(
70 machine: Machine<SP1Field, RiscvAir<SP1Field>>,
71 ) -> ProverClientBuilder {
72 ProverClientBuilder::new(machine)
73 }
74}
75
76/// A builder to define which proving client to use.
77pub struct ProverClientBuilder {
78 machine: Machine<SP1Field, RiscvAir<SP1Field>>,
79}
80
81impl ProverClientBuilder {
82 fn new(machine: Machine<SP1Field, RiscvAir<SP1Field>>) -> Self {
83 Self { machine }
84 }
85
86 /// Builds a [`CpuProver`] specifically for local CPU proving.
87 ///
88 /// # Usage
89 /// ```no_run
90 /// use sp1_sdk::{Elf, ProveRequest, Prover, ProverClient, SP1Stdin};
91 ///
92 /// tokio_test::block_on(async {
93 /// let elf = Elf::Static(&[1, 2, 3]);
94 /// let stdin = SP1Stdin::new();
95 ///
96 /// let prover = ProverClient::builder().cpu().build().await;
97 /// let pk = prover.setup(elf).await.unwrap();
98 /// let proof = prover.prove(&pk, stdin).compressed().await.unwrap();
99 /// });
100 /// ```
101 #[must_use]
102 pub fn cpu(&self) -> CpuProverBuilder {
103 CpuProverBuilder::new_with_machine(self.machine.clone())
104 }
105
106 /// Builds a [`CudaProver`] specifically for local proving on NVIDIA GPUs.
107 ///
108 /// # Example
109 /// ```no_run
110 /// use sp1_sdk::{Elf, ProveRequest, Prover, ProverClient, SP1Stdin};
111 ///
112 /// tokio_test::block_on(async {
113 /// let elf = Elf::Static(&[1, 2, 3]);
114 /// let stdin = SP1Stdin::new();
115 ///
116 /// let prover = ProverClient::builder().cuda().build().await;
117 /// let pk = prover.setup(elf).await.unwrap();
118 /// let proof = prover.prove(&pk, stdin).compressed().await.unwrap();
119 /// });
120 /// ```
121 #[cfg(feature = "cuda")]
122 #[must_use]
123 pub fn cuda(&self) -> CudaProverBuilder {
124 CudaProverBuilder::new_with_machine(self.machine.clone())
125 }
126
127 /// Builds a [`MockProver`] for testing without real proving or verification.
128 ///
129 /// # Example
130 /// ```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 prover = ProverClient::builder().mock().build().await;
138 /// let pk = prover.setup(elf).await.unwrap();
139 /// let proof = prover.prove(&pk, stdin).compressed().await.unwrap();
140 /// });
141 /// ```
142 #[must_use]
143 pub fn mock(&self) -> MockProverBuilder {
144 MockProverBuilder::new_with_machine(self.machine.clone())
145 }
146
147 /// Builds a [`LightProver`] that only executes and verifies but does not generate proofs.
148 ///
149 /// # Example
150 /// ```no_run
151 /// use sp1_sdk::{Elf, ProveRequest, Prover, ProverClient, SP1Stdin};
152 ///
153 /// tokio_test::block_on(async {
154 /// let elf = Elf::Static(&[1, 2, 3]);
155 /// let stdin = SP1Stdin::new();
156 ///
157 /// let prover = ProverClient::builder().light().build().await;
158 /// let pk = prover.setup(elf).await.unwrap();
159 /// let proof = prover.prove(&pk, stdin).compressed().await.unwrap();
160 /// });
161 /// ```
162 #[must_use]
163 pub fn light(&self) -> LightProverBuilder {
164 LightProverBuilder::new_with_machine(self.machine.clone())
165 }
166
167 /// Builds a [`NetworkProver`] specifically for proving on the network.
168 ///
169 /// # Example
170 /// ```no_run
171 /// use sp1_sdk::{Elf, ProveRequest, Prover, ProverClient, SP1Stdin};
172 ///
173 /// tokio_test::block_on(async {
174 /// let elf = Elf::Static(&[1, 2, 3]);
175 /// let stdin = SP1Stdin::new();
176 ///
177 /// let prover = ProverClient::builder().network().build().await;
178 /// let pk = prover.setup(elf).await.unwrap();
179 /// let proof = prover.prove(&pk, stdin).compressed().await.unwrap();
180 /// });
181 /// ```
182 #[cfg(feature = "network")]
183 #[must_use]
184 pub fn network(&self) -> NetworkProverBuilder {
185 NetworkProverBuilder::new_with_machine(self.machine.clone())
186 }
187
188 /// Builds a [`NetworkProver`] specifically for proving on the network with a specified mode.
189 ///
190 /// # Examples
191 /// ```no_run
192 /// use sp1_sdk::{network::NetworkMode, Elf, ProveRequest, Prover, ProverClient, SP1Stdin};
193 ///
194 /// tokio_test::block_on(async {
195 /// let elf = Elf::Static(&[1, 2, 3]);
196 /// let stdin = SP1Stdin::new();
197 ///
198 /// let prover = ProverClient::builder().network_for(NetworkMode::Mainnet).build().await;
199 /// let pk = prover.setup(elf).await.unwrap();
200 /// let proof = prover.prove(&pk, stdin).compressed().await.unwrap();
201 /// });
202 /// ```
203 #[cfg(feature = "network")]
204 #[must_use]
205 pub fn network_for(&self, mode: NetworkMode) -> NetworkProverBuilder {
206 NetworkProverBuilder {
207 private_key: None,
208 signer: None,
209 rpc_url: None,
210 tee_signers: None,
211 network_mode: Some(mode),
212 hosted: false,
213 machine: self.machine.clone(),
214 }
215 }
216
217 /// Builds a hosted [`NetworkProver`] for self-hosted clusters talking to the network-gateway.
218 ///
219 /// # Details
220 /// A hosted prover runs in [`NetworkMode::Reserved`] and makes `prove(&pk, stdin).await` skip
221 /// local simulation and use the maximum cycle and gas limits by default, so no
222 /// network-specific toggles are needed. The defaults remain overridable per request.
223 ///
224 /// # Example
225 /// ```no_run
226 /// use sp1_sdk::{Elf, ProveRequest, Prover, ProverClient, SP1Stdin};
227 ///
228 /// tokio_test::block_on(async {
229 /// let elf = Elf::Static(&[1, 2, 3]);
230 /// let stdin = SP1Stdin::new();
231 ///
232 /// let prover = ProverClient::builder().hosted().build().await;
233 /// let pk = prover.setup(elf).await.unwrap();
234 /// let proof = prover.prove(&pk, stdin).compressed().await.unwrap();
235 /// });
236 /// ```
237 #[cfg(feature = "network")]
238 #[must_use]
239 pub fn hosted(&self) -> NetworkProverBuilder {
240 self.network_for(NetworkMode::Reserved).hosted()
241 }
242}