feat: compute pallet/storage prefix hash at compile time (#1539)

Since the hash rules of this part of the `pallet_prefix/storage_prefix`
are always fixed, we can put the runtime calculation into compile time.

---
polkadot address: 15ouFh2SHpGbHtDPsJ6cXQfes9Cx1gEFnJJsJVqPGzBSTudr

---------

Co-authored-by: Juan <juangirini@gmail.com>
Co-authored-by: command-bot <>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
This commit is contained in:
yjh
2023-10-03 23:16:46 +08:00
committed by GitHub
parent 3ea497b5a0
commit aad80cce31
28 changed files with 263 additions and 123 deletions
Generated
+1
View File
@@ -5289,6 +5289,7 @@ dependencies = [
"proc-macro-warning",
"proc-macro2",
"quote",
"sp-core-hashing",
"syn 2.0.37",
]
@@ -79,7 +79,7 @@ pub struct ProposerFactory<A, B, C, PR> {
/// The soft deadline indicates where we should stop attempting to add transactions
/// to the block, which exhaust resources. After soft deadline is reached,
/// we switch to a fixed-amount mode, in which after we see `MAX_SKIPPED_TRANSACTIONS`
/// transactions which exhaust resrouces, we will conclude that the block is full.
/// transactions which exhaust resources, we will conclude that the block is full.
soft_deadline_percent: Percent,
telemetry: Option<TelemetryHandle>,
/// When estimating the block size, should the proof be included?
@@ -42,8 +42,8 @@ where
.to_string()],
at: None,
hashed_prefixes: vec![
<pallet_staking::Bonded<Runtime>>::prefix_hash(),
<pallet_staking::Ledger<Runtime>>::prefix_hash(),
<pallet_staking::Bonded<Runtime>>::prefix_hash().to_vec(),
<pallet_staking::Ledger<Runtime>>::prefix_hash().to_vec(),
<pallet_staking::Validators<Runtime>>::map_storage_final_prefix(),
<pallet_staking::Nominators<Runtime>>::map_storage_final_prefix(),
],
@@ -39,8 +39,8 @@ pub async fn execute<Runtime, Block>(
pallets: vec![pallet_bags_list::Pallet::<Runtime, pallet_bags_list::Instance1>::name()
.to_string()],
hashed_prefixes: vec![
<pallet_staking::Bonded<Runtime>>::prefix_hash(),
<pallet_staking::Ledger<Runtime>>::prefix_hash(),
<pallet_staking::Bonded<Runtime>>::prefix_hash().to_vec(),
<pallet_staking::Ledger<Runtime>>::prefix_hash().to_vec(),
],
..Default::default()
}))
+6 -6
View File
@@ -53,7 +53,7 @@ pub type ValueIndex = u32;
/// [`Page`]s.
///
/// Each [`Page`] holds at most `ValuesPerNewPage` values in its `values` vector. The last page is
/// the only one that could have less than `ValuesPerNewPage` values.
/// the only one that could have less than `ValuesPerNewPage` values.
/// **Iteration** happens by starting
/// at [`first_page`][StoragePagedListMeta::first_page]/
/// [`first_value_offset`][StoragePagedListMeta::first_value_offset] and incrementing these indices
@@ -373,11 +373,11 @@ where
/// that are completely useless for prefix calculation.
struct StoragePagedListPrefix<Prefix>(PhantomData<Prefix>);
impl<Prefix> frame_support::storage::StoragePrefixedContainer for StoragePagedListPrefix<Prefix>
impl<Prefix> StoragePrefixedContainer for StoragePagedListPrefix<Prefix>
where
Prefix: StorageInstance,
{
fn module_prefix() -> &'static [u8] {
fn pallet_prefix() -> &'static [u8] {
Prefix::pallet_prefix().as_bytes()
}
@@ -386,15 +386,15 @@ where
}
}
impl<Prefix, Value, ValuesPerNewPage> frame_support::storage::StoragePrefixedContainer
impl<Prefix, Value, ValuesPerNewPage> StoragePrefixedContainer
for StoragePagedList<Prefix, Value, ValuesPerNewPage>
where
Prefix: StorageInstance,
Value: FullCodec,
ValuesPerNewPage: Get<u32>,
{
fn module_prefix() -> &'static [u8] {
StoragePagedListPrefix::<Prefix>::module_prefix()
fn pallet_prefix() -> &'static [u8] {
StoragePagedListPrefix::<Prefix>::pallet_prefix()
}
fn storage_prefix() -> &'static [u8] {
@@ -26,6 +26,7 @@ frame-support-procedural-tools = { path = "tools" }
proc-macro-warning = { version = "0.4.2", default-features = false }
macro_magic = { version = "0.4.2", features = ["proc_support"] }
expander = "2.0.0"
sp-core-hashing = { path = "../../../primitives/core/hashing" }
[features]
default = [ "std" ]
@@ -211,6 +211,7 @@
mod expand;
mod parse;
use crate::pallet::parse::helper::two128_str;
use cfg_expr::Predicate;
use frame_support_procedural_tools::{
generate_crate_access, generate_crate_access_2018, generate_hidden_includes,
@@ -403,17 +404,19 @@ fn construct_runtime_final_expansion(
let integrity_test = decl_integrity_test(&scrate);
let static_assertions = decl_static_assertions(&name, &pallets, &scrate);
let warning =
where_section.map_or(None, |where_section| {
Some(proc_macro_warning::Warning::new_deprecated("WhereSection")
.old("use a `where` clause in `construct_runtime`")
.new("use `frame_system::Config` to set the `Block` type and delete this clause.
It is planned to be removed in December 2023")
.help_links(&["https://github.com/paritytech/substrate/pull/14437"])
.span(where_section.span)
.build(),
let warning = where_section.map_or(None, |where_section| {
Some(
proc_macro_warning::Warning::new_deprecated("WhereSection")
.old("use a `where` clause in `construct_runtime`")
.new(
"use `frame_system::Config` to set the `Block` type and delete this clause.
It is planned to be removed in December 2023",
)
.help_links(&["https://github.com/paritytech/substrate/pull/14437"])
.span(where_section.span)
.build(),
)
});
});
let res = quote!(
#warning
@@ -659,7 +662,6 @@ fn decl_all_pallets<'a>(
#( #all_pallets_reversed_with_system_first )*
)
}
fn decl_pallet_runtime_setup(
runtime: &Ident,
pallet_declarations: &[Pallet],
@@ -667,6 +669,7 @@ fn decl_pallet_runtime_setup(
) -> TokenStream2 {
let names = pallet_declarations.iter().map(|d| &d.name).collect::<Vec<_>>();
let name_strings = pallet_declarations.iter().map(|d| d.name.to_string());
let name_hashes = pallet_declarations.iter().map(|d| two128_str(&d.name.to_string()));
let module_names = pallet_declarations.iter().map(|d| d.path.module_name());
let indices = pallet_declarations.iter().map(|pallet| pallet.index as usize);
let pallet_structs = pallet_declarations
@@ -699,6 +702,7 @@ fn decl_pallet_runtime_setup(
pub struct PalletInfo;
impl #scrate::traits::PalletInfo for PalletInfo {
fn index<P: 'static>() -> Option<usize> {
let type_id = #scrate::__private::sp_std::any::TypeId::of::<P>();
#(
@@ -723,6 +727,18 @@ fn decl_pallet_runtime_setup(
None
}
fn name_hash<P: 'static>() -> Option<[u8; 16]> {
let type_id = #scrate::__private::sp_std::any::TypeId::of::<P>();
#(
#pallet_attrs
if type_id == #scrate::__private::sp_std::any::TypeId::of::<#names>() {
return Some(#name_hashes)
}
)*
None
}
fn module_name<P: 'static>() -> Option<&'static str> {
let type_id = #scrate::__private::sp_std::any::TypeId::of::<P>();
#(
@@ -246,6 +246,14 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream {
implemented by the runtime")
}
fn name_hash() -> [u8; 16] {
<
<T as #frame_system::Config>::PalletInfo as #frame_support::traits::PalletInfo
>::name_hash::<Self>()
.expect("Pallet is part of the runtime because pallet `Config` trait is \
implemented by the runtime")
}
fn module_name() -> &'static str {
<
<T as #frame_system::Config>::PalletInfo as #frame_support::traits::PalletInfo
@@ -18,7 +18,10 @@
use crate::{
counter_prefix,
pallet::{
parse::storage::{Metadata, QueryKind, StorageDef, StorageGenerics},
parse::{
helper::two128_str,
storage::{Metadata, QueryKind, StorageDef, StorageGenerics},
},
Def,
},
};
@@ -638,6 +641,7 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream {
Metadata::CountedMap { .. } => {
let counter_prefix_struct_ident = counter_prefix_ident(&storage_def.ident);
let counter_prefix_struct_const = counter_prefix(&prefix_struct_const);
let storage_prefix_hash = two128_str(&counter_prefix_struct_const);
quote::quote_spanned!(storage_def.attr_span =>
#(#cfg_attrs)*
#[doc(hidden)]
@@ -656,7 +660,19 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream {
>::name::<Pallet<#type_use_gen>>()
.expect("No name found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`.")
}
fn pallet_prefix_hash() -> [u8; 16] {
<
<T as #frame_system::Config>::PalletInfo
as #frame_support::traits::PalletInfo
>::name_hash::<Pallet<#type_use_gen>>()
.expect("No name_hash found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`.")
}
const STORAGE_PREFIX: &'static str = #counter_prefix_struct_const;
fn storage_prefix_hash() -> [u8; 16] {
#storage_prefix_hash
}
}
#(#cfg_attrs)*
impl<#type_impl_gen> #frame_support::storage::types::CountedStorageMapInstance
@@ -670,6 +686,7 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream {
Metadata::CountedNMap { .. } => {
let counter_prefix_struct_ident = counter_prefix_ident(&storage_def.ident);
let counter_prefix_struct_const = counter_prefix(&prefix_struct_const);
let storage_prefix_hash = two128_str(&counter_prefix_struct_const);
quote::quote_spanned!(storage_def.attr_span =>
#(#cfg_attrs)*
#[doc(hidden)]
@@ -688,7 +705,17 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream {
>::name::<Pallet<#type_use_gen>>()
.expect("No name found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`.")
}
fn pallet_prefix_hash() -> [u8; 16] {
<
<T as #frame_system::Config>::PalletInfo
as #frame_support::traits::PalletInfo
>::name_hash::<Pallet<#type_use_gen>>()
.expect("No name_hash found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`.")
}
const STORAGE_PREFIX: &'static str = #counter_prefix_struct_const;
fn storage_prefix_hash() -> [u8; 16] {
#storage_prefix_hash
}
}
#(#cfg_attrs)*
impl<#type_impl_gen> #frame_support::storage::types::CountedStorageNMapInstance
@@ -702,6 +729,7 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream {
_ => proc_macro2::TokenStream::default(),
};
let storage_prefix_hash = two128_str(&prefix_struct_const);
quote::quote_spanned!(storage_def.attr_span =>
#maybe_counter
@@ -722,7 +750,19 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream {
>::name::<Pallet<#type_use_gen>>()
.expect("No name found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`.")
}
fn pallet_prefix_hash() -> [u8; 16] {
<
<T as #frame_system::Config>::PalletInfo
as #frame_support::traits::PalletInfo
>::name_hash::<Pallet<#type_use_gen>>()
.expect("No name_hash found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`.")
}
const STORAGE_PREFIX: &'static str = #prefix_struct_const;
fn storage_prefix_hash() -> [u8; 16] {
#storage_prefix_hash
}
}
)
});
@@ -26,7 +26,7 @@
//! to user defined types. And also crate new types and implement block.
mod expand;
mod parse;
pub(crate) mod parse;
pub use parse::{composite::keyword::CompositeKeyword, Def};
use syn::spanned::Spanned;
@@ -15,7 +15,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use quote::ToTokens;
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::spanned::Spanned;
/// List of additional token to be used for parsing.
@@ -610,3 +611,16 @@ pub fn check_pallet_call_return_type(type_: &syn::Type) -> syn::Result<()> {
syn::parse2::<Checker>(type_.to_token_stream()).map(|_| ())
}
pub(crate) fn two128_str(s: &str) -> TokenStream {
bytes_to_array(sp_core_hashing::twox_128(s.as_bytes()).into_iter())
}
pub(crate) fn bytes_to_array(bytes: impl IntoIterator<Item = u8>) -> TokenStream {
let bytes = bytes.into_iter();
quote!(
[ #( #bytes ),* ]
)
.into()
}
@@ -17,7 +17,7 @@
//! Implementation of the `storage_alias` attribute macro.
use crate::counter_prefix;
use crate::{counter_prefix, pallet::parse::helper};
use frame_support_procedural_tools::generate_crate_access_2018;
use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens};
@@ -619,6 +619,7 @@ fn generate_storage_instance(
let counter_code = is_counted_map.then(|| {
let counter_name = Ident::new(&counter_prefix(&name_str), Span::call_site());
let counter_storage_name_str = counter_prefix(&storage_name_str);
let storage_prefix_hash = helper::two128_str(&counter_storage_name_str);
quote! {
#visibility struct #counter_name< #impl_generics >(
@@ -633,6 +634,9 @@ fn generate_storage_instance(
}
const STORAGE_PREFIX: &'static str = #counter_storage_name_str;
fn storage_prefix_hash() -> [u8; 16] {
#storage_prefix_hash
}
}
impl<#impl_generics> #crate_::storage::types::CountedStorageMapInstance
@@ -643,6 +647,8 @@ fn generate_storage_instance(
}
});
let storage_prefix_hash = helper::two128_str(&storage_name_str);
// Implement `StorageInstance` trait.
let code = quote! {
#[allow(non_camel_case_types)]
@@ -658,6 +664,9 @@ fn generate_storage_instance(
}
const STORAGE_PREFIX: &'static str = #storage_name_str;
fn storage_prefix_hash() -> [u8; 16] {
#storage_prefix_hash
}
}
#counter_code
@@ -33,7 +33,7 @@ use sp_std::prelude::*;
///
/// Thus value for (key1, key2) is stored at:
/// ```nocompile
/// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher1(encode(key1)) ++ Hasher2(encode(key2))
/// Twox128(pallet_prefix) ++ Twox128(storage_prefix) ++ Hasher1(encode(key1)) ++ Hasher2(encode(key2))
/// ```
///
/// # Warning
@@ -53,18 +53,15 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
/// Hasher for the second key.
type Hasher2: StorageHasher;
/// Module prefix. Used for generating final key.
fn module_prefix() -> &'static [u8];
/// Pallet prefix. Used for generating final key.
fn pallet_prefix() -> &'static [u8];
/// Storage prefix. Used for generating final key.
fn storage_prefix() -> &'static [u8];
/// The full prefix; just the hash of `module_prefix` concatenated to the hash of
/// The full prefix; just the hash of `pallet_prefix` concatenated to the hash of
/// `storage_prefix`.
fn prefix_hash() -> Vec<u8> {
let result = storage_prefix(Self::module_prefix(), Self::storage_prefix());
result.to_vec()
}
fn prefix_hash() -> [u8; 32];
/// Convert an optional value retrieved from storage to the type queried.
fn from_optional_value_to_query(v: Option<V>) -> Self::Query;
@@ -77,7 +74,7 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
where
KArg1: EncodeLike<K1>,
{
let storage_prefix = storage_prefix(Self::module_prefix(), Self::storage_prefix());
let storage_prefix = storage_prefix(Self::pallet_prefix(), Self::storage_prefix());
let key_hashed = k1.using_encoded(Self::Hasher1::hash);
let mut final_key = Vec::with_capacity(storage_prefix.len() + key_hashed.as_ref().len());
@@ -94,7 +91,7 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
{
let storage_prefix = storage_prefix(Self::module_prefix(), Self::storage_prefix());
let storage_prefix = storage_prefix(Self::pallet_prefix(), Self::storage_prefix());
let key1_hashed = k1.using_encoded(Self::Hasher1::hash);
let key2_hashed = k2.using_encoded(Self::Hasher2::hash);
@@ -334,7 +331,7 @@ where
key2: KeyArg2,
) -> Option<V> {
let old_key = {
let storage_prefix = storage_prefix(Self::module_prefix(), Self::storage_prefix());
let storage_prefix = storage_prefix(Self::pallet_prefix(), Self::storage_prefix());
let key1_hashed = key1.using_encoded(OldHasher1::hash);
let key2_hashed = key2.using_encoded(OldHasher2::hash);
@@ -419,7 +416,7 @@ where
}
fn iter() -> Self::Iterator {
let prefix = G::prefix_hash();
let prefix = G::prefix_hash().to_vec();
Self::Iterator {
prefix: prefix.clone(),
previous_key: prefix,
@@ -442,7 +439,7 @@ where
}
fn iter_keys() -> Self::FullKeyIterator {
let prefix = G::prefix_hash();
let prefix = G::prefix_hash().to_vec();
Self::FullKeyIterator {
prefix: prefix.clone(),
previous_key: prefix,
@@ -470,7 +467,7 @@ where
}
fn translate<O: Decode, F: FnMut(K1, K2, O) -> Option<V>>(mut f: F) {
let prefix = G::prefix_hash();
let prefix = G::prefix_hash().to_vec();
let mut previous_key = prefix.clone();
while let Some(next) =
sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))
@@ -561,7 +558,7 @@ mod test_iterators {
type DoubleMap = self::frame_system::DoubleMap<Runtime>;
// All map iterator
let prefix = DoubleMap::prefix_hash();
let prefix = DoubleMap::prefix_hash().to_vec();
unhashed::put(&key_before_prefix(prefix.clone()), &1u64);
unhashed::put(&key_after_prefix(prefix.clone()), &1u64);
@@ -621,7 +618,7 @@ mod test_iterators {
assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64));
// Translate
let prefix = DoubleMap::prefix_hash();
let prefix = DoubleMap::prefix_hash().to_vec();
unhashed::put(&key_before_prefix(prefix.clone()), &1u64);
unhashed::put(&key_after_prefix(prefix.clone()), &1u64);
@@ -28,7 +28,7 @@ use sp_std::prelude::*;
///
/// By default each key value is stored at:
/// ```nocompile
/// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher(encode(key))
/// Twox128(pallet_prefix) ++ Twox128(storage_prefix) ++ Hasher(encode(key))
/// ```
///
/// # Warning
@@ -42,18 +42,15 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
/// Hasher. Used for generating final key.
type Hasher: StorageHasher;
/// Module prefix. Used for generating final key.
fn module_prefix() -> &'static [u8];
/// Pallet prefix. Used for generating final key.
fn pallet_prefix() -> &'static [u8];
/// Storage prefix. Used for generating final key.
fn storage_prefix() -> &'static [u8];
/// The full prefix; just the hash of `module_prefix` concatenated to the hash of
/// The full prefix; just the hash of `pallet_prefix` concatenated to the hash of
/// `storage_prefix`.
fn prefix_hash() -> Vec<u8> {
let result = storage_prefix(Self::module_prefix(), Self::storage_prefix());
result.to_vec()
}
fn prefix_hash() -> [u8; 32];
/// Convert an optional value retrieved from storage to the type queried.
fn from_optional_value_to_query(v: Option<V>) -> Self::Query;
@@ -66,7 +63,7 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
where
KeyArg: EncodeLike<K>,
{
let storage_prefix = storage_prefix(Self::module_prefix(), Self::storage_prefix());
let storage_prefix = storage_prefix(Self::pallet_prefix(), Self::storage_prefix());
let key_hashed = key.using_encoded(Self::Hasher::hash);
let mut final_key = Vec::with_capacity(storage_prefix.len() + key_hashed.as_ref().len());
@@ -128,7 +125,7 @@ where
/// Enumerate all elements in the map.
fn iter() -> Self::Iterator {
let prefix = G::prefix_hash();
let prefix = G::prefix_hash().to_vec();
PrefixIterator {
prefix: prefix.clone(),
previous_key: prefix,
@@ -150,7 +147,7 @@ where
/// Enumerate all keys in the map.
fn iter_keys() -> Self::KeyIterator {
let prefix = G::prefix_hash();
let prefix = G::prefix_hash().to_vec();
KeyPrefixIterator {
prefix: prefix.clone(),
previous_key: prefix,
@@ -190,7 +187,7 @@ where
previous_key: Option<Vec<u8>>,
mut f: F,
) -> Option<Vec<u8>> {
let prefix = G::prefix_hash();
let prefix = G::prefix_hash().to_vec();
let previous_key = previous_key.unwrap_or_else(|| prefix.clone());
let current_key =
@@ -339,7 +336,7 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
fn migrate_key<OldHasher: StorageHasher, KeyArg: EncodeLike<K>>(key: KeyArg) -> Option<V> {
let old_key = {
let storage_prefix = storage_prefix(Self::module_prefix(), Self::storage_prefix());
let storage_prefix = storage_prefix(Self::pallet_prefix(), Self::storage_prefix());
let key_hashed = key.using_encoded(OldHasher::hash);
let mut final_key =
@@ -398,7 +395,7 @@ mod test_iterators {
type Map = self::frame_system::Map<Runtime>;
// All map iterator
let prefix = Map::prefix_hash();
let prefix = Map::prefix_hash().to_vec();
unhashed::put(&key_before_prefix(prefix.clone()), &1u64);
unhashed::put(&key_after_prefix(prefix.clone()), &1u64);
@@ -420,7 +417,7 @@ mod test_iterators {
assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64));
// Translate
let prefix = Map::prefix_hash();
let prefix = Map::prefix_hash().to_vec();
unhashed::put(&key_before_prefix(prefix.clone()), &1u64);
unhashed::put(&key_after_prefix(prefix.clone()), &1u64);
@@ -61,18 +61,15 @@ pub trait StorageNMap<K: KeyGenerator, V: FullCodec> {
/// The type that get/take returns.
type Query;
/// Module prefix. Used for generating final key.
fn module_prefix() -> &'static [u8];
/// Pallet prefix. Used for generating final key.
fn pallet_prefix() -> &'static [u8];
/// Storage prefix. Used for generating final key.
fn storage_prefix() -> &'static [u8];
/// The full prefix; just the hash of `module_prefix` concatenated to the hash of
/// The full prefix; just the hash of `pallet_prefix` concatenated to the hash of
/// `storage_prefix`.
fn prefix_hash() -> Vec<u8> {
let result = storage_prefix(Self::module_prefix(), Self::storage_prefix());
result.to_vec()
}
fn prefix_hash() -> [u8; 32];
/// Convert an optional value retrieved from storage to the type queried.
fn from_optional_value_to_query(v: Option<V>) -> Self::Query;
@@ -85,7 +82,7 @@ pub trait StorageNMap<K: KeyGenerator, V: FullCodec> {
where
K: HasKeyPrefix<KP>,
{
let storage_prefix = storage_prefix(Self::module_prefix(), Self::storage_prefix());
let storage_prefix = storage_prefix(Self::pallet_prefix(), Self::storage_prefix());
let key_hashed = <K as HasKeyPrefix<KP>>::partial_key(key);
let mut final_key = Vec::with_capacity(storage_prefix.len() + key_hashed.len());
@@ -102,7 +99,7 @@ pub trait StorageNMap<K: KeyGenerator, V: FullCodec> {
KG: KeyGenerator,
KArg: EncodeLikeTuple<KG::KArg> + TupleToEncodedIter,
{
let storage_prefix = storage_prefix(Self::module_prefix(), Self::storage_prefix());
let storage_prefix = storage_prefix(Self::pallet_prefix(), Self::storage_prefix());
let key_hashed = KG::final_key(key);
let mut final_key = Vec::with_capacity(storage_prefix.len() + key_hashed.len());
@@ -299,7 +296,7 @@ where
KArg: EncodeLikeTuple<K::KArg> + TupleToEncodedIter,
{
let old_key = {
let storage_prefix = storage_prefix(Self::module_prefix(), Self::storage_prefix());
let storage_prefix = storage_prefix(Self::pallet_prefix(), Self::storage_prefix());
let key_hashed = K::migrate_key(&key, hash_fns);
let mut final_key = Vec::with_capacity(storage_prefix.len() + key_hashed.len());
@@ -386,11 +383,11 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
}
fn iter() -> Self::Iterator {
Self::iter_from(G::prefix_hash())
Self::iter_from(G::prefix_hash().to_vec())
}
fn iter_from(starting_raw_key: Vec<u8>) -> Self::Iterator {
let prefix = G::prefix_hash();
let prefix = G::prefix_hash().to_vec();
Self::Iterator {
prefix,
previous_key: starting_raw_key,
@@ -404,11 +401,11 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
}
fn iter_keys() -> Self::KeyIterator {
Self::iter_keys_from(G::prefix_hash())
Self::iter_keys_from(G::prefix_hash().to_vec())
}
fn iter_keys_from(starting_raw_key: Vec<u8>) -> Self::KeyIterator {
let prefix = G::prefix_hash();
let prefix = G::prefix_hash().to_vec();
Self::KeyIterator {
prefix,
previous_key: starting_raw_key,
@@ -427,7 +424,7 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
}
fn translate<O: Decode, F: FnMut(K::Key, O) -> Option<V>>(mut f: F) {
let prefix = G::prefix_hash();
let prefix = G::prefix_hash().to_vec();
let mut previous_key = prefix.clone();
while let Some(next) =
sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))
@@ -537,7 +534,7 @@ mod test_iterators {
type NMap = self::frame_system::NMap<Runtime>;
// All map iterator
let prefix = NMap::prefix_hash();
let prefix = NMap::prefix_hash().to_vec();
unhashed::put(&key_before_prefix(prefix.clone()), &1u64);
unhashed::put(&key_after_prefix(prefix.clone()), &1u64);
@@ -594,7 +591,7 @@ mod test_iterators {
assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64));
// Translate
let prefix = NMap::prefix_hash();
let prefix = NMap::prefix_hash().to_vec();
unhashed::put(&key_before_prefix(prefix.clone()), &1u64);
unhashed::put(&key_after_prefix(prefix.clone()), &1u64);
@@ -25,14 +25,14 @@ use codec::{Decode, Encode, EncodeLike, FullCodec};
///
/// By default value is stored at:
/// ```nocompile
/// Twox128(module_prefix) ++ Twox128(storage_prefix)
/// Twox128(pallet_prefix) ++ Twox128(storage_prefix)
/// ```
pub trait StorageValue<T: FullCodec> {
/// The type that get/take returns.
type Query;
/// Module prefix. Used for generating final key.
fn module_prefix() -> &'static [u8];
/// Pallet prefix. Used for generating final key.
fn pallet_prefix() -> &'static [u8];
/// Storage prefix. Used for generating final key.
fn storage_prefix() -> &'static [u8];
@@ -44,9 +44,7 @@ pub trait StorageValue<T: FullCodec> {
fn from_query_to_optional_value(v: Self::Query) -> Option<T>;
/// Generate the full key used in top storage.
fn storage_value_final_key() -> [u8; 32] {
crate::storage::storage_prefix(Self::module_prefix(), Self::storage_prefix())
}
fn storage_value_final_key() -> [u8; 32];
}
impl<T: FullCodec, G: StorageValue<T>> storage::StorageValue<T> for G {
@@ -97,10 +95,6 @@ impl<T: FullCodec, G: StorageValue<T>> storage::StorageValue<T> for G {
}
}
fn kill() {
unhashed::kill(&Self::storage_value_final_key())
}
fn mutate<R, F: FnOnce(&mut G::Query) -> R>(f: F) -> R {
Self::try_mutate(|v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
}
@@ -142,6 +136,10 @@ impl<T: FullCodec, G: StorageValue<T>> storage::StorageValue<T> for G {
ret
}
fn kill() {
unhashed::kill(&Self::storage_value_final_key())
}
fn take() -> G::Query {
let key = Self::storage_value_final_key();
let value = unhashed::get(&key);
+20 -12
View File
@@ -191,7 +191,7 @@ pub trait StorageList<V: FullCodec> {
/// Append a single element.
///
/// Should not be called repeatedly; use `append_many` instead.
/// Should not be called repeatedly; use `append_many` instead.
/// Worst case linear `O(len)` with `len` being the number if elements in the list.
fn append_one<EncodeLikeValue>(item: EncodeLikeValue)
where
@@ -202,7 +202,7 @@ pub trait StorageList<V: FullCodec> {
/// Append many elements.
///
/// Should not be called repeatedly; use `appender` instead.
/// Should not be called repeatedly; use `appender` instead.
/// Worst case linear `O(len + items.count())` with `len` beings the number if elements in the
/// list.
fn append_many<EncodeLikeValue, I>(items: I)
@@ -1273,15 +1273,15 @@ impl<T> Iterator for ChildTriePrefixIterator<T> {
/// Trait for storage types that store all its value after a unique prefix.
pub trait StoragePrefixedContainer {
/// Module prefix. Used for generating final key.
fn module_prefix() -> &'static [u8];
/// Pallet prefix. Used for generating final key.
fn pallet_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] {
crate::storage::storage_prefix(Self::module_prefix(), Self::storage_prefix())
crate::storage::storage_prefix(Self::pallet_prefix(), Self::storage_prefix())
}
}
@@ -1289,18 +1289,18 @@ pub trait StoragePrefixedContainer {
///
/// By default the final prefix is:
/// ```nocompile
/// Twox128(module_prefix) ++ Twox128(storage_prefix)
/// Twox128(pallet_prefix) ++ Twox128(storage_prefix)
/// ```
pub trait StoragePrefixedMap<Value: FullCodec> {
/// Module prefix. Used for generating final key.
fn module_prefix() -> &'static [u8]; // TODO move to StoragePrefixedContainer
/// Pallet prefix. Used for generating final key.
fn pallet_prefix() -> &'static [u8]; // TODO move to StoragePrefixedContainer
/// Storage prefix. Used for generating final key.
fn storage_prefix() -> &'static [u8];
/// Final full prefix that prefixes all keys.
fn final_prefix() -> [u8; 32] {
crate::storage::storage_prefix(Self::module_prefix(), Self::storage_prefix())
crate::storage::storage_prefix(Self::pallet_prefix(), Self::storage_prefix())
}
/// Remove all values in the overlay and up to `limit` in the backend.
@@ -1624,7 +1624,7 @@ mod test {
TestExternalities::default().execute_with(|| {
struct MyStorage;
impl StoragePrefixedMap<u64> for MyStorage {
fn module_prefix() -> &'static [u8] {
fn pallet_prefix() -> &'static [u8] {
b"MyModule"
}
@@ -1701,7 +1701,7 @@ mod test {
impl generator::StorageValue<Digest> for Storage {
type Query = Digest;
fn module_prefix() -> &'static [u8] {
fn pallet_prefix() -> &'static [u8] {
b"MyModule"
}
@@ -1716,6 +1716,10 @@ mod test {
fn from_query_to_optional_value(v: Self::Query) -> Option<Digest> {
Some(v)
}
fn storage_value_final_key() -> [u8; 32] {
storage_prefix(Self::pallet_prefix(), Self::storage_prefix())
}
}
Storage::append(DigestItem::Other(Vec::new()));
@@ -1736,7 +1740,7 @@ mod test {
type Query = u64;
type Hasher = Twox64Concat;
fn module_prefix() -> &'static [u8] {
fn pallet_prefix() -> &'static [u8] {
b"MyModule"
}
@@ -1744,6 +1748,10 @@ mod test {
b"MyStorageMap"
}
fn prefix_hash() -> [u8; 32] {
storage_prefix(Self::pallet_prefix(), Self::storage_prefix())
}
fn from_optional_value_to_query(v: Option<u64>) -> Self::Query {
v.unwrap_or_default()
}
@@ -107,7 +107,7 @@ where
/// The prefix used to generate the key of the map.
pub fn map_storage_final_prefix() -> Vec<u8> {
use crate::storage::generator::StorageMap;
<Self as MapWrapper>::Map::prefix_hash()
<Self as MapWrapper>::Map::prefix_hash().to_vec()
}
/// Get the storage key used to fetch a value corresponding to a specific key.
@@ -104,7 +104,7 @@ where
/// The prefix used to generate the key of the map.
pub fn map_storage_final_prefix() -> Vec<u8> {
use crate::storage::generator::StorageNMap;
<Self as MapWrapper>::Map::prefix_hash()
<Self as MapWrapper>::Map::prefix_hash().to_vec()
}
/// Get the storage key used to fetch a value corresponding to a specific key.
@@ -117,12 +117,17 @@ where
type Query = QueryKind::Query;
type Hasher1 = Hasher1;
type Hasher2 = Hasher2;
fn module_prefix() -> &'static [u8] {
fn pallet_prefix() -> &'static [u8] {
Prefix::pallet_prefix().as_bytes()
}
fn storage_prefix() -> &'static [u8] {
Prefix::STORAGE_PREFIX.as_bytes()
}
fn prefix_hash() -> [u8; 32] {
Prefix::prefix_hash()
}
fn from_optional_value_to_query(v: Option<Value>) -> Self::Query {
QueryKind::from_optional_value_to_query(v)
}
@@ -145,8 +150,8 @@ where
OnEmpty: Get<QueryKind::Query> + 'static,
MaxValues: Get<Option<u32>>,
{
fn module_prefix() -> &'static [u8] {
<Self as crate::storage::generator::StorageDoubleMap<Key1, Key2, Value>>::module_prefix()
fn pallet_prefix() -> &'static [u8] {
<Self as crate::storage::generator::StorageDoubleMap<Key1, Key2, Value>>::pallet_prefix()
}
fn storage_prefix() -> &'static [u8] {
<Self as crate::storage::generator::StorageDoubleMap<Key1, Key2, Value>>::storage_prefix()
@@ -691,7 +696,7 @@ where
{
fn storage_info() -> Vec<StorageInfo> {
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
pallet_name: Self::pallet_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
@@ -722,7 +727,7 @@ where
{
fn partial_storage_info() -> Vec<StorageInfo> {
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
pallet_name: Self::pallet_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
@@ -83,12 +83,15 @@ where
{
type Query = QueryKind::Query;
type Hasher = Hasher;
fn module_prefix() -> &'static [u8] {
fn pallet_prefix() -> &'static [u8] {
Prefix::pallet_prefix().as_bytes()
}
fn storage_prefix() -> &'static [u8] {
Prefix::STORAGE_PREFIX.as_bytes()
}
fn prefix_hash() -> [u8; 32] {
Prefix::prefix_hash()
}
fn from_optional_value_to_query(v: Option<Value>) -> Self::Query {
QueryKind::from_optional_value_to_query(v)
}
@@ -108,8 +111,8 @@ where
OnEmpty: Get<QueryKind::Query> + 'static,
MaxValues: Get<Option<u32>>,
{
fn module_prefix() -> &'static [u8] {
<Self as crate::storage::generator::StorageMap<Key, Value>>::module_prefix()
fn pallet_prefix() -> &'static [u8] {
<Self as crate::storage::generator::StorageMap<Key, Value>>::pallet_prefix()
}
fn storage_prefix() -> &'static [u8] {
<Self as crate::storage::generator::StorageMap<Key, Value>>::storage_prefix()
@@ -469,7 +472,7 @@ where
{
fn storage_info() -> Vec<StorageInfo> {
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
pallet_name: Self::pallet_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
@@ -497,7 +500,7 @@ where
{
fn partial_storage_info() -> Vec<StorageInfo> {
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
pallet_name: Self::pallet_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
@@ -72,12 +72,15 @@ where
MaxValues: Get<Option<u32>>,
{
type Query = QueryKind::Query;
fn module_prefix() -> &'static [u8] {
fn pallet_prefix() -> &'static [u8] {
Prefix::pallet_prefix().as_bytes()
}
fn storage_prefix() -> &'static [u8] {
Prefix::STORAGE_PREFIX.as_bytes()
}
fn prefix_hash() -> [u8; 32] {
Prefix::prefix_hash()
}
fn from_optional_value_to_query(v: Option<Value>) -> Self::Query {
QueryKind::from_optional_value_to_query(v)
}
@@ -96,8 +99,8 @@ where
OnEmpty: Get<QueryKind::Query> + 'static,
MaxValues: Get<Option<u32>>,
{
fn module_prefix() -> &'static [u8] {
<Self as crate::storage::generator::StorageNMap<Key, Value>>::module_prefix()
fn pallet_prefix() -> &'static [u8] {
<Self as crate::storage::generator::StorageNMap<Key, Value>>::pallet_prefix()
}
fn storage_prefix() -> &'static [u8] {
<Self as crate::storage::generator::StorageNMap<Key, Value>>::storage_prefix()
@@ -581,7 +584,7 @@ where
{
fn storage_info() -> Vec<StorageInfo> {
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
pallet_name: Self::pallet_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
@@ -607,7 +610,7 @@ where
{
fn partial_storage_info() -> Vec<StorageInfo> {
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
pallet_name: Self::pallet_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
@@ -49,7 +49,7 @@ where
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static,
{
type Query = QueryKind::Query;
fn module_prefix() -> &'static [u8] {
fn pallet_prefix() -> &'static [u8] {
Prefix::pallet_prefix().as_bytes()
}
fn storage_prefix() -> &'static [u8] {
@@ -61,6 +61,9 @@ where
fn from_query_to_optional_value(v: Self::Query) -> Option<Value> {
QueryKind::from_query_to_optional_value(v)
}
fn storage_value_final_key() -> [u8; 32] {
Prefix::prefix_hash()
}
}
impl<Prefix, Value, QueryKind, OnEmpty> StorageValue<Prefix, Value, QueryKind, OnEmpty>
@@ -251,7 +254,7 @@ where
{
fn storage_info() -> Vec<StorageInfo> {
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
pallet_name: Self::pallet_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::hashed_key().to_vec(),
max_values: Some(1),
@@ -271,7 +274,7 @@ where
{
fn partial_storage_info() -> Vec<StorageInfo> {
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
pallet_name: Self::pallet_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::hashed_key().to_vec(),
max_values: Some(1),
@@ -112,7 +112,7 @@ fn verbatim_attribute() {
assert_eq!(1, Value::get().unwrap());
// The prefix is the one we declared above.
assert_eq!(&b"Test"[..], Value::module_prefix());
assert_eq!(&b"Test"[..], Value::pallet_prefix());
});
}
@@ -130,7 +130,7 @@ fn pallet_name_attribute() {
// The prefix is the pallet name. In this case the pallet name is `System` as declared in
// `construct_runtime!`.
assert_eq!(&b"System"[..], Value::<Runtime>::module_prefix());
assert_eq!(&b"System"[..], Value::<Runtime>::pallet_prefix());
});
}
@@ -154,7 +154,7 @@ fn dynamic_attribute() {
assert_eq!(1, Value::<Prefix>::get().unwrap());
// The prefix is the one we declared above.
assert_eq!(&b"Hello"[..], Value::<Prefix>::module_prefix());
assert_eq!(&b"Hello"[..], Value::<Prefix>::pallet_prefix());
});
}
@@ -166,13 +166,13 @@ fn storage_alias_guess() {
#[crate::storage_alias]
pub type Value = StorageValue<Test, u32>;
assert_eq!(&b"Test"[..], Value::module_prefix());
assert_eq!(&b"Test"[..], Value::pallet_prefix());
// The macro will use the pallet name as prefix.
#[crate::storage_alias]
pub type PalletValue<T: Config> = StorageValue<Pallet<T>, u32>;
assert_eq!(&b"System"[..], PalletValue::<Runtime>::module_prefix());
assert_eq!(&b"System"[..], PalletValue::<Runtime>::pallet_prefix());
});
}
@@ -31,6 +31,8 @@ pub trait PalletInfo {
fn index<P: 'static>() -> Option<usize>;
/// Convert the given pallet `P` into its name as configured in the runtime.
fn name<P: 'static>() -> Option<&'static str>;
/// The two128 hash of name.
fn name_hash<P: 'static>() -> Option<[u8; 16]>;
/// Convert the given pallet `P` into its Rust module name as used in `construct_runtime!`.
fn module_name<P: 'static>() -> Option<&'static str>;
/// Convert the given pallet `P` into its containing crate version.
@@ -59,6 +61,8 @@ pub trait PalletInfoAccess {
fn index() -> usize;
/// Name of the pallet as configured in the runtime.
fn name() -> &'static str;
/// Two128 hash of name.
fn name_hash() -> [u8; 16];
/// Name of the Rust module containing the pallet.
fn module_name() -> &'static str;
/// Version of the crate containing the pallet.
@@ -281,6 +285,7 @@ pub trait GetStorageVersion {
#[cfg(test)]
mod tests {
use super::*;
use sp_core::twox_128;
struct Pallet1;
impl PalletInfoAccess for Pallet1 {
@@ -290,6 +295,9 @@ mod tests {
fn name() -> &'static str {
"Pallet1"
}
fn name_hash() -> [u8; 16] {
twox_128(Self::name().as_bytes())
}
fn module_name() -> &'static str {
"pallet1"
}
@@ -305,6 +313,11 @@ mod tests {
fn name() -> &'static str {
"Pallet2"
}
fn name_hash() -> [u8; 16] {
twox_128(Self::name().as_bytes())
}
fn module_name() -> &'static str {
"pallet2"
}
@@ -61,8 +61,35 @@ pub trait StorageInstance {
/// Prefix of a pallet to isolate it from other pallets.
fn pallet_prefix() -> &'static str;
/// Return the prefix hash of pallet instance.
///
/// NOTE: This hash must be `twox_128(pallet_prefix())`.
/// Should not impl this function by hand. Only use the default or macro generated impls.
fn pallet_prefix_hash() -> [u8; 16] {
sp_io::hashing::twox_128(Self::pallet_prefix().as_bytes())
}
/// Prefix given to a storage to isolate from other storages in the pallet.
const STORAGE_PREFIX: &'static str;
/// Return the prefix hash of storage instance.
///
/// NOTE: This hash must be `twox_128(STORAGE_PREFIX)`.
fn storage_prefix_hash() -> [u8; 16] {
sp_io::hashing::twox_128(Self::STORAGE_PREFIX.as_bytes())
}
/// Return the prefix hash of instance.
///
/// NOTE: This hash must be `twox_128(pallet_prefix())++twox_128(STORAGE_PREFIX)`.
/// Should not impl this function by hand. Only use the default or macro generated impls.
fn prefix_hash() -> [u8; 32] {
let mut final_key = [0u8; 32];
final_key[..16].copy_from_slice(&Self::pallet_prefix_hash());
final_key[16..].copy_from_slice(&Self::storage_prefix_hash());
final_key
}
}
/// Metadata about storage from the runtime.
+1 -1
View File
@@ -489,7 +489,7 @@ fn test_last_reward_migration() {
s.top = data.into_iter().collect();
sp_io::TestExternalities::new(s).execute_with(|| {
let module = pallet_tips::Tips::<Test>::module_prefix();
let module = pallet_tips::Tips::<Test>::pallet_prefix();
let item = pallet_tips::Tips::<Test>::storage_prefix();
Tips::migrate_retract_tip_for_tip_new(module, item);
+1 -1
View File
@@ -205,7 +205,7 @@ impl<T: Config> Pallet<T> {
/// Ensure that this call can be paused.
pub fn ensure_can_pause(full_name: &RuntimeCallNameOf<T>) -> Result<(), Error<T>> {
// SAFETY: The `TxPause` pallet can never pause itself.
if full_name.0.as_ref() == <Self as PalletInfoAccess>::name().as_bytes().to_vec() {
if full_name.0.as_slice() == <Self as PalletInfoAccess>::name().as_bytes() {
return Err(Error::<T>::Unpausable)
}