sp1_sdk/env/mod.rs
1//! # SP1 Environment Prover
2//!
3//! A prover that can execute programs and generate proofs with a different implementation based on
4//! the value of certain environment variables.
5
6mod prove;
7
8use std::env;
9
10use anyhow::Result;
11use prove::EnvProveBuilder;
12use sp1_core_executor::SP1ContextBuilder;
13use sp1_core_machine::io::SP1Stdin;
14use sp1_cuda::MoongateServer;
15use sp1_prover::{components::CpuProverComponents, SP1Prover, SP1ProvingKey, SP1VerifyingKey};
16
17use super::{Prover, SP1VerificationError};
18#[cfg(feature = "network")]
19use crate::network::builder::NetworkProverBuilder;
20use crate::{
21 cpu::{execute::CpuExecuteBuilder, CpuProver},
22 cuda::CudaProver,
23 utils::check_release_build,
24 SP1ProofMode, SP1ProofWithPublicValues,
25};
26
27/// A prover that can execute programs and generate proofs with a different implementation based on
28/// the value of certain environment variables.
29///
30/// The environment variables are described in [`EnvProver::new`].
31pub struct EnvProver {
32 pub(crate) prover: Box<dyn Prover<CpuProverComponents>>,
33}
34
35impl EnvProver {
36 /// Creates a new [`EnvProver`] with the given configuration.
37 ///
38 /// The following environment variables are used to configure the prover:
39 /// - `SP1_PROVER`: The type of prover to use. Must be one of `mock`, `local`, `cuda`, or
40 /// `network`.
41 /// - `NETWORK_PRIVATE_KEY`: The private key to use for the network prover.
42 /// - `NETWORK_RPC_URL`: The RPC URL to use for the network prover.
43 #[must_use]
44 pub fn new() -> Self {
45 let mode = if let Ok(mode) = env::var("SP1_PROVER") {
46 mode
47 } else {
48 tracing::warn!("SP1_PROVER environment variable not set, defaulting to 'cpu'");
49 "cpu".to_string()
50 };
51
52 let prover: Box<dyn Prover<CpuProverComponents>> = match mode.as_str() {
53 "mock" => Box::new(CpuProver::mock()),
54 "cpu" => {
55 check_release_build();
56 Box::new(CpuProver::new())
57 },
58 "cuda" => {
59 check_release_build();
60 Box::new(CudaProver::new(SP1Prover::new(), MoongateServer::default()))
61 }
62 "network" => {
63 #[cfg(not(feature = "network"))]
64 panic!(
65 r#"The network prover requires the 'network' feature to be enabled.
66 Please enable it in your Cargo.toml with:
67 sp1-sdk = {{ version = "...", features = ["network"] }}"#
68 );
69
70 #[cfg(feature = "network")]
71 {
72 Box::new(NetworkProverBuilder::default().build())
73 }
74 }
75 _ => panic!(
76 "Invalid SP1_PROVER value. Expected one of: mock, cpu, cuda, or network. Got: '{mode}'.\n\
77 Please set the SP1_PROVER environment variable to one of the supported values."
78 ),
79 };
80 EnvProver { prover }
81 }
82
83 /// Creates a new [`CpuExecuteBuilder`] for simulating the execution of a program on the CPU.
84 ///
85 /// # Details
86 /// The builder is used for both the [`crate::cpu::CpuProver`] and [`crate::CudaProver`] client
87 /// types.
88 ///
89 /// # Example
90 /// ```rust,no_run
91 /// use sp1_sdk::{Prover, ProverClient, SP1Stdin};
92 ///
93 /// let elf = &[1, 2, 3];
94 /// let stdin = SP1Stdin::new();
95 ///
96 /// let client = ProverClient::from_env();
97 /// let (public_values, execution_report) = client.execute(elf, &stdin).run().unwrap();
98 /// ```
99 #[must_use]
100 pub fn execute<'a>(&'a self, elf: &'a [u8], stdin: &SP1Stdin) -> CpuExecuteBuilder<'a> {
101 CpuExecuteBuilder {
102 prover: self.prover.inner(),
103 elf,
104 stdin: stdin.clone(),
105 context_builder: SP1ContextBuilder::default(),
106 }
107 }
108
109 /// Creates a new [`EnvProve`] for proving a program on the CPU.
110 ///
111 /// # Details
112 /// The builder is used for only the [`crate::cpu::CpuProver`] client type.
113 ///
114 /// # Example
115 /// ```rust,no_run
116 /// use sp1_sdk::{Prover, ProverClient, SP1Stdin};
117 ///
118 /// let elf = &[1, 2, 3];
119 /// let stdin = SP1Stdin::new();
120 ///
121 /// let client = ProverClient::from_env();
122 /// let (pk, vk) = client.setup(elf);
123 /// let builder = client.prove(&pk, &stdin).core().run();
124 /// ```
125 #[must_use]
126 pub fn prove<'a>(&'a self, pk: &'a SP1ProvingKey, stdin: &'a SP1Stdin) -> EnvProveBuilder<'a> {
127 EnvProveBuilder {
128 prover: self.prover.as_ref(),
129 mode: SP1ProofMode::Core,
130 pk,
131 stdin: stdin.clone(),
132 }
133 }
134
135 /// Verifies that the given proof is valid and matches the given verification key produced by
136 /// [`Self::setup`].
137 ///
138 /// ### Examples
139 /// ```no_run
140 /// use sp1_sdk::{ProverClient, SP1Stdin};
141 ///
142 /// let elf = test_artifacts::FIBONACCI_ELF;
143 /// let stdin = SP1Stdin::new();
144 ///
145 /// let client = ProverClient::from_env();
146 /// let (pk, vk) = client.setup(elf);
147 /// let proof = client.prove(&pk, &stdin).run().unwrap();
148 /// client.verify(&proof, &vk).unwrap();
149 /// ```
150 pub fn verify(
151 &self,
152 proof: &SP1ProofWithPublicValues,
153 vk: &SP1VerifyingKey,
154 ) -> Result<(), SP1VerificationError> {
155 self.prover.verify(proof, vk)
156 }
157
158 /// Setup a program to be proven and verified by the SP1 RISC-V zkVM by computing the proving
159 /// and verifying keys.
160 #[must_use]
161 pub fn setup(&self, elf: &[u8]) -> (SP1ProvingKey, SP1VerifyingKey) {
162 self.prover.setup(elf)
163 }
164}
165
166impl Default for EnvProver {
167 fn default() -> Self {
168 Self::new()
169 }
170}
171
172impl Prover<CpuProverComponents> for EnvProver {
173 fn inner(&self) -> &SP1Prover<CpuProverComponents> {
174 self.prover.inner()
175 }
176
177 fn setup(&self, elf: &[u8]) -> (SP1ProvingKey, SP1VerifyingKey) {
178 self.prover.setup(elf)
179 }
180
181 fn prove(
182 &self,
183 pk: &SP1ProvingKey,
184 stdin: &SP1Stdin,
185 mode: SP1ProofMode,
186 ) -> Result<SP1ProofWithPublicValues> {
187 self.prover.prove(pk, stdin, mode)
188 }
189
190 fn verify(
191 &self,
192 bundle: &SP1ProofWithPublicValues,
193 vkey: &SP1VerifyingKey,
194 ) -> Result<(), SP1VerificationError> {
195 self.prover.verify(bundle, vkey)
196 }
197}