// This file is part of Substrate. // Copyright (C) 2017-2020 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_std::prelude::*; use codec::{FullCodec, FullEncode, Encode, EncodeLike, Decode}; use crate::hash::{Twox128, StorageHasher}; use sp_runtime::generic::{Digest, DigestItem}; pub use sp_runtime::TransactionOutcome; pub mod unhashed; pub mod hashed; 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 { crate::debug::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; `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; /// 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); } /// 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; /// 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) 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; } /// 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 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 => { crate::debug::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) => { crate::debug::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() { sp_io::storage::clear_prefix(&Self::final_prefix()) } /// 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>(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 => { crate::debug::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` /// outside of this crate. mod private { use super::*; pub trait Sealed {} impl Sealed for Vec {} impl Sealed for Digest {} } 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 {} #[cfg(test)] mod test { use super::*; use sp_core::hashing::twox_128; use sp_io::TestExternalities; use generator::StorageValue as _; #[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(); 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(); // 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(); // 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(()) }); }); } }