snark_verifier_sdk/halo2/
utils.rs

1use halo2_base::halo2_proofs::{
2    halo2curves::bn256::{Bn256, Fr, G1Affine},
3    plonk::{Circuit, VerifyingKey},
4    poly::kzg::commitment::ParamsKZG,
5};
6use rand::{rngs::StdRng, SeedableRng};
7use snark_verifier::{
8    system::halo2::{compile, Config},
9    verifier::plonk::PlonkProtocol,
10};
11
12use crate::{Snark, SHPLONK};
13
14use super::gen_dummy_snark_from_vk;
15
16#[derive(Clone, Copy, Debug)]
17pub struct AggregationDependencyIntent<'a> {
18    pub vk: &'a VerifyingKey<G1Affine>,
19    pub num_instance: &'a [usize],
20    pub accumulator_indices: Option<&'a [(usize, usize)]>,
21    /// See [`AggregationDependencyIntentOwned::agg_vk_hash_data`].
22    pub agg_vk_hash_data: Option<((usize, usize), Fr)>,
23}
24
25#[derive(Clone, Debug)]
26pub struct AggregationDependencyIntentOwned {
27    pub vk: VerifyingKey<G1Affine>,
28    pub num_instance: Vec<usize>,
29    pub accumulator_indices: Option<Vec<(usize, usize)>>,
30    /// If this dependency is itself from a universal aggregation circuit, this should contain (index, agg_vkey_hash), where `index = (i,j)` is the pair recording that the agg_vkey_hash is located at `instances[i][j]`.
31    pub agg_vk_hash_data: Option<((usize, usize), Fr)>,
32}
33
34impl AggregationDependencyIntent<'_> {
35    /// Converts `self` into `PlonkProtocol`
36    pub fn compile(self, params: &ParamsKZG<Bn256>) -> PlonkProtocol<G1Affine> {
37        compile(
38            params,
39            self.vk,
40            Config::kzg()
41                .with_num_instance(self.num_instance.to_vec())
42                .with_accumulator_indices(self.accumulator_indices.map(|v| v.to_vec())),
43        )
44    }
45}
46
47/// This trait should be implemented on the minimal circuit configuration data necessary to
48/// completely determine an aggregation circuit
49/// (independent of circuit inputs or specific snarks to be aggregated).
50/// This is used to generate a _dummy_ instantiation of a concrete `Circuit` type for the purposes of key generation.
51/// This dummy instantiation just needs to have the correct arithmetization format, but the witnesses do not need to
52/// satisfy constraints.
53///
54/// This trait is specialized for aggregation circuits, which need to aggregate **dependency** snarks.
55/// The aggregation circuit should only depend on the verifying key of each dependency snark.
56pub trait KeygenAggregationCircuitIntent {
57    /// Concrete circuit type. Defaults to [`AggregationCircuit`].
58    type AggregationCircuit: Circuit<Fr>;
59
60    /// The **ordered** list of [`VerifyingKey`]s of the circuits to be aggregated.
61    fn intent_of_dependencies(&self) -> Vec<AggregationDependencyIntent>;
62
63    /// Builds a _dummy_ instantiation of `Self::AggregationCircuit` for the purposes of key generation.
64    /// Assumes that `snarks` is an ordered list of [`Snark`]s, where the `i`th snark corresponds to the `i`th [`VerifyingKey`] in `vk_of_dependencies`.
65    /// The `snarks` only need to have the correct witness sizes (e.g., proof length) but the
66    /// snarks do _not_ need to verify.
67    ///
68    /// May specify additional custom logic for building the aggregation circuit from the snarks.
69    fn build_keygen_circuit_from_snarks(self, snarks: Vec<Snark>) -> Self::AggregationCircuit;
70
71    /// Builds a _dummy_ instantiation of `Self::AggregationCircuit` for the purposes of key generation.
72    ///
73    /// Generates dummy snarks from the verifying keys in `vk_of_dependencies`, **assuming** that SHPLONK is
74    /// used for the multi-open scheme.
75    fn build_keygen_circuit_shplonk(self) -> Self::AggregationCircuit
76    where
77        Self: Sized,
78    {
79        let mut rng = StdRng::seed_from_u64(0u64);
80        let snarks =
81            self.intent_of_dependencies()
82                .into_iter()
83                .map(
84                    |AggregationDependencyIntent {
85                         vk,
86                         num_instance,
87                         accumulator_indices,
88                         agg_vk_hash_data,
89                     }| {
90                        let k = vk.get_domain().k();
91                        // In KZG `gen_dummy_snark_from_vk` calls `compile`, which only uses `params` for `params.k()` so we can just use a random untrusted setup.
92                        // Moreover since this is a dummy snark, the trusted setup shouldn't matter.
93                        let params = ParamsKZG::setup(k, &mut rng);
94                        let mut snark = gen_dummy_snark_from_vk::<SHPLONK>(
95                            &params,
96                            vk,
97                            num_instance.to_vec(),
98                            accumulator_indices.map(|v| v.to_vec()),
99                        );
100                        // We set the current agg_vk_hash in the dummy snark so that the final agg_vk_hash is correct at the end of keygen.
101                        if let Some(((i, j), agg_vk_hash)) = agg_vk_hash_data {
102                            assert!(
103                            i < snark.instances.len(),
104                            "Invalid agg_vk_hash index: ({i},{j}), num_instance: {num_instance:?}");
105                            assert!(j < snark.instances[i].len(),
106                            "Invalid agg_vk_hash index: ({i},{j}), num_instance: {num_instance:?}");
107                            snark.instances[i][j] = agg_vk_hash;
108                        }
109                        snark
110                    },
111                )
112                .collect();
113        self.build_keygen_circuit_from_snarks(snarks)
114    }
115}
116
117impl<'a> From<&'a AggregationDependencyIntentOwned> for AggregationDependencyIntent<'a> {
118    fn from(intent: &'a AggregationDependencyIntentOwned) -> Self {
119        Self {
120            vk: &intent.vk,
121            num_instance: &intent.num_instance,
122            accumulator_indices: intent.accumulator_indices.as_deref(),
123            agg_vk_hash_data: intent.agg_vk_hash_data,
124        }
125    }
126}