From 96dc9bd840b6b859a3be115d61c82029e822d5a3 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Fri, 16 May 2025 18:37:38 -0400 Subject: [PATCH 1/8] serialize for `HashStorageMerkleTree` --- common/src/merkle_tree_public/merkle_tree.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/common/src/merkle_tree_public/merkle_tree.rs b/common/src/merkle_tree_public/merkle_tree.rs index 16d185e..d5fd72d 100644 --- a/common/src/merkle_tree_public/merkle_tree.rs +++ b/common/src/merkle_tree_public/merkle_tree.rs @@ -12,6 +12,24 @@ pub struct HashStorageMerkleTree { tree: MerkleTree, } +impl Serialize for HashStorageMerkleTree { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut vector = self.leaves.iter().collect::>(); + vector.sort_by(|a, b| a.0.cmp(b.0)); + + let mut seq = serializer.serialize_seq(Some(self.leaves.len()))?; + for element in vector.iter() { + seq.serialize_element(element.1)?; + } + seq.end() + } +} + + + pub type PublicTransactionMerkleTree = HashStorageMerkleTree; pub type UTXOCommitmentsMerkleTree = HashStorageMerkleTree; From 0daffaf4ada799228cd17760d7082e641a7dd242 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Fri, 16 May 2025 18:37:58 -0400 Subject: [PATCH 2/8] HashStorageMerkleTreeDeserializer --- common/src/merkle_tree_public/merkle_tree.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/common/src/merkle_tree_public/merkle_tree.rs b/common/src/merkle_tree_public/merkle_tree.rs index d5fd72d..70ca0f4 100644 --- a/common/src/merkle_tree_public/merkle_tree.rs +++ b/common/src/merkle_tree_public/merkle_tree.rs @@ -28,6 +28,18 @@ impl Serialize for HashStorageMerkleTree } } +struct HashStorageMerkleTreeDeserializer { + marker: PhantomData HashStorageMerkleTree> +} + +impl HashStorageMerkleTreeDeserializer { + fn new() -> Self { + HashStorageMerkleTreeDeserializer { + marker: PhantomData + } + } +} + pub type PublicTransactionMerkleTree = HashStorageMerkleTree; From 9df2b51813a56e22bae56d195c548abc8a0908af Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Fri, 16 May 2025 18:38:36 -0400 Subject: [PATCH 3/8] imple `Visitor` for `HashStorageMerkleTreeDeserializer` --- common/src/merkle_tree_public/merkle_tree.rs | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/common/src/merkle_tree_public/merkle_tree.rs b/common/src/merkle_tree_public/merkle_tree.rs index 70ca0f4..0dc3f6b 100644 --- a/common/src/merkle_tree_public/merkle_tree.rs +++ b/common/src/merkle_tree_public/merkle_tree.rs @@ -40,6 +40,32 @@ impl HashStorageMerkleTreeDeserializer { } } +impl<'de, Leav: TreeLeavItem + Clone + Deserialize<'de>> Visitor<'de> for HashStorageMerkleTreeDeserializer { + type Value= HashStorageMerkleTree; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("HashStorageMerkleTree key value sequence.") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let mut vector = vec![]; + + loop { + let opt_key = seq.next_element::()?; + if let Some(value) = opt_key { + vector.push(value); + } else { + break; + } + } + + Ok(HashStorageMerkleTree::new(vector)) + } +} + pub type PublicTransactionMerkleTree = HashStorageMerkleTree; From cdb8e3a08a0876d663858b52c2865f098189c93f Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Fri, 16 May 2025 18:39:24 -0400 Subject: [PATCH 4/8] imple`Deserialize` for `HashStorageMerkleTree` --- common/src/merkle_tree_public/merkle_tree.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/common/src/merkle_tree_public/merkle_tree.rs b/common/src/merkle_tree_public/merkle_tree.rs index 0dc3f6b..d769218 100644 --- a/common/src/merkle_tree_public/merkle_tree.rs +++ b/common/src/merkle_tree_public/merkle_tree.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use rs_merkle::{MerkleProof, MerkleTree}; +use serde::{de::{self, SeqAccess, Visitor}, ser::SerializeSeq, Deserialize, Deserializer, Serialize}; use crate::{transaction::Transaction, utxo_commitment::UTXOCommitment}; @@ -66,7 +67,11 @@ impl<'de, Leav: TreeLeavItem + Clone + Deserialize<'de>> Visitor<'de> for HashSt } } - +impl<'de, Leav: TreeLeavItem + Clone + Deserialize<'de>> serde::Deserialize<'de> for HashStorageMerkleTree { + fn deserialize>(deserializer: D) -> Result { + deserializer.deserialize_seq(HashStorageMerkleTreeDeserializer::new()) + } +} pub type PublicTransactionMerkleTree = HashStorageMerkleTree; From 2346f06d23ec733a1f15486faa4b63970be4575a Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Fri, 16 May 2025 18:39:39 -0400 Subject: [PATCH 5/8] add a test --- common/src/merkle_tree_public/merkle_tree.rs | 22 ++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/common/src/merkle_tree_public/merkle_tree.rs b/common/src/merkle_tree_public/merkle_tree.rs index d769218..21275d3 100644 --- a/common/src/merkle_tree_public/merkle_tree.rs +++ b/common/src/merkle_tree_public/merkle_tree.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, fmt, marker::PhantomData}; use rs_merkle::{MerkleProof, MerkleTree}; use serde::{de::{self, SeqAccess, Visitor}, ser::SerializeSeq, Deserialize, Deserializer, Serialize}; @@ -162,7 +162,7 @@ mod tests { use super::*; // Mock implementation of TreeLeavItem trait for testing - #[derive(Debug, Clone, PartialEq, Eq, Hash)] + #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] struct MockTransaction { pub hash: TreeHashType, } @@ -197,6 +197,24 @@ mod tests { assert!(tree.get_root().is_some()); } + #[test] + fn test_new_merkle_tree_serialize() { + let tx1 = MockTransaction { + hash: get_first_32_bytes("tx1"), + }; + let tx2 = MockTransaction { + hash: get_first_32_bytes("tx2"), + }; + + let tree = HashStorageMerkleTree::new(vec![tx1.clone(), tx2.clone()]); + + let binding = serde_json::to_vec(&tree).unwrap(); + + let obj: HashStorageMerkleTree = serde_json::from_slice(&binding).unwrap(); + + assert_eq!(tree.leaves, obj.leaves); + } + #[test] fn test_get_tx() { let tx1 = MockTransaction { From b4c0fb935130679f625254f61bc5ef568a390bc6 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Fri, 16 May 2025 18:40:45 -0400 Subject: [PATCH 6/8] fmt --- common/src/merkle_tree_public/merkle_tree.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/common/src/merkle_tree_public/merkle_tree.rs b/common/src/merkle_tree_public/merkle_tree.rs index 21275d3..1cb84e8 100644 --- a/common/src/merkle_tree_public/merkle_tree.rs +++ b/common/src/merkle_tree_public/merkle_tree.rs @@ -1,7 +1,11 @@ use std::{collections::HashMap, fmt, marker::PhantomData}; use rs_merkle::{MerkleProof, MerkleTree}; -use serde::{de::{self, SeqAccess, Visitor}, ser::SerializeSeq, Deserialize, Deserializer, Serialize}; +use serde::{ + de::{self, SeqAccess, Visitor}, + ser::SerializeSeq, + Deserialize, Deserializer, Serialize, +}; use crate::{transaction::Transaction, utxo_commitment::UTXOCommitment}; @@ -30,19 +34,21 @@ impl Serialize for HashStorageMerkleTree } struct HashStorageMerkleTreeDeserializer { - marker: PhantomData HashStorageMerkleTree> + marker: PhantomData HashStorageMerkleTree>, } impl HashStorageMerkleTreeDeserializer { fn new() -> Self { HashStorageMerkleTreeDeserializer { - marker: PhantomData + marker: PhantomData, } } } -impl<'de, Leav: TreeLeavItem + Clone + Deserialize<'de>> Visitor<'de> for HashStorageMerkleTreeDeserializer { - type Value= HashStorageMerkleTree; +impl<'de, Leav: TreeLeavItem + Clone + Deserialize<'de>> Visitor<'de> + for HashStorageMerkleTreeDeserializer +{ + type Value = HashStorageMerkleTree; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("HashStorageMerkleTree key value sequence.") @@ -67,7 +73,9 @@ impl<'de, Leav: TreeLeavItem + Clone + Deserialize<'de>> Visitor<'de> for HashSt } } -impl<'de, Leav: TreeLeavItem + Clone + Deserialize<'de>> serde::Deserialize<'de> for HashStorageMerkleTree { +impl<'de, Leav: TreeLeavItem + Clone + Deserialize<'de>> serde::Deserialize<'de> + for HashStorageMerkleTree +{ fn deserialize>(deserializer: D) -> Result { deserializer.deserialize_seq(HashStorageMerkleTreeDeserializer::new()) } From 4ba4c12a87522fb0c34a66e77dd1aecf5c3da874 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Fri, 16 May 2025 19:16:45 -0400 Subject: [PATCH 7/8] rm unused --- common/src/merkle_tree_public/merkle_tree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/merkle_tree_public/merkle_tree.rs b/common/src/merkle_tree_public/merkle_tree.rs index 1cb84e8..64a6343 100644 --- a/common/src/merkle_tree_public/merkle_tree.rs +++ b/common/src/merkle_tree_public/merkle_tree.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, fmt, marker::PhantomData}; use rs_merkle::{MerkleProof, MerkleTree}; use serde::{ - de::{self, SeqAccess, Visitor}, + de::{SeqAccess, Visitor}, ser::SerializeSeq, Deserialize, Deserializer, Serialize, }; From a6429466657bfc996ff5338bcab5a441dd629bd2 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Wed, 28 May 2025 01:05:44 -0400 Subject: [PATCH 8/8] add asserts to test --- common/src/merkle_tree_public/merkle_tree.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/src/merkle_tree_public/merkle_tree.rs b/common/src/merkle_tree_public/merkle_tree.rs index 64a6343..3540b06 100644 --- a/common/src/merkle_tree_public/merkle_tree.rs +++ b/common/src/merkle_tree_public/merkle_tree.rs @@ -221,6 +221,8 @@ mod tests { let obj: HashStorageMerkleTree = serde_json::from_slice(&binding).unwrap(); assert_eq!(tree.leaves, obj.leaves); + assert_eq!(tree.hash_to_id_map, obj.hash_to_id_map); + assert_eq!(tree.tree.root(), obj.tree.root()); } #[test]