diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 8e40573916..fbb690a622 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -78,7 +78,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to equal spec_version. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 195, + spec_version: 196, impl_version: 196, apis: RUNTIME_API_VERSIONS, }; diff --git a/substrate/frame/executive/src/lib.rs b/substrate/frame/executive/src/lib.rs index f6b50143a7..d160bd7bdd 100644 --- a/substrate/frame/executive/src/lib.rs +++ b/substrate/frame/executive/src/lib.rs @@ -525,7 +525,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("f0d1d66255c2e5b40580eb8b93ddbe732491478487f85e358e1d167d369e398e").into(), + state_root: hex!("c6b01b27df520ba23adb96e7fc032acb7c586ba1b477c6282de43184111f2091").into(), extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), digest: Digest { logs: vec![], }, }, diff --git a/substrate/frame/metadata/src/lib.rs b/substrate/frame/metadata/src/lib.rs index d85a6837fc..113273be02 100644 --- a/substrate/frame/metadata/src/lib.rs +++ b/substrate/frame/metadata/src/lib.rs @@ -342,8 +342,10 @@ pub enum RuntimeMetadata { V6(RuntimeMetadataDeprecated), /// Version 7 for runtime metadata. No longer used. V7(RuntimeMetadataDeprecated), - /// Version 8 for runtime metadata. - V8(RuntimeMetadataV8), + /// Version 8 for runtime metadata. No longer used. + V8(RuntimeMetadataDeprecated), + /// Version 9 for runtime metadata. + V9(RuntimeMetadataV9), } /// Enum that should fail. @@ -367,12 +369,12 @@ impl Decode for RuntimeMetadataDeprecated { /// The metadata of a runtime. #[derive(Eq, Encode, PartialEq, RuntimeDebug)] #[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub struct RuntimeMetadataV8 { +pub struct RuntimeMetadataV9 { pub modules: DecodeDifferentArray, } /// The latest version of the metadata. -pub type RuntimeMetadataLastVersion = RuntimeMetadataV8; +pub type RuntimeMetadataLastVersion = RuntimeMetadataV9; /// All metadata about an runtime module. #[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] @@ -397,6 +399,6 @@ impl Into for RuntimeMetadataPrefixed { impl Into for RuntimeMetadataLastVersion { fn into(self) -> RuntimeMetadataPrefixed { - RuntimeMetadataPrefixed(META_RESERVED, RuntimeMetadata::V8(self)) + RuntimeMetadataPrefixed(META_RESERVED, RuntimeMetadata::V9(self)) } } diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 8f23142bea..506e55fa17 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -56,7 +56,15 @@ use proc_macro::TokenStream; /// * Value: `Foo: type`: Implements the /// [`StorageValue`](../frame_support/storage/trait.StorageValue.html) trait using the /// [`StorageValue generator`](../frame_support/storage/generator/trait.StorageValue.html). -/// The generator `unhashed_key` is `$module_prefix ++ " " ++ $storage_name` +/// +/// The generator is implemented with: +/// * `module_prefix`: module_prefix +/// * `storage_prefix`: storage_name +/// +/// Thus the storage value is finally stored at: +/// ```nocompile +/// Twox128(module_prefix) ++ Twox128(storage_prefix) +/// ``` /// /// * Map: `Foo: map hasher($hash) type => type`: Implements the /// [`StorageMap`](../frame_support/storage/trait.StorageMap.html) trait using the @@ -69,9 +77,15 @@ use proc_macro::TokenStream; /// with care, see generator documentation. /// /// The generator is implemented with: -/// * `prefix`: `$module_prefix ++ " " ++ $storage_name` +/// * `module_prefix`: $module_prefix +/// * `storage_prefix`: storage_name /// * `Hasher`: $hash /// +/// Thus the keys are stored at: +/// ```nocompile +/// twox128(module_prefix) ++ twox128(storage_prefix) ++ hasher(encode(key)) +/// ``` +/// /// * Linked map: `Foo: linked_map hasher($hash) type => type`: Implements the /// [`StorageLinkedMap`](../frame_support/storage/trait.StorageLinkedMap.html) trait using the /// [`StorageLinkedMap generator`](../frame_support/storage/generator/trait.StorageLinkedMap.html). @@ -82,15 +96,25 @@ use proc_macro::TokenStream; /// `hasher($hash)` is optional and its default is `blake2_256`. One should use another hasher /// with care, see generator documentation. /// -/// The generator is implemented with: -/// * `prefix`: `$module_prefix ++ " " ++ $storage_name` -/// * `head_key`: `"head of " ++ $module_prefix ++ " " ++ $storage_name` -/// * `Hasher`: $hash -/// /// All key formatting logic can be accessed in a type-agnostic format via the /// [`KeyFormat`](../srml_support/storage/generator/trait.KeyFormat.html) trait, which /// is implemented for the storage linked map type as well. /// +/// The generator key format is implemented with: +/// * `module_prefix`: $module_prefix +/// * `storage_prefix`: storage_name +/// * `head_prefix`: `"HeadOf" ++ storage_name` +/// * `Hasher`: $hash +/// +/// Thus the keys are stored at: +/// ```nocompile +/// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher(encode(key)) +/// ``` +/// and head is stored at: +/// ```nocompile +/// Twox128(module_prefix) ++ Twox128(head_prefix) +/// ``` +/// /// * Double map: `Foo: double_map hasher($hash1) u32, $hash2(u32) => u32`: Implements the /// [`StorageDoubleMap`](../frame_support/storage/trait.StorageDoubleMap.html) trait using the /// [`StorageDoubleMap generator`](../frame_support/storage/generator/trait.StorageDoubleMap.html). @@ -111,10 +135,16 @@ use proc_macro::TokenStream; /// Otherwise, other items in storage with the same first key can be compromised. /// /// The generator is implemented with: -/// * `key1_prefix`: `$module_prefix ++ " " ++ $storage_name` +/// * `module_prefix`: $module_prefix +/// * `storage_prefix`: storage_name /// * `Hasher1`: $hash1 /// * `Hasher2`: $hash2 /// +/// Thus keys are stored at: +/// ```nocompile +/// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher1(encode(key1)) ++ Hasher2(encode(key2)) +/// ``` +/// /// Supported hashers (ordered from least to best security): /// /// * `twox_64_concat` - TwoX with 64bit + key concatenated. diff --git a/substrate/frame/support/procedural/src/storage/instance_trait.rs b/substrate/frame/support/procedural/src/storage/instance_trait.rs index 1a7add89a4..abc56092e3 100644 --- a/substrate/frame/support/procedural/src/storage/instance_trait.rs +++ b/substrate/frame/support/procedural/src/storage/instance_trait.rs @@ -19,24 +19,12 @@ use proc_macro2::{TokenStream, Span}; use quote::quote; -use super::{DeclStorageDefExt, StorageLineTypeDef}; +use super::DeclStorageDefExt; const NUMBER_OF_INSTANCE: usize = 16; -const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance"; +pub(crate) const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance"; pub(crate) const DEFAULT_INSTANTIABLE_TRAIT_NAME: &str = "__GeneratedInstantiable"; -// prefix for consts in trait Instance -pub(crate) const PREFIX_FOR: &str = "PREFIX_FOR_"; -pub(crate) const HEAD_KEY_FOR: &str = "HEAD_KEY_FOR_"; - -// Used to generate the const: -// `const $name: &'static str = $value_prefix ++ instance_prefix ++ $value_suffix` -struct InstanceConstDef { - name: syn::Ident, - value_prefix: String, - value_suffix: String, -} - // Used to generate an instance implementation. struct InstanceDef { prefix: String, @@ -47,33 +35,7 @@ struct InstanceDef { pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream { let mut impls = TokenStream::new(); - let mut const_defs = vec![]; - - for line in def.storage_lines.iter() { - let storage_prefix = format!("{} {}", def.crate_name, line.name); - - let const_name = syn::Ident::new( - &format!("{}{}", PREFIX_FOR, line.name.to_string()), proc_macro2::Span::call_site() - ); - const_defs.push(InstanceConstDef { - name: const_name, - value_prefix: String::new(), - value_suffix: storage_prefix.clone(), - }); - - if let StorageLineTypeDef::LinkedMap(_) = line.storage_type { - let const_name = syn::Ident::new( - &format!("{}{}", HEAD_KEY_FOR, line.name.to_string()), proc_macro2::Span::call_site() - ); - const_defs.push(InstanceConstDef { - name: const_name, - value_prefix: "head of ".into(), - value_suffix: storage_prefix, - }); - } - } - - impls.extend(create_instance_trait(&const_defs, def)); + impls.extend(create_instance_trait(def)); // Implementation of instances. if let Some(module_instance) = &def.module_instance { @@ -95,7 +57,7 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre ); for instance_def in instance_defs { - impls.extend(create_and_impl_instance_struct(scrate, &instance_def, &const_defs, def)); + impls.extend(create_and_impl_instance_struct(scrate, &instance_def, def)); } } @@ -116,27 +78,18 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre instance_struct: inherent_instance, doc: quote!(#[doc(hidden)]), }; - impls.extend(create_and_impl_instance_struct(scrate, &instance_def, &const_defs, def)); + impls.extend(create_and_impl_instance_struct(scrate, &instance_def, def)); } impls } fn create_instance_trait( - const_defs: &[InstanceConstDef], def: &DeclStorageDefExt, ) -> TokenStream { let instance_trait = def.module_instance.as_ref().map(|i| i.instance_trait.clone()) .unwrap_or_else(|| syn::Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site())); - let mut const_impls = TokenStream::new(); - for const_def in const_defs { - let const_name = &const_def.name; - const_impls.extend(quote! { - const #const_name: &'static str; - }); - } - let optional_hide = if def.module_instance.is_some() { quote!() } else { @@ -151,7 +104,6 @@ fn create_instance_trait( pub trait #instance_trait: 'static { /// The prefix used by any storage entry of an instance. const PREFIX: &'static str; - #const_impls } } } @@ -159,22 +111,8 @@ fn create_instance_trait( fn create_and_impl_instance_struct( scrate: &TokenStream, instance_def: &InstanceDef, - const_defs: &[InstanceConstDef], def: &DeclStorageDefExt, ) -> TokenStream { - let mut const_impls = TokenStream::new(); - - for const_def in const_defs { - let const_value = format!( - "{}{}{}", const_def.value_prefix, instance_def.prefix, const_def.value_suffix - ); - let const_name = &const_def.name; - - const_impls.extend(quote! { - const #const_name: &'static str = #const_value; - }); - } - let instance_trait = def.module_instance.as_ref().map(|i| i.instance_trait.clone()) .unwrap_or_else(|| syn::Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site())); @@ -194,7 +132,6 @@ fn create_and_impl_instance_struct( pub struct #instance_struct; impl #instance_trait for #instance_struct { const PREFIX: &'static str = #prefix; - #const_impls } } } diff --git a/substrate/frame/support/procedural/src/storage/storage_struct.rs b/substrate/frame/support/procedural/src/storage/storage_struct.rs index 5267876a44..017e6cf2ff 100644 --- a/substrate/frame/support/procedural/src/storage/storage_struct.rs +++ b/substrate/frame/support/procedural/src/storage/storage_struct.rs @@ -16,11 +16,11 @@ //! Implementation of storage structures and implementation of storage traits on them. -use proc_macro2::TokenStream; +use proc_macro2::{TokenStream, Ident, Span}; use quote::quote; use super::{ DeclStorageDefExt, StorageLineTypeDef, - instance_trait::{PREFIX_FOR, HEAD_KEY_FOR}, + instance_trait::INHERENT_INSTANCE_NAME, }; fn from_optional_value_to_query(is_option: bool, default: &Option) -> TokenStream { @@ -78,17 +78,14 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre let from_optional_value_to_query = from_optional_value_to_query(line.is_option, &line.default_value); - let final_prefix = if let Some(instance) = def.module_instance.as_ref() { - let instance = &instance.instance_generic; - let const_name = syn::Ident::new( - &format!("{}{}", PREFIX_FOR, line.name.to_string()), proc_macro2::Span::call_site() - ); - quote!( #instance::#const_name.as_bytes() ) + // Contains accessor to instance, used to get prefixes + let instance_or_inherent = if let Some(instance) = def.module_instance.as_ref() { + instance.instance_generic.clone() } else { - let prefix = format!("{} {}", def.crate_name, line.name); - quote!( #prefix.as_bytes() ) + Ident::new(INHERENT_INSTANCE_NAME, Span::call_site()) }; + let storage_name_str = syn::LitStr::new(&line.name.to_string(), line.name.span()); let storage_generator_trait = &line.storage_generator_trait; let storage_struct = &line.storage_struct; @@ -104,8 +101,12 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre { type Query = #query_type; - fn unhashed_key() -> &'static [u8] { - #final_prefix + fn module_prefix() -> &'static [u8] { + #instance_or_inherent::PREFIX.as_bytes() + } + + fn storage_prefix() -> &'static [u8] { + #storage_name_str.as_bytes() } fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { @@ -127,8 +128,12 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre type Query = #query_type; type Hasher = #scrate::#hasher; - fn prefix() -> &'static [u8] { - #final_prefix + fn module_prefix() -> &'static [u8] { + #instance_or_inherent::PREFIX.as_bytes() + } + + fn storage_prefix() -> &'static [u8] { + #storage_name_str.as_bytes() } fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { @@ -144,30 +149,18 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre StorageLineTypeDef::LinkedMap(map) => { let hasher = map.hasher.to_storage_hasher_struct(); - // make sure to use different prefix for head and elements. - let head_key = if let Some(instance) = def.module_instance.as_ref() { - let instance = &instance.instance_generic; - let const_name = syn::Ident::new( - &format!("{}{}", HEAD_KEY_FOR, line.name.to_string()), proc_macro2::Span::call_site() - ); - quote!( #instance::#const_name.as_bytes() ) - } else { - let prefix = format!("head of {} {}", def.crate_name, line.name); - quote!( #prefix.as_bytes() ) - }; + let head_prefix_str = syn::LitStr::new( + &format!("HeadOf{}", line.name.to_string()), + line.name.span(), + ); quote!( impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct #optional_storage_where_clause { type Query = #query_type; - type Hasher = #scrate::#hasher; type KeyFormat = Self; - fn prefix() -> &'static [u8] { - #final_prefix - } - fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { #from_optional_value_to_query } @@ -180,8 +173,16 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre impl<#impl_trait> #scrate::storage::generator::LinkedMapKeyFormat for #storage_struct { type Hasher = #scrate::#hasher; - fn head_key() -> &'static [u8] { - #head_key + fn module_prefix() -> &'static [u8] { + #instance_or_inherent::PREFIX.as_bytes() + } + + fn storage_prefix() -> &'static [u8] { + #storage_name_str.as_bytes() + } + + fn head_prefix() -> &'static [u8] { + #head_prefix_str.as_bytes() } } ) @@ -199,8 +200,12 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre type Hasher2 = #scrate::#hasher2; - fn key1_prefix() -> &'static [u8] { - #final_prefix + fn module_prefix() -> &'static [u8] { + #instance_or_inherent::PREFIX.as_bytes() + } + + fn storage_prefix() -> &'static [u8] { + #storage_name_str.as_bytes() } fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { diff --git a/substrate/frame/support/src/storage/generator/double_map.rs b/substrate/frame/support/src/storage/generator/double_map.rs index 072b530e4c..28378034b2 100644 --- a/substrate/frame/support/src/storage/generator/double_map.rs +++ b/substrate/frame/support/src/storage/generator/double_map.rs @@ -17,7 +17,7 @@ use rstd::prelude::*; use rstd::borrow::Borrow; use codec::{Ref, FullCodec, FullEncode, Encode, EncodeLike, EncodeAppend}; -use crate::{storage::{self, unhashed}, hash::StorageHasher}; +use crate::{storage::{self, unhashed}, hash::{StorageHasher, Twox128}}; /// Generator for `StorageDoubleMap` used by `decl_storage`. /// @@ -29,7 +29,7 @@ use crate::{storage::{self, unhashed}, hash::StorageHasher}; /// /// Thus value for (key1, key2) is stored at: /// ```nocompile -/// Hasher1(key1_prefix ++ key1) ++ Hasher2(key2) +/// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher1(encode(key1)) ++ Hasher2(encode(key2)) /// ``` /// /// # Warning @@ -49,8 +49,11 @@ pub trait StorageDoubleMap { /// Hasher for the second key. type Hasher2: StorageHasher; - /// Get the prefix for first key. - fn key1_prefix() -> &'static [u8]; + /// Module prefix. Used for generating final key. + fn module_prefix() -> &'static [u8]; + + /// Storage prefix. Used for generating final key. + fn storage_prefix() -> &'static [u8]; /// Convert an optional value retrieved from storage to the type queried. fn from_optional_value_to_query(v: Option) -> Self::Query; @@ -59,13 +62,23 @@ pub trait StorageDoubleMap { fn from_query_to_optional_value(v: Self::Query) -> Option; /// Generate the first part of the key used in top storage. - fn storage_double_map_final_key1(k1: KArg1) -> ::Output + fn storage_double_map_final_key1(k1: KArg1) -> Vec where KArg1: EncodeLike, { - let mut final_key1 = Self::key1_prefix().to_vec(); - k1.encode_to(&mut final_key1); - Self::Hasher1::hash(&final_key1) + let module_prefix_hashed = Twox128::hash(Self::module_prefix()); + let storage_prefix_hashed = Twox128::hash(Self::storage_prefix()); + let key_hashed = k1.borrow().using_encoded(Self::Hasher1::hash); + + let mut final_key = Vec::with_capacity( + module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len() + ); + + final_key.extend_from_slice(&module_prefix_hashed[..]); + final_key.extend_from_slice(&storage_prefix_hashed[..]); + final_key.extend_from_slice(key_hashed.as_ref()); + + final_key } /// Generate the full key used in top storage. @@ -74,7 +87,7 @@ pub trait StorageDoubleMap { KArg1: EncodeLike, KArg2: EncodeLike, { - let mut final_key = Self::storage_double_map_final_key1(k1).as_ref().to_vec(); + let mut final_key = Self::storage_double_map_final_key1(k1); final_key.extend_from_slice(k2.using_encoded(Self::Hasher2::hash).as_ref()); final_key } diff --git a/substrate/frame/support/src/storage/generator/linked_map.rs b/substrate/frame/support/src/storage/generator/linked_map.rs index cf40349699..fb0603fce7 100644 --- a/substrate/frame/support/src/storage/generator/linked_map.rs +++ b/substrate/frame/support/src/storage/generator/linked_map.rs @@ -15,22 +15,52 @@ // along with Substrate. If not, see . use codec::{FullCodec, Encode, Decode, EncodeLike, Ref}; -use crate::{storage::{self, unhashed}, hash::StorageHasher, traits::Len}; -use rstd::marker::PhantomData; +use crate::{storage::{self, unhashed}, hash::{StorageHasher, Twox128}, traits::Len}; +use rstd::{prelude::*, marker::PhantomData}; /// Generator for `StorageLinkedMap` used by `decl_storage`. /// -/// # Mapping of keys to a storage path +/// By default final key generation rely on `KeyFormat`. +pub trait StorageLinkedMap { + /// The type that get/take returns. + type Query; + + /// The family of key formats used for this map. + type KeyFormat: KeyFormat; + + /// Convert an optional value retrieved from storage to the type queried. + fn from_optional_value_to_query(v: Option) -> Self::Query; + + /// Convert a query to an optional value into storage. + fn from_query_to_optional_value(v: Self::Query) -> Option; + + /// Generate the full key used in top storage. + fn storage_linked_map_final_key(key: KeyArg) -> Vec + where + KeyArg: EncodeLike, + { + ::storage_linked_map_final_key::(&key) + } + + /// Generate the hashed key for head + fn storage_linked_map_final_head_key() -> Vec { + ::storage_linked_map_final_head_key() + } +} + +/// A type-abstracted key format used for a family of linked-map types. +/// +/// # Default mapping of keys to a storage path /// /// The key for the head of the map is stored at one fixed path: /// ```nocompile -/// Hasher(head_key) +/// Twox128(module_prefix) ++ Twox128(head_prefix) /// ``` /// /// For each key, the value stored under that key is appended with a /// [`Linkage`](struct.Linkage.html) (which hold previous and next key) at the path: /// ```nocompile -/// Hasher(prefix ++ key) +/// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher(encode(key)) /// ``` /// /// Enumeration is done by getting the head of the linked map and then iterating getting the @@ -40,66 +70,45 @@ use rstd::marker::PhantomData; /// /// If the keys are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as /// `blake2_256` must be used. Otherwise, other values in storage can be compromised. -pub trait StorageLinkedMap { - /// The type that get/take returns. - type Query; - - /// Hasher used to insert into storage. - type Hasher: StorageHasher; - - /// The family of key formats used for this map. - type KeyFormat: KeyFormat; - - /// Prefix used to prepend each key. - fn prefix() -> &'static [u8]; - - /// The head key of the linked-map. - fn head_key() -> &'static [u8] { - ::head_key() - } - - /// Convert an optional value retrieved from storage to the type queried. - fn from_optional_value_to_query(v: Option) -> Self::Query; - - /// Convert a query to an optional value into storage. - fn from_query_to_optional_value(v: Self::Query) -> Option; - - /// Generate the full key used in top storage. - fn storage_linked_map_final_key(key: KeyArg) -> ::Output - where - KeyArg: EncodeLike, - { - ::storage_linked_map_final_key::(Self::prefix(), &key) - } - - /// Generate the hashed key for head - fn storage_linked_map_final_head_key() -> ::Output { - ::storage_linked_map_final_head_key() - } -} - -/// A type-abstracted key format used for a family of linked-map types. pub trait KeyFormat { + /// Hasher. Used for generating final key and final head key. type Hasher: StorageHasher; - /// Key used to store linked map head. - fn head_key() -> &'static [u8]; + /// Module prefix. Used for generating final key. + fn module_prefix() -> &'static [u8]; + + /// Storage prefix. Used for generating final key. + fn storage_prefix() -> &'static [u8]; + + /// Storage prefix. Used for generating final head key. + fn head_prefix() -> &'static [u8]; /// Generate the full key used in top storage. - fn storage_linked_map_final_key(prefix: &[u8], key: &K) - -> ::Output + fn storage_linked_map_final_key(key: &K) -> Vec where K: Encode, { - let mut final_key = prefix.to_vec(); - key.encode_to(&mut final_key); - ::hash(&final_key) + let module_prefix_hashed = Twox128::hash(Self::module_prefix()); + let storage_prefix_hashed = Twox128::hash(Self::storage_prefix()); + let key_hashed = key.using_encoded(Self::Hasher::hash); + + let mut final_key = Vec::with_capacity( + module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len() + ); + + final_key.extend_from_slice(&module_prefix_hashed[..]); + final_key.extend_from_slice(&storage_prefix_hashed[..]); + final_key.extend_from_slice(key_hashed.as_ref()); + + final_key } - fn storage_linked_map_final_head_key() - -> ::Output - { - ::hash(Self::head_key()) + /// Generate the full key used in top storage to store the head of the linked map. + fn storage_linked_map_final_head_key() -> Vec { + [ + Twox128::hash(Self::module_prefix()), + Twox128::hash(Self::head_prefix()), + ].concat() } } @@ -135,17 +144,15 @@ struct EncodeLikeLinkage, NKey: EncodeLike, Key: Enco /// A key-value pair iterator for enumerable map. pub struct Enumerator { next: Option, - prefix: &'static [u8], _phantom: PhantomData<(V, F)>, } impl Enumerator { /// Create an explicit enumerator for testing. #[cfg(test)] - pub fn from_head(head: K, prefix: &'static [u8]) -> Self { + pub fn from_head(head: K) -> Self { Enumerator { next: Some(head), - prefix, _phantom: Default::default(), } } @@ -163,15 +170,15 @@ where let next = self.next.take()?; let (val, linkage): (V, Linkage) = { - let next_full_key = F::storage_linked_map_final_key(self.prefix, &next); + let next_full_key = F::storage_linked_map_final_key(&next); match read_with_linkage::(next_full_key.as_ref()) { Some(value) => value, None => { // TODO #3700: error should be handleable. runtime_print!( - "ERROR: Corrupted state: linked map head_key={:?}: \ + "ERROR: Corrupted state: linked map {:?}{:?}: \ next value doesn't exist at {:?}", - F::head_key(), next_full_key.as_ref(), + F::module_prefix(), F::storage_prefix(), next_full_key, ); return None } @@ -187,18 +194,14 @@ where /// /// Takes care of updating previous and next elements points /// as well as updates head if the element is first or last. -fn remove_linkage(linkage: Linkage, prefix: &[u8]) +fn remove_linkage(linkage: Linkage) where K: FullCodec, V: FullCodec, F: KeyFormat, { - let next_key = linkage.next.as_ref() - .map(|k| F::storage_linked_map_final_key(prefix, k)) - .map(|x| x.as_ref().to_vec()); - let prev_key = linkage.previous.as_ref() - .map(|k| F::storage_linked_map_final_key(prefix, k)) - .map(|x| x.as_ref().to_vec()); + let next_key = linkage.next.as_ref().map(|k| F::storage_linked_map_final_key(k)); + let prev_key = linkage.previous.as_ref().map(|k| F::storage_linked_map_final_key(k)); if let Some(prev_key) = prev_key { // Retrieve previous element and update `next` @@ -208,9 +211,9 @@ where } else { // TODO #3700: error should be handleable. runtime_print!( - "ERROR: Corrupted state: linked map head_key={:?}: \ + "ERROR: Corrupted state: linked map {:?}{:?}: \ previous value doesn't exist at {:?}", - F::head_key(), prev_key, + F::module_prefix(), F::storage_prefix(), prev_key, ); } } else { @@ -225,9 +228,9 @@ where } else { // TODO #3700: error should be handleable. runtime_print!( - "ERROR: Corrupted state: linked map head_key={:?}: \ + "ERROR: Corrupted state: linked map {:?}{:?}: \ next value doesn't exist at {:?}", - F::head_key(), next_key, + F::module_prefix(), F::storage_prefix(), next_key, ); } } @@ -245,7 +248,7 @@ where /// Generate linkage for newly inserted element. /// /// Takes care of updating head and previous head's pointer. -pub(super) fn new_head_linkage(key: KeyArg, prefix: &[u8]) -> Linkage +pub(super) fn new_head_linkage(key: KeyArg) -> Linkage where KeyArg: EncodeLike, K: FullCodec, @@ -255,7 +258,7 @@ where if let Some(head) = read_head::() { // update previous head predecessor { - let head_key = F::storage_linked_map_final_key(prefix, &head); + let head_key = F::storage_linked_map_final_key(&head); if let Some((data, linkage)) = read_with_linkage::(head_key.as_ref()) { let new_linkage = EncodeLikeLinkage::<_, _, K> { previous: Some(Ref::from(&key)), @@ -266,9 +269,9 @@ where } else { // TODO #3700: error should be handleable. runtime_print!( - "ERROR: Corrupted state: linked map head_key={:?}: \ + "ERROR: Corrupted state: linked map {:?}{:?}: \ head value doesn't exist at {:?}", - F::head_key(), head_key.as_ref(), + F::module_prefix(), F::storage_prefix(), head_key, ); // Thus we consider we are first - update the head and produce empty linkage @@ -333,7 +336,6 @@ where } fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2) { - let prefix = Self::prefix(); let final_key1 = Self::storage_linked_map_final_key(Ref::from(&key1)); let final_key2 = Self::storage_linked_map_final_key(Ref::from(&key2)); let full_value_1 = read_with_linkage::(final_key1.as_ref()); @@ -348,13 +350,13 @@ where // Remove key and insert the new one. (Some((value, _linkage)), None) => { Self::remove(key1); - let linkage = new_head_linkage::<_, _, V, G::KeyFormat>(key2, prefix); + let linkage = new_head_linkage::<_, _, V, G::KeyFormat>(key2); unhashed::put(final_key2.as_ref(), &(value, linkage)); } // Remove key and insert the new one. (None, Some((value, _linkage))) => { Self::remove(key2); - let linkage = new_head_linkage::<_, _, V, G::KeyFormat>(key1, prefix); + let linkage = new_head_linkage::<_, _, V, G::KeyFormat>(key1); unhashed::put(final_key1.as_ref(), &(value, linkage)); } // No-op. @@ -368,7 +370,7 @@ where // overwrite but reuse existing linkage Some((_data, linkage)) => linkage, // create new linkage - None => new_head_linkage::<_, _, V, G::KeyFormat>(key, Self::prefix()), + None => new_head_linkage::<_, _, V, G::KeyFormat>(key), }; unhashed::put(final_key.as_ref(), &(val, linkage)) } @@ -398,7 +400,7 @@ where let full_value: Option<(V, Linkage)> = unhashed::take(final_key.as_ref()); let value = full_value.map(|(data, linkage)| { - remove_linkage::(linkage, Self::prefix()); + remove_linkage::(linkage); data }); @@ -408,7 +410,6 @@ where fn enumerate() -> Self::Enumerator { Enumerator::<_, _, G::KeyFormat> { next: read_head::<_, G::KeyFormat>(), - prefix: Self::prefix(), _phantom: Default::default(), } } @@ -436,7 +437,6 @@ where where K2: FullCodec + Clone, V2: Decode, TK: Fn(K2) -> K, TV: Fn(V2) -> V { let head_key = read_head::().ok_or(None)?; - let prefix = G::prefix(); let mut last_key = None; let mut current_key = head_key.clone(); @@ -451,7 +451,7 @@ where }; loop { - let old_raw_key = G::KeyFormat::storage_linked_map_final_key(prefix, ¤t_key); + let old_raw_key = G::KeyFormat::storage_linked_map_final_key(¤t_key); let x = unhashed::take(old_raw_key.as_ref()); let (val, linkage): (V2, Linkage) = match x { Some(v) => v, diff --git a/substrate/frame/support/src/storage/generator/map.rs b/substrate/frame/support/src/storage/generator/map.rs index 3c3edac28a..926fe8748d 100644 --- a/substrate/frame/support/src/storage/generator/map.rs +++ b/substrate/frame/support/src/storage/generator/map.rs @@ -18,13 +18,13 @@ use rstd::prelude::*; use rstd::borrow::Borrow; use codec::{FullCodec, FullEncode, Encode, EncodeLike, Ref, EncodeAppend}; -use crate::{storage::{self, unhashed}, hash::StorageHasher, traits::Len}; +use crate::{storage::{self, unhashed}, hash::{StorageHasher, Twox128}, traits::Len}; /// Generator for `StorageMap` used by `decl_storage`. /// -/// For each key value is stored at: +/// By default each key value is stored at: /// ```nocompile -/// Hasher(prefix ++ key) +/// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher(encode(key)) /// ``` /// /// # Warning @@ -35,11 +35,14 @@ pub trait StorageMap { /// The type that get/take returns. type Query; - /// Hasher used to insert into storage. + /// Hasher. Used for generating final key. type Hasher: StorageHasher; - /// Prefix used to prepend each key. - fn prefix() -> &'static [u8]; + /// Module prefix. Used for generating final key. + fn module_prefix() -> &'static [u8]; + + /// Storage prefix. Used for generating final key. + fn storage_prefix() -> &'static [u8]; /// Convert an optional value retrieved from storage to the type queried. fn from_optional_value_to_query(v: Option) -> Self::Query; @@ -48,13 +51,23 @@ pub trait StorageMap { fn from_query_to_optional_value(v: Self::Query) -> Option; /// Generate the full key used in top storage. - fn storage_map_final_key(key: KeyArg) -> ::Output + fn storage_map_final_key(key: KeyArg) -> Vec where KeyArg: EncodeLike, { - let mut final_key = Self::prefix().to_vec(); - key.borrow().encode_to(&mut final_key); - Self::Hasher::hash(&final_key) + let module_prefix_hashed = Twox128::hash(Self::module_prefix()); + let storage_prefix_hashed = Twox128::hash(Self::storage_prefix()); + let key_hashed = key.borrow().using_encoded(Self::Hasher::hash); + + let mut final_key = Vec::with_capacity( + module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len() + ); + + final_key.extend_from_slice(&module_prefix_hashed[..]); + final_key.extend_from_slice(&storage_prefix_hashed[..]); + final_key.extend_from_slice(key_hashed.as_ref()); + + final_key } } @@ -62,7 +75,7 @@ impl> storage::StorageMap type Query = G::Query; fn hashed_key_for>(key: KeyArg) -> Vec { - Self::storage_map_final_key(key).as_ref().to_vec() + Self::storage_map_final_key(key) } fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2) { diff --git a/substrate/frame/support/src/storage/generator/mod.rs b/substrate/frame/support/src/storage/generator/mod.rs index f546546dc7..2db3e08ccf 100644 --- a/substrate/frame/support/src/storage/generator/mod.rs +++ b/substrate/frame/support/src/storage/generator/mod.rs @@ -94,22 +94,18 @@ mod tests { let t = GenesisConfig::default().build_storage().unwrap(); TestExternalities::new(t).execute_with(|| { - let prefix = NumberMap::prefix(); - // start with a map of u32 -> u32. for i in 0u32..100u32 { - let final_key = ::storage_linked_map_final_key( - prefix, &i, - ); + let final_key = ::storage_linked_map_final_key(&i); - let linkage = linked_map::new_head_linkage::<_, u32, u32, Format>(&i, prefix); + let linkage = linked_map::new_head_linkage::<_, u32, u32, Format>(&i); unhashed::put(final_key.as_ref(), &(&i, linkage)); } let head = linked_map::read_head::().unwrap(); assert_eq!( - Enumerator::::from_head(head, prefix).collect::>(), + Enumerator::::from_head(head).collect::>(), (0..100).rev().map(|x| (x, x)).collect::>(), ); diff --git a/substrate/frame/support/src/storage/generator/value.rs b/substrate/frame/support/src/storage/generator/value.rs index 5ebc25a70a..0cf143bac1 100644 --- a/substrate/frame/support/src/storage/generator/value.rs +++ b/substrate/frame/support/src/storage/generator/value.rs @@ -21,16 +21,19 @@ use crate::{storage::{self, unhashed}, hash::{Twox128, StorageHasher}, traits::L /// Generator for `StorageValue` used by `decl_storage`. /// -/// Value is stored at: +/// By default value is stored at: /// ```nocompile -/// Twox128(unhashed_key) +/// Twox128(module_prefix) ++ Twox128(storage_prefix) /// ``` pub trait StorageValue { /// The type that get/take returns. type Query; - /// Unhashed key used in storage - fn unhashed_key() -> &'static [u8]; + /// Module prefix. Used for generating final key. + fn module_prefix() -> &'static [u8]; + + /// Storage prefix. Used for generating final key. + fn storage_prefix() -> &'static [u8]; /// Convert an optional value retrieved from storage to the type queried. fn from_optional_value_to_query(v: Option) -> Self::Query; @@ -39,15 +42,18 @@ pub trait StorageValue { fn from_query_to_optional_value(v: Self::Query) -> Option; /// Generate the full key used in top storage. - fn storage_value_final_key() -> [u8; 16] { - Twox128::hash(Self::unhashed_key()) + fn storage_value_final_key() -> [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 } } impl> storage::StorageValue for G { type Query = G::Query; - fn hashed_key() -> [u8; 16] { + fn hashed_key() -> [u8; 32] { Self::storage_value_final_key() } diff --git a/substrate/frame/support/src/storage/mod.rs b/substrate/frame/support/src/storage/mod.rs index 91e1776788..88818b84e2 100644 --- a/substrate/frame/support/src/storage/mod.rs +++ b/substrate/frame/support/src/storage/mod.rs @@ -34,7 +34,7 @@ pub trait StorageValue { type Query; /// Get the storage key. - fn hashed_key() -> [u8; 16]; + fn hashed_key() -> [u8; 32]; /// Does the value (explicitly) exist in storage? fn exists() -> bool; diff --git a/substrate/frame/support/test/tests/final_keys.rs b/substrate/frame/support/test/tests/final_keys.rs index c1cf5c651a..365aa5779d 100644 --- a/substrate/frame/support/test/tests/final_keys.rs +++ b/substrate/frame/support/test/tests/final_keys.rs @@ -17,7 +17,7 @@ use support::storage::unhashed; use codec::Encode; use support::{StorageDoubleMap, StorageLinkedMap, StorageMap, StorageValue}; -use runtime_io::{TestExternalities, hashing}; +use runtime_io::{TestExternalities, hashing::{twox_128, blake2_128, blake2_256}}; mod no_instance { use codec::{Encode, Decode, EncodeLike}; @@ -89,44 +89,43 @@ mod instance { fn final_keys_no_instance() { TestExternalities::default().execute_with(|| { no_instance::Value::put(1); - assert_eq!(unhashed::get::(&hashing::twox_128(b"FinalKeysNone Value")), Some(1u32)); + let k = [twox_128(b"FinalKeysNone"), twox_128(b"Value")].concat(); + assert_eq!(unhashed::get::(&k), Some(1u32)); no_instance::Map::insert(1, 2); - let mut k = b"FinalKeysNone Map".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&hashing::blake2_256(&k)), Some(2u32)); + let mut k = [twox_128(b"FinalKeysNone"), twox_128(b"Map")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); no_instance::Map2::insert(1, 2); - let mut k = b"FinalKeysNone Map2".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&hashing::twox_128(&k)), Some(2u32)); + let mut k = [twox_128(b"FinalKeysNone"), twox_128(b"Map2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); - let head = b"head of FinalKeysNone LinkedMap".to_vec(); - assert_eq!(unhashed::get::(&hashing::blake2_256(&head)), None); + let head = [twox_128(b"FinalKeysNone"), twox_128(b"HeadOfLinkedMap")].concat(); + assert_eq!(unhashed::get::(&head), None); no_instance::LinkedMap::insert(1, 2); - let mut k = b"FinalKeysNone LinkedMap".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&hashing::blake2_256(&k)), Some(2u32)); - assert_eq!(unhashed::get::(&hashing::blake2_256(&head)), Some(1u32)); + let mut k = [twox_128(b"FinalKeysNone"), twox_128(b"LinkedMap")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(unhashed::get::(&head), Some(1u32)); no_instance::LinkedMap2::insert(1, 2); - let mut k = b"FinalKeysNone LinkedMap2".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&hashing::twox_128(&k)), Some(2u32)); + let mut k = [twox_128(b"FinalKeysNone"), twox_128(b"LinkedMap2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); no_instance::DoubleMap::insert(&1, &2, &3); - let mut k = b"FinalKeysNone DoubleMap".to_vec(); - k.extend(1u32.encode()); - let mut k = hashing::blake2_256(&k).to_vec(); - k.extend(&hashing::blake2_256(&2u32.encode())); + let mut k = [twox_128(b"FinalKeysNone"), twox_128(b"DoubleMap")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + k.extend(2u32.using_encoded(blake2_256).to_vec()); assert_eq!(unhashed::get::(&k), Some(3u32)); no_instance::DoubleMap2::insert(&1, &2, &3); - let mut k = b"FinalKeysNone DoubleMap2".to_vec(); - k.extend(1u32.encode()); - let mut k = hashing::twox_128(&k).to_vec(); - k.extend(&hashing::blake2_128(&2u32.encode())); + let mut k = [twox_128(b"FinalKeysNone"), twox_128(b"DoubleMap2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + k.extend(2u32.using_encoded(blake2_128).to_vec()); assert_eq!(unhashed::get::(&k), Some(3u32)); }); } @@ -135,44 +134,43 @@ fn final_keys_no_instance() { fn final_keys_default_instance() { TestExternalities::default().execute_with(|| { >::put(1); - assert_eq!(unhashed::get::(&hashing::twox_128(b"FinalKeysSome Value")), Some(1u32)); + let k = [twox_128(b"FinalKeysSome"), twox_128(b"Value")].concat(); + assert_eq!(unhashed::get::(&k), Some(1u32)); >::insert(1, 2); - let mut k = b"FinalKeysSome Map".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&hashing::blake2_256(&k)), Some(2u32)); + let mut k = [twox_128(b"FinalKeysSome"), twox_128(b"Map")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); >::insert(1, 2); - let mut k = b"FinalKeysSome Map2".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&hashing::twox_128(&k)), Some(2u32)); + let mut k = [twox_128(b"FinalKeysSome"), twox_128(b"Map2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); - let head = b"head of FinalKeysSome LinkedMap".to_vec(); - assert_eq!(unhashed::get::(&hashing::blake2_256(&head)), None); + let head = [twox_128(b"FinalKeysSome"), twox_128(b"HeadOfLinkedMap")].concat(); + assert_eq!(unhashed::get::(&head), None); >::insert(1, 2); - let mut k = b"FinalKeysSome LinkedMap".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&hashing::blake2_256(&k)), Some(2u32)); - assert_eq!(unhashed::get::(&hashing::blake2_256(&head)), Some(1u32)); + let mut k = [twox_128(b"FinalKeysSome"), twox_128(b"LinkedMap")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(unhashed::get::(&head), Some(1u32)); >::insert(1, 2); - let mut k = b"FinalKeysSome LinkedMap2".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&hashing::twox_128(&k)), Some(2u32)); + let mut k = [twox_128(b"FinalKeysSome"), twox_128(b"LinkedMap2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); >::insert(&1, &2, &3); - let mut k = b"FinalKeysSome DoubleMap".to_vec(); - k.extend(1u32.encode()); - let mut k = hashing::blake2_256(&k).to_vec(); - k.extend(&hashing::blake2_256(&2u32.encode())); + let mut k = [twox_128(b"FinalKeysSome"), twox_128(b"DoubleMap")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + k.extend(2u32.using_encoded(blake2_256).to_vec()); assert_eq!(unhashed::get::(&k), Some(3u32)); >::insert(&1, &2, &3); - let mut k = b"FinalKeysSome DoubleMap2".to_vec(); - k.extend(1u32.encode()); - let mut k = hashing::twox_128(&k).to_vec(); - k.extend(&hashing::blake2_128(&2u32.encode())); + let mut k = [twox_128(b"FinalKeysSome"), twox_128(b"DoubleMap2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + k.extend(2u32.using_encoded(blake2_128).to_vec()); assert_eq!(unhashed::get::(&k), Some(3u32)); }); } @@ -181,47 +179,43 @@ fn final_keys_default_instance() { fn final_keys_instance_2() { TestExternalities::default().execute_with(|| { >::put(1); - assert_eq!( - unhashed::get::(&hashing::twox_128(b"Instance2FinalKeysSome Value")), - Some(1u32) - ); + let k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"Value")].concat(); + assert_eq!(unhashed::get::(&k), Some(1u32)); >::insert(1, 2); - let mut k = b"Instance2FinalKeysSome Map".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&hashing::blake2_256(&k)), Some(2u32)); + let mut k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"Map")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); >::insert(1, 2); - let mut k = b"Instance2FinalKeysSome Map2".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&hashing::twox_128(&k)), Some(2u32)); + let mut k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"Map2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); - let head = b"head of Instance2FinalKeysSome LinkedMap".to_vec(); - assert_eq!(unhashed::get::(&hashing::blake2_256(&head)), None); + let head = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"HeadOfLinkedMap")].concat(); + assert_eq!(unhashed::get::(&head), None); >::insert(1, 2); - let mut k = b"Instance2FinalKeysSome LinkedMap".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&hashing::blake2_256(&k)), Some(2u32)); - assert_eq!(unhashed::get::(&hashing::blake2_256(&head)), Some(1u32)); + let mut k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"LinkedMap")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(unhashed::get::(&head), Some(1u32)); >::insert(1, 2); - let mut k = b"Instance2FinalKeysSome LinkedMap2".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&hashing::twox_128(&k)), Some(2u32)); + let mut k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"LinkedMap2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); >::insert(&1, &2, &3); - let mut k = b"Instance2FinalKeysSome DoubleMap".to_vec(); - k.extend(1u32.encode()); - let mut k = hashing::blake2_256(&k).to_vec(); - k.extend(&hashing::blake2_256(&2u32.encode())); + let mut k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"DoubleMap")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + k.extend(2u32.using_encoded(blake2_256).to_vec()); assert_eq!(unhashed::get::(&k), Some(3u32)); >::insert(&1, &2, &3); - let mut k = b"Instance2FinalKeysSome DoubleMap2".to_vec(); - k.extend(1u32.encode()); - let mut k = hashing::twox_128(&k).to_vec(); - k.extend(&hashing::blake2_128(&2u32.encode())); + let mut k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"DoubleMap2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + k.extend(2u32.using_encoded(blake2_128).to_vec()); assert_eq!(unhashed::get::(&k), Some(3u32)); }); } diff --git a/substrate/frame/support/test/tests/instance.rs b/substrate/frame/support/test/tests/instance.rs index dc4fded17e..eff73ad6ea 100644 --- a/substrate/frame/support/test/tests/instance.rs +++ b/substrate/frame/support/test/tests/instance.rs @@ -472,14 +472,3 @@ fn test_instance_storage_metadata() { let metadata = Module2_2::storage_metadata(); pretty_assertions::assert_eq!(EXPECTED_METADATA, metadata); } - -#[test] -fn instance_prefix_is_prefix_of_entries() { - use module2::Instance; - - let prefix = module2::Instance2::PREFIX; - assert!(module2::Instance2::PREFIX_FOR_Value.starts_with(prefix)); - assert!(module2::Instance2::PREFIX_FOR_Map.starts_with(prefix)); - assert!(module2::Instance2::PREFIX_FOR_LinkedMap.starts_with(prefix)); - assert!(module2::Instance2::PREFIX_FOR_DoubleMap.starts_with(prefix)); -} diff --git a/substrate/utils/frame/rpc/support/src/lib.rs b/substrate/utils/frame/rpc/support/src/lib.rs index ef594b687e..c9163bdc30 100644 --- a/substrate/utils/frame/rpc/support/src/lib.rs +++ b/substrate/utils/frame/rpc/support/src/lib.rs @@ -108,7 +108,7 @@ impl StorageQuery { /// Create a storage query for a value in a StorageMap. pub fn map, K: FullEncode>(key: K) -> Self { Self { - key: StorageKey(St::storage_map_final_key(key).as_ref().to_vec()), + key: StorageKey(St::storage_map_final_key(key)), _spook: PhantomData, } } @@ -116,7 +116,7 @@ impl StorageQuery { /// Create a storage query for a value in a StorageLinkedMap. pub fn linked_map, K: FullCodec>(key: K) -> Self { Self { - key: StorageKey(St::storage_linked_map_final_key(key).as_ref().to_vec()), + key: StorageKey(St::storage_linked_map_final_key(key)), _spook: PhantomData, } }