From 5236b4621446cab198afbbafd57583cd43bea670 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Mon, 10 Feb 2025 12:37:11 +0100 Subject: [PATCH] Migrate fmt to use Display trait (#44) Migrate fmt to use Display trait to simplify the usage of it. Also with this, in the same snipped of code we can print types from backend, middleware and frontend; which before needed to import the two different `Printer` structs (frontend::Printer and mock_main::Printer). Before: ``` let printer = mock_main::Printer { skip_none: false }; let mut w = io::stdout(); printer.fmt_mock_main_pod(&mut w, &pod).unwrap(); let printer = frontend::Printer { skip_none: false }; printer.fmt_main_pod_builder(&mut w, &pod_builder).unwrap(); ``` now: ``` println!("{:#}", pod); println!("{:#}", pod_builder); ``` And the equivalent to the old `skip_none: true`, now is done by just using `println!("{}", pod); --- src/backends/mock_main.rs | 194 +++++++++++++++++--------------------- src/frontend.rs | 130 +++++++++++++------------ src/middleware.rs | 25 +++++ 3 files changed, 176 insertions(+), 173 deletions(-) diff --git a/src/backends/mock_main.rs b/src/backends/mock_main.rs index 412f0e3..d9ec4fa 100644 --- a/src/backends/mock_main.rs +++ b/src/backends/mock_main.rs @@ -7,6 +7,7 @@ use itertools::Itertools; use plonky2::hash::poseidon::PoseidonHash; use plonky2::plonk::config::Hasher; use std::any::Any; +use std::fmt; use std::io::{self, Write}; pub struct MockProver {} @@ -32,6 +33,24 @@ impl OperationArg { #[derive(Clone, Debug, PartialEq, Eq)] struct Operation(pub NativeOperation, pub Vec); +impl fmt::Display for Operation { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?} ", self.0)?; + for (i, arg) in self.1.iter().enumerate() { + if !(!f.alternate() && arg.is_none()) { + if i != 0 { + write!(f, " ")?; + } + match arg { + OperationArg::None => write!(f, "none")?, + OperationArg::Index(i) => write!(f, "{:02}", i)?, + } + } + } + Ok(()) + } +} + #[derive(Clone, Debug)] pub struct MockMainPod { params: Params, @@ -46,6 +65,73 @@ pub struct MockMainPod { statements: Vec, } +impl fmt::Display for MockMainPod { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + writeln!(f, "MockMainPod ({}):", self.id)?; + // TODO print input signed pods id and type + // TODO print input main pods id and type + let offset_input_main_pods = self.offset_input_main_pods(); + let offset_input_statements = self.offset_input_statements(); + let offset_public_statements = self.offset_public_statements(); + for (i, st) in self.statements.iter().enumerate() { + if (i < self.offset_input_main_pods()) && (i % self.params.max_signed_pod_values == 0) { + writeln!( + f, + " from input SignedPod {}:", + i / self.params.max_signed_pod_values + )?; + } + if (i >= offset_input_main_pods) + && (i < offset_input_statements) + && (i % self.params.max_public_statements == 0) + { + writeln!( + f, + " from input MainPod {}:", + (i - offset_input_main_pods) / self.params.max_signed_pod_values + )?; + } + if i == offset_input_statements { + writeln!(f, " private statements:")?; + } + if i == offset_public_statements { + writeln!(f, " public statements:")?; + } + + let op = (i >= offset_input_statements) + .then(|| &self.operations[i - offset_input_statements]); + fmt_statement_index(f, &st, op, i)?; + } + Ok(()) + } +} + +fn fmt_statement_index( + f: &mut fmt::Formatter, + st: &Statement, + op: Option<&Operation>, + index: usize, +) -> fmt::Result { + if !(!f.alternate() && st.is_none()) { + write!(f, " {:03}. ", index)?; + if f.alternate() { + write!(f, "{:#}", &st)?; + } else { + write!(f, "{}", &st)?; + } + if let Some(op) = op { + write!(f, " <- ")?; + if f.alternate() { + write!(f, "{:#}", op)?; + } else { + write!(f, "{}", op)?; + } + } + write!(f, "\n")?; + } + Ok(()) +} + fn fill_pad(v: &mut Vec, pad_value: T, len: usize) { if v.len() > len { panic!("length exceeded"); @@ -305,110 +391,6 @@ impl MainPod for MockMainPod { } } -/// Useful for debugging -pub struct Printer { - pub skip_none: bool, -} - -impl Printer { - fn fmt_arg(&self, w: &mut dyn Write, arg: &StatementArg) -> io::Result<()> { - match arg { - StatementArg::None => write!(w, "none"), - StatementArg::Literal(v) => write!(w, "{}", v), - StatementArg::Key(r) => write!(w, "{}.{}", r.0, r.1), - } - } - - fn fmt_statement(&self, w: &mut dyn Write, st: &Statement) -> io::Result<()> { - write!(w, "{:?} ", st.0)?; - for (i, arg) in st.1.iter().enumerate() { - if !(self.skip_none && arg.is_none()) { - if i != 0 { - write!(w, " ")?; - } - self.fmt_arg(w, arg)?; - } - } - Ok(()) - } - - fn fmt_operation(&self, w: &mut dyn Write, op: &Operation) -> io::Result<()> { - write!(w, "{:?} ", op.0)?; - for (i, arg) in op.1.iter().enumerate() { - if !(self.skip_none && arg.is_none()) { - if i != 0 { - write!(w, " ")?; - } - match arg { - OperationArg::None => write!(w, "none")?, - OperationArg::Index(i) => write!(w, "{:02}", i)?, - } - } - } - Ok(()) - } - - fn fmt_statement_index( - &self, - w: &mut dyn Write, - st: &Statement, - op: Option<&Operation>, - index: usize, - ) -> io::Result<()> { - if !(self.skip_none && st.is_none()) { - write!(w, " {:03}. ", index)?; - self.fmt_statement(w, &st)?; - if let Some(op) = op { - write!(w, " <- ")?; - self.fmt_operation(w, op)?; - } - write!(w, "\n")?; - } - Ok(()) - } - - pub fn fmt_mock_main_pod(&self, w: &mut dyn Write, pod: &MockMainPod) -> io::Result<()> { - writeln!(w, "MockMainPod ({}):", pod.id)?; - // TODO print input signed pods id and type - // TODO print input main pods id and type - let offset_input_main_pods = pod.offset_input_main_pods(); - let offset_input_statements = pod.offset_input_statements(); - let offset_public_statements = pod.offset_public_statements(); - for (i, st) in pod.statements.iter().enumerate() { - if (i < pod.offset_input_main_pods()) && (i % pod.params.max_signed_pod_values == 0) { - writeln!( - w, - " from input SignedPod {}:", - i / pod.params.max_signed_pod_values - )?; - } - if (i >= offset_input_main_pods) - && (i < offset_input_statements) - && (i % pod.params.max_public_statements == 0) - { - writeln!( - w, - " from input MainPod {}:", - (i - offset_input_main_pods) / pod.params.max_signed_pod_values - )?; - } - if i == offset_input_statements { - writeln!(w, " private statements:")?; - } - if i == offset_public_statements { - writeln!(w, " public statements:")?; - } - - let op = (i >= offset_input_statements) - .then(|| &pod.operations[i - offset_input_statements]); - if !(self.skip_none && st.is_none()) { - self.fmt_statement_index(w, &st, op, i)?; - } - } - Ok(()) - } -} - #[cfg(test)] pub mod tests { use super::*; @@ -435,9 +417,7 @@ pub mod tests { let kyc_pod = kyc_builder.prove(&mut prover).unwrap(); let pod = kyc_pod.pod.into_any().downcast::().unwrap(); - let printer = Printer { skip_none: false }; - let mut w = io::stdout(); - printer.fmt_mock_main_pod(&mut w, &pod).unwrap(); + println!("{:#}", pod); // assert_eq!(pod.verify(), true); // TODO // println!("id: {}", pod.id()); diff --git a/src/frontend.rs b/src/frontend.rs index e04dd07..b82002f 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -7,7 +7,6 @@ use plonky2::field::types::Field; use std::collections::HashMap; use std::convert::From; use std::fmt; -use std::io::{self, Write}; use crate::middleware::{ self, hash_str, Hash, MainPodInputs, NativeOperation, NativeStatement, Params, PodId, @@ -119,6 +118,20 @@ pub struct SignedPod { pub key_string_map: HashMap, } +impl fmt::Display for SignedPod { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "SignedPod (id:{}):", self.id())?; + // Note: current version iterates sorting by keys of the kvs, but the merkletree defined at + // https://0xparc.github.io/pod2/merkletree.html will not need it since it will be + // deterministic based on the keys values not on the order of the keys when added into the + // tree. + for (k, v) in self.pod.kvs().iter().sorted_by_key(|kv| kv.0) { + writeln!(f, " - {}: {}", k, v)?; + } + Ok(()) + } +} + impl SignedPod { pub fn id(&self) -> PodId { self.pod.id() @@ -176,6 +189,17 @@ pub enum OperationArg { Entry(String, Value), } +impl fmt::Display for OperationArg { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + OperationArg::Statement(s) => write!(f, "{}", s), + OperationArg::Key(k) => write!(f, "{}.{}", k.0 .1, k.1), + OperationArg::Literal(v) => write!(f, "{}", v), + OperationArg::Entry(k, v) => write!(f, "({}, {})", k, v), + } + } +} + impl From for OperationArg { fn from(v: Value) -> Self { Self::Literal(v) @@ -215,6 +239,19 @@ impl From<(&SignedPod, &str)> for OperationArg { #[derive(Clone, Debug, PartialEq, Eq)] pub struct Operation(pub NativeOperation, pub Vec); +impl fmt::Display for Operation { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?} ", self.0)?; + for (i, arg) in self.1.iter().enumerate() { + if i != 0 { + write!(f, " ")?; + } + write!(f, "{}", arg)?; + } + Ok(()) + } +} + #[derive(Debug)] pub struct MainPodBuilder { pub params: Params, @@ -227,6 +264,27 @@ pub struct MainPodBuilder { const_cnt: usize, } +impl fmt::Display for MainPodBuilder { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "MainPod:")?; + writeln!(f, " input_signed_pods:")?; + for in_pod in &self.input_signed_pods { + writeln!(f, " - {}", in_pod.id())?; + } + writeln!(f, " input_main_pods:")?; + for in_pod in &self.input_main_pods { + writeln!(f, " - {}", in_pod.id())?; + } + writeln!(f, " statements:")?; + for (st, op) in self.statements.iter().zip_eq(self.operations.iter()) { + write!(f, " - {} <- ", st)?; + write!(f, "{}", op)?; + write!(f, "\n")?; + } + Ok(()) + } +} + impl MainPodBuilder { pub fn new(params: &Params) -> Self { Self { @@ -484,70 +542,13 @@ impl MainPodCompiler { } } -pub struct Printer {} - -impl Printer { - pub fn fmt_op_arg(&self, w: &mut dyn Write, arg: &OperationArg) -> io::Result<()> { - match arg { - OperationArg::Statement(s) => write!(w, "{}", s), - OperationArg::Key(k) => write!(w, "{}.{}", k.0 .1, k.1), - OperationArg::Literal(v) => write!(w, "{}", v), - OperationArg::Entry(k, v) => write!(w, "({}, {})", k, v), - } - } - - pub fn fmt_op(&self, w: &mut dyn Write, op: &Operation) -> io::Result<()> { - write!(w, "{:?} ", op.0)?; - for (i, arg) in op.1.iter().enumerate() { - if i != 0 { - write!(w, " ")?; - } - self.fmt_op_arg(w, arg)?; - } - Ok(()) - } - - // TODO fn fmt_signed_pod_builder - - pub fn fmt_signed_pod(&self, w: &mut dyn Write, pod: &SignedPod) -> io::Result<()> { - writeln!(w, "SignedPod (id:{}):", pod.id())?; - // Note: current version iterates sorting by keys of the kvs, but the merkletree defined at - // https://0xparc.github.io/pod2/merkletree.html will not need it since it will be - // deterministic based on the keys values not on the order of the keys when added into the - // tree. - for (k, v) in pod.pod.kvs().iter().sorted_by_key(|kv| kv.0) { - writeln!(w, " - {}: {}", k, v)?; - } - Ok(()) - } - - pub fn fmt_main_pod_builder(&self, w: &mut dyn Write, pod: &MainPodBuilder) -> io::Result<()> { - writeln!(w, "MainPod:")?; - writeln!(w, " input_signed_pods:")?; - for in_pod in &pod.input_signed_pods { - writeln!(w, " - {}", in_pod.id())?; - } - writeln!(w, " input_main_pods:")?; - for in_pod in &pod.input_main_pods { - writeln!(w, " - {}", in_pod.id())?; - } - writeln!(w, " statements:")?; - for (st, op) in pod.statements.iter().zip_eq(pod.operations.iter()) { - write!(w, " - {} <- ", st)?; - self.fmt_op(w, op)?; - write!(w, "\n")?; - } - Ok(()) - } - - // TODO fn fmt_main_pod -} +// TODO fn fmt_signed_pod_builder +// TODO fn fmt_main_pod #[cfg(test)] pub mod tests { use super::*; use crate::backends::mock_signed::MockSigner; - use std::io; macro_rules! args { ($($arg:expr),+) => {vec![$(OperationArg::from($arg)),*]} @@ -601,9 +602,6 @@ pub mod tests { #[test] fn test_front_0() -> Result<()> { - let printer = Printer {}; - let mut w = io::stdout(); - let params = Params::default(); let (gov_id, pay_stub) = zu_kyc_sign_pod_builders(¶ms); @@ -613,16 +611,16 @@ pub mod tests { pk: "ZooGov".into(), }; let gov_id = gov_id.sign(&mut signer).unwrap(); - printer.fmt_signed_pod(&mut w, &gov_id).unwrap(); + println!("{}", gov_id); let mut signer = MockSigner { pk: "ZooDeel".into(), }; let pay_stub = pay_stub.sign(&mut signer).unwrap(); - printer.fmt_signed_pod(&mut w, &pay_stub).unwrap(); + println!("{}", pay_stub); let kyc = zu_kyc_pod_builder(¶ms, &gov_id, &pay_stub); - printer.fmt_main_pod_builder(&mut w, &kyc).unwrap(); + println!("{}", kyc); // TODO: prove kyc with MockProver and print it diff --git a/src/middleware.rs b/src/middleware.rs index fbee7f6..ef2a517 100644 --- a/src/middleware.rs +++ b/src/middleware.rs @@ -293,6 +293,16 @@ pub enum StatementArg { Key(AnchoredKey), } +impl fmt::Display for StatementArg { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + StatementArg::None => write!(f, "none"), + StatementArg::Literal(v) => write!(f, "{}", v), + StatementArg::Key(r) => write!(f, "{}.{}", r.0, r.1), + } + } +} + impl StatementArg { pub fn is_none(&self) -> bool { matches!(self, Self::None) @@ -332,6 +342,21 @@ impl ToFields for StatementArg { #[derive(Clone, Debug, PartialEq, Eq)] pub struct Statement(pub NativeStatement, pub Vec); +impl fmt::Display for Statement { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?} ", self.0)?; + for (i, arg) in self.1.iter().enumerate() { + if !(!f.alternate() && arg.is_none()) { + if i != 0 { + write!(f, " ")?; + } + write!(f, "{}", arg)?; + } + } + Ok(()) + } +} + impl Statement { pub fn is_none(&self) -> bool { matches!(self.0, NativeStatement::None)