Serialization for Plonky2 Signed and Main PODs (#234)

* WIP

* WIP

* Working serialization for both Mock and Plonky2 versions of Signed and Main Pods

* Restore useful comment about serialized_proof()

* Use plonky2 serialization for signatures and proofs

* Add schema renames for Serialized SignedPod/MainPod types

* Break out utility function for generating common circuit data

* Review feedback fixes
This commit is contained in:
Rob Knight 2025-05-19 02:22:38 -07:00 committed by GitHub
parent def0730462
commit de9b206852
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 381 additions and 115 deletions

View file

@ -2,6 +2,7 @@ pub mod operation;
pub mod statement;
use std::{any::Any, sync::Arc};
use base64::{prelude::BASE64_STANDARD, Engine};
use itertools::Itertools;
pub use operation::*;
use plonky2::{
@ -9,10 +10,11 @@ use plonky2::{
iop::witness::PartialWitness,
plonk::{
circuit_builder::CircuitBuilder,
circuit_data::CircuitConfig,
circuit_data::{CircuitConfig, CommonCircuitData},
config::Hasher,
proof::{Proof, ProofWithPublicInputs},
},
util::serialization::{Buffer, Read},
};
pub use statement::*;
@ -219,7 +221,7 @@ fn fill_pad<T: Clone>(v: &mut Vec<T>, pad_value: T, len: usize) {
}
}
fn pad_statement(params: &Params, s: &mut Statement) {
pub fn pad_statement(params: &Params, s: &mut Statement) {
fill_pad(&mut s.1, StatementArg::None, params.max_statement_args)
}
@ -454,12 +456,14 @@ impl PodProver for Prover {
}
}
pub type MainPodProof = Proof<F, C, D>;
#[derive(Clone, Debug)]
pub struct MainPod {
params: Params,
id: PodId,
public_statements: Vec<Statement>,
proof: Proof<F, C, D>,
proof: MainPodProof,
}
/// Convert a Statement into middleware::Statement and replace references to SELF by `self_id`.
@ -481,6 +485,23 @@ pub(crate) fn normalize_statement(statement: &Statement, self_id: PodId) -> midd
.unwrap()
}
// This is a helper function to get the CommonCircuitData necessary to decode
// a serialized proof. At some point in the future, this data may be available
// as a constant or with static initialization, but in the meantime we can
// generate it on-demand.
fn get_common_data(params: &Params) -> Result<CommonCircuitData<F, D>, Error> {
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let _main_pod = MainPodVerifyCircuit {
params: params.clone(),
}
.eval(&mut builder)
.map_err(|e| Error::custom(format!("Failed to evaluate MainPodVerifyCircuit: {}", e)))?;
let data = builder.build::<C>();
Ok(data.common)
}
impl MainPod {
fn _verify(&self) -> Result<()> {
// 2. get the id out of the public statements
@ -505,6 +526,48 @@ impl MainPod {
})
.map_err(|e| Error::custom(format!("MainPod proof verification failure: {:?}", e)))
}
pub fn proof(&self) -> MainPodProof {
self.proof.clone()
}
pub fn params(&self) -> &Params {
&self.params
}
pub(crate) fn new(
proof: MainPodProof,
public_statements: Vec<Statement>,
id: PodId,
params: Params,
) -> Self {
Self {
params,
id,
public_statements,
proof,
}
}
pub fn decode_proof(proof: &str, params: &Params) -> Result<MainPodProof, Error> {
let decoded = BASE64_STANDARD.decode(proof).map_err(|e| {
Error::custom(format!(
"Failed to decode proof from base64: {}. Value: {}",
e, proof
))
})?;
let mut buf = Buffer::new(&decoded);
let common = get_common_data(params)?;
let proof = buf.read_proof(&common).map_err(|e| {
Error::custom(format!(
"Failed to read proof from buffer: {}. Value: {}",
e, proof
))
})?;
Ok(proof)
}
}
impl Pod for MainPod {
@ -526,7 +589,10 @@ impl Pod for MainPod {
}
fn serialized_proof(&self) -> String {
todo!()
let mut buffer = Vec::new();
use plonky2::util::serialization::Write;
buffer.write_proof(&self.proof).unwrap();
BASE64_STANDARD.encode(buffer)
}
}