Skip to main content

sp1_sdk/cpu/
prove.rs

1//! # CPU Proving
2//!
3//! This module provides a builder for proving a program on the CPU.
4
5use std::{
6    future::{Future, IntoFuture},
7    pin::Pin,
8};
9
10use anyhow::Result;
11// use sp1_core_executor::IoWriter;
12use sp1_core_machine::io::SP1Stdin;
13
14use super::{CPUProverError, CpuProver};
15use crate::{
16    prover::{BaseProveRequest, ProveRequest},
17    utils::proof_mode,
18    SP1ProofWithPublicValues, SP1ProvingKey,
19};
20
21/// A builder for proving a program on the CPU.
22///
23/// This builder provides a typed interface for configuring the SP1 RISC-V prover. The builder is
24/// used for only the [`crate::cpu::CpuProver`] client type.
25pub struct CpuProveBuilder<'a> {
26    pub(crate) base: BaseProveRequest<'a, CpuProver>,
27}
28
29impl<'a> CpuProveBuilder<'a> {
30    pub(super) const fn new(prover: &'a CpuProver, pk: &'a SP1ProvingKey, stdin: SP1Stdin) -> Self {
31        Self { base: BaseProveRequest::new(prover, pk, stdin) }
32    }
33
34    // todo!(n): add stdout/stderr pipes here.
35    // /// Override the default stdout of the guest program.
36    // ///
37    // /// # Example
38    // /// ```rust,no_run
39    // /// use sp1_sdk::{include_elf, Prover, ProverClient, SP1Stdin};
40    // ///
41    // /// let mut stdout = Vec::new();
42    // ///
43    // /// let elf = &[1, 2, 3];
44    // /// let stdin = SP1Stdin::new();
45    // ///
46    // /// let client = ProverClient::builder().cpu().build();
47    // /// client.execute(elf, &stdin).stdout(&mut stdout).run();
48    // /// ```
49    // #[must_use]
50    // pub fn stdout<W: IoWriter>(mut self, writer: &'static mut W) -> Self {
51    //     self.context_builder.stdout(writer);
52    //     self
53    // }
54
55    // /// Override the default stdout of the guest program.
56    // ///
57    // /// # Example
58    // /// ```rust,no_run
59    // /// use sp1_sdk::{include_elf, Prover, ProverClient, SP1Stdin};
60    // ///
61    // /// let mut stderr = Vec::new();
62    // ///
63    // /// let elf = &[1, 2, 3];
64    // /// let stdin = SP1Stdin::new();
65    // ///
66    // /// let client = ProverClient::builder().cpu().build();
67    // /// client.execute(elf, &stdin).stderr(&mut stderr).run();
68    // /// ```````
69    // #[must_use]
70    // pub fn stderr<W: IoWriter>(mut self, writer: &'static mut W) -> Self {
71    //     self.context_builder.stderr(writer);
72    //     self
73    // }
74
75    /// Run the prover with the built arguments.
76    ///
77    /// # Details
78    /// This method will run the prover with the built arguments. If the prover fails to run, the
79    /// method will return an error.
80    ///
81    /// # Example
82    /// ```rust,no_run
83    /// use sp1_sdk::{Elf, Prover, ProverClient, SP1Stdin};
84    ///
85    /// tokio_test::block_on(async {
86    ///     let elf = Elf::Static(&[1, 2, 3]);
87    ///     let stdin = SP1Stdin::new();
88    ///
89    ///     let client = ProverClient::builder().cpu().build().await;
90    ///     let pk = client.setup(elf).await.unwrap();
91    ///     let proof = client.prove(&pk, stdin).await.unwrap();
92    /// });
93    /// ```
94    async fn run(self) -> Result<SP1ProofWithPublicValues, CPUProverError> {
95        // Get the arguments.
96        let BaseProveRequest { prover, pk, stdin, mode, mut context_builder } = self.base;
97
98        // Dump the program and stdin to files for debugging if `SP1_DUMP` is set.
99        crate::utils::sp1_dump(&pk.elf, &stdin);
100
101        tracing::info!(mode = ?mode, "starting proof generation");
102        let context = context_builder.build();
103        Ok(prover.prover.prove_with_mode(&pk.elf, stdin, context, proof_mode(mode)).await?.into())
104    }
105}
106
107impl<'a> ProveRequest<'a, CpuProver> for CpuProveBuilder<'a> {
108    fn base(&mut self) -> &mut BaseProveRequest<'a, CpuProver> {
109        &mut self.base
110    }
111}
112
113impl<'a> IntoFuture for CpuProveBuilder<'a> {
114    type Output = Result<SP1ProofWithPublicValues, CPUProverError>;
115    type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>;
116
117    fn into_future(self) -> Self::IntoFuture {
118        Box::pin(self.run())
119    }
120}