diff --git a/src/backends/plonky2/basetypes.rs b/src/backends/plonky2/basetypes.rs index 5bec085..e8cda34 100644 --- a/src/backends/plonky2/basetypes.rs +++ b/src/backends/plonky2/basetypes.rs @@ -56,7 +56,7 @@ impl Ord for Value { return Ordering::Greater; } } - return Ordering::Equal; + Ordering::Equal } } @@ -84,7 +84,7 @@ impl TryInto for Value { type Error = Error; fn try_into(self) -> std::result::Result { let value = self.0; - if &value[2..] != &[F::ZERO, F::ZERO] + if value[2..] != [F::ZERO, F::ZERO] || value[..2] .iter() .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) } pub fn hash_fields(input: &[F]) -> Hash { - Hash(PoseidonHash::hash_no_pad(&input).elements) + Hash(PoseidonHash::hash_no_pad(input).elements) } impl From for Hash { @@ -208,7 +208,7 @@ mod tests { #[test] fn test_i64_value_roundtrip() { - let test_cases = vec![ + let test_cases = [ 0i64, 1, -1, diff --git a/src/backends/plonky2/mock_main/mod.rs b/src/backends/plonky2/mock_main/mod.rs index 1c4377b..28d2bb5 100644 --- a/src/backends/plonky2/mock_main/mod.rs +++ b/src/backends/plonky2/mock_main/mod.rs @@ -75,7 +75,7 @@ impl fmt::Display for MockMainPod { let op = (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(()) } @@ -102,7 +102,7 @@ fn fmt_statement_index( write!(f, "{}", op)?; } } - write!(f, "\n")?; + writeln!(f)?; } Ok(()) } @@ -151,11 +151,7 @@ impl MockMainPod { let none_sig_pod: Box = Box::new(NonePod {}); assert!(inputs.signed_pods.len() <= params.max_input_signed_pods); for i in 0..params.max_input_signed_pods { - let pod = inputs - .signed_pods - .get(i) - .map(|p| *p) - .unwrap_or(&none_sig_pod); + let pod = inputs.signed_pods.get(i).copied().unwrap_or(&none_sig_pod); let sts = pod.pub_statements(); assert!(sts.len() <= 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 = Box::new(NonePod {}); assert!(inputs.main_pods.len() <= params.max_input_main_pods); for i in 0..params.max_input_main_pods { - let pod = inputs - .main_pods - .get(i) - .map(|p| *p) - .unwrap_or(&none_main_pod); + let pod = inputs.main_pods.get(i).copied().unwrap_or(&none_main_pod); let sts = pod.pub_statements(); assert!(sts.len() <= 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) }) .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 { 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) } @@ -368,7 +363,7 @@ impl MockMainPod { pub fn hash_statements(statements: &[Statement], _params: &Params) -> middleware::Hash { let field_elems = statements - .into_iter() + .iter() .flat_map(|statement| statement.clone().to_fields(_params).0) .collect::>(); Hash(PoseidonHash::hash_no_pad(&field_elems).elements) @@ -388,7 +383,7 @@ impl Pod for MockMainPod { .iter() .find(|s| { 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] { pod_id == SELF && key_hash == hash_str(KEY_TYPE) } else { @@ -402,7 +397,7 @@ impl Pod for MockMainPod { // `NewValue` operation. let value_ofs_unique = { let key_id_pairs = input_statements - .into_iter() + .iter() .enumerate() .map(|(i, s)| { ( @@ -512,9 +507,9 @@ pub mod tests { println!("{:#}", pod); - assert_eq!(pod.verify(), true); // TODO - // println!("id: {}", pod.id()); - // println!("pub_statements: {:?}", pod.pub_statements()); + assert!(pod.verify()); // TODO + // println!("id: {}", pod.id()); + // println!("pub_statements: {:?}", pod.pub_statements()); Ok(()) } @@ -533,7 +528,7 @@ pub mod tests { println!("{}", pod); - assert_eq!(pod.verify(), true); + assert!(pod.verify()); Ok(()) } @@ -547,7 +542,7 @@ pub mod tests { let pod = proof_pod.pod.into_any().downcast::().unwrap(); println!("{}", pod); - assert_eq!(pod.verify(), true); + assert!(pod.verify()); Ok(()) } diff --git a/src/backends/plonky2/mock_main/operation.rs b/src/backends/plonky2/mock_main/operation.rs index c1ec964..9e2bd96 100644 --- a/src/backends/plonky2/mock_main/operation.rs +++ b/src/backends/plonky2/mock_main/operation.rs @@ -2,7 +2,7 @@ use anyhow::Result; use std::fmt; use super::Statement; -use crate::middleware::{self, NativeOperation, OperationType}; +use crate::middleware::{self, OperationType}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum OperationArg { diff --git a/src/backends/plonky2/mock_main/statement.rs b/src/backends/plonky2/mock_main/statement.rs index 69343df..452a29c 100644 --- a/src/backends/plonky2/mock_main/statement.rs +++ b/src/backends/plonky2/mock_main/statement.rs @@ -50,7 +50,7 @@ impl TryFrom for middleware::Statement { type SA = StatementArg; let proper_args = s.args(); let args = ( - proper_args.get(0).cloned(), + proper_args.first().cloned(), proper_args.get(1).cloned(), proper_args.get(2).cloned(), ); @@ -110,11 +110,11 @@ impl From for Statement { match s.code() { middleware::Predicate::Native(c) => Statement( 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), - s.args().into_iter().map(|arg| arg).collect(), + s.args().into_iter().collect(), ), middleware::Predicate::BatchSelf(_) => unreachable!(), } diff --git a/src/backends/plonky2/mock_signed.rs b/src/backends/plonky2/mock_signed.rs index 46a9095..d86264c 100644 --- a/src/backends/plonky2/mock_signed.rs +++ b/src/backends/plonky2/mock_signed.rs @@ -23,8 +23,8 @@ impl PodSigner for MockSigner { fn sign(&mut self, _params: &Params, kvs: &HashMap) -> Result> { let mut kvs = kvs.clone(); let pubkey = self.pubkey(); - kvs.insert(hash_str(&KEY_SIGNER), pubkey); - kvs.insert(hash_str(&KEY_TYPE), Value::from(PodType::MockSigned)); + kvs.insert(hash_str(KEY_SIGNER), pubkey); + kvs.insert(hash_str(KEY_TYPE), Value::from(PodType::MockSigned)); let dict = Dictionary::new(&kvs)?; let id = PodId(dict.commitment()); @@ -47,7 +47,7 @@ pub struct MockSignedPod { impl Pod for MockSignedPod { fn verify(&self) -> bool { // 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, Err(_) => return false, }; @@ -73,7 +73,7 @@ impl Pod for MockSignedPod { } // 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, Err(_) => return false, }; @@ -82,7 +82,7 @@ impl Pod for MockSignedPod { return false; } - return true; + true } fn id(&self) -> PodId { @@ -124,17 +124,17 @@ pub mod tests { let pod = pod.sign(&mut signer).unwrap(); let pod = pod.pod.into_any().downcast::().unwrap(); - assert_eq!(pod.verify(), true); + assert!(pod.verify()); println!("id: {}", pod.id()); println!("kvs: {:?}", pod.kvs()); let mut bad_pod = pod.clone(); bad_pod.signature = "".into(); - assert_eq!(bad_pod.verify(), false); + assert!(!bad_pod.verify()); let mut bad_pod = pod.clone(); 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 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)) .chain(iter::once(bad_kv)) .collect::>(); - 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; - assert_eq!(bad_pod.verify(), false); + assert!(!bad_pod.verify()); let mut bad_pod = pod.clone(); 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)) .chain(iter::once(bad_kv)) .collect::>(); - 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; - assert_eq!(bad_pod.verify(), false); + assert!(!bad_pod.verify()); Ok(()) } diff --git a/src/backends/plonky2/primitives/merkletree.rs b/src/backends/plonky2/primitives/merkletree.rs index b80b640..67b5820 100644 --- a/src/backends/plonky2/primitives/merkletree.rs +++ b/src/backends/plonky2/primitives/merkletree.rs @@ -133,7 +133,7 @@ impl MerkleTree { let h = proof.compute_root_from_leaf(max_depth, key, Some(*value))?; if h != root { - return Err(anyhow!("proof of inclusion does not verify")); + Err(anyhow!("proof of inclusion does not verify")) } else { Ok(()) } @@ -155,7 +155,7 @@ impl MerkleTree { let h = proof.compute_root_from_leaf(max_depth, &k, v)?; if h != root { - return Err(anyhow!("proof of exclusion does not verify")); + Err(anyhow!("proof of exclusion does not verify")) } else { Ok(()) } @@ -332,12 +332,12 @@ impl Node { if let Some(s) = siblings.as_mut() { 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 { if let Some(s) = siblings.as_mut() { 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 { @@ -345,7 +345,7 @@ impl Node { value, path: _p, hash: _h, - }) => Ok(Some((key.clone(), value.clone()))), + }) => Ok(Some((*key, *value))), _ => Ok(None), } } @@ -549,8 +549,8 @@ impl<'a> Iterator for Iter<'a> { left, right, })) => { - self.state.push(&right); - self.state.push(&left); + self.state.push(right); + self.state.push(left); self.next() } _ => None, @@ -621,7 +621,7 @@ pub mod tests { match first_unequal_bits { Some((b1, b2)) => { - if b1 < b2 { + if !b1 & b2 { Ordering::Less } else { Ordering::Greater diff --git a/src/examples.rs b/src/examples.rs index be19a93..7af2e58 100644 --- a/src/examples.rs +++ b/src/examples.rs @@ -10,7 +10,7 @@ use crate::frontend::{ }; use crate::middleware::containers::Set; 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; // ZuKYC @@ -47,21 +47,21 @@ pub fn zu_kyc_pod_builder( let now_minus_1y: i64 = 1706367566; let mut kyc = MainPodBuilder::new(params); - kyc.add_signed_pod(&gov_id); - kyc.add_signed_pod(&pay_stub); - kyc.add_signed_pod(&sanction_list); + kyc.add_signed_pod(gov_id); + kyc.add_signed_pod(pay_stub); + kyc.add_signed_pod(sanction_list); kyc.pub_op(op!( not_contains, (sanction_list, "sanctionList"), (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!( eq, (gov_id, "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) } @@ -87,20 +87,18 @@ pub fn eth_dos_pod_builder( // ETHDoS POD builder let mut alice_bob_ethdos = MainPodBuilder::new(params); - alice_bob_ethdos.add_signed_pod(&alice_attestation); - alice_bob_ethdos.add_signed_pod(&charlie_attestation); + alice_bob_ethdos.add_signed_pod(alice_attestation); + alice_bob_ethdos.add_signed_pod(charlie_attestation); // Attestation POD entries - let alice_pubkey = alice_attestation + let alice_pubkey = *alice_attestation .kvs() .get(&KEY_SIGNER.into()) - .ok_or(anyhow!("Could not find Alice's public key!"))? - .clone(); - let charlie_pubkey = charlie_attestation + .ok_or(anyhow!("Could not find Alice's public key!"))?; + let charlie_pubkey = *charlie_attestation .kvs() .get(&KEY_SIGNER.into()) - .ok_or(anyhow!("Could not find Charlie's public key!"))? - .clone(); + .ok_or(anyhow!("Could not find Charlie's public key!"))?; // Include Alice and Bob's keys as public statements. let alice_pubkey_copy = alice_bob_ethdos.pub_op(Operation( @@ -110,12 +108,9 @@ pub fn eth_dos_pod_builder( 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), - vec![OperationArg::Entry( - "Bob".to_string(), - bob_pubkey.clone().into(), - )], + vec![OperationArg::Entry("Bob".to_string(), bob_pubkey.clone())], ))?; let charlie_pubkey = alice_bob_ethdos.priv_op(Operation( OperationType::Native(NativeOperation::NewEntry), @@ -137,7 +132,7 @@ pub fn eth_dos_pod_builder( 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)), vec![ OperationArg::Statement(alice_equals_alice), @@ -161,7 +156,7 @@ pub fn eth_dos_pod_builder( 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)), vec![ 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. - let one = alice_bob_ethdos.priv_op(Operation( + let _one = alice_bob_ethdos.priv_op(Operation( OperationType::Native(NativeOperation::NewEntry), vec![OperationArg::Entry("ZERO".to_string(), Value::from(0i64))], ))?; @@ -181,7 +176,7 @@ pub fn eth_dos_pod_builder( // OperationType::Native(NativeOperation::SumOf // ), // vec![ - // OperationArg::Statement(one.clone()), + // OperationArg::Statement(_one.clone()), // OperationArg::Statement(zero.clone()), // OperationArg::Statement(zero.clone()) // ] @@ -214,7 +209,7 @@ pub fn great_boy_pod_builder( friend_pods: [&SignedPod; 2], good_boy_issuers: &Value, receiver: &str, -) -> MainPodBuilder { +) -> Result { // Attestment chain (issuer -> good boy -> great boy): // issuer 0 -> good_boy_pods[0] => 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); 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 { - great_boy.add_signed_pod(&friend_pods[i]); + great_boy.add_signed_pod(friend_pods[i]); } for good_boy_idx in 0..2 { @@ -237,44 +232,44 @@ pub fn great_boy_pod_builder( eq, (friend_pods[good_boy_idx], KEY_TYPE), PodType::MockSigned as i64 - )); + ))?; for issuer_idx in 0..2 { // Type check great_boy.pub_op(op!( eq, (good_boy_pods[good_boy_idx * 2 + issuer_idx], KEY_TYPE), PodType::MockSigned as i64 - )); + ))?; // Each good boy POD comes from a valid issuer great_boy.pub_op(op!( contains, good_boy_issuers, (good_boy_pods[good_boy_idx * 2 + issuer_idx], KEY_SIGNER) - )); + ))?; // Each good boy has 2 good boy pods great_boy.pub_op(op!( eq, (good_boy_pods[good_boy_idx * 2 + issuer_idx], "user"), (friend_pods[good_boy_idx], KEY_SIGNER) - )); + ))?; } // The good boy PODs from each good boy have different issuers great_boy.pub_op(op!( 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) - )); + ))?; // 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 great_boy.pub_op(op!( ne, (friend_pods[0], KEY_SIGNER), (friend_pods[1], KEY_SIGNER) - )); + ))?; - great_boy + Ok(great_boy) } pub fn great_boy_pod_full_flow() -> Result { @@ -306,7 +301,7 @@ pub fn great_boy_pod_full_flow() -> Result { let bob = "Bob"; 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 macrosoft_signer).unwrap()); @@ -315,19 +310,19 @@ pub fn great_boy_pod_full_flow() -> Result { let charlie = "Charlie"; 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 faebook_signer).unwrap()); // Bob and Charlie send Alice a Friend POD 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 charlie_signer).unwrap()); let good_boy_issuers_dict = Value::Dictionary(Dictionary::new(&HashMap::new())?); // empty - Ok(great_boy_pod_builder( + great_boy_pod_builder( ¶ms, [ &bob_good_boys[0], @@ -338,7 +333,7 @@ pub fn great_boy_pod_full_flow() -> Result { [&alice_friend_pods[0], &alice_friend_pods[1]], &good_boy_issuers_dict, alice, - )) + ) } // Tickets @@ -361,30 +356,30 @@ pub fn tickets_pod_builder( expected_event_id: i64, expect_consumed: bool, blacklisted_emails: &Value, -) -> MainPodBuilder { +) -> Result { // Create a main pod referencing this signed pod with some statements let mut builder = MainPodBuilder::new(params); builder.add_signed_pod(signed_pod); - 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, "isRevoked"), false)); + 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, "isRevoked"), false))?; builder.pub_op(op!( not_contains, blacklisted_emails, (signed_pod, "attendeeEmail") - )); - builder + ))?; + Ok(builder) } pub fn tickets_pod_full_flow() -> Result { let params = Params::default(); let builder = tickets_sign_pod_builder(¶ms); let signed_pod = builder.sign(&mut MockSigner { pk: "test".into() }).unwrap(); - Ok(tickets_pod_builder( + tickets_pod_builder( ¶ms, &signed_pod, 123, true, &Value::Dictionary(Dictionary::new(&HashMap::new())?), - )) + ) } diff --git a/src/examples/custom.rs b/src/examples/custom.rs index 8d3b541..e88ca93 100644 --- a/src/examples/custom.rs +++ b/src/examples/custom.rs @@ -53,7 +53,7 @@ pub fn eth_dos_batch(params: &Params) -> Result> { // ValueOf(distance_or, distance_key, 0) // > let eth_dos_distance_base = builder.predicate_and( - ¶ms, + params, &[ // arguments: "src_ori", @@ -83,7 +83,7 @@ pub fn eth_dos_batch(params: &Params) -> Result> { let eth_dos_distance = Predicate::BatchSelf(2); let eth_dos_distance_ind = builder.predicate_and( - ¶ms, + params, &[ // arguments: "src_ori", @@ -127,7 +127,7 @@ pub fn eth_dos_batch(params: &Params) -> Result> { ); let _eth_dos_distance = builder.predicate_or( - ¶ms, + params, &[ "src_ori", "src_key", diff --git a/src/frontend/custom.rs b/src/frontend/custom.rs index 668ee71..9ef8e8d 100644 --- a/src/frontend/custom.rs +++ b/src/frontend/custom.rs @@ -44,13 +44,13 @@ impl From<(&str, HashOrWildcardStr)> for BuilderArg { HashOrWildcardStr::Hash(_) => (), _ => panic!("not supported"), }; - Self::Key(wildcard(&origin), lit) + Self::Key(wildcard(origin), lit) } } /// case ii. impl From<(&str, &str)> for BuilderArg { fn from((origin, field): (&str, &str)) -> Self { - Self::Key(wildcard(&origin), wildcard(&field)) + Self::Key(wildcard(origin), wildcard(field)) } } /// case iii. diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 372f40c..a0b70ac 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -5,7 +5,6 @@ use anyhow::{anyhow, Result}; use itertools::Itertools; use std::collections::HashMap; use std::convert::From; -use std::sync::Arc; use std::{fmt, hash as h}; use crate::middleware::{ @@ -14,7 +13,7 @@ use crate::middleware::{ hash_str, Hash, MainPodInputs, NativeOperation, NativePredicate, Params, PodId, PodProver, PodSigner, SELF, }; -use crate::middleware::{OperationType, Predicate, KEY_SIGNER}; +use crate::middleware::{OperationType, Predicate, KEY_SIGNER, KEY_TYPE}; mod custom; mod operation; @@ -73,7 +72,7 @@ impl From<&Value> for middleware::Value { Value::Dictionary(d) => d.commitment().value(), Value::Set(s) => s.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(&self, signer: &mut S) -> Result { - let mut kvs = HashMap::new(); - let mut key_string_map = HashMap::new(); - let mut value_hash_map = HashMap::new(); - for (k, v) in self.kvs.iter() { - let k_hash = hash_str(k); - let v_hash = middleware::Value::from(v); - kvs.insert(k_hash, v_hash); - key_string_map.insert(k_hash, k.clone()); - value_hash_map.insert(v_hash.into(), v.clone()); - } - let pod = signer.sign(&self.params, &kvs)?; - Ok(SignedPod { - pod, - key_string_map, - value_hash_map, - }) + // Sign POD with committed KV store. + let committed_kvs = self + .kvs + .iter() + .map(|(k, v)| (hash_str(k), v.into())) + .collect::>(); + let pod = signer.sign(&self.params, &committed_kvs)?; + + let mut kvs = self.kvs.clone(); + + // Type and signer information are passed in by the + // backend. Include these in the frontend representation. + let mid_kvs = pod.kvs(); + let pod_type = mid_kvs + .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)] pub struct SignedPod { pub pod: Box, - /// HashMap to store the reverse relation between key strings and key hashes - pub key_string_map: HashMap, - /// HashMap to store the reverse relation between values and their hashes - pub value_hash_map: HashMap, + /// Key-value pairs as represented in the frontend. These should + /// correspond to the entries of `pod.kvs()` after hashing and + /// replacing each key with its corresponding anchored key. + pub kvs: HashMap, } 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 // deterministic based on the keys values not on the order of the keys when added into the // 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!( f, " - {} = {}: {}", + hash_str(k), k, - *self.key_string_map.get(&k).unwrap_or(&"--".to_string()), - v + crate::middleware::Value::from(v) )?; } Ok(()) @@ -234,7 +247,7 @@ impl fmt::Display for MainPodBuilder { for (st, op) in self.statements.iter().zip_eq(self.operations.iter()) { write!(f, " - {} <- ", st)?; write!(f, "{}", op)?; - write!(f, "\n")?; + writeln!(f)?; } Ok(()) } @@ -251,25 +264,35 @@ impl MainPodBuilder { public_statements: Vec::new(), const_cnt: 0, 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) { self.input_signed_pods.push(pod.clone()); - pod.key_string_map.iter().for_each(|(hash, key)| { - self.key_table.insert(hash.clone(), key.clone()); + // Add key-hash correspondences to key table. + 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); } 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); - pod.key_string_map.iter().for_each(|(hash, key)| { - self.key_table.insert(hash.clone(), key.clone()); - }); - pod.pod_class_map.iter().for_each(|(pod_id, pod_class)| { - self.pod_class_table - .insert(pod_id.clone(), pod_class.clone()); - }); + // Add key-hash and POD ID-class correspondences to tables. + pod.public_statements + .iter() + .flat_map(|s| &s.1) + .flat_map(|arg| match arg { + 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); } pub fn insert(&mut self, st_op: (Statement, Operation)) { @@ -417,11 +440,10 @@ impl MainPodBuilder { } // Add key-hash pairs in statement to table. - (&st).1.iter().for_each(|arg| match arg { - StatementArg::Key(AnchoredKey(_, key)) => { + st.1.iter().for_each(|arg| { + if let StatementArg::Key(AnchoredKey(_, key)) = arg { self.key_table.insert(hash_str(key), key.clone()); } - _ => (), }); self.statements.push(st); @@ -441,27 +463,6 @@ impl MainPodBuilder { operations: &self.operations, 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::>(); - - 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::>(); let (statements, operations, public_statements) = compiler.compile(inputs, params)?; let inputs = MainPodInputs { @@ -472,10 +473,54 @@ impl MainPodBuilder { public_statements: &public_statements, }; 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 { pod, - key_string_map, - pod_class_map, + public_statements, }) } } @@ -483,9 +528,7 @@ impl MainPodBuilder { #[derive(Debug)] pub struct MainPod { pub pod: Box, - // TODO: metadata - pub key_string_map: HashMap, - pub pod_class_map: HashMap, + pub public_statements: Vec, } impl fmt::Display for MainPod { @@ -590,9 +633,9 @@ impl MainPodCompiler { } } - pub fn compile<'a>( + pub fn compile( mut self, - inputs: MainPodCompilerInputs<'a>, + inputs: MainPodCompilerInputs<'_>, params: &Params, ) -> Result<( Vec, // input statements @@ -627,16 +670,16 @@ impl MainPodCompiler { pub mod build_utils { #[macro_export] macro_rules! op_args { - ($($arg:expr),+) => {vec![$(crate::frontend::OperationArg::from($arg)),*]} + ($($arg:expr),+) => {vec![$($crate::frontend::OperationArg::from($arg)),*]} } #[macro_export] macro_rules! op { - (eq, $($arg:expr),+) => { crate::frontend::Operation( - crate::middleware::OperationType::Native(crate::middleware::NativeOperation::EqualFromEntries), - crate::op_args!($($arg),*)) }; - (ne, $($arg:expr),+) => { crate::frontend::Operation( - crate::middleware::OperationType::Native(crate::middleware::NativeOperation::NotEqualFromEntries), + (eq, $($arg:expr),+) => { $crate::frontend::Operation( + $crate::middleware::OperationType::Native($crate::middleware::NativeOperation::EqualFromEntries), + $crate::op_args!($($arg),*)) }; + (ne, $($arg:expr),+) => { $crate::frontend::Operation( + $crate::middleware::OperationType::Native(crate::middleware::NativeOperation::NotEqualFromEntries), crate::op_args!($($arg),*)) }; (gt, $($arg:expr),+) => { crate::frontend::Operation( 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, }; + // 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::>(); + let embedded_kvs = pod + .pod + .kvs() + .into_iter() + .map(|(middleware::AnchoredKey(_, k), v)| (k, v)) + .collect::>(); + + if kvs == embedded_kvs { + Ok(()) + } else { + Err(anyhow!( + "KVs {:?} do not agree with those embedded in the POD: {:?}", + kvs, + embedded_kvs + )) + } + } + #[test] fn test_front_zu_kyc() -> Result<()> { let params = Params::default(); @@ -675,29 +752,33 @@ pub mod tests { pk: "ZooGov".into(), }; let gov_id = gov_id.sign(&mut signer)?; + check_kvs(&gov_id)?; println!("{}", gov_id); let mut signer = MockSigner { pk: "ZooDeel".into(), }; let pay_stub = pay_stub.sign(&mut signer)?; + check_kvs(&pay_stub)?; println!("{}", pay_stub); let mut signer = MockSigner { pk: "ZooOFAC".into(), }; let sanction_list = sanction_list.sign(&mut signer)?; + check_kvs(&sanction_list)?; println!("{}", sanction_list); let kyc_builder = zu_kyc_pod_builder(¶ms, &gov_id, &pay_stub, &sanction_list)?; println!("{}", kyc_builder); + // prove kyc with MockProver and print it let mut prover = MockProver {}; let kyc = kyc_builder.prove(&mut prover, ¶ms)?; println!("{}", kyc); - Ok(()) + check_public_statements(&kyc) } #[test] @@ -705,7 +786,7 @@ pub mod tests { let params = Params::default(); let mut alice = MockSigner { pk: "Alice".into() }; - let mut bob = MockSigner { pk: "Bob".into() }; + let bob = MockSigner { pk: "Bob".into() }; let mut charlie = MockSigner { pk: "Charlie".into(), }; @@ -714,8 +795,10 @@ pub mod tests { // attests that he is ETH friends with Bob. let alice_attestation = eth_friend_signed_pod_builder(¶ms, charlie.pubkey().into()).sign(&mut alice)?; + check_kvs(&alice_attestation)?; let charlie_attestation = eth_friend_signed_pod_builder(¶ms, bob.pubkey().into()).sign(&mut charlie)?; + check_kvs(&charlie_attestation)?; let mut prover = MockProver {}; let alice_bob_ethdos = eth_dos_pod_builder( @@ -726,7 +809,7 @@ pub mod tests { )? .prove(&mut prover, ¶ms)?; - Ok(()) + check_public_statements(&alice_bob_ethdos) } #[test] diff --git a/src/frontend/operation.rs b/src/frontend/operation.rs index 4be6a54..9b35a97 100644 --- a/src/frontend/operation.rs +++ b/src/frontend/operation.rs @@ -1,7 +1,7 @@ use std::fmt; -use super::{AnchoredKey, SignedPod, Statement, StatementArg, Value}; -use crate::middleware::{hash_str, NativePredicate, OperationType, Predicate}; +use super::{SignedPod, Statement, Value}; +use crate::middleware::OperationType; #[derive(Clone, Debug, PartialEq, Eq)] pub enum OperationArg { diff --git a/src/frontend/statement.rs b/src/frontend/statement.rs index 21bc4ca..5b4b396 100644 --- a/src/frontend/statement.rs +++ b/src/frontend/statement.rs @@ -2,7 +2,7 @@ use anyhow::{anyhow, Result}; use std::fmt; use super::{AnchoredKey, SignedPod, Value}; -use crate::middleware::{self, hash_str, NativePredicate, Predicate}; +use crate::middleware::{self, NativePredicate, Predicate}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum StatementArg { @@ -24,13 +24,12 @@ pub struct Statement(pub Predicate, pub Vec); impl From<(&SignedPod, &str)> for Statement { fn from((pod, key): (&SignedPod, &str)) -> Self { - // TODO: Actual value, TryFrom. - let value_hash = pod.kvs().get(&hash_str(key)).cloned().unwrap(); + // TODO: TryFrom. let value = pod - .value_hash_map - .get(&value_hash.into()) + .kvs + .get(key) .cloned() - .unwrap_or(Value::Raw(value_hash)); + .unwrap_or_else(|| panic!("Key {} is not present in POD: {}", key, pod)); Statement( Predicate::Native(NativePredicate::ValueOf), vec![ @@ -48,7 +47,7 @@ impl TryFrom for middleware::Statement { type NP = NativePredicate; type SA = StatementArg; let args = ( - s.1.get(0).cloned(), + s.1.first().cloned(), s.1.get(1).cloned(), s.1.get(2).cloned(), ); diff --git a/src/middleware/containers.rs b/src/middleware/containers.rs index 6a1f505..193a7e9 100644 --- a/src/middleware/containers.rs +++ b/src/middleware/containers.rs @@ -21,7 +21,7 @@ pub struct Dictionary { impl Dictionary { pub fn new(kvs: &HashMap) -> Result { - let kvs: HashMap = kvs.into_iter().map(|(&k, &v)| (Value(k.0), v)).collect(); + let kvs: HashMap = kvs.iter().map(|(&k, &v)| (Value(k.0), v)).collect(); Ok(Self { mt: MerkleTree::new(MAX_DEPTH, &kvs)?, }) @@ -75,7 +75,7 @@ pub struct Set { impl Set { pub fn new(set: &Vec) -> Result { let kvs: HashMap = set - .into_iter() + .iter() .map(|e| { let h = hash_value(e); (Value::from(h), EMPTY) @@ -128,7 +128,7 @@ pub struct Array { impl Array { pub fn new(array: &Vec) -> Result { let kvs: HashMap = array - .into_iter() + .iter() .enumerate() .map(|(i, &e)| (Value::from(i as i64), e)) .collect(); diff --git a/src/middleware/custom.rs b/src/middleware/custom.rs index 3cf0e47..5b34571 100644 --- a/src/middleware/custom.rs +++ b/src/middleware/custom.rs @@ -26,8 +26,8 @@ impl HashOrWildcard { /// match is possible. pub fn match_against(&self, v: &Value) -> Result> { match self { - HashOrWildcard::Hash(h) if &Value::from(h.clone()) == v => Ok(None), - HashOrWildcard::Wildcard(i) => Ok(Some((*i, v.clone()))), + HashOrWildcard::Hash(h) if &Value::from(*h) == v => Ok(None), + HashOrWildcard::Wildcard(i) => Ok(Some((*i, *v))), _ => Err(anyhow!( "Failed to match hash or wildcard {} against value {}.", self, @@ -79,9 +79,9 @@ impl StatementTmplArg { (Self::None, StatementArg::None) => 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))) => { - let o_corr = tmpl_o.match_against(&o.clone().into())?; - let k_corr = tmpl_k.match_against(&k.clone().into())?; - Ok([o_corr, k_corr].into_iter().flat_map(|x| x).collect()) + let o_corr = tmpl_o.match_against(&(*o).into())?; + let k_corr = tmpl_k.match_against(&(*k).into())?; + Ok([o_corr, k_corr].into_iter().flatten().collect()) } _ => Err(anyhow!( "Failed to match statement template argument {:?} against statement argument {:?}.", @@ -110,15 +110,15 @@ impl ToFields for StatementTmplArg { } StatementTmplArg::Literal(v) => { let fields: Vec = 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)) .collect(); (fields, statement_tmpl_arg_size) } StatementTmplArg::Key(hw1, hw2) => { let fields: Vec = std::iter::once(F::from_canonical_u64(2)) - .chain(hw1.to_fields(_params).0.into_iter()) - .chain(hw2.to_fields(_params).0.into_iter()) + .chain(hw1.to_fields(_params).0) + .chain(hw2.to_fields(_params).0) .collect(); (fields, statement_tmpl_arg_size) } @@ -325,8 +325,8 @@ impl ToFields for CustomPredicateBatch { impl CustomPredicateBatch { pub fn hash(&self, _params: &Params) -> Hash { 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, pub usize); impl CustomPredicateRef { 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> { let mut bindings = HashMap::new(); @@ -414,7 +414,7 @@ impl ToFields for Predicate { // in every case: pad to (hash_size + 2) field elements let mut fields: Vec = match self { 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(), Self::BatchSelf(i) => std::iter::once(F::from_canonical_u64(2)) .chain(std::iter::once(F::from_canonical_usize(*i))) diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index 217db74..9faeda4 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -133,7 +133,7 @@ impl Params { 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!( " Statement template argument: {}", @@ -146,7 +146,7 @@ impl Params { " Custom predicate batch: {}", self.custom_predicate_batch_size_field_elts() ); - println!(""); + println!(); } } diff --git a/src/middleware/operation.rs b/src/middleware/operation.rs index 584814c..c4cce4c 100644 --- a/src/middleware/operation.rs +++ b/src/middleware/operation.rs @@ -1,15 +1,9 @@ -use std::collections::HashMap; use std::fmt; use anyhow::{anyhow, Result}; use super::{CustomPredicateRef, Statement}; -use crate::{ - middleware::{ - AnchoredKey, CustomPredicate, Params, PodId, Predicate, StatementTmpl, Value, SELF, - }, - util::hashmap_insert_no_dupe, -}; +use crate::middleware::{AnchoredKey, Params, Value, SELF}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum OperationType { @@ -109,7 +103,7 @@ impl Operation { pub fn op(op_code: OperationType, args: &[Statement]) -> Result { type NO = NativeOperation; let arg_tup = ( - args.get(0).cloned(), + args.first().cloned(), args.get(1).cloned(), args.get(2).cloned(), ); @@ -148,7 +142,7 @@ impl Operation { }) } /// Checks the given operation against a statement. - pub fn check(&self, params: &Params, output_statement: &Statement) -> Result { + pub fn check(&self, _params: &Params, output_statement: &Statement) -> Result { use Statement::*; match (self, output_statement) { (Self::None, None) => Ok(true), @@ -189,9 +183,9 @@ impl Operation { Self::SumOf(ValueOf(ak1, v1), ValueOf(ak2, v2), ValueOf(ak3, v3)), SumOf(ak4, ak5, ak6), ) => { - let v1: i64 = v1.clone().try_into()?; - let v2: i64 = v2.clone().try_into()?; - let v3: i64 = v3.clone().try_into()?; + let v1: i64 = (*v1).try_into()?; + let v2: i64 = (*v2).try_into()?; + let v3: i64 = (*v3).try_into()?; Ok((v1 == v2 + v3) && ak4 == ak1 && ak5 == ak2 && ak6 == ak3) } (Self::Custom(CustomPredicateRef(cpb, i), args), Custom(cpr, s_args)) @@ -214,8 +208,8 @@ impl Operation { }) .collect::>>()?; let s_args = s_args - .into_iter() - .flat_map(|AnchoredKey(o, k)| [Value::from(o.0.clone()), k.clone().into()]) + .iter() + .flat_map(|AnchoredKey(o, k)| [Value::from(o.0), (*k).into()]) .collect::>(); if bound_args != s_args { 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 { writeln!(f, "middleware::Operation:")?; writeln!(f, " {:?} ", self.code())?; - for (i, arg) in self.args().iter().enumerate() { + for (_, arg) in self.args().iter().enumerate() { writeln!(f, " {}", arg)?; } Ok(()) diff --git a/src/middleware/statement.rs b/src/middleware/statement.rs index 17414bb..7a0321f 100644 --- a/src/middleware/statement.rs +++ b/src/middleware/statement.rs @@ -82,7 +82,7 @@ impl Statement { 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::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)), } } }