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}