From f4e36f0d74ac21c6cdee9a6bc85efce2e5ad45cd Mon Sep 17 00:00:00 2001
From: thiolliere <gui.thiolliere@gmail.com>
Date: Wed, 16 Oct 2019 15:47:46 +0200
Subject: [PATCH] Refactor decl storage (#3765)

* split implementation in multiple files:
  * transformation -> genesis_config/  getters.rs  instance_trait.rs  metadata.rs  mod.rs  store_trait.rs
  * mod.rs -> parser.rs
  * impl.rs -> storage_struct.rs
* parser is isolated into parse module, it could be improved as well but this can be done in another PR
* modules contains a defintion of decl_storage input which must be ok to work with.
* implementation change:
  * T: Trait might be more often bound to 'static (anyway we only use static one and it is needed for metadata current implementation).
  * GenesisConfig no longer requires its fields to be Clone (possible since to EncodeLike feature)
  * builder for map storages must return precise type Vec<(key, value)>
---
 substrate/node/runtime/src/lib.rs             |    4 +-
 substrate/srml/support/procedural/src/lib.rs  |    2 +-
 .../src/storage/genesis_config/builder_def.rs |  111 ++
 .../genesis_config/genesis_config_def.rs      |  144 ++
 .../src/storage/genesis_config/mod.rs         |  203 +++
 .../support/procedural/src/storage/getters.rs |   80 ++
 .../support/procedural/src/storage/impls.rs   |  418 ------
 .../procedural/src/storage/instance_trait.rs  |  196 +++
 .../procedural/src/storage/metadata.rs        |  230 +++
 .../support/procedural/src/storage/mod.rs     |  521 ++++---
 .../support/procedural/src/storage/parse.rs   |  377 +++++
 .../procedural/src/storage/storage_struct.rs  |  220 +++
 .../procedural/src/storage/store_trait.rs     |   54 +
 .../procedural/src/storage/transformation.rs  | 1264 -----------------
 .../support/procedural/tools/src/syn_ext.rs   |   12 +-
 15 files changed, 1978 insertions(+), 1858 deletions(-)
 create mode 100644 substrate/srml/support/procedural/src/storage/genesis_config/builder_def.rs
 create mode 100644 substrate/srml/support/procedural/src/storage/genesis_config/genesis_config_def.rs
 create mode 100644 substrate/srml/support/procedural/src/storage/genesis_config/mod.rs
 create mode 100644 substrate/srml/support/procedural/src/storage/getters.rs
 delete mode 100644 substrate/srml/support/procedural/src/storage/impls.rs
 create mode 100644 substrate/srml/support/procedural/src/storage/instance_trait.rs
 create mode 100644 substrate/srml/support/procedural/src/storage/metadata.rs
 create mode 100644 substrate/srml/support/procedural/src/storage/parse.rs
 create mode 100644 substrate/srml/support/procedural/src/storage/storage_struct.rs
 create mode 100644 substrate/srml/support/procedural/src/storage/store_trait.rs
 delete mode 100644 substrate/srml/support/procedural/src/storage/transformation.rs

diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs
index fd31969efa0..63fc8560138 100644
--- a/substrate/node/runtime/src/lib.rs
+++ b/substrate/node/runtime/src/lib.rs
@@ -84,8 +84,8 @@ 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: 176,
-	impl_version: 176,
+	spec_version: 177,
+	impl_version: 177,
 	apis: RUNTIME_API_VERSIONS,
 };
 
diff --git a/substrate/srml/support/procedural/src/lib.rs b/substrate/srml/support/procedural/src/lib.rs
index a9cfa8d30d1..38d404712ed 100644
--- a/substrate/srml/support/procedural/src/lib.rs
+++ b/substrate/srml/support/procedural/src/lib.rs
@@ -213,5 +213,5 @@ use proc_macro::TokenStream;
 ///
 #[proc_macro]
 pub fn decl_storage(input: TokenStream) -> TokenStream {
-	storage::transformation::decl_storage_impl(input)
+	storage::decl_storage_impl(input)
 }
