1use crate::{
7 prover::{BaseProveRequest, SendFutureResult},
8 CpuProver, LightProver, MockProver, Prover, SP1ProofWithPublicValues, SP1VerificationError,
9 StatusCode,
10};
11
12#[cfg(feature = "cuda")]
13use crate::{cuda::builder::CudaProverBuilder, CudaProver};
14use sp1_core_executor::SP1CoreOpts;
15
16#[cfg(feature = "network")]
17use crate::NetworkProver;
18
19pub mod pk;
20pub mod prove;
22pub use pk::EnvProvingKey;
23use prove::EnvProveRequest;
24use sp1_core_machine::io::SP1Stdin;
25use sp1_core_machine::riscv::RiscvAir;
26use sp1_hypercube::Machine;
27use sp1_primitives::{Elf, SP1Field};
28use sp1_prover::{worker::SP1NodeCore, SP1VerifyingKey};
29
30#[derive(Clone)]
33#[allow(clippy::large_enum_variant)]
34pub enum EnvProver {
35 Mock(MockProver),
37 Light(LightProver),
39 Cpu(CpuProver),
41 #[cfg(feature = "cuda")]
43 Cuda(CudaProver),
44 #[cfg(feature = "network")]
46 Network(NetworkProver),
47}
48
49impl EnvProver {
50 pub async fn new() -> Self {
57 Self::new_with_machine(RiscvAir::machine()).await
58 }
59
60 pub async fn new_with_machine(machine: Machine<SP1Field, RiscvAir<SP1Field>>) -> Self {
62 Self::from_env_with_opts_and_machine(None, machine).await
63 }
64
65 pub async fn with_opts(self, opts: SP1CoreOpts) -> Self {
82 Self::from_env_with_opts(Some(opts)).await
83 }
84
85 pub async fn from_env_with_opts(core_opts: Option<SP1CoreOpts>) -> Self {
92 Self::from_env_with_opts_and_machine(core_opts, RiscvAir::machine()).await
93 }
94
95 pub async fn from_env_with_opts_and_machine(
97 core_opts: Option<SP1CoreOpts>,
98 machine: Machine<SP1Field, RiscvAir<SP1Field>>,
99 ) -> Self {
100 let prover = match std::env::var("SP1_PROVER") {
101 Ok(prover) => prover,
102 Err(_) => "cpu".to_string(),
103 };
104
105 match prover.as_str() {
106 "cpu" => Self::Cpu(CpuProver::new_with_opts_and_machine(core_opts, machine).await),
107 #[cfg(feature = "cuda")]
108 "cuda" => Self::Cuda(CudaProverBuilder::new_with_machine(machine).build().await),
109 #[cfg(not(feature = "cuda"))]
110 "cuda" => panic!("The CUDA prover requires the `cuda` feature to be enabled"),
111 "mock" => Self::Mock(MockProver::new_with_machine(machine).await),
112 "light" => Self::Light(LightProver::new_with_machine(machine).await),
113 #[cfg(feature = "network")]
114 "network" | "hosted" => {
115 let private_key =
116 std::env::var("NETWORK_PRIVATE_KEY").ok().filter(|k| !k.is_empty()).expect(
117 "NETWORK_PRIVATE_KEY environment variable is not set. \
118 Please set it to your private key or use the .private_key() method.",
119 );
120
121 let mut network_builder =
122 crate::network::builder::NetworkProverBuilder::new_with_machine(machine)
123 .private_key(&private_key);
124
125 if prover == "hosted" {
128 network_builder = network_builder.hosted();
129 }
130
131 Self::Network(network_builder.build().await)
132 }
133 _ => unreachable!(),
134 }
135 }
136}
137
138impl Prover for EnvProver {
139 type Error = anyhow::Error;
140 type ProvingKey = EnvProvingKey;
141 type ProveRequest<'a> = prove::EnvProveRequest<'a>;
142
143 fn inner(&self) -> &SP1NodeCore {
144 match self {
145 Self::Cpu(prover) => prover.inner(),
146 #[cfg(feature = "cuda")]
147 Self::Cuda(prover) => prover.inner(),
148 Self::Mock(prover) => prover.inner(),
149 Self::Light(prover) => prover.inner(),
150 #[cfg(feature = "network")]
151 Self::Network(prover) => prover.inner(),
152 }
153 }
154 fn setup(&self, elf: Elf) -> impl SendFutureResult<Self::ProvingKey, Self::Error> {
155 async move {
156 match self {
157 Self::Cpu(prover) => {
158 let pk = prover.setup(elf).await?;
159 Ok(EnvProvingKey::cpu(pk))
160 }
161 #[cfg(feature = "cuda")]
162 Self::Cuda(prover) => {
163 let pk = prover.setup(elf).await?;
164 Ok(EnvProvingKey::cuda(pk))
165 }
166 Self::Mock(prover) => {
167 let pk = prover.setup(elf).await?;
168 Ok(EnvProvingKey::mock(pk))
169 }
170 Self::Light(prover) => {
171 let pk = prover.setup(elf).await?;
172 Ok(EnvProvingKey::light(pk))
173 }
174 #[cfg(feature = "network")]
175 Self::Network(prover) => {
176 let pk = prover.setup(elf).await?;
177 Ok(EnvProvingKey::network(pk))
178 }
179 }
180 }
181 }
182
183 fn prove<'a>(&'a self, pk: &'a Self::ProvingKey, stdin: SP1Stdin) -> Self::ProveRequest<'a> {
184 EnvProveRequest { base: BaseProveRequest::new(self, pk, stdin) }
185 }
186
187 fn verify(
188 &self,
189 proof: &SP1ProofWithPublicValues,
190 vkey: &SP1VerifyingKey,
191 status_code: Option<StatusCode>,
192 ) -> Result<(), SP1VerificationError> {
193 match self {
194 Self::Cpu(prover) => prover.verify(proof, vkey, status_code),
195 #[cfg(feature = "cuda")]
196 Self::Cuda(prover) => prover.verify(proof, vkey, status_code),
197 Self::Mock(prover) => prover.verify(proof, vkey, status_code),
198 Self::Light(prover) => prover.verify(proof, vkey, status_code),
199 #[cfg(feature = "network")]
200 Self::Network(prover) => prover.verify(proof, vkey, status_code),
201 }
202 }
203}
204
205#[cfg(test)]
206mod tests {
207 use crate::{prover::ProveRequest, utils::setup_logger, MockProver, Prover, SP1Stdin};
208
209 use super::EnvProver;
210
211 #[tokio::test]
216 async fn test_envprover_mock_verifies_plonk_and_groth16() {
217 setup_logger();
218 let mock = MockProver::new().await;
219 let pk =
220 mock.setup(test_artifacts::FIBONACCI_ELF).await.expect("failed to setup proving key");
221
222 let mut stdin = SP1Stdin::new();
223 stdin.write(&10usize);
224 let plonk_proof =
225 mock.prove(&pk, stdin).plonk().await.expect("failed to create mock Plonk proof");
226
227 let mut stdin = SP1Stdin::new();
228 stdin.write(&10usize);
229 let groth16_proof =
230 mock.prove(&pk, stdin).groth16().await.expect("failed to create mock Groth16 proof");
231
232 let env = EnvProver::Mock(mock);
233 env.verify(&plonk_proof, &pk.vk, None)
234 .expect("EnvProver::Mock must verify a mock Plonk proof");
235 env.verify(&groth16_proof, &pk.vk, None)
236 .expect("EnvProver::Mock must verify a mock Groth16 proof");
237 }
238}