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
6pub mod 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, setup_memory_usage_monitoring},
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 setup_memory_usage_monitoring();
57 Box::new(CpuProver::new())
58 },
59 "cuda" => {
60 check_release_build();
61 setup_memory_usage_monitoring();
62 Box::new(CudaProver::new(SP1Prover::new(), MoongateServer::default()))
63 }
64 "network" => {
65 #[cfg(not(feature = "network"))]
66 panic!(
67 r#"The network prover requires the 'network' feature to be enabled.
68 Please enable it in your Cargo.toml with:
69 sp1-sdk = {{ version = "...", features = ["network"] }}"#
70 );
71
72 #[cfg(feature = "network")]
73 {
74 Box::new(NetworkProverBuilder::default().build())
75 }
76 }
77 _ => panic!(
78 "Invalid SP1_PROVER value. Expected one of: mock, cpu, cuda, or network. Got: '{mode}'.\n\
79 Please set the SP1_PROVER environment variable to one of the supported values."
80 ),
81 };
82 EnvProver { prover }
83 }
84
85 /// Creates a new [`CpuExecuteBuilder`] for simulating the execution of a program on the CPU.
86 ///
87 /// # Details
88 /// The builder is used for both the [`crate::cpu::CpuProver`] and [`crate::CudaProver`] client
89 /// types.
90 ///
91 /// # Example
92 /// ```rust,no_run
93 /// use sp1_sdk::{Prover, ProverClient, SP1Stdin};
94 ///
95 /// let elf = &[1, 2, 3];
96 /// let stdin = SP1Stdin::new();
97 ///
98 /// let client = ProverClient::from_env();
99 /// let (public_values, execution_report) = client.execute(elf, &stdin).run().unwrap();
100 /// ```
101 #[must_use]
102 pub fn execute<'a>(&'a self, elf: &'a [u8], stdin: &SP1Stdin) -> CpuExecuteBuilder<'a> {
103 CpuExecuteBuilder {
104 prover: self.prover.inner(),
105 elf,
106 stdin: stdin.clone(),
107 context_builder: SP1ContextBuilder::default(),
108 }
109 }
110
111 /// Creates a new [`EnvProveBuilder`] for proving a program on the CPU.
112 ///
113 /// # Details
114 /// The builder is used for only the [`crate::cpu::CpuProver`] client type.
115 ///
116 /// # Example
117 /// ```rust,no_run
118 /// use sp1_sdk::{Prover, ProverClient, SP1Stdin};
119 ///
120 /// let elf = &[1, 2, 3];
121 /// let stdin = SP1Stdin::new();
122 ///
123 /// let client = ProverClient::from_env();
124 /// let (pk, vk) = client.setup(elf);
125 /// let builder = client.prove(&pk, &stdin).core().run();
126 /// ```
127 #[must_use]
128 pub fn prove<'a>(&'a self, pk: &'a SP1ProvingKey, stdin: &'a SP1Stdin) -> EnvProveBuilder<'a> {
129 EnvProveBuilder {
130 prover: self.prover.as_ref(),
131 mode: SP1ProofMode::Core,
132 pk,
133 stdin: stdin.clone(),
134 }
135 }
136
137 /// Verifies that the given proof is valid and matches the given verification key produced by
138 /// [`Self::setup`].
139 ///
140 /// ### Examples
141 /// ```no_run
142 /// use sp1_sdk::{ProverClient, SP1Stdin};
143 ///
144 /// let elf = test_artifacts::FIBONACCI_ELF;
145 /// let stdin = SP1Stdin::new();
146 ///
147 /// let client = ProverClient::from_env();
148 /// let (pk, vk) = client.setup(elf);
149 /// let proof = client.prove(&pk, &stdin).run().unwrap();
150 /// client.verify(&proof, &vk).unwrap();
151 /// ```
152 pub fn verify(
153 &self,
154 proof: &SP1ProofWithPublicValues,
155 vk: &SP1VerifyingKey,
156 ) -> Result<(), SP1VerificationError> {
157 self.prover.verify(proof, vk)
158 }
159
160 /// Setup a program to be proven and verified by the SP1 RISC-V zkVM by computing the proving
161 /// and verifying keys.
162 #[must_use]
163 pub fn setup(&self, elf: &[u8]) -> (SP1ProvingKey, SP1VerifyingKey) {
164 self.prover.setup(elf)
165 }
166}
167
168impl Default for EnvProver {
169 fn default() -> Self {
170 Self::new()
171 }
172}
173
174impl Prover<CpuProverComponents> for EnvProver {
175 fn inner(&self) -> &SP1Prover<CpuProverComponents> {
176 self.prover.inner()
177 }
178
179 fn setup(&self, elf: &[u8]) -> (SP1ProvingKey, SP1VerifyingKey) {
180 self.prover.setup(elf)
181 }
182
183 fn prove(
184 &self,
185 pk: &SP1ProvingKey,
186 stdin: &SP1Stdin,
187 mode: SP1ProofMode,
188 ) -> Result<SP1ProofWithPublicValues> {
189 self.prover.prove(pk, stdin, mode)
190 }
191
192 fn verify(
193 &self,
194 bundle: &SP1ProofWithPublicValues,
195 vkey: &SP1VerifyingKey,
196 ) -> Result<(), SP1VerificationError> {
197 self.prover.verify(bundle, vkey)
198 }
199}