openvm_continuations/static_verifier/
mod.rs

1use openvm_circuit::arch::PROGRAM_CACHED_TRACE_INDEX;
2use openvm_native_compiler::prelude::*;
3use openvm_native_recursion::{
4    challenger::multi_field32::MultiField32ChallengerVariable,
5    config::outer::{new_from_outer_multi_vk, OuterConfig},
6    digest::DigestVariable,
7    fri::TwoAdicFriPcsVariable,
8    halo2::DslOperations,
9    stark::StarkVerifier,
10    utils::const_fri_config,
11    vars::StarkProofVariable,
12    witness::Witnessable,
13};
14use openvm_stark_backend::keygen::types::MultiStarkVerifyingKey;
15use openvm_stark_sdk::{
16    config::FriParameters, openvm_stark_backend::proof::Proof, p3_bn254_fr::Bn254Fr,
17};
18
19use crate::{
20    verifier::{
21        common::{
22            assert_single_segment_vm_exit_successfully_with_connector_air_id, types::SpecialAirIds,
23        },
24        root::types::RootVmVerifierPvs,
25        utils::compress_babybear_var_to_bn254,
26    },
27    RootSC,
28};
29/// Custom public values handler for static verifier.
30/// This trait implementation defines what the public values of the
31/// final EVM proof will be.
32pub trait StaticVerifierPvHandler {
33    /// Returns the number of public values, as [Bn254Fr] field elements.
34    fn handle_public_values(
35        &self,
36        builder: &mut Builder<OuterConfig>,
37        input: &StarkProofVariable<OuterConfig>,
38        special_air_ids: &SpecialAirIds,
39    ) -> usize;
40}
41
42pub struct DefaultStaticVerifierPvHandler;
43
44impl StaticVerifierPvHandler for DefaultStaticVerifierPvHandler {
45    fn handle_public_values(
46        &self,
47        builder: &mut Builder<OuterConfig>,
48        input: &StarkProofVariable<OuterConfig>,
49        special_air_ids: &SpecialAirIds,
50    ) -> usize {
51        let pv_air = builder.get(&input.per_air, special_air_ids.public_values_air_id);
52        let public_values: Vec<_> = pv_air
53            .public_values
54            .vec()
55            .into_iter()
56            .map(|x| builder.cast_felt_to_var(x))
57            .collect();
58        let pvs = RootVmVerifierPvs::from_flatten(public_values);
59        let exe_commit = compress_babybear_var_to_bn254(builder, pvs.exe_commit);
60        let leaf_commit = compress_babybear_var_to_bn254(builder, pvs.leaf_verifier_commit);
61        let num_public_values = 2 + pvs.public_values.len();
62        builder.static_commit_public_value(0, exe_commit);
63        builder.static_commit_public_value(1, leaf_commit);
64        for (i, x) in pvs.public_values.into_iter().enumerate() {
65            builder.static_commit_public_value(i + 2, x);
66        }
67        num_public_values
68    }
69}
70
71/// Config to generate static verifier DSL operations.
72pub struct StaticVerifierConfig {
73    pub root_verifier_fri_params: FriParameters,
74    pub special_air_ids: SpecialAirIds,
75    pub root_verifier_program_commit: [Bn254Fr; 1],
76}
77
78impl StaticVerifierConfig {
79    pub fn build_static_verifier_operations(
80        &self,
81        root_verifier_vk: &MultiStarkVerifyingKey<RootSC>,
82        proof: &Proof<RootSC>,
83        pv_handler: &impl StaticVerifierPvHandler,
84    ) -> DslOperations<OuterConfig> {
85        let mut builder = Builder::<OuterConfig>::default();
86        builder.flags.static_only = true;
87        let num_public_values = {
88            builder.cycle_tracker_start("VerifierProgram");
89            let input = proof.read(&mut builder);
90            self.verify_root_proof(&mut builder, root_verifier_vk, &input);
91
92            let num_public_values =
93                pv_handler.handle_public_values(&mut builder, &input, &self.special_air_ids);
94            builder.cycle_tracker_end("VerifierProgram");
95            num_public_values
96        };
97        DslOperations {
98            operations: builder.operations,
99            num_public_values,
100        }
101    }
102
103    /// `root_verifier_vk` is the verifying key of the root verifier STARK circuit.
104    /// `root_verifier_fri_params` are the FRI parameters used to prove the root
105    /// verifier STARK circuit.
106    fn verify_root_proof(
107        &self,
108        builder: &mut Builder<OuterConfig>,
109        root_verifier_vk: &MultiStarkVerifyingKey<RootSC>,
110        input: &StarkProofVariable<OuterConfig>,
111    ) {
112        let advice = new_from_outer_multi_vk(root_verifier_vk);
113        let pcs = TwoAdicFriPcsVariable {
114            config: const_fri_config(builder, &self.root_verifier_fri_params),
115        };
116        StarkVerifier::verify::<MultiField32ChallengerVariable<_>>(builder, &pcs, &advice, input);
117        {
118            // Program AIR is the only AIR with a cached trace. The cached trace index doesn't
119            // change after reordering.
120            let t_id = RVar::from(PROGRAM_CACHED_TRACE_INDEX);
121            let commit = builder.get(&input.commitments.main_trace, t_id);
122            let commit = if let DigestVariable::Var(commit_arr) = commit {
123                builder.get(&commit_arr, 0)
124            } else {
125                unreachable!()
126            };
127            builder.assert_var_eq(commit, self.root_verifier_program_commit[0]);
128        }
129        assert_single_segment_vm_exit_successfully_with_connector_air_id(
130            builder,
131            input,
132            self.special_air_ids.connector_air_id,
133        );
134    }
135}