diff --git a/substrate/srml/support/procedural/src/storage/genesis_config/builder_def.rs b/substrate/srml/support/procedural/src/storage/genesis_config/builder_def.rs
new file mode 100644
index 00000000000..60f094e9fe4
--- /dev/null
+++ b/substrate/srml/support/procedural/src/storage/genesis_config/builder_def.rs
@@ -0,0 +1,111 @@
+// Copyright 2017-2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Substrate is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Builder logic definition used to build genesis storage.
+
+use srml_support_procedural_tools::syn_ext as ext;
+use proc_macro2::TokenStream;
+use syn::spanned::Spanned;
+use quote::{quote, quote_spanned};
+use super::super::{DeclStorageDefExt, StorageLineTypeDef};
+
+/// Definition of builder blocks, each block insert some value in the storage.
+/// They must be called inside externalities, and with `self` being the genesis config.
+pub struct BuilderDef {
+	/// Contains:
+	/// * build block for storage with build attribute.
+	/// * build block for storage with config attribute and no build attribute.
+	/// * build block for extra genesis build expression.
+	pub blocks: Vec<TokenStream>,
+	/// The build blocks requires generic traits.
+	pub is_generic: bool,
+}
+
+impl BuilderDef {
+	pub fn from_def(scrate: &TokenStream, def: &DeclStorageDefExt) -> Self {
+		let mut blocks = Vec::new();
+		let mut is_generic = false;
+
+		for line in def.storage_lines.iter() {
+			let storage_struct = &line.storage_struct;
+			let storage_trait = &line.storage_trait;
+			let value_type = &line.value_type;
+
+			// Contains the data to inset at genesis either from build or config.
+			let mut data = None;
+
+			if let Some(builder) = &line.build {
+				is_generic |= ext::expr_contains_ident(&builder, &def.module_runtime_generic);
+				is_generic |= line.is_generic;
+
+				data = Some(quote_spanned!(builder.span() => &(#builder)(&self)));
+			} else if let Some(config) = &line.config {
+				is_generic |= line.is_generic;
+
+				data = Some(quote!(&self.#config;));
+			};
+
+			if let Some(data) = data {
+				blocks.push(match &line.storage_type {
+					StorageLineTypeDef::Simple(_) => {
+						quote!{{
+							let v: &#value_type = #data;
+							<#storage_struct as #scrate::#storage_trait>::put::<&#value_type>(v);
+						}}
+					},
+					StorageLineTypeDef::Map(map) | StorageLineTypeDef::LinkedMap(map) => {
+						let key = &map.key;
+						quote!{{
+							let data: &#scrate::rstd::vec::Vec<(#key, #value_type)> = #data;
+							data.iter().for_each(|(k, v)| {
+								<#storage_struct as #scrate::#storage_trait>::insert::<
+									&#key, &#value_type
+								>(k, v);
+							});
+						}}
+					},
+					StorageLineTypeDef::DoubleMap(map) => {
+						let key1 = &map.key1;
+						let key2 = &map.key2;
+						quote!{{
+							let data: &#scrate::rstd::vec::Vec<(#key1, #key2, #value_type)> = #data;
+							data.iter().for_each(|(k1, k2, v)| {
+								<#storage_struct as #scrate::#storage_trait>::insert::<
+									&#key1, &#key2, &#value_type
+								>(k1, k2, v);
+							});
+						}}
+					},
+				});
+			}
+		}
+
+		if let Some(builder) = def.extra_genesis_build.as_ref() {
+			is_generic |= ext::expr_contains_ident(&builder, &def.module_runtime_generic);
+
+			blocks.push(quote_spanned! { builder.span() =>
+				let extra_genesis_builder: fn(&Self) = #builder;
+				extra_genesis_builder(&self);
+			});
+		}
+
+
+		Self {
+			blocks,
+			is_generic,
+		}
+	}
+}
diff --git a/substrate/srml/support/procedural/src/storage/genesis_config/genesis_config_def.rs b/substrate/srml/support/procedural/src/storage/genesis_config/genesis_config_def.rs
new file mode 100644
index 00000000000..f9d2f8abe80
--- /dev/null
+++ b/substrate/srml/support/procedural/src/storage/genesis_config/genesis_config_def.rs
@@ -0,0 +1,144 @@
+// Copyright 2017-2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Substrate is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Genesis config defintion.
+
+use srml_support_procedural_tools::syn_ext as ext;
+use proc_macro2::TokenStream;
+use syn::parse_quote;
+use quote::quote;
+use super::super::{DeclStorageDefExt, StorageLineTypeDef};
+
+pub struct GenesisConfigFieldDef {
+	pub doc: Vec<syn::Meta>,
+	pub name: syn::Ident,
+	pub typ: syn::Type,
+	pub default: TokenStream,
+}
+
+pub struct GenesisConfigDef {
+	pub is_generic: bool,
+	pub fields: Vec<GenesisConfigFieldDef>,
+	/// For example: `<T: Trait<I>, I: Instance=DefaultInstance>`.
+	pub genesis_struct_decl: TokenStream,
+	/// For example: `<T, I>`.
+	pub genesis_struct: TokenStream,
+	/// For example: `<T: Trait<I>, I: Instance>`.
+	pub genesis_impl: TokenStream,
+	/// The where clause to use to constrain generics if genesis config is generic.
+	pub genesis_where_clause: Option<syn::WhereClause>,
+}
+
+impl GenesisConfigDef {
+	pub fn from_def(def: &DeclStorageDefExt) -> Self {
+		let fields = Self::get_genesis_config_field_defs(def);
+
+		let is_generic = fields.iter()
+			.any(|field| ext::type_contains_ident(&field.typ, &def.module_runtime_generic));
+
+		let (
+			genesis_struct_decl,
+			genesis_impl,
+			genesis_struct,
+			genesis_where_clause
+		) = if is_generic {
+			let runtime_generic = &def.module_runtime_generic;
+			let runtime_trait = &def.module_runtime_trait;
+			let optional_instance = &def.optional_instance;
+			let optional_instance_bound = &def.optional_instance_bound;
+			let optional_instance_bound_optional_default = &def.optional_instance_bound_optional_default;
+			let where_clause = &def.where_clause;
+			(
+				quote!(<#runtime_generic: #runtime_trait, #optional_instance_bound_optional_default>),
+				quote!(<#runtime_generic: #runtime_trait, #optional_instance_bound>),
+				quote!(<#runtime_generic, #optional_instance>),
+				where_clause.clone(),
+			)
+		} else {
+			(quote!(), quote!(), quote!(), None)
+		};
+
+		Self {
+			is_generic,
+			fields,
+			genesis_struct_decl,
+			genesis_struct,
+			genesis_impl,
+			genesis_where_clause,
+		}
+	}
+
+	fn get_genesis_config_field_defs(def: &DeclStorageDefExt) -> Vec<GenesisConfigFieldDef> {
+		let mut config_field_defs = Vec::new();
+
+		for (config_field, line) in def.storage_lines.iter()
+			.filter_map(|line| line.config.as_ref().map(|config_field| (config_field.clone(), line)))
+		{
+			let value_type = &line.value_type;
+
+			let typ = match &line.storage_type {
+				StorageLineTypeDef::Simple(_) => (*value_type).clone(),
+				StorageLineTypeDef::Map(map) | StorageLineTypeDef::LinkedMap(map) => {
+					let key = &map.key;
+					parse_quote!( Vec<(#key, #value_type)> )
+				},
+				StorageLineTypeDef::DoubleMap(map) => {
+					let key1 = &map.key1;
+					let key2 = &map.key2;
+
+					parse_quote!( Vec<(#key1, #key2, #value_type)> )
+				},
+			};
+
+			let default = line.default_value.as_ref()
+				.map(|d| {
+					if line.is_option {
+						quote!( #d.unwrap_or_default() )
+					} else {
+						quote!( #d )
+					}
+				})
+				.unwrap_or_else(|| quote!( Default::default() ));
+
+			config_field_defs.push(GenesisConfigFieldDef {
+				doc: line.doc_attrs.clone(),
+				name: config_field,
+				typ,
+				default,
+			});
+		}
+
+		for line in &def.extra_genesis_config_lines {
+			let doc = line.attrs.iter()
+				.filter_map(|a| a.parse_meta().ok())
+				.filter(|m| m.name() == "doc")
+				.collect();
+
+			let default = line.default.as_ref().map(|e| quote!( #e ))
+				.unwrap_or_else(|| quote!( Default::default() ));
+
+
+			config_field_defs.push(GenesisConfigFieldDef {
+				doc,
+				name: line.name.clone(),
+				typ: line.typ.clone(),
+				default,
+			});
+		}
+
+		config_field_defs
+	}
+}
diff --git a/substrate/srml/support/procedural/src/storage/genesis_config/mod.rs b/substrate/srml/support/procedural/src/storage/genesis_config/mod.rs
new file mode 100644
index 00000000000..57de1e34a8d
--- /dev/null
+++ b/substrate/srml/support/procedural/src/storage/genesis_config/mod.rs
@@ -0,0 +1,203 @@
+// Copyright 2017-2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Substrate is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Declaration of genesis config structure and implementation of build storage trait and
+//! functions.
+
+use proc_macro2::{TokenStream, Span};
+use quote::quote;
+use super::{DeclStorageDefExt, instance_trait::DEFAULT_INSTANTIABLE_TRAIT_NAME};
+use genesis_config_def::GenesisConfigDef;
+use builder_def::BuilderDef;
+
+mod genesis_config_def;
+mod builder_def;
+
+const DEFAULT_INSTANCE_NAME: &str = "__GeneratedInstance";
+
+fn decl_genesis_config_and_impl_default(
+	scrate: &TokenStream,
+	genesis_config: &GenesisConfigDef,
+) -> TokenStream {
+	let config_fields = genesis_config.fields.iter().map(|field| {
+		let (name, typ, doc) = (&field.name, &field.typ, &field.doc);
+		quote!( #( #[ #doc] )* pub #name: #typ, )
+	});
+
+	let config_field_defaults = genesis_config.fields.iter().map(|field| {
+		let (name, default, doc) = (&field.name, &field.default, &field.doc);
+		quote!( #( #[ #doc] )* #name: #default, )
+	});
+
+	let serde_bug_bound = if !genesis_config.fields.is_empty() {
+		let mut b_ser = String::new();
+		let mut b_dser = String::new();
+
+		for typ in genesis_config.fields.iter().map(|c| &c.typ) {
+			let typ = quote!( #typ );
+			b_ser.push_str(&format!("{} : {}::serde::Serialize, ", typ, scrate));
+			b_dser.push_str(&format!("{} : {}::serde::de::DeserializeOwned, ", typ, scrate));
+		}
+
+		quote! {
+			#[serde(bound(serialize = #b_ser))]
+			#[serde(bound(deserialize = #b_dser))]
+		}
+	} else {
+		quote!()
+	};
+
+	let genesis_struct_decl = &genesis_config.genesis_struct_decl;
+	let genesis_struct = &genesis_config.genesis_struct;
+	let genesis_impl = &genesis_config.genesis_impl;
+	let genesis_where_clause = &genesis_config.genesis_where_clause;
+
+	quote!(
+		#[derive(#scrate::Serialize, #scrate::Deserialize)]
+		#[cfg(feature = "std")]
+		#[serde(rename_all = "camelCase")]
+		#[serde(deny_unknown_fields)]
+		#serde_bug_bound
+		pub struct GenesisConfig#genesis_struct_decl #genesis_where_clause {
+			#( #config_fields )*
+		}
+
+		#[cfg(feature = "std")]
+		impl#genesis_impl Default for GenesisConfig#genesis_struct #genesis_where_clause {
+			fn default() -> Self {
+				GenesisConfig {
+					#( #config_field_defaults )*
+				}
+			}
+		}
+	)
+}
+
+fn impl_build_storage(
+	scrate: &TokenStream,
+	def: &DeclStorageDefExt,
+	genesis_config: &GenesisConfigDef,
+	builders: &BuilderDef,
+) -> TokenStream {
+	let runtime_generic = &def.module_runtime_generic;
+	let runtime_trait = &def.module_runtime_trait;
+	let optional_instance = &def.optional_instance;
+	let optional_instance_bound = &def.optional_instance_bound;
+	let where_clause = &def.where_clause;
+
+	let inherent_instance = def.optional_instance.clone().unwrap_or_else(|| {
+		let name = syn::Ident::new(DEFAULT_INSTANCE_NAME, Span::call_site());
+		quote!( #name )
+	});
+	let inherent_instance_bound = def.optional_instance_bound.clone().unwrap_or_else(|| {
+		let bound = syn::Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site());
+		quote!( #inherent_instance: #bound )
+	});
+
+	let build_storage_impl = quote!(
+		<#runtime_generic: #runtime_trait, #inherent_instance_bound>
+	);
+
+	let genesis_struct = &genesis_config.genesis_struct;
+	let genesis_impl = &genesis_config.genesis_impl;
+	let genesis_where_clause = &genesis_config.genesis_where_clause;
+
+	let (
+		fn_generic,
+		fn_traitinstance,
+		fn_where_clause
+	) = if !genesis_config.is_generic && builders.is_generic {
+		(
+			quote!( <#runtime_generic: #runtime_trait, #optional_instance_bound> ),
+			quote!( #runtime_generic, #optional_instance ),
+			Some(&def.where_clause),
+		)
+	} else {
+		(quote!(), quote!(), None)
+	};
+
+	let builder_blocks = &builders.blocks;
+
+	let build_storage_impl_trait = quote!(
+		#scrate::sr_primitives::BuildModuleGenesisStorage<#runtime_generic, #inherent_instance>
+	);
+
+	quote!{
+		#[cfg(feature = "std")]
+		impl#genesis_impl GenesisConfig#genesis_struct #genesis_where_clause {
+			pub fn build_storage #fn_generic (self) -> std::result::Result<
+				(
+					#scrate::sr_primitives::StorageOverlay,
+					#scrate::sr_primitives::ChildrenStorageOverlay,
+				),
+				String
+			> #fn_where_clause {
+				let mut storage = (Default::default(), Default::default());
+				self.assimilate_storage::<#fn_traitinstance>(&mut storage)?;
+				Ok(storage)
+			}
+
+			/// Assimilate the storage for this module into pre-existing overlays.
+			pub fn assimilate_storage #fn_generic (
+				self,
+				tuple_storage: &mut (
+					#scrate::sr_primitives::StorageOverlay,
+					#scrate::sr_primitives::ChildrenStorageOverlay,
+				),
+			) -> std::result::Result<(), String> #fn_where_clause {
+				#scrate::with_storage(tuple_storage, || {
+					#( #builder_blocks )*
+					Ok(())
+				})
+			}
+		}
+
+		#[cfg(feature = "std")]
+		impl#build_storage_impl #build_storage_impl_trait for GenesisConfig#genesis_struct
+			#where_clause
+		{
+			fn build_module_genesis_storage(
+				self,
+				storage: &mut (
+					#scrate::sr_primitives::StorageOverlay,
+					#scrate::sr_primitives::ChildrenStorageOverlay,
+				),
+			) -> std::result::Result<(), String> {
+				self.assimilate_storage::<#fn_traitinstance> (storage)
+			}
+		}
+	}
+}
+
+pub fn genesis_config_and_build_storage(
+	scrate: &TokenStream,
+	def: &DeclStorageDefExt,
+) -> TokenStream {
+	let builders = BuilderDef::from_def(scrate, def);
+	if !builders.blocks.is_empty() {
+		let genesis_config = &GenesisConfigDef::from_def(def);
+		let decl_genesis_config_and_impl_default =
+			decl_genesis_config_and_impl_default(scrate, genesis_config);
+		let impl_build_storage = impl_build_storage(scrate, def, genesis_config, &builders);
+
+		quote!{
+			#decl_genesis_config_and_impl_default
+			#impl_build_storage
+		}
+	} else {
+		quote!()
+	}
+}
diff --git a/substrate/srml/support/procedural/src/storage/getters.rs b/substrate/srml/support/procedural/src/storage/getters.rs
new file mode 100644
index 00000000000..f30e489eb58
--- /dev/null
+++ b/substrate/srml/support/procedural/src/storage/getters.rs
@@ -0,0 +1,80 @@
+// Copyright 2017-2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Substrate is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Implementation of getters on module structure.
+
+use proc_macro2::TokenStream;
+use quote::quote;
+use super::{DeclStorageDefExt, StorageLineTypeDef};
+
+pub fn impl_getters(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream {
+	let mut getters = TokenStream::new();
+
+	for (get_fn, line) in def.storage_lines.iter()
+		.filter_map(|line| line.getter.as_ref().map(|get_fn| (get_fn, line)))
+	{
+		let attrs = &line.doc_attrs;
+
+		let storage_struct = &line.storage_struct;
+		let storage_trait = &line.storage_trait;
+
+		let getter = match &line.storage_type {
+			StorageLineTypeDef::Simple(value) => {
+				quote!{
+					#( #[ #attrs ] )*
+					pub fn #get_fn() -> #value {
+						<#storage_struct as #scrate::#storage_trait>::get()
+					}
+				}
+			},
+			StorageLineTypeDef::Map(map) | StorageLineTypeDef::LinkedMap(map) => {
+				let key = &map.key;
+				let value = &map.value;
+				quote!{
+					#( #[ #attrs ] )*
+					pub fn #get_fn<K: #scrate::codec::EncodeLike<#key>>(key: K) -> #value {
+						<#storage_struct as #scrate::#storage_trait>::get(key)
+					}
+				}
+			},
+			StorageLineTypeDef::DoubleMap(map) => {
+				let key1 = &map.key1;
+				let key2 = &map.key2;
+				let value = &map.value;
+				quote!{
+					pub fn #get_fn<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> #value
+					where
+						KArg1: #scrate::codec::EncodeLike<#key1>,
+						KArg2: #scrate::codec::EncodeLike<#key2>,
+					{
+						<#storage_struct as #scrate::#storage_trait>::get(k1, k2)
+					}
+				}
+			},
+		};
+		getters.extend(getter);
+	}
+
+	let module_struct = &def.module_struct;
+	let module_impl = &def.module_impl;
+	let where_clause = &def.where_clause;
+
+	quote!(
+		impl#module_impl #module_struct #where_clause {
+			#getters
+		}
+	)
+}
diff --git a/substrate/srml/support/procedural/src/storage/impls.rs b/substrate/srml/support/procedural/src/storage/impls.rs
deleted file mode 100644
index ee6fa9a1642..00000000000
--- a/substrate/srml/support/procedural/src/storage/impls.rs
+++ /dev/null
@@ -1,418 +0,0 @@
-// Copyright 2019 Parity Technologies (UK) Ltd.
-// This file is part of Substrate.
-
-// Substrate is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Substrate is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
-
-use crate::storage::transformation::{DeclStorageTypeInfos, InstanceOpts};
-
-use srml_support_procedural_tools::syn_ext as ext;
-use proc_macro2::TokenStream as TokenStream2;
-use syn::Ident;
-use quote::quote;
-
-fn from_optional_value_to_query(is_option: bool, fielddefault: TokenStream2) -> TokenStream2 {
-	if !is_option {
-		// raw type case
-		quote!( v.unwrap_or_else(|| #fielddefault ) )
-	} else {
-		// Option<> type case
-		quote!( v.or_else(|| #fielddefault ) )
-	}
-}
-
-fn from_query_to_optional_value(is_option: bool) -> TokenStream2 {
-	if !is_option {
-		// raw type case
-		quote!( Some(v) )
-	} else {
-		// Option<> type case
-		quote!( v )
-	}
-}
-
-// prefix for consts in trait Instance
-pub(crate) const PREFIX_FOR: &str = "PREFIX_FOR_";
-pub(crate) const HEAD_KEY_FOR: &str = "HEAD_KEY_FOR_";
-
-pub(crate) struct Impls<'a, I: Iterator<Item=syn::Meta>> {
-	pub scrate: &'a TokenStream2,
-	pub visibility: &'a syn::Visibility,
-	pub traitinstance: &'a syn::Ident,
-	pub traittype: &'a syn::TypeParamBound,
-	pub instance_opts: &'a InstanceOpts,
-	pub type_infos: DeclStorageTypeInfos<'a>,
-	pub fielddefault: TokenStream2,
-	pub prefix: String,
-	pub cratename: &'a syn::Ident,
-	pub name: &'a syn::Ident,
-	pub attrs: I,
-	pub where_clause: &'a Option<syn::WhereClause>,
-}
-
-impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
-	pub fn simple_value(self) -> TokenStream2 {
-		let Self {
-			scrate,
-			visibility,
-			traitinstance,
-			traittype,
-			instance_opts,
-			type_infos,
-			fielddefault,
-			prefix,
-			name,
-			attrs,
-			where_clause,
-			..
-		} = self;
-		let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos;
-
-		let from_optional_value_to_query = from_optional_value_to_query(is_option, fielddefault);
-		let from_query_to_optional_value = from_query_to_optional_value(is_option);
-
-		let InstanceOpts {
-			equal_default_instance,
-			bound_instantiable,
-			instance,
-			..
-		} = instance_opts;
-
-		let final_prefix = if let Some(instance) = instance {
-			let const_name = Ident::new(&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site());
-			quote!{ #instance::#const_name.as_bytes() }
-		} else {
-			quote!{ #prefix.as_bytes() }
-		};
-
-		let (struct_trait, impl_trait, trait_and_instance, where_clause) = if ext::type_contains_ident(
-			value_type, traitinstance
-		) {
-			(
-				quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance),
-				quote!(#traitinstance: #traittype, #instance #bound_instantiable),
-				quote!(#traitinstance, #instance),
-				where_clause.clone(),
-			)
-		} else {
-			(
-				quote!(#instance #bound_instantiable #equal_default_instance),
-				quote!(#instance #bound_instantiable),
-				quote!(#instance),
-				None,
-			)
-		};
-
-		// generator for value
-		quote! {
-			#( #[ #attrs ] )*
-			#visibility struct #name<#struct_trait>(
-				#scrate::rstd::marker::PhantomData<(#trait_and_instance)>
-			) #where_clause;
-
-			impl<#impl_trait> #scrate::storage::generator::StorageValue<#typ>
-				for #name<#trait_and_instance> #where_clause
-			{
-				type Query = #value_type;
-
-				fn unhashed_key() -> &'static [u8] {
-					#final_prefix
-				}
-
-				fn from_optional_value_to_query(v: Option<#typ>) -> Self::Query {
-					#from_optional_value_to_query
-				}
-
-				fn from_query_to_optional_value(v: Self::Query) -> Option<#typ> {
-					#from_query_to_optional_value
-				}
-			}
-		}
-	}
-
-	pub fn map(self, hasher: TokenStream2, kty: &syn::Type) -> TokenStream2 {
-		let Self {
-			scrate,
-			visibility,
-			traitinstance,
-			traittype,
-			instance_opts,
-			type_infos,
-			fielddefault,
-			prefix,
-			name,
-			attrs,
-			where_clause,
-			..
-		} = self;
-		let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos;
-
-		let from_optional_value_to_query = from_optional_value_to_query(is_option, fielddefault);
-		let from_query_to_optional_value = from_query_to_optional_value(is_option);
-
-		let InstanceOpts {
-			equal_default_instance,
-			bound_instantiable,
-			instance,
-			..
-		} = instance_opts;
-
-		let final_prefix = if let Some(instance) = instance {
-			let const_name = syn::Ident::new(
-				&format!("{}{}", PREFIX_FOR, name.to_string()),
-				proc_macro2::Span::call_site(),
-			);
-			quote! { #instance::#const_name.as_bytes() }
-		} else {
-			quote! { #prefix.as_bytes() }
-		};
-
-		let trait_required = ext::type_contains_ident(value_type, traitinstance)
-			|| ext::type_contains_ident(kty, traitinstance);
-
-		let (struct_trait, impl_trait, trait_and_instance, where_clause) = if trait_required {
-			(
-				quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance),
-				quote!(#traitinstance: #traittype, #instance #bound_instantiable),
-				quote!(#traitinstance, #instance),
-				where_clause.clone(),
-			)
-		} else {
-			(
-				quote!(#instance #bound_instantiable #equal_default_instance),
-				quote!(#instance #bound_instantiable),
-				quote!(#instance),
-				None,
-			)
-		};
-
-		// generator for map
-		quote!{
-			#( #[ #attrs ] )*
-			#visibility struct #name<#struct_trait>(
-				#scrate::rstd::marker::PhantomData<(#trait_and_instance)>
-			) #where_clause;
-
-			impl<#impl_trait> #scrate::storage::generator::StorageMap<#kty, #typ>
-				for #name<#trait_and_instance> #where_clause
-			{
-				type Query = #value_type;
-				type Hasher = #scrate::#hasher;
-
-				fn prefix() -> &'static [u8] {
-					#final_prefix
-				}
-
-				fn from_optional_value_to_query(v: Option<#typ>) -> Self::Query {
-					#from_optional_value_to_query
-				}
-
-				fn from_query_to_optional_value(v: Self::Query) -> Option<#typ> {
-					#from_query_to_optional_value
-				}
-			}
-		}
-	}
-
-	pub fn linked_map(self, hasher: TokenStream2, kty: &syn::Type) -> TokenStream2 {
-		let Self {
-			scrate,
-			visibility,
-			traitinstance,
-			traittype,
-			instance_opts,
-			type_infos,
-			fielddefault,
-			prefix,
-			name,
-			attrs,
-			where_clause,
-			..
-		} = self;
-
-		let InstanceOpts {
-			equal_default_instance,
-			bound_instantiable,
-			instance,
-			..
-		} = instance_opts;
-
-		let final_prefix = if let Some(instance) = instance {
-			let const_name = Ident::new(
-				&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()
-			);
-			quote!{ #instance::#const_name.as_bytes() }
-		} else {
-			quote!{ #prefix.as_bytes() }
-		};
-
-		// make sure to use different prefix for head and elements.
-		let head_key = if let Some(instance) = instance {
-			let const_name = Ident::new(
-				&format!("{}{}", HEAD_KEY_FOR, name.to_string()), proc_macro2::Span::call_site()
-			);
-			quote!{ #instance::#const_name.as_bytes() }
-		} else {
-			let head_key = format!("head of {}", prefix);
-			quote!{ #head_key.as_bytes() }
-		};
-
-		let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos;
-
-		let from_optional_value_to_query = from_optional_value_to_query(is_option, fielddefault);
-		let from_query_to_optional_value = from_query_to_optional_value(is_option);
-
-		let trait_required = ext::type_contains_ident(value_type, traitinstance)
-			|| ext::type_contains_ident(kty, traitinstance);
-
-		let (struct_trait, impl_trait, trait_and_instance, where_clause) = if trait_required {
-			(
-				quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance),
-				quote!(#traitinstance: #traittype, #instance #bound_instantiable),
-				quote!(#traitinstance, #instance),
-				where_clause.clone(),
-			)
-		} else {
-			(
-				quote!(#instance #bound_instantiable #equal_default_instance),
-				quote!(#instance #bound_instantiable),
-				quote!(#instance),
-				None,
-			)
-		};
-
-		// generator for linked map
-		quote! {
-			#( #[ #attrs ] )*
-			#visibility struct #name<#struct_trait>(
-				#scrate::rstd::marker::PhantomData<(#trait_and_instance)>
-			) #where_clause;
-
-			impl<#impl_trait> #scrate::storage::generator::StorageLinkedMap<#kty, #typ>
-				for #name<#trait_and_instance> #where_clause
-			{
-				type Query = #value_type;
-				type Hasher = #scrate::#hasher;
-
-				fn prefix() -> &'static [u8] {
-					#final_prefix
-				}
-
-				fn head_key() -> &'static [u8] {
-					#head_key
-				}
-
-				fn from_optional_value_to_query(v: Option<#typ>) -> Self::Query {
-					#from_optional_value_to_query
-				}
-
-				fn from_query_to_optional_value(v: Self::Query) -> Option<#typ> {
-					#from_query_to_optional_value
-				}
-			}
-		}
-	}
-
-	pub fn double_map(
-		self,
-		hasher: TokenStream2,
-		k1ty: &syn::Type,
-		k2ty: &syn::Type,
-		k2_hasher: TokenStream2,
-	) -> TokenStream2 {
-		let Self {
-			scrate,
-			visibility,
-			traitinstance,
-			traittype,
-			type_infos,
-			fielddefault,
-			prefix,
-			name,
-			attrs,
-			instance_opts,
-			where_clause,
-			..
-		} = self;
-
-		let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos;
-
-		let from_optional_value_to_query = from_optional_value_to_query(is_option, fielddefault);
-		let from_query_to_optional_value = from_query_to_optional_value(is_option);
-
-		let InstanceOpts {
-			equal_default_instance,
-			bound_instantiable,
-			instance,
-			..
-		} = instance_opts;
-
-		let final_prefix = if let Some(instance) = instance {
-			let const_name = Ident::new(
-				&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()
-			);
-			quote!{ #instance::#const_name.as_bytes() }
-		} else {
-			quote!{ #prefix.as_bytes() }
-		};
-
-		let (struct_trait, impl_trait, trait_and_instance, where_clause) = if ext::type_contains_ident(
-			value_type, traitinstance
-		) || ext::type_contains_ident(k1ty, traitinstance) || ext::type_contains_ident(k2ty, traitinstance)
-		{
-			(
-				quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance),
-				quote!(#traitinstance: #traittype, #instance #bound_instantiable),
-				quote!(#traitinstance, #instance),
-				where_clause.clone(),
-			)
-		} else {
-			(
-				quote!(#instance #bound_instantiable #equal_default_instance),
-				quote!(#instance #bound_instantiable),
-				quote!(#instance),
-				None,
-			)
-		};
-
-		// generator for double map
-		quote!{
-			#( #[ #attrs ] )*
-			#visibility struct #name<#struct_trait> (
-				#scrate::rstd::marker::PhantomData<(#trait_and_instance)>
-			) #where_clause;
-
-			impl<#impl_trait> #scrate::storage::generator::StorageDoubleMap<#k1ty, #k2ty, #typ>
-				for #name<#trait_and_instance> #where_clause
-			{
-				type Query = #value_type;
-
-				type Hasher1 = #scrate::#hasher;
-
-				type Hasher2 = #scrate::#k2_hasher;
-
-				fn key1_prefix() -> &'static [u8] {
-					#final_prefix
-				}
-
-				fn from_optional_value_to_query(v: Option<#typ>) -> Self::Query {
-					#from_optional_value_to_query
-				}
-
-				fn from_query_to_optional_value(v: Self::Query) -> Option<#typ> {
-					#from_query_to_optional_value
-				}
-			}
-		}
-	}
-}
diff --git a/substrate/srml/support/procedural/src/storage/instance_trait.rs b/substrate/srml/support/procedural/src/storage/instance_trait.rs
new file mode 100644
index 00000000000..fe81dfe0db3
--- /dev/null
+++ b/substrate/srml/support/procedural/src/storage/instance_trait.rs
@@ -0,0 +1,196 @@
+// Copyright 2017-2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Substrate is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Implementation of the trait instance and the instance structures implementing it.
+//! (For not instantiable traits there is still the inherent instance implemented).
+
+use proc_macro2::{TokenStream, Span};
+use quote::quote;
+use super::{DeclStorageDefExt, StorageLineTypeDef};
+
+const NUMBER_OF_INSTANCE: usize = 16;
+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,
+	instance_struct: syn::Ident,
+	doc: TokenStream,
+}
+
+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));
+
+	// Implementation of instances.
+	if let Some(module_instance) = &def.module_instance {
+		let instance_defs = (0..NUMBER_OF_INSTANCE)
+			.map(|i| {
+				let name = format!("Instance{}", i);
+				InstanceDef {
+					instance_struct: syn::Ident::new(&name, proc_macro2::Span::call_site()),
+					prefix: name,
+					doc: quote!(#[doc=r"Module instance"]),
+				}
+			})
+			.chain(
+				module_instance.instance_default.as_ref().map(|ident| InstanceDef {
+					prefix: String::new(),
+					instance_struct: ident.clone(),
+					doc: quote!(#[doc=r"Default module instance"]),
+				})
+			);
+
+		for instance_def in instance_defs {
+			impls.extend(create_and_impl_instance_struct(scrate, &instance_def, &const_defs, def));
+		}
+	}
+
+	// The name of the inherently available instance.
+	let inherent_instance = syn::Ident::new(INHERENT_INSTANCE_NAME, Span::call_site());
+
+	// Implementation of inherent instance.
+	if let Some(default_instance) = def.module_instance.as_ref()
+		.and_then(|i| i.instance_default.as_ref())
+	{
+		impls.extend(quote! {
+			#[doc(hidden)]
+			pub type #inherent_instance = #default_instance;
+		});
+	} else {
+		let instance_def = InstanceDef {
+			prefix: String::new(),
+			instance_struct: inherent_instance,
+			doc: quote!(#[doc(hidden)]),
+		};
+		impls.extend(create_and_impl_instance_struct(scrate, &instance_def, &const_defs, 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 {
+		quote!(#[doc(hidden)])
+	};
+
+	quote! {
+		/// Tag a type as an instance of a module.
+		///
+		/// Defines storage prefixes, they must be unique.
+		#optional_hide
+		pub trait #instance_trait: 'static {
+			/// The prefix used by any storage entry of an instance.
+			const PREFIX: &'static str;
+			#const_impls
+		}
+	}
+}
+
+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()));
+
+	let instance_struct = &instance_def.instance_struct;
+	let prefix = format!("{}{}", instance_def.prefix, def.crate_name.to_string());
+	let doc = &instance_def.doc;
+
+	quote! {
+		// Those trait are derived because of wrong bounds for generics
+		#[cfg_attr(feature = "std", derive(Debug))]
+		#[derive(Clone, Eq, PartialEq, #scrate::codec::Encode, #scrate::codec::Decode)]
+		#doc
+		pub struct #instance_struct;
+		impl #instance_trait for #instance_struct {
+			const PREFIX: &'static str = #prefix;
+			#const_impls
+		}
+	}
+}
diff --git a/substrate/srml/support/procedural/src/storage/metadata.rs b/substrate/srml/support/procedural/src/storage/metadata.rs
new file mode 100644
index 00000000000..e280c7d8a20
--- /dev/null
+++ b/substrate/srml/support/procedural/src/storage/metadata.rs
@@ -0,0 +1,230 @@
+// Copyright 2017-2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Substrate is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Implementation of `storage_metadata` on module structure, used by construct_runtime.
+
+use srml_support_procedural_tools::clean_type_string;
+use proc_macro2::TokenStream;
+use quote::quote;
+use super::{DeclStorageDefExt, StorageLineDefExt, StorageLineTypeDef};
+
+fn storage_line_metadata_type(scrate: &TokenStream, line: &StorageLineDefExt) -> TokenStream {
+	let value_type = &line.value_type;
+	let value_type = clean_type_string(&quote!( #value_type ).to_string());
+	match &line.storage_type {
+		StorageLineTypeDef::Simple(_) => {
+			quote!{
+				#scrate::metadata::StorageEntryType::Plain(
+					#scrate::metadata::DecodeDifferent::Encode(#value_type),
+				)
+			}
+		},
+		StorageLineTypeDef::Map(map) => {
+			let hasher = map.hasher.into_metadata();
+			let key = &map.key;
+			let key = clean_type_string(&quote!(#key).to_string());
+			quote!{
+				#scrate::metadata::StorageEntryType::Map {
+					hasher: #scrate::metadata::#hasher,
+					key: #scrate::metadata::DecodeDifferent::Encode(#key),
+					value: #scrate::metadata::DecodeDifferent::Encode(#value_type),
+					is_linked: false,
+				}
+			}
+		},
+		StorageLineTypeDef::LinkedMap(map) => {
+			let hasher = map.hasher.into_metadata();
+			let key = &map.key;
+			let key = clean_type_string(&quote!(#key).to_string());
+			quote!{
+				#scrate::metadata::StorageEntryType::Map {
+					hasher: #scrate::metadata::#hasher,
+					key: #scrate::metadata::DecodeDifferent::Encode(#key),
+					value: #scrate::metadata::DecodeDifferent::Encode(#value_type),
+					is_linked: true,
+				}
+			}
+		},
+		StorageLineTypeDef::DoubleMap(map) => {
+			let hasher1 = map.hasher1.into_metadata();
+			let hasher2 = map.hasher2.into_metadata();
+			let key1 = &map.key1;
+			let key1 = clean_type_string(&quote!(#key1).to_string());
+			let key2 = &map.key2;
+			let key2 = clean_type_string(&quote!(#key2).to_string());
+			quote!{
+				#scrate::metadata::StorageEntryType::DoubleMap {
+					hasher: #scrate::metadata::#hasher1,
+					key1: #scrate::metadata::DecodeDifferent::Encode(#key1),
+					key2: #scrate::metadata::DecodeDifferent::Encode(#key2),
+					value: #scrate::metadata::DecodeDifferent::Encode(#value_type),
+					key2_hasher: #scrate::metadata::#hasher2,
+				}
+			}
+		},
+	}
+}
+
+fn default_byte_getter(
+	scrate: &TokenStream,
+	line: &StorageLineDefExt,
+	def: &DeclStorageDefExt,
+) -> (TokenStream, TokenStream) {
+	let default = line.default_value.as_ref().map(|d| quote!( #d ))
+		.unwrap_or_else(|| quote!( Default::default() ));
+
+	let str_name = line.name.to_string();
+	let struct_name = syn::Ident::new(&("__GetByteStruct".to_string() + &str_name), line.name.span());
+	let cache_name = syn::Ident::new(&("__CACHE_GET_BYTE_STRUCT_".to_string() + &str_name), line.name.span());
+
+	let runtime_generic = &def.module_runtime_generic;
+	let runtime_trait = &def.module_runtime_trait;
+	let optional_instance_bound_optional_default = &def.optional_instance_bound_optional_default;
+	let optional_instance_bound = &def.optional_instance_bound;
+	let optional_instance = &def.optional_instance;
+	let optional_comma_instance = optional_instance.as_ref().map(|i| quote!(, #i));
+	let where_clause = &def.where_clause;
+
+	let query_type = &line.query_type;
+
+	let struct_def = quote! {
+		#[doc(hidden)]
+		pub struct #struct_name<
+			#runtime_generic, #optional_instance_bound_optional_default
+		>(pub #scrate::rstd::marker::PhantomData<(#runtime_generic #optional_comma_instance)>);
+
+		#[cfg(feature = "std")]
+		#[allow(non_upper_case_globals)]
+		static #cache_name: #scrate::once_cell::sync::OnceCell<#scrate::rstd::vec::Vec<u8>> =
+			#scrate::once_cell::sync::OnceCell::new();
+
+		#[cfg(feature = "std")]
+		impl<#runtime_generic: #runtime_trait, #optional_instance_bound>
+			#scrate::metadata::DefaultByte
+			for #struct_name<#runtime_generic, #optional_instance>
+			#where_clause
+		{
+			fn default_byte(&self) -> #scrate::rstd::vec::Vec<u8> {
+				use #scrate::codec::Encode;
+				#cache_name.get_or_init(|| {
+					let def_val: #query_type = #default;
+					<#query_type as Encode>::encode(&def_val)
+				}).clone()
+			}
+		}
+
+		unsafe impl<#runtime_generic: #runtime_trait, #optional_instance_bound> Send
+			for #struct_name<#runtime_generic, #optional_instance> #where_clause {}
+
+		unsafe impl<#runtime_generic: #runtime_trait, #optional_instance_bound> Sync
+			for #struct_name<#runtime_generic, #optional_instance> #where_clause {}
+
+		#[cfg(not(feature = "std"))]
+		impl<#runtime_generic: #runtime_trait, #optional_instance_bound>
+			#scrate::metadata::DefaultByte
+			for #struct_name<#runtime_generic, #optional_instance>
+			#where_clause
+		{
+			fn default_byte(&self) -> #scrate::rstd::vec::Vec<u8> {
+				use #scrate::codec::Encode;
+				let def_val: #query_type = #default;
+				<#query_type as Encode>::encode(&def_val)
+			}
+		}
+	};
+	let struct_instance = quote!(
+		#struct_name::<#runtime_generic, #optional_instance>(#scrate::rstd::marker::PhantomData)
+	);
+
+	(struct_def, struct_instance)
+}
+
+pub fn impl_metadata(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream {
+	let mut entries = TokenStream::new();
+	let mut default_byte_getter_struct_defs = TokenStream::new();
+
+	for line in def.storage_lines.iter() {
+		let str_name = line.name.to_string();
+
+		let modifier = if line.is_option {
+			quote!(#scrate::metadata::StorageEntryModifier::Optional)
+		} else {
+			quote!(#scrate::metadata::StorageEntryModifier::Default)
+		};
+
+		let ty = storage_line_metadata_type(scrate, line);
+
+		let (
+			default_byte_getter_struct_def,
+			default_byte_getter_struct_instance,
+		) = default_byte_getter(scrate, line, def);
+
+		let mut docs = TokenStream::new();
+		for attr in line.attrs.iter().filter_map(|v| v.parse_meta().ok()) {
+			if let syn::Meta::NameValue(meta) = attr {
+				if meta.ident == "doc" {
+					let lit = meta.lit;
+					docs.extend(quote!(#lit,));
+				}
+			}
+		}
+
+		let entry = quote! {
+			#scrate::metadata::StorageEntryMetadata {
+				name: #scrate::metadata::DecodeDifferent::Encode(#str_name),
+				modifier: #modifier,
+				ty: #ty,
+				default: #scrate::metadata::DecodeDifferent::Encode(
+					#scrate::metadata::DefaultByteGetter(&#default_byte_getter_struct_instance)
+				),
+				documentation: #scrate::metadata::DecodeDifferent::Encode(&[ #docs ]),
+			},
+		};
+
+		default_byte_getter_struct_defs.extend(default_byte_getter_struct_def);
+		entries.extend(entry);
+	}
+
+	let prefix = if let Some(instance) = &def.module_instance {
+		let instance_generic = &instance.instance_generic;
+		quote!(#instance_generic::PREFIX)
+	} else {
+		let prefix = def.crate_name.to_string();
+		quote!(#prefix)
+	};
+
+	let store_metadata = quote!(
+		#scrate::metadata::StorageMetadata {
+			prefix: #scrate::metadata::DecodeDifferent::Encode(#prefix),
+			entries: #scrate::metadata::DecodeDifferent::Encode(&[ #entries ][..]),
+		}
+	);
+
+	let module_struct = &def.module_struct;
+	let module_impl = &def.module_impl;
+	let where_clause = &def.where_clause;
+
+	quote!(
+		#default_byte_getter_struct_defs
+
+		impl#module_impl #module_struct #where_clause {
+			#[doc(hidden)]
+			pub fn storage_metadata() -> #scrate::metadata::StorageMetadata {
+				#store_metadata
+			}
+		}
+	)
+}
diff --git a/substrate/srml/support/procedural/src/storage/mod.rs b/substrate/srml/support/procedural/src/storage/mod.rs
index 4253206f44d..9a6931d87e9 100644
--- a/substrate/srml/support/procedural/src/storage/mod.rs
+++ b/substrate/srml/support/procedural/src/storage/mod.rs
@@ -14,191 +14,358 @@
 // You should have received a copy of the GNU General Public License
 // along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
 
-// tag::description[]
-//! `decl_storage` macro
-// end::description[]
+//! `decl_storage` input definition and expansion.
+
+mod storage_struct;
+mod parse;
+mod store_trait;
+mod getters;
+mod metadata;
+mod instance_trait;
+mod genesis_config;
 
-use srml_support_procedural_tools::{ToTokens, Parse, syn_ext as ext};
-use syn::{Ident, Token};
-use proc_macro2::TokenStream as TokenStream2;
 use quote::quote;
+use srml_support_procedural_tools::{
+	generate_crate_access, generate_hidden_includes, syn_ext as ext
+};
 
-mod impls;
-
-pub mod transformation;
-
-mod keyword {
-	syn::custom_keyword!(hiddencrate);
-	syn::custom_keyword!(add_extra_genesis);
-	syn::custom_keyword!(extra_genesis_skip_phantom_data_field);
-	syn::custom_keyword!(config);
-	syn::custom_keyword!(build);
-	syn::custom_keyword!(get);
-	syn::custom_keyword!(map);
-	syn::custom_keyword!(linked_map);
-	syn::custom_keyword!(double_map);
-	syn::custom_keyword!(blake2_256);
-	syn::custom_keyword!(blake2_128);
-	syn::custom_keyword!(twox_256);
-	syn::custom_keyword!(twox_128);
-	syn::custom_keyword!(twox_64_concat);
-	syn::custom_keyword!(hasher);
+/// All informations contained in input of decl_storage
+pub struct DeclStorageDef {
+	/// Name of the module used to import hidden imports.
+	hidden_crate: Option<syn::Ident>,
+	/// Visibility of store trait.
+	visibility: syn::Visibility,
+	/// Name of store trait: usually `Store`.
+	store_trait: syn::Ident,
+	/// Module name used by construct_runtime: usually `Module`.
+	module_name: syn::Ident,
+	/// Usually `T`.
+	module_runtime_generic: syn::Ident,
+	/// Usually `Trait`
+	module_runtime_trait: syn::Path,
+	/// For instantiable module: usually `I: Instance=DefaultInstance`.
+	module_instance: Option<ModuleInstanceDef>,
+	/// Where claused used to constrain T and I even more.
+	where_clause: Option<syn::WhereClause>,
+	/// The extra build function used to build storage at genesis.
+	extra_genesis_build: Option<syn::Expr>,
+	/// The extra genesis config fields.
+	extra_genesis_config_lines: Vec<ExtraGenesisLineDef>,
+	/// Definition of storages.
+	storage_lines: Vec<StorageLineDef>,
+	/// Name of the crate, used for storage prefixes.
+	crate_name: syn::Ident,
 }
 
-/// Parsing usage only
-#[derive(Parse, ToTokens, Debug)]
-struct StorageDefinition {
-	pub hidden_crate: ext::Opt<SpecificHiddenCrate>,
-	pub visibility: syn::Visibility,
-	pub trait_token: Token![trait],
-	pub ident: Ident,
-	pub for_token: Token![for],
-	pub module_ident: Ident,
-	pub mod_lt_token: Token![<],
-	pub mod_param: syn::GenericParam,
-	pub mod_instance_param_token: Option<Token![,]>,
-	pub mod_instance: Option<syn::Ident>,
-	pub mod_instantiable_token: Option<Token![:]>,
-	pub mod_instantiable: Option<syn::Ident>,
-	pub mod_default_instance_token: Option<Token![=]>,
-	pub mod_default_instance: Option<syn::Ident>,
-	pub mod_gt_token: Token![>],
-	pub as_token: Token![as],
-	pub crate_ident: Ident,
-	pub where_clause: Option<syn::WhereClause>,
-	pub content: ext::Braces<ext::Punctuated<DeclStorageLine, Token![;]>>,
-	pub extra_genesis: ext::Opt<AddExtraGenesis>,
+impl syn::parse::Parse for DeclStorageDef {
+	fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
+		parse::parse(input)
+	}
 }
 
-#[derive(Parse, ToTokens, Debug)]
-struct SpecificHiddenCrate {
-	pub keyword: keyword::hiddencrate,
-	pub ident: ext::Parens<Ident>,
+/// Extended version of `DeclStorageDef` with useful precomputed value.
+pub struct DeclStorageDefExt {
+	/// Name of the module used to import hidden imports.
+	hidden_crate: Option<syn::Ident>,
+	/// Visibility of store trait.
+	visibility: syn::Visibility,
+	/// Name of store trait: usually `Store`.
+	store_trait: syn::Ident,
+	/// Module name used by construct_runtime: usually `Module`.
+	#[allow(unused)]
+	module_name: syn::Ident,
+	/// Usually `T`.
+	module_runtime_generic: syn::Ident,
+	/// Usually `Trait`.
+	module_runtime_trait: syn::Path,
+	/// For instantiable module: usually `I: Instance=DefaultInstance`.
+	module_instance: Option<ModuleInstanceDef>,
+	/// Where claused used to constrain T and I even more.
+	where_clause: Option<syn::WhereClause>,
+	/// The extra build function used to build storage at genesis.
+	extra_genesis_build: Option<syn::Expr>,
+	/// The extra genesis config fields.
+	extra_genesis_config_lines: Vec<ExtraGenesisLineDef>,
+	/// Definition of storages.
+	storage_lines: Vec<StorageLineDefExt>,
+	/// Name of the crate, used for storage prefixes.
+	crate_name: syn::Ident,
+	/// Full struct expansion: `Module<T, I>`.
+	module_struct: proc_macro2::TokenStream,
+	/// Impl block for module: `<T: Trait, I: Instance>`.
+	module_impl: proc_macro2::TokenStream,
+	/// For instantiable: `I`.
+	optional_instance: Option<proc_macro2::TokenStream>,
+	/// For instantiable: `I: Instance`.
+	optional_instance_bound: Option<proc_macro2::TokenStream>,
+	/// For instantiable: `I: Instance = DefaultInstance`.
+	optional_instance_bound_optional_default: Option<proc_macro2::TokenStream>,
 }
 
-#[derive(Parse, ToTokens, Debug)]
-struct AddExtraGenesis {
-	pub extragenesis_keyword: keyword::add_extra_genesis,
-	pub content: ext::Braces<AddExtraGenesisContent>,
-}
+impl From<DeclStorageDef> for DeclStorageDefExt {
+	fn from(mut def: DeclStorageDef) -> Self {
+		let storage_lines = def.storage_lines.drain(..).collect::<Vec<_>>();
+		let storage_lines = storage_lines.into_iter()
+			.map(|line| StorageLineDefExt::from_def(line, &def))
+			.collect();
+
+		let (
+			optional_instance,
+			optional_instance_bound,
+			optional_instance_bound_optional_default,
+		) = if let Some(instance) = def.module_instance.as_ref() {
+			let instance_generic = &instance.instance_generic;
+			let instance_trait= &instance.instance_trait;
+			let optional_equal_instance_default = instance.instance_default.as_ref()
+				.map(|d| quote!( = #d ));
+			(
+				Some(quote!(#instance_generic)),
+				Some(quote!(#instance_generic: #instance_trait)),
+				Some(quote!(#instance_generic: #instance_trait #optional_equal_instance_default)),
+			)
+		} else {
+			(None, None, None)
+		};
+
+		let module_runtime_generic = &def.module_runtime_generic;
+		let module_runtime_trait = &def.module_runtime_trait;
+		let module_name = &def.module_name;
 
-#[derive(Parse, ToTokens, Debug)]
-struct AddExtraGenesisContent {
-	pub lines: ext::Punctuated<AddExtraGenesisLineEnum, Token![;]>,
+		let module_struct = quote!(
+			#module_name<#module_runtime_generic, #optional_instance>
+		);
+
+		let module_impl = quote!(
+			<#module_runtime_generic: #module_runtime_trait + 'static, #optional_instance_bound>
+		);
+
+		Self {
+			hidden_crate: def.hidden_crate,
+			visibility: def.visibility,
+			store_trait: def.store_trait,
+			module_name: def.module_name,
+			module_runtime_generic: def.module_runtime_generic,
+			module_runtime_trait: def.module_runtime_trait,
+			module_instance: def.module_instance,
+			where_clause: def.where_clause,
+			extra_genesis_build: def.extra_genesis_build,
+			extra_genesis_config_lines: def.extra_genesis_config_lines,
+			crate_name: def.crate_name,
+			storage_lines,
+			module_struct,
+			module_impl,
+			optional_instance,
+			optional_instance_bound,
+			optional_instance_bound_optional_default,
+		}
+	}
 }
 
-#[derive(Parse, ToTokens, Debug)]
-enum AddExtraGenesisLineEnum {
-	AddExtraGenesisLine(AddExtraGenesisLine),
-	AddExtraGenesisBuild(DeclStorageBuild),
+/// Usually `I: Instance=DefaultInstance`.
+pub struct ModuleInstanceDef {
+	/// Usually: `I`.
+	instance_generic: syn::Ident,
+	/// Usually: `Instance`.
+	instance_trait: syn::Ident,
+	/// Usually: `DefaultInstance`.
+	instance_default: Option<syn::Ident>,
 }
 
-#[derive(Parse, ToTokens, Debug)]
-struct AddExtraGenesisLine {
-	pub attrs: ext::OuterAttributes,
-	pub config_keyword: keyword::config,
-	pub extra_field: ext::Parens<Ident>,
-	pub coldot_token: Token![:],
-	pub extra_type: syn::Type,
-	pub default_value: ext::Opt<DeclStorageDefault>,
+pub struct StorageLineDef {
+	attrs: Vec<syn::Attribute>,
+	/// Visibility of the storage struct.
+	visibility: syn::Visibility,
+	name: syn::Ident,
+	/// The name of getter function to be implemented on Module struct.
+	getter: Option<syn::Ident>,
+	/// The name of the field to be used in genesis config if any.
+	config: Option<syn::Ident>,
+	/// The build function of the storage if any.
+	build: Option<syn::Expr>,
+	/// Default value of genesis config field and also for storage when no value available.
+	default_value: Option<syn::Expr>,
+	storage_type: StorageLineTypeDef,
 }
 
-#[derive(Parse, ToTokens, Debug)]
-struct DeclStorageLine {
-	// attrs (main use case is doc)
-	pub attrs: ext::OuterAttributes,
-	// visibility (no need to make optional
-	pub visibility: syn::Visibility,
-	// name
-	pub name: Ident,
-	pub getter: ext::Opt<DeclStorageGetter>,
-	pub config: ext::Opt<DeclStorageConfig>,
-	pub build: ext::Opt<DeclStorageBuild>,
-	pub coldot_token: Token![:],
-	pub storage_type: DeclStorageType,
-	pub default_value: ext::Opt<DeclStorageDefault>,
+pub struct StorageLineDefExt {
+	#[allow(unused)]
+	attrs: Vec<syn::Attribute>,
+	/// Visibility of the storage struct.
+	visibility: syn::Visibility,
+	name: syn::Ident,
+	/// The name of getter function to be implemented on Module struct.
+	getter: Option<syn::Ident>,
+	/// The name of the field to be used in genesis config if any.
+	config: Option<syn::Ident>,
+	/// The build function of the storage if any.
+	build: Option<syn::Expr>,
+	/// Default value of genesis config field and also for storage when no value available.
+	default_value: Option<syn::Expr>,
+	storage_type: StorageLineTypeDef,
+	doc_attrs: Vec<syn::Meta>,
+	/// Either the type stored in storage or wrapped in an Option.
+	query_type: syn::Type,
+	/// The type stored in storage.
+	value_type: syn::Type,
+	/// Full struct, for example: `StorageName<T, I>`.
+	storage_struct: proc_macro2::TokenStream,
+	/// If storage is generic over runtime then `T`.
+	optional_storage_runtime_comma: Option<proc_macro2::TokenStream>,
+	/// If storage is generic over runtime then `T: Trait`.
+	optional_storage_runtime_bound_comma: Option<proc_macro2::TokenStream>,
+	/// The where clause to use to constrain generics if storage is generic over runtime.
+	optional_storage_where_clause: Option<proc_macro2::TokenStream>,
+	/// Full trait, for example: `storage::StorageMap<u32, u32>`.
+	storage_trait: proc_macro2::TokenStream,
+	/// Full trait, for example: `storage::generator::StorageMap<u32, u32>`.
+	storage_generator_trait: proc_macro2::TokenStream,
+	/// Weither the storage is generic.
+	is_generic: bool,
+	/// Weither the storage value is an option.
+	is_option: bool,
 }
 
+impl StorageLineDefExt {
+	fn from_def(storage_def: StorageLineDef, def: &DeclStorageDef) -> Self {
+		let is_generic = match &storage_def.storage_type {
+			StorageLineTypeDef::Simple(value) => {
+				ext::type_contains_ident(&value, &def.module_runtime_generic)
+			},
+			StorageLineTypeDef::Map(map) => {
+				ext::type_contains_ident(&map.key, &def.module_runtime_generic)
+					|| ext::type_contains_ident(&map.value, &def.module_runtime_generic)
+			}
+			StorageLineTypeDef::LinkedMap(map) => {
+				ext::type_contains_ident(&map.key, &def.module_runtime_generic)
+					|| ext::type_contains_ident(&map.value, &def.module_runtime_generic)
+			}
+			StorageLineTypeDef::DoubleMap(map) => {
+				ext::type_contains_ident(&map.key1, &def.module_runtime_generic)
+					|| ext::type_contains_ident(&map.key2, &def.module_runtime_generic)
+					|| ext::type_contains_ident(&map.value, &def.module_runtime_generic)
+			}
+		};
 
-#[derive(Parse, ToTokens, Debug)]
-struct DeclStorageGetter {
-	pub getter_keyword: keyword::get,
-	pub getfn: ext::Parens<Ident>,
-}
+		let query_type = match &storage_def.storage_type {
+			StorageLineTypeDef::Simple(value) => value.clone(),
+			StorageLineTypeDef::Map(map) => map.value.clone(),
+			StorageLineTypeDef::LinkedMap(map) => map.value.clone(),
+			StorageLineTypeDef::DoubleMap(map) => map.value.clone(),
+		};
+		let is_option = ext::extract_type_option(&query_type).is_some();
+		let value_type = ext::extract_type_option(&query_type).unwrap_or(query_type.clone());
 
-#[derive(Parse, ToTokens, Debug)]
-struct DeclStorageConfig {
-	pub config_keyword: keyword::config,
-	pub expr: ext::Parens<Option<syn::Ident>>,
-}
+		let module_runtime_generic = &def.module_runtime_generic;
+		let module_runtime_trait = &def.module_runtime_trait;
+		let optional_storage_runtime_comma = if is_generic {
+			Some(quote!( #module_runtime_generic, ))
+		} else {
+			None
+		};
+		let optional_storage_runtime_bound_comma = if is_generic {
+			Some(quote!( #module_runtime_generic: #module_runtime_trait, ))
+		} else {
+			None
+		};
 
-#[derive(Parse, ToTokens, Debug)]
-struct DeclStorageBuild {
-	pub build_keyword: keyword::build,
-	pub expr: ext::Parens<syn::Expr>,
-}
+		let storage_name = &storage_def.name;
+		let optional_instance_generic = def.module_instance.as_ref().map(|i| {
+			let instance_generic = &i.instance_generic;
+			quote!( #instance_generic )
+		});
+		let storage_struct = quote!(
+			#storage_name<#optional_storage_runtime_comma #optional_instance_generic>
+		);
 
-#[derive(Parse, ToTokens, Debug)]
-enum DeclStorageType {
-	Map(DeclStorageMap),
-	LinkedMap(DeclStorageLinkedMap),
-	DoubleMap(DeclStorageDoubleMap),
-	Simple(syn::Type),
+		let optional_storage_where_clause = if is_generic {
+			def.where_clause.as_ref().map(|w| quote!( #w ))
+		} else {
+			None
+		};
+
+		let storage_trait_trunkated = match &storage_def.storage_type {
+			StorageLineTypeDef::Simple(_) => {
+				quote!( StorageValue<#value_type> )
+			},
+			StorageLineTypeDef::Map(map) => {
+				let key = &map.key;
+				quote!( StorageMap<#key, #value_type> )
+			},
+			StorageLineTypeDef::LinkedMap(map) => {
+				let key = &map.key;
+				quote!( StorageLinkedMap<#key, #value_type> )
+			},
+			StorageLineTypeDef::DoubleMap(map) => {
+				let key1 = &map.key1;
+				let key2 = &map.key2;
+				quote!( StorageDoubleMap<#key1, #key2, #value_type> )
+			},
+		};
+
+		let storage_trait = quote!( storage::#storage_trait_trunkated );
+		let storage_generator_trait = quote!( storage::generator::#storage_trait_trunkated );
+
+		let doc_attrs = storage_def.attrs.iter()
+			.filter_map(|a| a.parse_meta().ok())
+			.filter(|m| m.name() == "doc")
+			.collect();
+
+		Self {
+			attrs: storage_def.attrs,
+			visibility: storage_def.visibility,
+			name: storage_def.name,
+			getter: storage_def.getter,
+			config: storage_def.config,
+			build: storage_def.build,
+			default_value: storage_def.default_value,
+			storage_type: storage_def.storage_type,
+			doc_attrs,
+			query_type,
+			value_type,
+			storage_struct,
+			optional_storage_runtime_comma,
+			optional_storage_runtime_bound_comma,
+			optional_storage_where_clause,
+			storage_trait,
+			storage_generator_trait,
+			is_generic,
+			is_option,
+		}
+	}
 }
 
-#[derive(Parse, ToTokens, Debug)]
-struct DeclStorageMap {
-	pub map_keyword: keyword::map,
-	pub hasher: ext::Opt<SetHasher>,
-	pub key: syn::Type,
-	pub ass_keyword: Token![=>],
-	pub value: syn::Type,
+pub enum StorageLineTypeDef {
+	Map(MapDef),
+	LinkedMap(MapDef),
+	DoubleMap(DoubleMapDef),
+	Simple(syn::Type),
 }
 
-#[derive(Parse, ToTokens, Debug)]
-struct DeclStorageLinkedMap {
-	pub map_keyword: keyword::linked_map,
-	pub hasher: ext::Opt<SetHasher>,
+pub struct MapDef {
+	pub hasher: HasherKind,
 	pub key: syn::Type,
-	pub ass_keyword: Token![=>],
+	/// This is the query value not the inner value used in storage trait implementation.
 	pub value: syn::Type,
 }
 
-#[derive(Parse, ToTokens, Debug)]
-struct DeclStorageDoubleMap {
-	pub map_keyword: keyword::double_map,
-	pub hasher: ext::Opt<SetHasher>,
+pub struct DoubleMapDef {
+	pub hasher1: HasherKind,
+	pub hasher2: HasherKind,
 	pub key1: syn::Type,
-	pub comma_keyword: Token![,],
-	pub key2_hasher: Hasher,
-	pub key2: ext::Parens<syn::Type>,
-	pub ass_keyword: Token![=>],
+	pub key2: syn::Type,
+	/// This is the query value not the inner value used in storage trait implementation.
 	pub value: syn::Type,
 }
 
-#[derive(Parse, ToTokens, Debug)]
-enum Hasher {
-	Blake2_256(keyword::blake2_256),
-	Blake2_128(keyword::blake2_128),
-	Twox256(keyword::twox_256),
-	Twox128(keyword::twox_128),
-	Twox64Concat(keyword::twox_64_concat),
-}
-
-#[derive(Parse, ToTokens, Debug)]
-struct DeclStorageDefault {
-	pub equal_token: Token![=],
-	pub expr: syn::Expr,
-}
-
-#[derive(Parse, ToTokens, Debug)]
-struct SetHasher {
-	pub hasher_keyword: keyword::hasher,
-	pub inner: ext::Parens<Hasher>,
+pub struct ExtraGenesisLineDef {
+	attrs: Vec<syn::Attribute>,
+	name: syn::Ident,
+	typ: syn::Type,
+	default: Option<syn::Expr>,
 }
 
 #[derive(Debug, Clone)]
-enum HasherKind {
+pub enum HasherKind {
 	Blake2_256,
 	Blake2_128,
 	Twox256,
@@ -206,26 +373,8 @@ enum HasherKind {
 	Twox64Concat,
 }
 
-impl From<&SetHasher> for HasherKind {
-	fn from(set_hasher: &SetHasher) -> Self {
-		(&set_hasher.inner.content).into()
-	}
-}
-
-impl From<&Hasher> for HasherKind {
-	fn from(hasher: &Hasher) -> Self {
-		match hasher {
-			Hasher::Blake2_256(_) => HasherKind::Blake2_256,
-			Hasher::Blake2_128(_) => HasherKind::Blake2_128,
-			Hasher::Twox256(_) => HasherKind::Twox256,
-			Hasher::Twox128(_) => HasherKind::Twox128,
-			Hasher::Twox64Concat(_) => HasherKind::Twox64Concat,
-		}
-	}
-}
-
 impl HasherKind {
-	fn into_storage_hasher_struct(&self) -> TokenStream2 {
+	fn to_storage_hasher_struct(&self) -> proc_macro2::TokenStream {
 		match self {
 			HasherKind::Blake2_256 => quote!( Blake2_256 ),
 			HasherKind::Blake2_128 => quote!( Blake2_128 ),
@@ -235,7 +384,7 @@ impl HasherKind {
 		}
 	}
 
-	fn into_metadata(&self) -> TokenStream2 {
+	fn into_metadata(&self) -> proc_macro2::TokenStream {
 		match self {
 			HasherKind::Blake2_256 => quote!( StorageHasher::Blake2_256 ),
 			HasherKind::Blake2_128 => quote!( StorageHasher::Blake2_128 ),
@@ -245,3 +394,39 @@ impl HasherKind {
 		}
 	}
 }
+
+/// Full implementation of decl_storage.
+pub fn decl_storage_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+	let def = syn::parse_macro_input!(input as DeclStorageDef);
+	let def_ext = DeclStorageDefExt::from(def);
+
+	let hidden_crate_name = def_ext.hidden_crate.as_ref().map(|i| i.to_string())
+		.unwrap_or_else(|| "decl_storage".to_string());
+
+	let scrate = generate_crate_access(&hidden_crate_name, "srml-support");
+	let scrate_decl = generate_hidden_includes(&hidden_crate_name, "srml-support");
+
+	let store_trait = store_trait::decl_and_impl(&def_ext);
+	let getters = getters::impl_getters(&scrate, &def_ext);
+	let metadata = metadata::impl_metadata(&scrate, &def_ext);
+	let instance_trait = instance_trait::decl_and_impl(&scrate, &def_ext);
+	let genesis_config = genesis_config::genesis_config_and_build_storage(&scrate, &def_ext);
+	let storage_struct = storage_struct::decl_and_impl(&scrate, &def_ext);
+
+	quote!(
+		use #scrate::{
+			StorageValue as _,
+			StorageMap as _,
+			StorageLinkedMap as _,
+			StorageDoubleMap as _
+		};
+
+		#scrate_decl
+		#store_trait
+		#getters
+		#metadata
+		#instance_trait
+		#genesis_config
+		#storage_struct
+	).into()
+}
diff --git a/substrate/srml/support/procedural/src/storage/parse.rs b/substrate/srml/support/procedural/src/storage/parse.rs
new file mode 100644
index 00000000000..8464077ca26
--- /dev/null
+++ b/substrate/srml/support/procedural/src/storage/parse.rs
@@ -0,0 +1,377 @@
+// Copyright 2017-2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Substrate is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Parsing of decl_storage input.
+
+use srml_support_procedural_tools::{ToTokens, Parse, syn_ext as ext};
+use syn::{Ident, Token};
+
+mod keyword {
+	syn::custom_keyword!(hiddencrate);
+	syn::custom_keyword!(add_extra_genesis);
+	syn::custom_keyword!(extra_genesis_skip_phantom_data_field);
+	syn::custom_keyword!(config);
+	syn::custom_keyword!(build);
+	syn::custom_keyword!(get);
+	syn::custom_keyword!(map);
+	syn::custom_keyword!(linked_map);
+	syn::custom_keyword!(double_map);
+	syn::custom_keyword!(blake2_256);
+	syn::custom_keyword!(blake2_128);
+	syn::custom_keyword!(twox_256);
+	syn::custom_keyword!(twox_128);
+	syn::custom_keyword!(twox_64_concat);
+	syn::custom_keyword!(hasher);
+}
+
+/// Parsing usage only
+#[derive(Parse, ToTokens, Debug)]
+struct StorageDefinition {
+	pub hidden_crate: ext::Opt<SpecificHiddenCrate>,
+	pub visibility: syn::Visibility,
+	pub trait_token: Token![trait],
+	pub ident: Ident,
+	pub for_token: Token![for],
+	pub module_ident: Ident,
+	pub mod_lt_token: Token![<],
+	pub mod_param_generic: syn::Ident,
+	pub mod_param_bound_token: Option<Token![:]>,
+	pub mod_param_bound: syn::Path,
+	pub mod_instance_param_token: Option<Token![,]>,
+	pub mod_instance: Option<syn::Ident>,
+	pub mod_instantiable_token: Option<Token![:]>,
+	pub mod_instantiable: Option<syn::Ident>,
+	pub mod_default_instance_token: Option<Token![=]>,
+	pub mod_default_instance: Option<syn::Ident>,
+	pub mod_gt_token: Token![>],
+	pub as_token: Token![as],
+	pub crate_ident: Ident,
+	pub where_clause: Option<syn::WhereClause>,
+	pub content: ext::Braces<ext::Punctuated<DeclStorageLine, Token![;]>>,
+	pub extra_genesis: ext::Opt<AddExtraGenesis>,
+}
+
+#[derive(Parse, ToTokens, Debug)]
+struct SpecificHiddenCrate {
+	pub keyword: keyword::hiddencrate,
+	pub ident: ext::Parens<Ident>,
+}
+
+#[derive(Parse, ToTokens, Debug)]
+struct AddExtraGenesis {
+	pub extragenesis_keyword: keyword::add_extra_genesis,
+	pub content: ext::Braces<AddExtraGenesisContent>,
+}
+
+#[derive(Parse, ToTokens, Debug)]
+struct AddExtraGenesisContent {
+	pub lines: ext::Punctuated<AddExtraGenesisLineEnum, Token![;]>,
+}
+
+#[derive(Parse, ToTokens, Debug)]
+enum AddExtraGenesisLineEnum {
+	AddExtraGenesisLine(AddExtraGenesisLine),
+	AddExtraGenesisBuild(DeclStorageBuild),
+}
+
+#[derive(Parse, ToTokens, Debug)]
+struct AddExtraGenesisLine {
+	pub attrs: ext::OuterAttributes,
+	pub config_keyword: keyword::config,
+	pub extra_field: ext::Parens<Ident>,
+	pub coldot_token: Token![:],
+	pub extra_type: syn::Type,
+	pub default_value: ext::Opt<DeclStorageDefault>,
+}
+
+#[derive(Parse, ToTokens, Debug)]
+struct DeclStorageLine {
+	// attrs (main use case is doc)
+	pub attrs: ext::OuterAttributes,
+	// visibility (no need to make optional
+	pub visibility: syn::Visibility,
+	// name
+	pub name: Ident,
+	pub getter: ext::Opt<DeclStorageGetter>,
+	pub config: ext::Opt<DeclStorageConfig>,
+	pub build: ext::Opt<DeclStorageBuild>,
+	pub coldot_token: Token![:],
+	pub storage_type: DeclStorageType,
+	pub default_value: ext::Opt<DeclStorageDefault>,
+}
+
+
+#[derive(Parse, ToTokens, Debug)]
+struct DeclStorageGetter {
+	pub getter_keyword: keyword::get,
+	pub getfn: ext::Parens<Ident>,
+}
+
+#[derive(Parse, ToTokens, Debug)]
+struct DeclStorageConfig {
+	pub config_keyword: keyword::config,
+	pub expr: ext::Parens<Option<syn::Ident>>,
+}
+
+#[derive(Parse, ToTokens, Debug)]
+struct DeclStorageBuild {
+	pub build_keyword: keyword::build,
+	pub expr: ext::Parens<syn::Expr>,
+}
+
+#[derive(Parse, ToTokens, Debug)]
+enum DeclStorageType {
+	Map(DeclStorageMap),
+	LinkedMap(DeclStorageLinkedMap),
+	DoubleMap(DeclStorageDoubleMap),
+	Simple(syn::Type),
+}
+
+#[derive(Parse, ToTokens, Debug)]
+struct DeclStorageMap {
+	pub map_keyword: keyword::map,
+	pub hasher: ext::Opt<SetHasher>,
+	pub key: syn::Type,
+	pub ass_keyword: Token![=>],
+	pub value: syn::Type,
+}
+
+#[derive(Parse, ToTokens, Debug)]
+struct DeclStorageLinkedMap {
+	pub map_keyword: keyword::linked_map,
+	pub hasher: ext::Opt<SetHasher>,
+	pub key: syn::Type,
+	pub ass_keyword: Token![=>],
+	pub value: syn::Type,
+}
+
+#[derive(Parse, ToTokens, Debug)]
+struct DeclStorageDoubleMap {
+	pub map_keyword: keyword::double_map,
+	pub hasher: ext::Opt<SetHasher>,
+	pub key1: syn::Type,
+	pub comma_keyword: Token![,],
+	pub key2_hasher: Hasher,
+	pub key2: ext::Parens<syn::Type>,
+	pub ass_keyword: Token![=>],
+	pub value: syn::Type,
+}
+
+#[derive(Parse, ToTokens, Debug)]
+enum Hasher {
+	Blake2_256(keyword::blake2_256),
+	Blake2_128(keyword::blake2_128),
+	Twox256(keyword::twox_256),
+	Twox128(keyword::twox_128),
+	Twox64Concat(keyword::twox_64_concat),
+}
+
+#[derive(Parse, ToTokens, Debug)]
+struct DeclStorageDefault {
+	pub equal_token: Token![=],
+	pub expr: syn::Expr,
+}
+
+#[derive(Parse, ToTokens, Debug)]
+struct SetHasher {
+	pub hasher_keyword: keyword::hasher,
+	pub inner: ext::Parens<Hasher>,
+}
+
+impl From<SetHasher> for super::HasherKind {
+	fn from(set_hasher: SetHasher) -> Self {
+		set_hasher.inner.content.into()
+	}
+}
+
+impl From<Hasher> for super::HasherKind {
+	fn from(hasher: Hasher) -> Self {
+		match hasher {
+			Hasher::Blake2_256(_) => super::HasherKind::Blake2_256,
+			Hasher::Blake2_128(_) => super::HasherKind::Blake2_128,
+			Hasher::Twox256(_) => super::HasherKind::Twox256,
+			Hasher::Twox128(_) => super::HasherKind::Twox128,
+			Hasher::Twox64Concat(_) => super::HasherKind::Twox64Concat,
+		}
+	}
+}
+
+fn get_module_instance(
+	instance: Option<syn::Ident>,
+	instantiable: Option<syn::Ident>,
+	default_instance: Option<syn::Ident>,
+) -> syn::Result<Option<super::ModuleInstanceDef>> {
+	let right_syntax = "Should be $Instance: $Instantiable = $DefaultInstance";
+
+	match (instance, instantiable, default_instance) {
+		(Some(instance), Some(instantiable), default_instance) => {
+			Ok(Some(super::ModuleInstanceDef {
+				instance_generic: instance,
+				instance_trait: instantiable,
+				instance_default: default_instance,
+			}))
+		},
+		(None, None, None) => Ok(None),
+		(Some(instance), None, _) => Err(
+			syn::Error::new(
+				instance.span(),
+				format!(
+					"Expect instantiable trait bound for instance: {}. {}",
+					instance,
+					right_syntax,
+				)
+			)
+		),
+		(None, Some(instantiable), _) => Err(
+			syn::Error::new(
+				instantiable.span(),
+				format!(
+					"Expect instance generic for bound instantiable: {}. {}",
+					instantiable,
+					right_syntax,
+				)
+			)
+		),
+		(None, _, Some(default_instance)) => Err(
+			syn::Error::new(
+				default_instance.span(),
+				format!(
+					"Expect instance generic for default instance: {}. {}",
+					default_instance,
+					right_syntax,
+				)
+			)
+		),
+	}
+}
+
+pub fn parse(input: syn::parse::ParseStream) -> syn::Result<super::DeclStorageDef> {
+	use syn::parse::Parse;
+	use syn::spanned::Spanned;
+
+	let def = StorageDefinition::parse(input)?;
+
+	let module_instance = get_module_instance(
+		def.mod_instance,
+		def.mod_instantiable,
+		def.mod_default_instance,
+	)?;
+
+	let mut extra_genesis_config_lines = vec![];
+	let mut extra_genesis_build = None;
+
+	for line in def.extra_genesis.inner.into_iter()
+		.flat_map(|o| o.content.content.lines.inner.into_iter())
+	{
+		match line {
+			AddExtraGenesisLineEnum::AddExtraGenesisLine(def) => {
+				extra_genesis_config_lines.push(super::ExtraGenesisLineDef{
+					attrs: def.attrs.inner,
+					name: def.extra_field.content,
+					typ: def.extra_type,
+					default: def.default_value.inner.map(|o| o.expr),
+				});
+			}
+			AddExtraGenesisLineEnum::AddExtraGenesisBuild(def) => {
+				if extra_genesis_build.is_some() {
+					return Err(syn::Error::new(
+						def.span(),
+						"Only one build expression allowed for extra genesis"
+					))
+				}
+
+				extra_genesis_build = Some(def.expr.content);
+			}
+		}
+	}
+
+	let mut storage_lines = vec![];
+
+	for line in def.content.content.inner.into_iter() {
+		let getter = line.getter.inner.map(|o| o.getfn.content);
+		let config = if let Some(config) = line.config.inner {
+			if let Some(ident) = config.expr.content {
+				Some(ident)
+			} else if let Some(ident) = getter.clone() {
+				Some(ident)
+			} else {
+				return Err(syn::Error::new(
+					config.span(),
+					"Invalid storage definiton, couldn't find config identifier: storage must either have a get \
+					identifier `get(ident)` or a defined config identifier `config(ident)`"
+				))
+			}
+		} else {
+			None
+		};
+
+		let storage_type = match line.storage_type {
+			DeclStorageType::Map(map) => super::StorageLineTypeDef::Map(
+				super::MapDef {
+					hasher: map.hasher.inner.map(Into::into)
+						.unwrap_or(super::HasherKind::Blake2_256),
+					key: map.key,
+					value: map.value,
+				}
+			),
+			DeclStorageType::LinkedMap(map) => super::StorageLineTypeDef::LinkedMap(
+				super::MapDef {
+					hasher: map.hasher.inner.map(Into::into)
+						.unwrap_or(super::HasherKind::Blake2_256),
+					key: map.key,
+					value: map.value,
+				}
+			),
+			DeclStorageType::DoubleMap(map) => super::StorageLineTypeDef::DoubleMap(
+				super::DoubleMapDef {
+					hasher1: map.hasher.inner.map(Into::into)
+						.unwrap_or(super::HasherKind::Blake2_256),
+					hasher2: map.key2_hasher.into(),
+					key1: map.key1,
+					key2: map.key2.content,
+					value: map.value,
+				}
+			),
+			DeclStorageType::Simple(expr) => super::StorageLineTypeDef::Simple(expr),
+		};
+
+		storage_lines.push(super::StorageLineDef {
+			attrs: line.attrs.inner,
+			visibility: line.visibility,
+			name: line.name,
+			getter,
+			config,
+			build: line.build.inner.map(|o| o.expr.content),
+			default_value: line.default_value.inner.map(|o| o.expr),
+			storage_type,
+		})
+	}
+
+	Ok(super::DeclStorageDef {
+		hidden_crate: def.hidden_crate.inner.map(|i| i.ident.content),
+		visibility: def.visibility,
+		module_name: def.module_ident,
+		store_trait: def.ident,
+		module_runtime_generic: def.mod_param_generic,
+		module_runtime_trait: def.mod_param_bound,
+		where_clause: def.where_clause,
+		crate_name: def.crate_ident,
+		module_instance,
+		extra_genesis_build,
+		extra_genesis_config_lines,
+		storage_lines,
+	})
+}
diff --git a/substrate/srml/support/procedural/src/storage/storage_struct.rs b/substrate/srml/support/procedural/src/storage/storage_struct.rs
new file mode 100644
index 00000000000..e195fb53e8a
--- /dev/null
+++ b/substrate/srml/support/procedural/src/storage/storage_struct.rs
@@ -0,0 +1,220 @@
+// Copyright 2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Substrate is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Implementation of storage structures and implementation of storage traits on them.
+
+use proc_macro2::TokenStream;
+use quote::quote;
+use super::{
+	DeclStorageDefExt, StorageLineTypeDef,
+	instance_trait::{PREFIX_FOR, HEAD_KEY_FOR},
+};
+
+fn from_optional_value_to_query(is_option: bool, default: &Option<syn::Expr>) -> TokenStream {
+	let default = default.as_ref().map(|d| quote!( #d ))
+		.unwrap_or_else(|| quote!( Default::default() ));
+
+	if !is_option {
+		// raw type case
+		quote!( v.unwrap_or_else(|| #default ) )
+	} else {
+		// Option<> type case
+		quote!( v.or_else(|| #default ) )
+	}
+}
+
+fn from_query_to_optional_value(is_option: bool) -> TokenStream {
+	if !is_option {
+		// raw type case
+		quote!( Some(v) )
+	} else {
+		// Option<> type case
+		quote!( v )
+	}
+}
+
+pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream {
+	let mut impls = TokenStream::new();
+
+	for line in &def.storage_lines {
+
+		// Propagate doc attributes.
+		let attrs = &line.doc_attrs;
+
+		let visibility = &line.visibility;
+		let optional_storage_runtime_comma = &line.optional_storage_runtime_comma;
+		let optional_storage_runtime_bound_comma = &line.optional_storage_runtime_bound_comma;
+		let optional_storage_where_clause = &line.optional_storage_where_clause;
+		let optional_instance_bound_optional_default = &def.optional_instance_bound_optional_default;
+		let optional_instance_bound = &def.optional_instance_bound;
+		let optional_instance = &def.optional_instance;
+		let name = &line.name;
+
+		let struct_decl = quote!(
+			#( #[ #attrs ] )*
+			#visibility struct #name<
+				#optional_storage_runtime_bound_comma #optional_instance_bound_optional_default
+			>(
+				#scrate::rstd::marker::PhantomData<
+					(#optional_storage_runtime_comma #optional_instance)
+				>
+			) #optional_storage_where_clause;
+		);
+
+		let from_query_to_optional_value = from_query_to_optional_value(line.is_option);
+		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() )
+		} else {
+			let prefix = format!("{} {}", def.crate_name, line.name);
+			quote!( #prefix.as_bytes() )
+		};
+
+
+		let storage_generator_trait = &line.storage_generator_trait;
+		let storage_struct = &line.storage_struct;
+		let impl_trait = quote!( #optional_storage_runtime_bound_comma #optional_instance_bound );
+		let value_type = &line.value_type;
+		let query_type = &line.query_type;
+
+		let struct_impl = match &line.storage_type {
+			StorageLineTypeDef::Simple(_) => {
+				quote!(
+					impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct
+					#optional_storage_where_clause
+					{
+						type Query = #query_type;
+
+						fn unhashed_key() -> &'static [u8] {
+							#final_prefix
+						}
+
+						fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query {
+							#from_optional_value_to_query
+						}
+
+						fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> {
+							#from_query_to_optional_value
+						}
+					}
+				)
+			},
+			StorageLineTypeDef::Map(map) => {
+				let hasher = map.hasher.to_storage_hasher_struct();
+				quote!(
+					impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct
+					#optional_storage_where_clause
+					{
+						type Query = #query_type;
+						type Hasher = #scrate::#hasher;
+
+						fn prefix() -> &'static [u8] {
+							#final_prefix
+						}
+
+						fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query {
+							#from_optional_value_to_query
+						}
+
+						fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> {
+							#from_query_to_optional_value
+						}
+					}
+				)
+			},
+			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() )
+				};
+
+				quote!(
+					impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct
+					#optional_storage_where_clause
+					{
+						type Query = #query_type;
+						type Hasher = #scrate::#hasher;
+
+						fn prefix() -> &'static [u8] {
+							#final_prefix
+						}
+
+						fn head_key() -> &'static [u8] {
+							#head_key
+						}
+
+						fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query {
+							#from_optional_value_to_query
+						}
+
+						fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> {
+							#from_query_to_optional_value
+						}
+					}
+				)
+			},
+			StorageLineTypeDef::DoubleMap(map) => {
+				let hasher1 = map.hasher1.to_storage_hasher_struct();
+				let hasher2 = map.hasher2.to_storage_hasher_struct();
+				quote!(
+					impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct
+					#optional_storage_where_clause
+					{
+						type Query = #query_type;
+
+						type Hasher1 = #scrate::#hasher1;
+
+						type Hasher2 = #scrate::#hasher2;
+
+						fn key1_prefix() -> &'static [u8] {
+							#final_prefix
+						}
+
+						fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query {
+							#from_optional_value_to_query
+						}
+
+						fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> {
+							#from_query_to_optional_value
+						}
+					}
+				)
+			}
+		};
+
+		impls.extend(quote!(
+			#struct_decl
+			#struct_impl
+		))
+	}
+
+	impls
+}
diff --git a/substrate/srml/support/procedural/src/storage/store_trait.rs b/substrate/srml/support/procedural/src/storage/store_trait.rs
new file mode 100644
index 00000000000..4c9d96b6bb2
--- /dev/null
+++ b/substrate/srml/support/procedural/src/storage/store_trait.rs
@@ -0,0 +1,54 @@
+// Copyright 2017-2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Substrate is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Declaration of store trait and implementation on module structure.
+
+use proc_macro2::TokenStream;
+use quote::quote;
+use super::DeclStorageDefExt;
+
+pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
+	let decl_store_items = def.storage_lines.iter()
+		.map(|sline| &sline.name)
+		.fold(TokenStream::new(), |mut items, name| {
+			items.extend(quote!(type #name;));
+			items
+		});
+
+	let impl_store_items = def.storage_lines.iter()
+		.fold(TokenStream::new(), |mut items, line| {
+			let name = &line.name;
+			let storage_struct = &line.storage_struct;
+
+			items.extend(quote!(type #name = #storage_struct;));
+			items
+		});
+
+	let visibility = &def.visibility;
+	let store_trait = &def.store_trait;
+	let module_struct = &def.module_struct;
+	let module_impl = &def.module_impl;
+	let where_clause = &def.where_clause;
+
+	quote!(
+		#visibility trait #store_trait {
+			#decl_store_items
+		}
+		impl#module_impl #store_trait for #module_struct #where_clause {
+			#impl_store_items
+		}
+	)
+}
diff --git a/substrate/srml/support/procedural/src/storage/transformation.rs b/substrate/srml/support/procedural/src/storage/transformation.rs
deleted file mode 100644
index c6a3a1f668c..00000000000
--- a/substrate/srml/support/procedural/src/storage/transformation.rs
+++ /dev/null
@@ -1,1264 +0,0 @@
-// Copyright 2017-2019 Parity Technologies (UK) Ltd.
-// This file is part of Substrate.
-
-// Substrate is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Substrate is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
-
-//! `decl_storage` macro transformation
-
-use srml_support_procedural_tools::syn_ext as ext;
-use srml_support_procedural_tools::{
-	generate_crate_access, generate_hidden_includes, clean_type_string
-};
-
-use proc_macro::TokenStream;
-use proc_macro2::{TokenStream as TokenStream2, Span};
-
-use syn::{
-	Ident,
-	GenericParam,
-	WhereClause,
-	spanned::Spanned,
-	parse::{
-		Error,
-		Result,
-	},
-	parse_macro_input,
-};
-use quote::{quote, quote_spanned};
-
-use super::*;
-
-const NUMBER_OF_INSTANCE: usize = 16;
-const DEFAULT_INSTANTIABLE_TRAIT_NAME: &str = "__GeneratedInstantiable";
-const DEFAULT_INSTANCE_NAME: &str = "__GeneratedInstance";
-const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance";
-
-// try macro but returning tokenized error
-macro_rules! try_tok(( $expre : expr ) => {
-	match $expre {
-		Ok(r) => r,
-		Err (err) => {
-			return err.to_compile_error().into()
-		}
-	}
-});
-
-pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
-	let def = parse_macro_input!(input as StorageDefinition);
-
-	let StorageDefinition {
-		hidden_crate,
-		visibility,
-		ident: storetype,
-		module_ident,
-		mod_param: strait,
-		mod_instance,
-		mod_instantiable,
-		mod_default_instance,
-		crate_ident: cratename,
-		content: ext::Braces { content: storage_lines, ..},
-		extra_genesis,
-		where_clause,
-		..
-	} = def;
-
-	let instance_opts = match get_instance_opts(
-		mod_instance,
-		mod_instantiable,
-		mod_default_instance
-	) {
-		Ok(opts) => opts,
-		Err(err) => return err.to_compile_error().into(),
-	};
-
-	let hidden_crate_name = hidden_crate.inner.map(|rc| rc.ident.content).map(|i| i.to_string())
-		.unwrap_or_else(|| "decl_storage".to_string());
-	let scrate = generate_crate_access(&hidden_crate_name, "srml-support");
-	let scrate_decl = generate_hidden_includes(
-		&hidden_crate_name,
-		"srml-support",
-	);
-
-	let (
-		traitinstance,
-		traittypes,
-	) = if let GenericParam::Type(syn::TypeParam {ident, bounds, ..}) = strait {
-		(ident, bounds)
-	} else {
-		return try_tok!(Err(Error::new(strait.span(), "Missing declare store generic params")));
-	};
-
-	let traittype =	if let Some(traittype) = traittypes.first() {
-		traittype.into_value()
-	} else {
-		return try_tok!(Err(Error::new(traittypes.span(), "Trait bound expected")));
-	};
-
-	let extra_genesis = try_tok!(decl_store_extra_genesis(
-		&scrate,
-		&traitinstance,
-		&traittype,
-		&instance_opts,
-		&storage_lines,
-		&extra_genesis.inner,
-		&where_clause,
-	));
-	let decl_storage_items = decl_storage_items(
-		&scrate,
-		&traitinstance,
-		&traittype,
-		&instance_opts,
-		&cratename,
-		&storage_lines,
-		&where_clause,
-	).unwrap_or_else(|err| err.to_compile_error());
-
-	let decl_store_items = decl_store_items(
-		&storage_lines,
-	);
-	let impl_store_items = impl_store_items(
-		&traitinstance,
-		&instance_opts.instance,
-		&storage_lines,
-	);
-	let impl_store_fns = impl_store_fns(
-		&scrate,
-		&traitinstance,
-		&instance_opts.instance,
-		&storage_lines,
-	);
-	let (store_default_struct, store_metadata) = store_functions_to_metadata(
-		&scrate,
-		&traitinstance,
-		&traittype,
-		&instance_opts,
-		&storage_lines,
-		&where_clause,
-		&cratename,
-	);
-
-	let InstanceOpts {
-		instance,
-		bound_instantiable,
-		..
-	} = instance_opts;
-
-	let expanded = quote! {
-		use #scrate::{
-			StorageValue as _,
-			StorageMap as _,
-			StorageLinkedMap as _,
-			StorageDoubleMap as _
-		};
-
-		#scrate_decl
-		#decl_storage_items
-		#visibility trait #storetype {
-			#decl_store_items
-		}
-		#store_default_struct
-		impl<#traitinstance: #traittype, #instance #bound_instantiable> #storetype
-			for #module_ident<#traitinstance, #instance> #where_clause
-		{
-			#impl_store_items
-		}
-		impl<#traitinstance: 'static + #traittype, #instance #bound_instantiable>
-			#module_ident<#traitinstance, #instance> #where_clause
-		{
-			#impl_store_fns
-			#[doc(hidden)]
-			pub fn storage_metadata() -> #scrate::metadata::StorageMetadata {
-				#store_metadata
-			}
-		}
-
-		#extra_genesis
-	};
-
-	expanded.into()
-}
-
-fn decl_store_extra_genesis(
-	scrate: &TokenStream2,
-	traitinstance: &Ident,
-	traittype: &syn::TypeParamBound,
-	instance_opts: &InstanceOpts,
-	storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
-	extra_genesis: &Option<AddExtraGenesis>,
-	where_clause: &Option<syn::WhereClause>,
-) -> Result<TokenStream2> {
-
-	let InstanceOpts {
-		equal_default_instance,
-		bound_instantiable,
-		instance,
-		..
-	} = instance_opts;
-
-	let mut is_trait_needed = false;
-	let mut serde_complete_bound = Vec::new();
-	let mut config_field = TokenStream2::new();
-	let mut config_field_default = TokenStream2::new();
-	let mut builders = TokenStream2::new();
-	let mut assimilate_require_generic = instance.is_some();
-	let mut builders_clone_bound = Vec::new();
-
-	for sline in storage_lines.inner.iter() {
-		let DeclStorageLine {
-			attrs,
-			name,
-			getter,
-			config,
-			build,
-			storage_type,
-			default_value,
-			..
-		} = sline;
-
-		let type_infos = get_type_infos(storage_type);
-
-		let opt_build = build
-			.inner
-			.as_ref()
-			.map(|b| {
-				assimilate_require_generic |= ext::expr_contains_ident(&b.expr.content, traitinstance);
-				&b.expr.content
-			})
-			.map(|b| quote!( #b ));
-
-		// need build line
-		let builder = if let Some(ref config) = config.inner {
-			let ident = if let Some(ident) = config.expr.content.as_ref() {
-				quote!( #ident )
-			} else if let Some(ref getter) = getter.inner {
-				let ident = &getter.getfn.content;
-				quote!( #ident )
-			} else {
-				return Err(
-					Error::new_spanned(
-						name,
-						"Invalid storage definiton, couldn't find config identifier: storage must either have a get identifier \
-						`get(ident)` or a defined config identifier `config(ident)`"
-					)
-				);
-			};
-
-			if ext::type_contains_ident(type_infos.value_type, traitinstance) {
-				is_trait_needed = true;
-			}
-
-			if opt_build.is_none() {
-				builders_clone_bound.push(type_infos.value_type.clone());
-			}
-
-			let value_type = &type_infos.value_type;
-			serde_complete_bound.push(quote!( #value_type ));
-			match type_infos.kind {
-				DeclStorageTypeInfosKind::Map { key_type, .. } => {
-					serde_complete_bound.push(quote!( #key_type ));
-					is_trait_needed = is_trait_needed
-						|| ext::type_contains_ident(key_type, traitinstance);
-
-					if opt_build.is_none() {
-						builders_clone_bound.push(key_type.clone());
-					}
-				},
-				DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => {
-					serde_complete_bound.push(quote!( #key1_type ));
-					serde_complete_bound.push(quote!( #key2_type ));
-					is_trait_needed = is_trait_needed
-						|| ext::type_contains_ident(key1_type, traitinstance)
-						|| ext::type_contains_ident(key2_type, traitinstance);
-					if opt_build.is_none() {
-						builders_clone_bound.push(key1_type.clone());
-						builders_clone_bound.push(key2_type.clone());
-					}
-				},
-				_ => {},
-			}
-
-			if type_infos.is_option {
-				serde_complete_bound.push(type_infos.typ.clone());
-			}
-
-			// Propagate doc attributes.
-			let attrs = attrs.inner.iter().filter_map(|a| a.parse_meta().ok()).filter(|m| m.name() == "doc");
-
-			let storage_type = type_infos.typ.clone();
-			config_field.extend(match type_infos.kind {
-				DeclStorageTypeInfosKind::Simple => {
-					quote!( #( #[ #attrs ] )* pub #ident: #storage_type, )
-				},
-				DeclStorageTypeInfosKind::Map {key_type, .. } => {
-					quote!( #( #[ #attrs ] )* pub #ident: Vec<(#key_type, #storage_type)>, )
-				},
-				DeclStorageTypeInfosKind::DoubleMap {key1_type, key2_type, .. } => {
-					quote!( #( #[ #attrs ] )* pub #ident: Vec<(#key1_type, #key2_type, #storage_type)>, )
-				},
-			});
-
-			let fielddefault = default_value.inner.as_ref().map(|d| &d.expr).map(|d|
-				if type_infos.is_option {
-					quote!( #d.unwrap_or_default() )
-				} else {
-					quote!( #d )
-				}).unwrap_or_else(|| quote!( Default::default() ));
-
-			config_field_default.extend(quote!( #ident: #fielddefault, ));
-
-			opt_build.or_else(|| Some(quote!( (|config: &Self| config.#ident.clone()) )))
-		} else {
-			opt_build
-		};
-
-		let typ = type_infos.typ;
-		if let Some(builder) = builder {
-			builders.extend(match type_infos.kind {
-				DeclStorageTypeInfosKind::Simple => {
-					let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance) {
-						assimilate_require_generic = true;
-						quote!(#traitinstance,)
-					} else {
-						quote!()
-					};
-
-					quote!{{
-						let v = (#builder)(&self);
-						<
-							#name<#struct_trait #instance> as
-							#scrate::storage::StorageValue<#typ>
-						>::put::<#typ>(v);
-					}}
-				},
-				DeclStorageTypeInfosKind::Map { key_type, is_linked, .. } => {
-					let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance)
-						|| ext::type_contains_ident(key_type, traitinstance)
-					{
-						assimilate_require_generic = true;
-						quote!(#traitinstance,)
-					} else {
-						quote!()
-					};
-
-					let map = if is_linked {
-						quote! { StorageLinkedMap }
-					} else {
-						quote! { StorageMap }
-					};
-
-					quote!{{
-						let data = (#builder)(&self);
-						data.into_iter().for_each(|(k, v)| {
-							<
-								#name<#struct_trait #instance> as
-								#scrate::storage::#map<#key_type, #typ>
-							>::insert::<#key_type, #typ>(k, v);
-						});
-					}}
-				},
-				DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => {
-					let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance)
-						|| ext::type_contains_ident(key1_type, traitinstance)
-						|| ext::type_contains_ident(key2_type, traitinstance)
-					{
-						assimilate_require_generic = true;
-						quote!(#traitinstance,)
-					} else {
-						quote!()
-					};
-
-					quote!{{
-						let data = (#builder)(&self);
-						data.into_iter().for_each(|(k1, k2, v)| {
-							<
-								#name<#struct_trait #instance> as
-								#scrate::storage::StorageDoubleMap<#key1_type, #key2_type, #typ>
-							>::insert::<#key1_type, #key2_type, #typ>(k1, k2, v);
-						});
-					}}
-				},
-			});
-		}
-	}
-
-	let mut has_scall = false;
-	let mut scall = quote!{ let scall: fn(&Self) = |_| {}; scall };
-	let mut genesis_extrafields = TokenStream2::new();
-	let mut genesis_extrafields_default = TokenStream2::new();
-
-	// extra genesis
-	if let Some(eg) = extra_genesis {
-		for ex_content in eg.content.content.lines.inner.iter() {
-			match ex_content {
-				AddExtraGenesisLineEnum::AddExtraGenesisLine(AddExtraGenesisLine {
-					attrs,
-					extra_field,
-					extra_type,
-					default_value,
-					..
-				}) => {
-					if ext::type_contains_ident(&extra_type, traitinstance) {
-						is_trait_needed = true;
-					}
-
-					serde_complete_bound.push(quote!( #extra_type ));
-
-					let extrafield = &extra_field.content;
-					genesis_extrafields.extend(quote!{
-						#attrs pub #extrafield: #extra_type,
-					});
-					let extra_default = default_value.inner.as_ref().map(|d| &d.expr).map(|e| quote!{ #e })
-						.unwrap_or_else(|| quote!( Default::default() ));
-					genesis_extrafields_default.extend(quote!{
-						#extrafield: #extra_default,
-					});
-				},
-				AddExtraGenesisLineEnum::AddExtraGenesisBuild(DeclStorageBuild{ expr, .. }) => {
-					if has_scall {
-						return Err(Error::new(expr.span(), "Only one build expression allowed for extra genesis"));
-					}
-					assimilate_require_generic |= ext::expr_contains_ident(&expr.content, traitinstance);
-					let content = &expr.content;
-					scall = quote_spanned! { expr.span() =>
-						let scall: fn(&Self) = #content; scall
-					};
-					has_scall = true;
-				},
-			}
-		}
-	}
-
-	let serde_bug_bound = if !serde_complete_bound.is_empty() {
-		let mut b_ser = String::new();
-		let mut b_dser = String::new();
-
-		serde_complete_bound.into_iter().for_each(|bound| {
-			let stype = quote!(#bound);
-			b_ser.push_str(&format!("{} : {}::serde::Serialize, ", stype, scrate));
-			b_dser.push_str(&format!("{} : {}::serde::de::DeserializeOwned, ", stype, scrate));
-		});
-
-		quote! {
-			#[serde(bound(serialize = #b_ser))]
-			#[serde(bound(deserialize = #b_dser))]
-		}
-	} else {
-		quote!()
-	};
-
-	let is_extra_genesis_needed = has_scall
-		|| !config_field.is_empty()
-		|| !genesis_extrafields.is_empty()
-		|| !builders.is_empty();
-	if is_extra_genesis_needed {
-		let (inherent_instance, inherent_bound_instantiable) = if instance.is_some() {
-			(instance.clone(), bound_instantiable.clone())
-		} else {
-			let instantiable = Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site());
-			(
-				Some(Ident::new(DEFAULT_INSTANCE_NAME, Span::call_site())),
-				quote!(: #instantiable),
-			)
-		};
-
-		let (fparam_struct, fparam_impl, sparam, build_storage_impl) = if is_trait_needed {
-			(
-				quote!(<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>),
-				quote!(<#traitinstance: #traittype, #instance #bound_instantiable>),
-				quote!(<#traitinstance, #instance>),
-				quote!(<#traitinstance: #traittype, #inherent_instance #inherent_bound_instantiable>),
-			)
-		} else {
-			// do not even need type parameter
-			(
-				quote!(),
-				quote!(),
-				quote!(),
-				quote!(<#traitinstance: #traittype, #inherent_instance #inherent_bound_instantiable>),
-			)
-		};
-
-		let (fn_generic, fn_traitinstance) = if !is_trait_needed && assimilate_require_generic {
-			(
-				quote!( <#traitinstance: #traittype, #instance #bound_instantiable> ),
-				quote!( #traitinstance, #instance )
-			)
-		} else {
-			(quote!(), quote!())
-		};
-
-		let impl_trait = quote!(BuildModuleGenesisStorage<#traitinstance, #inherent_instance>);
-
-		let extend_where_clause = |to_extend: &mut WhereClause| {
-			if let Some(where_clause) = where_clause {
-				to_extend.predicates.extend(where_clause.predicates.iter().cloned());
-			}
-		};
-
-		let mut genesis_where_clause: WhereClause = syn::parse_quote!(
-			where #( #builders_clone_bound: Clone ),*
-		);
-		let mut fn_where_clause = genesis_where_clause.clone();
-
-
-		let mut build_storage_where_clause = genesis_where_clause.clone();
-		extend_where_clause(&mut build_storage_where_clause);
-
-		if is_trait_needed {
-			extend_where_clause(&mut genesis_where_clause);
-		} else if assimilate_require_generic {
-			extend_where_clause(&mut fn_where_clause);
-		}
-
-		let res = quote!{
-			#[derive(#scrate::Serialize, #scrate::Deserialize)]
-			#[cfg(feature = "std")]
-			#[serde(rename_all = "camelCase")]
-			#[serde(deny_unknown_fields)]
-			#serde_bug_bound
-			pub struct GenesisConfig#fparam_struct #genesis_where_clause {
-				#config_field
-				#genesis_extrafields
-			}
-
-			#[cfg(feature = "std")]
-			impl#fparam_impl Default for GenesisConfig#sparam #genesis_where_clause {
-				fn default() -> Self {
-					GenesisConfig {
-						#config_field_default
-						#genesis_extrafields_default
-					}
-				}
-			}
-
-			#[cfg(feature = "std")]
-			impl#fparam_impl GenesisConfig#sparam #genesis_where_clause {
-				pub fn build_storage #fn_generic (self) -> std::result::Result<
-					(
-						#scrate::sr_primitives::StorageOverlay,
-						#scrate::sr_primitives::ChildrenStorageOverlay,
-					),
-					String
-				> #fn_where_clause {
-					let mut storage = (Default::default(), Default::default());
-					self.assimilate_storage::<#fn_traitinstance>(&mut storage)?;
-					Ok(storage)
-				}
-
-				/// Assimilate the storage for this module into pre-existing overlays.
-				pub fn assimilate_storage #fn_generic (
-					self,
-					tuple_storage: &mut (
-						#scrate::sr_primitives::StorageOverlay,
-						#scrate::sr_primitives::ChildrenStorageOverlay,
-					),
-				) -> std::result::Result<(), String> #fn_where_clause {
-					#scrate::with_storage(tuple_storage, || {
-						#builders
-
-						#scall(&self);
-
-						Ok(())
-					})
-				}
-			}
-
-			#[cfg(feature = "std")]
-			impl#build_storage_impl #scrate::sr_primitives::#impl_trait
-				for GenesisConfig#sparam #build_storage_where_clause
-			{
-				fn build_module_genesis_storage(
-					self,
-					storage: &mut (
-						#scrate::sr_primitives::StorageOverlay,
-						#scrate::sr_primitives::ChildrenStorageOverlay,
-					),
-				) -> std::result::Result<(), String> {
-					self.assimilate_storage::<#fn_traitinstance> (storage)
-				}
-			}
-		};
-
-		Ok(res)
-	} else {
-		Ok(quote!())
-	}
-}
-
-fn create_and_impl_instance(
-	instance_prefix: &str,
-	ident: &Ident,
-	doc: &TokenStream2,
-	const_names: &[(Ident, String, String)],
-	scrate: &TokenStream2,
-	instantiable: &Ident,
-	cratename: &Ident,
-) -> TokenStream2 {
-	let mut const_impls = TokenStream2::new();
-
-	for (const_name, const_value_prefix, const_value_suffix) in const_names {
-		let const_value = format!("{}{}{}", const_value_prefix, instance_prefix, const_value_suffix);
-		const_impls.extend(quote! {
-			const #const_name: &'static str = #const_value;
-		});
-	}
-
-	let prefix = format!("{}{}", instance_prefix, cratename.to_string());
-
-	quote! {
-		// Those trait are derived because of wrong bounds for generics
-		#[cfg_attr(feature = "std", derive(Debug))]
-		#[derive(Clone, Eq, PartialEq, #scrate::codec::Encode, #scrate::codec::Decode)]
-		#doc
-		pub struct #ident;
-		impl #instantiable for #ident {
-			const PREFIX: &'static str = #prefix;
-			#const_impls
-		}
-	}
-}
-
-fn decl_storage_items(
-	scrate: &TokenStream2,
-	traitinstance: &Ident,
-	traittype: &syn::TypeParamBound,
-	instance_opts: &InstanceOpts,
-	cratename: &Ident,
-	storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
-	where_clause: &Option<WhereClause>,
-) -> syn::Result<TokenStream2> {
-	let mut impls = TokenStream2::new();
-
-	let InstanceOpts {
-		instance,
-		default_instance,
-		instantiable,
-		..
-	} = instance_opts;
-
-	let build_prefix = |cratename, name| format!("{} {}", cratename, name);
-
-	// Build Instantiable trait
-	let mut const_names = vec![];
-
-	for sline in storage_lines.inner.iter() {
-		let DeclStorageLine {
-			storage_type,
-			name,
-			..
-		} = sline;
-
-		let prefix = build_prefix(cratename, name);
-
-		let type_infos = get_type_infos(storage_type);
-
-		let const_name = syn::Ident::new(
-			&format!("{}{}", impls::PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()
-		);
-		const_names.push((const_name, String::new(), prefix.clone()));
-
-		if let DeclStorageTypeInfosKind::Map { is_linked: true, .. } = type_infos.kind {
-			let const_name = syn::Ident::new(
-				&format!("{}{}", impls::HEAD_KEY_FOR, name.to_string()), proc_macro2::Span::call_site()
-			);
-			const_names.push((const_name, "head of ".into(), prefix));
-		}
-	}
-
-	let instantiable = instantiable
-		.clone()
-		.unwrap_or_else(|| Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site()));
-
-	// Declare Instance trait
-	{
-		let mut const_impls = TokenStream2::new();
-		for (const_name, ..) in &const_names {
-			const_impls.extend(quote! {
-				const #const_name: &'static str;
-			});
-		}
-
-		let hide = if instance.is_some() {
-			quote!()
-		} else {
-			quote!(#[doc(hidden)])
-		};
-
-		impls.extend(quote! {
-			/// Tag a type as an instance of a module.
-			///
-			/// Defines storage prefixes, they must be unique.
-			#hide
-			pub trait #instantiable: 'static {
-				/// The prefix used by any storage entry of an instance.
-				const PREFIX: &'static str;
-				#const_impls
-			}
-		});
-	}
-
-	if instance.is_some() {
-		let instances = (0..NUMBER_OF_INSTANCE)
-			.map(|i| {
-				let name = format!("Instance{}", i);
-				let ident = Ident::new(&name, proc_macro2::Span::call_site());
-				(name, ident, quote! {#[doc=r"Module instance"]})
-			})
-			.chain(
-				default_instance
-					.clone()
-					.map(|ident|
-						(String::new(), ident, quote! {#[doc=r"Default module instance"]})
-					)
-			);
-
-		// Impl Instance trait for instances
-		for (instance_prefix, ident, doc) in instances {
-			impls.extend(
-				create_and_impl_instance(
-					&instance_prefix, &ident, &doc, &const_names, scrate, &instantiable, cratename
-				)
-			);
-		}
-	}
-
-	// The name of the inherently available instance.
-	let inherent_instance = Ident::new(INHERENT_INSTANCE_NAME, Span::call_site());
-
-	if default_instance.is_some() {
-		impls.extend(quote! {
-			#[doc(hidden)]
-			pub type #inherent_instance = #default_instance;
-		});
-	} else {
-		impls.extend(
-			create_and_impl_instance(
-				"",
-				&inherent_instance,
-				&quote!(#[doc(hidden)]),
-				&const_names,
-				scrate,
-				&instantiable,
-				cratename,
-			)
-		);
-	}
-
-	for sline in storage_lines.inner.iter() {
-		let DeclStorageLine {
-			attrs,
-			name,
-			storage_type,
-			default_value,
-			visibility,
-			..
-		} = sline;
-
-		let type_infos = get_type_infos(storage_type);
-
-		if type_infos.is_option && default_value.inner.is_some() {
-			return Err(syn::Error::new_spanned(
-				default_value,
-				"Default values for Option types are not supported"
-			));
-		}
-
-		let fielddefault = default_value.inner
-			.as_ref()
-			.map(|d| &d.expr)
-			.map(|d| quote!( #d ))
-			.unwrap_or_else(|| quote!{ Default::default() });
-		let kind = type_infos.kind.clone();
-		// Propagate doc attributes.
-		let attrs = attrs.inner.iter().filter_map(|a| a.parse_meta().ok()).filter(|m| m.name() == "doc");
-
-		let i = impls::Impls {
-			scrate,
-			visibility,
-			cratename,
-			traitinstance,
-			traittype,
-			instance_opts,
-			type_infos,
-			fielddefault,
-			prefix: build_prefix(cratename, name),
-			name,
-			attrs,
-			where_clause,
-		};
-
-		let implementation = match kind {
-			DeclStorageTypeInfosKind::Simple => {
-				i.simple_value()
-			},
-			DeclStorageTypeInfosKind::Map { key_type, is_linked: false, hasher } => {
-				i.map(hasher.into_storage_hasher_struct(), key_type)
-			},
-			DeclStorageTypeInfosKind::Map { key_type, is_linked: true, hasher } => {
-				i.linked_map(hasher.into_storage_hasher_struct(), key_type)
-			},
-			DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, key2_hasher, hasher } => {
-				i.double_map(hasher.into_storage_hasher_struct(), key1_type, key2_type, key2_hasher.into_storage_hasher_struct())
-			},
-		};
-		impls.extend(implementation)
-	}
-
-	Ok(impls)
-}
-
-fn decl_store_items(storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>) -> TokenStream2 {
-	storage_lines.inner.iter().map(|sline| &sline.name)
-		.fold(TokenStream2::new(), |mut items, name| {
-		items.extend(quote!(type #name;));
-		items
-	})
-}
-
-fn impl_store_items(
-	traitinstance: &Ident,
-	instance: &Option<syn::Ident>,
-	storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
-) -> TokenStream2 {
-	storage_lines.inner
-		.iter()
-		.fold(TokenStream2::new(), |mut items, line| {
-			let name = &line.name;
-			let type_infos = get_type_infos(&line.storage_type);
-			let requires_trait = match type_infos.kind {
-				DeclStorageTypeInfosKind::Simple => {
-					ext::type_contains_ident(&type_infos.value_type, traitinstance)
-				},
-				DeclStorageTypeInfosKind::Map { key_type, .. } => {
-					ext::type_contains_ident(&type_infos.value_type, traitinstance)
-						|| ext::type_contains_ident(key_type, traitinstance)
-				}
-				DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => {
-					ext::type_contains_ident(&type_infos.value_type, traitinstance)
-						|| ext::type_contains_ident(key1_type, traitinstance)
-						|| ext::type_contains_ident(key2_type, traitinstance)
-				}
-			};
-
-			let struct_trait = if requires_trait {
-				quote!(#traitinstance,)
-			} else {
-				quote!()
-			};
-
-			items.extend(
-				quote!(
-					type #name = #name<#struct_trait #instance>;
-				)
-			);
-			items
-		})
-}
-
-fn impl_store_fns(
-	scrate: &TokenStream2,
-	traitinstance: &Ident,
-	instance: &Option<syn::Ident>,
-	storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
-) -> TokenStream2 {
-	let mut items = TokenStream2::new();
-	for sline in storage_lines.inner.iter() {
-		let DeclStorageLine {
-			attrs,
-			name,
-			getter,
-			storage_type,
-			..
-		} = sline;
-
-		if let Some(getter) = getter.inner.as_ref() {
-			let get_fn = &getter.getfn.content;
-
-			let type_infos = get_type_infos(storage_type);
-			let value_type = type_infos.value_type;
-
-			// Propagate doc attributes.
-			let attrs = attrs.inner.iter().filter_map(|a| a.parse_meta().ok()).filter(|m| m.name() == "doc");
-
-			let typ = type_infos.typ;
-			let item = match type_infos.kind {
-				DeclStorageTypeInfosKind::Simple => {
-					let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance) {
-						quote!(#traitinstance,)
-					} else {
-						quote!()
-					};
-
-					quote!{
-						#( #[ #attrs ] )*
-						pub fn #get_fn() -> #value_type {
-							<
-								#name<#struct_trait #instance> as
-								#scrate::storage::StorageValue<#typ>
-							>::get()
-						}
-					}
-				},
-				DeclStorageTypeInfosKind::Map { key_type, is_linked, .. } => {
-					let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance)
-						|| ext::type_contains_ident(key_type, traitinstance)
-					{
-						quote!(#traitinstance,)
-					} else {
-						quote!()
-					};
-
-					let map = if is_linked {
-						quote! { StorageLinkedMap }
-					} else {
-						quote! { StorageMap }
-					};
-
-					quote!{
-						#( #[ #attrs ] )*
-						pub fn #get_fn<K: #scrate::codec::EncodeLike<#key_type>>(key: K) -> #value_type {
-							<
-								#name<#struct_trait #instance> as
-								#scrate::storage::#map<#key_type, #typ>
-							>::get(key)
-						}
-					}
-				}
-				DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => {
-					let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance)
-						|| ext::type_contains_ident(key1_type, traitinstance)
-						|| ext::type_contains_ident(key2_type, traitinstance)
-					{
-						quote!(#traitinstance,)
-					} else {
-						quote!()
-					};
-
-					quote!{
-						pub fn #get_fn<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> #value_type
-						where
-							KArg1: #scrate::codec::EncodeLike<#key1_type>,
-							KArg2: #scrate::codec::EncodeLike<#key2_type>,
-						{
-							<
-								#name<#struct_trait #instance> as
-								#scrate::storage::StorageDoubleMap<#key1_type, #key2_type, #typ>
-							>::get(k1, k2)
-						}
-					}
-				}
-			};
-			items.extend(item);
-		}
-	}
-	items
-}
-
-fn store_functions_to_metadata (
-	scrate: &TokenStream2,
-	traitinstance: &Ident,
-	traittype: &syn::TypeParamBound,
-	instance_opts: &InstanceOpts,
-	storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
-	where_clause: &Option<WhereClause>,
-	cratename: &Ident,
-) -> (TokenStream2, TokenStream2) {
-	let InstanceOpts {
-		comma_instance,
-		equal_default_instance,
-		bound_instantiable,
-		instance,
-		..
-	} = instance_opts;
-
-	let mut items = TokenStream2::new();
-	let mut default_getter_struct_def = TokenStream2::new();
-	for sline in storage_lines.inner.iter() {
-		let DeclStorageLine {
-			attrs,
-			name,
-			storage_type,
-			default_value,
-			..
-		} = sline;
-
-		let type_infos = get_type_infos(storage_type);
-		let value_type = type_infos.value_type;
-
-		let typ = type_infos.typ;
-		let styp = clean_type_string(&typ.to_string());
-		let stype = match type_infos.kind {
-			DeclStorageTypeInfosKind::Simple => {
-				quote!{
-					#scrate::metadata::StorageEntryType::Plain(
-						#scrate::metadata::DecodeDifferent::Encode(#styp),
-					)
-				}
-			},
-			DeclStorageTypeInfosKind::Map { key_type, is_linked, hasher } => {
-				let hasher = hasher.into_metadata();
-				let kty = clean_type_string(&quote!(#key_type).to_string());
-				quote!{
-					#scrate::metadata::StorageEntryType::Map {
-						hasher: #scrate::metadata::#hasher,
-						key: #scrate::metadata::DecodeDifferent::Encode(#kty),
-						value: #scrate::metadata::DecodeDifferent::Encode(#styp),
-						is_linked: #is_linked,
-					}
-				}
-			},
-			DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, key2_hasher, hasher } => {
-				let hasher = hasher.into_metadata();
-				let k1ty = clean_type_string(&quote!(#key1_type).to_string());
-				let k2ty = clean_type_string(&quote!(#key2_type).to_string());
-				let k2_hasher = key2_hasher.into_metadata();
-				quote!{
-					#scrate::metadata::StorageEntryType::DoubleMap {
-						hasher: #scrate::metadata::#hasher,
-						key1: #scrate::metadata::DecodeDifferent::Encode(#k1ty),
-						key2: #scrate::metadata::DecodeDifferent::Encode(#k2ty),
-						value: #scrate::metadata::DecodeDifferent::Encode(#styp),
-						key2_hasher: #scrate::metadata::#k2_hasher,
-					}
-				}
-			},
-		};
-		let modifier = if type_infos.is_option {
-			quote!{
-				#scrate::metadata::StorageEntryModifier::Optional
-			}
-		} else {
-			quote!{
-				#scrate::metadata::StorageEntryModifier::Default
-			}
-		};
-		let default = default_value.inner.as_ref().map(|d| &d.expr)
-			.map(|d| {
-				quote!( #d )
-			})
-			.unwrap_or_else(|| quote!( Default::default() ));
-		let mut docs = TokenStream2::new();
-		for attr in attrs.inner.iter().filter_map(|v| v.parse_meta().ok()) {
-			if let syn::Meta::NameValue(syn::MetaNameValue{
-				ref ident,
-				ref lit,
-				..
-			}) = attr {
-				if ident == "doc" {
-					docs.extend(quote!(#lit,));
-				}
-			}
-		}
-		let str_name = name.to_string();
-		let struct_name = proc_macro2::Ident::new(&("__GetByteStruct".to_string() + &str_name), name.span());
-		let cache_name = proc_macro2::Ident::new(&("__CACHE_GET_BYTE_STRUCT_".to_string() + &str_name), name.span());
-
-		let item = quote! {
-			#scrate::metadata::StorageEntryMetadata {
-				name: #scrate::metadata::DecodeDifferent::Encode(#str_name),
-				modifier: #modifier,
-				ty: #stype,
-				default: #scrate::metadata::DecodeDifferent::Encode(
-					#scrate::metadata::DefaultByteGetter(
-						&#struct_name::<#traitinstance, #instance>(#scrate::rstd::marker::PhantomData)
-					)
-				),
-				documentation: #scrate::metadata::DecodeDifferent::Encode(&[ #docs ]),
-			},
-		};
-		items.extend(item);
-
-		let def_get = quote! {
-			#[doc(hidden)]
-			pub struct #struct_name<
-				#traitinstance, #instance #bound_instantiable #equal_default_instance
-			>(pub #scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>);
-
-			#[cfg(feature = "std")]
-			#[allow(non_upper_case_globals)]
-			static #cache_name: #scrate::once_cell::sync::OnceCell<
-				#scrate::rstd::vec::Vec<u8>
-			> = #scrate::once_cell::sync::OnceCell::new();
-
-			#[cfg(feature = "std")]
-			impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::metadata::DefaultByte
-				for #struct_name<#traitinstance, #instance> #where_clause
-			{
-				fn default_byte(&self) -> #scrate::rstd::vec::Vec<u8> {
-					use #scrate::codec::Encode;
-					#cache_name.get_or_init(|| {
-						let def_val: #value_type = #default;
-						<#value_type as Encode>::encode(&def_val)
-					}).clone()
-				}
-			}
-
-			unsafe impl<#traitinstance: #traittype, #instance #bound_instantiable> Send
-				for #struct_name<#traitinstance, #instance> #where_clause {}
-
-			unsafe impl<#traitinstance: #traittype, #instance #bound_instantiable> Sync
-				for #struct_name<#traitinstance, #instance> #where_clause {}
-
-			#[cfg(not(feature = "std"))]
-			impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::metadata::DefaultByte
-				for #struct_name<#traitinstance, #instance> #where_clause
-			{
-				fn default_byte(&self) -> #scrate::rstd::vec::Vec<u8> {
-					use #scrate::codec::Encode;
-					let def_val: #value_type = #default;
-					<#value_type as Encode>::encode(&def_val)
-				}
-			}
-		};
-
-		default_getter_struct_def.extend(def_get);
-	}
-
-	let prefix = cratename.to_string();
-	let prefix = instance.as_ref().map_or_else(|| quote!(#prefix), |i| quote!(#i::PREFIX));
-
-	(default_getter_struct_def, quote!{
-		#scrate::metadata::StorageMetadata {
-			prefix: #scrate::metadata::DecodeDifferent::Encode(#prefix),
-			entries: #scrate::metadata::DecodeDifferent::Encode(&[ #items ][..]),
-		}
-	})
-}
-
-
-#[derive(Debug, Clone)]
-pub(crate) struct DeclStorageTypeInfos<'a> {
-	pub is_option: bool,
-	pub typ: TokenStream2,
-	pub value_type: &'a syn::Type,
-	kind: DeclStorageTypeInfosKind<'a>,
-}
-
-#[derive(Debug, Clone)]
-enum DeclStorageTypeInfosKind<'a> {
-	Simple,
-	Map {
-		hasher: HasherKind,
-		key_type: &'a syn::Type,
-		is_linked: bool,
-	},
-	DoubleMap {
-		hasher: HasherKind,
-		key1_type: &'a syn::Type,
-		key2_type: &'a syn::Type,
-		key2_hasher: HasherKind,
-	}
-}
-
-fn get_type_infos(storage_type: &DeclStorageType) -> DeclStorageTypeInfos {
-	let (value_type, kind) = match storage_type {
-		DeclStorageType::Simple(ref st) => (st, DeclStorageTypeInfosKind::Simple),
-		DeclStorageType::Map(ref map) => (&map.value, DeclStorageTypeInfosKind::Map {
-			hasher: map.hasher.inner.as_ref().map(|h| h.into()).unwrap_or(HasherKind::Blake2_256),
-			key_type: &map.key,
-			is_linked: false,
-		}),
-		DeclStorageType::LinkedMap(ref map) => (&map.value, DeclStorageTypeInfosKind::Map {
-			hasher: map.hasher.inner.as_ref().map(|h| h.into()).unwrap_or(HasherKind::Blake2_256),
-			key_type: &map.key,
-			is_linked: true,
-		}),
-		DeclStorageType::DoubleMap(ref map) => (&map.value, DeclStorageTypeInfosKind::DoubleMap {
-			hasher: map.hasher.inner.as_ref().map(|h| h.into()).unwrap_or(HasherKind::Blake2_256),
-			key1_type: &map.key1,
-			key2_type: &map.key2.content,
-			key2_hasher: (&map.key2_hasher).into(),
-		}),
-	};
-
-	let extracted_type = ext::extract_type_option(value_type);
-	let is_option = extracted_type.is_some();
-	let typ = extracted_type.unwrap_or(quote!( #value_type ));
-
-	DeclStorageTypeInfos {
-		is_option,
-		typ,
-		value_type,
-		kind,
-	}
-
-}
-
-#[derive(Default)]
-pub(crate) struct InstanceOpts {
-	pub instance: Option<Ident>,
-	pub default_instance: Option<Ident>,
-	pub instantiable: Option<Ident>,
-	pub comma_instance: TokenStream2,
-	pub equal_default_instance: TokenStream2,
-	pub bound_instantiable: TokenStream2,
-}
-
-fn get_instance_opts(
-	instance: Option<Ident>,
-	instantiable: Option<Ident>,
-	default_instance: Option<Ident>,
-) -> Result<InstanceOpts> {
-	let right_syntax = "Should be $Instance: $Instantiable = $DefaultInstance";
-
-	match (instance, instantiable, default_instance) {
-		(Some(instance), Some(instantiable), default_instance) => {
-			let (equal_default_instance, default_instance) = if let Some(def) = default_instance {
-				(quote!{= #def}, Some(def))
-			} else {
-				(quote!(), None)
-			};
-
-			Ok(InstanceOpts {
-				comma_instance: quote!{, #instance},
-				equal_default_instance,
-				bound_instantiable: quote!{: #instantiable},
-				instance: Some(instance),
-				default_instance,
-				instantiable: Some(instantiable),
-			})
-		},
-		(None, None, None) => Ok(Default::default()),
-		(Some(instance), None, _) => Err(
-			Error::new(
-				instance.span(),
-				format!(
-					"Expect instantiable trait bound for instance: {}. {}",
-					instance,
-					right_syntax,
-				)
-			)
-		),
-		(None, Some(instantiable), _) => Err(
-			Error::new(
-				instantiable.span(),
-				format!(
-					"Expect instance generic for bound instantiable: {}. {}",
-					instantiable,
-					right_syntax,
-				)
-			)
-		),
-		(None, _, Some(default_instance)) => Err(
-			Error::new(
-				default_instance.span(),
-				format!(
-					"Expect instance generic for default instance: {}. {}",
-					default_instance,
-					right_syntax,
-				)
-			)
-		),
-	}
-}
diff --git a/substrate/srml/support/procedural/tools/src/syn_ext.rs b/substrate/srml/support/procedural/tools/src/syn_ext.rs
index 1033ebcce2d..1658a6b4aea 100644
--- a/substrate/srml/support/procedural/tools/src/syn_ext.rs
+++ b/substrate/srml/support/procedural/tools/src/syn_ext.rs
@@ -184,13 +184,15 @@ impl<P: ToTokens> ToTokens for Opt<P> {
 	}
 }
 
-pub fn extract_type_option(typ: &syn::Type) -> Option<TokenStream> {
+pub fn extract_type_option(typ: &syn::Type) -> Option<syn::Type> {
 	if let syn::Type::Path(ref path) = typ {
 		let v = path.path.segments.last()?;
 		if v.value().ident == "Option" {
-			if let syn::PathArguments::AngleBracketed(ref a) = v.value().arguments {
-				let args = &a.args;
-				return Some(quote!{ #args })
+			// Option has only one type argument in angle bracket.
+			if let syn::PathArguments::AngleBracketed(a) = &v.value().arguments {
+				if let syn::GenericArgument::Type(typ) = a.args.last()?.value() {
+					return Some(typ.clone())
+				}
 			}
 		}
 	}
@@ -253,4 +255,4 @@ pub fn expr_contains_ident(expr: &syn::Expr, ident: &Ident) -> bool {
 
 	visit::visit_expr(&mut visit, expr);
 	visit.result
-}
\ No newline at end of file
+}
-- 
GitLab