feat: added utility to format MerkleTree and MerklePath to hex
Example formatted MerkleTree:
```
880abe452320966617646e7740b014954300f19a28780a0889d62ff33f4b0534
1ade1369091efa31201e9b60c9c28874d0ddce5362b335135a6bb4c917285983
3e60a9c843b4bb19f7a0572102e6507195f5240767a396335fd21981b048b807
0100000000000000000000000000000000000000000000000000000000000000
0200000000000000000000000000000000000000000000000000000000000000
0300000000000000000000000000000000000000000000000000000000000000
0400000000000000000000000000000000000000000000000000000000000000
```
Example formatted MerklePath:
```
[0400000000000000000000000000000000000000000000000000000000000000, 1ade1369091efa31201e9b60c9c28874d0ddce5362b335135a6bb4c917285983]
```
Augusto F. Hack hack.augusto@gmail.com
Wed, 22 Mar 2023 12:06:02 +0100
4 files changed,
74 insertions(+),
9 deletions(-)
M
src/lib.rs
→
src/lib.rs
@@ -7,18 +7,13 @@
mod bit; pub mod hash; pub mod merkle; +pub mod utils; // RE-EXPORTS // ================================================================================================ pub use winter_crypto::{RandomCoin, RandomCoinError}; pub use winter_math::{fields::f64::BaseElement as Felt, FieldElement, StarkField}; -pub mod utils { - pub use winter_utils::{ - collections, string, uninit_vector, ByteReader, ByteWriter, Deserializable, - DeserializationError, Serializable, SliceReader, - }; -} // TYPE ALIASES // ================================================================================================
M
src/merkle/merkle_tree.rs
→
src/merkle/merkle_tree.rs
@@ -1,6 +1,9 @@
use super::{Felt, MerkleError, MerklePath, NodeIndex, Rpo256, RpoDigest, Vec, Word}; -use crate::{utils::uninit_vector, FieldElement}; -use core::slice; +use crate::{ + utils::{string::String, uninit_vector, word_to_hex}, + FieldElement, +}; +use core::{fmt, slice}; use winter_math::log2; // MERKLE TREE@@ -155,6 +158,52 @@ }
Ok(()) } +} + +/// Utility to vizualize a [MerkleTree] in text. +pub fn tree_to_text(tree: &MerkleTree) -> Result<String, fmt::Error> { + let indent = " "; + let mut s = String::new(); + s.push_str(&word_to_hex(&tree.root())?); + s.push('\n'); + for d in 1..=tree.depth() { + let entries = 2u64.pow(d.into()); + for i in 0..entries { + let index = NodeIndex::new(d, i); + + let node = tree + .get_node(index) + .expect("The index must always be valid"); + + for _ in 0..d { + s.push_str(indent); + } + s.push_str(&word_to_hex(&node)?); + s.push('\n'); + } + } + + Ok(s) +} + +/// Utility to vizualize a [MerklePath] in text. +pub fn path_to_text(path: &MerklePath) -> Result<String, fmt::Error> { + let mut s = String::new(); + s.push('['); + + for el in path.iter() { + s.push_str(&word_to_hex(el)?); + s.push_str(", "); + } + + // remove the last ", " + if path.len() != 0 { + s.pop(); + s.pop(); + } + s.push(']'); + + Ok(s) } // TESTS
M
src/merkle/mod.rs
→
src/merkle/mod.rs
@@ -15,7 +15,7 @@ mod index;
pub use index::NodeIndex; mod merkle_tree; -pub use merkle_tree::MerkleTree; +pub use merkle_tree::{path_to_text, tree_to_text, MerkleTree}; mod path; pub use path::{MerklePath, RootPath, ValuePath};
A
src/utils.rs
@@ -0,0 +1,21 @@
+use super::Word; +use crate::utils::string::String; +use core::fmt::{self, Write}; + +// RE-EXPORTS +// ================================================================================================ +pub use winter_utils::{ + collections, string, uninit_vector, ByteReader, ByteWriter, Deserializable, + DeserializationError, Serializable, SliceReader, +}; + +/// Converts a [Word] into hex. +pub fn word_to_hex(w: &Word) -> Result<String, fmt::Error> { + let mut s = String::new(); + + for byte in w.iter().flat_map(|e| e.to_bytes()) { + write!(s, "{byte:02x}")?; + } + + Ok(s) +}