openvm_static_verifier/
codec.rs

1use std::io::{self, Read, Write};
2
3use halo2_base::{
4    gates::circuit::builder::BaseCircuitBuilder,
5    halo2_proofs::{
6        halo2curves::bn256::{Fr, G1Affine},
7        plonk::ProvingKey,
8        SerdeFormat,
9    },
10};
11use openvm_stark_sdk::openvm_stark_backend::codec::{Decode, Encode};
12use serde::{de::DeserializeOwned, Serialize};
13
14use crate::{
15    keygen::StaticVerifierProvingKey,
16    prover::{Halo2ProvingMetadata, Halo2ProvingPinning},
17    wrapper::Halo2WrapperProvingKey,
18};
19
20const MAX_JSON_SECTION_LEN: usize = 64 * 1024 * 1024;
21
22impl Encode for StaticVerifierProvingKey {
23    fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> {
24        write_json_section(writer, &(&self.circuit, &self.shape))?;
25        self.pinning.encode(writer)
26    }
27}
28
29impl Decode for StaticVerifierProvingKey {
30    fn decode<R: Read>(reader: &mut R) -> io::Result<Self> {
31        let (circuit, shape) = read_json_section(reader)?;
32        let pinning = Halo2ProvingPinning::decode(reader)?;
33        Ok(Self {
34            circuit,
35            pinning,
36            shape,
37        })
38    }
39}
40
41impl Encode for Halo2WrapperProvingKey {
42    fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> {
43        self.pinning.encode(writer)
44    }
45}
46
47impl Decode for Halo2WrapperProvingKey {
48    fn decode<R: Read>(reader: &mut R) -> io::Result<Self> {
49        Ok(Self {
50            pinning: Halo2ProvingPinning::decode(reader)?,
51        })
52    }
53}
54
55impl Encode for Halo2ProvingPinning {
56    fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> {
57        write_json_section(writer, &self.metadata)?;
58        self.pk.write(writer, SerdeFormat::RawBytes)
59    }
60}
61
62impl Decode for Halo2ProvingPinning {
63    fn decode<R: Read>(reader: &mut R) -> io::Result<Self> {
64        let metadata: Halo2ProvingMetadata = read_json_section(reader)?;
65        let pk = ProvingKey::<G1Affine>::read::<_, BaseCircuitBuilder<Fr>>(
66            reader,
67            SerdeFormat::RawBytes,
68            metadata.config_params.clone(),
69        )?;
70        Ok(Self { pk, metadata })
71    }
72}
73
74// Each JSON section is length-prefixed because it is followed by raw Halo2 proving-key bytes.
75fn write_json_section<W: Write, T: Serialize>(writer: &mut W, value: &T) -> io::Result<()> {
76    let bytes = serde_json::to_vec(value).map_err(io::Error::other)?;
77    writer.write_all(&(bytes.len() as u64).to_le_bytes())?;
78    writer.write_all(&bytes)
79}
80
81fn read_json_section<R: Read, T: DeserializeOwned>(reader: &mut R) -> io::Result<T> {
82    let mut len_bytes = [0u8; 8];
83    reader.read_exact(&mut len_bytes)?;
84    let len = usize::try_from(u64::from_le_bytes(len_bytes)).map_err(|_| {
85        io::Error::new(
86            io::ErrorKind::InvalidData,
87            "JSON section length overflows usize",
88        )
89    })?;
90    if len > MAX_JSON_SECTION_LEN {
91        return Err(io::Error::new(
92            io::ErrorKind::InvalidData,
93            "JSON section is too large",
94        ));
95    }
96    let mut bytes = vec![0u8; len];
97    reader.read_exact(&mut bytes)?;
98    serde_json::from_slice(&bytes).map_err(io::Error::other)
99}