Optimize decode_len (#5975)

* Optimize `decode_len`

Instead of reading the full storage value into the runtime, we only read
at maximum `5bytes` from the storage into the runtime. Furthermore this
drops any handling with regards to set default values in
`decl_storage!`. If the value does not exists or the decoding of the
length fails, it will return `None`. To prevent people from messing
stuff up, this feature relies on the `StorageDecodeLength` trait that is
sealed by `frame-support` (aka only implementable inside this crate).

* Some clean ups

* Update frame/support/src/storage/mod.rs

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>
This commit is contained in:
Bastian Köcher
2020-05-12 12:13:28 +02:00
committed by GitHub
parent 0690bb51a8
commit 22db788c08
7 changed files with 91 additions and 87 deletions
@@ -17,7 +17,7 @@
use sp_std::prelude::*;
use sp_std::borrow::Borrow;
use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike};
use crate::{storage::{self, unhashed, StorageAppend}, traits::Len, Never};
use crate::{storage::{self, unhashed, StorageAppend}, Never};
use crate::hash::{StorageHasher, Twox128, ReversibleStorageHasher};
/// Generator for `StorageDoubleMap` used by `decl_storage`.
@@ -260,23 +260,6 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
sp_io::storage::append(&final_key, item.encode());
}
fn decode_len<KArg1, KArg2>(key1: KArg1, key2: KArg2) -> Result<usize, &'static str> where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
V: codec::DecodeLength + Len,
{
let final_key = Self::storage_double_map_final_key(key1, key2);
if let Some(v) = unhashed::get_raw(&final_key) {
<V as codec::DecodeLength>::len(&v).map_err(|e| e.what())
} else {
let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None))
.map(|v| v.len())
.unwrap_or(0);
Ok(len)
}
}
fn migrate_keys<
OldHasher1: StorageHasher,
OldHasher2: StorageHasher,
@@ -18,8 +18,10 @@
use sp_std::prelude::*;
use sp_std::borrow::Borrow;
use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike};
use crate::{storage::{self, unhashed, StorageAppend}, traits::Len, Never};
use crate::hash::{StorageHasher, Twox128, ReversibleStorageHasher};
use crate::{
storage::{self, unhashed, StorageAppend},
Never, hash::{StorageHasher, Twox128, ReversibleStorageHasher},
};
/// Generator for `StorageMap` used by `decl_storage`.
///
@@ -287,21 +289,6 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
sp_io::storage::append(&key, item.encode());
}
fn decode_len<KeyArg: EncodeLike<K>>(key: KeyArg) -> Result<usize, &'static str>
where V: codec::DecodeLength + Len
{
let key = Self::storage_map_final_key(key);
if let Some(v) = unhashed::get_raw(key.as_ref()) {
<V as codec::DecodeLength>::len(&v).map_err(|e| e.what())
} else {
let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None))
.map(|v| v.len())
.unwrap_or(0);
Ok(len)
}
}
fn migrate_key<OldHasher: StorageHasher, KeyArg: EncodeLike<K>>(key: KeyArg) -> Option<V> {
let old_key = {
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
@@ -19,7 +19,6 @@ use crate::{
Never,
storage::{self, unhashed, StorageAppend},
hash::{Twox128, StorageHasher},
traits::Len
};
/// Generator for `StorageValue` used by `decl_storage`.
@@ -141,19 +140,4 @@ impl<T: FullCodec, G: StorageValue<T>> storage::StorageValue<T> for G {
let key = Self::storage_value_final_key();
sp_io::storage::append(&key, item.encode());
}
fn decode_len() -> Result<usize, &'static str> where T: codec::DecodeLength, T: Len {
let key = Self::storage_value_final_key();
// attempt to get the length directly.
if let Some(k) = unhashed::get_raw(&key) {
<T as codec::DecodeLength>::len(&k).map_err(|e| e.what())
} else {
let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None))
.map(|v| v.len())
.unwrap_or(0);
Ok(len)
}
}
}