1pub mod builder;
6
7use std::pin::Pin;
8
9use sp1_core_machine::io::SP1Stdin;
10use sp1_core_machine::riscv::RiscvAir;
11use sp1_hypercube::Machine;
12use sp1_primitives::SP1Field;
13use sp1_prover::{
14 worker::{SP1LightNode, SP1NodeCore},
15 Groth16Bn254Proof, PlonkBn254Proof, SP1VerifyingKey,
16};
17
18use crate::{
19 proof::verify_mock_public_inputs,
20 prover::{BaseProveRequest, ProveRequest},
21 Prover, SP1Proof, SP1ProofWithPublicValues, SP1ProvingKey, SP1VerificationError, StatusCode,
22};
23use sp1_core_executor::SP1CoreOpts;
24use std::future::{Future, IntoFuture};
25
26#[derive(Clone)]
28pub struct MockProver {
29 inner: SP1LightNode,
30}
31
32impl MockProver {
33 #[must_use]
35 pub async fn new() -> Self {
36 Self::new_with_machine(RiscvAir::machine()).await
37 }
38
39 #[must_use]
41 pub async fn new_with_machine(machine: Machine<SP1Field, RiscvAir<SP1Field>>) -> Self {
42 tracing::info!("initializing mock prover");
43 Self { inner: SP1LightNode::new_with_machine(machine).await }
44 }
45
46 #[must_use]
48 pub async fn new_with_opts(opts: SP1CoreOpts) -> Self {
49 Self::new_with_opts_and_machine(RiscvAir::machine(), opts).await
50 }
51
52 #[must_use]
54 pub async fn new_with_opts_and_machine(
55 machine: Machine<SP1Field, RiscvAir<SP1Field>>,
56 opts: SP1CoreOpts,
57 ) -> Self {
58 Self { inner: SP1LightNode::with_opts_and_machine(machine, opts).await }
59 }
60}
61
62impl Prover for MockProver {
63 type ProvingKey = SP1ProvingKey;
64
65 type Error = anyhow::Error;
66
67 type ProveRequest<'a> = MockProveRequest<'a>;
68
69 fn inner(&self) -> &SP1NodeCore {
70 self.inner.inner()
71 }
72
73 fn prove<'a>(&'a self, pk: &'a Self::ProvingKey, stdin: SP1Stdin) -> Self::ProveRequest<'a> {
74 MockProveRequest { base: BaseProveRequest::new(self, pk, stdin) }
75 }
76
77 fn setup(
78 &self,
79 elf: sp1_build::Elf,
80 ) -> impl crate::prover::SendFutureResult<Self::ProvingKey, Self::Error> {
81 async move {
82 let vk = self.inner.setup(&elf).await?;
83 let pk = SP1ProvingKey { vk, elf };
84 Ok(pk)
85 }
86 }
87
88 fn verify(
89 &self,
90 proof: &SP1ProofWithPublicValues,
91 vkey: &SP1VerifyingKey,
92 _status_code: Option<StatusCode>,
93 ) -> Result<(), SP1VerificationError> {
94 match &proof.proof {
95 SP1Proof::Plonk(PlonkBn254Proof { public_inputs, .. }) => {
96 verify_mock_public_inputs(vkey, &proof.public_values, public_inputs)
99 .map_err(SP1VerificationError::Plonk)
100 }
101 SP1Proof::Groth16(Groth16Bn254Proof { public_inputs, .. }) => {
102 verify_mock_public_inputs(vkey, &proof.public_values, public_inputs)
105 .map_err(SP1VerificationError::Groth16)
106 }
107 _ => Ok(()),
108 }
109 }
110}
111
112pub struct MockProveRequest<'a> {
114 pub(crate) base: BaseProveRequest<'a, MockProver>,
115}
116
117impl<'a> ProveRequest<'a, MockProver> for MockProveRequest<'a> {
118 fn base(&mut self) -> &mut BaseProveRequest<'a, MockProver> {
119 &mut self.base
120 }
121}
122
123impl<'a> IntoFuture for MockProveRequest<'a> {
124 type Output = Result<SP1ProofWithPublicValues, anyhow::Error>;
125 type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>;
126
127 fn into_future(self) -> Self::IntoFuture {
128 Box::pin(async move {
129 let BaseProveRequest { prover, pk, mode, stdin, context_builder } = self.base;
130 tracing::info!(mode = ?mode, "generating mock proof");
131
132 let mut req = prover.execute(pk.elf.clone(), stdin);
134 req.context_builder = context_builder;
135
136 let (public_values, _) = req.await?;
138
139 Ok(SP1ProofWithPublicValues::create_mock_proof(
140 &pk.vk,
141 public_values,
142 mode,
143 prover.version(),
144 ))
145 })
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use crate::{prover::ProveRequest, utils::setup_logger, MockProver, Prover, SP1Stdin};
152
153 #[tokio::test]
155 async fn test_mock_proof_all_types() {
156 setup_logger();
157 let prover = MockProver::new().await;
158 let pk =
159 prover.setup(test_artifacts::FIBONACCI_ELF).await.expect("failed to setup proving key");
160
161 let mut stdin = SP1Stdin::new();
163 stdin.write(&10usize);
164 let core_proof =
165 prover.prove(&pk, stdin).core().await.expect("failed to create mock Core proof");
166 prover.verify(&core_proof, &pk.vk, None).expect("failed to verify mock Core proof");
167
168 let mut stdin = SP1Stdin::new();
170 stdin.write(&10usize);
171 let compressed_proof = prover
172 .prove(&pk, stdin)
173 .compressed()
174 .await
175 .expect("failed to create mock Compressed proof");
176 prover
177 .verify(&compressed_proof, &pk.vk, None)
178 .expect("failed to verify mock Compressed proof");
179
180 let mut stdin = SP1Stdin::new();
182 stdin.write(&10usize);
183 let plonk_proof =
184 prover.prove(&pk, stdin).plonk().await.expect("failed to create mock Plonk proof");
185 prover.verify(&plonk_proof, &pk.vk, None).expect("failed to verify mock Plonk proof");
186
187 let mut stdin = SP1Stdin::new();
189 stdin.write(&10usize);
190 let groth16_proof =
191 prover.prove(&pk, stdin).groth16().await.expect("failed to create mock Groth16 proof");
192 prover.verify(&groth16_proof, &pk.vk, None).expect("failed to verify mock Groth16 proof");
193 }
194
195 #[tokio::test]
197 async fn test_mock_proof_public_values() {
198 setup_logger();
199 let prover = MockProver::new().await;
200 let pk =
201 prover.setup(test_artifacts::FIBONACCI_ELF).await.expect("failed to setup proving key");
202 let mut stdin = SP1Stdin::new();
203 stdin.write(&10usize);
204
205 let (expected_pv, _) =
207 prover.execute(pk.elf.clone(), stdin.clone()).await.expect("failed to execute program");
208
209 let proof =
211 prover.prove(&pk, stdin).core().await.expect("failed to create mock Core proof");
212
213 assert_eq!(proof.public_values.as_slice(), expected_pv.as_slice());
215 }
216
217 #[tokio::test]
219 async fn test_mock_plonk_proof_wrong_vkey_fails() {
220 setup_logger();
221 let prover = MockProver::new().await;
222
223 let pk1 = prover
225 .setup(test_artifacts::FIBONACCI_ELF)
226 .await
227 .expect("failed to setup proving key 1");
228 let pk2 = prover
229 .setup(test_artifacts::HELLO_WORLD_ELF)
230 .await
231 .expect("failed to setup proving key 2");
232
233 let mut stdin = SP1Stdin::new();
235 stdin.write(&10usize);
236 let proof =
237 prover.prove(&pk1, stdin).plonk().await.expect("failed to create mock Plonk proof");
238
239 let result = prover.verify(&proof, &pk2.vk, None);
241 assert!(result.is_err(), "Verification should fail with wrong vkey");
242 }
243
244 #[tokio::test]
246 async fn test_mock_groth16_proof_wrong_vkey_fails() {
247 setup_logger();
248 let prover = MockProver::new().await;
249
250 let pk1 = prover
252 .setup(test_artifacts::FIBONACCI_ELF)
253 .await
254 .expect("failed to setup proving key 1");
255 let pk2 = prover
256 .setup(test_artifacts::HELLO_WORLD_ELF)
257 .await
258 .expect("failed to setup proving key 2");
259
260 let mut stdin = SP1Stdin::new();
262 stdin.write(&10usize);
263 let proof =
264 prover.prove(&pk1, stdin).groth16().await.expect("failed to create mock Groth16 proof");
265
266 let result = prover.verify(&proof, &pk2.vk, None);
268 assert!(result.is_err(), "Verification should fail with wrong vkey");
269 }
270
271 #[tokio::test]
273 async fn test_mock_plonk_proof_tampered_public_values_fails() {
274 setup_logger();
275 let prover = MockProver::new().await;
276 let pk =
277 prover.setup(test_artifacts::FIBONACCI_ELF).await.expect("failed to setup proving key");
278
279 let mut stdin = SP1Stdin::new();
281 stdin.write(&10usize);
282 let mut proof =
283 prover.prove(&pk, stdin).plonk().await.expect("failed to create mock Plonk proof");
284
285 proof.public_values = sp1_primitives::io::SP1PublicValues::from(&[0xDE, 0xAD, 0xBE, 0xEF]);
287
288 let result = prover.verify(&proof, &pk.vk, None);
290 assert!(result.is_err(), "Verification should fail with tampered public values");
291 }
292
293 #[tokio::test]
295 async fn test_mock_groth16_proof_tampered_public_values_fails() {
296 setup_logger();
297 let prover = MockProver::new().await;
298 let pk =
299 prover.setup(test_artifacts::FIBONACCI_ELF).await.expect("failed to setup proving key");
300
301 let mut stdin = SP1Stdin::new();
303 stdin.write(&10usize);
304 let mut proof =
305 prover.prove(&pk, stdin).groth16().await.expect("failed to create mock Groth16 proof");
306
307 proof.public_values = sp1_primitives::io::SP1PublicValues::from(&[0xDE, 0xAD, 0xBE, 0xEF]);
309
310 let result = prover.verify(&proof, &pk.vk, None);
312 assert!(result.is_err(), "Verification should fail with tampered public values");
313 }
314}