Use storage::append in the implementation of the storage types (#5889)

* Start improving `storage_append`

* Fix some stuff

* Fix compilation

* Update docs and add new test

* More tests

* Test kill + append
This commit is contained in:
Bastian Köcher
2020-05-05 15:09:07 +02:00
committed by GitHub
parent be0c7b9340
commit bc9707b4c5
19 changed files with 252 additions and 362 deletions
+45 -67
View File
@@ -17,7 +17,7 @@
//! Stuff to do with the runtime's storage.
use sp_std::{prelude::*, marker::PhantomData};
use codec::{FullCodec, FullEncode, Encode, EncodeAppend, EncodeLike, Decode};
use codec::{FullCodec, FullEncode, Encode, EncodeLike, Decode};
use crate::{traits::Len, hash::{Twox128, StorageHasher}};
pub mod unhashed;
@@ -91,33 +91,18 @@ pub trait StorageValue<T: FullCodec> {
/// Append the given item to the value in the storage.
///
/// `T` is required to implement `codec::EncodeAppend`.
fn append<Items, Item, EncodeLikeItem>(items: Items) -> Result<(), &'static str>
/// `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>(item: EncodeLikeItem)
where
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
T: EncodeAppend<Item=Item>,
Items: IntoIterator<Item=EncodeLikeItem>,
Items::IntoIter: ExactSizeIterator;
/// Append the given items to the value in the storage.
///
/// `T` is required to implement `Codec::EncodeAppend`.
///
/// Upon any failure, it replaces `items` as the new value (assuming that the previous stored
/// data is simply corrupt and no longer usable).
///
/// ### WARNING
///
/// use with care; if your use-case is not _exactly_ as what this function is doing,
/// you should use append and sensibly handle failure within the runtime code if it happens.
fn append_or_put<Items, Item, EncodeLikeItem>(items: Items) where
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
T: EncodeAppend<Item=Item>,
Items: IntoIterator<Item=EncodeLikeItem> + Clone + EncodeLike<T>,
Items::IntoIter: ExactSizeIterator;
T: StorageAppend<Item>;
/// Read the length of the value in a fast way, without decoding the entire value.
///
@@ -176,25 +161,18 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
/// Append the given items to the value in the storage.
///
/// `V` is required to implement `codec::EncodeAppend`.
fn append<Items, Item, EncodeLikeItem, KeyArg>(key: KeyArg, items: Items) -> Result<(), &'static str> where
KeyArg: EncodeLike<K>,
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
V: EncodeAppend<Item=Item>,
Items: IntoIterator<Item=EncodeLikeItem>,
Items::IntoIter: ExactSizeIterator;
/// Safely append the given items to the value in the storage. If a codec error occurs, then the
/// old (presumably corrupt) value is replaced with the given `items`.
///
/// `V` is required to implement `codec::EncodeAppend`.
fn append_or_insert<Items, Item, EncodeLikeItem, KeyArg>(key: KeyArg, items: Items) where
KeyArg: EncodeLike<K>,
/// # 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<Item, EncodeLikeItem, EncodeLikeKey>(key: EncodeLikeKey, item: EncodeLikeItem)
where
EncodeLikeKey: EncodeLike<K>,
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
V: EncodeAppend<Item=Item>,
Items: IntoIterator<Item=EncodeLikeItem> + Clone + EncodeLike<V>,
Items::IntoIter: ExactSizeIterator;
V: StorageAppend<Item>;
/// Read the length of the value in a fast way, without decoding the entire value.
///
@@ -351,38 +329,23 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
/// Append the given item to the value in the storage.
///
/// `V` is required to implement `codec::EncodeAppend`.
fn append<Items, Item, EncodeLikeItem, KArg1, KArg2>(
k1: KArg1,
k2: KArg2,
items: Items,
) -> Result<(), &'static str>
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
V: EncodeAppend<Item=Item>,
Items: IntoIterator<Item=EncodeLikeItem>,
Items::IntoIter: ExactSizeIterator;
/// Safely append the given items to the value in the storage. If a codec error occurs, then the
/// old (presumably corrupt) value is replaced with the given `items`.
/// `V` is required to implement [`StorageAppend`].
///
/// `V` is required to implement `codec::EncodeAppend`.
fn append_or_insert<Items, Item, EncodeLikeItem, KArg1, KArg2>(
/// # 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<Item, EncodeLikeItem, KArg1, KArg2>(
k1: KArg1,
k2: KArg2,
items: Items,
)
where
item: EncodeLikeItem,
) where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
V: EncodeAppend<Item=Item>,
Items: IntoIterator<Item=EncodeLikeItem> + Clone + EncodeLike<V>,
Items::IntoIter: ExactSizeIterator;
V: StorageAppend<Item>;
/// Read the length of the value in a fast way, without decoding the entire value.
///
@@ -449,7 +412,6 @@ impl<Value: Decode> Iterator for PrefixIterator<Value> {
/// Twox128(module_prefix) ++ Twox128(storage_prefix)
/// ```
pub trait StoragePrefixedMap<Value: FullCodec> {
/// Module prefix. Used for generating final key.
fn module_prefix() -> &'static [u8];
@@ -525,6 +487,22 @@ pub trait StoragePrefixedMap<Value: FullCodec> {
}
}
/// Marker trait that will be implemented for types that support the `storage::append` api.
///
/// This trait is sealed.
pub trait StorageAppend<Item: Encode>: private::Sealed {}
/// Provides `Sealed` trait to prevent implementing trait `StorageAppend` outside of this crate.
mod private {
use super::*;
pub trait Sealed {}
impl<T: Encode> Sealed for Vec<T> {}
}
impl<T: Encode> StorageAppend<T> for Vec<T> {}
#[cfg(test)]
mod test {
use sp_core::hashing::twox_128;