From a7fab03defe79fc239868c6f31773407f2b1c595 Mon Sep 17 00:00:00 2001 From: Brian Lawrence Date: Tue, 25 Feb 2025 08:27:41 -0800 Subject: [PATCH 01/12] Print pods from SignedPodBuilder --- src/frontend/mod.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index f3d665f..574a72e 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -96,6 +96,16 @@ pub struct SignedPodBuilder { pub kvs: HashMap, } +impl fmt::Display for SignedPodBuilder { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "SignedPodBuilder:")?; + for (k, v) in self.kvs.iter().sorted_by_key(|kv| kv.0){ + writeln!(f, " - {}: {}", k, v)?; + } + Ok(()) + } +} + impl SignedPodBuilder { pub fn new(params: &Params) -> Self { Self { @@ -498,7 +508,7 @@ pub mod tests { let params = Params::default(); let (gov_id, pay_stub) = zu_kyc_sign_pod_builders(¶ms); - // TODO: print pods from the builder + println!("{}", gov_id); let mut signer = MockSigner { pk: "ZooGov".into(), From ba373c0422985da9c10bd544222741a6c1b24cb3 Mon Sep 17 00:00:00 2001 From: Brian Lawrence Date: Tue, 25 Feb 2025 08:29:10 -0800 Subject: [PATCH 02/12] Add additional print to test printing SignedPodBuilder --- src/frontend/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 574a72e..983b9a8 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -509,6 +509,7 @@ pub mod tests { let (gov_id, pay_stub) = zu_kyc_sign_pod_builders(¶ms); println!("{}", gov_id); + println!("{}", pay_stub); let mut signer = MockSigner { pk: "ZooGov".into(), From fc5bf165f9c7b52568fe2ec8bcae0b2e87a0a8a4 Mon Sep 17 00:00:00 2001 From: Brian Lawrence Date: Tue, 25 Feb 2025 10:03:17 -0800 Subject: [PATCH 03/12] Mock-prove and print MainPod --- src/frontend/mod.rs | 21 +++++++++++++++++++++ src/middleware/mod.rs | 7 +++++++ 2 files changed, 28 insertions(+) diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 983b9a8..3b932ad 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -357,6 +357,22 @@ pub struct MainPod { // TODO: metadata } +impl fmt::Display for MainPod { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "MainPod: {}", self.pod.id())?; + writeln!(f, " valid? {}", self.pod.verify())?; + writeln!(f, " statements:")?; + for st in &self.pod.pub_statements() { + writeln!(f, " - {}", st)?; + } + writeln!(f, " kvs:")?; + for (k, v) in &self.pod.kvs() { + writeln!(f, " - {}: {}", k, v)?; + } + Ok(()) + } +} + impl MainPod { pub fn id(&self) -> PodId { self.pod.id() @@ -497,6 +513,7 @@ pub mod build_utils { #[cfg(test)] pub mod tests { use super::*; + use crate::backends::mock_main::MockProver; use crate::backends::mock_signed::MockSigner; use crate::examples::{ great_boy_pod_full_flow, tickets_pod_full_flow, zu_kyc_pod_builder, @@ -526,7 +543,11 @@ pub mod tests { let kyc = zu_kyc_pod_builder(¶ms, &gov_id, &pay_stub)?; println!("{}", kyc); + let mut prover = MockProver{}; + let kyc = kyc.prove(&mut prover)?; + // TODO: prove kyc with MockProver and print it + println!("{}", kyc); Ok(()) } diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index f120b69..28dfcf5 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -42,6 +42,13 @@ impl AnchoredKey { } } +impl fmt::Display for AnchoredKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}.{}", self.0, self.1)?; + Ok(()) + } +} + /// An entry consists of a key-value pair. pub type Entry = (String, Value); From 5b3a74673e2061dab05df19f24bea94d02dda7c6 Mon Sep 17 00:00:00 2001 From: Brian Lawrence Date: Tue, 25 Feb 2025 12:59:35 -0800 Subject: [PATCH 04/12] Implement ToFields for custom predicates and dependencies --- src/backends/mock_main/mod.rs | 8 +- src/backends/mock_main/statement.rs | 10 +- src/middleware/custom.rs | 162 +++++++++++++++++++++++++--- src/middleware/mod.rs | 41 +++++-- src/middleware/statement.rs | 18 ++-- 5 files changed, 202 insertions(+), 37 deletions(-) diff --git a/src/backends/mock_main/mod.rs b/src/backends/mock_main/mod.rs index 9008710..915a0f7 100644 --- a/src/backends/mock_main/mod.rs +++ b/src/backends/mock_main/mod.rs @@ -327,7 +327,7 @@ impl MockMainPod { statements[statements.len() - params.max_public_statements..].to_vec(); // get the id out of the public statements - let id: PodId = PodId(hash_statements(&public_statements)); + let id: PodId = PodId(hash_statements(&public_statements, *params)); Ok(Self { params: params.clone(), @@ -362,10 +362,10 @@ impl MockMainPod { } } -pub fn hash_statements(statements: &[Statement]) -> middleware::Hash { +pub fn hash_statements(statements: &[Statement], params: Params) -> middleware::Hash { let field_elems = statements .into_iter() - .flat_map(|statement| statement.clone().to_fields().0) + .flat_map(|statement| statement.clone().to_fields(params).0) .collect::>(); Hash(PoseidonHash::hash_no_pad(&field_elems).elements) } @@ -376,7 +376,7 @@ impl Pod for MockMainPod { // get the input_statements from the self.statements let input_statements = &self.statements[input_statement_offset..]; // get the id out of the public statements, and ensure it is equal to self.id - let ids_match = self.id == PodId(hash_statements(&self.public_statements)); + let ids_match = self.id == PodId(hash_statements(&self.public_statements, self.params)); // find a ValueOf statement from the public statements with key=KEY_TYPE and check that the // value is PodType::MockMainPod let has_type_statement = self diff --git a/src/backends/mock_main/statement.rs b/src/backends/mock_main/statement.rs index 8c38f0e..3317f36 100644 --- a/src/backends/mock_main/statement.rs +++ b/src/backends/mock_main/statement.rs @@ -1,7 +1,7 @@ use anyhow::{anyhow, Result}; use std::fmt; -use crate::middleware::{self, NativePredicate, StatementArg, ToFields}; +use crate::middleware::{self, NativePredicate, Params, StatementArg, ToFields}; #[derive(Clone, Debug, PartialEq, Eq)] pub struct Statement(pub NativePredicate, pub Vec); @@ -21,12 +21,12 @@ impl Statement { } impl ToFields for Statement { - fn to_fields(self) -> (Vec, usize) { - let (native_statement_f, native_statement_f_len) = self.0.to_fields(); + fn to_fields(&self, params: Params) -> (Vec, usize) { + let (native_statement_f, native_statement_f_len) = self.0.to_fields(params); let (vec_statementarg_f, vec_statementarg_f_len) = self - .1 + .1.clone() .into_iter() - .map(|statement_arg| statement_arg.to_fields()) + .map(|statement_arg| statement_arg.to_fields(params)) .fold((Vec::new(), 0), |mut acc, (f, l)| { acc.0.extend(f); acc.1 += l; diff --git a/src/middleware/custom.rs b/src/middleware/custom.rs index dc08d9d..9f94304 100644 --- a/src/middleware/custom.rs +++ b/src/middleware/custom.rs @@ -2,10 +2,13 @@ use std::sync::Arc; use std::{fmt, hash as h, iter::zip}; use anyhow::{anyhow, Result}; +use plonky2::field::goldilocks_field::GoldilocksField; +use plonky2::field::types::Field; +use plonky2::hash::poseidon::PoseidonHash; +use plonky2::plonk::config::Hasher; use super::{ - hash_str, AnchoredKey, Hash, NativePredicate, PodId, Statement, StatementArg, ToFields, Value, - F, + hash_str, AnchoredKey, Hash, NativePredicate, Params, PodId, Statement, StatementArg, ToFields, Value, F }; // BEGIN Custom 1b @@ -38,6 +41,23 @@ impl fmt::Display for HashOrWildcard { } } +impl ToFields for HashOrWildcard { + fn to_fields(&self, params: Params) -> (Vec, usize) { + match self { + HashOrWildcard::Hash(h) => { + h.to_fields(params) + } + HashOrWildcard::Wildcard(w) => { + let usizes: Vec = vec![0, 0, 0, *w]; + let fields: Vec = usizes.iter().map( + |x| F::from_canonical_u64(*x as u64) + ).collect(); + (fields, 4) + } + } + } +} + #[derive(Clone, Debug, PartialEq, Eq, h::Hash)] pub enum StatementTmplArg { None, @@ -64,6 +84,40 @@ impl StatementTmplArg { } } +impl ToFields for StatementTmplArg { + fn to_fields(&self, params: Params) -> (Vec, usize) { + // None => (0, ...) + // Literal(value) => (1, [value], 0, 0, 0, 0) + // Key(hash_or_wildcard1, hash_or_wildcard2) + // => (2, [hash_or_wildcard1], [hash_or_wildcard2]) + // In all three cases, we pad to 2 * hash_size + 1 = 9 field elements + let hash_size = 4; + let statement_tmpl_arg_size = 2 * hash_size + 1; + match self { + StatementTmplArg::None => { + let fields: Vec = std::iter::repeat_with(|| F::from_canonical_u64(0)) + .take(statement_tmpl_arg_size) + .collect(); + (fields, statement_tmpl_arg_size) + } + StatementTmplArg::Literal(v) => { + let fields: Vec = std::iter::once(F::from_canonical_u64(1)) + .chain(v.to_fields(params).0.into_iter()) + .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()) + .collect(); + (fields, statement_tmpl_arg_size) + } + } + } +} + impl fmt::Display for StatementTmplArg { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -117,6 +171,28 @@ impl StatementTmpl { } } +impl ToFields for StatementTmpl { + fn to_fields(&self, params: Params) -> (Vec, usize) { + // serialize as: + // predicate (6 field elements) + // then the StatementTmplArgs + if self.1.len() > params.max_statement_args { + panic!("Statement template has too many arguments"); + } + let mut fields: Vec = self.0.to_fields(params).0 + .into_iter() + .chain( + self.1.iter() + .flat_map(|sta| sta.to_fields(params).0) + ) + .collect(); + fields.resize_with(params.statement_tmpl_size(), + || F::from_canonical_u64(0) + ); + (fields, params.statement_tmpl_size()) + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct CustomPredicate { /// true for "and", false for "or" @@ -128,10 +204,27 @@ pub struct CustomPredicate { } impl ToFields for CustomPredicate { - fn to_fields(self) -> (Vec, usize) { - todo!() - // let f: Vec = Vec::new(); - // (self.conjunction.to_f(), 1) + fn to_fields(&self, params: Params) -> (Vec, usize) { + // serialize as: + // conjunction (one field element) + // statements + // (params.max_custom_predicate_arity * params.statement_tmpl_size()) + // field elements + // args_len (one field element) + if self.statements.len() > params.max_custom_predicate_arity { + panic!("Custom predicate depends on too many statements"); + } + let mut fields: Vec = std::iter::once(F::from_bool(self.conjunction)) + .chain( + self.statements.iter().flat_map( + |st| st.to_fields(params).0 + ) + ).chain( + std::iter::once(F::from_canonical_usize(self.args_len)) + ).collect(); + fields.resize_with(params.custom_predicate_size(), + || F::from_canonical_u64(0)); + (fields, params.custom_predicate_size()) } } @@ -166,10 +259,27 @@ pub struct CustomPredicateBatch { pub predicates: Vec, } +impl ToFields for CustomPredicateBatch { + fn to_fields(&self, params: Params) -> (Vec, usize) { + // all the custom predicates in order + if self.predicates.len() > params.max_custom_batch_size { + panic!("Predicate batch exceeds maximum size"); + } + let mut fields: Vec = self.predicates.iter().flat_map( + |p| p.to_fields(params).0 + ).collect(); + fields.resize_with( params.custom_predicate_batch_size_field_elts(), + || F::from_canonical_u64(0)); + + (fields, params.custom_predicate_batch_size_field_elts()) + } +} + impl CustomPredicateBatch { - pub fn hash(&self) -> Hash { - // TODO - hash_str(&format!("{:?}", self)) + pub fn hash(&self, params: Params) -> Hash { + let input = self.to_fields(params).0; + let h = Hash(PoseidonHash::hash_no_pad(&input).elements); + h } } @@ -190,12 +300,38 @@ impl From for Predicate { } impl ToFields for Predicate { - fn to_fields(self) -> (Vec, usize) { + fn to_fields(&self, params: Params) -> (Vec, usize) { + // serialize: + // NativePredicate(id) as (0, id, 0, 0, 0, 0) -- id: usize + // BatchSelf(i) as (1, i, 0, 0, 0, 0) -- i: usize + // CustomPredicateRef(pb, i) as + // (2, [hash of pb], i) -- pb hashes to 4 field elements + // -- i: usize + + // in every case: pad to (hash_size + 2) field elements + let mut fields: Vec = Vec::new(); match self { - Self::Native(p) => p.to_fields(), - Self::BatchSelf(i) => Value::from(i as i64).to_fields(), - Self::Custom(_) => todo!(), // TODO + Self::Native(p) => { + fields = std::iter::once(F::from_canonical_u64(0)) + .chain(p.to_fields(params).0.into_iter()) + .collect(); + + }, + Self::BatchSelf(i) => { + fields = std::iter::once(F::from_canonical_u64(1)) + .chain(std::iter::once(F::from_canonical_usize(*i))) + .collect(); + } + Self::Custom(CustomPredicateRef(pb, i)) => { + fields = std::iter::once(F::from_canonical_u64(2)) + .chain(pb.hash(params).0) + .chain(std::iter::once(F::from_canonical_usize(*i))) + .collect(); + } } + fields.resize_with(params.predicate_size(), + || F::from_canonical_u64(0)); + (fields, params.predicate_size()) } } diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index 28dfcf5..c72d19e 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -56,7 +56,7 @@ pub type Entry = (String, Value); pub struct Value(pub [F; 4]); impl ToFields for Value { - fn to_fields(self) -> (Vec, usize) { + fn to_fields(&self, params: Params) -> (Vec, usize) { (self.0.to_vec(), 4) } } @@ -139,7 +139,7 @@ impl fmt::Display for Value { pub struct Hash(pub [F; 4]); impl ToFields for Hash { - fn to_fields(self) -> (Vec, usize) { + fn to_fields(&self, params: Params) -> (Vec, usize) { (self.0.to_vec(), 4) } } @@ -189,8 +189,8 @@ impl FromHex for Hash { pub struct PodId(pub Hash); impl ToFields for PodId { - fn to_fields(self) -> (Vec, usize) { - self.0.to_fields() + fn to_fields(&self, params: Params) -> (Vec, usize) { + self.0.to_fields(params) } } @@ -241,7 +241,7 @@ pub fn hash_str(s: &str) -> Hash { Hash(PoseidonHash::hash_no_pad(&input).elements) } -#[derive(Clone, Debug, Copy)] +#[derive(Clone, Debug, Copy, PartialEq, Eq)] pub struct Params { pub max_input_signed_pods: usize, pub max_input_main_pods: usize, @@ -250,12 +250,38 @@ pub struct Params { pub max_public_statements: usize, pub max_statement_args: usize, pub max_operation_args: usize, + // max number of statements that can be ANDed or ORed together + // in a custom predicate + pub max_custom_predicate_arity: usize, + pub max_custom_batch_size: usize, + // number of field elements in a hash + pub hash_size: usize, } impl Params { pub fn max_priv_statements(&self) -> usize { self.max_statements - self.max_public_statements } + + pub fn statement_tmpl_arg_size(self) -> usize { + 2 * self.hash_size + 1 + } + + pub fn predicate_size(self) -> usize { + self.hash_size + 2 + } + + pub fn statement_tmpl_size(self) -> usize { + self.predicate_size() + self.max_statement_args * self.statement_tmpl_arg_size() + } + + pub fn custom_predicate_size(self) -> usize { + self.max_custom_predicate_arity * self.statement_tmpl_size() + 2 + } + + pub fn custom_predicate_batch_size_field_elts(self) -> usize { + self.max_custom_batch_size * self.custom_predicate_size() + } } impl Default for Params { @@ -268,6 +294,9 @@ impl Default for Params { max_public_statements: 10, max_statement_args: 5, max_operation_args: 5, + max_custom_predicate_arity: 5, + max_custom_batch_size: 5, + hash_size: 4, } } } @@ -335,5 +364,5 @@ pub trait PodProver { pub trait ToFields { /// returns Vec representation of the type, and a usize indicating how many field elements /// does the vector contain - fn to_fields(self) -> (Vec, usize); + fn to_fields(&self, params: Params) -> (Vec, usize); } diff --git a/src/middleware/statement.rs b/src/middleware/statement.rs index ce84f2a..a46c44b 100644 --- a/src/middleware/statement.rs +++ b/src/middleware/statement.rs @@ -3,7 +3,7 @@ use plonky2::field::types::Field; use std::{collections::HashMap, fmt}; use strum_macros::FromRepr; -use super::{AnchoredKey, CustomPredicateRef, Hash, Predicate, ToFields, Value, F}; +use super::{AnchoredKey, CustomPredicateRef, Hash, Params, Predicate, ToFields, Value, F}; pub const KEY_SIGNER: &str = "_signer"; pub const KEY_TYPE: &str = "_type"; @@ -25,8 +25,8 @@ pub enum NativePredicate { } impl ToFields for NativePredicate { - fn to_fields(self) -> (Vec, usize) { - (vec![F::from_canonical_u64(self as u64)], 1) + fn to_fields(&self, params: Params) -> (Vec, usize) { + (vec![F::from_canonical_u64(*self as u64)], 1) } } @@ -88,12 +88,12 @@ impl Statement { } impl ToFields for Statement { - fn to_fields(self) -> (Vec, usize) { - let (native_statement_f, native_statement_f_len) = self.code().to_fields(); + fn to_fields(&self, params: Params) -> (Vec, usize) { + let (native_statement_f, native_statement_f_len) = self.code().to_fields(params); let (vec_statementarg_f, vec_statementarg_f_len) = self .args() .into_iter() - .map(|statement_arg| statement_arg.to_fields()) + .map(|statement_arg| statement_arg.to_fields(params)) .fold((Vec::new(), 0), |mut acc, (f, l)| { acc.0.extend(f); acc.1 += l; @@ -156,7 +156,7 @@ impl StatementArg { } impl ToFields for StatementArg { - fn to_fields(self) -> (Vec, usize) { + fn to_fields(&self, params: Params) -> (Vec, usize) { // NOTE: current version returns always the same amount of field elements in the returned // vector, which means that the `None` case is padded with 8 zeroes, and the `Literal` case // is padded with 4 zeroes. Since the returned vector will mostly be hashed (and reproduced @@ -175,8 +175,8 @@ impl ToFields for StatementArg { .concat() } StatementArg::Key(ak) => { - let (podid_f, _) = ak.0.to_fields(); - let (hash_f, _) = ak.1.to_fields(); + let (podid_f, _) = ak.0.to_fields(params); + let (hash_f, _) = ak.1.to_fields(params); [podid_f, hash_f].concat() } }; From 493bbd712639b465b8f23af604fab4edf3e1964f Mon Sep 17 00:00:00 2001 From: Brian Lawrence Date: Tue, 25 Feb 2025 13:05:16 -0800 Subject: [PATCH 05/12] Test: print serialization of a recursive batch --- src/frontend/custom.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/frontend/custom.rs b/src/frontend/custom.rs index e4d0ab2..b26a66d 100644 --- a/src/frontend/custom.rs +++ b/src/frontend/custom.rs @@ -171,13 +171,15 @@ fn resolve_wildcard(args: &[&str], priv_args: &[&str], v: &HashOrWildcardStr) -> #[cfg(test)] mod tests { use super::*; - use crate::middleware::{CustomPredicateRef, PodType}; + use crate::middleware::{CustomPredicateRef, Params, PodType}; #[test] fn test_custom_pred() { use NativePredicate as NP; use StatementTmplBuilder as STB; + let params = Params::default(); + let mut builder = CustomPredicateBatchBuilder::new("eth_friend".into()); let _eth_friend = builder.predicate_and( // arguments: @@ -311,5 +313,9 @@ mod tests { "b.2. eth_dos_distance = {}", builder.predicates.last().unwrap() ); + + let eth_dos_batch_b = builder.finish(); + let fields = eth_dos_batch_b.to_fields(params); + println!("Batch b, serialized: {:?}", fields); } } From 54296d9169a57d9fe6f0ac8d80d7c531ae739c52 Mon Sep 17 00:00:00 2001 From: Brian Lawrence Date: Tue, 25 Feb 2025 13:38:07 -0800 Subject: [PATCH 06/12] Rearrange serialization of CustomPredicate so args_len is always in the same position --- src/frontend/custom.rs | 1 + src/middleware/custom.rs | 10 +++++----- src/middleware/mod.rs | 10 ++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/frontend/custom.rs b/src/frontend/custom.rs index b26a66d..2258e50 100644 --- a/src/frontend/custom.rs +++ b/src/frontend/custom.rs @@ -179,6 +179,7 @@ mod tests { use StatementTmplBuilder as STB; let params = Params::default(); + params.print_serialized_sizes(); let mut builder = CustomPredicateBatchBuilder::new("eth_friend".into()); let _eth_friend = builder.predicate_and( diff --git a/src/middleware/custom.rs b/src/middleware/custom.rs index 9f94304..b9cbd99 100644 --- a/src/middleware/custom.rs +++ b/src/middleware/custom.rs @@ -207,20 +207,20 @@ impl ToFields for CustomPredicate { fn to_fields(&self, params: Params) -> (Vec, usize) { // serialize as: // conjunction (one field element) - // statements - // (params.max_custom_predicate_arity * params.statement_tmpl_size()) - // field elements // args_len (one field element) + // statements + // (params.max_custom_predicate_arity * params.statement_tmpl_size()) + // field elements if self.statements.len() > params.max_custom_predicate_arity { panic!("Custom predicate depends on too many statements"); } let mut fields: Vec = std::iter::once(F::from_bool(self.conjunction)) .chain( + std::iter::once(F::from_canonical_usize(self.args_len)) + ).chain( self.statements.iter().flat_map( |st| st.to_fields(params).0 ) - ).chain( - std::iter::once(F::from_canonical_usize(self.args_len)) ).collect(); fields.resize_with(params.custom_predicate_size(), || F::from_canonical_u64(0)); diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index c72d19e..a0c2a05 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -282,6 +282,16 @@ impl Params { pub fn custom_predicate_batch_size_field_elts(self) -> usize { self.max_custom_batch_size * self.custom_predicate_size() } + + pub fn print_serialized_sizes(self) -> () { + println!("Parameter sizes:"); + println!(" Statement template argument: {}", self.statement_tmpl_arg_size()); + println!(" Predicate: {}", self.predicate_size()); + println!(" Statement template: {}", self.statement_tmpl_size()); + println!(" Custom predicate: {}", self.custom_predicate_size()); + println!(" Custom predicate batch: {}", self.custom_predicate_batch_size_field_elts()); + println!(""); + } } impl Default for Params { From daf2c230e00f91255c0166ec6bba91efee447d12 Mon Sep 17 00:00:00 2001 From: Brian Lawrence Date: Tue, 25 Feb 2025 13:41:05 -0800 Subject: [PATCH 07/12] Serialize predicates with first entry nonzero to avoid collision with padding --- src/middleware/custom.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/middleware/custom.rs b/src/middleware/custom.rs index b9cbd99..aca3e21 100644 --- a/src/middleware/custom.rs +++ b/src/middleware/custom.rs @@ -312,18 +312,18 @@ impl ToFields for Predicate { let mut fields: Vec = Vec::new(); match self { Self::Native(p) => { - fields = std::iter::once(F::from_canonical_u64(0)) + fields = std::iter::once(F::from_canonical_u64(1)) .chain(p.to_fields(params).0.into_iter()) .collect(); }, Self::BatchSelf(i) => { - fields = std::iter::once(F::from_canonical_u64(1)) + fields = std::iter::once(F::from_canonical_u64(2)) .chain(std::iter::once(F::from_canonical_usize(*i))) .collect(); } Self::Custom(CustomPredicateRef(pb, i)) => { - fields = std::iter::once(F::from_canonical_u64(2)) + fields = std::iter::once(F::from_canonical_u64(3)) .chain(pb.hash(params).0) .chain(std::iter::once(F::from_canonical_usize(*i))) .collect(); From b12c5dfc4c6b5dfe579cb8be345468ad548c4b71 Mon Sep 17 00:00:00 2001 From: Brian Lawrence Date: Tue, 25 Feb 2025 13:54:42 -0800 Subject: [PATCH 08/12] Off by one error in ethdos test BatchSelf(2) --- src/frontend/custom.rs | 2 +- src/middleware/custom.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/frontend/custom.rs b/src/frontend/custom.rs index 2258e50..20f4657 100644 --- a/src/frontend/custom.rs +++ b/src/frontend/custom.rs @@ -242,7 +242,7 @@ mod tests { builder.predicates.last().unwrap() ); - let eth_dos_distance = Predicate::BatchSelf(3); + let eth_dos_distance = Predicate::BatchSelf(2); // next chunk builds: let eth_dos_distance_ind = builder.predicate_and( diff --git a/src/middleware/custom.rs b/src/middleware/custom.rs index aca3e21..b626aad 100644 --- a/src/middleware/custom.rs +++ b/src/middleware/custom.rs @@ -315,7 +315,6 @@ impl ToFields for Predicate { fields = std::iter::once(F::from_canonical_u64(1)) .chain(p.to_fields(params).0.into_iter()) .collect(); - }, Self::BatchSelf(i) => { fields = std::iter::once(F::from_canonical_u64(2)) From d10dbb7181cfac8d67152ef022acec572ee59c84 Mon Sep 17 00:00:00 2001 From: Brian Lawrence Date: Tue, 25 Feb 2025 18:00:19 -0800 Subject: [PATCH 09/12] Improve formatting of SignedPods: show keys as strings --- src/frontend/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 3b932ad..d72e380 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -151,7 +151,7 @@ impl fmt::Display for SignedPod { // 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) { - writeln!(f, " - {}: {}", k, v)?; + writeln!(f, " - {} = {}: {}", k, *self.key_string_map.get(&k).unwrap_or(&"--".to_string()), v)?; } Ok(()) } From a2f8b45b5f3a61f0e68fbd0689b2cb39a602d239 Mon Sep 17 00:00:00 2001 From: Brian Lawrence Date: Wed, 26 Feb 2025 08:44:53 -0800 Subject: [PATCH 10/12] cargo fmt --- src/backends/mock_main/statement.rs | 3 +- src/frontend/mod.rs | 12 ++++-- src/middleware/custom.rs | 65 +++++++++++++---------------- src/middleware/mod.rs | 10 ++++- 4 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/backends/mock_main/statement.rs b/src/backends/mock_main/statement.rs index 3317f36..f8fdd0c 100644 --- a/src/backends/mock_main/statement.rs +++ b/src/backends/mock_main/statement.rs @@ -24,7 +24,8 @@ impl ToFields for Statement { fn to_fields(&self, params: Params) -> (Vec, usize) { let (native_statement_f, native_statement_f_len) = self.0.to_fields(params); let (vec_statementarg_f, vec_statementarg_f_len) = self - .1.clone() + .1 + .clone() .into_iter() .map(|statement_arg| statement_arg.to_fields(params)) .fold((Vec::new(), 0), |mut acc, (f, l)| { diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index d72e380..0f8873f 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -99,7 +99,7 @@ pub struct SignedPodBuilder { impl fmt::Display for SignedPodBuilder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "SignedPodBuilder:")?; - 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, " - {}: {}", k, v)?; } Ok(()) @@ -151,7 +151,13 @@ impl fmt::Display for SignedPod { // 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) { - writeln!(f, " - {} = {}: {}", k, *self.key_string_map.get(&k).unwrap_or(&"--".to_string()), v)?; + writeln!( + f, + " - {} = {}: {}", + k, + *self.key_string_map.get(&k).unwrap_or(&"--".to_string()), + v + )?; } Ok(()) } @@ -543,7 +549,7 @@ pub mod tests { let kyc = zu_kyc_pod_builder(¶ms, &gov_id, &pay_stub)?; println!("{}", kyc); - let mut prover = MockProver{}; + let mut prover = MockProver {}; let kyc = kyc.prove(&mut prover)?; // TODO: prove kyc with MockProver and print it diff --git a/src/middleware/custom.rs b/src/middleware/custom.rs index b626aad..ad2a9d8 100644 --- a/src/middleware/custom.rs +++ b/src/middleware/custom.rs @@ -8,7 +8,8 @@ use plonky2::hash::poseidon::PoseidonHash; use plonky2::plonk::config::Hasher; use super::{ - hash_str, AnchoredKey, Hash, NativePredicate, Params, PodId, Statement, StatementArg, ToFields, Value, F + hash_str, AnchoredKey, Hash, NativePredicate, Params, PodId, Statement, StatementArg, ToFields, + Value, F, }; // BEGIN Custom 1b @@ -44,14 +45,13 @@ impl fmt::Display for HashOrWildcard { impl ToFields for HashOrWildcard { fn to_fields(&self, params: Params) -> (Vec, usize) { match self { - HashOrWildcard::Hash(h) => { - h.to_fields(params) - } + HashOrWildcard::Hash(h) => h.to_fields(params), HashOrWildcard::Wildcard(w) => { let usizes: Vec = vec![0, 0, 0, *w]; - let fields: Vec = usizes.iter().map( - |x| F::from_canonical_u64(*x as u64) - ).collect(); + let fields: Vec = usizes + .iter() + .map(|x| F::from_canonical_u64(*x as u64)) + .collect(); (fields, 4) } } @@ -179,16 +179,14 @@ impl ToFields for StatementTmpl { if self.1.len() > params.max_statement_args { panic!("Statement template has too many arguments"); } - let mut fields: Vec = self.0.to_fields(params).0 + let mut fields: Vec = self + .0 + .to_fields(params) + .0 .into_iter() - .chain( - self.1.iter() - .flat_map(|sta| sta.to_fields(params).0) - ) + .chain(self.1.iter().flat_map(|sta| sta.to_fields(params).0)) .collect(); - fields.resize_with(params.statement_tmpl_size(), - || F::from_canonical_u64(0) - ); + fields.resize_with(params.statement_tmpl_size(), || F::from_canonical_u64(0)); (fields, params.statement_tmpl_size()) } } @@ -208,22 +206,17 @@ impl ToFields for CustomPredicate { // serialize as: // conjunction (one field element) // args_len (one field element) - // statements + // statements // (params.max_custom_predicate_arity * params.statement_tmpl_size()) // field elements if self.statements.len() > params.max_custom_predicate_arity { panic!("Custom predicate depends on too many statements"); } let mut fields: Vec = std::iter::once(F::from_bool(self.conjunction)) - .chain( - std::iter::once(F::from_canonical_usize(self.args_len)) - ).chain( - self.statements.iter().flat_map( - |st| st.to_fields(params).0 - ) - ).collect(); - fields.resize_with(params.custom_predicate_size(), - || F::from_canonical_u64(0)); + .chain(std::iter::once(F::from_canonical_usize(self.args_len))) + .chain(self.statements.iter().flat_map(|st| st.to_fields(params).0)) + .collect(); + fields.resize_with(params.custom_predicate_size(), || F::from_canonical_u64(0)); (fields, params.custom_predicate_size()) } } @@ -265,12 +258,15 @@ impl ToFields for CustomPredicateBatch { if self.predicates.len() > params.max_custom_batch_size { panic!("Predicate batch exceeds maximum size"); } - let mut fields: Vec = self.predicates.iter().flat_map( - |p| p.to_fields(params).0 - ).collect(); - fields.resize_with( params.custom_predicate_batch_size_field_elts(), - || F::from_canonical_u64(0)); - + let mut fields: Vec = self + .predicates + .iter() + .flat_map(|p| p.to_fields(params).0) + .collect(); + fields.resize_with(params.custom_predicate_batch_size_field_elts(), || { + F::from_canonical_u64(0) + }); + (fields, params.custom_predicate_batch_size_field_elts()) } } @@ -315,7 +311,7 @@ impl ToFields for Predicate { fields = std::iter::once(F::from_canonical_u64(1)) .chain(p.to_fields(params).0.into_iter()) .collect(); - }, + } Self::BatchSelf(i) => { fields = std::iter::once(F::from_canonical_u64(2)) .chain(std::iter::once(F::from_canonical_usize(*i))) @@ -328,9 +324,8 @@ impl ToFields for Predicate { .collect(); } } - fields.resize_with(params.predicate_size(), - || F::from_canonical_u64(0)); - (fields, params.predicate_size()) + fields.resize_with(params.predicate_size(), || F::from_canonical_u64(0)); + (fields, params.predicate_size()) } } diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index a0c2a05..451de8a 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -285,11 +285,17 @@ impl Params { pub fn print_serialized_sizes(self) -> () { println!("Parameter sizes:"); - println!(" Statement template argument: {}", self.statement_tmpl_arg_size()); + println!( + " Statement template argument: {}", + self.statement_tmpl_arg_size() + ); println!(" Predicate: {}", self.predicate_size()); println!(" Statement template: {}", self.statement_tmpl_size()); println!(" Custom predicate: {}", self.custom_predicate_size()); - println!(" Custom predicate batch: {}", self.custom_predicate_batch_size_field_elts()); + println!( + " Custom predicate batch: {}", + self.custom_predicate_batch_size_field_elts() + ); println!(""); } } From ce885ed913780f52abbb18bf82c108c084e0bf6c Mon Sep 17 00:00:00 2001 From: Brian Lawrence Date: Wed, 26 Feb 2025 08:59:24 -0800 Subject: [PATCH 11/12] Not a typo --- .github/workflows/typos.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/typos.toml b/.github/workflows/typos.toml index 4814700..06ad5b1 100644 --- a/.github/workflows/typos.toml +++ b/.github/workflows/typos.toml @@ -1,3 +1,4 @@ [default.extend-words] groth = "groth" # to avoid it dectecting it as 'growth' BA = "BA" +ANDed = "ANDed" From 183a05ce6fbc9ef6ee52c8bf1ca4cd92563b3dc4 Mon Sep 17 00:00:00 2001 From: Brian Lawrence Date: Wed, 26 Feb 2025 09:06:33 -0800 Subject: [PATCH 12/12] trying to make typo checker happy --- .github/workflows/typos.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/typos.toml b/.github/workflows/typos.toml index 06ad5b1..cef8a2b 100644 --- a/.github/workflows/typos.toml +++ b/.github/workflows/typos.toml @@ -1,4 +1,4 @@ [default.extend-words] groth = "groth" # to avoid it dectecting it as 'growth' BA = "BA" -ANDed = "ANDed" +Ded = "Ded" # "ANDed", it thought "Ded" should be "Dead"