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_zkp::hal::{CircuitHal, Hal};
29
30use self::{dev_mode::DevModeProver, prover_impl::ProverImpl};
31use crate::{
32 host::prove_info::ProveInfo,
33 receipt::{
34 CompositeReceipt, Groth16Receipt, Groth16ReceiptVerifierParameters, InnerAssumptionReceipt,
35 InnerReceipt, SegmentReceipt, SuccinctReceipt,
36 },
37 receipt_claim::{UnionClaim, Unknown},
38 sha::Digestible,
39 stark_to_snark, ExecutorEnv, PreflightResults, ProverOpts, Receipt, ReceiptClaim, ReceiptKind,
40 Segment, Session, VerifierContext,
41};
42
43mod private {
44 use super::{dev_mode::DevModeProver, prover_impl::ProverImpl};
45
46 pub trait Sealed {}
47 impl Sealed for ProverImpl {}
48 impl Sealed for DevModeProver {}
49}
50
51pub trait ProverServer: private::Sealed {
54 fn prove(&self, env: ExecutorEnv<'_>, elf: &[u8]) -> Result<ProveInfo> {
56 self.prove_with_ctx(env, &VerifierContext::default(), elf)
57 }
58
59 fn prove_with_ctx(
61 &self,
62 env: ExecutorEnv<'_>,
63 ctx: &VerifierContext,
64 elf: &[u8],
65 ) -> Result<ProveInfo>;
66
67 fn prove_session(&self, ctx: &VerifierContext, session: &Session) -> Result<ProveInfo>;
69
70 fn prove_segment(&self, ctx: &VerifierContext, segment: &Segment) -> Result<SegmentReceipt> {
72 let results = self.segment_preflight(segment)?;
73 self.prove_segment_core(ctx, results)
74 }
75
76 fn segment_preflight(&self, segment: &Segment) -> Result<PreflightResults>;
78
79 fn prove_segment_core(
81 &self,
82 ctx: &VerifierContext,
83 preflight_results: PreflightResults,
84 ) -> Result<SegmentReceipt>;
85
86 fn prove_keccak(&self, request: &crate::ProveKeccakRequest)
88 -> Result<SuccinctReceipt<Unknown>>;
89
90 fn lift(&self, receipt: &SegmentReceipt) -> Result<SuccinctReceipt<ReceiptClaim>>;
92
93 fn join(
95 &self,
96 a: &SuccinctReceipt<ReceiptClaim>,
97 b: &SuccinctReceipt<ReceiptClaim>,
98 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
99
100 fn union(
102 &self,
103 a: &SuccinctReceipt<Unknown>,
104 b: &SuccinctReceipt<Unknown>,
105 ) -> Result<SuccinctReceipt<UnionClaim>>;
106
107 fn resolve(
110 &self,
111 conditional: &SuccinctReceipt<ReceiptClaim>,
112 assumption: &SuccinctReceipt<Unknown>,
113 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
114
115 fn identity_p254(
117 &self,
118 a: &SuccinctReceipt<ReceiptClaim>,
119 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
120
121 fn composite_to_succinct(
130 &self,
131 receipt: &CompositeReceipt,
132 ) -> Result<SuccinctReceipt<ReceiptClaim>> {
133 let continuation_receipt = receipt
135 .segments
136 .iter()
137 .try_fold(
138 None,
139 |left: Option<SuccinctReceipt<ReceiptClaim>>,
140 right: &SegmentReceipt|
141 -> Result<_> {
142 Ok(Some(match left {
143 Some(left) => self.join(&left, &self.lift(right)?)?,
144 None => self.lift(right)?,
145 }))
146 },
147 )?
148 .ok_or_else(|| {
149 anyhow!("malformed composite receipt has no continuation segment receipts")
150 })?;
151
152 receipt.assumption_receipts.iter().try_fold(
154 continuation_receipt,
155 |conditional: SuccinctReceipt<ReceiptClaim>, assumption: &InnerAssumptionReceipt| match assumption {
156 InnerAssumptionReceipt::Succinct(assumption) => self.resolve(&conditional, assumption),
157 InnerAssumptionReceipt::Composite(assumption) => {
158 self.resolve(&conditional, &self.composite_to_succinct(assumption)?.into_unknown())
159 }
160 InnerAssumptionReceipt::Fake(_) => bail!(
161 "compressing composite receipts with fake receipt assumptions is not supported"
162 ),
163 InnerAssumptionReceipt::Groth16(_) => bail!(
164 "compressing composite receipts with Groth16 receipt assumptions is not supported"
165 )
166 },
167 )
168 }
169
170 fn succinct_to_groth16(
172 &self,
173 receipt: &SuccinctReceipt<ReceiptClaim>,
174 ) -> Result<Groth16Receipt<ReceiptClaim>> {
175 let ident_receipt = self.identity_p254(receipt).unwrap();
176 let seal_bytes = ident_receipt.get_seal_bytes();
177
178 let seal = stark_to_snark(&seal_bytes)?.to_vec();
179 Ok(Groth16Receipt {
180 seal,
181 claim: receipt.claim.clone(),
182 verifier_parameters: Groth16ReceiptVerifierParameters::default().digest(),
183 })
184 }
185
186 fn compress(&self, opts: &ProverOpts, receipt: &Receipt) -> Result<Receipt> {
192 match &receipt.inner {
193 InnerReceipt::Composite(inner) => match opts.receipt_kind {
194 ReceiptKind::Composite => Ok(receipt.clone()),
195 ReceiptKind::Succinct => {
196 let succinct_receipt = self.composite_to_succinct(inner)?;
197 Ok(Receipt::new(
198 InnerReceipt::Succinct(succinct_receipt),
199 receipt.journal.bytes.clone(),
200 ))
201 }
202 ReceiptKind::Groth16 => {
203 let succinct_receipt = self.composite_to_succinct(inner)?;
204 let groth16_receipt = self.succinct_to_groth16(&succinct_receipt)?;
205 Ok(Receipt::new(
206 InnerReceipt::Groth16(groth16_receipt),
207 receipt.journal.bytes.clone(),
208 ))
209 }
210 },
211 InnerReceipt::Succinct(inner) => match opts.receipt_kind {
212 ReceiptKind::Composite | ReceiptKind::Succinct => Ok(receipt.clone()),
213 ReceiptKind::Groth16 => {
214 let groth16_receipt = self.succinct_to_groth16(inner)?;
215 Ok(Receipt::new(
216 InnerReceipt::Groth16(groth16_receipt),
217 receipt.journal.bytes.clone(),
218 ))
219 }
220 },
221 InnerReceipt::Groth16(_) => match opts.receipt_kind {
222 ReceiptKind::Composite | ReceiptKind::Succinct | ReceiptKind::Groth16 => {
223 Ok(receipt.clone())
224 }
225 },
226 InnerReceipt::Fake(_) => {
227 ensure!(
228 opts.dev_mode(),
229 "dev mode must be enabled to compress fake receipts"
230 );
231 Ok(receipt.clone())
232 }
233 }
234 }
235}
236
237#[derive(Clone)]
239pub struct HalPair<H, C>
240where
241 H: Hal<Field = BabyBear, Elem = Elem, ExtElem = ExtElem>,
242 C: CircuitHal<H>,
243{
244 pub hal: Rc<H>,
246
247 pub circuit_hal: Rc<C>,
249}
250
251impl Session {
252 pub fn prove(&self) -> Result<ProveInfo> {
255 let prover = get_prover_server(&ProverOpts::default())?;
256 prover.prove_session(&VerifierContext::default(), self)
257 }
258}
259
260pub fn get_prover_server(opts: &ProverOpts) -> Result<Rc<dyn ProverServer>> {
262 if opts.dev_mode() {
263 eprintln!("WARNING: proving in dev mode. This will not generate valid, secure proofs.");
264 return Ok(Rc::new(DevModeProver::new()));
265 }
266
267 Ok(Rc::new(ProverImpl::new(opts.clone())))
268}