Skip to main content

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}