diff --git a/src/merkle/delta.rs b/src/merkle/delta.rs deleted file mode 100644 index 846eb16..0000000 --- a/src/merkle/delta.rs +++ /dev/null @@ -1,151 +0,0 @@ -use super::{ - BTreeMap, KvMap, MerkleError, MerkleStore, NodeIndex, RpoDigest, StoreNode, Vec, Word, -}; -use crate::utils::collections::Diff; - -#[cfg(test)] -use super::{super::ONE, Felt, SimpleSmt, EMPTY_WORD, ZERO}; - -// MERKLE STORE DELTA -// ================================================================================================ - -/// [MerkleStoreDelta] stores a vector of ([RpoDigest], [MerkleTreeDelta]) tuples where the -/// [RpoDigest] represents the root of the Merkle tree and [MerkleTreeDelta] represents the -/// differences between the initial and final Merkle tree states. -#[derive(Default, Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -pub struct MerkleStoreDelta(pub Vec<(RpoDigest, MerkleTreeDelta)>); - -// MERKLE TREE DELTA -// ================================================================================================ - -/// [MerkleTreeDelta] stores the differences between the initial and final Merkle tree states. -/// -/// The differences are represented as follows: -/// - depth: the depth of the merkle tree. -/// - cleared_slots: indexes of slots where values were set to [ZERO; 4]. -/// - updated_slots: index-value pairs of slots where values were set to non [ZERO; 4] values. -#[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -pub struct MerkleTreeDelta { - depth: u8, - cleared_slots: Vec, - updated_slots: Vec<(u64, Word)>, -} - -impl MerkleTreeDelta { - // CONSTRUCTOR - // -------------------------------------------------------------------------------------------- - pub fn new(depth: u8) -> Self { - Self { - depth, - cleared_slots: Vec::new(), - updated_slots: Vec::new(), - } - } - - // ACCESSORS - // -------------------------------------------------------------------------------------------- - /// Returns the depth of the Merkle tree the [MerkleTreeDelta] is associated with. - pub fn depth(&self) -> u8 { - self.depth - } - - /// Returns the indexes of slots where values were set to [ZERO; 4]. - pub fn cleared_slots(&self) -> &[u64] { - &self.cleared_slots - } - - /// Returns the index-value pairs of slots where values were set to non [ZERO; 4] values. - pub fn updated_slots(&self) -> &[(u64, Word)] { - &self.updated_slots - } - - // MODIFIERS - // -------------------------------------------------------------------------------------------- - /// Adds a slot index to the list of cleared slots. - pub fn add_cleared_slot(&mut self, index: u64) { - self.cleared_slots.push(index); - } - - /// Adds a slot index and a value to the list of updated slots. - pub fn add_updated_slot(&mut self, index: u64, value: Word) { - self.updated_slots.push((index, value)); - } -} - -/// Extracts a [MerkleTreeDelta] object by comparing the leaves of two Merkle trees specifies by -/// their roots and depth. -pub fn merkle_tree_delta>( - tree_root_1: RpoDigest, - tree_root_2: RpoDigest, - depth: u8, - merkle_store: &MerkleStore, -) -> Result { - if tree_root_1 == tree_root_2 { - return Ok(MerkleTreeDelta::new(depth)); - } - - let tree_1_leaves: BTreeMap = - merkle_store.non_empty_leaves(tree_root_1, depth).collect(); - let tree_2_leaves: BTreeMap = - merkle_store.non_empty_leaves(tree_root_2, depth).collect(); - let diff = tree_1_leaves.diff(&tree_2_leaves); - - // TODO: Refactor this diff implementation to prevent allocation of both BTree and Vec. - Ok(MerkleTreeDelta { - depth, - cleared_slots: diff.removed.into_iter().map(|index| index.value()).collect(), - updated_slots: diff - .updated - .into_iter() - .map(|(index, leaf)| (index.value(), *leaf)) - .collect(), - }) -} - -// TESTS -// ================================================================================================ - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_compute_merkle_delta() { - const TREE_DEPTH: u8 = 30; - - let entries = vec![ - (10, [ZERO, ONE, Felt::new(2), Felt::new(3)]), - (15, [Felt::new(4), Felt::new(5), Felt::new(6), Felt::new(7)]), - (20, [Felt::new(8), Felt::new(9), Felt::new(10), Felt::new(11)]), - (31, [Felt::new(12), Felt::new(13), Felt::new(14), Felt::new(15)]), - ]; - let simple_smt = SimpleSmt::::with_leaves(entries.clone()).unwrap(); - let mut store: MerkleStore = (&simple_smt).into(); - let root = simple_smt.root(); - - // add a new node - let new_value = [Felt::new(16), Felt::new(17), Felt::new(18), Felt::new(19)]; - let new_index = NodeIndex::new(TREE_DEPTH, 32).unwrap(); - let root = store.set_node(root, new_index, new_value.into()).unwrap().root; - - // update an existing node - let update_value = [Felt::new(20), Felt::new(21), Felt::new(22), Felt::new(23)]; - let update_idx = NodeIndex::new(TREE_DEPTH, entries[0].0).unwrap(); - let root = store.set_node(root, update_idx, update_value.into()).unwrap().root; - - // remove a node - let remove_idx = NodeIndex::new(TREE_DEPTH, entries[1].0).unwrap(); - let root = store.set_node(root, remove_idx, EMPTY_WORD.into()).unwrap().root; - - let merkle_delta = merkle_tree_delta(simple_smt.root(), root, TREE_DEPTH, &store).unwrap(); - let expected_merkle_delta = MerkleTreeDelta { - depth: TREE_DEPTH, - cleared_slots: vec![remove_idx.value()], - updated_slots: vec![(update_idx.value(), update_value), (new_index.value(), new_value)], - }; - - assert_eq!(merkle_delta, expected_merkle_delta); - } -} diff --git a/src/merkle/mod.rs b/src/merkle/mod.rs index c3ad147..a7acb36 100644 --- a/src/merkle/mod.rs +++ b/src/merkle/mod.rs @@ -2,7 +2,7 @@ use super::{ hash::rpo::{Rpo256, RpoDigest}, - utils::collections::{vec, BTreeMap, BTreeSet, KvMap, RecordingMap, TryApplyDiff, Vec}, + utils::collections::{vec, BTreeMap, BTreeSet, KvMap, RecordingMap, Vec}, Felt, StarkField, Word, EMPTY_WORD, ZERO, }; @@ -12,9 +12,6 @@ use super::{ mod empty_roots; pub use empty_roots::EmptySubtreeRoots; -mod delta; -pub use delta::{merkle_tree_delta, MerkleStoreDelta, MerkleTreeDelta}; - mod index; pub use index::NodeIndex; diff --git a/src/merkle/smt/simple/mod.rs b/src/merkle/smt/simple/mod.rs index 4186cf7..02b3b34 100644 --- a/src/merkle/smt/simple/mod.rs +++ b/src/merkle/smt/simple/mod.rs @@ -1,6 +1,5 @@ use crate::{ - merkle::{EmptySubtreeRoots, InnerNodeInfo, MerkleTreeDelta, StoreNode, ValuePath}, - utils::collections::TryApplyDiff, + merkle::{EmptySubtreeRoots, InnerNodeInfo, ValuePath}, EMPTY_WORD, }; @@ -300,26 +299,3 @@ impl SparseMerkleTree for SimpleSmt { *key } } - -// TRY APPLY DIFF -// ================================================================================================ -impl TryApplyDiff for SimpleSmt { - type Error = MerkleError; - type DiffType = MerkleTreeDelta; - - fn try_apply(&mut self, diff: MerkleTreeDelta) -> Result<(), MerkleError> { - if diff.depth() != DEPTH { - return Err(MerkleError::InvalidDepth { expected: DEPTH, provided: diff.depth() }); - } - - for slot in diff.cleared_slots() { - self.insert(LeafIndex::::new(*slot)?, Self::EMPTY_VALUE); - } - - for (slot, value) in diff.updated_slots() { - self.insert(LeafIndex::::new(*slot)?, *value); - } - - Ok(()) - } -} diff --git a/src/merkle/store/mod.rs b/src/merkle/store/mod.rs index 9f9bf0d..5f3e36c 100644 --- a/src/merkle/store/mod.rs +++ b/src/merkle/store/mod.rs @@ -1,7 +1,7 @@ use super::{ mmr::Mmr, BTreeMap, EmptySubtreeRoots, InnerNodeInfo, KvMap, MerkleError, MerklePath, - MerkleStoreDelta, MerkleTree, NodeIndex, PartialMerkleTree, RecordingMap, RootPath, Rpo256, - RpoDigest, SimpleSmt, TieredSmt, TryApplyDiff, ValuePath, Vec, EMPTY_WORD, + MerkleTree, NodeIndex, PartialMerkleTree, RecordingMap, RootPath, Rpo256, RpoDigest, SimpleSmt, + TieredSmt, ValuePath, Vec, }; use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}; use core::borrow::Borrow; @@ -550,39 +550,6 @@ impl> Extend for MerkleStore { } } -// DiffT & ApplyDiffT TRAIT IMPLEMENTATION -// ================================================================================================ -impl> TryApplyDiff for MerkleStore { - type Error = MerkleError; - type DiffType = MerkleStoreDelta; - - fn try_apply(&mut self, diff: Self::DiffType) -> Result<(), MerkleError> { - for (root, delta) in diff.0 { - let mut root = root; - for cleared_slot in delta.cleared_slots() { - root = self - .set_node( - root, - NodeIndex::new(delta.depth(), *cleared_slot)?, - EMPTY_WORD.into(), - )? - .root; - } - for (updated_slot, updated_value) in delta.updated_slots() { - root = self - .set_node( - root, - NodeIndex::new(delta.depth(), *updated_slot)?, - (*updated_value).into(), - )? - .root; - } - } - - Ok(()) - } -} - // SERIALIZATION // ================================================================================================ diff --git a/src/utils/diff.rs b/src/utils/diff.rs deleted file mode 100644 index 97fc32f..0000000 --- a/src/utils/diff.rs +++ /dev/null @@ -1,31 +0,0 @@ -/// A trait for computing the difference between two objects. -pub trait Diff { - /// The type that describes the difference between two objects. - type DiffType; - - /// Returns a [Self::DiffType] object that represents the difference between this object and - /// other. - fn diff(&self, other: &Self) -> Self::DiffType; -} - -/// A trait for applying the difference between two objects. -pub trait ApplyDiff { - /// The type that describes the difference between two objects. - type DiffType; - - /// Applies the provided changes described by [Self::DiffType] to the object implementing this trait. - fn apply(&mut self, diff: Self::DiffType); -} - -/// A trait for applying the difference between two objects with the possibility of failure. -pub trait TryApplyDiff { - /// The type that describes the difference between two objects. - type DiffType; - - /// An error type that can be returned if the changes cannot be applied. - type Error; - - /// Applies the provided changes described by [Self::DiffType] to the object implementing this trait. - /// Returns an error if the changes cannot be applied. - fn try_apply(&mut self, diff: Self::DiffType) -> Result<(), Self::Error>; -} diff --git a/src/utils/kv_map.rs b/src/utils/kv_map.rs index 136eb55..dc8927a 100644 --- a/src/utils/kv_map.rs +++ b/src/utils/kv_map.rs @@ -1,4 +1,3 @@ -use super::{collections::ApplyDiff, diff::Diff}; use core::cell::RefCell; use winter_utils::{ collections::{btree_map::IntoIter, BTreeMap, BTreeSet}, @@ -209,74 +208,6 @@ impl IntoIterator for RecordingMap { } } -// KV MAP DIFF -// ================================================================================================ -/// [KvMapDiff] stores the difference between two key-value maps. -/// -/// The [KvMapDiff] is composed of two parts: -/// - `updates` - a map of key-value pairs that were updated in the second map compared to the -/// first map. This includes new key-value pairs. -/// - `removed` - a set of keys that were removed from the second map compared to the first map. -#[derive(Debug, Clone)] -pub struct KvMapDiff { - pub updated: BTreeMap, - pub removed: BTreeSet, -} - -impl KvMapDiff { - // CONSTRUCTOR - // -------------------------------------------------------------------------------------------- - /// Creates a new [KvMapDiff] instance. - pub fn new() -> Self { - KvMapDiff { - updated: BTreeMap::new(), - removed: BTreeSet::new(), - } - } -} - -impl Default for KvMapDiff { - fn default() -> Self { - Self::new() - } -} - -impl> Diff for T { - type DiffType = KvMapDiff; - - fn diff(&self, other: &T) -> Self::DiffType { - let mut diff = KvMapDiff::default(); - for (k, v) in self.iter() { - if let Some(other_value) = other.get(k) { - if v != other_value { - diff.updated.insert(k.clone(), other_value.clone()); - } - } else { - diff.removed.insert(k.clone()); - } - } - for (k, v) in other.iter() { - if self.get(k).is_none() { - diff.updated.insert(k.clone(), v.clone()); - } - } - diff - } -} - -impl> ApplyDiff for T { - type DiffType = KvMapDiff; - - fn apply(&mut self, diff: Self::DiffType) { - for (k, v) in diff.updated { - self.insert(k, v); - } - for k in diff.removed { - self.remove(&k); - } - } -} - // TESTS // ================================================================================================ @@ -470,35 +401,4 @@ mod tests { } } } - - #[test] - fn test_kv_map_diff() { - let mut initial_state = ITEMS.into_iter().collect::>(); - let mut map = RecordingMap::new(initial_state.clone()); - - // remove an item that exists - let key = 0; - let _value = map.remove(&key).unwrap(); - - // add a new item - let key = 100; - let value = 100; - map.insert(key, value); - - // update an existing item - let key = 1; - let value = 100; - map.insert(key, value); - - // compute a diff - let diff = initial_state.diff(map.inner()); - assert!(diff.updated.len() == 2); - assert!(diff.updated.iter().all(|(k, v)| [(100, 100), (1, 100)].contains(&(*k, *v)))); - assert!(diff.removed.len() == 1); - assert!(diff.removed.first() == Some(&0)); - - // apply the diff to the initial state and assert the contents are the same as the map - initial_state.apply(diff); - assert!(initial_state.iter().eq(map.iter())); - } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 715eee8..94f27d1 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -9,7 +9,6 @@ pub use alloc::{format, vec}; #[cfg(feature = "std")] pub use std::{format, vec}; -mod diff; mod kv_map; // RE-EXPORTS @@ -20,7 +19,6 @@ pub use winter_utils::{ }; pub mod collections { - pub use super::diff::*; pub use super::kv_map::*; pub use winter_utils::collections::*; }