1pub mod builder;
11
12use std::pin::Pin;
13
14use sp1_core_executor::SP1CoreOpts;
15use sp1_core_machine::{io::SP1Stdin, riscv::RiscvAir};
16use sp1_hypercube::Machine;
17use sp1_primitives::SP1Field;
18use sp1_prover::worker::{SP1LightNode, SP1NodeCore};
19
20use crate::{
21 prover::{BaseProveRequest, ProveRequest},
22 Prover, SP1ProofWithPublicValues, SP1ProvingKey,
23};
24use std::future::{Future, IntoFuture};
25
26#[derive(Clone)]
28pub struct LightProver {
29 inner: SP1LightNode,
30}
31
32impl LightProver {
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 light 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 LightProver {
63 type ProvingKey = SP1ProvingKey;
64
65 type Error = anyhow::Error;
66
67 type ProveRequest<'a> = LightProveRequest<'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 LightProveRequest { 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 }
92
93pub struct LightProveRequest<'a> {
95 pub(crate) base: BaseProveRequest<'a, LightProver>,
96}
97
98impl<'a> ProveRequest<'a, LightProver> for LightProveRequest<'a> {
99 fn base(&mut self) -> &mut BaseProveRequest<'a, LightProver> {
100 &mut self.base
101 }
102}
103
104impl<'a> IntoFuture for LightProveRequest<'a> {
105 type Output = Result<SP1ProofWithPublicValues, anyhow::Error>;
106 type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>;
107
108 fn into_future(self) -> Self::IntoFuture {
109 Box::pin(async move {
110 Err(anyhow::anyhow!(
111 "Use LightProver for executing and verifying only. For proving, use CpuProver"
112 ))
113 })
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use crate::{prover::ProveRequest, utils::setup_logger, LightProver, Prover, SP1Stdin};
120
121 #[tokio::test]
123 async fn test_light_execute_and_prove() {
124 setup_logger();
125 let prover = LightProver::new().await;
126 let pk =
127 prover.setup(test_artifacts::FIBONACCI_ELF).await.expect("failed to setup proving key");
128
129 let mut stdin = SP1Stdin::new();
131 stdin.write(&10usize);
132 let (pv, _) =
133 prover.execute(pk.elf.clone(), stdin).await.expect("failed to execute program");
134 assert!(!pv.as_slice().is_empty());
135
136 let mut stdin = SP1Stdin::new();
138 stdin.write(&10usize);
139 let result = prover.prove(&pk, stdin).core().await;
140 assert!(result.is_err());
141 assert!(result.unwrap_err().to_string().contains("executing and verifying only"));
142 }
143}