No Pod IDs (#394)
- middleware:
- Add `Statement::Intro`
- Add `SignedBy` native predicate and operation. The signature is auxiliary data to the operation
- Rename `PodSigner` to `Signer` with a new API (just for signing `RawValue`)
- Removed `NewEntry` operation. Use `ContainsFromEntries` instead
- Remove `KEY_SIGNER` and `KEY_TYPE` which are no longer used
- Merge `RecursivePod` and `Pod` traits
- Change the `Pod::deserialize_data` method to use `Self` instead of `Box<dyn Pod>`
- Extend `Pod` trait with these methods:
- `is_main`: when the pod is Main, in a (recursive) verification its vk will be checked to exist in the vd_set but not if it's intro pod
- `is_mock`: skip some verifications in the recursive mock MainPod verification
- `verifier_data_hash`
- `pod_id` renamed to `statements_hash`
- AnchoredKeys are now a pair of dictionary root and key
- Entry statements are now defined as Contains with literal arguments
- Operations that take Entries now use Contains statements with literal arguments
- frontend:
- Rename `SignedPod` to `SignedDict` (which now contains the dict, public key and signature, and can still `verify(self)`ed)
- The `SignedDict` keeps the method `get_statement` for convenience but now it returns a `Contains` statement that proves the existence of the key in the dict
- The `MainPodBuilder` automatically inserts a `Contains` statement when an operation is added that uses an entry as argument that was not yet "opened".
- Removed the `literal` methods from the `MainPodBuilder` that were loading literals to anchored keys: that was no longer needed after we introduced literal arguments
- backend
- Only verify inclusion of the verifying key into the vd_set if the pod is MainPod. A pod is not MainPod if the first statement is Intro.
- Reject intro pods that have non-intro statements
- Empty pod now returns an intro statement
- Don't insert a type statement automatically in MainPod and MockMainPod. We get rid of the type entry.
- Implement `SignedBy` operation, which uses the muxed table to store signature verifications
- Rename `PodId` to `statements_hash` or `sts_hash` for short. Now this is only used as a hash of the statements for the circuits public inputs.
- Refactor normalization of `self` statements:
- Before: replace values that contain `SELF` by the given pod_id
- After: place the verifying key hash into the Intro predicates
This commit is contained in:
parent
122f9c3cac
commit
0e2f7b756e
39 changed files with 2127 additions and 3064 deletions
|
|
@ -6,7 +6,7 @@ use schemars::JsonSchema;
|
|||
use crate::{
|
||||
frontend::{AnchoredKey, Error, Result, Statement, StatementArg},
|
||||
middleware::{
|
||||
self, hash_str, CustomPredicate, CustomPredicateBatch, Key, NativePredicate, Params, PodId,
|
||||
self, hash_str, CustomPredicate, CustomPredicateBatch, Hash, Key, NativePredicate, Params,
|
||||
Predicate, StatementTmpl, StatementTmplArg, ToFields, Value, Wildcard,
|
||||
},
|
||||
};
|
||||
|
|
@ -181,8 +181,8 @@ impl CustomPredicateBatchBuilder {
|
|||
.map(|a| {
|
||||
Ok::<_, Error>(match a {
|
||||
BuilderArg::Literal(v) => StatementTmplArg::Literal(v.clone()),
|
||||
BuilderArg::Key(pod_id_wc, key_str) => StatementTmplArg::AnchoredKey(
|
||||
resolve_wildcard(args, priv_args, pod_id_wc)?,
|
||||
BuilderArg::Key(root_wc, key_str) => StatementTmplArg::AnchoredKey(
|
||||
resolve_wildcard(args, priv_args, root_wc)?,
|
||||
Key::from(key_str),
|
||||
),
|
||||
BuilderArg::WildcardLiteral(v) => {
|
||||
|
|
@ -223,7 +223,7 @@ fn resolve_wildcard(args: &[&str], priv_args: &[&str], s: &str) -> Result<Wildca
|
|||
.enumerate()
|
||||
.find_map(|(i, name)| (s == *name).then_some(Wildcard::new(s.to_string(), i)))
|
||||
.ok_or(Error::custom(format!(
|
||||
"Wildcard {} not amongst args {:?}",
|
||||
"Wildcard \"{}\" not amongst args {:?}",
|
||||
s,
|
||||
[args.to_vec(), priv_args.to_vec()].concat()
|
||||
)))
|
||||
|
|
@ -274,15 +274,10 @@ mod tests {
|
|||
let mut builder = CustomPredicateBatchBuilder::new(params.clone(), "gt_custom_pred".into());
|
||||
|
||||
let gt_stb = StatementTmplBuilder::new(NativePredicate::Gt)
|
||||
.arg(("s1_origin", "s1_key"))
|
||||
.arg(("s2_origin", "s2_key"));
|
||||
.arg("s1")
|
||||
.arg("s2");
|
||||
|
||||
builder.predicate_and(
|
||||
"gt_custom_pred",
|
||||
&["s1_origin", "s2_origin"],
|
||||
&[],
|
||||
&[gt_stb],
|
||||
)?;
|
||||
builder.predicate_and("gt_custom_pred", &["s1", "s2"], &[], &[gt_stb])?;
|
||||
let batch = builder.finish();
|
||||
let batch_clone = batch.clone();
|
||||
let gt_custom_pred = CustomPredicateRef::new(batch, 0);
|
||||
|
|
@ -290,11 +285,8 @@ mod tests {
|
|||
let mut mp_builder = MainPodBuilder::new(¶ms, vd_set);
|
||||
|
||||
// 2 > 1
|
||||
let s1 = mp_builder.priv_op(Operation::new_entry("s1_key", Value::from(2)))?;
|
||||
let s2 = mp_builder.priv_op(Operation::new_entry("s2_key", Value::from(1)))?;
|
||||
|
||||
// Adding a gt operation will produce a desugared lt operation
|
||||
let desugared_gt = mp_builder.pub_op(Operation::gt(s1, s2))?;
|
||||
let desugared_gt = mp_builder.pub_op(Operation::gt(2, 1))?;
|
||||
assert_eq!(
|
||||
desugared_gt.predicate(),
|
||||
Predicate::Native(NativePredicate::Lt)
|
||||
|
|
@ -324,12 +316,12 @@ mod tests {
|
|||
CustomPredicateBatchBuilder::new(params.clone(), "set_contains_custom_pred".into());
|
||||
|
||||
let set_contains_stb = StatementTmplBuilder::new(NativePredicate::SetContains)
|
||||
.arg(("s1_origin", "s1_key"))
|
||||
.arg(("s2_origin", "s2_key"));
|
||||
.arg("s1")
|
||||
.arg("s2");
|
||||
|
||||
builder.predicate_and(
|
||||
"set_contains_custom_pred",
|
||||
&["s1_origin", "s2_origin"],
|
||||
&["s1", "s2"],
|
||||
&[],
|
||||
&[set_contains_stb],
|
||||
)?;
|
||||
|
|
@ -339,11 +331,8 @@ mod tests {
|
|||
let mut mp_builder = MainPodBuilder::new(¶ms, vd_set);
|
||||
|
||||
let set_values: HashSet<Value> = [1, 2, 3].iter().map(|i| Value::from(*i)).collect();
|
||||
let s1 = mp_builder.priv_op(Operation::new_entry(
|
||||
"s1_key",
|
||||
Value::from(Set::new(params.max_depth_mt_containers, set_values)?),
|
||||
))?;
|
||||
let s2 = mp_builder.priv_op(Operation::new_entry("s2_key", Value::from(1)))?;
|
||||
let s1 = Set::new(params.max_depth_mt_containers, set_values)?;
|
||||
let s2 = 1;
|
||||
|
||||
let set_contains = mp_builder.pub_op(Operation::set_contains(s1, s2))?;
|
||||
assert_eq!(
|
||||
|
|
|
|||
|
|
@ -4,13 +4,15 @@
|
|||
use std::{collections::HashMap, convert::From, fmt};
|
||||
|
||||
use itertools::Itertools;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
pub use serialization::{SerializedMainPod, SerializedSignedPod};
|
||||
pub use serialization::SerializedMainPod;
|
||||
|
||||
use crate::middleware::{
|
||||
self, check_custom_pred, check_st_tmpl, hash_op, hash_str, max_op, prod_op, sum_op,
|
||||
AnchoredKey, Key, MainPodInputs, NativeOperation, OperationAux, OperationType, Params, PodId,
|
||||
PodProver, PodSigner, Statement, StatementArg, VDSet, Value, ValueRef, KEY_TYPE, SELF,
|
||||
self, check_custom_pred, check_st_tmpl, containers::Dictionary, hash_op, max_op, prod_op,
|
||||
sum_op, AnchoredKey, Hash, Key, MainPodInputs, MainPodProver, NativeOperation, OperationAux,
|
||||
OperationType, Params, PublicKey, RawValue, Signature, Signer, Statement, StatementArg, VDSet,
|
||||
Value, ValueRef,
|
||||
};
|
||||
|
||||
mod custom;
|
||||
|
|
@ -24,14 +26,14 @@ pub use operation::*;
|
|||
pub use pod_request::*;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SignedPodBuilder {
|
||||
pub struct SignedDictBuilder {
|
||||
pub params: Params,
|
||||
pub kvs: HashMap<Key, Value>,
|
||||
}
|
||||
|
||||
impl fmt::Display for SignedPodBuilder {
|
||||
impl fmt::Display for SignedDictBuilder {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "SignedPodBuilder:")?;
|
||||
writeln!(f, "SignedDictBuilder:")?;
|
||||
for (k, v) in self.kvs.iter().sorted_by_key(|kv| kv.0.hash()) {
|
||||
writeln!(f, " - {}: {}", k, v)?;
|
||||
}
|
||||
|
|
@ -39,7 +41,7 @@ impl fmt::Display for SignedPodBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
impl SignedPodBuilder {
|
||||
impl SignedDictBuilder {
|
||||
pub fn new(params: &Params) -> Self {
|
||||
Self {
|
||||
params: params.clone(),
|
||||
|
|
@ -51,65 +53,66 @@ impl SignedPodBuilder {
|
|||
self.kvs.insert(key.into(), value.into());
|
||||
}
|
||||
|
||||
pub fn sign<S: PodSigner>(&self, signer: &S) -> Result<SignedPod> {
|
||||
// Sign POD with committed KV store.
|
||||
let pod = signer.sign(&self.params, &self.kvs)?;
|
||||
pub fn sign<S: Signer>(&self, signer: &S) -> Result<SignedDict> {
|
||||
// Sign committed KV store.
|
||||
let dict = Dictionary::new(self.params.max_depth_mt_containers, self.kvs.clone())?;
|
||||
// NOTE: This is the same way that `TypedValue::Dictionary` computes the `RawValue`
|
||||
let msg_raw = RawValue::from(dict.commitment());
|
||||
let signature = signer.sign(msg_raw);
|
||||
|
||||
Ok(SignedPod::new(pod))
|
||||
Ok(SignedDict {
|
||||
dict,
|
||||
public_key: signer.public_key(),
|
||||
signature,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// SignedPod is a wrapper on top of backend::SignedPod, which additionally stores the
|
||||
/// string<-->hash relation of the keys.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(try_from = "SerializedSignedPod", into = "SerializedSignedPod")]
|
||||
pub struct SignedPod {
|
||||
pub pod: Box<dyn middleware::Pod>,
|
||||
// We store a copy of the key values for quick access
|
||||
kvs: HashMap<Key, Value>,
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
||||
// #[serde(try_from = "SerializedSignedDict", into = "SerializedSignedDict")]
|
||||
pub struct SignedDict {
|
||||
pub dict: Dictionary,
|
||||
pub public_key: PublicKey,
|
||||
pub signature: Signature,
|
||||
}
|
||||
|
||||
impl fmt::Display for SignedPod {
|
||||
impl fmt::Display for SignedDict {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "SignedPod (id:{}):", self.id())?;
|
||||
writeln!(f, "SignedDict (raw:{}):", self.dict.commitment())?;
|
||||
// Note: current version iterates sorting by keys of the kvs, but the merkletree defined at
|
||||
// https://0xparc.github.io/pod2/merkletree.html will not need it since it will be
|
||||
// deterministic based on the keys values not on the order of the keys when added into the
|
||||
// tree.
|
||||
for (k, v) in self.pod.kvs().iter().sorted_by_key(|kv| kv.0.key.hash()) {
|
||||
for (k, v) in self.dict.kvs().iter().sorted_by_key(|kv| kv.0.hash()) {
|
||||
writeln!(f, " - {} = {}", k, v)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl SignedPod {
|
||||
pub fn new(pod: Box<dyn middleware::Pod>) -> Self {
|
||||
let kvs = pod
|
||||
.kvs()
|
||||
.into_iter()
|
||||
.map(|(AnchoredKey { key, .. }, v)| (key, v))
|
||||
.collect();
|
||||
Self { pod, kvs }
|
||||
}
|
||||
pub fn id(&self) -> PodId {
|
||||
self.pod.id()
|
||||
}
|
||||
impl SignedDict {
|
||||
pub fn verify(&self) -> Result<()> {
|
||||
self.pod.verify().map_err(Error::Backend)
|
||||
self.signature
|
||||
.verify(self.public_key, RawValue::from(self.dict.commitment()))
|
||||
.then_some(())
|
||||
.ok_or(Error::custom("Invalid signature!"))
|
||||
}
|
||||
pub fn kvs(&self) -> &HashMap<Key, Value> {
|
||||
&self.kvs
|
||||
self.dict.kvs()
|
||||
}
|
||||
pub fn get(&self, key: impl Into<Key>) -> Option<&Value> {
|
||||
self.kvs.get(&key.into())
|
||||
self.kvs().get(&key.into())
|
||||
}
|
||||
// Returns the Equal statement that defines key if it exists.
|
||||
// Returns the Contains statement that defines key if it exists.
|
||||
pub fn get_statement(&self, key: impl Into<Key>) -> Option<Statement> {
|
||||
let key: Key = key.into();
|
||||
self.kvs()
|
||||
.get(&key)
|
||||
.map(|value| Statement::equal(AnchoredKey::from((self.id(), key)), value.clone()))
|
||||
self.kvs().get(&key).map(|value| {
|
||||
Statement::Contains(
|
||||
ValueRef::Literal(Value::from(self.dict.clone())),
|
||||
ValueRef::Literal(Value::from(key.name())),
|
||||
ValueRef::Literal(value.clone()),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -119,27 +122,20 @@ impl SignedPod {
|
|||
pub struct MainPodBuilder {
|
||||
pub params: Params,
|
||||
pub vd_set: VDSet,
|
||||
pub input_signed_pods: Vec<SignedPod>,
|
||||
pub input_recursive_pods: Vec<MainPod>,
|
||||
pub input_pods: Vec<MainPod>,
|
||||
pub statements: Vec<Statement>,
|
||||
pub operations: Vec<Operation>,
|
||||
pub public_statements: Vec<Statement>,
|
||||
// Internal state
|
||||
/// Counter for constants created from literals
|
||||
const_cnt: usize,
|
||||
/// Map from (public, Value) to Key of already created literals via Equal statements.
|
||||
literals: HashMap<(bool, Value), Key>,
|
||||
// TODO: track contains ops with literals added explicitly as well.
|
||||
dict_contains: Vec<(Value, Value)>, // (root, key)
|
||||
}
|
||||
|
||||
impl fmt::Display for MainPodBuilder {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "MainPod:")?;
|
||||
writeln!(f, " input_signed_pods:")?;
|
||||
for in_pod in &self.input_signed_pods {
|
||||
writeln!(f, " - {}", in_pod.id())?;
|
||||
}
|
||||
writeln!(f, " input_main_pods:")?;
|
||||
for in_pod in &self.input_recursive_pods {
|
||||
for in_pod in &self.input_pods {
|
||||
writeln!(f, " - {}", in_pod.id())?;
|
||||
}
|
||||
writeln!(f, " statements:")?;
|
||||
|
|
@ -157,20 +153,15 @@ impl MainPodBuilder {
|
|||
Self {
|
||||
params: params.clone(),
|
||||
vd_set: vd_set.clone(),
|
||||
input_signed_pods: Vec::new(),
|
||||
input_recursive_pods: Vec::new(),
|
||||
input_pods: Vec::new(),
|
||||
statements: Vec::new(),
|
||||
operations: Vec::new(),
|
||||
public_statements: Vec::new(),
|
||||
const_cnt: 0,
|
||||
literals: HashMap::new(),
|
||||
dict_contains: Vec::new(),
|
||||
}
|
||||
}
|
||||
pub fn add_signed_pod(&mut self, pod: &SignedPod) {
|
||||
self.input_signed_pods.push(pod.clone());
|
||||
}
|
||||
pub fn add_recursive_pod(&mut self, pod: MainPod) {
|
||||
self.input_recursive_pods.push(pod);
|
||||
pub fn add_pod(&mut self, pod: MainPod) {
|
||||
self.input_pods.push(pod);
|
||||
}
|
||||
pub fn insert(&mut self, public: bool, st_op: (Statement, Operation)) -> Result<()> {
|
||||
// TODO: Do error handling instead of panic
|
||||
|
|
@ -384,12 +375,9 @@ impl MainPodBuilder {
|
|||
let st = match op.0 {
|
||||
OperationType::Native(o) => {
|
||||
let native_arg_error = move || Error::op_invalid_args(format!("{o:?}"));
|
||||
match (o, &op.1.as_slice()) {
|
||||
(None, &[]) => Statement::None,
|
||||
(NewEntry, &[OperationArg::Entry(k, v)]) => {
|
||||
Statement::equal(AnchoredKey::from((SELF, k.as_str())), v.clone())
|
||||
}
|
||||
(EqualFromEntries, &[a1, a2]) => {
|
||||
match (o, &op.1.as_slice(), &op.2) {
|
||||
(None, &[], _) => Statement::None,
|
||||
(EqualFromEntries, &[a1, a2], _) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if v1 == v2 {
|
||||
|
|
@ -398,7 +386,7 @@ impl MainPodBuilder {
|
|||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(NotEqualFromEntries, &[a1, a2]) => {
|
||||
(NotEqualFromEntries, &[a1, a2], _) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if v1 != v2 {
|
||||
|
|
@ -407,7 +395,7 @@ impl MainPodBuilder {
|
|||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(LtFromEntries, &[a1, a2]) => {
|
||||
(LtFromEntries, &[a1, a2], _) => {
|
||||
let (r1, v1) = a1.int_value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.int_value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if v1 < v2 {
|
||||
|
|
@ -416,7 +404,7 @@ impl MainPodBuilder {
|
|||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(LtEqFromEntries, &[a1, a2]) => {
|
||||
(LtEqFromEntries, &[a1, a2], _) => {
|
||||
let (r1, v1) = a1.int_value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.int_value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if v1 <= v2 {
|
||||
|
|
@ -425,10 +413,11 @@ impl MainPodBuilder {
|
|||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(CopyStatement, &[OperationArg::Statement(s)]) => s.clone(),
|
||||
(CopyStatement, &[OperationArg::Statement(s)], _) => s.clone(),
|
||||
(
|
||||
TransitiveEqualFromStatements,
|
||||
&[OperationArg::Statement(Statement::Equal(r1, r2)), OperationArg::Statement(Statement::Equal(r3, r4))],
|
||||
_,
|
||||
) => {
|
||||
if r2 == r3 {
|
||||
Statement::Equal(r1.clone(), r4.clone())
|
||||
|
|
@ -436,10 +425,10 @@ impl MainPodBuilder {
|
|||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(LtToNotEqual, &[OperationArg::Statement(Statement::Lt(r1, r2))]) => {
|
||||
(LtToNotEqual, &[OperationArg::Statement(Statement::Lt(r1, r2))], _) => {
|
||||
Statement::NotEqual(r1.clone(), r2.clone())
|
||||
}
|
||||
(SumOf, &[a1, a2, a3]) => {
|
||||
(SumOf, &[a1, a2, a3], _) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r3, v3) = a3.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
|
|
@ -449,7 +438,7 @@ impl MainPodBuilder {
|
|||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(ProductOf, &[a1, a2, a3]) => {
|
||||
(ProductOf, &[a1, a2, a3], _) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r3, v3) = a3.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
|
|
@ -459,7 +448,7 @@ impl MainPodBuilder {
|
|||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(MaxOf, &[a1, a2, a3]) => {
|
||||
(MaxOf, &[a1, a2, a3], _) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r3, v3) = a3.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
|
|
@ -469,7 +458,7 @@ impl MainPodBuilder {
|
|||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(HashOf, &[a1, a2, a3]) => {
|
||||
(HashOf, &[a1, a2, a3], _) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r3, v3) = a3.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
|
|
@ -479,20 +468,20 @@ impl MainPodBuilder {
|
|||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(ContainsFromEntries, &[a1, a2, a3]) => {
|
||||
(ContainsFromEntries, &[a1, a2, a3], _) => {
|
||||
let (r1, _v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, _v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r3, _v3) = a3.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
// TODO: validate proof
|
||||
Statement::Contains(r1, r2, r3)
|
||||
}
|
||||
(NotContainsFromEntries, &[a1, a2]) => {
|
||||
(NotContainsFromEntries, &[a1, a2], _) => {
|
||||
let (r1, _v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, _v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
// TODO: validate proof
|
||||
Statement::NotContains(r1, r2)
|
||||
}
|
||||
(PublicKeyOf, &[a1, a2]) => {
|
||||
(PublicKeyOf, &[a1, a2], _) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if middleware::Operation::check_public_key(v1, v2)? {
|
||||
|
|
@ -501,7 +490,16 @@ impl MainPodBuilder {
|
|||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(ContainerInsertFromEntries, &[a1, a2, a3, a4]) => {
|
||||
(SignedBy, &[a1, a2], OperationAux::Signature(sig)) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if middleware::Operation::check_signed_by(v1, v2, sig)? {
|
||||
Statement::SignedBy(r1, r2)
|
||||
} else {
|
||||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(ContainerInsertFromEntries, &[a1, a2, a3, a4], _) => {
|
||||
let (r1, _v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, _v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r3, _v3) = a3.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
|
|
@ -509,7 +507,7 @@ impl MainPodBuilder {
|
|||
// TODO: validate proof
|
||||
Statement::ContainerInsert(r1, r2, r3, r4)
|
||||
}
|
||||
(ContainerUpdateFromEntries, &[a1, a2, a3, a4]) => {
|
||||
(ContainerUpdateFromEntries, &[a1, a2, a3, a4], _) => {
|
||||
let (r1, _v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, _v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r3, _v3) = a3.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
|
|
@ -517,14 +515,14 @@ impl MainPodBuilder {
|
|||
// TODO: validate proof
|
||||
Statement::ContainerUpdate(r1, r2, r3, r4)
|
||||
}
|
||||
(ContainerDeleteFromEntries, &[a1, a2, a3]) => {
|
||||
(ContainerDeleteFromEntries, &[a1, a2, a3], _) => {
|
||||
let (r1, _v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, _v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r3, _v3) = a3.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
// TODO: validate proof
|
||||
Statement::ContainerDelete(r1, r2, r3)
|
||||
}
|
||||
(t, _) => {
|
||||
(t, _, _) => {
|
||||
if t.is_syntactic_sugar() {
|
||||
return Err(Error::custom(format!(
|
||||
"Unexpected syntactic sugar: {:?}",
|
||||
|
|
@ -583,7 +581,28 @@ impl MainPodBuilder {
|
|||
Ok(st)
|
||||
}
|
||||
|
||||
/// For every operation that has Entry statements as arguments we add a Contains statement to
|
||||
/// open the dictionary.
|
||||
fn add_entries_contains(&mut self, op: &Operation) -> Result<()> {
|
||||
for arg in &op.1 {
|
||||
if let OperationArg::Statement(Statement::Contains(
|
||||
ValueRef::Literal(dict),
|
||||
ValueRef::Literal(key),
|
||||
ValueRef::Literal(v),
|
||||
)) = arg
|
||||
{
|
||||
let root_key = (dict.clone(), key.clone());
|
||||
if !self.dict_contains.contains(&root_key) {
|
||||
self.dict_contains.push(root_key);
|
||||
self.priv_op(Operation::dict_contains(dict, key, v))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn op(&mut self, public: bool, op: Operation) -> Result<Statement> {
|
||||
self.add_entries_contains(&op)?;
|
||||
let op = Self::fill_in_aux(Self::lower_op(op)?)?;
|
||||
let st = self.op_statement(op.clone())?;
|
||||
self.insert(public, (st, op))?;
|
||||
|
|
@ -591,48 +610,13 @@ impl MainPodBuilder {
|
|||
Ok(self.statements[self.statements.len() - 1].clone())
|
||||
}
|
||||
|
||||
/// Convenience method for introducing public constants.
|
||||
pub fn pub_literal(&mut self, v: impl Into<Value>) -> Result<Statement> {
|
||||
self.literal(true, v.into())
|
||||
}
|
||||
|
||||
/// Convenience method for introducing private constants.
|
||||
pub fn priv_literal(&mut self, v: impl Into<Value>) -> Result<Statement> {
|
||||
self.literal(false, v.into())
|
||||
}
|
||||
|
||||
fn literal(&mut self, public: bool, value: Value) -> Result<Statement> {
|
||||
let public_value = (public, value);
|
||||
if let Some(key) = self.literals.get(&public_value) {
|
||||
Ok(Statement::equal(
|
||||
AnchoredKey::new(SELF, key.clone()),
|
||||
public_value.1,
|
||||
))
|
||||
} else {
|
||||
let key = format!("c{}", self.const_cnt);
|
||||
self.literals
|
||||
.insert(public_value.clone(), Key::new(key.clone()));
|
||||
self.const_cnt += 1;
|
||||
self.op(
|
||||
public,
|
||||
Operation(
|
||||
OperationType::Native(NativeOperation::NewEntry),
|
||||
vec![OperationArg::Entry(key.clone(), public_value.1)],
|
||||
OperationAux::None,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reveal(&mut self, st: &Statement) {
|
||||
self.public_statements.push(st.clone());
|
||||
}
|
||||
|
||||
pub fn prove(&self, prover: &dyn PodProver) -> Result<MainPod> {
|
||||
pub fn prove(&self, prover: &dyn MainPodProver) -> Result<MainPod> {
|
||||
let compiler = MainPodCompiler::new(&self.params);
|
||||
let inputs = MainPodCompilerInputs {
|
||||
// signed_pods: &self.input_signed_pods,
|
||||
// main_pods: &self.input_main_pods,
|
||||
statements: &self.statements,
|
||||
operations: &self.operations,
|
||||
public_statements: &self.public_statements,
|
||||
|
|
@ -641,67 +625,18 @@ impl MainPodBuilder {
|
|||
let (statements, operations, public_statements) = compiler.compile(inputs, &self.params)?;
|
||||
|
||||
let inputs = MainPodInputs {
|
||||
signed_pods: &self
|
||||
.input_signed_pods
|
||||
.iter()
|
||||
.map(|p| p.pod.as_ref())
|
||||
.collect_vec(),
|
||||
recursive_pods: &self
|
||||
.input_recursive_pods
|
||||
.iter()
|
||||
.map(|p| p.pod.as_ref())
|
||||
.collect_vec(),
|
||||
pods: &self.input_pods.iter().map(|p| p.pod.as_ref()).collect_vec(),
|
||||
statements: &statements,
|
||||
operations: &operations,
|
||||
public_statements: &public_statements,
|
||||
vd_set: self.vd_set.clone(),
|
||||
};
|
||||
let pod = prover.prove(&self.params, &self.vd_set, inputs)?;
|
||||
|
||||
// Gather public statements, making sure to inject the type
|
||||
// information specified by the backend.
|
||||
let pod_id = pod.id();
|
||||
let type_key_hash = hash_str(KEY_TYPE);
|
||||
let type_statement = pod
|
||||
.pub_statements()
|
||||
.into_iter()
|
||||
.find_map(|s| match s.as_entry() {
|
||||
Some((AnchoredKey { pod_id: id, key }, _))
|
||||
if id == &pod_id && key.hash() == type_key_hash =>
|
||||
{
|
||||
Some(s)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.ok_or(Error::custom(format!(
|
||||
// TODO use a specific Error
|
||||
"Missing POD type information in POD: {:?}",
|
||||
pod
|
||||
)))?;
|
||||
// Replace instances of `SELF` with the POD ID for consistency
|
||||
// with `pub_statements` method.
|
||||
let public_statements = [type_statement]
|
||||
.into_iter()
|
||||
.chain(self.public_statements.clone().into_iter().map(|s| {
|
||||
let s_type = s.predicate();
|
||||
let s_args = s
|
||||
.args()
|
||||
.into_iter()
|
||||
.map(|arg| match arg {
|
||||
StatementArg::Key(AnchoredKey { pod_id: id, key }) if id == SELF => {
|
||||
StatementArg::Key(AnchoredKey::new(pod_id, key))
|
||||
}
|
||||
_ => arg,
|
||||
})
|
||||
.collect();
|
||||
Statement::from_args(s_type, s_args).expect("valid arguments")
|
||||
}))
|
||||
.collect();
|
||||
let pod = prover.prove(&self.params, inputs)?;
|
||||
|
||||
Ok(MainPod {
|
||||
pod,
|
||||
params: self.params.clone(),
|
||||
public_statements,
|
||||
public_statements: self.public_statements.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -709,30 +644,26 @@ impl MainPodBuilder {
|
|||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(try_from = "SerializedMainPod", into = "SerializedMainPod")]
|
||||
pub struct MainPod {
|
||||
pub pod: Box<dyn middleware::RecursivePod>,
|
||||
pub pod: Box<dyn middleware::Pod>,
|
||||
pub public_statements: Vec<Statement>,
|
||||
pub params: Params,
|
||||
}
|
||||
|
||||
impl fmt::Display for MainPod {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "MainPod: {}", self.pod.id())?;
|
||||
writeln!(f, "MainPod: {}", self.pod.statements_hash())?;
|
||||
writeln!(f, " valid? {}", self.pod.verify().is_ok())?;
|
||||
writeln!(f, " statements:")?;
|
||||
for st in &self.pod.pub_statements() {
|
||||
writeln!(f, " - {}", st)?;
|
||||
}
|
||||
writeln!(f, " kvs:")?;
|
||||
for (k, v) in &self.pod.kvs() {
|
||||
writeln!(f, " - {}: {}", k, v)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl MainPod {
|
||||
pub fn id(&self) -> PodId {
|
||||
self.pod.id()
|
||||
pub fn id(&self) -> Hash {
|
||||
self.pod.statements_hash()
|
||||
}
|
||||
|
||||
/// Returns the value of a Equal statement with self id that defines key if it exists.
|
||||
|
|
@ -742,7 +673,7 @@ impl MainPod {
|
|||
.iter()
|
||||
.find_map(|st| match st {
|
||||
Statement::Equal(ValueRef::Key(ak), ValueRef::Literal(value))
|
||||
if ak.pod_id == self.id() && ak.key.hash() == key.hash() =>
|
||||
if ak.root == self.id() && ak.key.hash() == key.hash() =>
|
||||
{
|
||||
Some(value)
|
||||
}
|
||||
|
|
@ -753,8 +684,6 @@ impl MainPod {
|
|||
}
|
||||
|
||||
struct MainPodCompilerInputs<'a> {
|
||||
// pub signed_pods: &'a [Box<dyn middleware::SignedPod>],
|
||||
// pub main_pods: &'a [Box<dyn middleware::MainPod>],
|
||||
pub statements: &'a [Statement],
|
||||
pub operations: &'a [Operation],
|
||||
pub public_statements: &'a [Statement],
|
||||
|
|
@ -832,8 +761,6 @@ impl MainPodCompiler {
|
|||
Vec<Statement>, // public statements
|
||||
)> {
|
||||
let MainPodCompilerInputs {
|
||||
// signed_pods: _,
|
||||
// main_pods: _,
|
||||
statements,
|
||||
operations,
|
||||
public_statements,
|
||||
|
|
@ -853,16 +780,17 @@ pub mod tests {
|
|||
use super::*;
|
||||
use crate::{
|
||||
backends::plonky2::{
|
||||
mock::mainpod::MockProver, primitives::ec::schnorr::SecretKey, signedpod::Signer,
|
||||
mock::mainpod::MockProver, primitives::ec::schnorr::SecretKey, signer::Signer,
|
||||
},
|
||||
dict,
|
||||
examples::{
|
||||
attest_eth_friend, custom::eth_dos_request, great_boy_pod_full_flow,
|
||||
tickets_pod_full_flow, zu_kyc_pod_builder, zu_kyc_pod_request,
|
||||
zu_kyc_sign_pod_builders, EthDosHelper, MOCK_VD_SET,
|
||||
zu_kyc_sign_dict_builders, EthDosHelper, MOCK_VD_SET,
|
||||
},
|
||||
middleware::{
|
||||
containers::{Array, Dictionary, Set},
|
||||
Value,
|
||||
containers::{Array, Set},
|
||||
Signer as _, Value,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -874,44 +802,21 @@ pub mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// Check that frontend key-values agree with those embedded in a
|
||||
// SignedPod.
|
||||
fn check_kvs(pod: &SignedPod) -> Result<()> {
|
||||
let kvs = pod.kvs.clone().into_iter().collect::<HashMap<_, _>>();
|
||||
let embedded_kvs = pod
|
||||
.pod
|
||||
.kvs()
|
||||
.into_iter()
|
||||
.map(|(middleware::AnchoredKey { key, .. }, v)| (key, v))
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
if kvs == embedded_kvs {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::custom(format!(
|
||||
"KVs {:?} do not agree with those embedded in the POD: {:?}",
|
||||
kvs, embedded_kvs
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_front_zu_kyc() -> Result<()> {
|
||||
let params = Params::default();
|
||||
let vd_set = &*MOCK_VD_SET;
|
||||
let (gov_id, pay_stub) = zu_kyc_sign_pod_builders(¶ms);
|
||||
let (gov_id, pay_stub) = zu_kyc_sign_dict_builders(¶ms);
|
||||
|
||||
println!("{}", gov_id);
|
||||
println!("{}", pay_stub);
|
||||
|
||||
let signer = Signer(SecretKey(1u32.into()));
|
||||
let gov_id = gov_id.sign(&signer)?;
|
||||
check_kvs(&gov_id)?;
|
||||
let gov_id_signer = Signer(SecretKey(1u32.into()));
|
||||
let gov_id = gov_id.sign(&gov_id_signer)?;
|
||||
println!("{}", gov_id);
|
||||
|
||||
let signer = Signer(SecretKey(2u32.into()));
|
||||
let pay_stub = pay_stub.sign(&signer)?;
|
||||
check_kvs(&pay_stub)?;
|
||||
let pay_stub_signer = Signer(SecretKey(2u32.into()));
|
||||
let pay_stub = pay_stub.sign(&pay_stub_signer)?;
|
||||
println!("{}", pay_stub);
|
||||
|
||||
let kyc_builder = zu_kyc_pod_builder(¶ms, vd_set, &gov_id, &pay_stub)?;
|
||||
|
|
@ -923,14 +828,22 @@ pub mod tests {
|
|||
|
||||
println!("{}", kyc);
|
||||
|
||||
kyc.pod.verify()?;
|
||||
|
||||
let request = zu_kyc_pod_request(
|
||||
gov_id.get("_signer").unwrap(),
|
||||
pay_stub.get("_signer").unwrap(),
|
||||
&Value::from(gov_id_signer.public_key()),
|
||||
&Value::from(pay_stub_signer.public_key()),
|
||||
)?;
|
||||
// Check the bindings of the "gov" and "pay" wildcards from the PodRequest
|
||||
let bindings = request.exact_match_pod(&*kyc.pod).unwrap();
|
||||
assert_eq!(*bindings.get("gov").unwrap(), gov_id.id().into());
|
||||
assert_eq!(*bindings.get("pay").unwrap(), pay_stub.id().into());
|
||||
assert_eq!(
|
||||
*bindings.get("gov").unwrap(),
|
||||
gov_id.dict.commitment().into()
|
||||
);
|
||||
assert_eq!(
|
||||
*bindings.get("pay").unwrap(),
|
||||
pay_stub.dict.commitment().into()
|
||||
);
|
||||
|
||||
check_public_statements(&kyc)
|
||||
}
|
||||
|
|
@ -950,7 +863,7 @@ pub mod tests {
|
|||
let charlie = Signer(SecretKey(3u32.into()));
|
||||
let david = Signer(SecretKey(4u32.into()));
|
||||
|
||||
let helper = EthDosHelper::new(¶ms, vd_set, true, alice.public_key())?;
|
||||
let helper = EthDosHelper::new(¶ms, vd_set, alice.public_key())?;
|
||||
|
||||
let prover = MockProver {};
|
||||
|
||||
|
|
@ -960,8 +873,8 @@ pub mod tests {
|
|||
let request = eth_dos_request()?;
|
||||
assert!(request.exact_match_pod(&*dist_1.pod).is_ok());
|
||||
let bindings = request.exact_match_pod(&*dist_1.pod).unwrap();
|
||||
assert_eq!(*bindings.get("src").unwrap(), alice.public_key());
|
||||
assert_eq!(*bindings.get("dst").unwrap(), bob.public_key());
|
||||
assert_eq!(*bindings.get("src").unwrap(), alice.public_key().into());
|
||||
assert_eq!(*bindings.get("dst").unwrap(), bob.public_key().into());
|
||||
assert_eq!(*bindings.get("distance").unwrap(), 1.into());
|
||||
|
||||
let bob_attestation = attest_eth_friend(¶ms, &bob, charlie.public_key());
|
||||
|
|
@ -971,8 +884,8 @@ pub mod tests {
|
|||
dist_2.pod.verify()?;
|
||||
assert!(request.exact_match_pod(&*dist_2.pod).is_ok());
|
||||
let bindings = request.exact_match_pod(&*dist_2.pod).unwrap();
|
||||
assert_eq!(*bindings.get("src").unwrap(), alice.public_key());
|
||||
assert_eq!(*bindings.get("dst").unwrap(), charlie.public_key());
|
||||
assert_eq!(*bindings.get("src").unwrap(), alice.public_key().into());
|
||||
assert_eq!(*bindings.get("dst").unwrap(), charlie.public_key().into());
|
||||
assert_eq!(*bindings.get("distance").unwrap(), 2.into());
|
||||
|
||||
let charlie_attestation = attest_eth_friend(¶ms, &charlie, david.public_key());
|
||||
|
|
@ -982,8 +895,8 @@ pub mod tests {
|
|||
dist_3.pod.verify()?;
|
||||
assert!(request.exact_match_pod(&*dist_3.pod).is_ok());
|
||||
let bindings = request.exact_match_pod(&*dist_3.pod).unwrap();
|
||||
assert_eq!(*bindings.get("src").unwrap(), alice.public_key());
|
||||
assert_eq!(*bindings.get("dst").unwrap(), david.public_key());
|
||||
assert_eq!(*bindings.get("src").unwrap(), alice.public_key().into());
|
||||
assert_eq!(*bindings.get("dst").unwrap(), david.public_key().into());
|
||||
assert_eq!(*bindings.get("distance").unwrap(), 3.into());
|
||||
|
||||
Ok(())
|
||||
|
|
@ -1014,25 +927,22 @@ pub mod tests {
|
|||
let params = Params::default();
|
||||
let vd_set = &*MOCK_VD_SET;
|
||||
|
||||
let mut signed_builder = SignedPodBuilder::new(¶ms);
|
||||
let mut signed_builder = SignedDictBuilder::new(¶ms);
|
||||
signed_builder.insert("a", 1);
|
||||
signed_builder.insert("b", 1);
|
||||
let signer = Signer(SecretKey(1u32.into()));
|
||||
let signed_pod = signed_builder.sign(&signer).unwrap();
|
||||
let signed_dict = signed_builder.sign(&signer).unwrap();
|
||||
|
||||
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
||||
builder.add_signed_pod(&signed_pod);
|
||||
|
||||
//let op_val1 = Operation{
|
||||
// OperationType::Native(NativeOperation::CopyStatement),
|
||||
// signed_pod.
|
||||
//}
|
||||
builder
|
||||
.pub_op(Operation::dict_signed_by(&signed_dict))
|
||||
.unwrap();
|
||||
|
||||
let op_eq1 = Operation(
|
||||
OperationType::Native(NativeOperation::EqualFromEntries),
|
||||
vec![
|
||||
OperationArg::from((&signed_pod, "a")),
|
||||
OperationArg::from((&signed_pod, "b")),
|
||||
OperationArg::from((&signed_dict, "a")),
|
||||
OperationArg::from((&signed_dict, "b")),
|
||||
],
|
||||
OperationAux::None,
|
||||
);
|
||||
|
|
@ -1040,8 +950,8 @@ pub mod tests {
|
|||
let op_eq2 = Operation(
|
||||
OperationType::Native(NativeOperation::EqualFromEntries),
|
||||
vec![
|
||||
OperationArg::from((&signed_pod, "b")),
|
||||
OperationArg::from((&signed_pod, "a")),
|
||||
OperationArg::from((&signed_dict, "b")),
|
||||
OperationArg::from((&signed_dict, "a")),
|
||||
],
|
||||
OperationAux::None,
|
||||
);
|
||||
|
|
@ -1065,17 +975,21 @@ pub mod tests {
|
|||
fn test_false_st() {
|
||||
let params = Params::default();
|
||||
let vd_set = &*MOCK_VD_SET;
|
||||
let mut builder = SignedPodBuilder::new(¶ms);
|
||||
let mut builder = SignedDictBuilder::new(¶ms);
|
||||
|
||||
builder.insert("num", 2);
|
||||
let signer = Signer(SecretKey(1u32.into()));
|
||||
let pod = builder.sign(&signer).unwrap();
|
||||
let signed_dict = builder.sign(&signer).unwrap();
|
||||
|
||||
println!("{}", pod);
|
||||
println!("{}", signed_dict);
|
||||
|
||||
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
||||
builder.add_signed_pod(&pod);
|
||||
builder.pub_op(Operation::gt((&pod, "num"), 5)).unwrap();
|
||||
builder
|
||||
.pub_op(Operation::dict_signed_by(&signed_dict))
|
||||
.unwrap();
|
||||
builder
|
||||
.pub_op(Operation::gt((&signed_dict, "num"), 5))
|
||||
.unwrap();
|
||||
|
||||
let prover = MockProver {};
|
||||
let false_pod = builder.prove(&prover).unwrap();
|
||||
|
|
@ -1088,26 +1002,28 @@ pub mod tests {
|
|||
fn test_dictionaries() -> Result<()> {
|
||||
let params = Params::default();
|
||||
let vd_set = &*MOCK_VD_SET;
|
||||
let mut builder = SignedPodBuilder::new(¶ms);
|
||||
let mut builder = SignedDictBuilder::new(¶ms);
|
||||
|
||||
let mut my_dict_kvs: HashMap<Key, Value> = HashMap::new();
|
||||
my_dict_kvs.insert(Key::from("a"), Value::from(1));
|
||||
my_dict_kvs.insert(Key::from("b"), Value::from(2));
|
||||
my_dict_kvs.insert(Key::from("c"), Value::from(3));
|
||||
// let my_dict_as_mt = MerkleTree::new(5, &my_dict_kvs).unwrap();
|
||||
// let dict = Dictionary { mt: my_dict_as_mt };
|
||||
let dict = Dictionary::new(params.max_depth_mt_containers, my_dict_kvs)?;
|
||||
let dict = dict!(params.max_depth_mt_containers, {
|
||||
"a" => 1,
|
||||
"b" => 2,
|
||||
"c" => 3,
|
||||
})?;
|
||||
let dict_root = Value::from(dict.clone());
|
||||
builder.insert("dict", dict_root);
|
||||
|
||||
let signer = Signer(SecretKey(1u32.into()));
|
||||
let pod = builder.sign(&signer).unwrap();
|
||||
let signed_dict = builder.sign(&signer).unwrap();
|
||||
|
||||
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
||||
builder.add_signed_pod(&pod);
|
||||
let st0 = pod.get_statement("dict").unwrap();
|
||||
let st1 = builder.op(true, Operation::new_entry("key", "a")).unwrap();
|
||||
let st2 = builder.literal(false, Value::from(1)).unwrap();
|
||||
builder
|
||||
.pub_op(Operation::dict_signed_by(&signed_dict))
|
||||
.unwrap();
|
||||
let st0 = signed_dict.get_statement("dict").unwrap();
|
||||
let local = dict!(32, {"key" => "a"})?;
|
||||
let st1 = builder
|
||||
.op(true, Operation::dict_contains(local, "key", "a"))
|
||||
.unwrap();
|
||||
|
||||
builder.pub_op(Operation(
|
||||
// OperationType
|
||||
|
|
@ -1116,7 +1032,7 @@ pub mod tests {
|
|||
vec![
|
||||
OperationArg::Statement(st0.clone()),
|
||||
OperationArg::Statement(st1),
|
||||
OperationArg::Statement(st2),
|
||||
OperationArg::Literal(Value::from(1)),
|
||||
],
|
||||
OperationAux::MerkleProof(dict.prove(&Key::from("a")).unwrap().1),
|
||||
))?;
|
||||
|
|
@ -1259,25 +1175,35 @@ pub mod tests {
|
|||
let sk = SecretKey::new_rand();
|
||||
let pk = sk.public_key();
|
||||
|
||||
// Signed POD contains public key as owner
|
||||
let mut builder = SignedPodBuilder::new(¶ms);
|
||||
// Signed Dict contains public key as owner
|
||||
let mut builder = SignedDictBuilder::new(¶ms);
|
||||
builder.insert("owner", Value::from(pk));
|
||||
builder.insert("other_data", Value::from(123));
|
||||
let signer = Signer(SecretKey(1u32.into()));
|
||||
let signed_pod = builder.sign(&signer).unwrap();
|
||||
let signed_dict = builder.sign(&signer).unwrap();
|
||||
|
||||
// Main POD proves ownership of the owner's secret key.
|
||||
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
||||
builder.add_signed_pod(&signed_pod);
|
||||
let st0 = signed_pod.get_statement("owner").unwrap();
|
||||
let st1 = builder
|
||||
.priv_op(Operation::new_entry("known_secret", Value::from(sk)))
|
||||
.unwrap();
|
||||
builder.pub_op(Operation::signed_by(
|
||||
Value::from(signed_dict.dict.clone()),
|
||||
Value::from(signed_dict.public_key),
|
||||
signed_dict.signature.clone(),
|
||||
))?;
|
||||
|
||||
let st0 = builder.priv_op(Operation::dict_contains(
|
||||
signed_dict.dict,
|
||||
"owner",
|
||||
Value::from(pk),
|
||||
))?;
|
||||
let local = dict!(32, { "known_secret" => sk.clone() })?;
|
||||
let st1 = builder.priv_op(Operation::dict_contains(
|
||||
local,
|
||||
"known_secret",
|
||||
Value::from(sk),
|
||||
))?;
|
||||
builder
|
||||
.pub_op(Operation(
|
||||
// OperationType
|
||||
OperationType::Native(NativeOperation::PublicKeyOf),
|
||||
// Vec<OperationArg>
|
||||
vec![OperationArg::Statement(st0), OperationArg::Statement(st1)],
|
||||
OperationAux::None,
|
||||
))
|
||||
|
|
@ -1301,22 +1227,25 @@ pub mod tests {
|
|||
let pk = sk.public_key();
|
||||
|
||||
// Signed POD contains public key as owner
|
||||
let mut builder = SignedPodBuilder::new(¶ms);
|
||||
let mut builder = SignedDictBuilder::new(¶ms);
|
||||
builder.insert("owner", Value::from(pk));
|
||||
builder.insert("other_data", Value::from(123));
|
||||
let signer = Signer(SecretKey(1u32.into()));
|
||||
let signed_pod = builder.sign(&signer).unwrap();
|
||||
let signed_dict = builder.sign(&signer).unwrap();
|
||||
|
||||
// Try to build with the wrong secret key. The pre-proving checks
|
||||
// will catch this.
|
||||
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
||||
builder.add_signed_pod(&signed_pod);
|
||||
let st0 = signed_pod.get_statement("owner").unwrap();
|
||||
builder
|
||||
.pub_op(Operation::dict_signed_by(&signed_dict))
|
||||
.unwrap();
|
||||
let st0 = signed_dict.get_statement("owner").unwrap();
|
||||
let local = dict!(32, {"known_secret" => SecretKey(BigUint::from(123u32))})?;
|
||||
let st1 = builder
|
||||
.priv_op(Operation::new_entry(
|
||||
"known_secret",
|
||||
Value::from(SecretKey(BigUint::from(123u32))),
|
||||
))
|
||||
.op(
|
||||
true,
|
||||
Operation::dict_contains(local, "known_secret", SecretKey(BigUint::from(123u32))),
|
||||
)
|
||||
.unwrap();
|
||||
assert!(builder
|
||||
.pub_op(Operation(
|
||||
|
|
@ -1341,33 +1270,30 @@ pub mod tests {
|
|||
|
||||
// Try to build with wrong type in 1st arg
|
||||
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
||||
let st_pk = builder.literal(false, Value::from(pk)).unwrap();
|
||||
let st_int1 = builder.literal(false, Value::from(123)).unwrap();
|
||||
let int2 = Value::from(123);
|
||||
let sk = Value::from(sk);
|
||||
assert!(builder
|
||||
.pub_op(Operation(
|
||||
// OperationType
|
||||
OperationType::Native(NativeOperation::PublicKeyOf),
|
||||
// Vec<OperationArg>
|
||||
vec![
|
||||
OperationArg::Statement(st_pk),
|
||||
OperationArg::Statement(st_int1),
|
||||
],
|
||||
vec![OperationArg::Literal(int2), OperationArg::Literal(sk),],
|
||||
OperationAux::None,
|
||||
))
|
||||
.is_err());
|
||||
|
||||
// Try to build with wrong type in 2nd arg
|
||||
builder = MainPodBuilder::new(¶ms, vd_set);
|
||||
let st_sk = builder.literal(false, Value::from(pk)).unwrap();
|
||||
let st_int2 = builder.literal(false, Value::from(123)).unwrap();
|
||||
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
||||
let pk = Value::from(pk);
|
||||
let int1 = Value::from(123);
|
||||
assert!(builder
|
||||
.pub_op(Operation(
|
||||
// OperationType
|
||||
OperationType::Native(NativeOperation::PublicKeyOf),
|
||||
// Vec<OperationArg>
|
||||
vec![
|
||||
OperationArg::Statement(st_int2),
|
||||
OperationArg::Statement(st_sk),
|
||||
OperationArg::Literal(pk.clone()),
|
||||
OperationArg::Literal(int1),
|
||||
],
|
||||
OperationAux::None,
|
||||
))
|
||||
|
|
@ -1376,33 +1302,6 @@ pub mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[should_panic]
|
||||
#[test]
|
||||
fn test_reject_duplicate_new_entry() {
|
||||
// try to insert the same key multiple times
|
||||
// right now this is not caught when you build the pod,
|
||||
// but it is caught on verify
|
||||
env_logger::init();
|
||||
|
||||
let params = Params::default();
|
||||
let vd_set = &*MOCK_VD_SET;
|
||||
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
||||
let st = Statement::equal(AnchoredKey::from((SELF, "a")), Value::from(3));
|
||||
let op_new_entry = Operation(
|
||||
OperationType::Native(NativeOperation::NewEntry),
|
||||
vec![],
|
||||
OperationAux::None,
|
||||
);
|
||||
builder.insert(false, (st, op_new_entry.clone())).unwrap();
|
||||
|
||||
let st = Statement::equal(AnchoredKey::from((SELF, "a")), Value::from(28));
|
||||
builder.insert(false, (st, op_new_entry.clone())).unwrap();
|
||||
|
||||
let prover = MockProver {};
|
||||
let pod = builder.prove(&prover).unwrap();
|
||||
pod.pod.verify().unwrap();
|
||||
}
|
||||
|
||||
#[should_panic]
|
||||
#[test]
|
||||
fn test_reject_unsound_statement() {
|
||||
|
|
@ -1411,23 +1310,25 @@ pub mod tests {
|
|||
let params = Params::default();
|
||||
let vd_set = &*MOCK_VD_SET;
|
||||
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
||||
let self_a = AnchoredKey::from((SELF, "a"));
|
||||
let self_b = AnchoredKey::from((SELF, "b"));
|
||||
let value_of_a = Statement::equal(self_a.clone(), Value::from(3));
|
||||
let value_of_b = Statement::equal(self_b.clone(), Value::from(27));
|
||||
let local = dict!(32, {"a" => 3, "b" => 27}).unwrap();
|
||||
let value_of_a = Statement::contains(local.clone(), "a", 3);
|
||||
let value_of_b = Statement::contains(local.clone(), "b", 27);
|
||||
|
||||
let op_new_entry = Operation(
|
||||
OperationType::Native(NativeOperation::NewEntry),
|
||||
let op_contains = Operation(
|
||||
OperationType::Native(NativeOperation::DictContainsFromEntries),
|
||||
vec![],
|
||||
OperationAux::None,
|
||||
);
|
||||
builder
|
||||
.insert(false, (value_of_a.clone(), op_new_entry.clone()))
|
||||
.insert(false, (value_of_a.clone(), op_contains.clone()))
|
||||
.unwrap();
|
||||
builder
|
||||
.insert(false, (value_of_b.clone(), op_new_entry))
|
||||
.insert(false, (value_of_b.clone(), op_contains))
|
||||
.unwrap();
|
||||
let st = Statement::equal(self_a, self_b);
|
||||
let st = Statement::equal(
|
||||
AnchoredKey::from((&local, "a")),
|
||||
AnchoredKey::from((&local, "b")),
|
||||
);
|
||||
let op = Operation(
|
||||
OperationType::Native(NativeOperation::EqualFromEntries),
|
||||
vec![
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use std::fmt;
|
||||
|
||||
use crate::{
|
||||
frontend::{MainPod, SignedPod},
|
||||
frontend::SignedDict,
|
||||
middleware::{
|
||||
AnchoredKey, CustomPredicateRef, NativeOperation, OperationAux, OperationType, Statement,
|
||||
TypedValue, Value, ValueRef,
|
||||
containers::Dictionary, root_key_to_ak, CustomPredicateRef, NativeOperation, OperationAux,
|
||||
OperationType, Signature, Statement, TypedValue, Value, ValueRef,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -16,12 +16,12 @@ pub enum OperationArg {
|
|||
}
|
||||
|
||||
impl OperationArg {
|
||||
/// Extracts the value underlying literal and `ValueOf` statement
|
||||
/// Extracts the value underlying literal and `Contains` statement
|
||||
/// operation args.
|
||||
pub(crate) fn value(&self) -> Option<&Value> {
|
||||
match self {
|
||||
Self::Literal(v) => Some(v),
|
||||
Self::Statement(Statement::Equal(_, ValueRef::Literal(v))) => Some(v),
|
||||
Self::Statement(Statement::Contains(_, _, ValueRef::Literal(v))) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -29,7 +29,11 @@ impl OperationArg {
|
|||
pub(crate) fn value_and_ref(&self) -> Option<(ValueRef, &Value)> {
|
||||
match self {
|
||||
Self::Literal(v) => Some((ValueRef::Literal(v.clone()), v)),
|
||||
Self::Statement(Statement::Equal(k, ValueRef::Literal(v))) => Some((k.clone(), v)),
|
||||
Self::Statement(Statement::Contains(
|
||||
ValueRef::Literal(root),
|
||||
ValueRef::Literal(key),
|
||||
ValueRef::Literal(v),
|
||||
)) => root_key_to_ak(root, key).map(|ak| (ValueRef::Key(ak), v)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -64,27 +68,21 @@ impl From<&Value> for OperationArg {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<(&SignedPod, &str)> for OperationArg {
|
||||
fn from((pod, key): (&SignedPod, &str)) -> Self {
|
||||
// TODO: TryFrom.
|
||||
let value = pod
|
||||
.kvs()
|
||||
.get(&key.into())
|
||||
.cloned()
|
||||
.unwrap_or_else(|| panic!("Key {} is not present in POD: {}", key, pod));
|
||||
Self::Statement(Statement::Equal(
|
||||
AnchoredKey::from((pod.id(), key)).into(),
|
||||
impl From<(&Dictionary, &str)> for OperationArg {
|
||||
fn from((dict, key): (&Dictionary, &str)) -> Self {
|
||||
// TODO: Use TryFrom
|
||||
let value = dict.get(&key.into()).cloned().unwrap();
|
||||
Self::Statement(Statement::Contains(
|
||||
dict.clone().into(),
|
||||
key.into(),
|
||||
value.into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
impl From<(&MainPod, &str)> for OperationArg {
|
||||
fn from((pod, key): (&MainPod, &str)) -> Self {
|
||||
// TODO: TryFrom.
|
||||
let value = pod
|
||||
.get(key)
|
||||
.unwrap_or_else(|| panic!("Key {} is not present in POD: {}", key, pod));
|
||||
Self::Statement(Statement::equal(AnchoredKey::from((pod.id(), key)), value))
|
||||
|
||||
impl From<(&SignedDict, &str)> for OperationArg {
|
||||
fn from((signed_dict, key): (&SignedDict, &str)) -> Self {
|
||||
OperationArg::from((&signed_dict.dict, key))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,13 +184,6 @@ macro_rules! op_impl_st {
|
|||
}
|
||||
|
||||
impl Operation {
|
||||
pub fn new_entry(a1: impl Into<String>, a2: impl Into<Value>) -> Self {
|
||||
Self(
|
||||
OperationType::Native(NativeOperation::NewEntry),
|
||||
vec![OperationArg::Entry(a1.into(), a2.into())],
|
||||
OperationAux::None,
|
||||
)
|
||||
}
|
||||
op_impl_oa!(eq, EqualFromEntries, 2);
|
||||
op_impl_oa!(ne, NotEqualFromEntries, 2);
|
||||
op_impl_oa!(gt_eq, GtEqFromEntries, 2);
|
||||
|
|
@ -229,4 +220,22 @@ impl Operation {
|
|||
op_impl_oa!(set_insert, SetInsertFromEntries, 3);
|
||||
op_impl_oa!(set_delete, SetDeleteFromEntries, 3);
|
||||
op_impl_oa!(array_update, ArrayUpdateFromEntries, 4);
|
||||
pub fn signed_by(
|
||||
msg: impl Into<OperationArg>,
|
||||
pk: impl Into<OperationArg>,
|
||||
sig: Signature,
|
||||
) -> Self {
|
||||
Self(
|
||||
OperationType::Native(NativeOperation::SignedBy),
|
||||
vec![msg.into(), pk.into()],
|
||||
OperationAux::Signature(sig),
|
||||
)
|
||||
}
|
||||
pub fn dict_signed_by(signed_dict: &SignedDict) -> Self {
|
||||
Self::signed_by(
|
||||
Value::from(signed_dict.dict.clone()),
|
||||
Value::from(signed_dict.public_key),
|
||||
signed_dict.signature.clone(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,8 +128,8 @@ impl PodRequest {
|
|||
}
|
||||
|
||||
// Try to bind wildcard to the POD ID
|
||||
let pod_id_value = Value::from(stmt_key.pod_id);
|
||||
self.try_bind_wildcard(&wildcard.name, pod_id_value, current_bindings, new_bindings)
|
||||
let root_value = Value::from(stmt_key.root);
|
||||
self.try_bind_wildcard(&wildcard.name, root_value, current_bindings, new_bindings)
|
||||
}
|
||||
|
||||
// Other combinations don't match
|
||||
|
|
@ -176,12 +176,14 @@ impl Display for PodRequest {
|
|||
mod tests {
|
||||
use crate::{
|
||||
backends::plonky2::{
|
||||
mock::mainpod::MockProver, primitives::ec::schnorr::SecretKey, signedpod::Signer,
|
||||
mock::mainpod::MockProver, primitives::ec::schnorr::SecretKey, signer::Signer,
|
||||
},
|
||||
examples::{
|
||||
zu_kyc_pod_builder, zu_kyc_pod_request, zu_kyc_sign_dict_builders, MOCK_VD_SET,
|
||||
},
|
||||
examples::{zu_kyc_pod_builder, zu_kyc_pod_request, zu_kyc_sign_pod_builders, MOCK_VD_SET},
|
||||
frontend::{MainPodBuilder, Operation},
|
||||
lang::parse,
|
||||
middleware::Params,
|
||||
middleware::{Params, Value},
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
|
@ -189,7 +191,7 @@ mod tests {
|
|||
let params = Params::default();
|
||||
let vd_set = &*MOCK_VD_SET;
|
||||
|
||||
let (gov_id, pay_stub) = zu_kyc_sign_pod_builders(¶ms);
|
||||
let (gov_id, pay_stub) = zu_kyc_sign_dict_builders(¶ms);
|
||||
let gov_id = gov_id.sign(&Signer(SecretKey(1u32.into()))).unwrap();
|
||||
let pay_stub = pay_stub.sign(&Signer(SecretKey(2u32.into()))).unwrap();
|
||||
let builder = zu_kyc_pod_builder(&Params::default(), vd_set, &gov_id, &pay_stub).unwrap();
|
||||
|
|
@ -198,8 +200,8 @@ mod tests {
|
|||
|
||||
// This request matches the POD
|
||||
let request = zu_kyc_pod_request(
|
||||
gov_id.get("_signer").unwrap(),
|
||||
pay_stub.get("_signer").unwrap(),
|
||||
&Value::from(gov_id.public_key),
|
||||
&Value::from(pay_stub.public_key),
|
||||
)
|
||||
.unwrap();
|
||||
assert!(request.exact_match_pod(&*kyc.pod).is_ok());
|
||||
|
|
|
|||
|
|
@ -1,73 +1,30 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::Error;
|
||||
use crate::{
|
||||
frontend::{MainPod, SignedPod},
|
||||
middleware::{
|
||||
deserialize_pod, deserialize_signed_pod, Key, Params, PodId, Statement, VDSet, Value,
|
||||
},
|
||||
frontend::MainPod,
|
||||
middleware::{deserialize_pod, Hash, Params, Statement, VDSet},
|
||||
};
|
||||
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[schemars(rename = "SignedPod")]
|
||||
pub struct SerializedSignedPod {
|
||||
pod_type: (usize, String),
|
||||
id: PodId,
|
||||
entries: HashMap<Key, Value>,
|
||||
data: serde_json::Value,
|
||||
}
|
||||
|
||||
impl SerializedSignedPod {
|
||||
pub fn id(&self) -> PodId {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[schemars(rename = "MainPod")]
|
||||
pub struct SerializedMainPod {
|
||||
params: Params,
|
||||
pod_type: (usize, String),
|
||||
id: PodId,
|
||||
id: Hash,
|
||||
vd_set: VDSet,
|
||||
public_statements: Vec<Statement>,
|
||||
data: serde_json::Value,
|
||||
}
|
||||
|
||||
impl SerializedMainPod {
|
||||
pub fn id(&self) -> PodId {
|
||||
pub fn id(&self) -> Hash {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SignedPod> for SerializedSignedPod {
|
||||
fn from(pod: SignedPod) -> Self {
|
||||
let (pod_type, pod_type_name_str) = pod.pod.pod_type();
|
||||
let data = pod.pod.serialize_data();
|
||||
SerializedSignedPod {
|
||||
pod_type: (pod_type, pod_type_name_str.to_string()),
|
||||
id: pod.id(),
|
||||
entries: pod.kvs().clone(),
|
||||
data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SerializedSignedPod> for SignedPod {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(serialized: SerializedSignedPod) -> Result<Self, Self::Error> {
|
||||
let pod = deserialize_signed_pod(serialized.pod_type.0, serialized.id, serialized.data)?;
|
||||
let kvs = pod.kvs().into_iter().map(|(ak, v)| (ak.key, v)).collect();
|
||||
Ok(Self { pod, kvs })
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MainPod> for SerializedMainPod {
|
||||
fn from(pod: MainPod) -> Self {
|
||||
let (pod_type, pod_type_name_str) = pod.pod.pod_type();
|
||||
|
|
@ -116,17 +73,17 @@ mod tests {
|
|||
mainpod::{rec_main_pod_circuit_data, Prover},
|
||||
mock::mainpod::MockProver,
|
||||
primitives::ec::schnorr::SecretKey,
|
||||
signedpod::Signer,
|
||||
signer::Signer,
|
||||
},
|
||||
examples::{
|
||||
attest_eth_friend, zu_kyc_pod_builder, zu_kyc_sign_pod_builders, EthDosHelper,
|
||||
attest_eth_friend, zu_kyc_pod_builder, zu_kyc_sign_dict_builders, EthDosHelper,
|
||||
MOCK_VD_SET,
|
||||
},
|
||||
frontend::{Result, SignedPodBuilder},
|
||||
frontend::{Result, SignedDict, SignedDictBuilder},
|
||||
middleware::{
|
||||
self,
|
||||
containers::{Array, Dictionary, Set},
|
||||
Params, TypedValue, DEFAULT_VD_LIST,
|
||||
Params, Signer as _, TypedValue, DEFAULT_VD_LIST,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -182,9 +139,9 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
fn signed_pod_builder() -> SignedPodBuilder {
|
||||
fn signed_dict_builder() -> SignedDictBuilder {
|
||||
let params = &Params::default();
|
||||
let mut builder = SignedPodBuilder::new(params);
|
||||
let mut builder = SignedDictBuilder::new(params);
|
||||
builder.insert("name", "test");
|
||||
builder.insert("age", 30);
|
||||
builder.insert("very_large_int", 1152921504606846976);
|
||||
|
|
@ -228,46 +185,29 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_signed_pod_serialization() {
|
||||
let builder = signed_pod_builder();
|
||||
fn test_signed_dict_serialization() {
|
||||
let builder = signed_dict_builder();
|
||||
let signer = Signer(SecretKey(1u32.into()));
|
||||
let pod = builder.sign(&signer).unwrap();
|
||||
let signed_dict = builder.sign(&signer).unwrap();
|
||||
|
||||
let serialized = serde_json::to_string_pretty(&pod).unwrap();
|
||||
let serialized = serde_json::to_string_pretty(&signed_dict).unwrap();
|
||||
println!("serialized: {}", serialized);
|
||||
let deserialized: SignedPod = serde_json::from_str(&serialized).unwrap();
|
||||
let deserialized: SignedDict = serde_json::from_str(&serialized).unwrap();
|
||||
println!(
|
||||
"deserialized: {}",
|
||||
serde_json::to_string_pretty(&deserialized).unwrap()
|
||||
);
|
||||
assert_eq!(pod.kvs, deserialized.kvs);
|
||||
assert_eq!(pod.verify().is_ok(), deserialized.verify().is_ok());
|
||||
assert_eq!(pod.id(), deserialized.id())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mock_signed_pod_serialization() {
|
||||
let builder = signed_pod_builder();
|
||||
let signer = Signer(SecretKey(1u32.into()));
|
||||
let pod = builder.sign(&signer).unwrap();
|
||||
|
||||
let serialized = serde_json::to_string_pretty(&pod).unwrap();
|
||||
println!("serialized: {}", serialized);
|
||||
let deserialized: SignedPod = serde_json::from_str(&serialized).unwrap();
|
||||
println!(
|
||||
"deserialized: {}",
|
||||
serde_json::to_string_pretty(&deserialized).unwrap()
|
||||
);
|
||||
assert_eq!(pod.kvs, deserialized.kvs);
|
||||
assert_eq!(pod.verify().is_ok(), deserialized.verify().is_ok());
|
||||
assert_eq!(pod.id(), deserialized.id())
|
||||
assert_eq!(signed_dict.dict.kvs(), deserialized.dict.kvs());
|
||||
assert_eq!(signed_dict.public_key, deserialized.public_key);
|
||||
assert_eq!(signed_dict.signature, deserialized.signature);
|
||||
assert_eq!(signed_dict.verify().is_ok(), deserialized.verify().is_ok());
|
||||
}
|
||||
|
||||
fn build_mock_zukyc_pod() -> Result<MainPod> {
|
||||
let params = middleware::Params::default();
|
||||
let vd_set = &*MOCK_VD_SET;
|
||||
|
||||
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_pod_builders(¶ms);
|
||||
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_dict_builders(¶ms);
|
||||
let signer = Signer(SecretKey(1u32.into()));
|
||||
let gov_id_pod = gov_id_builder.sign(&signer).unwrap();
|
||||
let signer = Signer(SecretKey(2u32.into()));
|
||||
|
|
@ -283,18 +223,19 @@ mod tests {
|
|||
let params = middleware::Params {
|
||||
// Currently the circuit uses random access that only supports vectors of length 64.
|
||||
// With max_input_main_pods=3 we need random access to a vector of length 73.
|
||||
max_input_recursive_pods: 1,
|
||||
max_input_pods: 1,
|
||||
..Default::default()
|
||||
};
|
||||
let mut vds = DEFAULT_VD_LIST.clone();
|
||||
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
||||
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
||||
|
||||
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_pod_builders(¶ms);
|
||||
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_dict_builders(¶ms);
|
||||
let signer = Signer(SecretKey(1u32.into()));
|
||||
let gov_id_pod = gov_id_builder.sign(&signer)?;
|
||||
let signer = Signer(SecretKey(2u32.into()));
|
||||
let pay_stub_pod = pay_stub_builder.sign(&signer)?;
|
||||
let _signer = Signer(SecretKey(3u32.into()));
|
||||
let kyc_builder = zu_kyc_pod_builder(¶ms, &vd_set, &gov_id_pod, &pay_stub_pod)?;
|
||||
|
||||
let prover = Prover {};
|
||||
|
|
@ -311,7 +252,10 @@ mod tests {
|
|||
let deserialized: MainPod = serde_json::from_str(&serialized).unwrap();
|
||||
|
||||
assert_eq!(kyc_pod.public_statements, deserialized.public_statements);
|
||||
assert_eq!(kyc_pod.pod.id(), deserialized.pod.id());
|
||||
assert_eq!(
|
||||
kyc_pod.pod.statements_hash(),
|
||||
deserialized.pod.statements_hash()
|
||||
);
|
||||
assert_eq!(kyc_pod.pod.verify()?, deserialized.pod.verify()?);
|
||||
|
||||
Ok(())
|
||||
|
|
@ -324,7 +268,10 @@ mod tests {
|
|||
let deserialized: MainPod = serde_json::from_str(&serialized).unwrap();
|
||||
|
||||
assert_eq!(kyc_pod.public_statements, deserialized.public_statements);
|
||||
assert_eq!(kyc_pod.pod.id(), deserialized.pod.id());
|
||||
assert_eq!(
|
||||
kyc_pod.pod.statements_hash(),
|
||||
deserialized.pod.statements_hash()
|
||||
);
|
||||
assert_eq!(kyc_pod.pod.verify()?, deserialized.pod.verify()?);
|
||||
|
||||
Ok(())
|
||||
|
|
@ -348,7 +295,7 @@ mod tests {
|
|||
let alice_attestation = attest_eth_friend(¶ms, &alice, bob.public_key());
|
||||
let bob_attestation = attest_eth_friend(¶ms, &bob, charlie.public_key());
|
||||
|
||||
let helper = EthDosHelper::new(¶ms, vd_set, true, alice.public_key())?;
|
||||
let helper = EthDosHelper::new(¶ms, vd_set, alice.public_key())?;
|
||||
let prover = MockProver {};
|
||||
let dist_1 = helper.dist_1(&alice_attestation)?.prove(&prover)?;
|
||||
let dist_2 = helper
|
||||
|
|
@ -360,28 +307,28 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
// This tests that we can generate JSON Schemas for the MainPod and
|
||||
// SignedPod types, and that we can validate Signed and Main Pods
|
||||
// SignedDict types, and that we can validate Signed and Main Pods
|
||||
// against the schemas. Since both Mock and Plonky2 PODs have the same
|
||||
// public interface, we can assume that the schema works for both.
|
||||
fn test_schema() {
|
||||
let mainpod_schema = schema_for!(SerializedMainPod);
|
||||
let signedpod_schema = schema_for!(SerializedSignedPod);
|
||||
let signeddict_schema = schema_for!(SignedDict);
|
||||
|
||||
let kyc_pod = build_mock_zukyc_pod().unwrap();
|
||||
let signed_pod = signed_pod_builder()
|
||||
let signed_dict = signed_dict_builder()
|
||||
.sign(&Signer(SecretKey(1u32.into())))
|
||||
.unwrap();
|
||||
let ethdos_pod = build_ethdos_pod().unwrap();
|
||||
let mainpod_schema_value = serde_json::to_value(&mainpod_schema).unwrap();
|
||||
let signedpod_schema_value = serde_json::to_value(&signedpod_schema).unwrap();
|
||||
let signed_dict_schema_value = serde_json::to_value(&signeddict_schema).unwrap();
|
||||
|
||||
let kyc_pod_value = serde_json::to_value(&kyc_pod).unwrap();
|
||||
let mainpod_valid = jsonschema::validate(&mainpod_schema_value, &kyc_pod_value);
|
||||
assert!(mainpod_valid.is_ok(), "{:#?}", mainpod_valid);
|
||||
|
||||
let signed_pod_value = serde_json::to_value(&signed_pod).unwrap();
|
||||
let signedpod_valid = jsonschema::validate(&signedpod_schema_value, &signed_pod_value);
|
||||
assert!(signedpod_valid.is_ok(), "{:#?}", signedpod_valid);
|
||||
let signed_dict_value = serde_json::to_value(&signed_dict).unwrap();
|
||||
let signed_dict_valid = jsonschema::validate(&signed_dict_schema_value, &signed_dict_value);
|
||||
assert!(signed_dict_valid.is_ok(), "{:#?}", signed_dict_valid);
|
||||
|
||||
let ethdos_pod_value = serde_json::to_value(ðdos_pod).unwrap();
|
||||
let ethdos_pod_valid = jsonschema::validate(&mainpod_schema_value, ðdos_pod_value);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue