Skip to main content

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 the `SP1_PROVER` environment variable.
5
6use crate::{
7    cuda::builder::CudaProverBuilder,
8    prover::{BaseProveRequest, SendFutureResult},
9    CpuProver, CudaProver, LightProver, MockProver, Prover,
10};
11use sp1_core_executor::SP1CoreOpts;
12
13#[cfg(feature = "network")]
14use crate::NetworkProver;
15
16pub mod pk;
17/// The module that defines the prove request for the [`EnvProver`].
18pub mod prove;
19pub use pk::EnvProvingKey;
20use prove::EnvProveRequest;
21use sp1_core_machine::io::SP1Stdin;
22use sp1_primitives::Elf;
23use sp1_prover::worker::SP1NodeCore;
24
25/// A prover that can execute programs and generate proofs with a different implementation based on
26/// the value of the `SP1_PROVER` environment variable.
27#[derive(Clone)]
28#[allow(clippy::large_enum_variant)]
29pub enum EnvProver {
30    /// A mock prover that does not prove anything.
31    Mock(MockProver),
32    /// A light prover that only executes and verifies but does not generate proofs.
33    Light(LightProver),
34    /// A CPU prover.
35    Cpu(CpuProver),
36    /// A CUDA prover.
37    Cuda(CudaProver),
38    /// A network prover.
39    #[cfg(feature = "network")]
40    Network(NetworkProver),
41}
42
43impl EnvProver {
44    /// Creates a new [`EnvProver`] from the environment.
45    ///
46    /// This method will read from the `SP1_PROVER` environment variable to determine which prover
47    /// to use. If the variable is not set, it will default to the CPU prover.
48    ///
49    /// If the prover is a network prover, the `NETWORK_PRIVATE_KEY` variable must be set.
50    pub async fn new() -> Self {
51        Self::from_env_with_opts(None).await
52    }
53
54    /// Updates the core options for this prover.
55    ///
56    /// This method allows you to configure the prover after creation.
57    /// It recreates the prover with the new options based on the current environment settings.
58    ///
59    /// # Example
60    /// ```rust,no_run
61    /// use sp1_core_executor::SP1CoreOpts;
62    /// use sp1_sdk::ProverClient;
63    ///
64    /// tokio_test::block_on(async {
65    ///     let mut client = ProverClient::from_env().await;
66    ///     let opts = SP1CoreOpts { shard_size: 500_000, ..Default::default() };
67    ///     client = client.with_opts(opts).await;
68    /// });
69    /// ```
70    pub async fn with_opts(self, opts: SP1CoreOpts) -> Self {
71        Self::from_env_with_opts(Some(opts)).await
72    }
73
74    /// Creates an [`EnvProver`] from the environment with optional custom [`SP1CoreOpts`].
75    ///
76    /// This method will read from the `SP1_PROVER` environment variable to determine which prover
77    /// to use. If the variable is not set, it will default to the CPU prover.
78    ///
79    /// If the prover is a network prover, the `NETWORK_PRIVATE_KEY` variable must be set.
80    pub async fn from_env_with_opts(core_opts: Option<SP1CoreOpts>) -> Self {
81        let prover = match std::env::var("SP1_PROVER") {
82            Ok(prover) => prover,
83            Err(_) => "cpu".to_string(),
84        };
85
86        match prover.as_str() {
87            "cpu" => Self::Cpu(CpuProver::new_with_opts(core_opts).await),
88            "cuda" => Self::Cuda(CudaProverBuilder::default().build().await),
89            "mock" => Self::Mock(MockProver::new().await),
90            "light" => Self::Light(LightProver::new().await),
91            #[cfg(feature = "network")]
92            "network" => {
93                let private_key =
94                    std::env::var("NETWORK_PRIVATE_KEY").ok().filter(|k| !k.is_empty()).expect(
95                        "NETWORK_PRIVATE_KEY environment variable is not set. \
96                Please set it to your private key or use the .private_key() method.",
97                    );
98
99                let network_builder =
100                    crate::network::builder::NetworkProverBuilder::new().private_key(&private_key);
101
102                Self::Network(network_builder.build().await)
103            }
104            _ => unreachable!(),
105        }
106    }
107}
108
109impl Prover for EnvProver {
110    type Error = anyhow::Error;
111    type ProvingKey = EnvProvingKey;
112    type ProveRequest<'a> = prove::EnvProveRequest<'a>;
113
114    fn inner(&self) -> &SP1NodeCore {
115        match self {
116            Self::Cpu(prover) => prover.inner(),
117            Self::Cuda(prover) => prover.inner(),
118            Self::Mock(prover) => prover.inner(),
119            Self::Light(prover) => prover.inner(),
120            #[cfg(feature = "network")]
121            Self::Network(prover) => prover.inner(),
122        }
123    }
124    fn setup(&self, elf: Elf) -> impl SendFutureResult<Self::ProvingKey, Self::Error> {
125        async move {
126            match self {
127                Self::Cpu(prover) => {
128                    let pk = prover.setup(elf).await?;
129                    Ok(EnvProvingKey::cpu(pk))
130                }
131                Self::Cuda(prover) => {
132                    let pk = prover.setup(elf).await?;
133                    Ok(EnvProvingKey::cuda(pk))
134                }
135                Self::Mock(prover) => {
136                    let pk = prover.setup(elf).await?;
137                    Ok(EnvProvingKey::mock(pk))
138                }
139                Self::Light(prover) => {
140                    let pk = prover.setup(elf).await?;
141                    Ok(EnvProvingKey::light(pk))
142                }
143                #[cfg(feature = "network")]
144                Self::Network(prover) => {
145                    let pk = prover.setup(elf).await?;
146                    Ok(EnvProvingKey::network(pk))
147                }
148            }
149        }
150    }
151
152    fn prove<'a>(&'a self, pk: &'a Self::ProvingKey, stdin: SP1Stdin) -> Self::ProveRequest<'a> {
153        EnvProveRequest { base: BaseProveRequest::new(self, pk, stdin) }
154    }
155}