risc0_zkvm/host/server/prove/
mod.rs1mod dev_mode;
18pub(crate) mod keccak;
19mod prover_impl;
20#[cfg(test)]
21mod tests;
22pub(crate) mod union_peak;
23
24use std::rc::Rc;
25
26use anyhow::{anyhow, bail, ensure, Result};
27use risc0_core::field::baby_bear::{BabyBear, Elem, ExtElem};
28use risc0_zkp::hal::{CircuitHal, Hal};
29
30use self::{dev_mode::DevModeProver, prover_impl::ProverImpl};
31use crate::{
32 host::prove_info::ProveInfo,
33 is_dev_mode,
34 receipt::{
35 CompositeReceipt, Groth16Receipt, Groth16ReceiptVerifierParameters, InnerAssumptionReceipt,
36 InnerReceipt, SegmentReceipt, SuccinctReceipt,
37 },
38 receipt_claim::{UnionClaim, Unknown},
39 sha::Digestible,
40 stark_to_snark, ExecutorEnv, ProverOpts, Receipt, ReceiptClaim, ReceiptKind, Segment, Session,
41 VerifierContext,
42};
43
44mod private {
45 use super::{dev_mode::DevModeProver, prover_impl::ProverImpl};
46
47 pub trait Sealed {}
48 impl Sealed for ProverImpl {}
49 impl Sealed for DevModeProver {}
50}
51
52pub trait ProverServer: private::Sealed {
55 #[cfg(feature = "unstable")]
57 fn prove_keccak(&self, request: &crate::ProveKeccakRequest)
58 -> Result<SuccinctReceipt<Unknown>>;
59
60 fn prove(&self, env: ExecutorEnv<'_>, elf: &[u8]) -> Result<ProveInfo> {
62 self.prove_with_ctx(env, &VerifierContext::default(), elf)
63 }
64
65 fn prove_with_ctx(
67 &self,
68 env: ExecutorEnv<'_>,
69 ctx: &VerifierContext,
70 elf: &[u8],
71 ) -> Result<ProveInfo>;
72
73 fn prove_session(&self, ctx: &VerifierContext, session: &Session) -> Result<ProveInfo>;
75
76 fn prove_segment(&self, ctx: &VerifierContext, segment: &Segment) -> Result<SegmentReceipt>;
78
79 fn lift(&self, receipt: &SegmentReceipt) -> Result<SuccinctReceipt<ReceiptClaim>>;
81
82 fn join(
84 &self,
85 a: &SuccinctReceipt<ReceiptClaim>,
86 b: &SuccinctReceipt<ReceiptClaim>,
87 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
88
89 fn union(
91 &self,
92 a: &SuccinctReceipt<Unknown>,
93 b: &SuccinctReceipt<Unknown>,
94 ) -> Result<SuccinctReceipt<UnionClaim>>;
95
96 fn resolve(
99 &self,
100 conditional: &SuccinctReceipt<ReceiptClaim>,
101 assumption: &SuccinctReceipt<Unknown>,
102 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
103
104 fn identity_p254(
106 &self,
107 a: &SuccinctReceipt<ReceiptClaim>,
108 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
109
110 fn composite_to_succinct(
119 &self,
120 receipt: &CompositeReceipt,
121 ) -> Result<SuccinctReceipt<ReceiptClaim>> {
122 let continuation_receipt = receipt
124 .segments
125 .iter()
126 .try_fold(
127 None,
128 |left: Option<SuccinctReceipt<ReceiptClaim>>,
129 right: &SegmentReceipt|
130 -> Result<_> {
131 Ok(Some(match left {
132 Some(left) => self.join(&left, &self.lift(right)?)?,
133 None => self.lift(right)?,
134 }))
135 },
136 )?
137 .ok_or_else(|| {
138 anyhow!("malformed composite receipt has no continuation segment receipts")
139 })?;
140
141 receipt.assumption_receipts.iter().try_fold(
143 continuation_receipt,
144 |conditional: SuccinctReceipt<ReceiptClaim>, assumption: &InnerAssumptionReceipt| match assumption {
145 InnerAssumptionReceipt::Succinct(assumption) => self.resolve(&conditional, assumption),
146 InnerAssumptionReceipt::Composite(assumption) => {
147 self.resolve(&conditional, &self.composite_to_succinct(assumption)?.into_unknown())
148 }
149 InnerAssumptionReceipt::Fake(_) => bail!(
150 "compressing composite receipts with fake receipt assumptions is not supported"
151 ),
152 InnerAssumptionReceipt::Groth16(_) => bail!(
153 "compressing composite receipts with Groth16 receipt assumptions is not supported"
154 )
155 },
156 )
157 }
158
159 fn succinct_to_groth16(
161 &self,
162 receipt: &SuccinctReceipt<ReceiptClaim>,
163 ) -> Result<Groth16Receipt<ReceiptClaim>> {
164 let ident_receipt = self.identity_p254(receipt).unwrap();
165 let seal_bytes = ident_receipt.get_seal_bytes();
166
167 let seal = stark_to_snark(&seal_bytes)?.to_vec();
168 Ok(Groth16Receipt {
169 seal,
170 claim: receipt.claim.clone(),
171 verifier_parameters: Groth16ReceiptVerifierParameters::default().digest(),
172 })
173 }
174
175 fn compress(&self, opts: &ProverOpts, receipt: &Receipt) -> Result<Receipt> {
181 match &receipt.inner {
182 InnerReceipt::Composite(inner) => match opts.receipt_kind {
183 ReceiptKind::Composite => Ok(receipt.clone()),
184 ReceiptKind::Succinct => {
185 let succinct_receipt = self.composite_to_succinct(inner)?;
186 Ok(Receipt::new(
187 InnerReceipt::Succinct(succinct_receipt),
188 receipt.journal.bytes.clone(),
189 ))
190 }
191 ReceiptKind::Groth16 => {
192 let succinct_receipt = self.composite_to_succinct(inner)?;
193 let groth16_receipt = self.succinct_to_groth16(&succinct_receipt)?;
194 Ok(Receipt::new(
195 InnerReceipt::Groth16(groth16_receipt),
196 receipt.journal.bytes.clone(),
197 ))
198 }
199 },
200 InnerReceipt::Succinct(inner) => match opts.receipt_kind {
201 ReceiptKind::Composite | ReceiptKind::Succinct => Ok(receipt.clone()),
202 ReceiptKind::Groth16 => {
203 let groth16_receipt = self.succinct_to_groth16(inner)?;
204 Ok(Receipt::new(
205 InnerReceipt::Groth16(groth16_receipt),
206 receipt.journal.bytes.clone(),
207 ))
208 }
209 },
210 InnerReceipt::Groth16(_) => match opts.receipt_kind {
211 ReceiptKind::Composite | ReceiptKind::Succinct | ReceiptKind::Groth16 => {
212 Ok(receipt.clone())
213 }
214 },
215 InnerReceipt::Fake(_) => {
216 ensure!(
217 is_dev_mode(),
218 "dev mode must be enabled to compress fake receipts"
219 );
220 Ok(receipt.clone())
221 }
222 }
223 }
224}
225
226#[derive(Clone)]
228pub struct HalPair<H, C>
229where
230 H: Hal<Field = BabyBear, Elem = Elem, ExtElem = ExtElem>,
231 C: CircuitHal<H>,
232{
233 pub hal: Rc<H>,
235
236 pub circuit_hal: Rc<C>,
238}
239
240impl Session {
241 pub fn prove(&self) -> Result<ProveInfo> {
244 let prover = get_prover_server(&ProverOpts::default())?;
245 prover.prove_session(&VerifierContext::default(), self)
246 }
247}
248
249pub fn get_prover_server(opts: &ProverOpts) -> Result<Rc<dyn ProverServer>> {
252 if is_dev_mode() {
253 eprintln!("WARNING: proving in dev mode. This will not generate valid, secure proofs.");
254 return Ok(Rc::new(DevModeProver));
255 }
256
257 Ok(Rc::new(ProverImpl::new(opts.clone())))
258}