Skip to main content

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}