* feat: add SignedPodVerify test * unify circuits style * more clear sizes * get operation_verify test working * be consistent with names
246 lines
6.8 KiB
Rust
246 lines
6.8 KiB
Rust
//! The middleware includes the type definitions and the traits used to connect the frontend and
|
|
//! the backend.
|
|
|
|
mod basetypes;
|
|
pub mod containers;
|
|
mod custom;
|
|
mod operation;
|
|
pub mod serialization;
|
|
mod statement;
|
|
pub use basetypes::*;
|
|
pub use custom::*;
|
|
pub use operation::*;
|
|
use schemars::JsonSchema;
|
|
pub use statement::*;
|
|
|
|
use anyhow::Result;
|
|
use dyn_clone::DynClone;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::any::Any;
|
|
use std::collections::HashMap;
|
|
use std::fmt;
|
|
|
|
pub const SELF: PodId = PodId(SELF_ID_HASH);
|
|
|
|
impl fmt::Display for PodId {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
if *self == SELF {
|
|
write!(f, "self")
|
|
} else if self.0 == EMPTY_HASH {
|
|
write!(f, "null")
|
|
} else {
|
|
write!(f, "{}", self.0)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// AnchoredKey is a tuple containing (OriginId: PodId, key: Hash)
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
pub struct AnchoredKey(pub PodId, pub Hash);
|
|
|
|
impl AnchoredKey {
|
|
pub fn origin(&self) -> PodId {
|
|
self.0
|
|
}
|
|
pub fn key(&self) -> Hash {
|
|
self.1
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for AnchoredKey {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(f, "{}.{}", self.0, self.1)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// An entry consists of a key-value pair.
|
|
pub type Entry = (String, Value);
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default, Serialize, Deserialize, JsonSchema)]
|
|
pub struct PodId(pub Hash);
|
|
|
|
impl ToFields for PodId {
|
|
fn to_fields(&self, params: &Params) -> Vec<F> {
|
|
self.0.to_fields(params)
|
|
}
|
|
}
|
|
|
|
pub enum PodType {
|
|
None = 0,
|
|
MockSigned = 1,
|
|
MockMain = 2,
|
|
Signed = 3,
|
|
Main = 4,
|
|
}
|
|
|
|
impl From<PodType> for Value {
|
|
fn from(v: PodType) -> Self {
|
|
Value::from(v as i64)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub struct Params {
|
|
pub max_input_signed_pods: usize,
|
|
pub max_input_main_pods: usize,
|
|
pub max_statements: usize,
|
|
pub max_signed_pod_values: usize,
|
|
pub max_public_statements: usize,
|
|
pub max_statement_args: usize,
|
|
pub max_operation_args: usize,
|
|
// max number of statements that can be ANDed or ORed together
|
|
// in a custom predicate
|
|
pub max_custom_predicate_arity: usize,
|
|
pub max_custom_batch_size: usize,
|
|
// maximum depth for merkle tree gates
|
|
pub max_depth_mt_gate: usize,
|
|
}
|
|
|
|
impl Default for Params {
|
|
fn default() -> Self {
|
|
Self {
|
|
max_input_signed_pods: 3,
|
|
max_input_main_pods: 3,
|
|
max_statements: 20,
|
|
max_signed_pod_values: 8,
|
|
max_public_statements: 10,
|
|
max_statement_args: 5,
|
|
max_operation_args: 5,
|
|
max_custom_predicate_arity: 5,
|
|
max_custom_batch_size: 5,
|
|
max_depth_mt_gate: 32,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Params {
|
|
pub fn max_priv_statements(&self) -> usize {
|
|
self.max_statements - self.max_public_statements
|
|
}
|
|
|
|
pub const fn statement_tmpl_arg_size() -> usize {
|
|
2 * HASH_SIZE + 1
|
|
}
|
|
|
|
pub const fn predicate_size() -> usize {
|
|
HASH_SIZE + 2
|
|
}
|
|
|
|
pub const fn operation_type_size() -> usize {
|
|
HASH_SIZE + 2
|
|
}
|
|
|
|
pub fn statement_size(&self) -> usize {
|
|
Self::predicate_size() + STATEMENT_ARG_F_LEN * self.max_statement_args
|
|
}
|
|
|
|
pub fn operation_size(&self) -> usize {
|
|
Self::operation_type_size() + OPERATION_ARG_F_LEN * self.max_operation_args
|
|
}
|
|
|
|
pub const fn statement_tmpl_size(&self) -> usize {
|
|
Self::predicate_size() + self.max_statement_args * Self::statement_tmpl_arg_size()
|
|
}
|
|
|
|
pub fn custom_predicate_size(&self) -> usize {
|
|
self.max_custom_predicate_arity * self.statement_tmpl_size() + 2
|
|
}
|
|
|
|
pub fn custom_predicate_batch_size_field_elts(&self) -> usize {
|
|
self.max_custom_batch_size * self.custom_predicate_size()
|
|
}
|
|
|
|
pub fn print_serialized_sizes(&self) {
|
|
println!("Parameter sizes:");
|
|
println!(
|
|
" Statement template argument: {}",
|
|
Self::statement_tmpl_arg_size()
|
|
);
|
|
println!(" Predicate: {}", Self::predicate_size());
|
|
println!(" Statement template: {}", self.statement_tmpl_size());
|
|
println!(" Custom predicate: {}", self.custom_predicate_size());
|
|
println!(
|
|
" Custom predicate batch: {}",
|
|
self.custom_predicate_batch_size_field_elts()
|
|
);
|
|
println!();
|
|
}
|
|
}
|
|
|
|
pub trait Pod: fmt::Debug + DynClone {
|
|
fn verify(&self) -> bool;
|
|
fn id(&self) -> PodId;
|
|
fn pub_statements(&self) -> Vec<Statement>;
|
|
/// Extract key-values from ValueOf public statements
|
|
fn kvs(&self) -> HashMap<AnchoredKey, Value> {
|
|
self.pub_statements()
|
|
.into_iter()
|
|
.filter_map(|st| match st {
|
|
Statement::ValueOf(ak, v) => Some((ak, v)),
|
|
_ => None,
|
|
})
|
|
.collect()
|
|
}
|
|
// Used for downcasting
|
|
fn into_any(self: Box<Self>) -> Box<dyn Any>;
|
|
// Front-end Pods keep references to middleware Pods. Most of the
|
|
// middleware data can be derived directly from front-end data, but the
|
|
// "proof" data is only created at the point of proving/signing, and
|
|
// cannot be reconstructed. As such, we need to serialize it whenever
|
|
// we serialize a front-end Pod. Since the front-end does not understand
|
|
// the implementation details of the middleware, this method allows the
|
|
// middleware to provide some serialized data that can be used to
|
|
// reconstruct the proof.
|
|
fn serialized_proof(&self) -> String;
|
|
}
|
|
|
|
// impl Clone for Box<dyn SignedPod>
|
|
dyn_clone::clone_trait_object!(Pod);
|
|
|
|
pub trait PodSigner {
|
|
fn sign(&mut self, params: &Params, kvs: &HashMap<Hash, Value>) -> Result<Box<dyn Pod>>;
|
|
}
|
|
|
|
/// This is a filler type that fulfills the Pod trait and always verifies. It's empty. This
|
|
/// can be used to simulate padding in a circuit.
|
|
#[derive(Debug, Clone)]
|
|
pub struct NonePod {}
|
|
|
|
impl Pod for NonePod {
|
|
fn verify(&self) -> bool {
|
|
true
|
|
}
|
|
fn id(&self) -> PodId {
|
|
PodId(EMPTY_HASH)
|
|
}
|
|
fn pub_statements(&self) -> Vec<Statement> {
|
|
Vec::new()
|
|
}
|
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
|
self
|
|
}
|
|
fn serialized_proof(&self) -> String {
|
|
"".to_string()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct MainPodInputs<'a> {
|
|
pub signed_pods: &'a [&'a Box<dyn Pod>],
|
|
pub main_pods: &'a [&'a Box<dyn Pod>],
|
|
pub statements: &'a [Statement],
|
|
pub operations: &'a [Operation],
|
|
/// Statements that need to be made public (they can come from input pods or input
|
|
/// statements)
|
|
pub public_statements: &'a [Statement],
|
|
}
|
|
|
|
pub trait PodProver {
|
|
fn prove(&mut self, params: &Params, inputs: MainPodInputs) -> Result<Box<dyn Pod>>;
|
|
}
|
|
|
|
pub trait ToFields {
|
|
/// returns Vec<F> representation of the type
|
|
fn to_fields(&self, params: &Params) -> Vec<F>;
|
|
}
|