openvm_sdk/prover/
evm.rs

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
19/// EVM prover that produces a root STARK proof with Halo2 wrapping.
20///
21/// [`EvmProver::prove_root`] outputs the unwrapped root STARK, while
22/// [`EvmProver::prove_root_from_vm_stark_proof`] outputs the unwrapped root STARK from an
23/// intermediate STARK proof, for more finegrained separation of work
24/// [`EvmProver::prove_evm`] produces an [`EvmProof`](crate::types::EvmProof)
25/// suitable for on-chain verification.
26pub 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}