sp1_sdk/cpu/
mod.rs

1//! # SP1 CPU Prover
2//!
3//! A prover that uses the CPU to execute and prove programs.
4
5pub mod builder;
6pub mod execute;
7pub mod prove;
8
9use anyhow::Result;
10use execute::CpuExecuteBuilder;
11use prove::CpuProveBuilder;
12use sp1_core_executor::{SP1Context, SP1ContextBuilder};
13use sp1_core_machine::io::SP1Stdin;
14use sp1_prover::{
15    components::CpuProverComponents,
16    verify::{verify_groth16_bn254_public_inputs, verify_plonk_bn254_public_inputs},
17    Groth16Bn254Proof, PlonkBn254Proof, SP1CoreProofData, SP1ProofWithMetadata, SP1Prover,
18};
19use sp1_stark::{SP1CoreOpts, SP1ProverOpts};
20
21use crate::{
22    install::try_install_circuit_artifacts, prover::verify_proof, Prover, SP1Proof, SP1ProofMode,
23    SP1ProofWithPublicValues, SP1ProvingKey, SP1VerificationError, SP1VerifyingKey,
24};
25
26/// A prover that uses the CPU to execute and prove programs.
27pub struct CpuProver {
28    pub(crate) prover: SP1Prover<CpuProverComponents>,
29    pub(crate) mock: bool,
30}
31
32impl CpuProver {
33    /// Creates a new [`CpuProver`].
34    #[must_use]
35    pub fn new() -> Self {
36        Self::default()
37    }
38
39    /// Creates a new [`CpuProver`] in mock mode.
40    #[must_use]
41    pub fn mock() -> Self {
42        Self { prover: SP1Prover::new(), mock: true }
43    }
44
45    /// Creates a new [`CpuExecuteBuilder`] for simulating the execution of a program on the CPU.
46    ///
47    /// # Details
48    /// The builder is used for both the [`crate::cpu::CpuProver`] and [`crate::CudaProver`] client
49    /// types.
50    ///
51    /// # Example
52    /// ```rust,no_run
53    /// use sp1_sdk::{include_elf, Prover, ProverClient, SP1Stdin};
54    ///
55    /// let elf = &[1, 2, 3];
56    /// let stdin = SP1Stdin::new();
57    ///
58    /// let client = ProverClient::builder().cpu().build();
59    /// let (public_values, execution_report) = client.execute(elf, &stdin).run().unwrap();
60    /// ```
61    pub fn execute<'a>(&'a self, elf: &'a [u8], stdin: &SP1Stdin) -> CpuExecuteBuilder<'a> {
62        CpuExecuteBuilder {
63            prover: &self.prover,
64            elf,
65            stdin: stdin.clone(),
66            context_builder: SP1ContextBuilder::default(),
67        }
68    }
69
70    /// Creates a new [`CpuProveBuilder`] for proving a program on the CPU.
71    ///
72    /// # Details
73    /// The builder is used for only the [`crate::cpu::CpuProver`] client type.
74    ///
75    /// # Example
76    /// ```rust,no_run
77    /// use sp1_sdk::{include_elf, Prover, ProverClient, SP1Stdin};
78    ///
79    /// let elf = &[1, 2, 3];
80    /// let stdin = SP1Stdin::new();
81    ///
82    /// let client = ProverClient::builder().cpu().build();
83    /// let (pk, vk) = client.setup(elf);
84    /// let builder = client.prove(&pk, &stdin).core().run();
85    /// ```
86    pub fn prove<'a>(&'a self, pk: &'a SP1ProvingKey, stdin: &SP1Stdin) -> CpuProveBuilder<'a> {
87        CpuProveBuilder {
88            prover: self,
89            mode: SP1ProofMode::Core,
90            pk,
91            stdin: stdin.clone(),
92            context_builder: SP1ContextBuilder::default(),
93            core_opts: SP1CoreOpts::default(),
94            recursion_opts: SP1CoreOpts::recursion(),
95            mock: self.mock,
96        }
97    }
98
99    pub(crate) fn prove_impl<'a>(
100        &'a self,
101        pk: &SP1ProvingKey,
102        stdin: &SP1Stdin,
103        opts: SP1ProverOpts,
104        context: SP1Context<'a>,
105        mode: SP1ProofMode,
106    ) -> Result<SP1ProofWithPublicValues> {
107        let program = self.prover.get_program(&pk.elf).unwrap();
108
109        // If we're in mock mode, return a mock proof.
110        if self.mock {
111            return self.mock_prove_impl(pk, stdin, context, mode);
112        }
113
114        // Generate the core proof.
115        let proof: SP1ProofWithMetadata<SP1CoreProofData> =
116            self.prover.prove_core(&pk.pk, program, stdin, opts, context)?;
117        if mode == SP1ProofMode::Core {
118            return Ok(SP1ProofWithPublicValues::new(
119                SP1Proof::Core(proof.proof.0),
120                proof.public_values,
121                self.version().to_string(),
122            ));
123        }
124
125        // Generate the compressed proof.
126        let deferred_proofs =
127            stdin.proofs.iter().map(|(reduce_proof, _)| reduce_proof.clone()).collect();
128        let public_values = proof.public_values.clone();
129        let reduce_proof = self.prover.compress(&pk.vk, proof, deferred_proofs, opts)?;
130        if mode == SP1ProofMode::Compressed {
131            return Ok(SP1ProofWithPublicValues::new(
132                SP1Proof::Compressed(Box::new(reduce_proof)),
133                public_values,
134                self.version().to_string(),
135            ));
136        }
137
138        // Generate the shrink proof.
139        let compress_proof = self.prover.shrink(reduce_proof, opts)?;
140
141        // Generate the wrap proof.
142        let outer_proof = self.prover.wrap_bn254(compress_proof, opts)?;
143
144        // Generate the gnark proof.
145        match mode {
146            SP1ProofMode::Groth16 => {
147                let groth16_bn254_artifacts = if sp1_prover::build::sp1_dev_mode() {
148                    sp1_prover::build::try_build_groth16_bn254_artifacts_dev(
149                        &outer_proof.vk,
150                        &outer_proof.proof,
151                    )
152                } else {
153                    try_install_circuit_artifacts("groth16")
154                };
155
156                let proof = self.prover.wrap_groth16_bn254(outer_proof, &groth16_bn254_artifacts);
157                Ok(SP1ProofWithPublicValues::new(
158                    SP1Proof::Groth16(proof),
159                    public_values,
160                    self.version().to_string(),
161                ))
162            }
163            SP1ProofMode::Plonk => {
164                let plonk_bn254_artifacts = if sp1_prover::build::sp1_dev_mode() {
165                    sp1_prover::build::try_build_plonk_bn254_artifacts_dev(
166                        &outer_proof.vk,
167                        &outer_proof.proof,
168                    )
169                } else {
170                    try_install_circuit_artifacts("plonk")
171                };
172                let proof = self.prover.wrap_plonk_bn254(outer_proof, &plonk_bn254_artifacts);
173                Ok(SP1ProofWithPublicValues::new(
174                    SP1Proof::Plonk(proof),
175                    public_values,
176                    self.version().to_string(),
177                ))
178            }
179            _ => unreachable!(),
180        }
181    }
182
183    pub(crate) fn mock_prove_impl<'a>(
184        &'a self,
185        pk: &SP1ProvingKey,
186        stdin: &SP1Stdin,
187        context: SP1Context<'a>,
188        mode: SP1ProofMode,
189    ) -> Result<SP1ProofWithPublicValues> {
190        let (public_values, _, _) = self.prover.execute(&pk.elf, stdin, context)?;
191        Ok(SP1ProofWithPublicValues::create_mock_proof(pk, public_values, mode, self.version()))
192    }
193
194    fn mock_verify(
195        bundle: &SP1ProofWithPublicValues,
196        vkey: &SP1VerifyingKey,
197    ) -> Result<(), SP1VerificationError> {
198        match &bundle.proof {
199            SP1Proof::Plonk(PlonkBn254Proof { public_inputs, .. }) => {
200                verify_plonk_bn254_public_inputs(vkey, &bundle.public_values, public_inputs)
201                    .map_err(SP1VerificationError::Plonk)
202            }
203            SP1Proof::Groth16(Groth16Bn254Proof { public_inputs, .. }) => {
204                verify_groth16_bn254_public_inputs(vkey, &bundle.public_values, public_inputs)
205                    .map_err(SP1VerificationError::Groth16)
206            }
207            _ => Ok(()),
208        }
209    }
210}
211
212impl Prover<CpuProverComponents> for CpuProver {
213    fn setup(&self, elf: &[u8]) -> (SP1ProvingKey, SP1VerifyingKey) {
214        let (pk, _, _, vk) = self.prover.setup(elf);
215        (pk, vk)
216    }
217
218    fn inner(&self) -> &SP1Prover<CpuProverComponents> {
219        &self.prover
220    }
221
222    fn prove(
223        &self,
224        pk: &SP1ProvingKey,
225        stdin: &SP1Stdin,
226        mode: SP1ProofMode,
227    ) -> Result<SP1ProofWithPublicValues> {
228        self.prove_impl(pk, stdin, SP1ProverOpts::default(), SP1Context::default(), mode)
229    }
230
231    fn verify(
232        &self,
233        bundle: &SP1ProofWithPublicValues,
234        vkey: &SP1VerifyingKey,
235    ) -> Result<(), SP1VerificationError> {
236        if self.mock {
237            tracing::warn!("using mock verifier");
238            return Self::mock_verify(bundle, vkey);
239        }
240        verify_proof(self.inner(), self.version(), bundle, vkey)
241    }
242}
243
244impl Default for CpuProver {
245    fn default() -> Self {
246        let prover = SP1Prover::new();
247        Self { prover, mock: false }
248    }
249}