Implement generic serialization/deserialization (#260)
* complete general serialization * bump default params temporarily * disable recursion in great_boy_pod example
This commit is contained in:
parent
c66506c048
commit
621f8be6b5
14 changed files with 392 additions and 253 deletions
|
|
@ -46,6 +46,8 @@ use super::serialization::*;
|
|||
// types would come from the plonky3 backend.
|
||||
#[cfg(feature = "backend_plonky2")]
|
||||
pub use crate::backends::plonky2::basetypes::*;
|
||||
#[cfg(feature = "backend_plonky2")]
|
||||
pub use crate::backends::plonky2::{Error as BackendError, Result as BackendResult};
|
||||
use crate::middleware::{Params, ToFields, Value};
|
||||
|
||||
pub const HASH_SIZE: usize = 4;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
//! the backend.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use strum_macros::FromRepr;
|
||||
mod basetypes;
|
||||
use std::{
|
||||
cmp::{Ordering, PartialEq, PartialOrd},
|
||||
|
|
@ -15,6 +17,7 @@ pub mod containers;
|
|||
mod custom;
|
||||
mod error;
|
||||
mod operation;
|
||||
mod pod_deserialization;
|
||||
pub mod serialization;
|
||||
mod statement;
|
||||
use std::{any::Any, collections::HashMap, fmt};
|
||||
|
|
@ -24,6 +27,7 @@ pub use custom::*;
|
|||
use dyn_clone::DynClone;
|
||||
pub use error::*;
|
||||
pub use operation::*;
|
||||
pub use pod_deserialization::*;
|
||||
use serialization::*;
|
||||
pub use statement::*;
|
||||
|
||||
|
|
@ -565,7 +569,7 @@ impl ToFields for PodId {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, FromRepr, Serialize, Deserialize, JsonSchema)]
|
||||
pub enum PodType {
|
||||
None = 0,
|
||||
MockSigned = 1,
|
||||
|
|
@ -636,7 +640,8 @@ impl Default for Params {
|
|||
max_signed_pod_values: 8,
|
||||
max_public_statements: 10,
|
||||
num_public_statements_id: 16,
|
||||
max_statement_args: 5,
|
||||
// TODO: Reduce to 5 or less after https://github.com/0xPARC/pod2/issues/229
|
||||
max_statement_args: 6,
|
||||
max_operation_args: 5,
|
||||
max_custom_predicate_batches: 2,
|
||||
max_custom_predicate_verifications: 5,
|
||||
|
|
@ -735,6 +740,8 @@ pub trait Pod: fmt::Debug + DynClone + Any {
|
|||
fn params(&self) -> &Params;
|
||||
fn verify(&self) -> Result<(), Box<DynError>>;
|
||||
fn id(&self) -> PodId;
|
||||
/// Return a uuid of the pod type and its name. The name is only used as metadata.
|
||||
fn pod_type(&self) -> (usize, &'static str);
|
||||
/// Statements as internally generated, where self-referencing arguments use SELF in the
|
||||
/// anchored key. The serialization of these statements is used to calculate the id.
|
||||
fn pub_self_statements(&self) -> Vec<Statement>;
|
||||
|
|
@ -746,6 +753,9 @@ pub trait Pod: fmt::Debug + DynClone + Any {
|
|||
.map(|statement| normalize_statement(&statement, self.id()))
|
||||
.collect()
|
||||
}
|
||||
/// Return this Pods data serialized into a json value. This serialization can skip `params,
|
||||
/// id, vds_root`
|
||||
fn serialize_data(&self) -> serde_json::Value;
|
||||
/// Extract key-values from ValueOf public statements
|
||||
fn kvs(&self) -> HashMap<AnchoredKey, Value> {
|
||||
self.pub_statements()
|
||||
|
|
@ -767,7 +777,7 @@ pub trait Pod: fmt::Debug + DynClone + Any {
|
|||
// reconstruct the proof.
|
||||
// It is an important principle that this data is opaque to the front-end
|
||||
// and any third-party code.
|
||||
fn serialized_proof(&self) -> String;
|
||||
// fn serialized_proof(&self) -> String;
|
||||
}
|
||||
|
||||
// impl Clone for Box<dyn Pod>
|
||||
|
|
@ -810,11 +820,14 @@ impl Pod for NonePod {
|
|||
fn id(&self) -> PodId {
|
||||
PodId(EMPTY_HASH)
|
||||
}
|
||||
fn pod_type(&self) -> (usize, &'static str) {
|
||||
(PodType::None as usize, "None")
|
||||
}
|
||||
fn pub_self_statements(&self) -> Vec<Statement> {
|
||||
Vec::new()
|
||||
}
|
||||
fn serialized_proof(&self) -> String {
|
||||
"".to_string()
|
||||
fn serialize_data(&self) -> serde_json::Value {
|
||||
serde_json::Value::Null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
93
src/middleware/pod_deserialization.rs
Normal file
93
src/middleware/pod_deserialization.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{LazyLock, Mutex},
|
||||
};
|
||||
|
||||
use crate::middleware::{
|
||||
BackendResult, Error, Hash, Params, Pod, PodId, PodType, RecursivePod, Result,
|
||||
};
|
||||
|
||||
type DeserializeFn = fn(
|
||||
params: Params,
|
||||
id: PodId,
|
||||
vds_root: Hash,
|
||||
data: serde_json::Value,
|
||||
) -> BackendResult<Box<dyn RecursivePod>>;
|
||||
|
||||
static DESERIALIZERS: LazyLock<Mutex<HashMap<usize, DeserializeFn>>> =
|
||||
LazyLock::new(backend::deserializers_default);
|
||||
|
||||
pub fn register_pod_deserializer(pod_type: usize, deserialize_fn: DeserializeFn) {
|
||||
DESERIALIZERS
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(pod_type, deserialize_fn);
|
||||
}
|
||||
|
||||
pub fn deserialize_pod(
|
||||
pod_type: usize,
|
||||
params: Params,
|
||||
id: PodId,
|
||||
vds_root: Hash,
|
||||
data: serde_json::Value,
|
||||
) -> Result<Box<dyn RecursivePod>> {
|
||||
let deserialize_fn: DeserializeFn =
|
||||
*DESERIALIZERS
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get(&pod_type)
|
||||
.ok_or(Error::custom(format!(
|
||||
"pod deserializer for pod_type={} not registered. See https://github.com/0xPARC/pod2/wiki/PodType for pod type assignments.",
|
||||
pod_type
|
||||
)))?;
|
||||
|
||||
deserialize_fn(params, id, vds_root, data)
|
||||
.map_err(|e| Error::custom(format!("deserialize error: {:?}", e)))
|
||||
}
|
||||
|
||||
pub fn deserialize_signed_pod(
|
||||
pod_type: usize,
|
||||
id: PodId,
|
||||
data: serde_json::Value,
|
||||
) -> Result<Box<dyn Pod>> {
|
||||
backend::deserialize_signed_pod(pod_type, id, data)
|
||||
}
|
||||
|
||||
#[cfg(feature = "backend_plonky2")]
|
||||
mod backend {
|
||||
use super::*;
|
||||
use crate::backends::plonky2::{
|
||||
emptypod::EmptyPod,
|
||||
mainpod::MainPod,
|
||||
mock::{emptypod::MockEmptyPod, mainpod::MockMainPod, signedpod::MockSignedPod},
|
||||
signedpod::SignedPod,
|
||||
};
|
||||
|
||||
pub(super) fn deserializers_default() -> Mutex<HashMap<usize, DeserializeFn>> {
|
||||
let mut map: HashMap<usize, DeserializeFn> = HashMap::new();
|
||||
map.insert(PodType::Empty as usize, EmptyPod::deserialize);
|
||||
map.insert(PodType::Main as usize, MainPod::deserialize);
|
||||
map.insert(PodType::MockEmpty as usize, MockEmptyPod::deserialize);
|
||||
map.insert(PodType::MockMain as usize, MockMainPod::deserialize);
|
||||
Mutex::new(map)
|
||||
}
|
||||
|
||||
pub(super) fn deserialize_signed_pod(
|
||||
pod_type: usize,
|
||||
id: PodId,
|
||||
data: serde_json::Value,
|
||||
) -> Result<Box<dyn Pod>> {
|
||||
if pod_type == PodType::MockSigned as usize {
|
||||
MockSignedPod::deserialize(id, data)
|
||||
.map_err(|e| Error::custom(format!("deserialize error: {:?}", e)))
|
||||
} else if pod_type == PodType::Signed as usize {
|
||||
SignedPod::deserialize(id, data)
|
||||
.map_err(|e| Error::custom(format!("deserialize error: {:?}", e)))
|
||||
} else {
|
||||
Err(Error::custom(format!(
|
||||
"unexpected pod_type={} for deserialize_signed_pod",
|
||||
pod_type
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue