1use std::sync::Arc;
2
3use eyre::Result;
4use openvm_circuit::arch::{
5 instructions::exe::VmExe, Executor, MeteredExecutor, PreflightExecutor, VmBuilder,
6 VmExecutionConfig,
7};
8use openvm_continuations::RootSC;
9use openvm_stark_backend::{p3_field::PrimeField32, proof::Proof, StarkEngine, Val};
10use openvm_verify_stark_host::VmStarkProof;
11
12#[cfg(feature = "evm-prove")]
13use crate::prover::Halo2Prover;
14use crate::{
15 prover::{vm::types::VmProvingKey, AggProver, InternalLayerMetadata, RootProver, StarkProver},
16 DeferralInput, DeferralSetup, StdIn, SC,
17};
18
19pub struct EvmProver<E, VB>
27where
28 E: StarkEngine,
29 VB: VmBuilder<E>,
30{
31 pub stark_prover: StarkProver<E, VB>,
32 pub root_prover: Arc<RootProver>,
33 #[cfg(feature = "evm-prove")]
34 pub halo2_prover: Option<Halo2Prover>,
35}
36
37impl<E, VB> EvmProver<E, VB>
38where
39 E: StarkEngine<SC = SC>,
40 VB: VmBuilder<E> + Clone,
41 Val<SC>: PrimeField32,
42{
43 pub fn new(
44 vm_builder: VB,
45 app_vm_pk: &VmProvingKey<VB::VmConfig>,
46 app_exe: Arc<VmExe<Val<SC>>>,
47 agg_prover: Arc<AggProver>,
48 deferral_setup: DeferralSetup,
49 root_prover: Arc<RootProver>,
50 #[cfg(feature = "evm-prove")] halo2_prover: Option<Halo2Prover>,
51 ) -> Result<Self> {
52 Ok(Self {
53 stark_prover: StarkProver::new(
54 vm_builder,
55 app_vm_pk,
56 app_exe,
57 agg_prover,
58 deferral_setup,
59 )?,
60 root_prover,
61 #[cfg(feature = "evm-prove")]
62 halo2_prover,
63 })
64 }
65
66 pub fn prove_root_from_vm_stark_proof(
67 &mut self,
68 stark_proof: VmStarkProof,
69 metadata: &mut InternalLayerMetadata,
70 ) -> Result<Proof<RootSC>>
71 where
72 <VB::VmConfig as VmExecutionConfig<Val<SC>>>::Executor: Executor<Val<SC>>
73 + MeteredExecutor<Val<SC>>
74 + PreflightExecutor<Val<SC>, VB::RecordArena>,
75 {
76 #[cfg(test)]
77 {
78 let agg_vk = self
79 .stark_prover
80 .agg_prover
81 .internal_recursive_prover
82 .get_vk()
83 .as_ref()
84 .clone();
85 let baseline = self.stark_prover.generate_baseline();
86 crate::GenericSdk::<E, VB>::verify_proof(agg_vk, baseline, &stark_proof)?;
87 }
88
89 const MAX_ROOT_TRACEGEN_RETRIES: usize = 8;
90 let agg_prover = &self.stark_prover.agg_prover;
91 let root_engine = self.root_prover.create_engine();
92 self.root_prover
93 .prove(stark_proof, &root_engine, MAX_ROOT_TRACEGEN_RETRIES, |p| {
94 agg_prover.wrap_proof(p, metadata)
95 })
96 }
97
98 pub fn prove_root(
99 &mut self,
100 input: StdIn<Val<SC>>,
101 def_inputs: &[DeferralInput],
102 ) -> Result<Proof<RootSC>>
103 where
104 <VB::VmConfig as VmExecutionConfig<Val<SC>>>::Executor: Executor<Val<SC>>
105 + MeteredExecutor<Val<SC>>
106 + PreflightExecutor<Val<SC>, VB::RecordArena>,
107 {
108 let (stark_proof, mut internal_metadata) = self.stark_prover.prove(input, def_inputs)?;
109 self.prove_root_from_vm_stark_proof(stark_proof, &mut internal_metadata)
110 }
111
112 #[cfg(feature = "evm-prove")]
113 pub fn prove_evm(
114 &mut self,
115 input: StdIn<Val<SC>>,
116 def_inputs: &[DeferralInput],
117 ) -> Result<crate::types::EvmProof>
118 where
119 <VB::VmConfig as VmExecutionConfig<Val<SC>>>::Executor: Executor<Val<SC>>
120 + MeteredExecutor<Val<SC>>
121 + PreflightExecutor<Val<SC>, VB::RecordArena>,
122 {
123 let root_proof = self.prove_root(input, def_inputs)?;
124 let evm_proof = self
125 .halo2_prover
126 .as_ref()
127 .unwrap()
128 .prove_for_evm(&root_proof);
129 Ok(evm_proof)
130 }
131}