arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
feat: add de/serialization to `InOrderIndex` and `PartialMmr` (#329)

Santiago Pittella 87827390+SantiagoPittella@users.noreply.github.com
Fri, 13 Sep 2024 12:47:46 -0300
commit

2b184cd4ca6e00d9a89fcfdb633c27c8c7d103ff

parent

8bb893345b078b8b71d9047f011b81ee29f6263f

3 files changed, 75 insertions(+), 5 deletions(-)

jump to
M CHANGELOG.md → CHANGELOG.md

@@ -1,3 +1,7 @@

+## 0.10.1 (TBD) + +* Added `Serializable` and `Deserializable` implementations for `PartialMmr` and `InOrderIndex` (#329). + ## 0.10.0 (2024-08-06) * Added more `RpoDigest` and `RpxDigest` conversions (#311).
M src/merkle/mmr/inorder.rs → src/merkle/mmr/inorder.rs

@@ -6,6 +6,8 @@ //! This property makes it is easy to compute changes to the index by adding or subtracting the

//! leaves count. use core::num::NonZeroUsize; +use winter_utils::{Deserializable, Serializable}; + // IN-ORDER INDEX // ================================================================================================

@@ -112,6 +114,21 @@ self.idx as u64

} } +impl Serializable for InOrderIndex { + fn write_into<W: winter_utils::ByteWriter>(&self, target: &mut W) { + target.write_usize(self.idx); + } +} + +impl Deserializable for InOrderIndex { + fn read_from<R: winter_utils::ByteReader>( + source: &mut R, + ) -> Result<Self, winter_utils::DeserializationError> { + let idx = source.read_usize()?; + Ok(InOrderIndex { idx }) + } +} + // CONVERSIONS FROM IN-ORDER INDEX // ------------------------------------------------------------------------------------------------

@@ -127,6 +144,7 @@

#[cfg(test)] mod test { use proptest::prelude::*; + use winter_utils::{Deserializable, Serializable}; use super::InOrderIndex;

@@ -161,5 +179,13 @@ assert_eq!(left.parent().right_child(), right);

assert_eq!(left, right.parent().left_child()); assert_eq!(left.sibling(), right); assert_eq!(left, right.sibling()); + } + + #[test] + fn test_inorder_index_serialization() { + let index = InOrderIndex::from_leaf_pos(5); + let bytes = index.to_bytes(); + let index2 = InOrderIndex::read_from_bytes(&bytes).unwrap(); + assert_eq!(index, index2); } }
M src/merkle/mmr/partial.rs → src/merkle/mmr/partial.rs

@@ -1,11 +1,14 @@

+use alloc::{ + collections::{BTreeMap, BTreeSet}, + vec::Vec, +}; + +use winter_utils::{Deserializable, Serializable}; + use super::{MmrDelta, MmrProof, Rpo256, RpoDigest}; use crate::merkle::{ mmr::{leaf_to_corresponding_tree, nodes_in_forest}, InOrderIndex, InnerNodeInfo, MerklePath, MmrError, MmrPeaks, -}; -use alloc::{ - collections::{BTreeMap, BTreeSet}, - vec::Vec, }; // TYPE ALIASES

@@ -572,6 +575,28 @@ None

} } +impl Serializable for PartialMmr { + fn write_into<W: winter_utils::ByteWriter>(&self, target: &mut W) { + self.forest.write_into(target); + self.peaks.write_into(target); + self.nodes.write_into(target); + target.write_bool(self.track_latest); + } +} + +impl Deserializable for PartialMmr { + fn read_from<R: winter_utils::ByteReader>( + source: &mut R, + ) -> Result<Self, winter_utils::DeserializationError> { + let forest = usize::read_from(source)?; + let peaks = Vec::<RpoDigest>::read_from(source)?; + let nodes = NodeMap::read_from(source)?; + let track_latest = source.read_bool()?; + + Ok(Self { forest, peaks, nodes, track_latest }) + } +} + // UTILS // ================================================================================================

@@ -613,12 +638,15 @@ // ================================================================================================

#[cfg(test)] mod tests { + use alloc::{collections::BTreeSet, vec::Vec}; + + use winter_utils::{Deserializable, Serializable}; + use super::{ forest_to_rightmost_index, forest_to_root_index, InOrderIndex, MmrPeaks, PartialMmr, RpoDigest, }; use crate::merkle::{int_to_node, MerkleStore, Mmr, NodeIndex}; - use alloc::{collections::BTreeSet, vec::Vec}; const LEAVES: [RpoDigest; 7] = [ int_to_node(0),

@@ -906,5 +934,17 @@ partial_mmr.add(leaf_at_7, false);

// the openings should be the same assert_eq!(mmr.open(5, mmr.forest()).unwrap(), partial_mmr.open(5).unwrap().unwrap()); + } + + #[test] + fn test_partial_mmr_serialization() { + let mmr = Mmr::from((0..7).map(int_to_node)); + let forest_size = mmr.forest(); + let partial_mmr = PartialMmr::from_peaks(mmr.peaks(forest_size).unwrap()); + + let bytes = partial_mmr.to_bytes(); + let decoded = PartialMmr::read_from_bytes(&bytes).unwrap(); + + assert_eq!(partial_mmr, decoded); } }