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);
This commit is contained in:
arnaucube 2025-02-10 12:37:11 +01:00 committed by GitHub
parent f23a78dcb8
commit 5236b46214
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 176 additions and 173 deletions

View file

@ -7,6 +7,7 @@ use itertools::Itertools;
use plonky2::hash::poseidon::PoseidonHash; use plonky2::hash::poseidon::PoseidonHash;
use plonky2::plonk::config::Hasher; use plonky2::plonk::config::Hasher;
use std::any::Any; use std::any::Any;
use std::fmt;
use std::io::{self, Write}; use std::io::{self, Write};
pub struct MockProver {} pub struct MockProver {}
@ -32,6 +33,24 @@ impl OperationArg {
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
struct Operation(pub NativeOperation, pub Vec<OperationArg>); struct Operation(pub NativeOperation, pub Vec<OperationArg>);
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)] #[derive(Clone, Debug)]
pub struct MockMainPod { pub struct MockMainPod {
params: Params, params: Params,
@ -46,6 +65,73 @@ pub struct MockMainPod {
statements: Vec<Statement>, statements: Vec<Statement>,
} }
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<T: Clone>(v: &mut Vec<T>, pad_value: T, len: usize) { fn fill_pad<T: Clone>(v: &mut Vec<T>, pad_value: T, len: usize) {
if v.len() > len { if v.len() > len {
panic!("length exceeded"); 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)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*; use super::*;
@ -435,9 +417,7 @@ pub mod tests {
let kyc_pod = kyc_builder.prove(&mut prover).unwrap(); let kyc_pod = kyc_builder.prove(&mut prover).unwrap();
let pod = kyc_pod.pod.into_any().downcast::<MockMainPod>().unwrap(); let pod = kyc_pod.pod.into_any().downcast::<MockMainPod>().unwrap();
let printer = Printer { skip_none: false }; println!("{:#}", pod);
let mut w = io::stdout();
printer.fmt_mock_main_pod(&mut w, &pod).unwrap();
// assert_eq!(pod.verify(), true); // TODO // assert_eq!(pod.verify(), true); // TODO
// println!("id: {}", pod.id()); // println!("id: {}", pod.id());

View file

@ -7,7 +7,6 @@ use plonky2::field::types::Field;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::From; use std::convert::From;
use std::fmt; use std::fmt;
use std::io::{self, Write};
use crate::middleware::{ use crate::middleware::{
self, hash_str, Hash, MainPodInputs, NativeOperation, NativeStatement, Params, PodId, self, hash_str, Hash, MainPodInputs, NativeOperation, NativeStatement, Params, PodId,
@ -119,6 +118,20 @@ pub struct SignedPod {
pub key_string_map: HashMap<Hash, String>, pub key_string_map: HashMap<Hash, String>,
} }
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 { impl SignedPod {
pub fn id(&self) -> PodId { pub fn id(&self) -> PodId {
self.pod.id() self.pod.id()
@ -176,6 +189,17 @@ pub enum OperationArg {
Entry(String, Value), 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<Value> for OperationArg { impl From<Value> for OperationArg {
fn from(v: Value) -> Self { fn from(v: Value) -> Self {
Self::Literal(v) Self::Literal(v)
@ -215,6 +239,19 @@ impl From<(&SignedPod, &str)> for OperationArg {
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct Operation(pub NativeOperation, pub Vec<OperationArg>); pub struct Operation(pub NativeOperation, pub Vec<OperationArg>);
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)] #[derive(Debug)]
pub struct MainPodBuilder { pub struct MainPodBuilder {
pub params: Params, pub params: Params,
@ -227,6 +264,27 @@ pub struct MainPodBuilder {
const_cnt: usize, 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 { impl MainPodBuilder {
pub fn new(params: &Params) -> Self { pub fn new(params: &Params) -> Self {
Self { Self {
@ -484,70 +542,13 @@ impl MainPodCompiler {
} }
} }
pub struct Printer {} // TODO fn fmt_signed_pod_builder
// TODO fn fmt_main_pod
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
}
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*; use super::*;
use crate::backends::mock_signed::MockSigner; use crate::backends::mock_signed::MockSigner;
use std::io;
macro_rules! args { macro_rules! args {
($($arg:expr),+) => {vec![$(OperationArg::from($arg)),*]} ($($arg:expr),+) => {vec![$(OperationArg::from($arg)),*]}
@ -601,9 +602,6 @@ pub mod tests {
#[test] #[test]
fn test_front_0() -> Result<()> { fn test_front_0() -> Result<()> {
let printer = Printer {};
let mut w = io::stdout();
let params = Params::default(); let params = Params::default();
let (gov_id, pay_stub) = zu_kyc_sign_pod_builders(&params); let (gov_id, pay_stub) = zu_kyc_sign_pod_builders(&params);
@ -613,16 +611,16 @@ pub mod tests {
pk: "ZooGov".into(), pk: "ZooGov".into(),
}; };
let gov_id = gov_id.sign(&mut signer).unwrap(); 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 { let mut signer = MockSigner {
pk: "ZooDeel".into(), pk: "ZooDeel".into(),
}; };
let pay_stub = pay_stub.sign(&mut signer).unwrap(); 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(&params, &gov_id, &pay_stub); let kyc = zu_kyc_pod_builder(&params, &gov_id, &pay_stub);
printer.fmt_main_pod_builder(&mut w, &kyc).unwrap(); println!("{}", kyc);
// TODO: prove kyc with MockProver and print it // TODO: prove kyc with MockProver and print it

View file

@ -293,6 +293,16 @@ pub enum StatementArg {
Key(AnchoredKey), 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 { impl StatementArg {
pub fn is_none(&self) -> bool { pub fn is_none(&self) -> bool {
matches!(self, Self::None) matches!(self, Self::None)
@ -332,6 +342,21 @@ impl ToFields for StatementArg {
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct Statement(pub NativeStatement, pub Vec<StatementArg>); pub struct Statement(pub NativeStatement, pub Vec<StatementArg>);
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 { impl Statement {
pub fn is_none(&self) -> bool { pub fn is_none(&self) -> bool {
matches!(self.0, NativeStatement::None) matches!(self.0, NativeStatement::None)