risc0_zkvm/host/server/prove/
mod.rs1pub(crate) mod 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_groth16::prove::shrink_wrap;
29use risc0_zkp::hal::{CircuitHal, Hal};
30
31use self::{dev_mode::DevModeProver, prover_impl::ProverImpl};
32use crate::{
33 claim::{receipt::UnionClaim, Unknown},
34 host::prove_info::ProveInfo,
35 receipt::{
36 CompositeReceipt, Groth16Receipt, Groth16ReceiptVerifierParameters, InnerAssumptionReceipt,
37 InnerReceipt, SegmentReceipt, SuccinctReceipt,
38 },
39 sha::Digestible,
40 ExecutorEnv, PreflightResults, ProverOpts, Receipt, ReceiptClaim, ReceiptKind, Segment,
41 Session, VerifierContext, WorkClaim,
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 fn prove(&self, env: ExecutorEnv<'_>, elf: &[u8]) -> Result<ProveInfo> {
57 self.prove_with_ctx(env, &VerifierContext::default(), elf)
58 }
59
60 fn prove_with_ctx(
62 &self,
63 env: ExecutorEnv<'_>,
64 ctx: &VerifierContext,
65 elf: &[u8],
66 ) -> Result<ProveInfo>;
67
68 fn prove_session(&self, ctx: &VerifierContext, session: &Session) -> Result<ProveInfo>;
70
71 fn prove_segment(&self, ctx: &VerifierContext, segment: &Segment) -> Result<SegmentReceipt> {
73 tracing::debug!("prove_segment");
74 let results = self.segment_preflight(segment)?;
75 self.prove_segment_core(ctx, results)
76 }
77
78 fn segment_preflight(&self, segment: &Segment) -> Result<PreflightResults>;
80
81 fn prove_segment_core(
83 &self,
84 ctx: &VerifierContext,
85 preflight_results: PreflightResults,
86 ) -> Result<SegmentReceipt>;
87
88 fn prove_keccak(&self, request: &crate::ProveKeccakRequest)
90 -> Result<SuccinctReceipt<Unknown>>;
91
92 fn lift(&self, receipt: &SegmentReceipt) -> Result<SuccinctReceipt<ReceiptClaim>>;
94
95 fn join(
97 &self,
98 a: &SuccinctReceipt<ReceiptClaim>,
99 b: &SuccinctReceipt<ReceiptClaim>,
100 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
101
102 fn union(
104 &self,
105 a: &SuccinctReceipt<Unknown>,
106 b: &SuccinctReceipt<Unknown>,
107 ) -> Result<SuccinctReceipt<UnionClaim>>;
108
109 fn resolve(
112 &self,
113 conditional: &SuccinctReceipt<ReceiptClaim>,
114 assumption: &SuccinctReceipt<Unknown>,
115 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
116
117 fn lift_povw(
119 &self,
120 receipt: &SegmentReceipt,
121 ) -> Result<SuccinctReceipt<WorkClaim<ReceiptClaim>>>;
122
123 fn join_povw(
126 &self,
127 a: &SuccinctReceipt<WorkClaim<ReceiptClaim>>,
128 b: &SuccinctReceipt<WorkClaim<ReceiptClaim>>,
129 ) -> Result<SuccinctReceipt<WorkClaim<ReceiptClaim>>>;
130
131 fn join_unwrap_povw(
134 &self,
135 a: &SuccinctReceipt<WorkClaim<ReceiptClaim>>,
136 b: &SuccinctReceipt<WorkClaim<ReceiptClaim>>,
137 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
138
139 fn resolve_povw(
142 &self,
143 conditional: &SuccinctReceipt<WorkClaim<ReceiptClaim>>,
144 assumption: &SuccinctReceipt<Unknown>,
145 ) -> Result<SuccinctReceipt<WorkClaim<ReceiptClaim>>>;
146
147 fn resolve_unwrap_povw(
151 &self,
152 conditional: &SuccinctReceipt<WorkClaim<ReceiptClaim>>,
153 assumption: &SuccinctReceipt<Unknown>,
154 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
155
156 fn unwrap_povw(
159 &self,
160 a: &SuccinctReceipt<WorkClaim<ReceiptClaim>>,
161 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
162
163 fn identity_p254(
165 &self,
166 a: &SuccinctReceipt<ReceiptClaim>,
167 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
168
169 fn composite_to_succinct(
178 &self,
179 receipt: &CompositeReceipt,
180 ) -> Result<SuccinctReceipt<ReceiptClaim>> {
181 <Self as Compress<_>>::composite_to_succinct(self, receipt)
182 }
183
184 fn composite_to_succinct_povw(
186 &self,
187 receipt: &CompositeReceipt,
188 ) -> Result<SuccinctReceipt<WorkClaim<ReceiptClaim>>> {
189 <Self as Compress<_>>::composite_to_succinct(self, receipt)
190 }
191
192 fn succinct_to_groth16(
194 &self,
195 receipt: &SuccinctReceipt<ReceiptClaim>,
196 ) -> Result<Groth16Receipt<ReceiptClaim>> {
197 let ident_receipt = self.identity_p254(receipt).unwrap();
198 let seal_bytes = ident_receipt.get_seal_bytes();
199 let seal = shrink_wrap(&seal_bytes)?.to_vec();
200 Ok(Groth16Receipt {
201 seal,
202 claim: receipt.claim.clone(),
203 verifier_parameters: Groth16ReceiptVerifierParameters::default().digest(),
204 })
205 }
206
207 fn compress(&self, opts: &ProverOpts, receipt: &Receipt) -> Result<Receipt> {
213 match &receipt.inner {
214 InnerReceipt::Composite(inner) => match opts.receipt_kind {
215 ReceiptKind::Composite => Ok(receipt.clone()),
216 ReceiptKind::Succinct => {
217 let succinct_receipt = self.composite_to_succinct(inner)?;
218 Ok(Receipt::new(
219 InnerReceipt::Succinct(succinct_receipt),
220 receipt.journal.bytes.clone(),
221 ))
222 }
223 ReceiptKind::Groth16 => {
224 let succinct_receipt = self.composite_to_succinct(inner)?;
225 let groth16_receipt = self.succinct_to_groth16(&succinct_receipt)?;
226 Ok(Receipt::new(
227 InnerReceipt::Groth16(groth16_receipt),
228 receipt.journal.bytes.clone(),
229 ))
230 }
231 },
232 InnerReceipt::Succinct(inner) => match opts.receipt_kind {
233 ReceiptKind::Composite | ReceiptKind::Succinct => Ok(receipt.clone()),
234 ReceiptKind::Groth16 => {
235 let groth16_receipt = self.succinct_to_groth16(inner)?;
236 Ok(Receipt::new(
237 InnerReceipt::Groth16(groth16_receipt),
238 receipt.journal.bytes.clone(),
239 ))
240 }
241 },
242 InnerReceipt::Groth16(_) => match opts.receipt_kind {
243 ReceiptKind::Composite | ReceiptKind::Succinct | ReceiptKind::Groth16 => {
244 Ok(receipt.clone())
245 }
246 },
247 InnerReceipt::Fake(_) => {
248 ensure!(
249 opts.dev_mode(),
250 "dev mode must be enabled to compress fake receipts"
251 );
252 Ok(receipt.clone())
253 }
254 }
255 }
256}
257
258trait Lift<Claim> {
259 fn lift(&self, segment_receipt: &SegmentReceipt) -> anyhow::Result<SuccinctReceipt<Claim>>;
260}
261
262impl<P: ProverServer + ?Sized> Lift<ReceiptClaim> for P {
263 fn lift(
264 &self,
265 segment_receipt: &SegmentReceipt,
266 ) -> anyhow::Result<SuccinctReceipt<ReceiptClaim>> {
267 <Self as ProverServer>::lift(self, segment_receipt)
268 }
269}
270
271impl<P: ProverServer + ?Sized> Lift<WorkClaim<ReceiptClaim>> for P {
272 fn lift(
273 &self,
274 segment_receipt: &SegmentReceipt,
275 ) -> anyhow::Result<SuccinctReceipt<WorkClaim<ReceiptClaim>>> {
276 self.lift_povw(segment_receipt)
277 }
278}
279
280trait Join<Claim> {
281 fn join(
282 &self,
283 a: &SuccinctReceipt<Claim>,
284 b: &SuccinctReceipt<Claim>,
285 ) -> anyhow::Result<SuccinctReceipt<Claim>>;
286}
287
288impl<P: ProverServer + ?Sized> Join<ReceiptClaim> for P {
289 fn join(
290 &self,
291 a: &SuccinctReceipt<ReceiptClaim>,
292 b: &SuccinctReceipt<ReceiptClaim>,
293 ) -> anyhow::Result<SuccinctReceipt<ReceiptClaim>> {
294 <Self as ProverServer>::join(self, a, b)
295 }
296}
297
298impl<P: ProverServer + ?Sized> Join<WorkClaim<ReceiptClaim>> for P {
299 fn join(
300 &self,
301 a: &SuccinctReceipt<WorkClaim<ReceiptClaim>>,
302 b: &SuccinctReceipt<WorkClaim<ReceiptClaim>>,
303 ) -> anyhow::Result<SuccinctReceipt<WorkClaim<ReceiptClaim>>> {
304 self.join_povw(a, b)
305 }
306}
307
308trait Resolve<Claim> {
309 fn resolve(
310 &self,
311 cond: &SuccinctReceipt<Claim>,
312 assum: &SuccinctReceipt<Unknown>,
313 ) -> anyhow::Result<SuccinctReceipt<Claim>>;
314}
315
316impl<P: ProverServer + ?Sized> Resolve<ReceiptClaim> for P {
317 fn resolve(
318 &self,
319 cond: &SuccinctReceipt<ReceiptClaim>,
320 assum: &SuccinctReceipt<Unknown>,
321 ) -> anyhow::Result<SuccinctReceipt<ReceiptClaim>> {
322 <Self as ProverServer>::resolve(self, cond, assum)
323 }
324}
325
326impl<P: ProverServer + ?Sized> Resolve<WorkClaim<ReceiptClaim>> for P {
327 fn resolve(
328 &self,
329 cond: &SuccinctReceipt<WorkClaim<ReceiptClaim>>,
330 assum: &SuccinctReceipt<Unknown>,
331 ) -> anyhow::Result<SuccinctReceipt<WorkClaim<ReceiptClaim>>> {
332 self.resolve_povw(cond, assum)
333 }
334}
335
336trait Compress<Claim> {
337 fn composite_to_succinct(
338 &self,
339 composite_receipt: &CompositeReceipt,
340 ) -> anyhow::Result<SuccinctReceipt<Claim>>;
341}
342
343impl<P, Claim> Compress<Claim> for P
344where
345 P: Lift<Claim>
346 + Join<Claim>
347 + Resolve<Claim>
348 + Lift<ReceiptClaim>
349 + Join<ReceiptClaim>
350 + Resolve<ReceiptClaim>
351 + ?Sized,
352{
353 fn composite_to_succinct(
354 &self,
355 composite_receipt: &CompositeReceipt,
356 ) -> anyhow::Result<SuccinctReceipt<Claim>> {
357 let continuation_receipt = composite_receipt
359 .segments
360 .iter()
361 .try_fold(
362 None,
363 |left: Option<SuccinctReceipt<Claim>>, right: &SegmentReceipt| -> Result<_> {
364 Ok(Some(match left {
365 Some(left) => self.join(&left, &self.lift(right)?)?,
366 None => self.lift(right)?,
367 }))
368 },
369 )?
370 .ok_or_else(|| {
371 anyhow!("malformed composite receipt has no continuation segment receipts")
372 })?;
373
374 composite_receipt.assumption_receipts.iter().try_fold(
376 continuation_receipt,
377 |conditional: SuccinctReceipt<Claim>, assumption: &InnerAssumptionReceipt| match assumption {
378 InnerAssumptionReceipt::Succinct(assumption) => self.resolve(&conditional, assumption),
379 InnerAssumptionReceipt::Composite(assumption) => {
380 self.resolve(&conditional, &SuccinctReceipt::<ReceiptClaim>::into_unknown(self.composite_to_succinct(assumption)?))
381 }
382 InnerAssumptionReceipt::Fake(_) => bail!(
383 "compressing composite receipts with fake receipt assumptions is not supported"
384 ),
385 InnerAssumptionReceipt::Groth16(_) => bail!(
386 "compressing composite receipts with Groth16 receipt assumptions is not supported"
387 )
388 },
389 )
390 }
391}
392
393#[derive(Clone)]
395pub struct HalPair<H, C>
396where
397 H: Hal<Field = BabyBear, Elem = Elem, ExtElem = ExtElem>,
398 C: CircuitHal<H>,
399{
400 pub hal: Rc<H>,
402
403 pub circuit_hal: Rc<C>,
405}
406
407impl Session {
408 pub fn prove(&self) -> Result<ProveInfo> {
411 let prover = get_prover_server(&ProverOpts::default())?;
412 prover.prove_session(&VerifierContext::default(), self)
413 }
414}
415
416pub fn get_prover_server(opts: &ProverOpts) -> Result<Rc<dyn ProverServer>> {
418 if opts.dev_mode() {
419 eprintln!("WARNING: proving in dev mode. This will not generate valid, secure proofs.");
420 return Ok(Rc::new(DevModeProver::new()));
421 }
422
423 Ok(Rc::new(ProverImpl::new(opts.clone())))
424}