1use halo2_base::{
2 gates::{
3 circuit::{builder::BaseCircuitBuilder, BaseCircuitParams, CircuitBuilderStage},
4 flex_gate::MultiPhaseThreadBreakPoints,
5 },
6 halo2_proofs::{
7 dev::MockProver,
8 halo2curves::bn256::{Bn256, Fr, G1Affine},
9 plonk::{create_proof, verify_proof, ProvingKey, VerifyingKey},
10 poly::{
11 commitment::ParamsProver,
12 kzg::{
13 commitment::{KZGCommitmentScheme, ParamsKZG},
14 multiopen::{ProverSHPLONK, VerifierSHPLONK},
15 strategy::SingleStrategy,
16 },
17 },
18 transcript::{
19 Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer,
20 },
21 },
22};
23use openvm_stark_sdk::{
24 config::baby_bear_bn254_poseidon2::BabyBearBn254Poseidon2Config as RootConfig,
25 openvm_stark_backend::proof::Proof,
26};
27use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng};
28use serde::{Deserialize, Serialize};
29
30use crate::{circuit::StaticVerifierCircuit, config::StaticVerifierShape};
31
32pub type Halo2Params = ParamsKZG<Bn256>;
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct Halo2ProvingMetadata {
41 pub config_params: BaseCircuitParams,
42 pub break_points: MultiPhaseThreadBreakPoints,
43 pub num_pvs: Vec<usize>,
44}
45
46#[derive(Debug, Clone)]
49pub struct Halo2ProvingPinning {
50 pub pk: ProvingKey<G1Affine>,
51 pub metadata: Halo2ProvingMetadata,
52}
53
54pub struct StaticVerifierProof {
56 pub proof_bytes: Vec<u8>,
57 pub public_inputs: Vec<Fr>,
58}
59
60impl StaticVerifierCircuit {
61 pub fn builder(
64 stage: CircuitBuilderStage,
65 shape: &StaticVerifierShape,
66 ) -> BaseCircuitBuilder<Fr> {
67 BaseCircuitBuilder::from_stage(stage)
68 .use_k(shape.k)
69 .use_lookup_bits(shape.lookup_bits)
70 .use_instance_columns(shape.instance_columns)
71 }
72
73 pub fn mock(&self, shape: &StaticVerifierShape, proof: &Proof<RootConfig>) {
78 let mut builder = Self::builder(CircuitBuilderStage::Mock, shape);
79 let public_inputs = self.populate(&mut builder, proof);
80
81 let _ = builder.calculate_params(Some(shape.minimum_rows));
82
83 let prover = MockProver::run(shape.k as u32, &builder, vec![public_inputs.to_vec()])
84 .expect("MockProver should initialize");
85 prover.assert_satisfied();
86 }
87
88 pub fn prove(
93 &self,
94 params: &Halo2Params,
95 pinning: &Halo2ProvingPinning,
96 shape: &StaticVerifierShape,
97 proof: &Proof<RootConfig>,
98 ) -> StaticVerifierProof {
99 let mut builder = BaseCircuitBuilder::prover(
100 pinning.metadata.config_params.clone(),
101 pinning.metadata.break_points.clone(),
102 );
103 builder = builder.use_instance_columns(shape.instance_columns);
104
105 let public_inputs = self.populate(&mut builder, proof);
106 let public_inputs = public_inputs.to_vec();
107
108 let rng = ChaCha20Rng::from_seed(Default::default());
109 let instances: &[&[Fr]] = &[&public_inputs];
110 let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]);
111 create_proof::<
112 KZGCommitmentScheme<Bn256>,
113 ProverSHPLONK<'_, Bn256>,
114 Challenge255<_>,
115 _,
116 Blake2bWrite<Vec<u8>, G1Affine, _>,
117 _,
118 >(
119 params,
120 &pinning.pk,
121 &[builder],
122 &[instances],
123 rng,
124 &mut transcript,
125 )
126 .expect("Halo2 proof generation should succeed");
127
128 StaticVerifierProof {
129 proof_bytes: transcript.finalize(),
130 public_inputs,
131 }
132 }
133
134 pub fn verify(
136 params: &Halo2Params,
137 vk: &VerifyingKey<G1Affine>,
138 proof: &StaticVerifierProof,
139 ) -> bool {
140 let verifier_params = params.verifier_params();
141 let strategy = SingleStrategy::new(params);
142 let mut transcript =
143 Blake2bRead::<_, _, Challenge255<_>>::init(proof.proof_bytes.as_slice());
144 let no_instance_cols: &[&[Fr]] = &[];
146 let ok = if proof.public_inputs.is_empty() {
147 verify_proof::<
148 KZGCommitmentScheme<Bn256>,
149 VerifierSHPLONK<'_, Bn256>,
150 Challenge255<G1Affine>,
151 Blake2bRead<&[u8], G1Affine, Challenge255<G1Affine>>,
152 SingleStrategy<'_, Bn256>,
153 >(
154 verifier_params,
155 vk,
156 strategy,
157 &[no_instance_cols],
158 &mut transcript,
159 )
160 } else {
161 let instances: &[&[Fr]] = &[&proof.public_inputs];
162 verify_proof::<
163 KZGCommitmentScheme<Bn256>,
164 VerifierSHPLONK<'_, Bn256>,
165 Challenge255<G1Affine>,
166 Blake2bRead<&[u8], G1Affine, Challenge255<G1Affine>>,
167 SingleStrategy<'_, Bn256>,
168 >(verifier_params, vk, strategy, &[instances], &mut transcript)
169 };
170 ok.is_ok()
171 }
172}
173
174impl Halo2ProvingPinning {
175 pub fn pk_to_bytes(&self) -> Vec<u8> {
177 use halo2_base::halo2_proofs::SerdeFormat;
178 self.pk.to_bytes(SerdeFormat::RawBytes)
179 }
180}