chore: add statement and KV metadata to frontend PODs (#117)
* Add statement and KV metadata to frontend PODs * Code review
This commit is contained in:
parent
02ec7c311b
commit
6627b46819
17 changed files with 290 additions and 224 deletions
|
|
@ -56,7 +56,7 @@ impl Ord for Value {
|
||||||
return Ordering::Greater;
|
return Ordering::Greater;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ordering::Equal;
|
Ordering::Equal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,7 +84,7 @@ impl TryInto<i64> for Value {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
fn try_into(self) -> std::result::Result<i64, Self::Error> {
|
fn try_into(self) -> std::result::Result<i64, Self::Error> {
|
||||||
let value = self.0;
|
let value = self.0;
|
||||||
if &value[2..] != &[F::ZERO, F::ZERO]
|
if value[2..] != [F::ZERO, F::ZERO]
|
||||||
|| value[..2]
|
|| value[..2]
|
||||||
.iter()
|
.iter()
|
||||||
.all(|x| x.to_canonical_u64() > u32::MAX as u64)
|
.all(|x| x.to_canonical_u64() > u32::MAX as u64)
|
||||||
|
|
@ -118,7 +118,7 @@ pub fn hash_value(input: &Value) -> Hash {
|
||||||
Hash(PoseidonHash::hash_no_pad(&input.0).elements)
|
Hash(PoseidonHash::hash_no_pad(&input.0).elements)
|
||||||
}
|
}
|
||||||
pub fn hash_fields(input: &[F]) -> Hash {
|
pub fn hash_fields(input: &[F]) -> Hash {
|
||||||
Hash(PoseidonHash::hash_no_pad(&input).elements)
|
Hash(PoseidonHash::hash_no_pad(input).elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Value> for Hash {
|
impl From<Value> for Hash {
|
||||||
|
|
@ -208,7 +208,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_i64_value_roundtrip() {
|
fn test_i64_value_roundtrip() {
|
||||||
let test_cases = vec![
|
let test_cases = [
|
||||||
0i64,
|
0i64,
|
||||||
1,
|
1,
|
||||||
-1,
|
-1,
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ impl fmt::Display for MockMainPod {
|
||||||
|
|
||||||
let op = (i >= offset_input_statements)
|
let op = (i >= offset_input_statements)
|
||||||
.then(|| &self.operations[i - offset_input_statements]);
|
.then(|| &self.operations[i - offset_input_statements]);
|
||||||
fmt_statement_index(f, &st, op, i)?;
|
fmt_statement_index(f, st, op, i)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +102,7 @@ fn fmt_statement_index(
|
||||||
write!(f, "{}", op)?;
|
write!(f, "{}", op)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write!(f, "\n")?;
|
writeln!(f)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -151,11 +151,7 @@ impl MockMainPod {
|
||||||
let none_sig_pod: Box<dyn Pod> = Box::new(NonePod {});
|
let none_sig_pod: Box<dyn Pod> = Box::new(NonePod {});
|
||||||
assert!(inputs.signed_pods.len() <= params.max_input_signed_pods);
|
assert!(inputs.signed_pods.len() <= params.max_input_signed_pods);
|
||||||
for i in 0..params.max_input_signed_pods {
|
for i in 0..params.max_input_signed_pods {
|
||||||
let pod = inputs
|
let pod = inputs.signed_pods.get(i).copied().unwrap_or(&none_sig_pod);
|
||||||
.signed_pods
|
|
||||||
.get(i)
|
|
||||||
.map(|p| *p)
|
|
||||||
.unwrap_or(&none_sig_pod);
|
|
||||||
let sts = pod.pub_statements();
|
let sts = pod.pub_statements();
|
||||||
assert!(sts.len() <= params.max_signed_pod_values);
|
assert!(sts.len() <= params.max_signed_pod_values);
|
||||||
for j in 0..params.max_signed_pod_values {
|
for j in 0..params.max_signed_pod_values {
|
||||||
|
|
@ -173,11 +169,7 @@ impl MockMainPod {
|
||||||
let none_main_pod: Box<dyn Pod> = Box::new(NonePod {});
|
let none_main_pod: Box<dyn Pod> = Box::new(NonePod {});
|
||||||
assert!(inputs.main_pods.len() <= params.max_input_main_pods);
|
assert!(inputs.main_pods.len() <= params.max_input_main_pods);
|
||||||
for i in 0..params.max_input_main_pods {
|
for i in 0..params.max_input_main_pods {
|
||||||
let pod = inputs
|
let pod = inputs.main_pods.get(i).copied().unwrap_or(&none_main_pod);
|
||||||
.main_pods
|
|
||||||
.get(i)
|
|
||||||
.map(|p| *p)
|
|
||||||
.unwrap_or(&none_main_pod);
|
|
||||||
let sts = pod.pub_statements();
|
let sts = pod.pub_statements();
|
||||||
assert!(sts.len() <= params.max_public_statements);
|
assert!(sts.len() <= params.max_public_statements);
|
||||||
for j in 0..params.max_public_statements {
|
for j in 0..params.max_public_statements {
|
||||||
|
|
@ -241,7 +233,10 @@ impl MockMainPod {
|
||||||
(&middleware::Statement::try_from(s.clone()).ok()? == op_arg).then_some(i)
|
(&middleware::Statement::try_from(s.clone()).ok()? == op_arg).then_some(i)
|
||||||
})
|
})
|
||||||
.map(OperationArg::Index)
|
.map(OperationArg::Index)
|
||||||
.ok_or(anyhow!("statement not found")),
|
.ok_or(anyhow!(
|
||||||
|
"Statement corresponding to op arg {} not found",
|
||||||
|
op_arg
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,7 +342,7 @@ impl MockMainPod {
|
||||||
|
|
||||||
fn statement_none(params: &Params) -> Statement {
|
fn statement_none(params: &Params) -> Statement {
|
||||||
let mut args = Vec::with_capacity(params.max_statement_args);
|
let mut args = Vec::with_capacity(params.max_statement_args);
|
||||||
Self::pad_statement_args(¶ms, &mut args);
|
Self::pad_statement_args(params, &mut args);
|
||||||
Statement(Predicate::Native(NativePredicate::None), args)
|
Statement(Predicate::Native(NativePredicate::None), args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -368,7 +363,7 @@ impl MockMainPod {
|
||||||
|
|
||||||
pub fn hash_statements(statements: &[Statement], _params: &Params) -> middleware::Hash {
|
pub fn hash_statements(statements: &[Statement], _params: &Params) -> middleware::Hash {
|
||||||
let field_elems = statements
|
let field_elems = statements
|
||||||
.into_iter()
|
.iter()
|
||||||
.flat_map(|statement| statement.clone().to_fields(_params).0)
|
.flat_map(|statement| statement.clone().to_fields(_params).0)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
Hash(PoseidonHash::hash_no_pad(&field_elems).elements)
|
Hash(PoseidonHash::hash_no_pad(&field_elems).elements)
|
||||||
|
|
@ -388,7 +383,7 @@ impl Pod for MockMainPod {
|
||||||
.iter()
|
.iter()
|
||||||
.find(|s| {
|
.find(|s| {
|
||||||
s.0 == Predicate::Native(NativePredicate::ValueOf)
|
s.0 == Predicate::Native(NativePredicate::ValueOf)
|
||||||
&& s.1.len() > 0
|
&& !s.1.is_empty()
|
||||||
&& if let StatementArg::Key(AnchoredKey(pod_id, key_hash)) = s.1[0] {
|
&& if let StatementArg::Key(AnchoredKey(pod_id, key_hash)) = s.1[0] {
|
||||||
pod_id == SELF && key_hash == hash_str(KEY_TYPE)
|
pod_id == SELF && key_hash == hash_str(KEY_TYPE)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -402,7 +397,7 @@ impl Pod for MockMainPod {
|
||||||
// `NewValue` operation.
|
// `NewValue` operation.
|
||||||
let value_ofs_unique = {
|
let value_ofs_unique = {
|
||||||
let key_id_pairs = input_statements
|
let key_id_pairs = input_statements
|
||||||
.into_iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, s)| {
|
.map(|(i, s)| {
|
||||||
(
|
(
|
||||||
|
|
@ -512,9 +507,9 @@ pub mod tests {
|
||||||
|
|
||||||
println!("{:#}", pod);
|
println!("{:#}", pod);
|
||||||
|
|
||||||
assert_eq!(pod.verify(), true); // TODO
|
assert!(pod.verify()); // TODO
|
||||||
// println!("id: {}", pod.id());
|
// println!("id: {}", pod.id());
|
||||||
// println!("pub_statements: {:?}", pod.pub_statements());
|
// println!("pub_statements: {:?}", pod.pub_statements());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -533,7 +528,7 @@ pub mod tests {
|
||||||
|
|
||||||
println!("{}", pod);
|
println!("{}", pod);
|
||||||
|
|
||||||
assert_eq!(pod.verify(), true);
|
assert!(pod.verify());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -547,7 +542,7 @@ pub mod tests {
|
||||||
let pod = proof_pod.pod.into_any().downcast::<MockMainPod>().unwrap();
|
let pod = proof_pod.pod.into_any().downcast::<MockMainPod>().unwrap();
|
||||||
|
|
||||||
println!("{}", pod);
|
println!("{}", pod);
|
||||||
assert_eq!(pod.verify(), true);
|
assert!(pod.verify());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use anyhow::Result;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use super::Statement;
|
use super::Statement;
|
||||||
use crate::middleware::{self, NativeOperation, OperationType};
|
use crate::middleware::{self, OperationType};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum OperationArg {
|
pub enum OperationArg {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ impl TryFrom<Statement> for middleware::Statement {
|
||||||
type SA = StatementArg;
|
type SA = StatementArg;
|
||||||
let proper_args = s.args();
|
let proper_args = s.args();
|
||||||
let args = (
|
let args = (
|
||||||
proper_args.get(0).cloned(),
|
proper_args.first().cloned(),
|
||||||
proper_args.get(1).cloned(),
|
proper_args.get(1).cloned(),
|
||||||
proper_args.get(2).cloned(),
|
proper_args.get(2).cloned(),
|
||||||
);
|
);
|
||||||
|
|
@ -110,11 +110,11 @@ impl From<middleware::Statement> for Statement {
|
||||||
match s.code() {
|
match s.code() {
|
||||||
middleware::Predicate::Native(c) => Statement(
|
middleware::Predicate::Native(c) => Statement(
|
||||||
middleware::Predicate::Native(c),
|
middleware::Predicate::Native(c),
|
||||||
s.args().into_iter().map(|arg| arg).collect(),
|
s.args().into_iter().collect(),
|
||||||
),
|
),
|
||||||
middleware::Predicate::Custom(cpr) => Statement(
|
middleware::Predicate::Custom(cpr) => Statement(
|
||||||
middleware::Predicate::Custom(cpr),
|
middleware::Predicate::Custom(cpr),
|
||||||
s.args().into_iter().map(|arg| arg).collect(),
|
s.args().into_iter().collect(),
|
||||||
),
|
),
|
||||||
middleware::Predicate::BatchSelf(_) => unreachable!(),
|
middleware::Predicate::BatchSelf(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ impl PodSigner for MockSigner {
|
||||||
fn sign(&mut self, _params: &Params, kvs: &HashMap<Hash, Value>) -> Result<Box<dyn Pod>> {
|
fn sign(&mut self, _params: &Params, kvs: &HashMap<Hash, Value>) -> Result<Box<dyn Pod>> {
|
||||||
let mut kvs = kvs.clone();
|
let mut kvs = kvs.clone();
|
||||||
let pubkey = self.pubkey();
|
let pubkey = self.pubkey();
|
||||||
kvs.insert(hash_str(&KEY_SIGNER), pubkey);
|
kvs.insert(hash_str(KEY_SIGNER), pubkey);
|
||||||
kvs.insert(hash_str(&KEY_TYPE), Value::from(PodType::MockSigned));
|
kvs.insert(hash_str(KEY_TYPE), Value::from(PodType::MockSigned));
|
||||||
|
|
||||||
let dict = Dictionary::new(&kvs)?;
|
let dict = Dictionary::new(&kvs)?;
|
||||||
let id = PodId(dict.commitment());
|
let id = PodId(dict.commitment());
|
||||||
|
|
@ -47,7 +47,7 @@ pub struct MockSignedPod {
|
||||||
impl Pod for MockSignedPod {
|
impl Pod for MockSignedPod {
|
||||||
fn verify(&self) -> bool {
|
fn verify(&self) -> bool {
|
||||||
// Verify type
|
// Verify type
|
||||||
let value_at_type = match self.dict.get(&hash_str(&KEY_TYPE).into()) {
|
let value_at_type = match self.dict.get(&hash_str(KEY_TYPE).into()) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(_) => return false,
|
Err(_) => return false,
|
||||||
};
|
};
|
||||||
|
|
@ -73,7 +73,7 @@ impl Pod for MockSignedPod {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify signature
|
// Verify signature
|
||||||
let pk_hash = match self.dict.get(&hash_str(&KEY_SIGNER).into()) {
|
let pk_hash = match self.dict.get(&hash_str(KEY_SIGNER).into()) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(_) => return false,
|
Err(_) => return false,
|
||||||
};
|
};
|
||||||
|
|
@ -82,7 +82,7 @@ impl Pod for MockSignedPod {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id(&self) -> PodId {
|
fn id(&self) -> PodId {
|
||||||
|
|
@ -124,17 +124,17 @@ pub mod tests {
|
||||||
let pod = pod.sign(&mut signer).unwrap();
|
let pod = pod.sign(&mut signer).unwrap();
|
||||||
let pod = pod.pod.into_any().downcast::<MockSignedPod>().unwrap();
|
let pod = pod.pod.into_any().downcast::<MockSignedPod>().unwrap();
|
||||||
|
|
||||||
assert_eq!(pod.verify(), true);
|
assert!(pod.verify());
|
||||||
println!("id: {}", pod.id());
|
println!("id: {}", pod.id());
|
||||||
println!("kvs: {:?}", pod.kvs());
|
println!("kvs: {:?}", pod.kvs());
|
||||||
|
|
||||||
let mut bad_pod = pod.clone();
|
let mut bad_pod = pod.clone();
|
||||||
bad_pod.signature = "".into();
|
bad_pod.signature = "".into();
|
||||||
assert_eq!(bad_pod.verify(), false);
|
assert!(!bad_pod.verify());
|
||||||
|
|
||||||
let mut bad_pod = pod.clone();
|
let mut bad_pod = pod.clone();
|
||||||
bad_pod.id.0 .0[0] = F::ZERO;
|
bad_pod.id.0 .0[0] = F::ZERO;
|
||||||
assert_eq!(bad_pod.verify(), false);
|
assert!(!bad_pod.verify());
|
||||||
|
|
||||||
let mut bad_pod = pod.clone();
|
let mut bad_pod = pod.clone();
|
||||||
let bad_kv = (hash_str(KEY_SIGNER).into(), Value(PodId(NULL).0 .0));
|
let bad_kv = (hash_str(KEY_SIGNER).into(), Value(PodId(NULL).0 .0));
|
||||||
|
|
@ -144,9 +144,9 @@ pub mod tests {
|
||||||
.map(|(AnchoredKey(_, k), v)| (Value(k.0), v))
|
.map(|(AnchoredKey(_, k), v)| (Value(k.0), v))
|
||||||
.chain(iter::once(bad_kv))
|
.chain(iter::once(bad_kv))
|
||||||
.collect::<HashMap<Value, Value>>();
|
.collect::<HashMap<Value, Value>>();
|
||||||
let bad_mt = MerkleTree::new(MAX_DEPTH, &bad_kvs_mt)?;
|
let bad_mt = MerkleTree::new(MAX_DEPTH, bad_kvs_mt)?;
|
||||||
bad_pod.dict.mt = bad_mt;
|
bad_pod.dict.mt = bad_mt;
|
||||||
assert_eq!(bad_pod.verify(), false);
|
assert!(!bad_pod.verify());
|
||||||
|
|
||||||
let mut bad_pod = pod.clone();
|
let mut bad_pod = pod.clone();
|
||||||
let bad_kv = (hash_str(KEY_TYPE).into(), Value::from(0));
|
let bad_kv = (hash_str(KEY_TYPE).into(), Value::from(0));
|
||||||
|
|
@ -156,9 +156,9 @@ pub mod tests {
|
||||||
.map(|(AnchoredKey(_, k), v)| (Value(k.0), v))
|
.map(|(AnchoredKey(_, k), v)| (Value(k.0), v))
|
||||||
.chain(iter::once(bad_kv))
|
.chain(iter::once(bad_kv))
|
||||||
.collect::<HashMap<Value, Value>>();
|
.collect::<HashMap<Value, Value>>();
|
||||||
let bad_mt = MerkleTree::new(MAX_DEPTH, &bad_kvs_mt)?;
|
let bad_mt = MerkleTree::new(MAX_DEPTH, bad_kvs_mt)?;
|
||||||
bad_pod.dict.mt = bad_mt;
|
bad_pod.dict.mt = bad_mt;
|
||||||
assert_eq!(bad_pod.verify(), false);
|
assert!(!bad_pod.verify());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ impl MerkleTree {
|
||||||
let h = proof.compute_root_from_leaf(max_depth, key, Some(*value))?;
|
let h = proof.compute_root_from_leaf(max_depth, key, Some(*value))?;
|
||||||
|
|
||||||
if h != root {
|
if h != root {
|
||||||
return Err(anyhow!("proof of inclusion does not verify"));
|
Err(anyhow!("proof of inclusion does not verify"))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -155,7 +155,7 @@ impl MerkleTree {
|
||||||
let h = proof.compute_root_from_leaf(max_depth, &k, v)?;
|
let h = proof.compute_root_from_leaf(max_depth, &k, v)?;
|
||||||
|
|
||||||
if h != root {
|
if h != root {
|
||||||
return Err(anyhow!("proof of exclusion does not verify"));
|
Err(anyhow!("proof of exclusion does not verify"))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -332,12 +332,12 @@ impl Node {
|
||||||
if let Some(s) = siblings.as_mut() {
|
if let Some(s) = siblings.as_mut() {
|
||||||
s.push(n.left.hash());
|
s.push(n.left.hash());
|
||||||
}
|
}
|
||||||
return n.right.down(lvl + 1, max_depth, path, siblings);
|
n.right.down(lvl + 1, max_depth, path, siblings)
|
||||||
} else {
|
} else {
|
||||||
if let Some(s) = siblings.as_mut() {
|
if let Some(s) = siblings.as_mut() {
|
||||||
s.push(n.right.hash());
|
s.push(n.right.hash());
|
||||||
}
|
}
|
||||||
return n.left.down(lvl + 1, max_depth, path, siblings);
|
n.left.down(lvl + 1, max_depth, path, siblings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Leaf(Leaf {
|
Self::Leaf(Leaf {
|
||||||
|
|
@ -345,7 +345,7 @@ impl Node {
|
||||||
value,
|
value,
|
||||||
path: _p,
|
path: _p,
|
||||||
hash: _h,
|
hash: _h,
|
||||||
}) => Ok(Some((key.clone(), value.clone()))),
|
}) => Ok(Some((*key, *value))),
|
||||||
_ => Ok(None),
|
_ => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -549,8 +549,8 @@ impl<'a> Iterator for Iter<'a> {
|
||||||
left,
|
left,
|
||||||
right,
|
right,
|
||||||
})) => {
|
})) => {
|
||||||
self.state.push(&right);
|
self.state.push(right);
|
||||||
self.state.push(&left);
|
self.state.push(left);
|
||||||
self.next()
|
self.next()
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -621,7 +621,7 @@ pub mod tests {
|
||||||
|
|
||||||
match first_unequal_bits {
|
match first_unequal_bits {
|
||||||
Some((b1, b2)) => {
|
Some((b1, b2)) => {
|
||||||
if b1 < b2 {
|
if !b1 & b2 {
|
||||||
Ordering::Less
|
Ordering::Less
|
||||||
} else {
|
} else {
|
||||||
Ordering::Greater
|
Ordering::Greater
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use crate::frontend::{
|
||||||
};
|
};
|
||||||
use crate::middleware::containers::Set;
|
use crate::middleware::containers::Set;
|
||||||
use crate::middleware::{containers::Dictionary, Params, PodType, KEY_SIGNER, KEY_TYPE};
|
use crate::middleware::{containers::Dictionary, Params, PodType, KEY_SIGNER, KEY_TYPE};
|
||||||
use crate::middleware::{hash_str, CustomPredicateRef, NativeOperation, OperationType, Pod};
|
use crate::middleware::{hash_str, CustomPredicateRef, NativeOperation, OperationType};
|
||||||
use crate::op;
|
use crate::op;
|
||||||
|
|
||||||
// ZuKYC
|
// ZuKYC
|
||||||
|
|
@ -47,21 +47,21 @@ pub fn zu_kyc_pod_builder(
|
||||||
let now_minus_1y: i64 = 1706367566;
|
let now_minus_1y: i64 = 1706367566;
|
||||||
|
|
||||||
let mut kyc = MainPodBuilder::new(params);
|
let mut kyc = MainPodBuilder::new(params);
|
||||||
kyc.add_signed_pod(&gov_id);
|
kyc.add_signed_pod(gov_id);
|
||||||
kyc.add_signed_pod(&pay_stub);
|
kyc.add_signed_pod(pay_stub);
|
||||||
kyc.add_signed_pod(&sanction_list);
|
kyc.add_signed_pod(sanction_list);
|
||||||
kyc.pub_op(op!(
|
kyc.pub_op(op!(
|
||||||
not_contains,
|
not_contains,
|
||||||
(sanction_list, "sanctionList"),
|
(sanction_list, "sanctionList"),
|
||||||
(gov_id, "idNumber")
|
(gov_id, "idNumber")
|
||||||
));
|
))?;
|
||||||
kyc.pub_op(op!(lt, (gov_id, "dateOfBirth"), now_minus_18y));
|
kyc.pub_op(op!(lt, (gov_id, "dateOfBirth"), now_minus_18y))?;
|
||||||
kyc.pub_op(op!(
|
kyc.pub_op(op!(
|
||||||
eq,
|
eq,
|
||||||
(gov_id, "socialSecurityNumber"),
|
(gov_id, "socialSecurityNumber"),
|
||||||
(pay_stub, "socialSecurityNumber")
|
(pay_stub, "socialSecurityNumber")
|
||||||
));
|
))?;
|
||||||
kyc.pub_op(op!(eq, (pay_stub, "startDate"), now_minus_1y));
|
kyc.pub_op(op!(eq, (pay_stub, "startDate"), now_minus_1y))?;
|
||||||
|
|
||||||
Ok(kyc)
|
Ok(kyc)
|
||||||
}
|
}
|
||||||
|
|
@ -87,20 +87,18 @@ pub fn eth_dos_pod_builder(
|
||||||
|
|
||||||
// ETHDoS POD builder
|
// ETHDoS POD builder
|
||||||
let mut alice_bob_ethdos = MainPodBuilder::new(params);
|
let mut alice_bob_ethdos = MainPodBuilder::new(params);
|
||||||
alice_bob_ethdos.add_signed_pod(&alice_attestation);
|
alice_bob_ethdos.add_signed_pod(alice_attestation);
|
||||||
alice_bob_ethdos.add_signed_pod(&charlie_attestation);
|
alice_bob_ethdos.add_signed_pod(charlie_attestation);
|
||||||
|
|
||||||
// Attestation POD entries
|
// Attestation POD entries
|
||||||
let alice_pubkey = alice_attestation
|
let alice_pubkey = *alice_attestation
|
||||||
.kvs()
|
.kvs()
|
||||||
.get(&KEY_SIGNER.into())
|
.get(&KEY_SIGNER.into())
|
||||||
.ok_or(anyhow!("Could not find Alice's public key!"))?
|
.ok_or(anyhow!("Could not find Alice's public key!"))?;
|
||||||
.clone();
|
let charlie_pubkey = *charlie_attestation
|
||||||
let charlie_pubkey = charlie_attestation
|
|
||||||
.kvs()
|
.kvs()
|
||||||
.get(&KEY_SIGNER.into())
|
.get(&KEY_SIGNER.into())
|
||||||
.ok_or(anyhow!("Could not find Charlie's public key!"))?
|
.ok_or(anyhow!("Could not find Charlie's public key!"))?;
|
||||||
.clone();
|
|
||||||
|
|
||||||
// Include Alice and Bob's keys as public statements.
|
// Include Alice and Bob's keys as public statements.
|
||||||
let alice_pubkey_copy = alice_bob_ethdos.pub_op(Operation(
|
let alice_pubkey_copy = alice_bob_ethdos.pub_op(Operation(
|
||||||
|
|
@ -110,12 +108,9 @@ pub fn eth_dos_pod_builder(
|
||||||
alice_pubkey.into(),
|
alice_pubkey.into(),
|
||||||
)],
|
)],
|
||||||
))?;
|
))?;
|
||||||
let bob_pubkey_copy = alice_bob_ethdos.pub_op(Operation(
|
let _bob_pubkey_copy = alice_bob_ethdos.pub_op(Operation(
|
||||||
OperationType::Native(NativeOperation::NewEntry),
|
OperationType::Native(NativeOperation::NewEntry),
|
||||||
vec![OperationArg::Entry(
|
vec![OperationArg::Entry("Bob".to_string(), bob_pubkey.clone())],
|
||||||
"Bob".to_string(),
|
|
||||||
bob_pubkey.clone().into(),
|
|
||||||
)],
|
|
||||||
))?;
|
))?;
|
||||||
let charlie_pubkey = alice_bob_ethdos.priv_op(Operation(
|
let charlie_pubkey = alice_bob_ethdos.priv_op(Operation(
|
||||||
OperationType::Native(NativeOperation::NewEntry),
|
OperationType::Native(NativeOperation::NewEntry),
|
||||||
|
|
@ -137,7 +132,7 @@ pub fn eth_dos_pod_builder(
|
||||||
OperationArg::Statement(alice_pubkey_copy.clone()),
|
OperationArg::Statement(alice_pubkey_copy.clone()),
|
||||||
],
|
],
|
||||||
))?;
|
))?;
|
||||||
let ethdos_alice_alice_is_zero = alice_bob_ethdos.priv_op(Operation(
|
let _ethdos_alice_alice_is_zero = alice_bob_ethdos.priv_op(Operation(
|
||||||
OperationType::Custom(CustomPredicateRef(eth_dos_batch, 0)),
|
OperationType::Custom(CustomPredicateRef(eth_dos_batch, 0)),
|
||||||
vec![
|
vec![
|
||||||
OperationArg::Statement(alice_equals_alice),
|
OperationArg::Statement(alice_equals_alice),
|
||||||
|
|
@ -161,7 +156,7 @@ pub fn eth_dos_pod_builder(
|
||||||
OperationArg::Statement(charlie_pubkey),
|
OperationArg::Statement(charlie_pubkey),
|
||||||
],
|
],
|
||||||
))?;
|
))?;
|
||||||
let ethfriends_alice_charlie = alice_bob_ethdos.priv_op(Operation(
|
let _ethfriends_alice_charlie = alice_bob_ethdos.priv_op(Operation(
|
||||||
OperationType::Custom(CustomPredicateRef(eth_friend_batch, 0)),
|
OperationType::Custom(CustomPredicateRef(eth_friend_batch, 0)),
|
||||||
vec![
|
vec![
|
||||||
OperationArg::Statement(attestation_is_signed_pod),
|
OperationArg::Statement(attestation_is_signed_pod),
|
||||||
|
|
@ -171,7 +166,7 @@ pub fn eth_dos_pod_builder(
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
// The ETHDoS distance from Alice to Charlie is 1.
|
// The ETHDoS distance from Alice to Charlie is 1.
|
||||||
let one = alice_bob_ethdos.priv_op(Operation(
|
let _one = alice_bob_ethdos.priv_op(Operation(
|
||||||
OperationType::Native(NativeOperation::NewEntry),
|
OperationType::Native(NativeOperation::NewEntry),
|
||||||
vec![OperationArg::Entry("ZERO".to_string(), Value::from(0i64))],
|
vec![OperationArg::Entry("ZERO".to_string(), Value::from(0i64))],
|
||||||
))?;
|
))?;
|
||||||
|
|
@ -181,7 +176,7 @@ pub fn eth_dos_pod_builder(
|
||||||
// OperationType::Native(NativeOperation::SumOf
|
// OperationType::Native(NativeOperation::SumOf
|
||||||
// ),
|
// ),
|
||||||
// vec![
|
// vec![
|
||||||
// OperationArg::Statement(one.clone()),
|
// OperationArg::Statement(_one.clone()),
|
||||||
// OperationArg::Statement(zero.clone()),
|
// OperationArg::Statement(zero.clone()),
|
||||||
// OperationArg::Statement(zero.clone())
|
// OperationArg::Statement(zero.clone())
|
||||||
// ]
|
// ]
|
||||||
|
|
@ -214,7 +209,7 @@ pub fn great_boy_pod_builder(
|
||||||
friend_pods: [&SignedPod; 2],
|
friend_pods: [&SignedPod; 2],
|
||||||
good_boy_issuers: &Value,
|
good_boy_issuers: &Value,
|
||||||
receiver: &str,
|
receiver: &str,
|
||||||
) -> MainPodBuilder {
|
) -> Result<MainPodBuilder> {
|
||||||
// Attestment chain (issuer -> good boy -> great boy):
|
// Attestment chain (issuer -> good boy -> great boy):
|
||||||
// issuer 0 -> good_boy_pods[0] => good boy 0
|
// issuer 0 -> good_boy_pods[0] => good boy 0
|
||||||
// issuer 1 -> good_boy_pods[1] => good boy 0
|
// issuer 1 -> good_boy_pods[1] => good boy 0
|
||||||
|
|
@ -225,10 +220,10 @@ pub fn great_boy_pod_builder(
|
||||||
|
|
||||||
let mut great_boy = MainPodBuilder::new(params);
|
let mut great_boy = MainPodBuilder::new(params);
|
||||||
for i in 0..4 {
|
for i in 0..4 {
|
||||||
great_boy.add_signed_pod(&good_boy_pods[i]);
|
great_boy.add_signed_pod(good_boy_pods[i]);
|
||||||
}
|
}
|
||||||
for i in 0..2 {
|
for i in 0..2 {
|
||||||
great_boy.add_signed_pod(&friend_pods[i]);
|
great_boy.add_signed_pod(friend_pods[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for good_boy_idx in 0..2 {
|
for good_boy_idx in 0..2 {
|
||||||
|
|
@ -237,44 +232,44 @@ pub fn great_boy_pod_builder(
|
||||||
eq,
|
eq,
|
||||||
(friend_pods[good_boy_idx], KEY_TYPE),
|
(friend_pods[good_boy_idx], KEY_TYPE),
|
||||||
PodType::MockSigned as i64
|
PodType::MockSigned as i64
|
||||||
));
|
))?;
|
||||||
for issuer_idx in 0..2 {
|
for issuer_idx in 0..2 {
|
||||||
// Type check
|
// Type check
|
||||||
great_boy.pub_op(op!(
|
great_boy.pub_op(op!(
|
||||||
eq,
|
eq,
|
||||||
(good_boy_pods[good_boy_idx * 2 + issuer_idx], KEY_TYPE),
|
(good_boy_pods[good_boy_idx * 2 + issuer_idx], KEY_TYPE),
|
||||||
PodType::MockSigned as i64
|
PodType::MockSigned as i64
|
||||||
));
|
))?;
|
||||||
// Each good boy POD comes from a valid issuer
|
// Each good boy POD comes from a valid issuer
|
||||||
great_boy.pub_op(op!(
|
great_boy.pub_op(op!(
|
||||||
contains,
|
contains,
|
||||||
good_boy_issuers,
|
good_boy_issuers,
|
||||||
(good_boy_pods[good_boy_idx * 2 + issuer_idx], KEY_SIGNER)
|
(good_boy_pods[good_boy_idx * 2 + issuer_idx], KEY_SIGNER)
|
||||||
));
|
))?;
|
||||||
// Each good boy has 2 good boy pods
|
// Each good boy has 2 good boy pods
|
||||||
great_boy.pub_op(op!(
|
great_boy.pub_op(op!(
|
||||||
eq,
|
eq,
|
||||||
(good_boy_pods[good_boy_idx * 2 + issuer_idx], "user"),
|
(good_boy_pods[good_boy_idx * 2 + issuer_idx], "user"),
|
||||||
(friend_pods[good_boy_idx], KEY_SIGNER)
|
(friend_pods[good_boy_idx], KEY_SIGNER)
|
||||||
));
|
))?;
|
||||||
}
|
}
|
||||||
// The good boy PODs from each good boy have different issuers
|
// The good boy PODs from each good boy have different issuers
|
||||||
great_boy.pub_op(op!(
|
great_boy.pub_op(op!(
|
||||||
ne,
|
ne,
|
||||||
(good_boy_pods[good_boy_idx * 2 + 0], KEY_SIGNER),
|
(good_boy_pods[good_boy_idx * 2], KEY_SIGNER),
|
||||||
(good_boy_pods[good_boy_idx * 2 + 1], KEY_SIGNER)
|
(good_boy_pods[good_boy_idx * 2 + 1], KEY_SIGNER)
|
||||||
));
|
))?;
|
||||||
// Each good boy is receivers' friend
|
// Each good boy is receivers' friend
|
||||||
great_boy.pub_op(op!(eq, (friend_pods[good_boy_idx], "friend"), receiver));
|
great_boy.pub_op(op!(eq, (friend_pods[good_boy_idx], "friend"), receiver))?;
|
||||||
}
|
}
|
||||||
// The two good boys are different
|
// The two good boys are different
|
||||||
great_boy.pub_op(op!(
|
great_boy.pub_op(op!(
|
||||||
ne,
|
ne,
|
||||||
(friend_pods[0], KEY_SIGNER),
|
(friend_pods[0], KEY_SIGNER),
|
||||||
(friend_pods[1], KEY_SIGNER)
|
(friend_pods[1], KEY_SIGNER)
|
||||||
));
|
))?;
|
||||||
|
|
||||||
great_boy
|
Ok(great_boy)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn great_boy_pod_full_flow() -> Result<MainPodBuilder> {
|
pub fn great_boy_pod_full_flow() -> Result<MainPodBuilder> {
|
||||||
|
|
@ -306,7 +301,7 @@ pub fn great_boy_pod_full_flow() -> Result<MainPodBuilder> {
|
||||||
let bob = "Bob";
|
let bob = "Bob";
|
||||||
let mut bob_good_boys = Vec::new();
|
let mut bob_good_boys = Vec::new();
|
||||||
|
|
||||||
let good_boy = good_boy_sign_pod_builder(¶ms, &bob, 36);
|
let good_boy = good_boy_sign_pod_builder(¶ms, bob, 36);
|
||||||
bob_good_boys.push(good_boy.sign(&mut giggles_signer).unwrap());
|
bob_good_boys.push(good_boy.sign(&mut giggles_signer).unwrap());
|
||||||
bob_good_boys.push(good_boy.sign(&mut macrosoft_signer).unwrap());
|
bob_good_boys.push(good_boy.sign(&mut macrosoft_signer).unwrap());
|
||||||
|
|
||||||
|
|
@ -315,19 +310,19 @@ pub fn great_boy_pod_full_flow() -> Result<MainPodBuilder> {
|
||||||
let charlie = "Charlie";
|
let charlie = "Charlie";
|
||||||
let mut charlie_good_boys = Vec::new();
|
let mut charlie_good_boys = Vec::new();
|
||||||
|
|
||||||
let good_boy = good_boy_sign_pod_builder(¶ms, &charlie, 27);
|
let good_boy = good_boy_sign_pod_builder(¶ms, charlie, 27);
|
||||||
charlie_good_boys.push(good_boy.sign(&mut macrosoft_signer).unwrap());
|
charlie_good_boys.push(good_boy.sign(&mut macrosoft_signer).unwrap());
|
||||||
charlie_good_boys.push(good_boy.sign(&mut faebook_signer).unwrap());
|
charlie_good_boys.push(good_boy.sign(&mut faebook_signer).unwrap());
|
||||||
|
|
||||||
// Bob and Charlie send Alice a Friend POD
|
// Bob and Charlie send Alice a Friend POD
|
||||||
|
|
||||||
let mut alice_friend_pods = Vec::new();
|
let mut alice_friend_pods = Vec::new();
|
||||||
let friend = friend_sign_pod_builder(¶ms, &alice);
|
let friend = friend_sign_pod_builder(¶ms, alice);
|
||||||
alice_friend_pods.push(friend.sign(&mut bob_signer).unwrap());
|
alice_friend_pods.push(friend.sign(&mut bob_signer).unwrap());
|
||||||
alice_friend_pods.push(friend.sign(&mut charlie_signer).unwrap());
|
alice_friend_pods.push(friend.sign(&mut charlie_signer).unwrap());
|
||||||
|
|
||||||
let good_boy_issuers_dict = Value::Dictionary(Dictionary::new(&HashMap::new())?); // empty
|
let good_boy_issuers_dict = Value::Dictionary(Dictionary::new(&HashMap::new())?); // empty
|
||||||
Ok(great_boy_pod_builder(
|
great_boy_pod_builder(
|
||||||
¶ms,
|
¶ms,
|
||||||
[
|
[
|
||||||
&bob_good_boys[0],
|
&bob_good_boys[0],
|
||||||
|
|
@ -338,7 +333,7 @@ pub fn great_boy_pod_full_flow() -> Result<MainPodBuilder> {
|
||||||
[&alice_friend_pods[0], &alice_friend_pods[1]],
|
[&alice_friend_pods[0], &alice_friend_pods[1]],
|
||||||
&good_boy_issuers_dict,
|
&good_boy_issuers_dict,
|
||||||
alice,
|
alice,
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tickets
|
// Tickets
|
||||||
|
|
@ -361,30 +356,30 @@ pub fn tickets_pod_builder(
|
||||||
expected_event_id: i64,
|
expected_event_id: i64,
|
||||||
expect_consumed: bool,
|
expect_consumed: bool,
|
||||||
blacklisted_emails: &Value,
|
blacklisted_emails: &Value,
|
||||||
) -> MainPodBuilder {
|
) -> Result<MainPodBuilder> {
|
||||||
// Create a main pod referencing this signed pod with some statements
|
// Create a main pod referencing this signed pod with some statements
|
||||||
let mut builder = MainPodBuilder::new(params);
|
let mut builder = MainPodBuilder::new(params);
|
||||||
builder.add_signed_pod(signed_pod);
|
builder.add_signed_pod(signed_pod);
|
||||||
builder.pub_op(op!(eq, (signed_pod, "eventId"), expected_event_id));
|
builder.pub_op(op!(eq, (signed_pod, "eventId"), expected_event_id))?;
|
||||||
builder.pub_op(op!(eq, (signed_pod, "isConsumed"), expect_consumed));
|
builder.pub_op(op!(eq, (signed_pod, "isConsumed"), expect_consumed))?;
|
||||||
builder.pub_op(op!(eq, (signed_pod, "isRevoked"), false));
|
builder.pub_op(op!(eq, (signed_pod, "isRevoked"), false))?;
|
||||||
builder.pub_op(op!(
|
builder.pub_op(op!(
|
||||||
not_contains,
|
not_contains,
|
||||||
blacklisted_emails,
|
blacklisted_emails,
|
||||||
(signed_pod, "attendeeEmail")
|
(signed_pod, "attendeeEmail")
|
||||||
));
|
))?;
|
||||||
builder
|
Ok(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tickets_pod_full_flow() -> Result<MainPodBuilder> {
|
pub fn tickets_pod_full_flow() -> Result<MainPodBuilder> {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
let builder = tickets_sign_pod_builder(¶ms);
|
let builder = tickets_sign_pod_builder(¶ms);
|
||||||
let signed_pod = builder.sign(&mut MockSigner { pk: "test".into() }).unwrap();
|
let signed_pod = builder.sign(&mut MockSigner { pk: "test".into() }).unwrap();
|
||||||
Ok(tickets_pod_builder(
|
tickets_pod_builder(
|
||||||
¶ms,
|
¶ms,
|
||||||
&signed_pod,
|
&signed_pod,
|
||||||
123,
|
123,
|
||||||
true,
|
true,
|
||||||
&Value::Dictionary(Dictionary::new(&HashMap::new())?),
|
&Value::Dictionary(Dictionary::new(&HashMap::new())?),
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ pub fn eth_dos_batch(params: &Params) -> Result<Arc<CustomPredicateBatch>> {
|
||||||
// ValueOf(distance_or, distance_key, 0)
|
// ValueOf(distance_or, distance_key, 0)
|
||||||
// >
|
// >
|
||||||
let eth_dos_distance_base = builder.predicate_and(
|
let eth_dos_distance_base = builder.predicate_and(
|
||||||
¶ms,
|
params,
|
||||||
&[
|
&[
|
||||||
// arguments:
|
// arguments:
|
||||||
"src_ori",
|
"src_ori",
|
||||||
|
|
@ -83,7 +83,7 @@ pub fn eth_dos_batch(params: &Params) -> Result<Arc<CustomPredicateBatch>> {
|
||||||
let eth_dos_distance = Predicate::BatchSelf(2);
|
let eth_dos_distance = Predicate::BatchSelf(2);
|
||||||
|
|
||||||
let eth_dos_distance_ind = builder.predicate_and(
|
let eth_dos_distance_ind = builder.predicate_and(
|
||||||
¶ms,
|
params,
|
||||||
&[
|
&[
|
||||||
// arguments:
|
// arguments:
|
||||||
"src_ori",
|
"src_ori",
|
||||||
|
|
@ -127,7 +127,7 @@ pub fn eth_dos_batch(params: &Params) -> Result<Arc<CustomPredicateBatch>> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let _eth_dos_distance = builder.predicate_or(
|
let _eth_dos_distance = builder.predicate_or(
|
||||||
¶ms,
|
params,
|
||||||
&[
|
&[
|
||||||
"src_ori",
|
"src_ori",
|
||||||
"src_key",
|
"src_key",
|
||||||
|
|
|
||||||
|
|
@ -44,13 +44,13 @@ impl From<(&str, HashOrWildcardStr)> for BuilderArg {
|
||||||
HashOrWildcardStr::Hash(_) => (),
|
HashOrWildcardStr::Hash(_) => (),
|
||||||
_ => panic!("not supported"),
|
_ => panic!("not supported"),
|
||||||
};
|
};
|
||||||
Self::Key(wildcard(&origin), lit)
|
Self::Key(wildcard(origin), lit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// case ii.
|
/// case ii.
|
||||||
impl From<(&str, &str)> for BuilderArg {
|
impl From<(&str, &str)> for BuilderArg {
|
||||||
fn from((origin, field): (&str, &str)) -> Self {
|
fn from((origin, field): (&str, &str)) -> Self {
|
||||||
Self::Key(wildcard(&origin), wildcard(&field))
|
Self::Key(wildcard(origin), wildcard(field))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// case iii.
|
/// case iii.
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ use anyhow::{anyhow, Result};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use std::sync::Arc;
|
|
||||||
use std::{fmt, hash as h};
|
use std::{fmt, hash as h};
|
||||||
|
|
||||||
use crate::middleware::{
|
use crate::middleware::{
|
||||||
|
|
@ -14,7 +13,7 @@ use crate::middleware::{
|
||||||
hash_str, Hash, MainPodInputs, NativeOperation, NativePredicate, Params, PodId, PodProver,
|
hash_str, Hash, MainPodInputs, NativeOperation, NativePredicate, Params, PodId, PodProver,
|
||||||
PodSigner, SELF,
|
PodSigner, SELF,
|
||||||
};
|
};
|
||||||
use crate::middleware::{OperationType, Predicate, KEY_SIGNER};
|
use crate::middleware::{OperationType, Predicate, KEY_SIGNER, KEY_TYPE};
|
||||||
|
|
||||||
mod custom;
|
mod custom;
|
||||||
mod operation;
|
mod operation;
|
||||||
|
|
@ -73,7 +72,7 @@ impl From<&Value> for middleware::Value {
|
||||||
Value::Dictionary(d) => d.commitment().value(),
|
Value::Dictionary(d) => d.commitment().value(),
|
||||||
Value::Set(s) => s.commitment().value(),
|
Value::Set(s) => s.commitment().value(),
|
||||||
Value::Array(a) => a.commitment().value(),
|
Value::Array(a) => a.commitment().value(),
|
||||||
Value::Raw(v) => v.clone(),
|
Value::Raw(v) => *v,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -127,22 +126,36 @@ impl SignedPodBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sign<S: PodSigner>(&self, signer: &mut S) -> Result<SignedPod> {
|
pub fn sign<S: PodSigner>(&self, signer: &mut S) -> Result<SignedPod> {
|
||||||
let mut kvs = HashMap::new();
|
// Sign POD with committed KV store.
|
||||||
let mut key_string_map = HashMap::new();
|
let committed_kvs = self
|
||||||
let mut value_hash_map = HashMap::new();
|
.kvs
|
||||||
for (k, v) in self.kvs.iter() {
|
.iter()
|
||||||
let k_hash = hash_str(k);
|
.map(|(k, v)| (hash_str(k), v.into()))
|
||||||
let v_hash = middleware::Value::from(v);
|
.collect::<HashMap<_, _>>();
|
||||||
kvs.insert(k_hash, v_hash);
|
let pod = signer.sign(&self.params, &committed_kvs)?;
|
||||||
key_string_map.insert(k_hash, k.clone());
|
|
||||||
value_hash_map.insert(v_hash.into(), v.clone());
|
let mut kvs = self.kvs.clone();
|
||||||
}
|
|
||||||
let pod = signer.sign(&self.params, &kvs)?;
|
// Type and signer information are passed in by the
|
||||||
Ok(SignedPod {
|
// backend. Include these in the frontend representation.
|
||||||
pod,
|
let mid_kvs = pod.kvs();
|
||||||
key_string_map,
|
let pod_type = mid_kvs
|
||||||
value_hash_map,
|
.get(&crate::middleware::AnchoredKey(
|
||||||
})
|
pod.id(),
|
||||||
|
hash_str(KEY_TYPE),
|
||||||
|
))
|
||||||
|
.cloned()
|
||||||
|
.ok_or(anyhow!("Missing POD type information in POD: {:?}", pod))?;
|
||||||
|
let pod_signer = mid_kvs
|
||||||
|
.get(&crate::middleware::AnchoredKey(
|
||||||
|
pod.id(),
|
||||||
|
hash_str(KEY_SIGNER),
|
||||||
|
))
|
||||||
|
.cloned()
|
||||||
|
.ok_or(anyhow!("Missing POD signer in POD: {:?}", pod))?;
|
||||||
|
kvs.insert(KEY_TYPE.to_string(), pod_type.into());
|
||||||
|
kvs.insert(KEY_SIGNER.to_string(), pod_signer.into());
|
||||||
|
Ok(SignedPod { pod, kvs })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,10 +164,10 @@ impl SignedPodBuilder {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SignedPod {
|
pub struct SignedPod {
|
||||||
pub pod: Box<dyn middleware::Pod>,
|
pub pod: Box<dyn middleware::Pod>,
|
||||||
/// HashMap to store the reverse relation between key strings and key hashes
|
/// Key-value pairs as represented in the frontend. These should
|
||||||
pub key_string_map: HashMap<Hash, String>,
|
/// correspond to the entries of `pod.kvs()` after hashing and
|
||||||
/// HashMap to store the reverse relation between values and their hashes
|
/// replacing each key with its corresponding anchored key.
|
||||||
pub value_hash_map: HashMap<Hash, Value>,
|
pub kvs: HashMap<String, Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for SignedPod {
|
impl fmt::Display for SignedPod {
|
||||||
|
|
@ -164,13 +177,13 @@ impl fmt::Display for SignedPod {
|
||||||
// https://0xparc.github.io/pod2/merkletree.html will not need it since it will be
|
// 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
|
// deterministic based on the keys values not on the order of the keys when added into the
|
||||||
// tree.
|
// tree.
|
||||||
for (k, v) in self.kvs().iter().sorted_by_key(|kv| kv.0) {
|
for (k, v) in self.kvs.iter().sorted_by_key(|kv| kv.0) {
|
||||||
writeln!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
" - {} = {}: {}",
|
" - {} = {}: {}",
|
||||||
|
hash_str(k),
|
||||||
k,
|
k,
|
||||||
*self.key_string_map.get(&k).unwrap_or(&"--".to_string()),
|
crate::middleware::Value::from(v)
|
||||||
v
|
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -234,7 +247,7 @@ impl fmt::Display for MainPodBuilder {
|
||||||
for (st, op) in self.statements.iter().zip_eq(self.operations.iter()) {
|
for (st, op) in self.statements.iter().zip_eq(self.operations.iter()) {
|
||||||
write!(f, " - {} <- ", st)?;
|
write!(f, " - {} <- ", st)?;
|
||||||
write!(f, "{}", op)?;
|
write!(f, "{}", op)?;
|
||||||
write!(f, "\n")?;
|
writeln!(f)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -251,25 +264,35 @@ impl MainPodBuilder {
|
||||||
public_statements: Vec::new(),
|
public_statements: Vec::new(),
|
||||||
const_cnt: 0,
|
const_cnt: 0,
|
||||||
key_table: HashMap::new(),
|
key_table: HashMap::new(),
|
||||||
pod_class_table: HashMap::from_iter([(SELF, PodClass::Main)].into_iter()),
|
pod_class_table: HashMap::from_iter([(SELF, PodClass::Main)]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn add_signed_pod(&mut self, pod: &SignedPod) {
|
pub fn add_signed_pod(&mut self, pod: &SignedPod) {
|
||||||
self.input_signed_pods.push(pod.clone());
|
self.input_signed_pods.push(pod.clone());
|
||||||
pod.key_string_map.iter().for_each(|(hash, key)| {
|
// Add key-hash correspondences to key table.
|
||||||
self.key_table.insert(hash.clone(), key.clone());
|
pod.kvs.iter().for_each(|(key, _)| {
|
||||||
|
self.key_table.insert(hash_str(key), key.clone());
|
||||||
});
|
});
|
||||||
|
// Add POD class to POD class table.
|
||||||
self.pod_class_table.insert(pod.id(), PodClass::Signed);
|
self.pod_class_table.insert(pod.id(), PodClass::Signed);
|
||||||
}
|
}
|
||||||
pub fn add_main_pod(&mut self, pod: MainPod) {
|
pub fn add_main_pod(&mut self, pod: MainPod) {
|
||||||
|
// Add POD class to POD class table.
|
||||||
self.pod_class_table.insert(pod.id(), PodClass::Main);
|
self.pod_class_table.insert(pod.id(), PodClass::Main);
|
||||||
pod.key_string_map.iter().for_each(|(hash, key)| {
|
// Add key-hash and POD ID-class correspondences to tables.
|
||||||
self.key_table.insert(hash.clone(), key.clone());
|
pod.public_statements
|
||||||
});
|
.iter()
|
||||||
pod.pod_class_map.iter().for_each(|(pod_id, pod_class)| {
|
.flat_map(|s| &s.1)
|
||||||
self.pod_class_table
|
.flat_map(|arg| match arg {
|
||||||
.insert(pod_id.clone(), pod_class.clone());
|
StatementArg::Key(AnchoredKey(Origin(pod_class, pod_id), key)) => {
|
||||||
});
|
Some((*pod_id, pod_class.clone(), hash_str(key), key.clone()))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.for_each(|(pod_id, pod_class, hash, key)| {
|
||||||
|
self.pod_class_table.insert(pod_id, pod_class);
|
||||||
|
self.key_table.insert(hash, key);
|
||||||
|
});
|
||||||
self.input_main_pods.push(pod);
|
self.input_main_pods.push(pod);
|
||||||
}
|
}
|
||||||
pub fn insert(&mut self, st_op: (Statement, Operation)) {
|
pub fn insert(&mut self, st_op: (Statement, Operation)) {
|
||||||
|
|
@ -417,11 +440,10 @@ impl MainPodBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add key-hash pairs in statement to table.
|
// Add key-hash pairs in statement to table.
|
||||||
(&st).1.iter().for_each(|arg| match arg {
|
st.1.iter().for_each(|arg| {
|
||||||
StatementArg::Key(AnchoredKey(_, key)) => {
|
if let StatementArg::Key(AnchoredKey(_, key)) = arg {
|
||||||
self.key_table.insert(hash_str(key), key.clone());
|
self.key_table.insert(hash_str(key), key.clone());
|
||||||
}
|
}
|
||||||
_ => (),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
self.statements.push(st);
|
self.statements.push(st);
|
||||||
|
|
@ -441,27 +463,6 @@ impl MainPodBuilder {
|
||||||
operations: &self.operations,
|
operations: &self.operations,
|
||||||
public_statements: &self.public_statements,
|
public_statements: &self.public_statements,
|
||||||
};
|
};
|
||||||
let key_string_map = inputs
|
|
||||||
.public_statements
|
|
||||||
.iter()
|
|
||||||
.flat_map(|s| &s.1)
|
|
||||||
.flat_map(|arg| match arg {
|
|
||||||
StatementArg::Key(AnchoredKey(_, key)) => Some((hash_str(key), key.clone())),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.collect::<HashMap<_, _>>();
|
|
||||||
|
|
||||||
let pod_class_map = (&inputs)
|
|
||||||
.public_statements
|
|
||||||
.into_iter()
|
|
||||||
.flat_map(|s| &s.1)
|
|
||||||
.flat_map(|arg| match arg {
|
|
||||||
StatementArg::Key(AnchoredKey(Origin(pod_class, pod_id), _)) => {
|
|
||||||
Some((pod_id.clone(), pod_class.clone()))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.collect::<HashMap<_, _>>();
|
|
||||||
|
|
||||||
let (statements, operations, public_statements) = compiler.compile(inputs, params)?;
|
let (statements, operations, public_statements) = compiler.compile(inputs, params)?;
|
||||||
let inputs = MainPodInputs {
|
let inputs = MainPodInputs {
|
||||||
|
|
@ -472,10 +473,54 @@ impl MainPodBuilder {
|
||||||
public_statements: &public_statements,
|
public_statements: &public_statements,
|
||||||
};
|
};
|
||||||
let pod = prover.prove(&self.params, inputs)?;
|
let pod = prover.prove(&self.params, 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 {
|
||||||
|
crate::middleware::Statement::ValueOf(
|
||||||
|
crate::middleware::AnchoredKey(id, key),
|
||||||
|
value,
|
||||||
|
) if id == pod_id && key == type_key_hash => Some(Statement(
|
||||||
|
Predicate::Native(NativePredicate::ValueOf),
|
||||||
|
vec![
|
||||||
|
StatementArg::Key(AnchoredKey(
|
||||||
|
Origin(PodClass::Main, pod_id),
|
||||||
|
KEY_TYPE.to_string(),
|
||||||
|
)),
|
||||||
|
StatementArg::Literal(value.into()),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.ok_or(anyhow!("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.0;
|
||||||
|
let s_args = s
|
||||||
|
.1
|
||||||
|
.into_iter()
|
||||||
|
.map(|arg| match arg {
|
||||||
|
StatementArg::Key(AnchoredKey(Origin(class, id), key)) if id == SELF => {
|
||||||
|
StatementArg::Key(AnchoredKey(Origin(class, pod_id), key))
|
||||||
|
}
|
||||||
|
_ => arg,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Statement(s_type, s_args)
|
||||||
|
}))
|
||||||
|
.collect();
|
||||||
|
|
||||||
Ok(MainPod {
|
Ok(MainPod {
|
||||||
pod,
|
pod,
|
||||||
key_string_map,
|
public_statements,
|
||||||
pod_class_map,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -483,9 +528,7 @@ impl MainPodBuilder {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MainPod {
|
pub struct MainPod {
|
||||||
pub pod: Box<dyn middleware::Pod>,
|
pub pod: Box<dyn middleware::Pod>,
|
||||||
// TODO: metadata
|
pub public_statements: Vec<Statement>,
|
||||||
pub key_string_map: HashMap<Hash, String>,
|
|
||||||
pub pod_class_map: HashMap<PodId, PodClass>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for MainPod {
|
impl fmt::Display for MainPod {
|
||||||
|
|
@ -590,9 +633,9 @@ impl MainPodCompiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile<'a>(
|
pub fn compile(
|
||||||
mut self,
|
mut self,
|
||||||
inputs: MainPodCompilerInputs<'a>,
|
inputs: MainPodCompilerInputs<'_>,
|
||||||
params: &Params,
|
params: &Params,
|
||||||
) -> Result<(
|
) -> Result<(
|
||||||
Vec<middleware::Statement>, // input statements
|
Vec<middleware::Statement>, // input statements
|
||||||
|
|
@ -627,16 +670,16 @@ impl MainPodCompiler {
|
||||||
pub mod build_utils {
|
pub mod build_utils {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! op_args {
|
macro_rules! op_args {
|
||||||
($($arg:expr),+) => {vec![$(crate::frontend::OperationArg::from($arg)),*]}
|
($($arg:expr),+) => {vec![$($crate::frontend::OperationArg::from($arg)),*]}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! op {
|
macro_rules! op {
|
||||||
(eq, $($arg:expr),+) => { crate::frontend::Operation(
|
(eq, $($arg:expr),+) => { $crate::frontend::Operation(
|
||||||
crate::middleware::OperationType::Native(crate::middleware::NativeOperation::EqualFromEntries),
|
$crate::middleware::OperationType::Native($crate::middleware::NativeOperation::EqualFromEntries),
|
||||||
crate::op_args!($($arg),*)) };
|
$crate::op_args!($($arg),*)) };
|
||||||
(ne, $($arg:expr),+) => { crate::frontend::Operation(
|
(ne, $($arg:expr),+) => { $crate::frontend::Operation(
|
||||||
crate::middleware::OperationType::Native(crate::middleware::NativeOperation::NotEqualFromEntries),
|
$crate::middleware::OperationType::Native(crate::middleware::NativeOperation::NotEqualFromEntries),
|
||||||
crate::op_args!($($arg),*)) };
|
crate::op_args!($($arg),*)) };
|
||||||
(gt, $($arg:expr),+) => { crate::frontend::Operation(
|
(gt, $($arg:expr),+) => { crate::frontend::Operation(
|
||||||
crate::middleware::OperationType::Native(crate::middleware::NativeOperation::GtFromEntries),
|
crate::middleware::OperationType::Native(crate::middleware::NativeOperation::GtFromEntries),
|
||||||
|
|
@ -663,6 +706,40 @@ pub mod tests {
|
||||||
tickets_pod_full_flow, zu_kyc_pod_builder, zu_kyc_sign_pod_builders,
|
tickets_pod_full_flow, zu_kyc_pod_builder, zu_kyc_sign_pod_builders,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check that frontend public statements agree with those
|
||||||
|
// embedded in a MainPod.
|
||||||
|
fn check_public_statements(pod: &MainPod) -> Result<()> {
|
||||||
|
std::iter::zip(pod.public_statements.clone(), pod.pod.pub_statements()).try_for_each(
|
||||||
|
|(fes, s)| crate::middleware::Statement::try_from(fes).map(|fes| assert_eq!(fes, s)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that frontend key-values agree with those embedded in a
|
||||||
|
// SignedPod.
|
||||||
|
fn check_kvs(pod: &SignedPod) -> Result<()> {
|
||||||
|
let kvs = pod
|
||||||
|
.kvs
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| (hash_str(k), middleware::Value::from(v)))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
let embedded_kvs = pod
|
||||||
|
.pod
|
||||||
|
.kvs()
|
||||||
|
.into_iter()
|
||||||
|
.map(|(middleware::AnchoredKey(_, k), v)| (k, v))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
if kvs == embedded_kvs {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(anyhow!(
|
||||||
|
"KVs {:?} do not agree with those embedded in the POD: {:?}",
|
||||||
|
kvs,
|
||||||
|
embedded_kvs
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_front_zu_kyc() -> Result<()> {
|
fn test_front_zu_kyc() -> Result<()> {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
|
|
@ -675,29 +752,33 @@ pub mod tests {
|
||||||
pk: "ZooGov".into(),
|
pk: "ZooGov".into(),
|
||||||
};
|
};
|
||||||
let gov_id = gov_id.sign(&mut signer)?;
|
let gov_id = gov_id.sign(&mut signer)?;
|
||||||
|
check_kvs(&gov_id)?;
|
||||||
println!("{}", gov_id);
|
println!("{}", gov_id);
|
||||||
|
|
||||||
let mut signer = MockSigner {
|
let mut signer = MockSigner {
|
||||||
pk: "ZooDeel".into(),
|
pk: "ZooDeel".into(),
|
||||||
};
|
};
|
||||||
let pay_stub = pay_stub.sign(&mut signer)?;
|
let pay_stub = pay_stub.sign(&mut signer)?;
|
||||||
|
check_kvs(&pay_stub)?;
|
||||||
println!("{}", pay_stub);
|
println!("{}", pay_stub);
|
||||||
|
|
||||||
let mut signer = MockSigner {
|
let mut signer = MockSigner {
|
||||||
pk: "ZooOFAC".into(),
|
pk: "ZooOFAC".into(),
|
||||||
};
|
};
|
||||||
let sanction_list = sanction_list.sign(&mut signer)?;
|
let sanction_list = sanction_list.sign(&mut signer)?;
|
||||||
|
check_kvs(&sanction_list)?;
|
||||||
println!("{}", sanction_list);
|
println!("{}", sanction_list);
|
||||||
|
|
||||||
let kyc_builder = zu_kyc_pod_builder(¶ms, &gov_id, &pay_stub, &sanction_list)?;
|
let kyc_builder = zu_kyc_pod_builder(¶ms, &gov_id, &pay_stub, &sanction_list)?;
|
||||||
println!("{}", kyc_builder);
|
println!("{}", kyc_builder);
|
||||||
|
|
||||||
|
// prove kyc with MockProver and print it
|
||||||
let mut prover = MockProver {};
|
let mut prover = MockProver {};
|
||||||
let kyc = kyc_builder.prove(&mut prover, ¶ms)?;
|
let kyc = kyc_builder.prove(&mut prover, ¶ms)?;
|
||||||
|
|
||||||
println!("{}", kyc);
|
println!("{}", kyc);
|
||||||
|
|
||||||
Ok(())
|
check_public_statements(&kyc)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -705,7 +786,7 @@ pub mod tests {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
|
|
||||||
let mut alice = MockSigner { pk: "Alice".into() };
|
let mut alice = MockSigner { pk: "Alice".into() };
|
||||||
let mut bob = MockSigner { pk: "Bob".into() };
|
let bob = MockSigner { pk: "Bob".into() };
|
||||||
let mut charlie = MockSigner {
|
let mut charlie = MockSigner {
|
||||||
pk: "Charlie".into(),
|
pk: "Charlie".into(),
|
||||||
};
|
};
|
||||||
|
|
@ -714,8 +795,10 @@ pub mod tests {
|
||||||
// attests that he is ETH friends with Bob.
|
// attests that he is ETH friends with Bob.
|
||||||
let alice_attestation =
|
let alice_attestation =
|
||||||
eth_friend_signed_pod_builder(¶ms, charlie.pubkey().into()).sign(&mut alice)?;
|
eth_friend_signed_pod_builder(¶ms, charlie.pubkey().into()).sign(&mut alice)?;
|
||||||
|
check_kvs(&alice_attestation)?;
|
||||||
let charlie_attestation =
|
let charlie_attestation =
|
||||||
eth_friend_signed_pod_builder(¶ms, bob.pubkey().into()).sign(&mut charlie)?;
|
eth_friend_signed_pod_builder(¶ms, bob.pubkey().into()).sign(&mut charlie)?;
|
||||||
|
check_kvs(&charlie_attestation)?;
|
||||||
|
|
||||||
let mut prover = MockProver {};
|
let mut prover = MockProver {};
|
||||||
let alice_bob_ethdos = eth_dos_pod_builder(
|
let alice_bob_ethdos = eth_dos_pod_builder(
|
||||||
|
|
@ -726,7 +809,7 @@ pub mod tests {
|
||||||
)?
|
)?
|
||||||
.prove(&mut prover, ¶ms)?;
|
.prove(&mut prover, ¶ms)?;
|
||||||
|
|
||||||
Ok(())
|
check_public_statements(&alice_bob_ethdos)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use super::{AnchoredKey, SignedPod, Statement, StatementArg, Value};
|
use super::{SignedPod, Statement, Value};
|
||||||
use crate::middleware::{hash_str, NativePredicate, OperationType, Predicate};
|
use crate::middleware::OperationType;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum OperationArg {
|
pub enum OperationArg {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use anyhow::{anyhow, Result};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use super::{AnchoredKey, SignedPod, Value};
|
use super::{AnchoredKey, SignedPod, Value};
|
||||||
use crate::middleware::{self, hash_str, NativePredicate, Predicate};
|
use crate::middleware::{self, NativePredicate, Predicate};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum StatementArg {
|
pub enum StatementArg {
|
||||||
|
|
@ -24,13 +24,12 @@ pub struct Statement(pub Predicate, pub Vec<StatementArg>);
|
||||||
|
|
||||||
impl From<(&SignedPod, &str)> for Statement {
|
impl From<(&SignedPod, &str)> for Statement {
|
||||||
fn from((pod, key): (&SignedPod, &str)) -> Self {
|
fn from((pod, key): (&SignedPod, &str)) -> Self {
|
||||||
// TODO: Actual value, TryFrom.
|
// TODO: TryFrom.
|
||||||
let value_hash = pod.kvs().get(&hash_str(key)).cloned().unwrap();
|
|
||||||
let value = pod
|
let value = pod
|
||||||
.value_hash_map
|
.kvs
|
||||||
.get(&value_hash.into())
|
.get(key)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(Value::Raw(value_hash));
|
.unwrap_or_else(|| panic!("Key {} is not present in POD: {}", key, pod));
|
||||||
Statement(
|
Statement(
|
||||||
Predicate::Native(NativePredicate::ValueOf),
|
Predicate::Native(NativePredicate::ValueOf),
|
||||||
vec![
|
vec![
|
||||||
|
|
@ -48,7 +47,7 @@ impl TryFrom<Statement> for middleware::Statement {
|
||||||
type NP = NativePredicate;
|
type NP = NativePredicate;
|
||||||
type SA = StatementArg;
|
type SA = StatementArg;
|
||||||
let args = (
|
let args = (
|
||||||
s.1.get(0).cloned(),
|
s.1.first().cloned(),
|
||||||
s.1.get(1).cloned(),
|
s.1.get(1).cloned(),
|
||||||
s.1.get(2).cloned(),
|
s.1.get(2).cloned(),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ pub struct Dictionary {
|
||||||
|
|
||||||
impl Dictionary {
|
impl Dictionary {
|
||||||
pub fn new(kvs: &HashMap<Hash, Value>) -> Result<Self> {
|
pub fn new(kvs: &HashMap<Hash, Value>) -> Result<Self> {
|
||||||
let kvs: HashMap<Value, Value> = kvs.into_iter().map(|(&k, &v)| (Value(k.0), v)).collect();
|
let kvs: HashMap<Value, Value> = kvs.iter().map(|(&k, &v)| (Value(k.0), v)).collect();
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
mt: MerkleTree::new(MAX_DEPTH, &kvs)?,
|
mt: MerkleTree::new(MAX_DEPTH, &kvs)?,
|
||||||
})
|
})
|
||||||
|
|
@ -75,7 +75,7 @@ pub struct Set {
|
||||||
impl Set {
|
impl Set {
|
||||||
pub fn new(set: &Vec<Value>) -> Result<Self> {
|
pub fn new(set: &Vec<Value>) -> Result<Self> {
|
||||||
let kvs: HashMap<Value, Value> = set
|
let kvs: HashMap<Value, Value> = set
|
||||||
.into_iter()
|
.iter()
|
||||||
.map(|e| {
|
.map(|e| {
|
||||||
let h = hash_value(e);
|
let h = hash_value(e);
|
||||||
(Value::from(h), EMPTY)
|
(Value::from(h), EMPTY)
|
||||||
|
|
@ -128,7 +128,7 @@ pub struct Array {
|
||||||
impl Array {
|
impl Array {
|
||||||
pub fn new(array: &Vec<Value>) -> Result<Self> {
|
pub fn new(array: &Vec<Value>) -> Result<Self> {
|
||||||
let kvs: HashMap<Value, Value> = array
|
let kvs: HashMap<Value, Value> = array
|
||||||
.into_iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, &e)| (Value::from(i as i64), e))
|
.map(|(i, &e)| (Value::from(i as i64), e))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ impl HashOrWildcard {
|
||||||
/// match is possible.
|
/// match is possible.
|
||||||
pub fn match_against(&self, v: &Value) -> Result<Option<(usize, Value)>> {
|
pub fn match_against(&self, v: &Value) -> Result<Option<(usize, Value)>> {
|
||||||
match self {
|
match self {
|
||||||
HashOrWildcard::Hash(h) if &Value::from(h.clone()) == v => Ok(None),
|
HashOrWildcard::Hash(h) if &Value::from(*h) == v => Ok(None),
|
||||||
HashOrWildcard::Wildcard(i) => Ok(Some((*i, v.clone()))),
|
HashOrWildcard::Wildcard(i) => Ok(Some((*i, *v))),
|
||||||
_ => Err(anyhow!(
|
_ => Err(anyhow!(
|
||||||
"Failed to match hash or wildcard {} against value {}.",
|
"Failed to match hash or wildcard {} against value {}.",
|
||||||
self,
|
self,
|
||||||
|
|
@ -79,9 +79,9 @@ impl StatementTmplArg {
|
||||||
(Self::None, StatementArg::None) => Ok(vec![]),
|
(Self::None, StatementArg::None) => Ok(vec![]),
|
||||||
(Self::Literal(v), StatementArg::Literal(w)) if v == w => Ok(vec![]),
|
(Self::Literal(v), StatementArg::Literal(w)) if v == w => Ok(vec![]),
|
||||||
(Self::Key(tmpl_o, tmpl_k), StatementArg::Key(AnchoredKey(PodId(o), k))) => {
|
(Self::Key(tmpl_o, tmpl_k), StatementArg::Key(AnchoredKey(PodId(o), k))) => {
|
||||||
let o_corr = tmpl_o.match_against(&o.clone().into())?;
|
let o_corr = tmpl_o.match_against(&(*o).into())?;
|
||||||
let k_corr = tmpl_k.match_against(&k.clone().into())?;
|
let k_corr = tmpl_k.match_against(&(*k).into())?;
|
||||||
Ok([o_corr, k_corr].into_iter().flat_map(|x| x).collect())
|
Ok([o_corr, k_corr].into_iter().flatten().collect())
|
||||||
}
|
}
|
||||||
_ => Err(anyhow!(
|
_ => Err(anyhow!(
|
||||||
"Failed to match statement template argument {:?} against statement argument {:?}.",
|
"Failed to match statement template argument {:?} against statement argument {:?}.",
|
||||||
|
|
@ -110,15 +110,15 @@ impl ToFields for StatementTmplArg {
|
||||||
}
|
}
|
||||||
StatementTmplArg::Literal(v) => {
|
StatementTmplArg::Literal(v) => {
|
||||||
let fields: Vec<F> = std::iter::once(F::from_canonical_u64(1))
|
let fields: Vec<F> = std::iter::once(F::from_canonical_u64(1))
|
||||||
.chain(v.to_fields(_params).0.into_iter())
|
.chain(v.to_fields(_params).0)
|
||||||
.chain(std::iter::repeat_with(|| F::from_canonical_u64(0)).take(hash_size))
|
.chain(std::iter::repeat_with(|| F::from_canonical_u64(0)).take(hash_size))
|
||||||
.collect();
|
.collect();
|
||||||
(fields, statement_tmpl_arg_size)
|
(fields, statement_tmpl_arg_size)
|
||||||
}
|
}
|
||||||
StatementTmplArg::Key(hw1, hw2) => {
|
StatementTmplArg::Key(hw1, hw2) => {
|
||||||
let fields: Vec<F> = std::iter::once(F::from_canonical_u64(2))
|
let fields: Vec<F> = std::iter::once(F::from_canonical_u64(2))
|
||||||
.chain(hw1.to_fields(_params).0.into_iter())
|
.chain(hw1.to_fields(_params).0)
|
||||||
.chain(hw2.to_fields(_params).0.into_iter())
|
.chain(hw2.to_fields(_params).0)
|
||||||
.collect();
|
.collect();
|
||||||
(fields, statement_tmpl_arg_size)
|
(fields, statement_tmpl_arg_size)
|
||||||
}
|
}
|
||||||
|
|
@ -325,8 +325,8 @@ impl ToFields for CustomPredicateBatch {
|
||||||
impl CustomPredicateBatch {
|
impl CustomPredicateBatch {
|
||||||
pub fn hash(&self, _params: &Params) -> Hash {
|
pub fn hash(&self, _params: &Params) -> Hash {
|
||||||
let input = self.to_fields(_params).0;
|
let input = self.to_fields(_params).0;
|
||||||
let h = hash_fields(&input);
|
|
||||||
h
|
hash_fields(&input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -335,7 +335,7 @@ pub struct CustomPredicateRef(pub Arc<CustomPredicateBatch>, pub usize);
|
||||||
|
|
||||||
impl CustomPredicateRef {
|
impl CustomPredicateRef {
|
||||||
pub fn arg_len(&self) -> usize {
|
pub fn arg_len(&self) -> usize {
|
||||||
(*self.0).predicates[self.1].args_len
|
self.0.predicates[self.1].args_len
|
||||||
}
|
}
|
||||||
pub fn match_against(&self, statements: &[Statement]) -> Result<HashMap<usize, Value>> {
|
pub fn match_against(&self, statements: &[Statement]) -> Result<HashMap<usize, Value>> {
|
||||||
let mut bindings = HashMap::new();
|
let mut bindings = HashMap::new();
|
||||||
|
|
@ -414,7 +414,7 @@ impl ToFields for Predicate {
|
||||||
// in every case: pad to (hash_size + 2) field elements
|
// in every case: pad to (hash_size + 2) field elements
|
||||||
let mut fields: Vec<F> = match self {
|
let mut fields: Vec<F> = match self {
|
||||||
Self::Native(p) => std::iter::once(F::from_canonical_u64(1))
|
Self::Native(p) => std::iter::once(F::from_canonical_u64(1))
|
||||||
.chain(p.to_fields(_params).0.into_iter())
|
.chain(p.to_fields(_params).0)
|
||||||
.collect(),
|
.collect(),
|
||||||
Self::BatchSelf(i) => std::iter::once(F::from_canonical_u64(2))
|
Self::BatchSelf(i) => std::iter::once(F::from_canonical_u64(2))
|
||||||
.chain(std::iter::once(F::from_canonical_usize(*i)))
|
.chain(std::iter::once(F::from_canonical_usize(*i)))
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ impl Params {
|
||||||
self.max_custom_batch_size * self.custom_predicate_size()
|
self.max_custom_batch_size * self.custom_predicate_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_serialized_sizes(&self) -> () {
|
pub fn print_serialized_sizes(&self) {
|
||||||
println!("Parameter sizes:");
|
println!("Parameter sizes:");
|
||||||
println!(
|
println!(
|
||||||
" Statement template argument: {}",
|
" Statement template argument: {}",
|
||||||
|
|
@ -146,7 +146,7 @@ impl Params {
|
||||||
" Custom predicate batch: {}",
|
" Custom predicate batch: {}",
|
||||||
self.custom_predicate_batch_size_field_elts()
|
self.custom_predicate_batch_size_field_elts()
|
||||||
);
|
);
|
||||||
println!("");
|
println!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,9 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
|
||||||
use super::{CustomPredicateRef, Statement};
|
use super::{CustomPredicateRef, Statement};
|
||||||
use crate::{
|
use crate::middleware::{AnchoredKey, Params, Value, SELF};
|
||||||
middleware::{
|
|
||||||
AnchoredKey, CustomPredicate, Params, PodId, Predicate, StatementTmpl, Value, SELF,
|
|
||||||
},
|
|
||||||
util::hashmap_insert_no_dupe,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum OperationType {
|
pub enum OperationType {
|
||||||
|
|
@ -109,7 +103,7 @@ impl Operation {
|
||||||
pub fn op(op_code: OperationType, args: &[Statement]) -> Result<Self> {
|
pub fn op(op_code: OperationType, args: &[Statement]) -> Result<Self> {
|
||||||
type NO = NativeOperation;
|
type NO = NativeOperation;
|
||||||
let arg_tup = (
|
let arg_tup = (
|
||||||
args.get(0).cloned(),
|
args.first().cloned(),
|
||||||
args.get(1).cloned(),
|
args.get(1).cloned(),
|
||||||
args.get(2).cloned(),
|
args.get(2).cloned(),
|
||||||
);
|
);
|
||||||
|
|
@ -148,7 +142,7 @@ impl Operation {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/// Checks the given operation against a statement.
|
/// Checks the given operation against a statement.
|
||||||
pub fn check(&self, params: &Params, output_statement: &Statement) -> Result<bool> {
|
pub fn check(&self, _params: &Params, output_statement: &Statement) -> Result<bool> {
|
||||||
use Statement::*;
|
use Statement::*;
|
||||||
match (self, output_statement) {
|
match (self, output_statement) {
|
||||||
(Self::None, None) => Ok(true),
|
(Self::None, None) => Ok(true),
|
||||||
|
|
@ -189,9 +183,9 @@ impl Operation {
|
||||||
Self::SumOf(ValueOf(ak1, v1), ValueOf(ak2, v2), ValueOf(ak3, v3)),
|
Self::SumOf(ValueOf(ak1, v1), ValueOf(ak2, v2), ValueOf(ak3, v3)),
|
||||||
SumOf(ak4, ak5, ak6),
|
SumOf(ak4, ak5, ak6),
|
||||||
) => {
|
) => {
|
||||||
let v1: i64 = v1.clone().try_into()?;
|
let v1: i64 = (*v1).try_into()?;
|
||||||
let v2: i64 = v2.clone().try_into()?;
|
let v2: i64 = (*v2).try_into()?;
|
||||||
let v3: i64 = v3.clone().try_into()?;
|
let v3: i64 = (*v3).try_into()?;
|
||||||
Ok((v1 == v2 + v3) && ak4 == ak1 && ak5 == ak2 && ak6 == ak3)
|
Ok((v1 == v2 + v3) && ak4 == ak1 && ak5 == ak2 && ak6 == ak3)
|
||||||
}
|
}
|
||||||
(Self::Custom(CustomPredicateRef(cpb, i), args), Custom(cpr, s_args))
|
(Self::Custom(CustomPredicateRef(cpb, i), args), Custom(cpr, s_args))
|
||||||
|
|
@ -214,8 +208,8 @@ impl Operation {
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<Result<Vec<_>>>()?;
|
||||||
let s_args = s_args
|
let s_args = s_args
|
||||||
.into_iter()
|
.iter()
|
||||||
.flat_map(|AnchoredKey(o, k)| [Value::from(o.0.clone()), k.clone().into()])
|
.flat_map(|AnchoredKey(o, k)| [Value::from(o.0), (*k).into()])
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
if bound_args != s_args {
|
if bound_args != s_args {
|
||||||
Err(anyhow!("Arguments to output statement {} do not match those implied by operation {:?}", output_statement,self))
|
Err(anyhow!("Arguments to output statement {} do not match those implied by operation {:?}", output_statement,self))
|
||||||
|
|
@ -237,7 +231,7 @@ impl fmt::Display for Operation {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
writeln!(f, "middleware::Operation:")?;
|
writeln!(f, "middleware::Operation:")?;
|
||||||
writeln!(f, " {:?} ", self.code())?;
|
writeln!(f, " {:?} ", self.code())?;
|
||||||
for (i, arg) in self.args().iter().enumerate() {
|
for (_, arg) in self.args().iter().enumerate() {
|
||||||
writeln!(f, " {}", arg)?;
|
writeln!(f, " {}", arg)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ impl Statement {
|
||||||
Self::SumOf(ak1, ak2, ak3) => vec![Key(ak1), Key(ak2), Key(ak3)],
|
Self::SumOf(ak1, ak2, ak3) => vec![Key(ak1), Key(ak2), Key(ak3)],
|
||||||
Self::ProductOf(ak1, ak2, ak3) => vec![Key(ak1), Key(ak2), Key(ak3)],
|
Self::ProductOf(ak1, ak2, ak3) => vec![Key(ak1), Key(ak2), Key(ak3)],
|
||||||
Self::MaxOf(ak1, ak2, ak3) => vec![Key(ak1), Key(ak2), Key(ak3)],
|
Self::MaxOf(ak1, ak2, ak3) => vec![Key(ak1), Key(ak2), Key(ak3)],
|
||||||
Self::Custom(_, args) => Vec::from_iter(args.into_iter().map(|h| Key(h))),
|
Self::Custom(_, args) => Vec::from_iter(args.into_iter().map(Key)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue