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