risc0_zkvm/host/server/prove/
mod.rs1mod dev_mode;
18pub(crate) mod keccak;
19mod prover_impl;
20#[cfg(test)]
21mod tests;
22
23use std::rc::Rc;
24
25use anyhow::{anyhow, bail, ensure, Result};
26use risc0_core::field::baby_bear::{BabyBear, Elem, ExtElem};
27use risc0_zkp::hal::{CircuitHal, Hal};
28
29use self::{dev_mode::DevModeProver, prover_impl::ProverImpl};
30use crate::{
31 host::prove_info::ProveInfo,
32 is_dev_mode,
33 receipt::{
34 CompositeReceipt, Groth16Receipt, Groth16ReceiptVerifierParameters, InnerAssumptionReceipt,
35 InnerReceipt, SegmentReceipt, SuccinctReceipt,
36 },
37 receipt_claim::Unknown,
38 sha::Digestible,
39 stark_to_snark, ExecutorEnv, ExecutorImpl, ProverOpts, Receipt, ReceiptClaim, ReceiptKind,
40 Segment, Session, VerifierContext,
41};
42
43pub trait ProverServer {
46 #[cfg(feature = "unstable")]
48 fn prove_keccak(&self, request: &crate::ProveKeccakRequest)
49 -> Result<SuccinctReceipt<Unknown>>;
50
51 fn prove(&self, env: ExecutorEnv<'_>, elf: &[u8]) -> Result<ProveInfo> {
53 self.prove_with_ctx(env, &VerifierContext::default(), elf)
54 }
55
56 fn prove_with_ctx(
58 &self,
59 env: ExecutorEnv<'_>,
60 ctx: &VerifierContext,
61 elf: &[u8],
62 ) -> Result<ProveInfo> {
63 let mut exec = ExecutorImpl::from_elf(env, elf)?;
64 let session = exec.run()?;
65 self.prove_session(ctx, &session)
66 }
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
74 fn lift(&self, receipt: &SegmentReceipt) -> Result<SuccinctReceipt<ReceiptClaim>>;
76
77 fn join(
79 &self,
80 a: &SuccinctReceipt<ReceiptClaim>,
81 b: &SuccinctReceipt<ReceiptClaim>,
82 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
83
84 fn resolve(
87 &self,
88 conditional: &SuccinctReceipt<ReceiptClaim>,
89 assumption: &SuccinctReceipt<Unknown>,
90 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
91
92 fn identity_p254(
94 &self,
95 a: &SuccinctReceipt<ReceiptClaim>,
96 ) -> Result<SuccinctReceipt<ReceiptClaim>>;
97
98 fn composite_to_succinct(
107 &self,
108 receipt: &CompositeReceipt,
109 ) -> Result<SuccinctReceipt<ReceiptClaim>> {
110 let continuation_receipt = receipt
112 .segments
113 .iter()
114 .try_fold(
115 None,
116 |left: Option<SuccinctReceipt<ReceiptClaim>>,
117 right: &SegmentReceipt|
118 -> Result<_> {
119 Ok(Some(match left {
120 Some(left) => self.join(&left, &self.lift(right)?)?,
121 None => self.lift(right)?,
122 }))
123 },
124 )?
125 .ok_or(anyhow!(
126 "malformed composite receipt has no continuation segment receipts"
127 ))?;
128
129 receipt.assumption_receipts.iter().try_fold(
131 continuation_receipt,
132 |conditional: SuccinctReceipt<ReceiptClaim>, assumption: &InnerAssumptionReceipt| match assumption {
133 InnerAssumptionReceipt::Succinct(assumption) => self.resolve(&conditional, assumption),
134 InnerAssumptionReceipt::Composite(assumption) => {
135 self.resolve(&conditional, &self.composite_to_succinct(assumption)?.into_unknown())
136 }
137 InnerAssumptionReceipt::Fake(_) => bail!(
138 "compressing composite receipts with fake receipt assumptions is not supported"
139 ),
140 InnerAssumptionReceipt::Groth16(_) => bail!(
141 "compressing composite receipts with Groth16 receipt assumptions is not supported"
142 )
143 },
144 )
145 }
146
147 fn succinct_to_groth16(
149 &self,
150 receipt: &SuccinctReceipt<ReceiptClaim>,
151 ) -> Result<Groth16Receipt<ReceiptClaim>> {
152 let ident_receipt = self.identity_p254(receipt).unwrap();
153 let seal_bytes = ident_receipt.get_seal_bytes();
154
155 let seal = stark_to_snark(&seal_bytes)?.to_vec();
156 Ok(Groth16Receipt {
157 seal,
158 claim: receipt.claim.clone(),
159 verifier_parameters: Groth16ReceiptVerifierParameters::default().digest(),
160 })
161 }
162
163 fn compress(&self, opts: &ProverOpts, receipt: &Receipt) -> Result<Receipt> {
169 match &receipt.inner {
170 InnerReceipt::Composite(inner) => match opts.receipt_kind {
171 ReceiptKind::Composite => Ok(receipt.clone()),
172 ReceiptKind::Succinct => {
173 let succinct_receipt = self.composite_to_succinct(inner)?;
174 Ok(Receipt::new(
175 InnerReceipt::Succinct(succinct_receipt),
176 receipt.journal.bytes.clone(),
177 ))
178 }
179 ReceiptKind::Groth16 => {
180 let succinct_receipt = self.composite_to_succinct(inner)?;
181 let groth16_receipt = self.succinct_to_groth16(&succinct_receipt)?;
182 Ok(Receipt::new(
183 InnerReceipt::Groth16(groth16_receipt),
184 receipt.journal.bytes.clone(),
185 ))
186 }
187 },
188 InnerReceipt::Succinct(inner) => match opts.receipt_kind {
189 ReceiptKind::Composite | ReceiptKind::Succinct => Ok(receipt.clone()),
190 ReceiptKind::Groth16 => {
191 let groth16_receipt = self.succinct_to_groth16(inner)?;
192 Ok(Receipt::new(
193 InnerReceipt::Groth16(groth16_receipt),
194 receipt.journal.bytes.clone(),
195 ))
196 }
197 },
198 InnerReceipt::Groth16(_) => match opts.receipt_kind {
199 ReceiptKind::Composite | ReceiptKind::Succinct | ReceiptKind::Groth16 => {
200 Ok(receipt.clone())
201 }
202 },
203 InnerReceipt::Fake(_) => {
204 ensure!(
205 is_dev_mode(),
206 "dev mode must be enabled to compress fake receipts"
207 );
208 Ok(receipt.clone())
209 }
210 }
211 }
212}
213
214#[derive(Clone)]
216pub struct HalPair<H, C>
217where
218 H: Hal<Field = BabyBear, Elem = Elem, ExtElem = ExtElem>,
219 C: CircuitHal<H>,
220{
221 pub hal: Rc<H>,
223
224 pub circuit_hal: Rc<C>,
226}
227
228impl Session {
229 pub fn prove(&self) -> Result<ProveInfo> {
232 let prover = get_prover_server(&ProverOpts::default())?;
233 prover.prove_session(&VerifierContext::default(), self)
234 }
235}
236
237pub fn get_prover_server(opts: &ProverOpts) -> Result<Rc<dyn ProverServer>> {
240 if is_dev_mode() {
241 eprintln!("WARNING: proving in dev mode. This will not generate valid, secure proofs.");
242 return Ok(Rc::new(DevModeProver));
243 }
244
245 Ok(Rc::new(ProverImpl::new(opts.clone())))
246}