Serialization of Signed and Main Pods (#128)

This commit is contained in:
Rob Knight 2025-03-21 14:42:16 +01:00 committed by GitHub
parent fee70af12b
commit 9afc43675d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 817 additions and 189 deletions

View file

@ -2,6 +2,10 @@
//! `backend_plonky2` feature is enabled.
//! See src/middleware/basetypes.rs for more details.
use crate::middleware::serialization::{
deserialize_hash_tuple, deserialize_value_tuple, serialize_hash_tuple, serialize_value_tuple,
};
use crate::middleware::{Params, ToFields};
use anyhow::{anyhow, Error, Result};
use hex::{FromHex, FromHexError};
use plonky2::field::goldilocks_field::GoldilocksField;
@ -10,11 +14,11 @@ use plonky2::hash::poseidon::PoseidonHash;
use plonky2::plonk::config::Hasher;
use plonky2::plonk::config::PoseidonGoldilocksConfig;
use plonky2::plonk::proof::Proof as Plonky2Proof;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::cmp::{Ord, Ordering};
use std::fmt;
use crate::middleware::{Params, ToFields};
use crate::backends::counter;
/// F is the native field we use everywhere. Currently it's Goldilocks from plonky2
@ -34,8 +38,18 @@ pub const EMPTY_VALUE: Value = Value([F::ZERO, F::ZERO, F::ZERO, F::ZERO]);
pub const SELF_ID_HASH: Hash = Hash([F::ONE, F::ZERO, F::ZERO, F::ZERO]);
pub const EMPTY_HASH: Hash = Hash([F::ZERO, F::ZERO, F::ZERO, F::ZERO]);
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq)]
pub struct Value(pub [F; VALUE_SIZE]);
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[schemars(rename = "MiddlewareValue")]
pub struct Value(
#[serde(
serialize_with = "serialize_value_tuple",
deserialize_with = "deserialize_value_tuple"
)]
// We know that Serde will serialize and deserialize this as a string, so we can
// use the JsonSchema to validate the format.
#[schemars(with = "String", regex(pattern = r"^[0-9a-fA-F]{64}$"))]
pub [F; VALUE_SIZE],
);
impl ToFields for Value {
fn to_fields(&self, _params: &Params) -> Vec<F> {
@ -117,8 +131,15 @@ impl fmt::Display for Value {
}
}
#[derive(Clone, Copy, Debug, Default, Hash, Eq, PartialEq)]
pub struct Hash(pub [F; HASH_SIZE]);
#[derive(Clone, Copy, Debug, Default, Hash, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Hash(
#[serde(
serialize_with = "serialize_hash_tuple",
deserialize_with = "deserialize_hash_tuple"
)]
#[schemars(with = "String", regex(pattern = r"^[0-9a-fA-F]{64}$"))]
pub [F; HASH_SIZE],
);
pub fn hash_value(input: &Value) -> Hash {
hash_fields(&input.0)

View file

@ -1,8 +1,10 @@
use anyhow::{anyhow, Result};
use base64::prelude::*;
use itertools::Itertools;
use log::error;
use plonky2::hash::poseidon::PoseidonHash;
use plonky2::plonk::config::Hasher;
use serde::{Deserialize, Serialize};
use std::any::Any;
use std::fmt;
@ -27,14 +29,14 @@ impl PodProver for MockProver {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MockMainPod {
params: Params,
id: PodId,
input_signed_pods: Vec<Box<dyn Pod>>,
input_main_pods: Vec<Box<dyn Pod>>,
// input_signed_pods: Vec<Box<dyn Pod>>,
// input_main_pods: Vec<Box<dyn Pod>>,
// New statements introduced by this pod
input_statements: Vec<Statement>,
// input_statements: Vec<Statement>,
public_statements: Vec<Statement>,
operations: Vec<Operation>,
// All statements (inherited + new)
@ -258,7 +260,7 @@ impl MockMainPod {
.map(|mid_arg| Self::find_op_arg(statements, mid_arg))
.collect::<Result<Vec<_>>>()?;
Self::pad_operation_args(params, &mut args);
operations.push(Operation(op.code(), args));
operations.push(Operation(op.predicate(), args));
}
Ok(operations)
}
@ -332,9 +334,9 @@ impl MockMainPod {
Ok(Self {
params: params.clone(),
id,
input_signed_pods,
input_main_pods,
input_statements,
// input_signed_pods,
// input_main_pods,
// input_statements,
public_statements,
statements,
operations,
@ -360,6 +362,15 @@ impl MockMainPod {
fn pad_operation_args(params: &Params, args: &mut Vec<OperationArg>) {
fill_pad(args, OperationArg::None, params.max_operation_args)
}
pub fn deserialize(serialized: String) -> Result<Self> {
let proof = String::from_utf8(BASE64_STANDARD.decode(&serialized)?)
.map_err(|e| anyhow::anyhow!("Invalid base64 encoding: {}", e))?;
let pod: MockMainPod = serde_json::from_str(&proof)
.map_err(|e| anyhow::anyhow!("Failed to parse proof: {}", e))?;
Ok(pod)
}
}
pub fn hash_statements(statements: &[Statement], _params: &Params) -> middleware::Hash {
@ -485,6 +496,10 @@ impl Pod for MockMainPod {
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
fn serialized_proof(&self) -> String {
BASE64_STANDARD.encode(serde_json::to_string(self).unwrap())
}
}
#[cfg(test)]

View file

@ -1,10 +1,10 @@
use anyhow::Result;
use std::fmt;
use super::Statement;
use crate::middleware::{self, OperationType};
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum OperationArg {
None,
Index(usize),
@ -16,7 +16,7 @@ impl OperationArg {
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Operation(pub OperationType, pub Vec<OperationArg>);
impl Operation {

View file

@ -1,11 +1,12 @@
use anyhow::{anyhow, Result};
use serde::{Deserialize, Serialize};
use std::fmt;
use crate::middleware::{
self, AnchoredKey, NativePredicate, Params, Predicate, StatementArg, ToFields,
};
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Statement(pub Predicate, pub Vec<StatementArg>);
impl Statement {

View file

@ -44,6 +44,16 @@ pub struct MockSignedPod {
dict: Dictionary,
}
impl MockSignedPod {
pub fn deserialize(id: PodId, signature: String, dict: Dictionary) -> Self {
Self {
id,
signature,
dict,
}
}
}
impl Pod for MockSignedPod {
fn verify(&self) -> bool {
// 1. Verify type
@ -100,6 +110,10 @@ impl Pod for MockSignedPod {
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
fn serialized_proof(&self) -> String {
self.signature.to_string()
}
}
#[cfg(test)]