// This file is part of Substrate. // Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! Stuff to do with the runtime's storage. use sp_core::storage::ChildInfo; use sp_std::prelude::*; use codec::{FullCodec, FullEncode, Encode, EncodeLike, Decode}; use crate::{ hash::{Twox128, StorageHasher, ReversibleStorageHasher}, storage::types::{ EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, KeyGenerator, ReversibleKeyGenerator, TupleToEncodedIter, }, }; use sp_runtime::generic::{Digest, DigestItem}; pub use sp_runtime::TransactionOutcome; pub use types::Key; pub mod unhashed; pub mod hashed; pub mod bounded_btree_map; pub mod bounded_btree_set; pub mod bounded_vec; pub mod weak_bounded_vec; pub mod child; #[doc(hidden)] pub mod generator; pub mod migration; pub mod types; #[cfg(all(feature = "std", any(test, debug_assertions)))] mod debug_helper { use std::cell::RefCell; thread_local! { static TRANSACTION_LEVEL: RefCell = RefCell::new(0); } pub fn require_transaction() { let level = TRANSACTION_LEVEL.with(|v| *v.borrow()); if level == 0 { panic!("Require transaction not called within with_transaction"); } } pub struct TransactionLevelGuard; impl Drop for TransactionLevelGuard { fn drop(&mut self) { TRANSACTION_LEVEL.with(|v| *v.borrow_mut() -= 1); } } /// Increments the transaction level. /// /// Returns a guard that when dropped decrements the transaction level automatically. pub fn inc_transaction_level() -> TransactionLevelGuard { TRANSACTION_LEVEL.with(|v| { let mut val = v.borrow_mut(); *val += 1; if *val > 10 { log::warn!( "Detected with_transaction with nest level {}. Nested usage of with_transaction is not recommended.", *val ); } }); TransactionLevelGuard } } /// Assert this method is called within a storage transaction. /// This will **panic** if is not called within a storage transaction. /// /// This assertion is enabled for native execution and when `debug_assertions` are enabled. pub fn require_transaction() { #[cfg(all(feature = "std", any(test, debug_assertions)))] debug_helper::require_transaction(); } /// Execute the supplied function in a new storage transaction. /// /// All changes to storage performed by the supplied function are discarded if the returned /// outcome is `TransactionOutcome::Rollback`. /// /// Transactions can be nested to any depth. Commits happen to the parent transaction. pub fn with_transaction(f: impl FnOnce() -> TransactionOutcome) -> R { use sp_io::storage::{ start_transaction, commit_transaction, rollback_transaction, }; use TransactionOutcome::*; start_transaction(); #[cfg(all(feature = "std", any(test, debug_assertions)))] let _guard = debug_helper::inc_transaction_level(); match f() { Commit(res) => { commit_transaction(); res }, Rollback(res) => { rollback_transaction(); res }, } } /// A trait for working with macro-generated storage values under the substrate storage API. /// /// Details on implementation can be found at [`generator::StorageValue`]. pub trait StorageValue { /// The type that get/take return. type Query; /// Get the storage key. fn hashed_key() -> [u8; 32]; /// Does the value (explicitly) exist in storage? fn exists() -> bool; /// Load the value from the provided storage instance. fn get() -> Self::Query; /// Try to get the underlying value from the provided storage instance. /// /// Returns `Ok` if it exists, `Err` if not. fn try_get() -> Result; /// Translate a value from some previous type (`O`) to the current type. /// /// `f: F` is the translation function. /// /// Returns `Err` if the storage item could not be interpreted as the old type, and Ok, along /// with the new value if it could. /// /// NOTE: This operates from and to `Option<_>` types; no effort is made to respect the default /// value of the original type. /// /// # Warning /// /// This function must be used with care, before being updated the storage still contains the /// old type, thus other calls (such as `get`) will fail at decoding it. /// /// # Usage /// /// This would typically be called inside the module implementation of on_runtime_upgrade, while /// ensuring **no usage of this storage are made before the call to `on_runtime_upgrade`**. (More /// precisely prior initialized modules doesn't make use of this storage). fn translate) -> Option>(f: F) -> Result, ()>; /// Store a value under this key into the provided storage instance. fn put>(val: Arg); /// Store a value under this key into the provided storage instance; this uses the query /// type rather than the underlying value. fn set(val: Self::Query); /// Mutate the value fn mutate R>(f: F) -> R; /// Mutate the value if closure returns `Ok` fn try_mutate Result>(f: F) -> Result; /// Clear the storage value. fn kill(); /// Take a value from storage, removing it afterwards. fn take() -> Self::Query; /// Append the given item to the value in the storage. /// /// `T` is required to implement [`StorageAppend`]. /// /// # Warning /// /// If the storage item is not encoded properly, the storage item will be overwritten /// and set to `[item]`. Any default value set for the storage item will be ignored /// on overwrite. fn append(item: EncodeLikeItem) where Item: Encode, EncodeLikeItem: EncodeLike, T: StorageAppend; /// Read the length of the storage value without decoding the entire value. /// /// `T` is required to implement [`StorageDecodeLength`]. /// /// If the value does not exists or it fails to decode the length, `None` is returned. /// Otherwise `Some(len)` is returned. /// /// # Warning /// /// `None` does not mean that `get()` does not return a value. The default value is completly /// ignored by this function. fn decode_len() -> Option where T: StorageDecodeLength { T::decode_len(&Self::hashed_key()) } } /// A strongly-typed map in storage. /// /// Details on implementation can be found at [`generator::StorageMap`]. pub trait StorageMap { /// The type that get/take return. type Query; /// Get the storage key used to fetch a value corresponding to a specific key. fn hashed_key_for>(key: KeyArg) -> Vec; /// Does the value (explicitly) exist in storage? fn contains_key>(key: KeyArg) -> bool; /// Load the value associated with the given key from the map. fn get>(key: KeyArg) -> Self::Query; /// Try to get the value for the given key from the map. /// /// Returns `Ok` if it exists, `Err` if not. fn try_get>(key: KeyArg) -> Result; /// Swap the values of two keys. fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2); /// Store a value to be associated with the given key from the map. fn insert, ValArg: EncodeLike>(key: KeyArg, val: ValArg); /// Remove the value under a key. fn remove>(key: KeyArg); /// Mutate the value under a key. fn mutate, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R; /// Mutate the item, only if an `Ok` value is returned. fn try_mutate, R, E, F: FnOnce(&mut Self::Query) -> Result>( key: KeyArg, f: F, ) -> Result; /// Mutate the value under a key. /// /// Deletes the item if mutated to a `None`. fn mutate_exists, R, F: FnOnce(&mut Option) -> R>(key: KeyArg, f: F) -> R; /// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`. fn try_mutate_exists, R, E, F: FnOnce(&mut Option) -> Result>( key: KeyArg, f: F, ) -> Result; /// Take the value under a key. fn take>(key: KeyArg) -> Self::Query; /// Append the given items to the value in the storage. /// /// `V` is required to implement `codec::EncodeAppend`. /// /// # Warning /// /// If the storage item is not encoded properly, the storage will be overwritten /// and set to `[item]`. Any default value set for the storage item will be ignored /// on overwrite. fn append(key: EncodeLikeKey, item: EncodeLikeItem) where EncodeLikeKey: EncodeLike, Item: Encode, EncodeLikeItem: EncodeLike, V: StorageAppend; /// Read the length of the storage value without decoding the entire value under the /// given `key`. /// /// `V` is required to implement [`StorageDecodeLength`]. /// /// If the value does not exists or it fails to decode the length, `None` is returned. /// Otherwise `Some(len)` is returned. /// /// # Warning /// /// `None` does not mean that `get()` does not return a value. The default value is completly /// ignored by this function. fn decode_len>(key: KeyArg) -> Option where V: StorageDecodeLength, { V::decode_len(&Self::hashed_key_for(key)) } /// Migrate an item with the given `key` from a defunct `OldHasher` to the current hasher. /// /// If the key doesn't exist, then it's a no-op. If it does, then it returns its value. fn migrate_key>(key: KeyArg) -> Option; /// Migrate an item with the given `key` from a `blake2_256` hasher to the current hasher. /// /// If the key doesn't exist, then it's a no-op. If it does, then it returns its value. fn migrate_key_from_blake>(key: KeyArg) -> Option { Self::migrate_key::(key) } } /// A strongly-typed map in storage whose keys and values can be iterated over. pub trait IterableStorageMap: StorageMap { /// The type that iterates over all `(key, value)`. type Iterator: Iterator; /// Enumerate all elements in the map in no particular order. If you alter the map while doing /// this, you'll get undefined results. fn iter() -> Self::Iterator; /// Remove all elements from the map and iterate through them in no particular order. If you /// add elements to the map while doing this, you'll get undefined results. fn drain() -> Self::Iterator; /// Translate the values of all elements by a function `f`, in the map in no particular order. /// By returning `None` from `f` for an element, you'll remove it from the map. /// /// NOTE: If a value fail to decode because storage is corrupted then it is skipped. fn translate Option>(f: F); } /// A strongly-typed double map in storage whose secondary keys and values can be iterated over. pub trait IterableStorageDoubleMap< K1: FullCodec, K2: FullCodec, V: FullCodec >: StorageDoubleMap { /// The type that iterates over all `(key2, value)`. type PrefixIterator: Iterator; /// The type that iterates over all `(key1, key2, value)`. type Iterator: Iterator; /// Enumerate all elements in the map with first key `k1` in no particular order. If you add or /// remove values whose first key is `k1` to the map while doing this, you'll get undefined /// results. fn iter_prefix(k1: impl EncodeLike) -> Self::PrefixIterator; /// Remove all elements from the map with first key `k1` and iterate through them in no /// particular order. If you add elements with first key `k1` to the map while doing this, /// you'll get undefined results. fn drain_prefix(k1: impl EncodeLike) -> Self::PrefixIterator; /// Enumerate all elements in the map in no particular order. If you add or remove values to /// the map while doing this, you'll get undefined results. fn iter() -> Self::Iterator; /// Remove all elements from the map and iterate through them in no particular order. If you /// add elements to the map while doing this, you'll get undefined results. fn drain() -> Self::Iterator; /// Translate the values of all elements by a function `f`, in the map in no particular order. /// By returning `None` from `f` for an element, you'll remove it from the map. /// /// NOTE: If a value fail to decode because storage is corrupted then it is skipped. fn translate Option>(f: F); } /// A strongly-typed map with arbitrary number of keys in storage whose keys and values can be /// iterated over. pub trait IterableStorageNMap: StorageNMap { /// The type that iterates over all `(key1, (key2, (key3, ... (keyN, ()))), value)` tuples type Iterator: Iterator; /// Enumerate all elements in the map with prefix key `kp` in no particular order. If you add or /// remove values whose prefix is `kp` to the map while doing this, you'll get undefined /// results. fn iter_prefix(kp: KP) -> PrefixIterator<(>::Suffix, V)> where K: HasReversibleKeyPrefix; /// Remove all elements from the map with prefix key `kp` and iterate through them in no /// particular order. If you add elements with prefix key `kp` to the map while doing this, /// you'll get undefined results. fn drain_prefix(kp: KP) -> PrefixIterator<(>::Suffix, V)> where K: HasReversibleKeyPrefix; /// Enumerate all elements in the map in no particular order. If you add or remove values to /// the map while doing this, you'll get undefined results. fn iter() -> Self::Iterator; /// Remove all elements from the map and iterate through them in no particular order. If you /// add elements to the map while doing this, you'll get undefined results. fn drain() -> Self::Iterator; /// Translate the values of all elements by a function `f`, in the map in no particular order. /// By returning `None` from `f` for an element, you'll remove it from the map. /// /// NOTE: If a value fail to decode because storage is corrupted then it is skipped. fn translate Option>(f: F); } /// An implementation of a map with a two keys. /// /// It provides an important ability to efficiently remove all entries /// that have a common first key. /// /// Details on implementation can be found at [`generator::StorageDoubleMap`]. pub trait StorageDoubleMap { /// The type that get/take returns. type Query; /// Get the storage key used to fetch a value corresponding to a specific key. fn hashed_key_for(k1: KArg1, k2: KArg2) -> Vec where KArg1: EncodeLike, KArg2: EncodeLike; /// Does the value (explicitly) exist in storage? fn contains_key(k1: KArg1, k2: KArg2) -> bool where KArg1: EncodeLike, KArg2: EncodeLike; /// Load the value associated with the given key from the double map. fn get(k1: KArg1, k2: KArg2) -> Self::Query where KArg1: EncodeLike, KArg2: EncodeLike; /// Try to get the value for the given key from the double map. /// /// Returns `Ok` if it exists, `Err` if not. fn try_get(k1: KArg1, k2: KArg2) -> Result where KArg1: EncodeLike, KArg2: EncodeLike; /// Take a value from storage, removing it afterwards. fn take(k1: KArg1, k2: KArg2) -> Self::Query where KArg1: EncodeLike, KArg2: EncodeLike; /// Swap the values of two key-pairs. fn swap(x_k1: XKArg1, x_k2: XKArg2, y_k1: YKArg1, y_k2: YKArg2) where XKArg1: EncodeLike, XKArg2: EncodeLike, YKArg1: EncodeLike, YKArg2: EncodeLike; /// Store a value to be associated with the given keys from the double map. fn insert(k1: KArg1, k2: KArg2, val: VArg) where KArg1: EncodeLike, KArg2: EncodeLike, VArg: EncodeLike; /// Remove the value under the given keys. fn remove(k1: KArg1, k2: KArg2) where KArg1: EncodeLike, KArg2: EncodeLike; /// Remove all values under the first key. 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 where KArg1: ?Sized + EncodeLike; /// Mutate the value under the given keys. fn mutate(k1: KArg1, k2: KArg2, f: F) -> R where KArg1: EncodeLike, KArg2: EncodeLike, F: FnOnce(&mut Self::Query) -> R; /// Mutate the value under the given keys when the closure returns `Ok`. fn try_mutate(k1: KArg1, k2: KArg2, f: F) -> Result where KArg1: EncodeLike, KArg2: EncodeLike, F: FnOnce(&mut Self::Query) -> Result; /// Mutate the value under the given keys. Deletes the item if mutated to a `None`. fn mutate_exists(k1: KArg1, k2: KArg2, f: F) -> R where KArg1: EncodeLike, KArg2: EncodeLike, F: FnOnce(&mut Option) -> R; /// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`. fn try_mutate_exists(k1: KArg1, k2: KArg2, f: F) -> Result where KArg1: EncodeLike, KArg2: EncodeLike, F: FnOnce(&mut Option) -> Result; /// Append the given item to the value in the storage. /// /// `V` is required to implement [`StorageAppend`]. /// /// # Warning /// /// If the storage item is not encoded properly, the storage will be overwritten /// and set to `[item]`. Any default value set for the storage item will be ignored /// on overwrite. fn append( k1: KArg1, k2: KArg2, item: EncodeLikeItem, ) where KArg1: EncodeLike, KArg2: EncodeLike, Item: Encode, EncodeLikeItem: EncodeLike, V: StorageAppend; /// Read the length of the storage value without decoding the entire value under the /// given `key1` and `key2`. /// /// `V` is required to implement [`StorageDecodeLength`]. /// /// If the value does not exists or it fails to decode the length, `None` is returned. /// Otherwise `Some(len)` is returned. /// /// # Warning /// /// `None` does not mean that `get()` does not return a value. The default value is completly /// ignored by this function. fn decode_len(key1: KArg1, key2: KArg2) -> Option where KArg1: EncodeLike, KArg2: EncodeLike, V: StorageDecodeLength, { V::decode_len(&Self::hashed_key_for(key1, key2)) } /// Migrate an item with the given `key1` and `key2` from defunct `OldHasher1` and /// `OldHasher2` to the current hashers. /// /// If the key doesn't exist, then it's a no-op. If it does, then it returns its value. fn migrate_keys< OldHasher1: StorageHasher, OldHasher2: StorageHasher, KeyArg1: EncodeLike, KeyArg2: EncodeLike, >(key1: KeyArg1, key2: KeyArg2) -> Option; } /// An implementation of a map with an arbitrary number of keys. /// /// Details of implementation can be found at [`generator::StorageNMap`]. pub trait StorageNMap { /// The type that get/take returns. type Query; /// Get the storage key used to fetch a value corresponding to a specific key. fn hashed_key_for + TupleToEncodedIter>(key: KArg) -> Vec; /// Does the value (explicitly) exist in storage? fn contains_key + TupleToEncodedIter>(key: KArg) -> bool; /// Load the value associated with the given key from the map. fn get + TupleToEncodedIter>(key: KArg) -> Self::Query; /// Try to get the value for the given key from the map. /// /// Returns `Ok` if it exists, `Err` if not. fn try_get + TupleToEncodedIter>(key: KArg) -> Result; /// Swap the values of two keys. fn swap(key1: KArg1, key2: KArg2) where KOther: KeyGenerator, KArg1: EncodeLikeTuple + TupleToEncodedIter, KArg2: EncodeLikeTuple + TupleToEncodedIter; /// Store a value to be associated with the given key from the map. fn insert(key: KArg, val: VArg) where KArg: EncodeLikeTuple + TupleToEncodedIter, VArg: EncodeLike; /// Remove the value under a key. fn remove + TupleToEncodedIter>(key: KArg); /// Remove all values under the partial prefix key. 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; /// Mutate the value under a key. fn mutate(key: KArg, f: F) -> R where KArg: EncodeLikeTuple + TupleToEncodedIter, F: FnOnce(&mut Self::Query) -> R; /// Mutate the item, only if an `Ok` value is returned. fn try_mutate(key: KArg, f: F) -> Result where KArg: EncodeLikeTuple + TupleToEncodedIter, F: FnOnce(&mut Self::Query) -> Result; /// Mutate the value under a key. /// /// Deletes the item if mutated to a `None`. fn mutate_exists(key: KArg, f: F) -> R where KArg: EncodeLikeTuple + TupleToEncodedIter, F: FnOnce(&mut Option) -> R; /// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`. fn try_mutate_exists(key: KArg, f: F) -> Result where KArg: EncodeLikeTuple + TupleToEncodedIter, F: FnOnce(&mut Option) -> Result; /// Take the value under a key. fn take + TupleToEncodedIter>(key: KArg) -> Self::Query; /// Append the given items to the value in the storage. /// /// `V` is required to implement `codec::EncodeAppend`. /// /// # Warning /// /// If the storage item is not encoded properly, the storage will be overwritten /// and set to `[item]`. Any default value set for the storage item will be ignored /// on overwrite. fn append(key: KArg, item: EncodeLikeItem) where KArg: EncodeLikeTuple + TupleToEncodedIter, Item: Encode, EncodeLikeItem: EncodeLike, V: StorageAppend; /// Read the length of the storage value without decoding the entire value under the /// given `key`. /// /// `V` is required to implement [`StorageDecodeLength`]. /// /// If the value does not exists or it fails to decode the length, `None` is returned. /// Otherwise `Some(len)` is returned. /// /// # Warning /// /// `None` does not mean that `get()` does not return a value. The default value is completly /// ignored by this function. fn decode_len + TupleToEncodedIter>(key: KArg) -> Option where V: StorageDecodeLength, { V::decode_len(&Self::hashed_key_for(key)) } /// Migrate an item with the given `key` from defunct `hash_fns` to the current hashers. /// /// If the key doesn't exist, then it's a no-op. If it does, then it returns its value. fn migrate_keys(key: KArg, hash_fns: K::HArg) -> Option where KArg: EncodeLikeTuple + TupleToEncodedIter; } /// Iterate over a prefix and decode raw_key and raw_value into `T`. /// /// If any decoding fails it skips it and continues to the next key. pub struct PrefixIterator { prefix: Vec, previous_key: Vec, /// If true then value are removed while iterating drain: bool, /// Function that take `(raw_key_without_prefix, raw_value)` and decode `T`. /// `raw_key_without_prefix` is the raw storage key without the prefix iterated on. closure: fn(&[u8], &[u8]) -> Result, } impl PrefixIterator { /// Mutate this iterator into a draining iterator; items iterated are removed from storage. pub fn drain(mut self) -> Self { self.drain = true; self } } impl Iterator for PrefixIterator { type Item = T; fn next(&mut self) -> Option { loop { let maybe_next = sp_io::storage::next_key(&self.previous_key) .filter(|n| n.starts_with(&self.prefix)); break match maybe_next { Some(next) => { self.previous_key = next; let raw_value = match unhashed::get_raw(&self.previous_key) { Some(raw_value) => raw_value, None => { log::error!( "next_key returned a key with no value at {:?}", self.previous_key, ); continue } }; if self.drain { unhashed::kill(&self.previous_key) } let raw_key_without_prefix = &self.previous_key[self.prefix.len()..]; let item = match (self.closure)(raw_key_without_prefix, &raw_value[..]) { Ok(item) => item, Err(e) => { log::error!( "(key, value) failed to decode at {:?}: {:?}", self.previous_key, e, ); continue } }; Some(item) } None => None, } } } } /// Iterate over a prefix of a child trie and decode raw_key and raw_value into `T`. /// /// If any decoding fails it skips the key and continues to the next one. pub struct ChildTriePrefixIterator { /// The prefix iterated on prefix: Vec, /// child info for child trie child_info: ChildInfo, /// The last key iterated on previous_key: Vec, /// If true then values are removed while iterating drain: bool, /// Whether or not we should fetch the previous key fetch_previous_key: bool, /// Function that takes `(raw_key_without_prefix, raw_value)` and decode `T`. /// `raw_key_without_prefix` is the raw storage key without the prefix iterated on. closure: fn(&[u8], &[u8]) -> Result, } impl ChildTriePrefixIterator { /// Mutate this iterator into a draining iterator; items iterated are removed from storage. pub fn drain(mut self) -> Self { self.drain = true; self } } impl ChildTriePrefixIterator<(Vec, T)> { /// Construct iterator to iterate over child trie items in `child_info` with the prefix `prefix`. /// /// NOTE: Iterator with [`Self::drain`] will remove any value who failed to decode pub fn with_prefix(child_info: &ChildInfo, prefix: &[u8]) -> Self { let prefix = prefix.to_vec(); let previous_key = prefix.clone(); let closure = |raw_key_without_prefix: &[u8], raw_value: &[u8]| { let value = T::decode(&mut &raw_value[..])?; Ok((raw_key_without_prefix.to_vec(), value)) }; Self { prefix, child_info: child_info.clone(), previous_key, drain: false, fetch_previous_key: true, closure, } } } impl ChildTriePrefixIterator<(K, T)> { /// Construct iterator to iterate over child trie items in `child_info` with the prefix `prefix`. /// /// NOTE: Iterator with [`Self::drain`] will remove any key or value who failed to decode pub fn with_prefix_over_key(child_info: &ChildInfo, prefix: &[u8]) -> Self { let prefix = prefix.to_vec(); let previous_key = prefix.clone(); let closure = |raw_key_without_prefix: &[u8], raw_value: &[u8]| { let mut key_material = H::reverse(raw_key_without_prefix); let key = K::decode(&mut key_material)?; let value = T::decode(&mut &raw_value[..])?; Ok((key, value)) }; Self { prefix, child_info: child_info.clone(), previous_key, drain: false, fetch_previous_key: true, closure, } } } impl Iterator for ChildTriePrefixIterator { type Item = T; fn next(&mut self) -> Option { loop { let maybe_next = if self.fetch_previous_key { self.fetch_previous_key = false; Some(self.previous_key.clone()) } else { sp_io::default_child_storage::next_key( &self.child_info.storage_key(), &self.previous_key, ) .filter(|n| n.starts_with(&self.prefix)) }; break match maybe_next { Some(next) => { self.previous_key = next; let raw_value = match child::get_raw(&self.child_info, &self.previous_key) { Some(raw_value) => raw_value, None => { log::error!( "next_key returned a key with no value at {:?}", self.previous_key, ); continue } }; if self.drain { child::kill(&self.child_info, &self.previous_key) } let raw_key_without_prefix = &self.previous_key[self.prefix.len()..]; let item = match (self.closure)(raw_key_without_prefix, &raw_value[..]) { Ok(item) => item, Err(e) => { log::error!( "(key, value) failed to decode at {:?}: {:?}", self.previous_key, e, ); continue } }; Some(item) } None => None, } } } } /// Trait for maps that store all its value after a unique prefix. /// /// By default the final prefix is: /// ```nocompile /// Twox128(module_prefix) ++ Twox128(storage_prefix) /// ``` pub trait StoragePrefixedMap { /// Module prefix. Used for generating final key. fn module_prefix() -> &'static [u8]; /// Storage prefix. Used for generating final key. fn storage_prefix() -> &'static [u8]; /// Final full prefix that prefixes all keys. fn final_prefix() -> [u8; 32] { let mut final_key = [0u8; 32]; final_key[0..16].copy_from_slice(&Twox128::hash(Self::module_prefix())); final_key[16..32].copy_from_slice(&Twox128::hash(Self::storage_prefix())); final_key } /// Remove all value of the storage. fn remove_all(limit: Option) -> sp_io::KillStorageResult { sp_io::storage::clear_prefix(&Self::final_prefix(), limit) } /// Iter over all value of the storage. /// /// NOTE: If a value failed to decode becaues storage is corrupted then it is skipped. fn iter_values() -> PrefixIterator { let prefix = Self::final_prefix(); PrefixIterator { prefix: prefix.to_vec(), previous_key: prefix.to_vec(), drain: false, closure: |_raw_key, mut raw_value| Value::decode(&mut raw_value), } } /// Translate the values of all elements by a function `f`, in the map in no particular order. /// By returning `None` from `f` for an element, you'll remove it from the map. /// /// NOTE: If a value fail to decode because storage is corrupted then it is skipped. /// /// # Warning /// /// This function must be used with care, before being updated the storage still contains the /// old type, thus other calls (such as `get`) will fail at decoding it. /// /// # Usage /// /// This would typically be called inside the module implementation of on_runtime_upgrade. fn translate_values Option>(mut f: F) { let prefix = Self::final_prefix(); let mut previous_key = prefix.clone().to_vec(); while let Some(next) = sp_io::storage::next_key(&previous_key) .filter(|n| n.starts_with(&prefix)) { previous_key = next; let maybe_value = unhashed::get::(&previous_key); match maybe_value { Some(value) => match f(value) { Some(new) => unhashed::put::(&previous_key, &new), None => unhashed::kill(&previous_key), }, None => { log::error!( "old key failed to decode at {:?}", previous_key, ); continue }, } } } } /// Marker trait that will be implemented for types that support the `storage::append` api. /// /// This trait is sealed. pub trait StorageAppend: private::Sealed {} /// Marker trait that will be implemented for types that support to decode their length in an /// effificent way. It is expected that the length is at the beginning of the encoded object /// and that the length is a `Compact`. /// /// This trait is sealed. pub trait StorageDecodeLength: private::Sealed + codec::DecodeLength { /// Decode the length of the storage value at `key`. /// /// This function assumes that the length is at the beginning of the encoded object /// and is a `Compact`. /// /// Returns `None` if the storage value does not exist or the decoding failed. fn decode_len(key: &[u8]) -> Option { // `Compact` is 5 bytes in maximum. let mut data = [0u8; 5]; let len = sp_io::storage::read(key, &mut data, 0)?; let len = data.len().min(len as usize); ::len(&data[..len]).ok() } } /// Provides `Sealed` trait to prevent implementing trait `StorageAppend` & `StorageDecodeLength` /// & `EncodeLikeTuple` outside of this crate. mod private { use super::*; use bounded_vec::BoundedVec; use weak_bounded_vec::WeakBoundedVec; pub trait Sealed {} impl Sealed for Vec {} impl Sealed for Digest {} impl Sealed for BoundedVec {} impl Sealed for WeakBoundedVec {} impl Sealed for bounded_btree_map::BoundedBTreeMap {} impl Sealed for bounded_btree_set::BoundedBTreeSet {} macro_rules! impl_sealed_for_tuple { ($($elem:ident),+) => { paste::paste! { impl<$($elem: Encode,)+> Sealed for ($($elem,)+) {} impl<$($elem: Encode,)+> Sealed for &($($elem,)+) {} } }; } impl_sealed_for_tuple!(A); impl_sealed_for_tuple!(A, B); impl_sealed_for_tuple!(A, B, C); impl_sealed_for_tuple!(A, B, C, D); impl_sealed_for_tuple!(A, B, C, D, E); impl_sealed_for_tuple!(A, B, C, D, E, F); impl_sealed_for_tuple!(A, B, C, D, E, F, G); impl_sealed_for_tuple!(A, B, C, D, E, F, G, H); impl_sealed_for_tuple!(A, B, C, D, E, F, G, H, I); impl_sealed_for_tuple!(A, B, C, D, E, F, G, H, I, J); impl_sealed_for_tuple!(A, B, C, D, E, F, G, H, I, J, K); impl_sealed_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L); impl_sealed_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M); impl_sealed_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, O); impl_sealed_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, O, P); impl_sealed_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, O, P, Q); impl_sealed_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, O, P, Q, R); } impl StorageAppend for Vec {} impl StorageDecodeLength for Vec {} /// We abuse the fact that SCALE does not put any marker into the encoding, i.e. we only encode the /// internal vec and we can append to this vec. We have a test that ensures that if the `Digest` /// format ever changes, we need to remove this here. impl StorageAppend> for Digest {} /// Marker trait that is implemented for types that support the `storage::append` api with a limit /// on the number of element. /// /// This trait is sealed. pub trait StorageTryAppend: StorageDecodeLength + private::Sealed { fn bound() -> usize; } /// Storage value that is capable of [`StorageTryAppend`](crate::storage::StorageTryAppend). pub trait TryAppendValue, I: Encode> { /// Try and append the `item` into the storage item. /// /// This might fail if bounds are not respected. fn try_append>(item: LikeI) -> Result<(), ()>; } impl TryAppendValue for StorageValueT where I: Encode, T: FullCodec + StorageTryAppend, StorageValueT: generator::StorageValue, { fn try_append>(item: LikeI) -> Result<(), ()> { let bound = T::bound(); let current = Self::decode_len().unwrap_or_default(); if current < bound { // NOTE: we cannot reuse the implementation for `Vec` here because we never want to // mark `BoundedVec` as `StorageAppend`. let key = Self::storage_value_final_key(); sp_io::storage::append(&key, item.encode()); Ok(()) } else { Err(()) } } } /// Storage map that is capable of [`StorageTryAppend`](crate::storage::StorageTryAppend). pub trait TryAppendMap, I: Encode> { /// Try and append the `item` into the storage map at the given `key`. /// /// This might fail if bounds are not respected. fn try_append + Clone, LikeI: EncodeLike>( key: LikeK, item: LikeI, ) -> Result<(), ()>; } impl TryAppendMap for StorageMapT where K: FullCodec, T: FullCodec + StorageTryAppend, I: Encode, StorageMapT: generator::StorageMap, { fn try_append + Clone, LikeI: EncodeLike>( key: LikeK, item: LikeI, ) -> Result<(), ()> { let bound = T::bound(); let current = Self::decode_len(key.clone()).unwrap_or_default(); if current < bound { let key = Self::storage_map_final_key(key); sp_io::storage::append(&key, item.encode()); Ok(()) } else { Err(()) } } } /// Storage double map that is capable of [`StorageTryAppend`](crate::storage::StorageTryAppend). pub trait TryAppendDoubleMap, I: Encode> { /// Try and append the `item` into the storage double map at the given `key`. /// /// This might fail if bounds are not respected. fn try_append< LikeK1: EncodeLike + Clone, LikeK2: EncodeLike + Clone, LikeI: EncodeLike, >( key1: LikeK1, key2: LikeK2, item: LikeI, ) -> Result<(), ()>; } impl TryAppendDoubleMap for StorageDoubleMapT where K1: FullCodec, K2: FullCodec, T: FullCodec + StorageTryAppend, I: Encode, StorageDoubleMapT: generator::StorageDoubleMap, { fn try_append< LikeK1: EncodeLike + Clone, LikeK2: EncodeLike + Clone, LikeI: EncodeLike, >( key1: LikeK1, key2: LikeK2, item: LikeI, ) -> Result<(), ()> { let bound = T::bound(); let current = Self::decode_len(key1.clone(), key2.clone()).unwrap_or_default(); if current < bound { let double_map_key = Self::storage_double_map_final_key(key1, key2); sp_io::storage::append(&double_map_key, item.encode()); Ok(()) } else { Err(()) } } } #[cfg(test)] mod test { use super::*; use sp_core::hashing::twox_128; use crate::{hash::Identity, assert_ok}; use sp_io::TestExternalities; use generator::StorageValue as _; use bounded_vec::BoundedVec; use weak_bounded_vec::WeakBoundedVec; use core::convert::{TryFrom, TryInto}; #[test] fn prefixed_map_works() { TestExternalities::default().execute_with(|| { struct MyStorage; impl StoragePrefixedMap for MyStorage { fn module_prefix() -> &'static [u8] { b"MyModule" } fn storage_prefix() -> &'static [u8] { b"MyStorage" } } let key_before = { let mut k = MyStorage::final_prefix(); let last = k.iter_mut().last().unwrap(); *last = last.checked_sub(1).unwrap(); k }; let key_after = { let mut k = MyStorage::final_prefix(); let last = k.iter_mut().last().unwrap(); *last = last.checked_add(1).unwrap(); k }; unhashed::put(&key_before[..], &32u64); unhashed::put(&key_after[..], &33u64); let k = [twox_128(b"MyModule"), twox_128(b"MyStorage")].concat(); assert_eq!(MyStorage::final_prefix().to_vec(), k); // test iteration assert!(MyStorage::iter_values().collect::>().is_empty()); unhashed::put(&[&k[..], &vec![1][..]].concat(), &1u64); unhashed::put(&[&k[..], &vec![1, 1][..]].concat(), &2u64); unhashed::put(&[&k[..], &vec![8][..]].concat(), &3u64); unhashed::put(&[&k[..], &vec![10][..]].concat(), &4u64); assert_eq!(MyStorage::iter_values().collect::>(), vec![1, 2, 3, 4]); // test removal MyStorage::remove_all(None); assert!(MyStorage::iter_values().collect::>().is_empty()); // test migration unhashed::put(&[&k[..], &vec![1][..]].concat(), &1u32); unhashed::put(&[&k[..], &vec![8][..]].concat(), &2u32); 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(None); // test migration 2 unhashed::put(&[&k[..], &vec![1][..]].concat(), &1u128); unhashed::put(&[&k[..], &vec![1, 1][..]].concat(), &2u64); unhashed::put(&[&k[..], &vec![8][..]].concat(), &3u128); unhashed::put(&[&k[..], &vec![10][..]].concat(), &4u32); // (contains some value that successfully decoded to u64) 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(None); // test that other values are not modified. assert_eq!(unhashed::get(&key_before[..]), Some(32u64)); assert_eq!(unhashed::get(&key_after[..]), Some(33u64)); }); } // This test ensures that the Digest encoding does not change without being noticied. #[test] fn digest_storage_append_works_as_expected() { TestExternalities::default().execute_with(|| { struct Storage; impl generator::StorageValue> for Storage { type Query = Digest; fn module_prefix() -> &'static [u8] { b"MyModule" } fn storage_prefix() -> &'static [u8] { b"Storage" } fn from_optional_value_to_query(v: Option>) -> Self::Query { v.unwrap() } fn from_query_to_optional_value(v: Self::Query) -> Option> { Some(v) } } Storage::append(DigestItem::ChangesTrieRoot(1)); Storage::append(DigestItem::Other(Vec::new())); let value = unhashed::get_raw(&Storage::storage_value_final_key()).unwrap(); let expected = Digest { logs: vec![DigestItem::ChangesTrieRoot(1), DigestItem::Other(Vec::new())], }; assert_eq!(Digest::decode(&mut &value[..]).unwrap(), expected); }); } #[test] #[should_panic(expected = "Require transaction not called within with_transaction")] fn require_transaction_should_panic() { TestExternalities::default().execute_with(|| { require_transaction(); }); } #[test] fn require_transaction_should_not_panic_in_with_transaction() { TestExternalities::default().execute_with(|| { with_transaction(|| { require_transaction(); TransactionOutcome::Commit(()) }); with_transaction(|| { require_transaction(); TransactionOutcome::Rollback(()) }); }); } #[test] fn child_trie_prefixed_map_works() { TestExternalities::default().execute_with(|| { let child_info_a = child::ChildInfo::new_default(b"a"); child::put(&child_info_a, &[1, 2, 3], &8u16); child::put(&child_info_a, &[2], &8u16); child::put(&child_info_a, &[2, 1, 3], &8u8); child::put(&child_info_a, &[2, 2, 3], &8u16); child::put(&child_info_a, &[3], &8u16); assert_eq!( ChildTriePrefixIterator::with_prefix(&child_info_a, &[2]) .collect::, u16)>>(), vec![ (vec![], 8), (vec![2, 3], 8), ], ); assert_eq!( ChildTriePrefixIterator::with_prefix(&child_info_a, &[2]) .drain() .collect::, u16)>>(), vec![ (vec![], 8), (vec![2, 3], 8), ], ); // The only remaining is the ones outside prefix assert_eq!( ChildTriePrefixIterator::with_prefix(&child_info_a, &[]) .collect::, u8)>>(), vec![ (vec![1, 2, 3], 8), (vec![3], 8), ], ); child::put(&child_info_a, &[1, 2, 3], &8u16); child::put(&child_info_a, &[2], &8u16); child::put(&child_info_a, &[2, 1, 3], &8u8); child::put(&child_info_a, &[2, 2, 3], &8u16); child::put(&child_info_a, &[3], &8u16); assert_eq!( ChildTriePrefixIterator::with_prefix_over_key::(&child_info_a, &[2]) .collect::>(), vec![ (u16::decode(&mut &[2, 3][..]).unwrap(), 8), ], ); assert_eq!( ChildTriePrefixIterator::with_prefix_over_key::(&child_info_a, &[2]) .drain() .collect::>(), vec![ (u16::decode(&mut &[2, 3][..]).unwrap(), 8), ], ); // The only remaining is the ones outside prefix assert_eq!( ChildTriePrefixIterator::with_prefix(&child_info_a, &[]) .collect::, u8)>>(), vec![ (vec![1, 2, 3], 8), (vec![3], 8), ], ); }); } crate::parameter_types! { pub const Seven: u32 = 7; pub const Four: u32 = 4; } crate::generate_storage_alias! { Prefix, Foo => Value> } crate::generate_storage_alias! { Prefix, FooMap => Map<(u32, Twox128), BoundedVec> } crate::generate_storage_alias! { Prefix, FooDoubleMap => DoubleMap<(u32, Twox128), (u32, Twox128), BoundedVec> } #[test] fn try_append_works() { TestExternalities::default().execute_with(|| { let bounded: WeakBoundedVec = vec![1, 2, 3].try_into().unwrap(); Foo::put(bounded); assert_ok!(Foo::try_append(4)); assert_ok!(Foo::try_append(5)); assert_ok!(Foo::try_append(6)); assert_ok!(Foo::try_append(7)); assert_eq!(Foo::decode_len().unwrap(), 7); assert!(Foo::try_append(8).is_err()); }); TestExternalities::default().execute_with(|| { let bounded: BoundedVec = vec![1, 2, 3].try_into().unwrap(); FooMap::insert(1, bounded); assert_ok!(FooMap::try_append(1, 4)); assert_ok!(FooMap::try_append(1, 5)); assert_ok!(FooMap::try_append(1, 6)); assert_ok!(FooMap::try_append(1, 7)); assert_eq!(FooMap::decode_len(1).unwrap(), 7); assert!(FooMap::try_append(1, 8).is_err()); // append to a non-existing assert!(FooMap::get(2).is_none()); assert_ok!(FooMap::try_append(2, 4)); assert_eq!( FooMap::get(2).unwrap(), BoundedVec::::try_from(vec![4]).unwrap(), ); assert_ok!(FooMap::try_append(2, 5)); assert_eq!( FooMap::get(2).unwrap(), BoundedVec::::try_from(vec![4, 5]).unwrap(), ); }); TestExternalities::default().execute_with(|| { let bounded: BoundedVec = vec![1, 2, 3].try_into().unwrap(); FooDoubleMap::insert(1, 1, bounded); assert_ok!(FooDoubleMap::try_append(1, 1, 4)); assert_ok!(FooDoubleMap::try_append(1, 1, 5)); assert_ok!(FooDoubleMap::try_append(1, 1, 6)); assert_ok!(FooDoubleMap::try_append(1, 1, 7)); assert_eq!(FooDoubleMap::decode_len(1, 1).unwrap(), 7); assert!(FooDoubleMap::try_append(1, 1, 8).is_err()); // append to a non-existing assert!(FooDoubleMap::get(2, 1).is_none()); assert_ok!(FooDoubleMap::try_append(2, 1, 4)); assert_eq!( FooDoubleMap::get(2, 1).unwrap(), BoundedVec::::try_from(vec![4]).unwrap(), ); assert_ok!(FooDoubleMap::try_append(2, 1, 5)); assert_eq!( FooDoubleMap::get(2, 1).unwrap(), BoundedVec::::try_from(vec![4, 5]).unwrap(), ); }); } }