diff --git a/shared/src/ledger/storage_api/collections/hasher.rs b/shared/src/ledger/storage_api/collections/hasher.rs deleted file mode 100644 index 0f864259f54..00000000000 --- a/shared/src/ledger/storage_api/collections/hasher.rs +++ /dev/null @@ -1,9 +0,0 @@ -use borsh::BorshSerialize; - -/// Hash borsh encoded data into a storage sub-key. -/// This is a sha256 as an uppercase hexadecimal string. -pub fn hash_for_storage_key(data: impl BorshSerialize) -> String { - let bytes = data.try_to_vec().unwrap(); - let hash = crate::types::hash::Hash::sha256(bytes); - hash.to_string() -} diff --git a/shared/src/ledger/storage_api/collections/lazy_hashmap.rs b/shared/src/ledger/storage_api/collections/lazy_hashmap.rs deleted file mode 100644 index 9a60fd18f00..00000000000 --- a/shared/src/ledger/storage_api/collections/lazy_hashmap.rs +++ /dev/null @@ -1,269 +0,0 @@ -//! Lazy hash map. - -use std::marker::PhantomData; - -use borsh::{BorshDeserialize, BorshSerialize}; - -use super::super::Result; -use super::hasher::hash_for_storage_key; -use super::LazyCollection; -use crate::ledger::storage_api::{self, ResultExt, StorageRead, StorageWrite}; -use crate::types::storage; - -/// Subkey corresponding to the data elements of the LazyMap -pub const DATA_SUBKEY: &str = "data"; - -/// Lazy hash map. -/// -/// This can be used as an alternative to `std::collections::HashMap` and -/// `BTreeMap`. In the lazy map, the elements do not reside in memory but are -/// instead read and written to storage sub-keys of the storage `key` given to -/// construct the map. -/// -/// In the [`LazyHashMap`], the type of key `K` can be anything that -/// [`BorshSerialize`] and [`BorshDeserialize`] and a hex string of sha256 hash -/// over the borsh encoded keys are used as storage key segments. -/// -/// This is different from [`super::LazyMap`], which uses [`storage::KeySeg`] -/// trait. -/// -/// Additionally, [`LazyHashMap`] also writes the unhashed values into the -/// storage together with the values (using an internal `KeyVal` type). -#[derive(Debug)] -pub struct LazyHashMap { - key: storage::Key, - phantom_k: PhantomData, - phantom_v: PhantomData, -} - -/// Struct to hold a key-value pair -#[derive(Debug, BorshSerialize, BorshDeserialize)] -struct KeyVal { - key: K, - val: V, -} - -impl LazyCollection for LazyHashMap { - /// Create or use an existing map with the given storage `key`. - fn open(key: storage::Key) -> Self { - Self { - key, - phantom_k: PhantomData, - phantom_v: PhantomData, - } - } -} - -impl LazyHashMap -where - K: BorshDeserialize + BorshSerialize + 'static, - V: BorshDeserialize + BorshSerialize + 'static, -{ - /// Inserts a key-value pair into the map. - /// - /// If the map did not have this key present, `None` is returned. - /// If the map did have this key present, the value is updated, and the old - /// value is returned. Unlike in `std::collection::HashMap`, the key is also - /// updated; this matters for types that can be `==` without being - /// identical. - pub fn insert( - &self, - storage: &mut S, - key: K, - val: V, - ) -> Result> - where - S: StorageWrite + for<'iter> StorageRead<'iter>, - { - let previous = self.get(storage, &key)?; - - let data_key = self.get_data_key(&key); - Self::write_key_val(storage, &data_key, key, val)?; - - Ok(previous) - } - - /// Removes a key from the map, returning the value at the key if the key - /// was previously in the map. - pub fn remove(&self, storage: &mut S, key: &K) -> Result> - where - S: StorageWrite + for<'iter> StorageRead<'iter>, - { - let value = self.get(storage, key)?; - - let data_key = self.get_data_key(key); - storage.delete(&data_key)?; - - Ok(value) - } - - /// Returns the value corresponding to the key, if any. - pub fn get(&self, storage: &S, key: &K) -> Result> - where - S: for<'iter> StorageRead<'iter>, - { - let res = self.get_key_val(storage, key)?; - Ok(res.map(|(_key, val)| val)) - } - - /// Returns the key-value corresponding to the key, if any. - pub fn get_key_val(&self, storage: &S, key: &K) -> Result> - where - S: for<'iter> StorageRead<'iter>, - { - let data_key = self.get_data_key(key); - Self::read_key_val(storage, &data_key) - } - - /// Returns the key-value corresponding to the given hash of a key, if any. - pub fn get_key_val_by_hash( - &self, - storage: &S, - key_hash: &str, - ) -> Result> - where - S: for<'iter> StorageRead<'iter>, - { - let data_key = - self.get_data_prefix().push(&key_hash.to_string()).unwrap(); - Self::read_key_val(storage, &data_key) - } - - /// Returns whether the set contains a value. - pub fn contains(&self, storage: &S, key: &K) -> Result - where - S: for<'iter> StorageRead<'iter>, - { - storage.has_key(&self.get_data_key(key)) - } - - /// Returns whether the map contains no elements. - pub fn is_empty(&self, storage: &S) -> Result - where - S: for<'iter> StorageRead<'iter>, - { - let mut iter = - storage_api::iter_prefix_bytes(storage, &self.get_data_prefix())?; - Ok(iter.next().is_none()) - } - - /// Reads the number of elements in the map. - /// - /// Note that this function shouldn't be used in transactions and VPs code - /// on unbounded maps to avoid gas usage increasing with the length of the - /// set. - #[allow(clippy::len_without_is_empty)] - pub fn len(&self, storage: &S) -> Result - where - S: for<'iter> StorageRead<'iter>, - { - let iter = - storage_api::iter_prefix_bytes(storage, &self.get_data_prefix())?; - iter.count().try_into().into_storage_result() - } - - /// An iterator visiting all key-value elements. The iterator element type - /// is `Result<(K, V)>`, because iterator's call to `next` may fail with - /// e.g. out of gas or data decoding error. - /// - /// Note that this function shouldn't be used in transactions and VPs code - /// on unbounded maps to avoid gas usage increasing with the length of the - /// map. - pub fn iter<'iter>( - &self, - storage: &'iter impl StorageRead<'iter>, - ) -> Result> + 'iter> { - let iter = storage_api::iter_prefix(storage, &self.get_data_prefix())?; - Ok(iter.map(|key_val_res| { - let (_key, val) = key_val_res?; - let KeyVal { key, val } = val; - Ok((key, val)) - })) - } - - /// Reads a key-value from storage - fn read_key_val( - storage: &S, - storage_key: &storage::Key, - ) -> Result> - where - S: for<'iter> StorageRead<'iter>, - { - let res = storage.read(storage_key)?; - Ok(res.map(|KeyVal { key, val }| (key, val))) - } - - /// Write a key-value into storage - fn write_key_val( - storage: &mut impl StorageWrite, - storage_key: &storage::Key, - key: K, - val: V, - ) -> Result<()> { - storage.write(storage_key, KeyVal { key, val }) - } - - /// Get the prefix of set's elements storage - fn get_data_prefix(&self) -> storage::Key { - self.key.push(&DATA_SUBKEY.to_owned()).unwrap() - } - - /// Get the sub-key of a given element - fn get_data_key(&self, key: &K) -> storage::Key { - let hash_str = hash_for_storage_key(key); - self.get_data_prefix().push(&hash_str).unwrap() - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::ledger::storage::testing::TestStorage; - - #[test] - fn test_lazy_hash_map_basics() -> storage_api::Result<()> { - let mut storage = TestStorage::default(); - - let key = storage::Key::parse("test").unwrap(); - let lazy_map = LazyHashMap::::open(key); - - // The map should be empty at first - assert!(lazy_map.is_empty(&storage)?); - assert!(lazy_map.len(&storage)? == 0); - assert!(!lazy_map.contains(&storage, &0)?); - assert!(!lazy_map.contains(&storage, &1)?); - assert!(lazy_map.iter(&storage)?.next().is_none()); - assert!(lazy_map.get(&storage, &0)?.is_none()); - assert!(lazy_map.get(&storage, &1)?.is_none()); - assert!(lazy_map.remove(&mut storage, &0)?.is_none()); - assert!(lazy_map.remove(&mut storage, &1)?.is_none()); - - // Insert a new value and check that it's added - let (key, val) = (123, "Test".to_string()); - lazy_map.insert(&mut storage, key, val.clone())?; - assert!(!lazy_map.contains(&storage, &0)?); - assert!(lazy_map.contains(&storage, &key)?); - assert!(!lazy_map.is_empty(&storage)?); - assert!(lazy_map.len(&storage)? == 1); - assert_eq!( - lazy_map.iter(&storage)?.next().unwrap()?, - (key, val.clone()) - ); - assert!(lazy_map.get(&storage, &0)?.is_none()); - assert_eq!(lazy_map.get(&storage, &key)?.unwrap(), val); - - // Remove the last value and check that the map is empty again - let removed = lazy_map.remove(&mut storage, &key)?.unwrap(); - assert_eq!(removed, val); - assert!(lazy_map.is_empty(&storage)?); - assert!(lazy_map.len(&storage)? == 0); - assert!(!lazy_map.contains(&storage, &0)?); - assert!(!lazy_map.contains(&storage, &1)?); - assert!(lazy_map.get(&storage, &0)?.is_none()); - assert!(lazy_map.get(&storage, &key)?.is_none()); - assert!(lazy_map.iter(&storage)?.next().is_none()); - assert!(lazy_map.remove(&mut storage, &key)?.is_none()); - - Ok(()) - } -} diff --git a/shared/src/ledger/storage_api/collections/lazy_hashset.rs b/shared/src/ledger/storage_api/collections/lazy_hashset.rs deleted file mode 100644 index 63ac5c845c7..00000000000 --- a/shared/src/ledger/storage_api/collections/lazy_hashset.rs +++ /dev/null @@ -1,184 +0,0 @@ -//! Lazy hash set. - -use std::marker::PhantomData; - -use borsh::{BorshDeserialize, BorshSerialize}; - -use super::super::Result; -use super::hasher::hash_for_storage_key; -use super::LazyCollection; -use crate::ledger::storage_api::{self, ResultExt, StorageRead, StorageWrite}; -use crate::types::storage; - -/// Subkey corresponding to the data elements of the LazySet -pub const DATA_SUBKEY: &str = "data"; - -/// Lazy hash set. -/// -/// This can be used as an alternative to `std::collections::HashSet` and -/// `BTreeSet`. In the lazy set, the elements do not reside in memory but are -/// instead read and written to storage sub-keys of the storage `key` given to -/// construct the set. -/// -/// In the [`LazyHashSet`], the type of value `T` can be anything that -/// [`BorshSerialize`] and [`BorshDeserialize`] and a hex string of sha256 hash -/// over the borsh encoded values are used as storage key segments. -/// -/// This is different from [`super::LazySet`], which uses [`storage::KeySeg`] -/// trait. -/// -/// Additionally, [`LazyHashSet`] also writes the unhashed values into the -/// storage. -#[derive(Debug)] -pub struct LazyHashSet { - key: storage::Key, - phantom: PhantomData, -} - -impl LazyCollection for LazyHashSet { - /// Create or use an existing set with the given storage `key`. - fn open(key: storage::Key) -> Self { - Self { - key, - phantom: PhantomData, - } - } -} - -impl LazyHashSet -where - T: BorshSerialize + BorshDeserialize + 'static, -{ - /// Adds a value to the set. If the set did not have this value present, - /// `Ok(true)` is returned, `Ok(false)` otherwise. - pub fn insert(&self, storage: &mut S, val: T) -> Result - where - S: StorageWrite + for<'iter> StorageRead<'iter>, - { - if self.contains(storage, &val)? { - Ok(false) - } else { - let data_key = self.get_data_key(&val); - storage.write(&data_key, &val)?; - Ok(true) - } - } - - /// Removes a value from the set. Returns whether the value was present in - /// the set. - pub fn remove(&self, storage: &mut S, val: &T) -> Result - where - S: StorageWrite + for<'iter> StorageRead<'iter>, - { - let data_key = self.get_data_key(val); - let value: Option = storage.read(&data_key)?; - storage.delete(&data_key)?; - Ok(value.is_some()) - } - - /// Returns whether the set contains a value. - pub fn contains(&self, storage: &S, val: &T) -> Result - where - S: for<'iter> StorageRead<'iter>, - { - let value: Option = storage.read(&self.get_data_key(val))?; - Ok(value.is_some()) - } - - /// Reads the number of elements in the set. - /// - /// Note that this function shouldn't be used in transactions and VPs code - /// on unbounded sets to avoid gas usage increasing with the length of the - /// set. - #[allow(clippy::len_without_is_empty)] - pub fn len(&self, storage: &S) -> Result - where - S: for<'iter> StorageRead<'iter>, - { - let iter = - storage_api::iter_prefix_bytes(storage, &self.get_data_prefix())?; - iter.count().try_into().into_storage_result() - } - - /// Returns whether the set contains no elements. - pub fn is_empty(&self, storage: &S) -> Result - where - S: for<'iter> StorageRead<'iter>, - { - let mut iter = storage.iter_prefix(&self.get_data_prefix())?; - Ok(storage.iter_next(&mut iter)?.is_none()) - } - - /// An iterator visiting all elements. The iterator element type is - /// `Result`, because iterator's call to `next` may fail with e.g. out of - /// gas or data decoding error. - /// - /// Note that this function shouldn't be used in transactions and VPs code - /// on unbounded sets to avoid gas usage increasing with the length of the - /// set. - pub fn iter<'iter>( - &self, - storage: &'iter impl StorageRead<'iter>, - ) -> Result> + 'iter> { - let iter = storage_api::iter_prefix(storage, &self.get_data_prefix())?; - Ok(iter.map(|key_val_res| { - let (_key, val) = key_val_res?; - Ok(val) - })) - } - - /// Get the prefix of set's elements storage - fn get_data_prefix(&self) -> storage::Key { - self.key.push(&DATA_SUBKEY.to_owned()).unwrap() - } - - /// Get the sub-key of a given element - fn get_data_key(&self, val: &T) -> storage::Key { - let hash_str = hash_for_storage_key(val); - self.get_data_prefix().push(&hash_str).unwrap() - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::ledger::storage::testing::TestStorage; - - #[test] - fn test_lazy_set_basics() -> storage_api::Result<()> { - let mut storage = TestStorage::default(); - - let key = storage::Key::parse("test").unwrap(); - let lazy_set = LazyHashSet::::open(key); - - // The set should be empty at first - assert!(lazy_set.is_empty(&storage)?); - assert!(lazy_set.len(&storage)? == 0); - assert!(!lazy_set.contains(&storage, &0)?); - assert!(lazy_set.is_empty(&storage)?); - assert!(lazy_set.iter(&storage)?.next().is_none()); - assert!(!lazy_set.remove(&mut storage, &0)?); - assert!(!lazy_set.remove(&mut storage, &1)?); - - // Insert a new value and check that it's added - let val = 1337; - lazy_set.insert(&mut storage, val)?; - assert!(!lazy_set.is_empty(&storage)?); - assert!(lazy_set.len(&storage)? == 1); - assert_eq!(lazy_set.iter(&storage)?.next().unwrap()?, val.clone()); - assert!(!lazy_set.contains(&storage, &0)?); - assert!(lazy_set.contains(&storage, &val)?); - - // Remove the last value and check that the set is empty again - let is_removed = lazy_set.remove(&mut storage, &val)?; - assert!(is_removed); - assert!(lazy_set.is_empty(&storage)?); - assert!(lazy_set.len(&storage)? == 0); - assert!(!lazy_set.contains(&storage, &0)?); - assert!(lazy_set.is_empty(&storage)?); - assert!(!lazy_set.remove(&mut storage, &0)?); - assert!(!lazy_set.remove(&mut storage, &1)?); - - Ok(()) - } -} diff --git a/shared/src/ledger/storage_api/collections/lazy_set.rs b/shared/src/ledger/storage_api/collections/lazy_set.rs deleted file mode 100644 index 3a001e6048e..00000000000 --- a/shared/src/ledger/storage_api/collections/lazy_set.rs +++ /dev/null @@ -1,284 +0,0 @@ -//! Lazy set. - -use std::fmt::Debug; -use std::marker::PhantomData; - -use thiserror::Error; - -use super::super::Result; -use super::{LazyCollection, ReadError}; -use crate::ledger::storage_api::{self, ResultExt, StorageRead, StorageWrite}; -use crate::types::storage::{self, DbKeySeg, KeySeg}; - -/// Subkey corresponding to the data elements of the LazySet -pub const DATA_SUBKEY: &str = "data"; - -/// Lazy set. -/// -/// This can be used as an alternative to `std::collections::HashSet` and -/// `BTreeSet`. In the lazy set, the elements do not reside in memory but are -/// instead read and written to storage sub-keys of the storage `key` used to -/// construct the set. -/// -/// In the [`LazySet`], the type of value `T` can be anything that implements -/// [`storage::KeySeg`] and this trait is used to turn the values into key -/// segments. -/// -/// This is different from [`super::LazyHashSet`], which hashes borsh encoded -/// values. -#[derive(Debug)] -pub struct LazySet { - key: storage::Key, - phantom: PhantomData, -} - -/// Possible sub-keys of a [`LazySet`] -#[derive(Clone, Debug)] -pub enum SubKey { - /// Data sub-key with its literal set value - Data(T), -} - -/// Possible actions that can modify a [`LazySet`]. This -/// roughly corresponds to the methods that have `StorageWrite` access. -#[derive(Clone, Debug)] -pub enum Action { - /// Insert or update a value `T` in a [`LazySet`]. - Insert(T), - /// Remove a value `T` from a [`LazySet`]. - Remove(T), -} - -#[allow(missing_docs)] -#[derive(Error, Debug)] -pub enum ValidationError { - #[error("Invalid storage key {0}")] - InvalidSubKey(storage::Key), -} - -impl LazyCollection for LazySet -where - T: storage::KeySeg + Debug, -{ - type Action = Action; - type SubKey = SubKey; - // In a set, the `SubKey` already contains the data, but we have to - // distinguish `Insert` from `Remove` - type SubKeyWithData = Action; - // There is no "value" for LazySet, `T` is written into the key - type Value = (); - - /// Create or use an existing set with the given storage `key`. - fn open(key: storage::Key) -> Self { - Self { - key, - phantom: PhantomData, - } - } - - fn is_valid_sub_key( - &self, - key: &storage::Key, - ) -> storage_api::Result> { - let suffix = match key.split_prefix(&self.key) { - None => { - // not matching prefix, irrelevant - return Ok(None); - } - Some(None) => { - // no suffix, invalid - return Err(ValidationError::InvalidSubKey(key.clone())) - .into_storage_result(); - } - Some(Some(suffix)) => suffix, - }; - - // Match the suffix against expected sub-keys - match &suffix.segments[..] { - [DbKeySeg::StringSeg(sub_a), DbKeySeg::StringSeg(sub_b)] - if sub_a == DATA_SUBKEY => - { - if let Ok(key_in_kv) = storage::KeySeg::parse(sub_b.clone()) { - Ok(Some(SubKey::Data(key_in_kv))) - } else { - Err(ValidationError::InvalidSubKey(key.clone())) - .into_storage_result() - } - } - _ => Err(ValidationError::InvalidSubKey(key.clone())) - .into_storage_result(), - } - } - - fn read_sub_key_data( - env: &ENV, - storage_key: &storage::Key, - sub_key: Self::SubKey, - ) -> storage_api::Result> - where - ENV: for<'a> crate::ledger::vp_env::VpEnv<'a>, - { - // There is no "value" for LazySet, `T` is written into the key - let SubKey::Data(sub_key) = sub_key; - let has_pre = env.has_key_pre(storage_key)?; - let has_post = env.has_key_post(storage_key)?; - if has_pre && !has_post { - Ok(Some(Action::Remove(sub_key))) - } else if !has_pre && has_post { - Ok(Some(Action::Insert(sub_key))) - } else { - Ok(None) - } - } - - fn validate_changed_sub_keys( - keys: Vec, - ) -> storage_api::Result> { - Ok(keys) - } -} - -impl LazySet -where - T: storage::KeySeg, -{ - /// Adds a value to the set. If the set did not have this value present, - /// `Ok(true)` is returned, `Ok(false)` otherwise. - pub fn insert(&self, storage: &mut S, val: T) -> Result - where - S: StorageWrite + for<'iter> StorageRead<'iter>, - { - if self.contains(storage, &val)? { - Ok(false) - } else { - let data_key = self.get_data_key(&val); - // The actual value is written into the key, so the value written to - // the storage is empty (unit) - storage.write(&data_key, ())?; - Ok(true) - } - } - - /// Removes a value from the set. Returns whether the value was present in - /// the set. - pub fn remove(&self, storage: &mut S, val: &T) -> Result - where - S: StorageWrite + for<'iter> StorageRead<'iter>, - { - let data_key = self.get_data_key(val); - let value: Option<()> = storage.read(&data_key)?; - storage.delete(&data_key)?; - Ok(value.is_some()) - } - - /// Returns whether the set contains a value. - pub fn contains(&self, storage: &S, val: &T) -> Result - where - S: for<'iter> StorageRead<'iter>, - { - storage.has_key(&self.get_data_key(val)) - } - - /// Returns whether the set contains no elements. - pub fn is_empty(&self, storage: &S) -> Result - where - S: for<'iter> StorageRead<'iter>, - { - let mut iter = - storage_api::iter_prefix_bytes(storage, &self.get_data_prefix())?; - Ok(iter.next().is_none()) - } - - /// Reads the number of elements in the set. - /// - /// Note that this function shouldn't be used in transactions and VPs code - /// on unbounded sets to avoid gas usage increasing with the length of the - /// set. - #[allow(clippy::len_without_is_empty)] - pub fn len(&self, storage: &S) -> Result - where - S: for<'iter> StorageRead<'iter>, - { - let iter = - storage_api::iter_prefix_bytes(storage, &self.get_data_prefix())?; - iter.count().try_into().into_storage_result() - } - - /// An iterator visiting all elements. The iterator element type is - /// `Result`, because iterator's call to `next` may fail with e.g. out of - /// gas or data decoding error. - /// - /// Note that this function shouldn't be used in transactions and VPs code - /// on unbounded sets to avoid gas usage increasing with the length of the - /// set. - pub fn iter<'iter>( - &self, - storage: &'iter impl StorageRead<'iter>, - ) -> Result> + 'iter> { - let iter = - storage_api::iter_prefix_bytes(storage, &self.get_data_prefix())?; - Ok(iter.map(|key_val_res| { - let (key, _val) = key_val_res?; - let last_key_seg = key - .last() - .ok_or(ReadError::UnexpectedlyEmptyStorageKey) - .into_storage_result()?; - T::parse(last_key_seg.raw()).into_storage_result() - })) - } - - /// Get the prefix of set's elements storage - fn get_data_prefix(&self) -> storage::Key { - self.key.push(&DATA_SUBKEY.to_owned()).unwrap() - } - - /// Get the sub-key of a given element - fn get_data_key(&self, val: &T) -> storage::Key { - let key_str = val.to_db_key(); - self.get_data_prefix().push(&key_str).unwrap() - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::ledger::storage::testing::TestStorage; - - #[test] - fn test_lazy_set_basics() -> storage_api::Result<()> { - let mut storage = TestStorage::default(); - - let key = storage::Key::parse("test").unwrap(); - let lazy_set = LazySet::::open(key); - - // The set should be empty at first - assert!(lazy_set.is_empty(&storage)?); - assert!(lazy_set.len(&storage)? == 0); - assert!(!lazy_set.contains(&storage, &0)?); - assert!(lazy_set.is_empty(&storage)?); - assert!(lazy_set.iter(&storage)?.next().is_none()); - assert!(!lazy_set.remove(&mut storage, &0)?); - assert!(!lazy_set.remove(&mut storage, &1)?); - - // Insert a new value and check that it's added - let val = 1337; - lazy_set.insert(&mut storage, val)?; - assert!(!lazy_set.is_empty(&storage)?); - assert!(lazy_set.len(&storage)? == 1); - assert_eq!(lazy_set.iter(&storage)?.next().unwrap()?, val.clone()); - assert!(!lazy_set.contains(&storage, &0)?); - assert!(lazy_set.contains(&storage, &val)?); - - // Remove the last value and check that the set is empty again - let is_removed = lazy_set.remove(&mut storage, &val)?; - assert!(is_removed); - assert!(lazy_set.is_empty(&storage)?); - assert!(lazy_set.len(&storage)? == 0); - assert!(!lazy_set.contains(&storage, &0)?); - assert!(lazy_set.is_empty(&storage)?); - assert!(!lazy_set.remove(&mut storage, &0)?); - assert!(!lazy_set.remove(&mut storage, &1)?); - - Ok(()) - } -} diff --git a/shared/src/ledger/storage_api/collections/mod.rs b/shared/src/ledger/storage_api/collections/mod.rs index b77b207c7fd..c8efde4b716 100644 --- a/shared/src/ledger/storage_api/collections/mod.rs +++ b/shared/src/ledger/storage_api/collections/mod.rs @@ -13,17 +13,10 @@ use borsh::BorshDeserialize; use derivative::Derivative; use thiserror::Error; -mod hasher; -// pub mod lazy_hashmap; -// pub mod lazy_hashset; pub mod lazy_map; -// pub mod lazy_set; pub mod lazy_vec; -// pub use lazy_hashmap::LazyHashMap; -// pub use lazy_hashset::LazyHashSet; pub use lazy_map::LazyMap; -// pub use lazy_set::LazySet; pub use lazy_vec::LazyVec; use crate::ledger::storage_api;