diff --git a/client/db/src/bench.rs b/client/db/src/bench.rs index c198fb400408e..1f2f46af0079e 100644 --- a/client/db/src/bench.rs +++ b/client/db/src/bench.rs @@ -373,13 +373,14 @@ impl StateBackend> for BenchmarkingState { } } - fn apply_to_child_keys_while bool>( + fn apply_to_keys_while bool>( &self, - child_info: &ChildInfo, + child_info: Option<&ChildInfo>, + prefix: Option<&[u8]>, f: F, ) { if let Some(ref state) = *self.state.borrow() { - state.apply_to_child_keys_while(child_info, f) + state.apply_to_keys_while(child_info, prefix, f) } } diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index cda197ab0687a..38b9d7a7adff4 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -205,12 +205,13 @@ impl StateBackend> for RefTrackingState { self.state.for_key_values_with_prefix(prefix, f) } - fn apply_to_child_keys_while bool>( + fn apply_to_keys_while bool>( &self, - child_info: &ChildInfo, + child_info: Option<&ChildInfo>, + prefix: Option<&[u8]>, f: F, ) { - self.state.apply_to_child_keys_while(child_info, f) + self.state.apply_to_keys_while(child_info, prefix, f) } fn for_child_keys_with_prefix( diff --git a/client/db/src/storage_cache.rs b/client/db/src/storage_cache.rs index cb2ab1de1b6c9..788e011fb2f05 100644 --- a/client/db/src/storage_cache.rs +++ b/client/db/src/storage_cache.rs @@ -605,12 +605,13 @@ impl>, B: BlockT> StateBackend> for Cachin self.state.exists_child_storage(child_info, key) } - fn apply_to_child_keys_while bool>( + fn apply_to_keys_while bool>( &self, - child_info: &ChildInfo, + child_info: Option<&ChildInfo>, + prefix: Option<&[u8]>, f: F, ) { - self.state.apply_to_child_keys_while(child_info, f) + self.state.apply_to_keys_while(child_info, prefix, f) } fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { @@ -787,12 +788,13 @@ impl>, B: BlockT> StateBackend> for Syncin self.caching_state().exists_child_storage(child_info, key) } - fn apply_to_child_keys_while bool>( + fn apply_to_keys_while bool>( &self, - child_info: &ChildInfo, + child_info: Option<&ChildInfo>, + prefix: Option<&[u8]>, f: F, ) { - self.caching_state().apply_to_child_keys_while(child_info, f) + self.caching_state().apply_to_keys_while(child_info, prefix, f) } fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { diff --git a/client/executor/runtime-test/src/lib.rs b/client/executor/runtime-test/src/lib.rs index 115683bffa62d..7969cb6896419 100644 --- a/client/executor/runtime-test/src/lib.rs +++ b/client/executor/runtime-test/src/lib.rs @@ -63,7 +63,7 @@ sp_core::wasm_export_functions! { } fn test_clear_prefix(input: Vec) -> Vec { - storage::clear_prefix(&input); + storage::clear_prefix(&input, None); b"all ok!".to_vec() } diff --git a/client/light/src/backend.rs b/client/light/src/backend.rs index 4c8ac3fe40f4d..a7f1b8e0c1696 100644 --- a/client/light/src/backend.rs +++ b/client/light/src/backend.rs @@ -461,14 +461,15 @@ impl StateBackend for GenesisOrUnavailableState } } - fn apply_to_child_keys_while bool>( + fn apply_to_keys_while bool>( &self, - child_info: &ChildInfo, + child_info: Option<&ChildInfo>, + prefix: Option<&[u8]>, action: A, ) { match *self { GenesisOrUnavailableState::Genesis(ref state) => - state.apply_to_child_keys_while(child_info, action), + state.apply_to_keys_while(child_info, prefix, action), GenesisOrUnavailableState::Unavailable => (), } } diff --git a/frame/contracts/src/storage.rs b/frame/contracts/src/storage.rs index 17486b274f2c9..15782d7d1e459 100644 --- a/frame/contracts/src/storage.rs +++ b/frame/contracts/src/storage.rs @@ -33,7 +33,7 @@ use sp_runtime::{ use sp_core::crypto::UncheckedFrom; use frame_support::{ dispatch::{DispatchError, DispatchResult}, - storage::child::{self, KillChildStorageResult, ChildInfo}, + storage::child::{self, KillStorageResult, ChildInfo}, traits::Get, weights::Weight, }; @@ -331,14 +331,14 @@ where let removed = queue.swap_remove(0); match outcome { // This should not happen as our budget was large enough to remove all keys. - KillChildStorageResult::SomeRemaining(_) => { + KillStorageResult::SomeRemaining(_) => { log::error!( target: "runtime::contracts", "After deletion keys are remaining in this child trie: {:?}", removed.trie_id, ); }, - KillChildStorageResult::AllRemoved(_) => (), + KillStorageResult::AllRemoved(_) => (), } } remaining_key_budget = remaining_key_budget diff --git a/frame/elections-phragmen/src/benchmarking.rs b/frame/elections-phragmen/src/benchmarking.rs index 3534a62ac3ce0..86a0116978067 100644 --- a/frame/elections-phragmen/src/benchmarking.rs +++ b/frame/elections-phragmen/src/benchmarking.rs @@ -142,7 +142,7 @@ fn clean() { >::kill(); >::kill(); >::kill(); - >::remove_all(); + >::remove_all(None); } benchmarks! { diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index e132f7f929a06..318e3d2de3ad2 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -809,8 +809,8 @@ impl OneSessionHandler for Pallet { // Remove all received heartbeats and number of authored blocks from the // current session, they have already been processed and won't be needed // anymore. - ReceivedHeartbeats::::remove_prefix(&T::ValidatorSet::session_index()); - AuthoredBlocks::::remove_prefix(&T::ValidatorSet::session_index()); + ReceivedHeartbeats::::remove_prefix(&T::ValidatorSet::session_index(), None); + AuthoredBlocks::::remove_prefix(&T::ValidatorSet::session_index(), None); if offenders.is_empty() { Self::deposit_event(Event::::AllGood); diff --git a/frame/society/src/lib.rs b/frame/society/src/lib.rs index 3b661386da23e..ff6cc0786dcb1 100644 --- a/frame/society/src/lib.rs +++ b/frame/society/src/lib.rs @@ -871,7 +871,7 @@ decl_module! { Founder::::kill(); Rules::::kill(); Candidates::::kill(); - SuspendedCandidates::::remove_all(); + SuspendedCandidates::::remove_all(None); Self::deposit_event(RawEvent::Unfounded(founder)); } @@ -1402,7 +1402,7 @@ impl, I: Instance> Module { }).collect::>(); // Clean up all votes. - >::remove_all(); + >::remove_all(None); // Reward one of the voters who voted the right way. if !total_slash.is_zero() { @@ -1570,7 +1570,7 @@ impl, I: Instance> Module { } // Clean up all votes. - >::remove_all(); + >::remove_all(None); } // Avoid challenging if there's only two members since we never challenge the Head or diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 734afb0824615..ff7a1ae8a8820 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -2655,9 +2655,9 @@ impl Pallet { /// Clear all era information for given era. fn clear_era_information(era_index: EraIndex) { - >::remove_prefix(era_index); - >::remove_prefix(era_index); - >::remove_prefix(era_index); + >::remove_prefix(era_index, None); + >::remove_prefix(era_index, None); + >::remove_prefix(era_index, None); >::remove(era_index); >::remove(era_index); >::remove(era_index); diff --git a/frame/staking/src/slashing.rs b/frame/staking/src/slashing.rs index 50cab1103b95a..1e959e9341add 100644 --- a/frame/staking/src/slashing.rs +++ b/frame/staking/src/slashing.rs @@ -543,8 +543,8 @@ impl<'a, T: 'a + Config> Drop for InspectingSpans<'a, T> { /// Clear slashing metadata for an obsolete era. pub(crate) fn clear_era_metadata(obsolete_era: EraIndex) { - as Store>::ValidatorSlashInEra::remove_prefix(&obsolete_era); - as Store>::NominatorSlashInEra::remove_prefix(&obsolete_era); + as Store>::ValidatorSlashInEra::remove_prefix(&obsolete_era, None); + as Store>::NominatorSlashInEra::remove_prefix(&obsolete_era, None); } /// Clear slashing metadata for a dead account. diff --git a/frame/staking/src/testing_utils.rs b/frame/staking/src/testing_utils.rs index 185b96983ab94..f3af4ac0920d1 100644 --- a/frame/staking/src/testing_utils.rs +++ b/frame/staking/src/testing_utils.rs @@ -29,8 +29,8 @@ const SEED: u32 = 0; /// This function removes all validators and nominators from storage. pub fn clear_validators_and_nominators() { - Validators::::remove_all(); - Nominators::::remove_all(); + Validators::::remove_all(None); + Nominators::::remove_all(None); } /// Grab a funded user. diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 43891c158200e..49e61eea569bd 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -1005,7 +1005,10 @@ pub mod tests { DoubleMap::insert(&key1, &(key2 + 1), &4u64); DoubleMap::insert(&(key1 + 1), &key2, &4u64); DoubleMap::insert(&(key1 + 1), &(key2 + 1), &4u64); - DoubleMap::remove_prefix(&key1); + assert!(matches!( + DoubleMap::remove_prefix(&key1, None), + sp_io::KillStorageResult::AllRemoved(0), // all in overlay + )); assert_eq!(DoubleMap::get(&key1, &key2), 0u64); assert_eq!(DoubleMap::get(&key1, &(key2 + 1)), 0u64); assert_eq!(DoubleMap::get(&(key1 + 1), &key2), 4u64); diff --git a/frame/support/src/storage/child.rs b/frame/support/src/storage/child.rs index 6f99874743946..52830c8ac5dc8 100644 --- a/frame/support/src/storage/child.rs +++ b/frame/support/src/storage/child.rs @@ -24,7 +24,7 @@ use crate::sp_std::prelude::*; use codec::{Codec, Encode, Decode}; pub use sp_core::storage::{ChildInfo, ChildType}; -pub use crate::sp_io::KillChildStorageResult; +pub use crate::sp_io::KillStorageResult; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. pub fn get( @@ -174,7 +174,7 @@ pub fn exists( pub fn kill_storage( child_info: &ChildInfo, limit: Option, -) -> KillChildStorageResult { +) -> KillStorageResult { match child_info.child_type() { ChildType::ParentKeyId => sp_io::default_child_storage::storage_kill( child_info.storage_key(), diff --git a/frame/support/src/storage/generator/double_map.rs b/frame/support/src/storage/generator/double_map.rs index c02ebe48290eb..836ae25bdbbcf 100644 --- a/frame/support/src/storage/generator/double_map.rs +++ b/frame/support/src/storage/generator/double_map.rs @@ -212,8 +212,9 @@ impl storage::StorageDoubleMap for G where unhashed::kill(&Self::storage_double_map_final_key(k1, k2)) } - fn remove_prefix(k1: KArg1) where KArg1: EncodeLike { - unhashed::kill_prefix(Self::storage_double_map_final_key1(k1).as_ref()) + fn remove_prefix(k1: KArg1, limit: Option) -> sp_io::KillStorageResult + where KArg1: EncodeLike { + unhashed::kill_prefix(Self::storage_double_map_final_key1(k1).as_ref(), limit) } fn iter_prefix_values(k1: KArg1) -> storage::PrefixIterator where diff --git a/frame/support/src/storage/generator/nmap.rs b/frame/support/src/storage/generator/nmap.rs index d1f00adda5e55..62f188a26db8d 100755 --- a/frame/support/src/storage/generator/nmap.rs +++ b/frame/support/src/storage/generator/nmap.rs @@ -196,11 +196,11 @@ where unhashed::kill(&Self::storage_n_map_final_key::(key)); } - fn remove_prefix(partial_key: KP) + fn remove_prefix(partial_key: KP, limit: Option) -> sp_io::KillStorageResult where K: HasKeyPrefix, { - unhashed::kill_prefix(&Self::storage_n_map_partial_key(partial_key)); + unhashed::kill_prefix(&Self::storage_n_map_partial_key(partial_key), limit) } fn iter_prefix_values(partial_key: KP) -> PrefixIterator diff --git a/frame/support/src/storage/migration.rs b/frame/support/src/storage/migration.rs index b4a1a9225dd1f..62db2eff839fb 100644 --- a/frame/support/src/storage/migration.rs +++ b/frame/support/src/storage/migration.rs @@ -244,7 +244,7 @@ pub fn remove_storage_prefix(module: &[u8], item: &[u8], hash: &[u8]) { key[0..16].copy_from_slice(&Twox128::hash(module)); key[16..32].copy_from_slice(&Twox128::hash(item)); key[32..].copy_from_slice(hash); - frame_support::storage::unhashed::kill_prefix(&key) + frame_support::storage::unhashed::kill_prefix(&key, None); } /// Get a particular value in storage by the `module`, the map's `item` name and the key `hash`. diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index 34d217f5c31b6..6a02c6572c7f2 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -464,7 +464,8 @@ pub trait StorageDoubleMap { KArg2: EncodeLike; /// Remove all values under the first key. - fn remove_prefix(k1: KArg1) where KArg1: ?Sized + EncodeLike; + fn remove_prefix(k1: KArg1, limit: Option) -> sp_io::KillStorageResult + where KArg1: ?Sized + EncodeLike; /// Iterate over values that share the first key. fn iter_prefix_values(k1: KArg1) -> PrefixIterator @@ -589,7 +590,8 @@ pub trait StorageNMap { fn remove + TupleToEncodedIter>(key: KArg); /// Remove all values under the partial prefix key. - fn remove_prefix(partial_key: KP) where K: HasKeyPrefix; + fn remove_prefix(partial_key: KP, limit: Option) -> sp_io::KillStorageResult + where K: HasKeyPrefix; /// Iterate over values that share the partial prefix key. fn iter_prefix_values(partial_key: KP) -> PrefixIterator where K: HasKeyPrefix; @@ -880,8 +882,8 @@ pub trait StoragePrefixedMap { } /// Remove all value of the storage. - fn remove_all() { - sp_io::storage::clear_prefix(&Self::final_prefix()) + fn remove_all(limit: Option) -> sp_io::KillStorageResult { + sp_io::storage::clear_prefix(&Self::final_prefix(), limit) } /// Iter over all value of the storage. @@ -1184,7 +1186,7 @@ mod test { assert_eq!(MyStorage::iter_values().collect::>(), vec![1, 2, 3, 4]); // test removal - MyStorage::remove_all(); + MyStorage::remove_all(None); assert!(MyStorage::iter_values().collect::>().is_empty()); // test migration @@ -1194,7 +1196,7 @@ mod test { assert!(MyStorage::iter_values().collect::>().is_empty()); MyStorage::translate_values(|v: u32| Some(v as u64)); assert_eq!(MyStorage::iter_values().collect::>(), vec![1, 2]); - MyStorage::remove_all(); + MyStorage::remove_all(None); // test migration 2 unhashed::put(&[&k[..], &vec![1][..]].concat(), &1u128); @@ -1206,7 +1208,7 @@ mod test { assert_eq!(MyStorage::iter_values().collect::>(), vec![1, 2, 3]); MyStorage::translate_values(|v: u128| Some(v as u64)); assert_eq!(MyStorage::iter_values().collect::>(), vec![1, 2, 3]); - MyStorage::remove_all(); + MyStorage::remove_all(None); // test that other values are not modified. assert_eq!(unhashed::get(&key_before[..]), Some(32u64)); diff --git a/frame/support/src/storage/types/double_map.rs b/frame/support/src/storage/types/double_map.rs index f0ed1999d912e..6f03e9b8b2dd0 100644 --- a/frame/support/src/storage/types/double_map.rs +++ b/frame/support/src/storage/types/double_map.rs @@ -205,8 +205,9 @@ where } /// Remove all values under the first key. - pub fn remove_prefix(k1: KArg1) where KArg1: ?Sized + EncodeLike { - >::remove_prefix(k1) + pub fn remove_prefix(k1: KArg1, limit: Option) -> sp_io::KillStorageResult + where KArg1: ?Sized + EncodeLike { + >::remove_prefix(k1, limit) } /// Iterate over values that share the first key. @@ -316,8 +317,8 @@ where } /// Remove all value of the storage. - pub fn remove_all() { - >::remove_all() + pub fn remove_all(limit: Option) -> sp_io::KillStorageResult { + >::remove_all(limit) } /// Iter over all value of the storage. @@ -615,7 +616,7 @@ mod test { A::insert(3, 30, 10); A::insert(4, 40, 10); - A::remove_all(); + A::remove_all(None); assert_eq!(A::contains_key(3, 30), false); assert_eq!(A::contains_key(4, 40), false); @@ -655,7 +656,7 @@ mod test { assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 97u32.encode()); assert_eq!(A::DEFAULT.0.default_byte(), Option::::None.encode()); - WithLen::remove_all(); + WithLen::remove_all(None); assert_eq!(WithLen::decode_len(3, 30), None); WithLen::append(0, 100, 10); assert_eq!(WithLen::decode_len(0, 100), Some(1)); @@ -669,7 +670,7 @@ mod test { assert_eq!(A::iter_prefix_values(4).collect::>(), vec![13, 14]); assert_eq!(A::iter_prefix(4).collect::>(), vec![(40, 13), (41, 14)]); - A::remove_prefix(3); + A::remove_prefix(3, None); assert_eq!(A::iter_prefix(3).collect::>(), vec![]); assert_eq!(A::iter_prefix(4).collect::>(), vec![(40, 13), (41, 14)]); diff --git a/frame/support/src/storage/types/map.rs b/frame/support/src/storage/types/map.rs index 35062fbc61b25..db3a5e73c9cb1 100644 --- a/frame/support/src/storage/types/map.rs +++ b/frame/support/src/storage/types/map.rs @@ -231,8 +231,8 @@ where } /// Remove all value of the storage. - pub fn remove_all() { - >::remove_all() + pub fn remove_all(limit: Option) -> sp_io::KillStorageResult { + >::remove_all(limit) } /// Iter over all value of the storage. @@ -498,7 +498,7 @@ mod test { A::insert(3, 10); A::insert(4, 10); - A::remove_all(); + A::remove_all(None); assert_eq!(A::contains_key(3), false); assert_eq!(A::contains_key(4), false); @@ -533,7 +533,7 @@ mod test { assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 97u32.encode()); assert_eq!(A::DEFAULT.0.default_byte(), Option::::None.encode()); - WithLen::remove_all(); + WithLen::remove_all(None); assert_eq!(WithLen::decode_len(3), None); WithLen::append(0, 10); assert_eq!(WithLen::decode_len(0), Some(1)); diff --git a/frame/support/src/storage/types/nmap.rs b/frame/support/src/storage/types/nmap.rs index e1f5feb956ef3..a9fc121d42d2e 100755 --- a/frame/support/src/storage/types/nmap.rs +++ b/frame/support/src/storage/types/nmap.rs @@ -166,11 +166,11 @@ where } /// Remove all values under the first key. - pub fn remove_prefix(partial_key: KP) + pub fn remove_prefix(partial_key: KP, limit: Option) -> sp_io::KillStorageResult where Key: HasKeyPrefix, { - >::remove_prefix(partial_key) + >::remove_prefix(partial_key, limit) } /// Iterate over values that share the first key. @@ -266,8 +266,8 @@ where } /// Remove all value of the storage. - pub fn remove_all() { - >::remove_all() + pub fn remove_all(limit: Option) -> sp_io::KillStorageResult { + >::remove_all(limit) } /// Iter over all value of the storage. @@ -546,7 +546,7 @@ mod test { A::insert((3,), 10); A::insert((4,), 10); - A::remove_all(); + A::remove_all(None); assert_eq!(A::contains_key((3,)), false); assert_eq!(A::contains_key((4,)), false); @@ -582,7 +582,7 @@ mod test { ); assert_eq!(A::DEFAULT.0.default_byte(), Option::::None.encode()); - WithLen::remove_all(); + WithLen::remove_all(None); assert_eq!(WithLen::decode_len((3,)), None); WithLen::append((0,), 10); assert_eq!(WithLen::decode_len((0,)), Some(1)); @@ -720,7 +720,7 @@ mod test { A::insert((3, 30), 10); A::insert((4, 40), 10); - A::remove_all(); + A::remove_all(None); assert_eq!(A::contains_key((3, 30)), false); assert_eq!(A::contains_key((4, 40)), false); @@ -768,7 +768,7 @@ mod test { ); assert_eq!(A::DEFAULT.0.default_byte(), Option::::None.encode()); - WithLen::remove_all(); + WithLen::remove_all(None); assert_eq!(WithLen::decode_len((3, 30)), None); WithLen::append((0, 100), 10); assert_eq!(WithLen::decode_len((0, 100)), Some(1)); @@ -953,7 +953,7 @@ mod test { A::insert((3, 30, 300), 10); A::insert((4, 40, 400), 10); - A::remove_all(); + A::remove_all(None); assert_eq!(A::contains_key((3, 30, 300)), false); assert_eq!(A::contains_key((4, 40, 400)), false); @@ -1003,7 +1003,7 @@ mod test { ); assert_eq!(A::DEFAULT.0.default_byte(), Option::::None.encode()); - WithLen::remove_all(); + WithLen::remove_all(None); assert_eq!(WithLen::decode_len((3, 30, 300)), None); WithLen::append((0, 100, 1000), 10); assert_eq!(WithLen::decode_len((0, 100, 1000)), Some(1)); diff --git a/frame/support/src/storage/unhashed.rs b/frame/support/src/storage/unhashed.rs index d3d54f3de5795..134b3debcd31b 100644 --- a/frame/support/src/storage/unhashed.rs +++ b/frame/support/src/storage/unhashed.rs @@ -92,8 +92,8 @@ pub fn kill(key: &[u8]) { } /// Ensure keys with the given `prefix` have no entries in storage. -pub fn kill_prefix(prefix: &[u8]) { - sp_io::storage::clear_prefix(prefix); +pub fn kill_prefix(prefix: &[u8], limit: Option) -> sp_io::KillStorageResult { + sp_io::storage::clear_prefix(prefix, limit) } /// Get a Vec of bytes from storage. diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index e3a110f2e7e2c..17ea3a71bec8c 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -463,7 +463,7 @@ pub mod pallet { _subkeys: u32, ) -> DispatchResultWithPostInfo { ensure_root(origin)?; - storage::unhashed::kill_prefix(&prefix); + storage::unhashed::kill_prefix(&prefix, None); Ok(().into()) } @@ -1334,7 +1334,7 @@ impl Pallet { if let InitKind::Full = kind { >::kill(); EventCount::::kill(); - >::remove_all(); + >::remove_all(None); } } @@ -1447,7 +1447,7 @@ impl Pallet { pub fn reset_events() { >::kill(); EventCount::::kill(); - >::remove_all(); + >::remove_all(None); } /// Assert the given `event` exists. diff --git a/frame/uniques/src/lib.rs b/frame/uniques/src/lib.rs index 28518843c96fc..b98a038ecff36 100644 --- a/frame/uniques/src/lib.rs +++ b/frame/uniques/src/lib.rs @@ -417,9 +417,9 @@ pub mod pallet { for (instance, details) in Asset::::drain_prefix(&class) { Account::::remove((&details.owner, &class, &instance)); } - InstanceMetadataOf::::remove_prefix(&class); + InstanceMetadataOf::::remove_prefix(&class, None); ClassMetadataOf::::remove(&class); - Attribute::::remove_prefix((&class,)); + Attribute::::remove_prefix((&class,), None); T::Currency::unreserve(&class_details.owner, class_details.total_deposit); Self::deposit_event(Event::Destroyed(class)); diff --git a/primitives/externalities/src/lib.rs b/primitives/externalities/src/lib.rs index 14145e8798498..7a8771bd623ed 100644 --- a/primitives/externalities/src/lib.rs +++ b/primitives/externalities/src/lib.rs @@ -151,14 +151,19 @@ pub trait Externalities: ExtensionStore { fn kill_child_storage(&mut self, child_info: &ChildInfo, limit: Option) -> (bool, u32); /// Clear storage entries which keys are start with the given prefix. - fn clear_prefix(&mut self, prefix: &[u8]); + /// + /// `limit` and result works as for `kill_child_storage`. + fn clear_prefix(&mut self, prefix: &[u8], limit: Option) -> (bool, u32); /// Clear child storage entries which keys are start with the given prefix. + /// + /// `limit` and result works as for `kill_child_storage`. fn clear_child_prefix( &mut self, child_info: &ChildInfo, prefix: &[u8], - ); + limit: Option, + ) -> (bool, u32); /// Set or clear a storage entry (`key`) of current contract being called (effective immediately). fn place_storage(&mut self, key: Vec, value: Option>); diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index f0fcc4f1b0672..12cbf09e86507 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -86,7 +86,7 @@ pub enum EcdsaVerifyError { /// The outcome of calling `storage_kill`. Returned value is the number of storage items /// removed from the trie from making the `storage_kill` call. #[derive(PassByCodec, Encode, Decode)] -pub enum KillChildStorageResult { +pub enum KillStorageResult { /// No key remains in the child trie. AllRemoved(u32), /// At least one key still resides in the child trie due to the supplied limit. @@ -133,9 +133,44 @@ pub trait Storage { /// Clear the storage of each key-value pair where the key starts with the given `prefix`. fn clear_prefix(&mut self, prefix: &[u8]) { - Externalities::clear_prefix(*self, prefix) + let _ = Externalities::clear_prefix(*self, prefix, None); } + /// Clear the storage of each key-value pair where the key starts with the given `prefix`. + /// + /// # Limit + /// + /// Deletes all keys from the overlay and up to `limit` keys from the backend if + /// it is set to `Some`. No limit is applied when `limit` is set to `None`. + /// + /// The limit can be used to partially delete a prefix storage in case it is too large + /// to delete in one go (block). + /// + /// It returns a boolean false iff some keys are remaining in + /// the prefix after the functions returns. Also returns a `u32` with + /// the number of keys removed from the process. + /// + /// # Note + /// + /// Please note that keys that are residing in the overlay for that prefix when + /// issuing this call are all deleted without counting towards the `limit`. Only keys + /// written during the current block are part of the overlay. Deleting with a `limit` + /// mostly makes sense with an empty overlay for that prefix. + /// + /// Calling this function multiple times per block for the same `prefix` does + /// not make much sense because it is not cumulative when called inside the same block. + /// Use this function to distribute the deletion of a single child trie across multiple + /// blocks. + #[version(2)] + fn clear_prefix(&mut self, prefix: &[u8], limit: Option) -> KillStorageResult { + let (all_removed, num_removed) = Externalities::clear_prefix(*self, prefix, limit); + match all_removed { + true => KillStorageResult::AllRemoved(num_removed), + false => KillStorageResult::SomeRemaining(num_removed), + } + } + + /// Append the encoded `value` to the storage item at `key`. /// /// The storage item needs to implement [`EncodeAppend`](codec::EncodeAppend). @@ -296,26 +331,7 @@ pub trait DefaultChildStorage { /// Clear a child storage key. /// - /// Deletes all keys from the overlay and up to `limit` keys from the backend if - /// it is set to `Some`. No limit is applied when `limit` is set to `None`. - /// - /// The limit can be used to partially delete a child trie in case it is too large - /// to delete in one go (block). - /// - /// It returns a boolean false iff some keys are remaining in - /// the child trie after the functions returns. - /// - /// # Note - /// - /// Please note that keys that are residing in the overlay for that child trie when - /// issuing this call are all deleted without counting towards the `limit`. Only keys - /// written during the current block are part of the overlay. Deleting with a `limit` - /// mostly makes sense with an empty overlay for that child trie. - /// - /// Calling this function multiple times per block for the same `storage_key` does - /// not make much sense because it is not cumulative when called inside the same block. - /// Use this function to distribute the deletion of a single child trie across multiple - /// blocks. + /// See `Storage` module `clear_prefix` documentation for `limit` usage. #[version(2)] fn storage_kill(&mut self, storage_key: &[u8], limit: Option) -> bool { let child_info = ChildInfo::new_default(storage_key); @@ -325,34 +341,14 @@ pub trait DefaultChildStorage { /// Clear a child storage key. /// - /// Deletes all keys from the overlay and up to `limit` keys from the backend if - /// it is set to `Some`. No limit is applied when `limit` is set to `None`. - /// - /// The limit can be used to partially delete a child trie in case it is too large - /// to delete in one go (block). - /// - /// It returns a boolean false iff some keys are remaining in - /// the child trie after the functions returns. Also returns a `u32` with - /// the number of keys removed from the process. - /// - /// # Note - /// - /// Please note that keys that are residing in the overlay for that child trie when - /// issuing this call are all deleted without counting towards the `limit`. Only keys - /// written during the current block are part of the overlay. Deleting with a `limit` - /// mostly makes sense with an empty overlay for that child trie. - /// - /// Calling this function multiple times per block for the same `storage_key` does - /// not make much sense because it is not cumulative when called inside the same block. - /// Use this function to distribute the deletion of a single child trie across multiple - /// blocks. + /// See `Storage` module `clear_prefix` documentation for `limit` usage. #[version(3)] - fn storage_kill(&mut self, storage_key: &[u8], limit: Option) -> KillChildStorageResult { + fn storage_kill(&mut self, storage_key: &[u8], limit: Option) -> KillStorageResult { let child_info = ChildInfo::new_default(storage_key); let (all_removed, num_removed) = self.kill_child_storage(&child_info, limit); match all_removed { - true => KillChildStorageResult::AllRemoved(num_removed), - false => KillChildStorageResult::SomeRemaining(num_removed), + true => KillStorageResult::AllRemoved(num_removed), + false => KillStorageResult::SomeRemaining(num_removed), } } @@ -377,7 +373,25 @@ pub trait DefaultChildStorage { prefix: &[u8], ) { let child_info = ChildInfo::new_default(storage_key); - self.clear_child_prefix(&child_info, prefix); + let _ = self.clear_child_prefix(&child_info, prefix, None); + } + + /// Clear the child storage of each key-value pair where the key starts with the given `prefix`. + /// + /// See `Storage` module `clear_prefix` documentation for `limit` usage. + #[version(2)] + fn clear_prefix( + &mut self, + storage_key: &[u8], + prefix: &[u8], + limit: Option, + ) -> KillStorageResult { + let child_info = ChildInfo::new_default(storage_key); + let (all_removed, num_removed) = self.clear_child_prefix(&child_info, prefix, limit); + match all_removed { + true => KillStorageResult::AllRemoved(num_removed), + false => KillStorageResult::SomeRemaining(num_removed), + } } /// Default child root calculation. @@ -1531,7 +1545,7 @@ mod tests { }); t.execute_with(|| { - storage::clear_prefix(b":abc"); + assert!(matches!(storage::clear_prefix(b":abc", None), KillStorageResult::AllRemoved(2))); assert!(storage::get(b":a").is_some()); assert!(storage::get(b":abdd").is_some()); diff --git a/primitives/state-machine/src/backend.rs b/primitives/state-machine/src/backend.rs index 92b4c83314e72..18b89acbc6f13 100644 --- a/primitives/state-machine/src/backend.rs +++ b/primitives/state-machine/src/backend.rs @@ -93,11 +93,12 @@ pub trait Backend: sp_std::fmt::Debug { key: &[u8] ) -> Result, Self::Error>; - /// Retrieve all entries keys of child storage and call `f` for each of those keys. + /// Retrieve all entries keys of storage and call `f` for each of those keys. /// Aborts as soon as `f` returns false. - fn apply_to_child_keys_while bool>( + fn apply_to_keys_while bool>( &self, - child_info: &ChildInfo, + child_info: Option<&ChildInfo>, + prefix: Option<&[u8]>, f: F, ); diff --git a/primitives/state-machine/src/basic.rs b/primitives/state-machine/src/basic.rs index dda8f523b77f9..08849ebcc69ab 100644 --- a/primitives/state-machine/src/basic.rs +++ b/primitives/state-machine/src/basic.rs @@ -216,13 +216,13 @@ impl Externalities for BasicExternalities { (true, num_removed as u32) } - fn clear_prefix(&mut self, prefix: &[u8]) { + fn clear_prefix(&mut self, prefix: &[u8], _limit: Option) -> (bool, u32) { if is_child_storage_key(prefix) { warn!( target: "trie", "Refuse to clear prefix that is part of child storage key via main storage" ); - return; + return (false, 0); } let to_remove = self.inner.top.range::<[u8], _>((Bound::Included(prefix), Bound::Unbounded)) @@ -231,16 +231,19 @@ impl Externalities for BasicExternalities { .cloned() .collect::>(); + let num_removed = to_remove.len(); for key in to_remove { self.inner.top.remove(&key); } + (true, num_removed as u32) } fn clear_child_prefix( &mut self, child_info: &ChildInfo, prefix: &[u8], - ) { + _limit: Option, + ) -> (bool, u32) { if let Some(child) = self.inner.children_default.get_mut(child_info.storage_key()) { let to_remove = child.data.range::<[u8], _>((Bound::Included(prefix), Bound::Unbounded)) .map(|(k, _)| k) @@ -248,9 +251,13 @@ impl Externalities for BasicExternalities { .cloned() .collect::>(); + let num_removed = to_remove.len(); for key in to_remove { child.data.remove(&key); } + (true, num_removed as u32) + } else { + (true, 0) } } diff --git a/primitives/state-machine/src/ext.rs b/primitives/state-machine/src/ext.rs index 8bcf1f28a0778..e66664647d9d8 100644 --- a/primitives/state-machine/src/ext.rs +++ b/primitives/state-machine/src/ext.rs @@ -460,36 +460,10 @@ where let _guard = guard(); self.mark_dirty(); self.overlay.clear_child_storage(child_info); - let mut num_deleted: u32 = 0; - - if let Some(limit) = limit { - let mut all_deleted = true; - self.backend.apply_to_child_keys_while(child_info, |key| { - if num_deleted == limit { - all_deleted = false; - return false; - } - if let Some(num) = num_deleted.checked_add(1) { - num_deleted = num; - } else { - all_deleted = false; - return false; - } - self.overlay.set_child_storage(child_info, key.to_vec(), None); - true - }); - (all_deleted, num_deleted) - } else { - self.backend.apply_to_child_keys_while(child_info, |key| { - num_deleted = num_deleted.saturating_add(1); - self.overlay.set_child_storage(child_info, key.to_vec(), None); - true - }); - (true, num_deleted) - } + self.limit_remove_from_backend(Some(child_info), None, limit) } - fn clear_prefix(&mut self, prefix: &[u8]) { + fn clear_prefix(&mut self, prefix: &[u8], limit: Option) -> (bool, u32) { trace!(target: "state", "{:04x}: ClearPrefix {}", self.id, HexDisplay::from(&prefix), @@ -498,21 +472,20 @@ where if sp_core::storage::well_known_keys::starts_with_child_storage_key(prefix) { warn!(target: "trie", "Refuse to directly clear prefix that is part or contains of child storage key"); - return; + return (false, 0); } self.mark_dirty(); self.overlay.clear_prefix(prefix); - self.backend.for_keys_with_prefix(prefix, |key| { - self.overlay.set_storage(key.to_vec(), None); - }); + self.limit_remove_from_backend(None, Some(prefix), limit) } fn clear_child_prefix( &mut self, child_info: &ChildInfo, prefix: &[u8], - ) { + limit: Option, + ) -> (bool, u32) { trace!(target: "state", "{:04x}: ClearChildPrefix({}) {}", self.id, HexDisplay::from(&child_info.storage_key()), @@ -522,9 +495,7 @@ where self.mark_dirty(); self.overlay.clear_child_prefix(child_info, prefix); - self.backend.for_child_keys_with_prefix(child_info, prefix, |key| { - self.overlay.set_child_storage(child_info, key.to_vec(), None); - }); + self.limit_remove_from_backend(Some(child_info), Some(prefix), limit) } fn storage_append( @@ -780,6 +751,57 @@ where } } +impl<'a, H, N, B> Ext<'a, H, N, B> +where + H: Hasher, + H::Out: Ord + 'static + codec::Codec, + B: Backend, + N: crate::changes_trie::BlockNumber, +{ + fn limit_remove_from_backend( + &mut self, + child_info: Option<&ChildInfo>, + prefix: Option<&[u8]>, + limit: Option, + ) -> (bool, u32) { + let mut num_deleted: u32 = 0; + + if let Some(limit) = limit { + let mut all_deleted = true; + self.backend.apply_to_keys_while(child_info, prefix, |key| { + if num_deleted == limit { + all_deleted = false; + return false; + } + if let Some(num) = num_deleted.checked_add(1) { + num_deleted = num; + } else { + all_deleted = false; + return false; + } + if let Some(child_info) = child_info { + self.overlay.set_child_storage(child_info, key.to_vec(), None); + } else { + self.overlay.set_storage(key.to_vec(), None); + } + true + }); + (all_deleted, num_deleted) + } else { + self.backend.apply_to_keys_while(child_info, prefix, |key| { + num_deleted = num_deleted.saturating_add(1); + if let Some(child_info) = child_info { + self.overlay.set_child_storage(child_info, key.to_vec(), None); + } else { + self.overlay.set_storage(key.to_vec(), None); + } + true + }); + (true, num_deleted) + } + } +} + /// Implement `Encode` by forwarding the stored raw vec. struct EncodeOpaqueValue(Vec); @@ -1155,14 +1177,14 @@ mod tests { not_under_prefix.extend(b"path"); ext.set_storage(not_under_prefix.clone(), vec![10]); - ext.clear_prefix(&[]); - ext.clear_prefix(&well_known_keys::CHILD_STORAGE_KEY_PREFIX[..4]); + ext.clear_prefix(&[], None); + ext.clear_prefix(&well_known_keys::CHILD_STORAGE_KEY_PREFIX[..4], None); let mut under_prefix = well_known_keys::CHILD_STORAGE_KEY_PREFIX.to_vec(); under_prefix.extend(b"path"); - ext.clear_prefix(&well_known_keys::CHILD_STORAGE_KEY_PREFIX[..4]); + ext.clear_prefix(&well_known_keys::CHILD_STORAGE_KEY_PREFIX[..4], None); assert_eq!(ext.child_storage(child_info, &[30]), Some(vec![40])); assert_eq!(ext.storage(not_under_prefix.as_slice()), Some(vec![10])); - ext.clear_prefix(¬_under_prefix[..5]); + ext.clear_prefix(¬_under_prefix[..5], None); assert_eq!(ext.storage(not_under_prefix.as_slice()), None); } diff --git a/primitives/state-machine/src/lib.rs b/primitives/state-machine/src/lib.rs index 0508bfb780929..c4ba39e160160 100644 --- a/primitives/state-machine/src/lib.rs +++ b/primitives/state-machine/src/lib.rs @@ -1102,6 +1102,7 @@ mod tests { overlay.set_storage(b"abd".to_vec(), Some(b"69".to_vec())); overlay.set_storage(b"bbd".to_vec(), Some(b"42".to_vec())); + let overlay_limit = overlay.clone(); { let mut cache = StorageTransactionCache::default(); let mut ext = Ext::new( @@ -1111,7 +1112,7 @@ mod tests { changes_trie::disabled_state::<_, u64>(), None, ); - ext.clear_prefix(b"ab"); + ext.clear_prefix(b"ab", None); } overlay.commit_transaction().unwrap(); @@ -1128,6 +1129,33 @@ mod tests { b"bbd".to_vec() => Some(b"42".to_vec()).into() ], ); + + let mut overlay = overlay_limit; + { + let mut cache = StorageTransactionCache::default(); + let mut ext = Ext::new( + &mut overlay, + &mut cache, + backend, + changes_trie::disabled_state::<_, u64>(), + None, + ); + assert_eq!((false, 1), ext.clear_prefix(b"ab", Some(1))); + } + overlay.commit_transaction().unwrap(); + + assert_eq!( + overlay.changes().map(|(k, v)| (k.clone(), v.value().cloned())) + .collect::>(), + map![ + b"abb".to_vec() => None.into(), + b"aba".to_vec() => None.into(), + b"abd".to_vec() => None.into(), + + b"bab".to_vec() => Some(b"228".to_vec()).into(), + b"bbd".to_vec() => Some(b"42".to_vec()).into() + ], + ); } #[test] diff --git a/primitives/state-machine/src/proving_backend.rs b/primitives/state-machine/src/proving_backend.rs index 963582a3cc35d..d68a87f9f56a5 100644 --- a/primitives/state-machine/src/proving_backend.rs +++ b/primitives/state-machine/src/proving_backend.rs @@ -260,12 +260,13 @@ impl<'a, S, H> Backend for ProvingBackend<'a, S, H> self.0.child_storage(child_info, key) } - fn apply_to_child_keys_while bool>( + fn apply_to_keys_while bool>( &self, - child_info: &ChildInfo, + child_info: Option<&ChildInfo>, + prefix: Option<&[u8]>, f: F, ) { - self.0.apply_to_child_keys_while(child_info, f) + self.0.apply_to_keys_while(child_info, prefix, f) } fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { diff --git a/primitives/state-machine/src/read_only.rs b/primitives/state-machine/src/read_only.rs index 296520900c952..7b67b61eea822 100644 --- a/primitives/state-machine/src/read_only.rs +++ b/primitives/state-machine/src/read_only.rs @@ -136,7 +136,7 @@ impl<'a, H: Hasher, B: 'a + Backend> Externalities for ReadOnlyExternalities< unimplemented!("kill_child_storage is not supported in ReadOnlyExternalities") } - fn clear_prefix(&mut self, _prefix: &[u8]) { + fn clear_prefix(&mut self, _prefix: &[u8], _limit: Option) -> (bool, u32) { unimplemented!("clear_prefix is not supported in ReadOnlyExternalities") } @@ -144,7 +144,8 @@ impl<'a, H: Hasher, B: 'a + Backend> Externalities for ReadOnlyExternalities< &mut self, _child_info: &ChildInfo, _prefix: &[u8], - ) { + _limit: Option, + ) -> (bool, u32) { unimplemented!("clear_child_prefix is not supported in ReadOnlyExternalities") } diff --git a/primitives/state-machine/src/trie_backend.rs b/primitives/state-machine/src/trie_backend.rs index 5dd8fb7562f72..98deca23a9570 100644 --- a/primitives/state-machine/src/trie_backend.rs +++ b/primitives/state-machine/src/trie_backend.rs @@ -113,12 +113,13 @@ impl, H: Hasher> Backend for TrieBackend where self.essence.for_key_values_with_prefix(prefix, f) } - fn apply_to_child_keys_while bool>( + fn apply_to_keys_while bool>( &self, - child_info: &ChildInfo, + child_info: Option<&ChildInfo>, + prefix: Option<&[u8]>, f: F, ) { - self.essence.apply_to_child_keys_while(child_info, f) + self.essence.apply_to_keys_while(child_info, prefix, f) } fn for_child_keys_with_prefix( diff --git a/primitives/state-machine/src/trie_backend_essence.rs b/primitives/state-machine/src/trie_backend_essence.rs index c085099da77d8..e0a24c08393c7 100644 --- a/primitives/state-machine/src/trie_backend_essence.rs +++ b/primitives/state-machine/src/trie_backend_essence.rs @@ -25,7 +25,7 @@ use crate::{warn, debug}; use hash_db::{self, Hasher, Prefix}; use sp_trie::{Trie, MemoryDB, PrefixedMemoryDB, DBValue, empty_child_trie_root, read_trie_value, read_child_trie_value, - for_keys_in_child_trie, KeySpacedDB, TrieDBIterator}; + KeySpacedDB, TrieDBIterator}; use sp_trie::trie_types::{TrieDB, TrieError, Layout}; use crate::{backend::Consolidate, StorageKey, StorageValue}; use sp_core::storage::ChildInfo; @@ -189,29 +189,30 @@ impl, H: Hasher> TrieBackendEssence where H::Out: .map_err(map_e) } - /// Retrieve all entries keys of child storage and call `f` for each of those keys. + /// Retrieve all entries keys of a storage and call `f` for each of those keys. /// Aborts as soon as `f` returns false. - pub fn apply_to_child_keys_while bool>( + pub fn apply_to_keys_while bool>( &self, - child_info: &ChildInfo, - f: F, + child_info: Option<&ChildInfo>, + prefix: Option<&[u8]>, + mut f: F, ) { - let root = match self.child_root(child_info) { - Ok(v) => v.unwrap_or_else(|| empty_child_trie_root::>().encode()), - Err(e) => { - debug!(target: "trie", "Error while iterating child storage: {}", e); - return; - } + let mut child_root = H::Out::default(); + let root = if let Some(child_info) = child_info.as_ref() { + let root_vec = match self.child_root(child_info) { + Ok(v) => v.unwrap_or_else(|| empty_child_trie_root::>().encode()), + Err(e) => { + debug!(target: "trie", "Error while iterating child storage: {}", e); + return; + } + }; + child_root.as_mut().copy_from_slice(&root_vec); + &child_root + } else { + &self.root }; - if let Err(e) = for_keys_in_child_trie::, _, _>( - child_info.keyspace(), - self, - &root, - f, - ) { - debug!(target: "trie", "Error while iterating child storage: {}", e); - } + self.trie_iter_inner(root, prefix, |k, _v| f(k), child_info) } /// Execute given closure for all keys starting with prefix. @@ -230,30 +231,38 @@ impl, H: Hasher> TrieBackendEssence where H::Out: }; let mut root = H::Out::default(); root.as_mut().copy_from_slice(&root_vec); - self.keys_values_with_prefix_inner(&root, prefix, |k, _v| f(k), Some(child_info)) + self.trie_iter_inner(&root, Some(prefix), |k, _v| { f(k); true }, Some(child_info)) } /// Execute given closure for all keys starting with prefix. pub fn for_keys_with_prefix(&self, prefix: &[u8], mut f: F) { - self.keys_values_with_prefix_inner(&self.root, prefix, |k, _v| f(k), None) + self.trie_iter_inner(&self.root, Some(prefix), |k, _v| { f(k); true }, None) } - fn keys_values_with_prefix_inner( + fn trie_iter_inner bool>( &self, root: &H::Out, - prefix: &[u8], + prefix: Option<&[u8]>, mut f: F, child_info: Option<&ChildInfo>, ) { let mut iter = move |db| -> sp_std::result::Result<(), Box>> { let trie = TrieDB::::new(db, root)?; - for x in TrieDBIterator::new_prefixed(&trie, prefix)? { + let iter = if let Some(prefix) = prefix.as_ref() { + TrieDBIterator::new_prefixed(&trie, prefix)? + } else { + TrieDBIterator::new(&trie)? + }; + + for x in iter { let (key, value) = x?; - debug_assert!(key.starts_with(prefix)); + debug_assert!(prefix.as_ref().map(|prefix| key.starts_with(prefix)).unwrap_or(true)); - f(&key, &value); + if !f(&key, &value) { + break; + } } Ok(()) @@ -271,8 +280,8 @@ impl, H: Hasher> TrieBackendEssence where H::Out: } /// Execute given closure for all key and values starting with prefix. - pub fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { - self.keys_values_with_prefix_inner(&self.root, prefix, f, None) + pub fn for_key_values_with_prefix(&self, prefix: &[u8], mut f: F) { + self.trie_iter_inner(&self.root, Some(prefix), |k, v| { f(k, v); true }, None) } } diff --git a/primitives/tasks/src/async_externalities.rs b/primitives/tasks/src/async_externalities.rs index 5d99ca4368d0b..b646149912643 100644 --- a/primitives/tasks/src/async_externalities.rs +++ b/primitives/tasks/src/async_externalities.rs @@ -123,7 +123,7 @@ impl Externalities for AsyncExternalities { panic!("`kill_child_storage`: should not be used in async externalities!") } - fn clear_prefix(&mut self, _prefix: &[u8]) { + fn clear_prefix(&mut self, _prefix: &[u8], _limit: Option) -> (bool, u32) { panic!("`clear_prefix`: should not be used in async externalities!") } @@ -131,7 +131,8 @@ impl Externalities for AsyncExternalities { &mut self, _child_info: &ChildInfo, _prefix: &[u8], - ) { + _limit: Option, + ) -> (bool, u32) { panic!("`clear_child_prefix`: should not be used in async externalities!") } diff --git a/primitives/trie/src/lib.rs b/primitives/trie/src/lib.rs index 89bef715ba99a..f815d2af44ad7 100644 --- a/primitives/trie/src/lib.rs +++ b/primitives/trie/src/lib.rs @@ -279,35 +279,6 @@ pub fn child_delta_trie_root( ) } -/// Call `f` for all keys in a child trie. -/// Aborts as soon as `f` returns false. -pub fn for_keys_in_child_trie bool, DB>( - keyspace: &[u8], - db: &DB, - root_slice: &[u8], - mut f: F -) -> Result<(), Box>> - where - DB: hash_db::HashDBRef -{ - let mut root = TrieHash::::default(); - // root is fetched from DB, not writable by runtime, so it's always valid. - root.as_mut().copy_from_slice(root_slice); - - let db = KeySpacedDB::new(&*db, keyspace); - let trie = TrieDB::::new(&db, &root)?; - let iter = trie.iter()?; - - for x in iter { - let (key, _) = x?; - if !f(&key) { - break; - } - } - - Ok(()) -} - /// Record all keys for a given root. pub fn record_all_keys( db: &DB,