diff --git a/substrate/core/test-runtime/wasm/Cargo.lock b/substrate/core/test-runtime/wasm/Cargo.lock index 984755fc82..b4731039c9 100644 --- a/substrate/core/test-runtime/wasm/Cargo.lock +++ b/substrate/core/test-runtime/wasm/Cargo.lock @@ -151,6 +151,15 @@ name = "crossbeam" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crossbeam-channel" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-deque" version = "0.6.2" @@ -1309,12 +1318,12 @@ dependencies = [ name = "substrate-consensus-common" version = "0.1.0" dependencies = [ + "crossbeam-channel 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", "substrate-inherents 0.1.0", @@ -1872,6 +1881,7 @@ dependencies = [ "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" +"checksum crossbeam-channel 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8d4f5844607ce8da3fff431e7dba56cda8bfcc570aa50bee36adba8a32b8cad7" "checksum crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe1b6f945f824c7a25afe44f62e25d714c0cc523f8e99d8db5cd1026e1269d3" "checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8" "checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72" diff --git a/substrate/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/substrate/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index 8fe26f1793..23239e917e 100644 Binary files a/substrate/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/substrate/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ diff --git a/substrate/node-template/runtime/wasm/Cargo.lock b/substrate/node-template/runtime/wasm/Cargo.lock index 905538fa8f..d06bef8fed 100644 --- a/substrate/node-template/runtime/wasm/Cargo.lock +++ b/substrate/node-template/runtime/wasm/Cargo.lock @@ -1563,12 +1563,12 @@ dependencies = [ name = "substrate-consensus-common" version = "0.1.0" dependencies = [ + "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", "substrate-inherents 0.1.0", diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index 2a3b8d873f..89f3a58030 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -61,7 +61,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_name: create_runtime_str!("substrate-node"), authoring_version: 10, spec_version: 29, - impl_version: 29, + impl_version: 30, apis: RUNTIME_API_VERSIONS, }; diff --git a/substrate/node/runtime/wasm/Cargo.lock b/substrate/node/runtime/wasm/Cargo.lock index d740d57ac6..29e7b12698 100644 --- a/substrate/node/runtime/wasm/Cargo.lock +++ b/substrate/node/runtime/wasm/Cargo.lock @@ -151,6 +151,15 @@ name = "crossbeam" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crossbeam-channel" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-deque" version = "0.6.2" @@ -1679,12 +1688,12 @@ dependencies = [ name = "substrate-consensus-common" version = "0.1.0" dependencies = [ + "crossbeam-channel 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", "substrate-inherents 0.1.0", @@ -2224,6 +2233,7 @@ dependencies = [ "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" +"checksum crossbeam-channel 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8d4f5844607ce8da3fff431e7dba56cda8bfcc570aa50bee36adba8a32b8cad7" "checksum crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe1b6f945f824c7a25afe44f62e25d714c0cc523f8e99d8db5cd1026e1269d3" "checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8" "checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72" diff --git a/substrate/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm b/substrate/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm index d797e49831..b6ff057716 100644 Binary files a/substrate/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm and b/substrate/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm differ diff --git a/substrate/srml/example/src/lib.rs b/substrate/srml/example/src/lib.rs index fbd4031869..4f4e0b96a0 100644 --- a/substrate/srml/example/src/lib.rs +++ b/substrate/srml/example/src/lib.rs @@ -63,6 +63,10 @@ decl_storage! { // `fn getter_name(key: KeyType) -> ValueType` for map items. Dummy get(dummy) config(): Option; + // A map that has enumerable entries. + Bar get(bar) config(): linked_map T::AccountId => T::Balance; + + // this one uses the default, we'll demonstrate the usage of 'mutate' API. Foo get(foo) config(): T::Balance; } @@ -292,6 +296,8 @@ mod tests { t.extend(balances::GenesisConfig::::default().build_storage().unwrap().0); t.extend(GenesisConfig::{ dummy: 42, + // we configure the map with (key, value) pairs. + bar: vec![(1, 2), (2, 3)], foo: 24, }.build_storage().unwrap().0); t.into() diff --git a/substrate/srml/support/procedural/src/storage/impls.rs b/substrate/srml/support/procedural/src/storage/impls.rs index 5336002830..e008c81f83 100644 --- a/substrate/srml/support/procedural/src/storage/impls.rs +++ b/substrate/srml/support/procedural/src/storage/impls.rs @@ -193,15 +193,14 @@ impl<'a> Impls<'a> { let head_key = format!("head of {}", prefix); let prefix = format!("{}", prefix); let name_lowercase = name.to_string().to_lowercase(); - let key_for = syn::Ident::new(&format!("key_for_{}", name_lowercase), name.span()); - let internal_module = syn::Ident::new(&format!("__internal_do_not_use_{}", name_lowercase), name.span()); - let linkage = syn::Ident::new(&format!("Linkage{}", name), name.span()); - let borrowing_linkage = syn::Ident::new(&format!("Borrowing{}", linkage), name.span()); - let enumerator = syn::Ident::new(&format!("Enumerator{}", name), name.span()); + let inner_module = syn::Ident::new(&format!("__linked_map_details_for_{}_do_not_use", name_lowercase), name.span()); + let linkage = syn::Ident::new(&format!("__LinkageFor{}DoNotUse", name), name.span()); + let phantom_data = quote! { #scrate::storage::generator::PhantomData }; + let as_map = quote!{ > }; let put_or_insert = quote! { match linkage { Some(linkage) => storage.put(key_for, &(val, linkage)), - None => >::insert(key, &val, storage), + None => #as_map::insert(key, &val, storage), } }; let mutate_impl = if !type_infos.is_option { @@ -210,146 +209,185 @@ impl<'a> Impls<'a> { quote! { match val { Some(ref val) => #put_or_insert, - None => >::remove(key, storage), + None => #as_map::remove(key, storage), } } }; // generator for linked map - quote! { + let helpers = quote! { + /// Linkage data of an element (it's successor and predecessor) + #[derive(#scrate::parity_codec_derive::Encode, #scrate::parity_codec_derive::Decode)] + pub(crate) struct #linkage { + /// Previous element key in storage (None for the first element) + pub previous: Option, + /// Next element key in storage (None for the last element) + pub next: Option, + } - mod #internal_module { + mod #inner_module { use super::*; - #[derive(Default, parity_codec_derive::Encode, parity_codec_derive::Decode)] - pub struct #linkage { - /// Previous element key in storage (None for the first element) - previous: Option<#kty>, - /// Next element key in storage (None for the last element) - next: Option<#kty>, - } + /// Re-exported version of linkage to overcome proc-macro derivation issue. + pub(crate) use super::#linkage as Linkage; - /// A helper struct to avoid unnecessary key cloning. - /// - /// NOTE It has to have exact same parity-codec encoding as #linkage! - #[derive(parity_codec_derive::Encode)] - struct #borrowing_linkage<'a> { - previous: Option<&'a #kty>, - next: Option<&'a #kty>, - } - - impl #linkage { - /// Update linkage when this element is removed. - /// - /// Takes care of updating previous and next elements points - /// as well as updates head if the element is first or last. - pub fn remove( - self, - storage: &S, - ) { - let next_key = self.next.as_ref().map(|x| #key_for(x)); - let prev_key = self.previous.as_ref().map(|x| #key_for(x)); - - if let Some(prev_key) = prev_key { - // Retrieve previous element and update `next` - let mut res = Self::read(storage, &*prev_key) - .expect("Linkage is updated in case entry is removed; it always points to existing keys; qed"); - res.1.next = self.next; - storage.put(&*prev_key, &res); - } else { - // we were first so let's update the head - Self::write_head(storage, self.next.as_ref()); - } - - if let Some(next_key) = next_key { - // Update previous of next element - let mut res = Self::read(storage, &*next_key) - .expect("Linkage is updated in case entry is removed; it always points to existing keys; qed"); - res.1.previous = self.previous; - storage.put(&*next_key, &res); - } - } - - /// Read the contained data and it's linkage. - pub fn read(storage: &S, key: &[u8]) -> Option<(#value_type, #linkage)> { - storage.get(key) - } - - /// Generate linkage for newly inserted element. - /// - /// Takes care of updating head and previous head's pointer. - pub fn insert_new_head( - storage: &S, - key: &#kty, - ) -> Self { - if let Some(head) = Self::read_head(storage) { - // update previous head predecessor - { - let head_key = #key_for(&head); - let (data, linkage) = Self::read(storage, &*head_key).expect(r#" - head is set when first element is inserted and unset when last element is removed; - if head is Some then it points to existing key; qed - "#); - storage.put(&*head_key, &(data, #borrowing_linkage { - next: linkage.next.as_ref(), - previous: Some(key), - })); - } - // update to current head - Self::write_head(storage, Some(key)); - // return linkage with pointer to previous head - let mut linkage = Self::default(); - linkage.next = Some(head); - linkage - } else { - // we are first - update the head and produce empty linkage - Self::write_head(storage, Some(key)); - Self::default() - } - } - - /// Read current head pointer. - pub fn read_head(storage: &S) -> Option<#kty> { - storage.get(#head_key.as_bytes()) - } - - /// Overwrite current head pointer. - /// - /// If `None` is given head is removed from storage. - fn write_head(storage: &S, head: Option<&#kty>) { - match head { - Some(head) => storage.put(#head_key.as_bytes(), head), - None => storage.kill(#head_key.as_bytes()), + impl Default for Linkage { + fn default() -> Self { + Self { + previous: None, + next: None, } } } - pub struct #enumerator<'a, S> { + /// A key-value pair iterator for enumerable map. + pub(crate) struct Enumerator<'a, S, K, V> { pub storage: &'a S, - pub next: Option<#kty>, + pub next: Option, + pub _data: #phantom_data, } - impl<'a, S: #scrate::GenericStorage> Iterator for #enumerator<'a, S> { - type Item = (#kty, #typ); + impl<'a, S: #scrate::GenericStorage, K, V> Iterator for Enumerator<'a, S, K, V> where + K: 'a + #scrate::codec::Codec, + V: 'a + #scrate::codec::Decode, + { + type Item = (K, V); fn next(&mut self) -> Option { let next = self.next.take()?; - let key_for = #key_for(&next); - let (val, linkage) = #linkage::read(self.storage, &*key_for) + let key_for = key_for(&next); + let (val, linkage): (V, Linkage) = self.storage.get(&*key_for) .expect("previous/next only contain existing entires; we enumerate using next; entry exists; qed"); self.next = linkage.next; Some((next, val)) } } - } - fn #key_for(key: &#kty) -> #scrate::rstd::vec::Vec { - let mut key_for = #prefix.as_bytes().to_vec(); - #scrate::codec::Encode::encode_to(&key, &mut key_for); - key_for - } + /// Generate a storage key for given item. + pub(crate) fn key_for(key: &Key) -> #scrate::rstd::vec::Vec { + let mut key_for = #prefix.as_bytes().to_vec(); + #scrate::codec::Encode::encode_to(&key, &mut key_for); + key_for + } - #visibility struct #name<#traitinstance: #traittype>(#scrate::storage::generator::PhantomData<#traitinstance>); + pub(crate) trait Utils<#traitinstance: #traittype> { + /// Update linkage when this element is removed. + /// + /// Takes care of updating previous and next elements points + /// as well as updates head if the element is first or last. + fn remove_linkage(linkage: Linkage<#kty>, storage: &S); + + /// Read the contained data and it's linkage. + fn read_with_linkage(storage: &S, key: &[u8]) -> Option<(#value_type, Linkage<#kty>)>; + + /// Generate linkage for newly inserted element. + /// + /// Takes care of updating head and previous head's pointer. + fn new_head_linkage( + storage: &S, + key: &#kty, + ) -> Linkage<#kty>; + + /// Read current head pointer. + fn read_head(storage: &S) -> Option<#kty>; + + /// Overwrite current head pointer. + /// + /// If `None` is given head is removed from storage. + fn write_head(storage: &S, head: Option<&#kty>); + } + } + }; + + let structure = quote! { + #visibility struct #name<#traitinstance: #traittype>(#phantom_data<#traitinstance>); + + impl<#traitinstance: #traittype> self::#inner_module::Utils<#traitinstance> for #name<#traitinstance> { + fn remove_linkage( + linkage: self::#inner_module::Linkage<#kty>, + storage: &S, + ) { + use self::#inner_module::{key_for, Utils}; + + let next_key = linkage.next.as_ref().map(|x| key_for(x)); + let prev_key = linkage.previous.as_ref().map(|x| key_for(x)); + + if let Some(prev_key) = prev_key { + // Retrieve previous element and update `next` + let mut res = Self::read_with_linkage(storage, &*prev_key) + .expect("Linkage is updated in case entry is removed; it always points to existing keys; qed"); + res.1.next = linkage.next; + storage.put(&*prev_key, &res); + } else { + // we were first so let's update the head + Self::write_head(storage, linkage.next.as_ref()); + } + + if let Some(next_key) = next_key { + // Update previous of next element + let mut res = Self::read_with_linkage(storage, &*next_key) + .expect("Linkage is updated in case entry is removed; it always points to existing keys; qed"); + res.1.previous = linkage.previous; + storage.put(&*next_key, &res); + } + } + + fn read_with_linkage( + storage: &S, + key: &[u8], + ) -> Option<(#value_type, self::#inner_module::Linkage<#kty>)> { + storage.get(key) + } + + fn new_head_linkage( + storage: &S, + key: &#kty, + ) -> self::#inner_module::Linkage<#kty> { + use self::#inner_module::{key_for, Utils}; + + if let Some(head) = Self::read_head(storage) { + // update previous head predecessor + { + let head_key = key_for(&head); + let (data, linkage) = Self::read_with_linkage(storage, &*head_key).expect(r#" + head is set when first element is inserted and unset when last element is removed; + if head is Some then it points to existing key; qed + "#); + storage.put(&*head_key, &(data, self::#inner_module::Linkage { + next: linkage.next.as_ref(), + previous: Some(key), + })); + } + // update to current head + Self::write_head(storage, Some(key)); + // return linkage with pointer to previous head + let mut linkage = self::#inner_module::Linkage::default(); + linkage.next = Some(head); + linkage + } else { + // we are first - update the head and produce empty linkage + Self::write_head(storage, Some(key)); + self::#inner_module::Linkage::default() + } + } + + fn read_head(storage: &S) -> Option<#kty> { + storage.get(#head_key.as_bytes()) + } + + fn write_head(storage: &S, head: Option<&#kty>) { + match head { + Some(head) => storage.put(#head_key.as_bytes(), head), + None => storage.kill(#head_key.as_bytes()), + } + } + } + }; + + quote! { + #helpers + + #structure impl<#traitinstance: #traittype> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance> { type Query = #value_type; @@ -361,49 +399,55 @@ impl<'a> Impls<'a> { /// Get the storage key used to fetch a value corresponding to a specific key. fn key_for(x: &#kty) -> #scrate::rstd::vec::Vec { - #key_for(x) + self::#inner_module::key_for(x) } /// Load the value associated with the given key from the map. fn get(key: &#kty, storage: &S) -> Self::Query { - storage.get(&*#key_for(key)).#option_simple_1(|| #fielddefault) + storage.get(&*#as_map::key_for(key)).#option_simple_1(|| #fielddefault) } /// Take the value, reading and removing it. fn take(key: &#kty, storage: &S) -> Self::Query { - let res: Option<(#value_type, self::#internal_module::#linkage)> = storage.take(&*#key_for(key)); + use self::#inner_module::{Utils, key_for}; + + let res: Option<(#value_type, self::#inner_module::Linkage<#kty>)> = storage.take(&*key_for(key)); match res { Some((data, linkage)) => { - linkage.remove(storage); + Self::remove_linkage(linkage, storage); data }, - None => #fielddefault + None => #fielddefault, } } /// Remove the value under a key. fn remove(key: &#kty, storage: &S) { - >::take(key, storage); + #as_map::take(key, storage); } /// Store a value to be associated with the given key from the map. fn insert(key: &#kty, val: &#typ, storage: &S) { - let key_for = &*#key_for(key); - let linkage = match self::#internal_module::#linkage::read(storage, key_for) { + use self::#inner_module::{Utils, key_for}; + + let key_for = &*key_for(key); + let linkage = match Self::read_with_linkage(storage, key_for) { // overwrite but reuse existing linkage Some((_data, linkage)) => linkage, // create new linkage - None => self::#internal_module::#linkage::insert_new_head(storage, key), + None => Self::new_head_linkage(storage, key), }; - storage.put(key_for, &(*val, linkage)) + storage.put(key_for, &(val, linkage)) } /// Mutate the value under a key fn mutate R, S: #scrate::GenericStorage>(key: &#kty, f: F, storage: &S) -> R { - let key_for = &*#key_for(key); - let (mut val, linkage) = self::#internal_module::#linkage::read(storage, key_for) + use self::#inner_module::{Utils, key_for}; + + let key_for = &*key_for(key); + let (mut val, linkage) = Self::read_with_linkage(storage, key_for) .map(|(data, linkage)| (data, Some(linkage))) - .#option_simple_1(|| (#fielddefault, None)); + .unwrap_or_else(|| (#fielddefault, None)); let ret = f(&mut val); #mutate_impl ; @@ -413,13 +457,21 @@ impl<'a> Impls<'a> { impl<#traitinstance: #traittype> #scrate::storage::generator::EnumerableStorageMap<#kty, #typ> for #name<#traitinstance> { fn head(storage: &S) -> Option<#kty> { - self::#internal_module::#linkage::read_head(storage) + use self::#inner_module::Utils; + + Self::read_head(storage) } - fn enumerate<'a, S: #scrate::GenericStorage>(storage: &'a S) -> #scrate::storage::generator::Box + 'a> { - #scrate::storage::generator::Box::new(self::#internal_module::#enumerator { - next: self::#internal_module::#linkage::read_head(storage), + fn enumerate<'a, S: #scrate::GenericStorage>(storage: &'a S) -> #scrate::storage::generator::Box + 'a> where + #kty: 'a, + #typ: 'a, + { + use self::#inner_module::{Utils, Enumerator}; + + #scrate::storage::generator::Box::new(Enumerator { + next: Self::read_head(storage), storage, + _data: #phantom_data::<#typ>::default(), }) } } diff --git a/substrate/srml/support/procedural/src/storage/transformation.rs b/substrate/srml/support/procedural/src/storage/transformation.rs index b481c114ac..736d39cae7 100644 --- a/substrate/srml/support/procedural/src/storage/transformation.rs +++ b/substrate/srml/support/procedural/src/storage/transformation.rs @@ -192,24 +192,33 @@ fn decl_store_extra_genesis( is_trait_needed = true; has_trait_field = true; } - for t in ext::get_non_bound_serde_derive_types(type_infos.value_type, &traitinstance).into_iter() { + for t in ext::get_non_bound_serde_derive_types(type_infos.value_type, &traitinstance) { serde_complete_bound.insert(t); } if let DeclStorageTypeInfosKind::Map { key_type, .. } = type_infos.kind { - for t in ext::get_non_bound_serde_derive_types(key_type, &traitinstance).into_iter() { + for t in ext::get_non_bound_serde_derive_types(key_type, &traitinstance) { serde_complete_bound.insert(t); } } let storage_type = type_infos.typ.clone(); - config_field.extend(quote!( pub #ident: #storage_type, )); + config_field.extend(match type_infos.kind { + DeclStorageTypeInfosKind::Simple => { + quote!( pub #ident: #storage_type, ) + }, + DeclStorageTypeInfosKind::Map {key_type, .. } => { + quote!( pub #ident: Vec<(#key_type, #storage_type)>, ) + }, + }); opt_build = Some(build.as_ref().map(|b| &b.expr.content).map(|b|quote!( #b )) .unwrap_or_else(|| quote!( (|config: &GenesisConfig<#traitinstance>| config.#ident.clone()) ))); + 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, )); } else { opt_build = build.as_ref().map(|b| &b.expr.content).map(|b| quote!( #b )); diff --git a/substrate/srml/support/src/lib.rs b/substrate/srml/support/src/lib.rs index 832c6cd5c9..5980f5ddad 100644 --- a/substrate/srml/support/src/lib.rs +++ b/substrate/srml/support/src/lib.rs @@ -136,11 +136,12 @@ macro_rules! for_each_tuple { #[cfg(test)] mod tests { use super::*; + use parity_codec::Codec; use runtime_io::{with_externalities, Blake2Hasher}; use runtime_primitives::BuildStorage; pub trait Trait { - type BlockNumber; + type BlockNumber: Codec + Default; type Origin; } @@ -160,6 +161,8 @@ mod tests { decl_storage! { trait Store for Module as Example { pub Data get(data) build(|_| vec![(15u32, 42u64)]): linked_map u32 => u64; + pub GenericData get(generic_data): linked_map T::BlockNumber => T::BlockNumber; + pub GenericData2 get(generic_data2): linked_map T::BlockNumber => Option; } } diff --git a/substrate/srml/support/src/storage/generator.rs b/substrate/srml/support/src/storage/generator.rs index d25d773221..e9c38e872c 100644 --- a/substrate/srml/support/src/storage/generator.rs +++ b/substrate/srml/support/src/storage/generator.rs @@ -223,7 +223,7 @@ pub trait EnumerableStorageMap: StorageMap(storage: &S) -> Option; /// Enumerate all elements in the map. - fn enumerate<'a, S: Storage>(storage: &'a S) -> Box + 'a>; + fn enumerate<'a, S: Storage>(storage: &'a S) -> Box + 'a> where K: 'a, V: 'a; } // FIXME #1466 Remove this in favour of `decl_storage` macro. diff --git a/substrate/srml/support/src/storage/mod.rs b/substrate/srml/support/src/storage/mod.rs index 96171b035c..6b6e68be19 100644 --- a/substrate/srml/support/src/storage/mod.rs +++ b/substrate/srml/support/src/storage/mod.rs @@ -345,7 +345,7 @@ pub trait EnumerableStorageMap: StorageMap { fn head() -> Option; /// Enumerate all elements in the map. - fn enumerate() -> Box>; + fn enumerate() -> Box> where K: 'static, V: 'static; } impl EnumerableStorageMap for U where U: generator::EnumerableStorageMap { @@ -353,7 +353,7 @@ impl EnumerableStorageMap for U where U: generator: >::head(&RuntimeStorage) } - fn enumerate() -> Box> { + fn enumerate() -> Box> where K: 'static, V: 'static { >::enumerate(&RuntimeStorage) } }