openvm_sdk/keygen/
static_verifier.rs

1use std::sync::Arc;
2
3use openvm_continuations::{RootSC, SC};
4use openvm_stark_backend::{keygen::types::MultiStarkVerifyingKey, proof::Proof};
5use openvm_static_verifier::{
6    compute_dag_onion_commit, log_heights_per_air_from_proof, Halo2Params, Halo2ParamsReader,
7    Halo2WrapperProvingKey, StaticVerifierCircuit, StaticVerifierProvingKey, StaticVerifierShape,
8};
9
10use crate::{config::Halo2Config, keygen::Halo2ProvingKey};
11
12/// Generate a [`Halo2ProvingKey`] (static verifier + wrapper) by running a
13/// dummy root proof through the pipeline.
14///
15/// This is the self-contained keygen flow:
16/// 1. Build a [`StaticVerifierProvingKey`] from the root VK and proof shape
17/// 2. Generate a dummy snark from the static verifier
18/// 3. Build a [`Halo2WrapperProvingKey`] (auto-tuned or fixed `k`)
19/// 4. Return the composite [`Halo2ProvingKey`]
20#[tracing::instrument(level = "info", fields(group = "halo2_keygen"), skip_all)]
21pub fn keygen_halo2(
22    halo2_config: &Halo2Config,
23    reader: &impl Halo2ParamsReader,
24    shape: StaticVerifierShape,
25    internal_recursive_vk: &MultiStarkVerifyingKey<SC>,
26    root_vk: &MultiStarkVerifyingKey<RootSC>,
27    dummy_root_proof: &Proof<RootSC>,
28) -> Halo2ProvingKey {
29    shape.assert_onchain_verifier_supported();
30
31    let params = reader.read_params(shape.k);
32
33    let verifier = keygen_static_verifier(
34        &params,
35        shape,
36        internal_recursive_vk,
37        root_vk,
38        dummy_root_proof,
39    );
40
41    let dummy_snark = verifier.generate_dummy_snark(reader);
42
43    let wrapper = if let Some(wrapper_k) = halo2_config.wrapper_k {
44        Halo2WrapperProvingKey::keygen(&reader.read_params(wrapper_k), dummy_snark)
45    } else {
46        Halo2WrapperProvingKey::keygen_auto_tune(reader, dummy_snark)
47    };
48
49    Halo2ProvingKey {
50        verifier: Arc::new(verifier),
51        wrapper: Arc::new(wrapper),
52        profiling: halo2_config.profiling,
53    }
54}
55
56/// Generate a [`StaticVerifierProvingKey`] from a root VK, heights, and a
57/// dummy root proof. This is the lower-level keygen without the wrapper.
58pub fn keygen_static_verifier(
59    params: &Halo2Params,
60    shape: StaticVerifierShape,
61    internal_recursive_vk: &MultiStarkVerifyingKey<SC>,
62    root_vk: &MultiStarkVerifyingKey<RootSC>,
63    dummy_root_proof: &Proof<RootSC>,
64) -> StaticVerifierProvingKey {
65    let log_heights = log_heights_per_air_from_proof(dummy_root_proof);
66    let onion_commit = compute_dag_onion_commit(internal_recursive_vk);
67
68    let circuit = StaticVerifierCircuit::try_new(root_vk.clone(), onion_commit, &log_heights)
69        .expect("Failed to construct StaticVerifierCircuit");
70
71    StaticVerifierProvingKey::keygen(params, shape, circuit, dummy_root_proof)
72}