From d574fd78e52d2fd3572422c0c3009910276121db Mon Sep 17 00:00:00 2001 From: Kurtis Charnock Date: Fri, 6 Feb 2026 17:29:33 +0000 Subject: [PATCH 1/2] feat(Merkle): make MerkleLayer modal Adds modal generics to `MerkleLayer` Adds a `MerkleLayerMode` trait Implements `MerkleLayerMode` for `Normal` --- Cargo.lock | 1 + durable-storage/Cargo.toml | 1 + durable-storage/src/merkle_layer.rs | 170 +++++++++++++++++++++------ durable-storage/src/merkle_worker.rs | 21 ++-- 4 files changed, 146 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1676fa900fb..8b5c0dcb184 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2447,6 +2447,7 @@ dependencies = [ "log", "octez-riscv-data", "octez-riscv-test-utils", + "perfect-derive", "proptest", "rand 0.9.2", "rocksdb", diff --git a/durable-storage/Cargo.toml b/durable-storage/Cargo.toml index 21e3845f1e4..aa9e6c41e01 100644 --- a/durable-storage/Cargo.toml +++ b/durable-storage/Cargo.toml @@ -15,6 +15,7 @@ goldenfile.workspace = true log.workspace = true hex.workspace = true octez-riscv-data.workspace = true +perfect-derive.workspace = true rand.workspace = true rocksdb.workspace = true tempfile.workspace = true diff --git a/durable-storage/src/merkle_layer.rs b/durable-storage/src/merkle_layer.rs index 3f7960a92f6..7ffb645a9bf 100644 --- a/durable-storage/src/merkle_layer.rs +++ b/durable-storage/src/merkle_layer.rs @@ -2,9 +2,13 @@ // // SPDX-License-Identifier: MIT +use std::fmt::Debug; +use std::marker::PhantomData; use std::sync::Arc; use octez_riscv_data::hash::Hash; +use octez_riscv_data::mode::Normal; +use perfect_derive::perfect_derive; use crate::avl::node::Value; use crate::avl::resolver::ArcResolver; @@ -17,31 +21,39 @@ use crate::persistence_layer::PersistenceLayerError; /// Errors for fallible [MerkleLayer] operations. #[derive(Debug, thiserror::Error)] -pub enum MerkleLayerError { +pub enum MerkleLayerError { #[error("Some error happened while trying to encode the node {0}")] EncodeError(#[from] bincode::error::EncodeError), #[error("Some error happened during the interaction with the persistence layer {0}")] PersistenceLayerError(#[from] PersistenceLayerError), + + #[error("A mode-specific error happened")] + ModeSpecific(E), } /// A layer for transforming data into a Merkelised representation before commitment to the [PersistenceLayer]. -#[derive(Clone, Debug)] -pub struct MerkleLayer { +#[perfect_derive(Clone, Debug)] +pub struct MerkleLayer { tree: Tree, persistence: Arc, resolver: ArcResolver, + _pd: PhantomData, } +unsafe impl Send for MerkleLayer {} +unsafe impl Sync for MerkleLayer {} + /// A layer for transforming data into a Merkelised representation before commitment to the [PersistenceLayer]. -impl MerkleLayer { +impl MerkleLayer { /// Create a new, empty Merkle layer that will commit to the provided persistence layer. pub fn new(persistence: Arc) -> Self { let resolver = ArcResolver; - MerkleLayer { + MerkleLayer:: { tree: Tree::default(), persistence, resolver, + _pd: Default::default(), } } @@ -49,7 +61,7 @@ impl MerkleLayer { pub fn checkout( _persistence: Arc, _root: Hash, - ) -> Result { + ) -> Result> { todo!() } @@ -57,7 +69,7 @@ impl MerkleLayer { pub fn clone_with( &self, _persistence: Arc, - ) -> Result { + ) -> Result> { Ok(self.clone()) } @@ -71,7 +83,7 @@ impl MerkleLayer { } /// Generates a commitment for the [MerkleLayer]. - pub fn commit(&mut self) -> Result { + pub fn commit(&mut self) -> Result> { // Note that although we're doing in order // iteration of the nodes the hashes are // calculated during the encoding of the node @@ -124,17 +136,103 @@ impl MerkleLayer { } } +#[cfg_attr( + not(feature = "bench"), + expect(dead_code, reason = "Used in next commit") +)] +pub trait MerkleLayerMode: Sized { + type Error: Debug + Send; + + /// Clear all data from the [MerkleLayer]. + fn clear(this: &mut MerkleLayer) -> Result<(), MerkleLayerError>; + + /// Delete the data associated with a given [Key]. + fn delete(this: &mut MerkleLayer, key: &Key) + -> Result<(), MerkleLayerError>; + + /// Sets the data associated with a given [Key]. + fn set( + this: &mut MerkleLayer, + key: &Key, + buffer: &[u8], + ) -> Result<(), MerkleLayerError>; + + /// Writes the data to the node associated with a given [Key] with the given offset. + fn write( + this: &mut MerkleLayer, + key: &Key, + offset: usize, + buffer: &mut [u8], + ) -> Result>; + + /// Returns the root hash, potentially re-hashing uncached nodes. + fn hash(this: &mut MerkleLayer) -> Result>; + + /// Clone the Merkle layer. The new layer will commit to the provided persistence layer. + fn clone(this: &MerkleLayer) -> Result, MerkleLayerError>; +} + +impl MerkleLayerMode for Normal { + type Error = MerkleLayerNormalError; + + fn clear(_this: &mut MerkleLayer) -> Result<(), MerkleLayerError> { + todo!() + } + + fn delete( + _this: &mut MerkleLayer, + _key: &Key, + ) -> Result<(), MerkleLayerError> { + todo!() + } + + fn set( + _this: &mut MerkleLayer, + _key: &Key, + _buffer: &[u8], + ) -> Result<(), MerkleLayerError> { + todo!() + } + + fn write( + _this: &mut MerkleLayer, + _key: &Key, + _offset: usize, + _buffer: &mut [u8], + ) -> Result> { + todo!() + } + + fn hash(_this: &mut MerkleLayer) -> Result> { + todo!() + } + + fn clone( + _this: &MerkleLayer, + ) -> Result, MerkleLayerError> { + todo!() + } +} + +#[derive(Clone, Debug)] +pub enum MerkleLayerNormalError {} + +unsafe impl Send for MerkleLayerNormalError {} +unsafe impl Sync for MerkleLayerNormalError {} + #[cfg(test)] mod tests { use std::collections::HashSet; use bytes::Bytes; + use octez_riscv_data::mode::Normal; use octez_riscv_test_utils::TestableTmpdir; use proptest::prelude::*; use proptest::prop_assert_eq; use proptest::proptest; use super::MerkleLayer; + use super::MerkleLayerMode; use crate::avl::Node; use crate::avl::Tree; use crate::avl::hash; @@ -142,13 +240,13 @@ mod tests { use crate::persistence_layer::PersistenceLayer; use crate::repo::DirectoryManager; - impl MerkleLayer { + impl MerkleLayer { fn tree(&self) -> &Tree { &self.tree } } - fn new_merkle_layer() -> MerkleLayer { + fn new_merkle_layer() -> MerkleLayer { let tmpdir = TestableTmpdir::new(); let repo = @@ -168,7 +266,7 @@ mod tests { let data = [vec![0; 0], vec![13; 5], vec![42; 129]]; - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); for i in 0..keys.len() { ml.set(&keys[i], &data[i]); @@ -232,7 +330,7 @@ mod tests { fn test_mavl_cow_prop(keys1 in prop::collection::vec(any::<[u8; 2]>(), 0..500), keys2 in prop::collection::vec(any::<[u8; 2]>(), 0..500)) { let data1 = Bytes::from("property"); let data2 = Bytes::from("cow"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); // Set all the keys in the tree for bytes in &keys1 { @@ -284,7 +382,7 @@ mod tests { fn test_mavl_create() { let key = Key::new(&[1]).expect("Size less than KEY_MAX_SIZE"); let data = Bytes::from("create"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); let empty_hash = ml.hash(); ml.set(&key, &data); assert_ne!(empty_hash, ml.hash()); @@ -303,7 +401,7 @@ mod tests { let key = Key::new(&[1]).expect("Size less than KEY_MAX_SIZE"); let data = Bytes::from("old"); let data2 = Bytes::from("new"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); ml.set(&key, &data); let old_hash = ml.hash(); @@ -316,10 +414,7 @@ mod tests { ml.set(&key, &data2); assert_ne!(old_hash, ml.hash()); - assert!( - ml.tree.is_inorder(&ml.resolver), - "AVL isn't in order: {ml:?}" - ); + assert!(ml.tree.is_inorder(&ml.resolver), "AVL isn't in order"); let node = Node::new(key.clone(), data2); let get_node = ml .get(&key) @@ -346,7 +441,7 @@ mod tests { Bytes::from("0, 0, 0"), ]; - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); for (key, data) in keys.iter().zip(data.iter()) { let old_hash = ml.hash(); @@ -374,7 +469,7 @@ mod tests { ] .map(|r| r.expect("Sizes less than KEY_MAX_SIZE")); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); let empty_hash = ml.hash(); // Left imbalance @@ -412,7 +507,7 @@ mod tests { let data = Bytes::from("left_right"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); for key in keys.iter() { let old_hash = ml.hash(); @@ -434,7 +529,7 @@ mod tests { let data = Bytes::from("right_left"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); for key in keys.iter() { let old_hash = ml.hash(); @@ -467,7 +562,7 @@ mod tests { let data = Bytes::from("right_left"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); for key in keys.iter() { let old_hash = ml.hash(); @@ -500,7 +595,7 @@ mod tests { let data = Bytes::from("right_left"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); for key in keys.iter() { let old_hash = ml.hash(); @@ -519,7 +614,7 @@ mod tests { #[test] fn test_mavl_create_prop(keys in prop::collection::vec(any::<[u8; 2]>(), 0..500)) { let data = Bytes::from("property"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); let old_hash = ml.hash(); for bytes in &keys { @@ -544,7 +639,7 @@ mod tests { fn test_mavl_delete() { let key = Key::new(&[1]).expect("Sizes less than KEY_MAX_SIZE"); let data = Bytes::from("delete"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); let empty_hash = ml.hash(); ml.set(&key, &data); let full_hash = ml.hash(); @@ -564,7 +659,7 @@ mod tests { #[test] fn test_mavl_delete_prop(keys in prop::collection::vec(any::<[u8; 2]>(), 0..500)) { let data = Bytes::from("delete_prop"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); let empty_hash = ml.hash(); for bytes in &keys { @@ -591,7 +686,7 @@ mod tests { fn test_mavl_delete_keys(keys: &[Key]) { let data = Bytes::from("delete"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); let empty_hash = ml.hash(); for key in keys.iter() { @@ -756,7 +851,7 @@ mod tests { fn test_mavl_get_mut() { let key = Key::new(&[1]).expect("Sizes less than KEY_MAX_SIZE"); let data = Bytes::from("get_mut"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); let empty_hash = ml.hash(); ml.set(&key, &data.clone()); let full_hash = ml.hash(); @@ -788,7 +883,7 @@ mod tests { let key = Key::new(&[1]).expect("Sizes less than KEY_MAX_SIZE"); let data = Bytes::from("get_mut_cow"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); let empty_hash = ml.hash(); ml.set(&key, &data); @@ -822,7 +917,7 @@ mod tests { #[test] fn test_mavl_get_mut_prop(keys in prop::collection::vec(any::<[u8; 2]>(), 0..500)) { let data = Bytes::from("get_mut_prop"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); for bytes in &keys { let key = Key::new(bytes).expect("Sizes less than KEY_MAX_SIZE"); @@ -860,7 +955,7 @@ mod tests { fn test_mavl_write_new_value() { let key = Key::new(&[1]).expect("Size less than KEY_MAX_SIZE"); let data = Bytes::from("write_new_value"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); let old_hash = ml.hash(); ml.write(&key, 0, &data); @@ -879,7 +974,7 @@ mod tests { let key = Key::new(&[1]).expect("Size less than KEY_MAX_SIZE"); let data = Bytes::from("a long value"); let data2 = Bytes::from("good"); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); ml.set(&key, &data); let old_hash = ml.hash(); @@ -893,10 +988,7 @@ mod tests { ml.write(&key, 2, &data2); assert_ne!(old_hash, ml.hash()); - assert!( - ml.tree.is_inorder(&ml.resolver), - "AVL isn't in order: {ml:?}" - ); + assert!(ml.tree.is_inorder(&ml.resolver), "AVL isn't in order"); let node = Node::new(key.clone(), Bytes::from("a good value")); let get_node = ml .get(&key) @@ -918,7 +1010,7 @@ mod tests { .cloned() .collect::>()); - let mut ml = new_merkle_layer(); + let mut ml = new_merkle_layer::(); let old_hash = ml.hash(); for bytes in &keys { @@ -949,7 +1041,7 @@ mod tests { /// is the same as the root hash #[test] fn test_merkle_layer_commit_persists_nodes() { - let mut merkle_layer = new_merkle_layer(); + let mut merkle_layer = new_merkle_layer::(); let keys = [ Key::new(&[12]).unwrap(), diff --git a/durable-storage/src/merkle_worker.rs b/durable-storage/src/merkle_worker.rs index e93245862f5..fb3f308b555 100644 --- a/durable-storage/src/merkle_worker.rs +++ b/durable-storage/src/merkle_worker.rs @@ -12,6 +12,7 @@ use std::sync::Arc; use bytes::Bytes; use octez_riscv_data::hash::Hash; +use octez_riscv_data::mode::Normal; use tokio::runtime::Handle; use tokio::sync::mpsc; use tokio::sync::oneshot; @@ -20,6 +21,7 @@ use crate::commit::CommitId; use crate::key::Key; use crate::merkle_layer::MerkleLayer; use crate::merkle_layer::MerkleLayerError; +use crate::merkle_layer::MerkleLayerNormalError; use crate::persistence_layer::PersistenceLayer; /// Commands that can be sent to the Merkle worker background thread @@ -46,7 +48,7 @@ enum Command { /// Flush the current Merkle state to the persistence layer and obtain a commit ID. Commit { /// The background thread will write its response to this one-shot channel. - response: oneshot::Sender>, + response: oneshot::Sender>>, }, /// Clone the current Merkle layer. @@ -55,7 +57,8 @@ enum Command { persistence_layer: Arc, /// The background thread will write its response to this one-shot channel. - response: oneshot::Sender>, + response: + oneshot::Sender, MerkleLayerError>>, }, } @@ -71,7 +74,7 @@ pub struct MerkleWorker { #[derive(Debug, thiserror::Error)] pub enum MerkleWorkerError { #[error("Merkle layer error: {0}")] - MerkleLayerError(#[from] MerkleLayerError), + MerkleLayerError(#[from] MerkleLayerError), } impl MerkleWorker { @@ -130,7 +133,7 @@ impl MerkleWorker { /// Create a Merkle worker from an existing Merkle layer. /// /// The provided handle is used to spawn the background worker thread. - fn from_layer(async_handle: &Handle, layer: MerkleLayer) -> Self { + fn from_layer(async_handle: &Handle, layer: MerkleLayer) -> Self { let (sender, receiver) = mpsc::unbounded_channel(); async_handle.spawn(async move { @@ -223,6 +226,7 @@ mod tests { use std::sync::Arc; use bytes::Bytes; + use octez_riscv_data::mode::Normal; use proptest::prelude::Just; use proptest::prelude::Strategy; use proptest::prop_assert_eq; @@ -231,6 +235,7 @@ mod tests { use crate::key::KEY_MAX_SIZE; use crate::key::Key; use crate::merkle_layer::MerkleLayer; + use crate::merkle_layer::MerkleLayerMode; use crate::merkle_worker::MerkleWorker; use crate::persistence_layer::PersistenceLayer; use crate::repo::DirectoryManager; @@ -267,17 +272,17 @@ mod tests { } impl TestCommand { - fn run( + fn run( self, handle: &Handle, dir_manager: &DirectoryManager, worker: &mut MerkleWorker, - layer: &mut MerkleLayer, + layer: &mut MerkleLayer, ) { match self { Self::Write { key, offset, value } => { layer.write(&key, offset, &value); - worker.write(key, offset, value); + MerkleWorker::write(worker, key, offset, value); } Self::Set { key, value } => { @@ -376,7 +381,7 @@ mod tests { let mut merkle_worker = MerkleWorker::new(handle, persistence_worker).expect("Creating a Merkle worker should succeed"); for command in commands { - command.run(handle, &dir_manager, &mut merkle_worker, &mut merkle_layer); + command.run::(handle, &dir_manager, &mut merkle_worker, &mut merkle_layer); } let layer_hash = merkle_layer.hash(); From f0fdcbd4b5511bb1e835a43f0a0b05859d6afd0d Mon Sep 17 00:00:00 2001 From: Kurtis Charnock Date: Fri, 6 Feb 2026 18:09:46 +0000 Subject: [PATCH 2/2] feat(Merkle): use `MerkleLayerMode` methods Implements `MerkleLayer` methods using the associated modal type. --- durable-storage/src/avl.rs | 2 +- durable-storage/src/merkle_layer.rs | 128 +++++++++++++++------------- 2 files changed, 70 insertions(+), 60 deletions(-) diff --git a/durable-storage/src/avl.rs b/durable-storage/src/avl.rs index 44714d3aada..34f94195c4d 100644 --- a/durable-storage/src/avl.rs +++ b/durable-storage/src/avl.rs @@ -21,5 +21,5 @@ cfg_if::cfg_if! { pub(crate) use node::Node; #[cfg(test)] pub(crate) use node::hash; -#[cfg(any(test, feature = "bench"))] +#[cfg(feature = "bench")] pub use tree::Tree; diff --git a/durable-storage/src/merkle_layer.rs b/durable-storage/src/merkle_layer.rs index 7ffb645a9bf..53a338d7007 100644 --- a/durable-storage/src/merkle_layer.rs +++ b/durable-storage/src/merkle_layer.rs @@ -70,7 +70,7 @@ impl MerkleLayer { &self, _persistence: Arc, ) -> Result> { - Ok(self.clone()) + M::clone(self) } /// Clear all data from the [MerkleLayer]. @@ -79,7 +79,7 @@ impl MerkleLayer { expect(dead_code, reason = "Not pub in `Database`") )] pub fn clear(&mut self) { - self.tree.take(); + M::clear(self).expect("Currently infallible"); } /// Generates a commitment for the [MerkleLayer]. @@ -99,7 +99,7 @@ impl MerkleLayer { /// Delete the data associated with a given [Key]. pub fn delete(&mut self, key: &Key) { - self.tree.delete(key, &mut self.resolver); + M::delete(self, key).expect("Currently infallible"); } /// Returns an immutable reference to the data stored for a given [Key]. @@ -122,24 +122,28 @@ impl MerkleLayer { /// Returns the root hash, potentially re-hashing uncached nodes. pub fn hash(&mut self) -> Hash { - self.tree.hash(&self.resolver) + M::hash(self).expect("Currently infallible") } /// Sets the data associated with a given [Key]. pub fn set(&mut self, key: &Key, data: &[u8]) { - self.tree.set(key, data, &mut self.resolver); + M::set(self, key, data).expect("Currently infallible"); } /// Writes the data to the node associated with a given [Key] with the given offset. pub fn write(&mut self, key: &Key, offset: usize, data: &[u8]) { - self.tree.write(key, offset, data, &mut self.resolver); + M::write(self, key, offset, data).expect("Currently infallible"); + } + + fn tree_mut(&mut self) -> &mut Tree { + &mut self.tree + } + + fn resolver_tree_pair_mut(&mut self) -> (&mut ArcResolver, &mut Tree) { + (&mut self.resolver, &mut self.tree) } } -#[cfg_attr( - not(feature = "bench"), - expect(dead_code, reason = "Used in next commit") -)] pub trait MerkleLayerMode: Sized { type Error: Debug + Send; @@ -162,7 +166,7 @@ pub trait MerkleLayerMode: Sized { this: &mut MerkleLayer, key: &Key, offset: usize, - buffer: &mut [u8], + buffer: &[u8], ) -> Result>; /// Returns the root hash, potentially re-hashing uncached nodes. @@ -175,42 +179,48 @@ pub trait MerkleLayerMode: Sized { impl MerkleLayerMode for Normal { type Error = MerkleLayerNormalError; - fn clear(_this: &mut MerkleLayer) -> Result<(), MerkleLayerError> { - todo!() + fn clear(this: &mut MerkleLayer) -> Result<(), MerkleLayerError> { + this.tree_mut().take(); + Ok(()) } fn delete( - _this: &mut MerkleLayer, - _key: &Key, + this: &mut MerkleLayer, + key: &Key, ) -> Result<(), MerkleLayerError> { - todo!() + let (resolver, tree) = this.resolver_tree_pair_mut(); + tree.delete(key, resolver); + Ok(()) } fn set( - _this: &mut MerkleLayer, - _key: &Key, - _buffer: &[u8], + this: &mut MerkleLayer, + key: &Key, + buffer: &[u8], ) -> Result<(), MerkleLayerError> { - todo!() + let (resolver, tree) = this.resolver_tree_pair_mut(); + tree.set(key, buffer, resolver); + Ok(()) } fn write( - _this: &mut MerkleLayer, - _key: &Key, - _offset: usize, - _buffer: &mut [u8], + this: &mut MerkleLayer, + key: &Key, + offset: usize, + buffer: &[u8], ) -> Result> { - todo!() + let (resolver, tree) = this.resolver_tree_pair_mut(); + tree.write(key, offset, buffer, resolver); + Ok(buffer.len()) } - fn hash(_this: &mut MerkleLayer) -> Result> { - todo!() + fn hash(this: &mut MerkleLayer) -> Result> { + let (resolver, tree) = this.resolver_tree_pair_mut(); + Ok(tree.hash(resolver)) } - fn clone( - _this: &MerkleLayer, - ) -> Result, MerkleLayerError> { - todo!() + fn clone(this: &MerkleLayer) -> Result, MerkleLayerError> { + Ok(this.clone()) } } @@ -234,15 +244,15 @@ mod tests { use super::MerkleLayer; use super::MerkleLayerMode; use crate::avl::Node; - use crate::avl::Tree; use crate::avl::hash; use crate::key::Key; use crate::persistence_layer::PersistenceLayer; use crate::repo::DirectoryManager; impl MerkleLayer { - fn tree(&self) -> &Tree { - &self.tree + fn check(&mut self) { + let (resolver, tree) = self.resolver_tree_pair_mut(); + tree.check(resolver); } } @@ -270,7 +280,7 @@ mod tests { for i in 0..keys.len() { ml.set(&keys[i], &data[i]); - ml.tree().check(&ml.resolver); + ml.check(); } let mut ml2 = ml.clone(); @@ -321,8 +331,8 @@ mod tests { .expect("The node should be retrieved successfully. Merkle layer: {ml2:?}") ); - ml.tree().check(&ml.resolver); - ml2.tree().check(&ml.resolver); + ml.check(); + ml2.check(); } proptest! { @@ -373,8 +383,8 @@ mod tests { prop_assert_eq!(ml2.get(&key).expect("The node should be retrieved successfully"), &data2); } - ml.tree().check(&ml.resolver); - ml2.tree().check(&ml2.resolver); + ml.check(); + ml2.check(); } } @@ -393,7 +403,7 @@ mod tests { .expect("The node should be retrieved successfully"); assert_eq!(&get_node, &node.data()); - ml.tree().check(&ml.resolver); + ml.check(); } #[test] @@ -421,7 +431,7 @@ mod tests { .expect("The node should be retrieved successfully"); assert_eq!(&get_node, &node.data()); - ml.tree().check(&ml.resolver); + ml.check(); } #[test] @@ -447,7 +457,7 @@ mod tests { let old_hash = ml.hash(); ml.set(key, data); assert_ne!(old_hash, ml.hash()); - ml.tree().check(&ml.resolver); + ml.check(); assert_eq!( ml.get(key) .expect("The node should be retrieved successfully"), @@ -478,7 +488,7 @@ mod tests { let old_hash = ml.hash(); ml.set(key, &data); assert_ne!(old_hash, ml.hash()); - ml.tree().check(&ml.resolver); + ml.check(); } ml.clear(); @@ -496,7 +506,7 @@ mod tests { let old_hash = ml.hash(); ml.set(key, &data); assert_ne!(old_hash, ml.hash()); - ml.tree().check(&ml.resolver); + ml.check(); } } @@ -513,7 +523,7 @@ mod tests { let old_hash = ml.hash(); ml.set(key, &data); assert_ne!(old_hash, ml.hash()); - ml.tree().check(&ml.resolver); + ml.check(); assert_eq!( ml.get(key) .expect("The node should be retrieved successfully"), @@ -535,7 +545,7 @@ mod tests { let old_hash = ml.hash(); ml.set(key, &data); assert_ne!(old_hash, ml.hash()); - ml.tree().check(&ml.resolver); + ml.check(); assert_eq!( ml.get(key) .expect("The node should be retrieved successfully"), @@ -568,7 +578,7 @@ mod tests { let old_hash = ml.hash(); ml.set(key, &data); assert_ne!(old_hash, ml.hash()); - ml.tree().check(&ml.resolver); + ml.check(); assert_eq!( ml.get(key) .expect("The node should be retrieved successfully"), @@ -601,7 +611,7 @@ mod tests { let old_hash = ml.hash(); ml.set(key, &data); assert_ne!(old_hash, ml.hash()); - ml.tree().check(&ml.resolver); + ml.check(); assert_eq!( ml.get(key) .expect("The node should be retrieved successfully"), @@ -631,7 +641,7 @@ mod tests { prop_assert_eq!(ml.get(&key).expect("The node should be retrieved successfully"), &data); } - ml.tree().check(&ml.resolver); + ml.check(); } } @@ -652,7 +662,7 @@ mod tests { let get_node = ml.get(&key); assert_eq!(get_node, None); - ml.tree().check(&ml.resolver); + ml.check(); } proptest! { @@ -679,7 +689,7 @@ mod tests { prop_assert_eq!(empty_hash, ml.hash()); - ml.tree().check(&ml.resolver); + ml.check(); } } @@ -691,7 +701,7 @@ mod tests { for key in keys.iter() { ml.set(key, &data); - ml.tree().check(&ml.resolver); + ml.check(); assert_eq!( ml.get(key) .expect("The node should be retrieved successfully"), @@ -705,7 +715,7 @@ mod tests { for key in keys.iter() { ml.delete(key); - ml.tree().check(&ml.resolver); + ml.check(); ml.delete(key); assert_eq!(ml.get(key), None); } @@ -875,7 +885,7 @@ mod tests { assert_ne!(&get_node, &before_node.data()); assert_eq!(&get_node, &after_node.data()); - ml.tree().check(&ml.resolver); + ml.check(); } #[test] @@ -910,7 +920,7 @@ mod tests { assert_eq!(&get_node, &before_node.data()); - ml.tree().check(&ml.resolver); + ml.check(); } proptest! { @@ -947,7 +957,7 @@ mod tests { seen.insert(key); } - ml.tree().check(&ml.resolver); + ml.check(); } } @@ -966,7 +976,7 @@ mod tests { assert_eq!(&get_node, &node.data()); assert_ne!(old_hash, ml.hash()); - ml.tree().check(&ml.resolver); + ml.check(); } #[test] @@ -996,7 +1006,7 @@ mod tests { assert_eq!(get_node.len(), data_len); assert_eq!(&get_node, &node.data()); - ml.tree().check(&ml.resolver); + ml.check(); } proptest! { @@ -1030,7 +1040,7 @@ mod tests { prop_assert_eq!(ml.get(&key).expect("The node should be retrieved successfully"), &alternating); } - ml.tree().check(&ml.resolver); + ml.check(); } }