Skip to main content

sp1_sdk/blocking/
mod.rs

1//! Blocking version of the sp1-sdk `ProverClient`.
2
3mod client;
4mod cpu;
5#[cfg(feature = "cuda")]
6mod cuda;
7mod env;
8mod light;
9mod mock;
10#[cfg(feature = "network")]
11mod network;
12mod prover;
13
14pub use client::ProverClient;
15pub use cpu::{builder::CpuProverBuilder, CpuProver};
16#[cfg(feature = "cuda")]
17pub use cuda::{builder::CudaProverBuilder, CudaProver};
18pub use env::{EnvProver, EnvProvingKey};
19pub use light::LightProver;
20pub use mock::MockProver;
21#[cfg(feature = "network")]
22pub use network::{builder::NetworkProverBuilder, NetworkProver};
23pub use prover::{ProveRequest, Prover};
24
25pub use crate::{utils, Elf, SP1ProofMode, SP1PublicValues, SP1Stdin};
26
27/// A prelude for the blocking API, including all the types and traits that are commonly used.
28pub mod prelude {
29    pub use super::{ProveRequest, Prover, SP1ProofMode, SP1Stdin};
30    pub use crate::{include_elf, Elf, HashableKey, ProvingKey, SP1ProofWithPublicValues};
31}
32
33use std::{future::Future, sync::LazyLock};
34
35/// Block on a future, and return the result.
36///
37/// Will panic if run within a tokio runtime. It is advised that you switch to the async api
38/// if you are already using the tokio runtime directly.
39pub(crate) fn block_on<T>(future: impl Future<Output = T>) -> T {
40    RUNTIME.block_on(future)
41}
42
43/// Runtime handle, used for running async code in a blocking context.
44static RUNTIME: LazyLock<tokio::runtime::Runtime> =
45    LazyLock::new(|| tokio::runtime::Runtime::new().unwrap());
46
47#[cfg(all(test, feature = "slow-tests"))]
48mod tests {
49    use super::*;
50
51    #[rstest::rstest]
52    fn test_execute(client: &CpuProver) {
53        utils::setup_logger();
54        let elf = test_artifacts::FIBONACCI_ELF;
55        let mut stdin = SP1Stdin::new();
56        stdin.write(&10usize);
57        let (_, _) = client.execute(elf, stdin).run().unwrap();
58    }
59
60    #[rstest::rstest]
61    fn test_execute_panic(client: &CpuProver) {
62        utils::setup_logger();
63        let elf = test_artifacts::PANIC_ELF;
64        let mut stdin = SP1Stdin::new();
65        stdin.write(&10usize);
66        client.execute(elf, stdin).run().unwrap();
67        // TODO: once the exit code is exposed to the SDK, check its value, both here and elsewhere.
68    }
69
70    #[rstest::rstest]
71    #[should_panic]
72    fn test_cycle_limit_fail(client: &CpuProver) {
73        utils::setup_logger();
74        let elf = test_artifacts::PANIC_ELF;
75        let mut stdin = SP1Stdin::new();
76        stdin.write(&10usize);
77        client.execute(elf, stdin).cycle_limit(1).run().unwrap();
78    }
79
80    #[rstest::rstest]
81    fn test_e2e_core(client: &CpuProver) {
82        utils::setup_logger();
83        let elf = test_artifacts::FIBONACCI_ELF;
84        let pk = client.setup(elf).unwrap();
85        let mut stdin = SP1Stdin::new();
86        stdin.write(&10usize);
87
88        // Generate proof & verify.
89        let mut proof = client.prove(&pk, stdin).run().unwrap();
90        client.verify(&proof, &pk.vk, None).unwrap();
91
92        // Test invalid public values.
93        proof.public_values = SP1PublicValues::from(&[255, 4, 84]);
94        if client.verify(&proof, &pk.vk, None).is_ok() {
95            panic!("verified proof with invalid public values")
96        }
97    }
98
99    #[rstest::fixture]
100    #[once]
101    fn client() -> CpuProver {
102        ProverClient::builder().cpu().build()
103    }
104}