1pub 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
26pub struct CpuProver {
28 pub(crate) prover: SP1Prover<CpuProverComponents>,
29 pub(crate) mock: bool,
30}
31
32impl CpuProver {
33 #[must_use]
35 pub fn new() -> Self {
36 Self::default()
37 }
38
39 #[must_use]
41 pub fn mock() -> Self {
42 Self { prover: SP1Prover::new(), mock: true }
43 }
44
45 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 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 self.mock {
111 return self.mock_prove_impl(pk, stdin, context, mode);
112 }
113
114 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 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 let compress_proof = self.prover.shrink(reduce_proof, opts)?;
140
141 let outer_proof = self.prover.wrap_bn254(compress_proof, opts)?;
143
144 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}