Implement a proper generic resolution in decl_storage! (#2913)

* Add failing test case

* move storage maps to blake2_128 (#2268)

* remove default hash, introduce twox_128 and blake2

* use blake2_128 & create ext_blake2_128

* refactor code

* add benchmark

* factorize generator

* fix

* parameterizable hasher

* some fix

* fix

* fix

* fix

* metadata

* fix

* remove debug print

* map -> blake2_256

* fix test

* fix test

* Apply suggestions from code review

Co-Authored-By: thiolliere <gui.thiolliere@gmail.com>

* impl twox 128 concat (#2353)

* impl twox_128_concat

* comment addressed

* fix

* impl twox_128->64_concat

* fix test

* Fix compilation and cleanup some docs

* Lol

* Remove traits from storage types that are not generic

* Get instance test almost working as wanted

* Make `srml-support-test` compile again :)

* Fixes test of srml-support

* Fix compilation

* Break some lines

* Remove incorrect macro match arm

* Integrates review feedback

* Update documentation

* Fix compilation
This commit is contained in:
Bastian Köcher
2019-06-27 13:40:22 +02:00
committed by GitHub
parent 23ea5d1795
commit 62b7c05def
55 changed files with 1441 additions and 860 deletions
+4 -4
View File
@@ -98,7 +98,7 @@ use proc_macro::TokenStream;
///
/// Storage items are accessible in multiple ways:
///
/// * The structure: `Foo::<T>`
/// * The structure: `Foo` or `Foo::<T>` depending if the value type is generic or not.
/// * The `Store` trait structure: `<Module<T> as Store>::Foo`
/// * The getter on the module that calls get on the structure: `Module::<T>::foo()`
///
@@ -136,9 +136,9 @@ use proc_macro::TokenStream;
/// trait Store for Module<T: Trait<I>, I: Instance=DefaultInstance> as Example {}
/// ```
///
/// Then the genesis config is generated with two generic parameters (i.e. `GenesisConfig<T, I>`)
/// and storage items are accessible using two generic parameters, e.g.:
/// `<Dummy<T, I>>::get()` or `Dummy::<T, I>::get()`.
/// Accessing the structure no requires the instance as generic parameter:
/// * `Foo::<I>` if the value type is not generic
/// * `Foo::<T, I>` if the value type is generic
#[proc_macro]
pub fn decl_storage(input: TokenStream) -> TokenStream {
storage::transformation::decl_storage_impl(input)
@@ -14,11 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use proc_macro2::TokenStream as TokenStream2;
use syn;
use quote::quote;
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;
pub fn option_unwrap(is_option: bool) -> TokenStream2 {
if !is_option {
// raw type case
@@ -79,7 +81,6 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
};
let InstanceOpts {
comma_instance,
equal_default_instance,
bound_instantiable,
instance,
@@ -87,20 +88,37 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
} = 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());
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() }
};
// generator for value
quote!{
#( #[ #attrs ] )*
#visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>
(#scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>);
let (struct_trait, impl_trait, trait_and_instance) = 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),
)
} else {
(
quote!(#instance #bound_instantiable #equal_default_instance),
quote!(#instance #bound_instantiable),
quote!(#instance)
)
};
impl<#traitinstance: #traittype, #instance #bound_instantiable>
#scrate::storage::hashed::generator::StorageValue<#typ> for #name<#traitinstance, #instance>
// generator for value
quote! {
#( #[ #attrs ] )*
#visibility struct #name<#struct_trait>(
#scrate::rstd::marker::PhantomData<(#trait_and_instance)>
);
impl<#impl_trait> #scrate::storage::hashed::generator::StorageValue<#typ>
for #name<#trait_and_instance>
{
type Query = #value_type;
@@ -170,7 +188,6 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
};
let InstanceOpts {
comma_instance,
equal_default_instance,
bound_instantiable,
instance,
@@ -184,14 +201,31 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
quote!{ #prefix.as_bytes() }
};
let (struct_trait, impl_trait, trait_and_instance) = if ext::type_contains_ident(value_type, traitinstance)
|| ext::type_contains_ident(kty, traitinstance)
{
(
quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance),
quote!(#traitinstance: #traittype, #instance #bound_instantiable),
quote!(#traitinstance, #instance),
)
} else {
(
quote!(#instance #bound_instantiable #equal_default_instance),
quote!(#instance #bound_instantiable),
quote!(#instance)
)
};
// generator for map
quote!{
#( #[ #attrs ] )*
#visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>
(#scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>);
#visibility struct #name<#struct_trait>(
#scrate::rstd::marker::PhantomData<(#trait_and_instance)>
);
impl<#traitinstance: #traittype, #instance #bound_instantiable>
#scrate::storage::hashed::generator::StorageMap<#kty, #typ> for #name<#traitinstance, #instance>
impl<#impl_trait>
#scrate::storage::hashed::generator::StorageMap<#kty, #typ> for #name<#trait_and_instance>
{
type Query = #value_type;
@@ -235,8 +269,8 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
}
}
impl<#traitinstance: 'static + #traittype, #instance #bound_instantiable>
#scrate::storage::hashed::generator::AppendableStorageMap<#kty, #typ> for #name<#traitinstance, #instance>
impl<#impl_trait> #scrate::storage::hashed::generator::AppendableStorageMap<#kty, #typ>
for #name<#trait_and_instance>
{}
}
}
@@ -257,7 +291,6 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
} = self;
let InstanceOpts {
comma_instance,
equal_default_instance,
bound_instantiable,
instance,
@@ -304,6 +337,26 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
}
};
let (struct_trait, impl_trait, trait_and_instance, trait_lifetime) = if ext::type_contains_ident(
value_type,
traitinstance
) || ext::type_contains_ident(kty, traitinstance)
{
(
quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance),
quote!(#traitinstance: #traittype, #instance #bound_instantiable),
quote!(#traitinstance, #instance),
quote!(#traitinstance: 'static),
)
} else {
(
quote!(#instance #bound_instantiable #equal_default_instance),
quote!(#instance #bound_instantiable),
quote!(#instance),
quote!()
)
};
// generator for linked map
let helpers = quote! {
/// Linkage data of an element (it's successor and predecessor)
@@ -337,15 +390,14 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
pub _data: #phantom_data<V>,
}
impl<'a, S: #scrate::HashedStorage<#scrate::#hasher>, #traitinstance: #traittype, #instance #bound_instantiable>
Iterator for Enumerator<'a, S, #kty, (#typ, #traitinstance, #instance)>
where #traitinstance: 'a
impl<'a, S: #scrate::HashedStorage<#scrate::#hasher>, #impl_trait>
Iterator for Enumerator<'a, S, #kty, (#typ, #trait_and_instance)>
{
type Item = (#kty, #typ);
fn next(&mut self) -> Option<Self::Item> {
let next = self.next.take()?;
let key_for = <super::#name<#traitinstance, #instance>
let key_for = <super::#name<#trait_and_instance>
as #scrate::storage::hashed::generator::StorageMap<#kty, #typ>>::key_for(&next);
let (val, linkage): (#typ, Linkage<#kty>) = self.storage.get(&*key_for)
@@ -355,7 +407,7 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
}
}
pub(crate) trait Utils<#traitinstance: #traittype, #instance #bound_instantiable> {
pub(crate) trait Utils<#struct_trait> {
/// Update linkage when this element is removed.
///
/// Takes care of updating previous and next elements points
@@ -388,9 +440,9 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
let structure = quote! {
#( #[ #attrs ] )*
#visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>(#phantom_data<(#traitinstance #comma_instance)>);
#visibility struct #name<#struct_trait>(#phantom_data<(#trait_and_instance)>);
impl<#traitinstance: #traittype, #instance #bound_instantiable> self::#inner_module::Utils<#traitinstance, #instance> for #name<#traitinstance, #instance> {
impl<#impl_trait> self::#inner_module::Utils<#trait_and_instance> for #name<#trait_and_instance> {
fn remove_linkage<S: #scrate::HashedStorage<#scrate::#hasher>>(
linkage: self::#inner_module::Linkage<#kty>,
storage: &mut S,
@@ -477,8 +529,8 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
#structure
impl<#traitinstance: #traittype, #instance #bound_instantiable>
#scrate::storage::hashed::generator::StorageMap<#kty, #typ> for #name<#traitinstance, #instance>
impl<#impl_trait>
#scrate::storage::hashed::generator::StorageMap<#kty, #typ> for #name<#trait_and_instance>
{
type Query = #value_type;
@@ -553,8 +605,10 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
}
}
impl<#traitinstance: 'static + #traittype, #instance #bound_instantiable>
#scrate::storage::hashed::generator::EnumerableStorageMap<#kty, #typ> for #name<#traitinstance, #instance>
impl<#impl_trait>
#scrate::storage::hashed::generator::EnumerableStorageMap<#kty, #typ> for #name<#trait_and_instance>
where
#trait_lifetime
{
fn head<S: #scrate::HashedStorage<#scrate::#hasher>>(storage: &S) -> Option<#kty> {
use self::#inner_module::Utils;
@@ -562,18 +616,20 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
Self::read_head(storage)
}
fn enumerate<'a, S>(storage: &'a S) -> #scrate::rstd::boxed::Box<dyn Iterator<Item = (#kty, #typ)> + 'a>
where
S: #scrate::HashedStorage<#scrate::#hasher>,
#kty: 'a,
#typ: 'a,
fn enumerate<'a, S>(
storage: &'a S
) -> #scrate::rstd::boxed::Box<dyn Iterator<Item = (#kty, #typ)> + 'a>
where
S: #scrate::HashedStorage<#scrate::#hasher>,
#kty: 'a,
#typ: 'a,
{
use self::#inner_module::{Utils, Enumerator};
#scrate::rstd::boxed::Box::new(Enumerator {
next: Self::read_head(storage),
storage,
_data: #phantom_data::<(#typ, #traitinstance, #instance)>::default(),
_data: #phantom_data::<(#typ, #trait_and_instance)>::default(),
})
}
}
@@ -620,7 +676,6 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
};
let InstanceOpts {
comma_instance,
equal_default_instance,
bound_instantiable,
instance,
@@ -634,14 +689,31 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
quote!{ #prefix.as_bytes() }
};
let (struct_trait, impl_trait, trait_and_instance) = 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),
)
} else {
(
quote!(#instance #bound_instantiable #equal_default_instance),
quote!(#instance #bound_instantiable),
quote!(#instance)
)
};
// generator for double map
quote!{
#( #[ #attrs ] )*
#visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>
(#scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>);
#visibility struct #name<#struct_trait>
(#scrate::rstd::marker::PhantomData<(#trait_and_instance)>);
impl<#traitinstance: #traittype, #instance #bound_instantiable>
#scrate::storage::unhashed::generator::StorageDoubleMap<#k1ty, #k2ty, #typ> for #name<#traitinstance, #instance>
impl<#impl_trait>
#scrate::storage::unhashed::generator::StorageDoubleMap<#k1ty, #k2ty, #typ> for #name<#trait_and_instance>
{
type Query = #value_type;
@@ -686,9 +758,7 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
#mutate_impl ;
ret
}
}
}
}
}
@@ -67,7 +67,6 @@ struct StorageDefinition {
pub crate_ident: Ident,
pub content: ext::Braces<ext::Punctuated<DeclStorageLine, Token![;]>>,
pub extra_genesis: ext::Opt<AddExtraGenesis>,
pub extra_genesis_skip_phantom_data_field: ext::Opt<ExtraGenesisSkipPhantomDataField>,
}
#[derive(Parse, ToTokens, Debug)]
@@ -82,12 +81,6 @@ struct AddExtraGenesis {
pub content: ext::Braces<AddExtraGenesisContent>,
}
#[derive(Parse, ToTokens, Debug)]
struct ExtraGenesisSkipPhantomDataField {
pub genesis_phantom_keyword: keyword::extra_genesis_skip_phantom_data_field,
pub token: Token![;],
}
#[derive(Parse, ToTokens, Debug)]
struct AddExtraGenesisContent {
pub lines: ext::Punctuated<AddExtraGenesisLineEnum, Token![;]>,
@@ -14,15 +14,15 @@
// 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 transformation
// end::description[]
use srml_support_procedural_tools::syn_ext as ext;
use srml_support_procedural_tools::{generate_crate_access, generate_hidden_includes, clean_type_string};
use srml_support_procedural_tools::{
generate_crate_access, generate_hidden_includes, clean_type_string
};
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use proc_macro2::{TokenStream as TokenStream2, Span};
use syn::{
Ident,
@@ -39,6 +39,9 @@ use quote::quote;
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 ) => {
@@ -65,11 +68,14 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
crate_ident: cratename,
content: ext::Braces { content: storage_lines, ..},
extra_genesis,
extra_genesis_skip_phantom_data_field,
..
} = def;
let instance_opts = match get_instance_opts(mod_instance, mod_instantiable, mod_default_instance) {
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(),
};
@@ -104,7 +110,6 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
&instance_opts,
&storage_lines,
&extra_genesis.inner,
extra_genesis_skip_phantom_data_field.inner.is_some(),
));
let decl_storage_items = decl_storage_items(
&scrate,
@@ -114,6 +119,7 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
&cratename,
&storage_lines,
);
let decl_store_items = decl_store_items(
&storage_lines,
);
@@ -172,7 +178,6 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
}
#extra_genesis
};
expanded.into()
@@ -185,11 +190,9 @@ fn decl_store_extra_genesis(
instance_opts: &InstanceOpts,
storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
extra_genesis: &Option<AddExtraGenesis>,
extra_genesis_skip_phantom_data_field: bool,
) -> Result<TokenStream2> {
let InstanceOpts {
comma_instance,
equal_default_instance,
bound_instantiable,
instance,
@@ -197,13 +200,14 @@ fn decl_store_extra_genesis(
} = instance_opts;
let mut is_trait_needed = false;
let mut has_trait_field = 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();
for sline in storage_lines.inner.iter() {
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,
@@ -217,9 +221,17 @@ fn decl_store_extra_genesis(
let type_infos = get_type_infos(storage_type);
let opt_build;
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
if let Some(ref config) = config.inner {
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 {
@@ -234,19 +246,37 @@ fn decl_store_extra_genesis(
)
);
};
if type_infos.kind.is_simple() && ext::has_parametric_type(type_infos.value_type, traitinstance) {
if ext::type_contains_ident(type_infos.value_type, traitinstance) {
is_trait_needed = true;
has_trait_field = 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 )),
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());
}
},
_ => {},
}
@@ -270,8 +300,6 @@ fn decl_store_extra_genesis(
quote!( #( #[ #attrs ] )* pub #ident: Vec<(#key1_type, #key2_type, #storage_type)>, )
},
});
opt_build = Some(build.inner.as_ref().map(|b| &b.expr.content).map(|b|quote!( #b ))
.unwrap_or_else(|| quote!( (|config: &GenesisConfig<#traitinstance, #instance>| config.#ident.clone()) )));
let fielddefault = default_value.inner.as_ref().map(|d| &d.expr).map(|d|
if type_infos.is_option {
@@ -281,48 +309,74 @@ fn decl_store_extra_genesis(
}).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 = build.inner.as_ref().map(|b| &b.expr.content).map(|b| quote!( #b ));
}
opt_build
};
let typ = type_infos.typ;
if let Some(builder) = opt_build {
is_trait_needed = true;
if let Some(builder) = builder {
builders.extend(match type_infos.kind {
DeclStorageTypeInfosKind::Simple => {
quote!{{
use #scrate::rstd::{cell::RefCell, marker::PhantomData};
use #scrate::codec::{Encode, Decode};
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<#traitinstance, #instance> as #scrate::storage::hashed::generator::StorageValue<#typ>>::put(&v, storage);
<
#name<#struct_trait #instance> as
#scrate::storage::hashed::generator::StorageValue<#typ>
>::put(&v, storage);
}}
},
DeclStorageTypeInfosKind::Map { key_type, .. } => {
quote!{{
use #scrate::rstd::{cell::RefCell, marker::PhantomData};
use #scrate::codec::{Encode, Decode};
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!()
};
quote!{{
let data = (#builder)(&self);
for (k, v) in data.into_iter() {
<#name<#traitinstance, #instance> as #scrate::storage::hashed::generator::StorageMap<#key_type, #typ>>::insert(&k, &v, storage);
}
data.into_iter().for_each(|(k, v)| {
<
#name<#struct_trait #instance> as
#scrate::storage::hashed::generator::StorageMap<#key_type, #typ>
>::insert(&k, &v, storage);
});
}}
},
DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => {
quote!{{
use #scrate::rstd::{cell::RefCell, marker::PhantomData};
use #scrate::codec::{Encode, Decode};
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);
for (k1, k2, v) in data.into_iter() {
<#name<#traitinstance, #instance> as #scrate::storage::unhashed::generator::StorageDoubleMap<#key1_type, #key2_type, #typ>>::insert(&k1, &k2, &v, storage);
}
data.into_iter().for_each(|(k1, k2, v)| {
<
#name<#struct_trait #instance> as
#scrate::storage::unhashed::generator::StorageDoubleMap<#key1_type, #key2_type, #typ>
>::insert(&k1, &k2, &v, storage);
});
}}
},
});
}
}
let mut has_scall = false;
@@ -341,9 +395,8 @@ fn decl_store_extra_genesis(
default_value,
..
}) => {
if ext::has_parametric_type(&extra_type, traitinstance) {
if ext::type_contains_ident(&extra_type, traitinstance) {
is_trait_needed = true;
has_trait_field = true;
}
serde_complete_bound.push(quote!( #extra_type ));
@@ -362,6 +415,7 @@ fn decl_store_extra_genesis(
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!( ( #content ) );
has_scall = true;
@@ -370,7 +424,6 @@ fn decl_store_extra_genesis(
}
}
let serde_bug_bound = if !serde_complete_bound.is_empty() {
let mut b_ser = String::new();
let mut b_dser = String::new();
@@ -393,46 +446,54 @@ fn decl_store_extra_genesis(
|| !config_field.is_empty()
|| !genesis_extrafields.is_empty()
|| !builders.is_empty();
Ok(if is_extra_genesis_needed {
let (fparam_struct, fparam_impl, sparam, ph_field, ph_default) = if is_trait_needed {
if (has_trait_field && instance.is_none()) || extra_genesis_skip_phantom_data_field {
// no phantom data required
(
quote!(<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>),
quote!(<#traitinstance: #traittype, #instance #bound_instantiable>),
quote!(<#traitinstance, #instance>),
quote!(),
quote!(),
)
} else {
// need phantom data
(
quote!(<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>),
quote!(<#traitinstance: #traittype, #instance #bound_instantiable>),
quote!(<#traitinstance, #instance>),
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),
)
};
quote!{
#[serde(skip)]
pub _genesis_phantom_data: #scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>,
},
quote!{
_genesis_phantom_data: Default::default(),
},
)
}
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!(), quote!())
(
quote!(),
quote!(),
quote!(),
quote!(<#traitinstance: #traittype, #inherent_instance #inherent_bound_instantiable>),
)
};
quote!{
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 builders_clone_bound = quote!( #( #builders_clone_bound: Clone ),* );
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 {
#ph_field
#config_field
#genesis_extrafields
}
@@ -441,7 +502,6 @@ fn decl_store_extra_genesis(
impl#fparam_impl Default for GenesisConfig#sparam {
fn default() -> Self {
GenesisConfig {
#ph_default
#config_field_default
#genesis_extrafields_default
}
@@ -449,23 +509,83 @@ fn decl_store_extra_genesis(
}
#[cfg(feature = "std")]
impl#fparam_impl #scrate::runtime_primitives::BuildStorage for GenesisConfig#sparam {
fn assimilate_storage(self, r: &mut #scrate::runtime_primitives::StorageOverlay, c: &mut #scrate::runtime_primitives::ChildrenStorageOverlay) -> ::std::result::Result<(), String> {
impl#fparam_impl GenesisConfig#sparam where #builders_clone_bound {
pub fn build_storage #fn_generic (self) -> std::result::Result<
(
#scrate::runtime_primitives::StorageOverlay,
#scrate::runtime_primitives::ChildrenStorageOverlay,
),
String
> {
let mut storage = Default::default();
let mut child_storage = Default::default();
self.assimilate_storage::<#fn_traitinstance>(&mut storage, &mut child_storage)?;
Ok((storage, child_storage))
}
/// Assimilate the storage for this module into pre-existing overlays.
pub fn assimilate_storage #fn_generic (
self,
r: &mut #scrate::runtime_primitives::StorageOverlay,
c: &mut #scrate::runtime_primitives::ChildrenStorageOverlay,
) -> std::result::Result<(), String> {
let storage = r;
#builders
let r = storage;
#scall(r, c, &self);
#scall(storage, c, &self);
Ok(())
}
}
}
#[cfg(feature = "std")]
impl#build_storage_impl #scrate::runtime_primitives::#impl_trait
for GenesisConfig#sparam where #builders_clone_bound
{
fn build_module_genesis_storage(
self,
r: &mut #scrate::runtime_primitives::StorageOverlay,
c: &mut #scrate::runtime_primitives::ChildrenStorageOverlay,
) -> std::result::Result<(), String> {
self.assimilate_storage::<#fn_traitinstance> (r, c)
}
}
};
Ok(res)
} else {
quote!()
})
Ok(quote!())
}
}
fn create_and_impl_instance(
prefix: &str,
ident: &Ident,
doc: &TokenStream2,
const_names: &[(Ident, String)],
scrate: &TokenStream2,
instantiable: &Ident,
) -> TokenStream2 {
let mut const_impls = TokenStream2::new();
for (const_name, partial_const_value) in const_names {
let const_value = format!("{}{}", partial_const_value, prefix);
const_impls.extend(quote! {
const #const_name: &'static str = #const_value;
});
}
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_impls
}
}
}
fn decl_storage_items(
@@ -489,82 +609,103 @@ fn decl_storage_items(
let build_prefix = |cratename, name| format!("{} {}", cratename, name);
// Build Instantiable trait
if instance.is_some() {
let mut const_names = vec![];
let mut const_names = vec![];
for sline in storage_lines.inner.iter() {
let DeclStorageLine {
storage_type,
name,
..
} = sline;
for sline in storage_lines.inner.iter() {
let DeclStorageLine {
storage_type,
name,
..
} = sline;
let prefix = build_prefix(cratename, name);
let prefix = build_prefix(cratename, name);
let type_infos = get_type_infos(storage_type);
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());
let partial_const_value = prefix.clone();
let const_name = syn::Ident::new(
&format!("{}{}", impls::PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()
);
let partial_const_value = prefix.clone();
const_names.push((const_name, partial_const_value));
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()
);
let partial_const_value = format!("head of {}", prefix);
const_names.push((const_name, partial_const_value));
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());
let partial_const_value = format!("head of {}", prefix);
const_names.push((const_name, partial_const_value));
}
}
}
// 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 instantiable = instantiable
.clone()
.unwrap_or_else(|| Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site()));
impls.extend(quote! {
/// Tag a type as an instance of a module.
///
/// Defines storage prefixes, they must be unique.
pub trait #instantiable: 'static {
#const_impls
}
// 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 {
#const_impls
}
});
}
if instance.is_some() {
let instances = (0..NUMBER_OF_INSTANCE)
.map(|i| {
let name = format!("Instance{}", i);
let ident = syn::Ident::new(&name, proc_macro2::Span::call_site());
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"]})));
.chain(
default_instance
.clone()
.map(|ident|
(String::new(), ident, quote! {#[doc=r"Default module instance"]})
)
);
// Impl Instance trait for instances
for (prefix, ident, doc) in instances {
let mut const_impls = TokenStream2::new();
for (const_name, partial_const_value) in &const_names {
let const_value = format!("{}{}", partial_const_value, prefix);
const_impls.extend(quote! {
const #const_name: &'static str = #const_value;
});
}
impls.extend(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_impls
}
});
impls.extend(
create_and_impl_instance(&prefix, &ident, &doc, &const_names, scrate, &instantiable)
);
}
}
// 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
)
);
}
for sline in storage_lines.inner.iter() {
let DeclStorageLine {
attrs,
@@ -630,15 +771,39 @@ fn impl_store_items(
instance: &Option<syn::Ident>,
storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
) -> TokenStream2 {
storage_lines.inner.iter().map(|sline| &sline.name)
.fold(TokenStream2::new(), |mut items, name| {
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<#traitinstance, #instance>;
type #name = #name<#struct_trait #instance>;
)
);
items
})
})
}
fn impl_store_fns(
@@ -669,29 +834,61 @@ fn impl_store_fns(
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<#traitinstance, #instance> as #scrate::storage::hashed::generator::StorageValue<#typ>> :: get(&#scrate::storage::RuntimeStorage)
<#name<#struct_trait #instance> as
#scrate::storage::hashed::generator::StorageValue<#typ>> :: get(
&#scrate::storage::RuntimeStorage
)
}
}
},
DeclStorageTypeInfosKind::Map { key_type, .. } => {
let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance)
|| ext::type_contains_ident(key_type, traitinstance)
{
quote!(#traitinstance,)
} else {
quote!()
};
quote!{
#( #[ #attrs ] )*
pub fn #get_fn<K: #scrate::rstd::borrow::Borrow<#key_type>>(key: K) -> #value_type {
<#name<#traitinstance, #instance> as #scrate::storage::hashed::generator::StorageMap<#key_type, #typ>> :: get(key.borrow(), &#scrate::storage::RuntimeStorage)
<
#name<#struct_trait #instance> as
#scrate::storage::hashed::generator::StorageMap<#key_type, #typ>
>::get(key.borrow(), &#scrate::storage::RuntimeStorage)
}
}
}
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::rstd::borrow::Borrow<#key1_type>,
KArg2: #scrate::rstd::borrow::Borrow<#key2_type>,
{
<#name<#traitinstance> as #scrate::storage::unhashed::generator::StorageDoubleMap<#key1_type, #key2_type, #typ>> :: get(k1.borrow(), k2.borrow(), &#scrate::storage::RuntimeStorage)
<
#name<#struct_trait #instance> as
#scrate::storage::unhashed::generator::StorageDoubleMap<#key1_type, #key2_type, #typ>
>::get(k1.borrow(), k2.borrow(), &#scrate::storage::RuntimeStorage)
}
}
}
@@ -799,6 +996,7 @@ fn store_functions_to_metadata (
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::StorageFunctionMetadata {
name: #scrate::metadata::DecodeDifferent::Encode(#str_name),
@@ -813,6 +1011,7 @@ fn store_functions_to_metadata (
},
};
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)>);
@@ -838,6 +1037,7 @@ fn store_functions_to_metadata (
}
}
};
default_getter_struct_def.extend(def_get);
}
(default_getter_struct_def, quote!{
@@ -874,15 +1074,6 @@ enum DeclStorageTypeInfosKind<'a> {
}
}
impl<'a> DeclStorageTypeInfosKind<'a> {
fn is_simple(&self) -> bool {
match *self {
DeclStorageTypeInfosKind::Simple => true,
_ => false,
}
}
}
fn get_type_infos(storage_type: &DeclStorageType) -> DeclStorageTypeInfos {
let (value_type, kind) = match storage_type {
DeclStorageType::Simple(ref st) => (st, DeclStorageTypeInfosKind::Simple),
@@ -919,29 +1110,29 @@ fn get_type_infos(storage_type: &DeclStorageType) -> DeclStorageTypeInfos {
#[derive(Default)]
pub(crate) struct InstanceOpts {
pub instance: Option<syn::Ident>,
pub default_instance: Option<syn::Ident>,
pub instantiable: Option<syn::Ident>,
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<syn::Ident>,
instantiable: Option<syn::Ident>,
default_instance: Option<syn::Ident>,
) -> syn::Result<InstanceOpts> {
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_def) => {
let (equal_default_instance, default_instance) = if let Some(default_instance) = default_instance_def {
(quote!{= #default_instance}, Some(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)
(quote!(), None)
};
Ok(InstanceOpts {
comma_instance: quote!{, #instance},
equal_default_instance,
@@ -952,8 +1143,35 @@ fn get_instance_opts(
})
},
(None, None, None) => Ok(Default::default()),
(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))),
(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,
)
)
),
}
}
@@ -18,22 +18,17 @@
//! Extension to syn types, mainly for parsing
// end::description[]
use syn::parse::{
Parse,
ParseStream,
Result,
};
use proc_macro2::TokenStream as T2;
use syn::{visit::{Visit, self}, parse::{Parse, ParseStream, Result}, Ident};
use proc_macro2::{TokenStream, TokenTree};
use quote::{ToTokens, quote};
use std::iter::once;
use syn::Ident;
use srml_support_procedural_tools_derive::{ToTokens, Parse};
/// stop parsing here getting remaining token as content
/// Warn duplicate stream (part of)
#[derive(Parse, ToTokens, Debug)]
pub struct StopParse {
pub inner: T2,
pub inner: TokenStream,
}
// inner macro really dependant on syn naming convention, do not export
@@ -55,8 +50,8 @@ macro_rules! groups_impl {
}
impl<P: ToTokens> ToTokens for $name<P> {
fn to_tokens(&self, tokens: &mut T2) {
let mut inner_stream = T2::new();
fn to_tokens(&self, tokens: &mut TokenStream) {
let mut inner_stream = TokenStream::new();
self.content.to_tokens(&mut inner_stream);
let token_tree: proc_macro2::TokenTree =
proc_macro2::Group::new(proc_macro2::Delimiter::$deli, inner_stream).into();
@@ -107,7 +102,7 @@ impl<P: Parse, T: Parse> Parse for PunctuatedInner<P,T,NoTrailing> {
}
impl<P: ToTokens, T: ToTokens, V> ToTokens for PunctuatedInner<P,T,V> {
fn to_tokens(&self, tokens: &mut T2) {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.inner.to_tokens(tokens)
}
}
@@ -127,7 +122,7 @@ impl Parse for Meta {
}
impl ToTokens for Meta {
fn to_tokens(&self, tokens: &mut T2) {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self.inner {
syn::Meta::Word(ref ident) => {
let ident = ident.clone();
@@ -157,7 +152,7 @@ impl Parse for OuterAttributes {
}
impl ToTokens for OuterAttributes {
fn to_tokens(&self, tokens: &mut T2) {
fn to_tokens(&self, tokens: &mut TokenStream) {
for att in self.inner.iter() {
att.to_tokens(tokens);
}
@@ -182,121 +177,80 @@ impl<P: Parse> Parse for Opt<P> {
}
impl<P: ToTokens> ToTokens for Opt<P> {
fn to_tokens(&self, tokens: &mut T2) {
fn to_tokens(&self, tokens: &mut TokenStream) {
if let Some(ref p) = self.inner {
p.to_tokens(tokens);
}
}
}
pub fn extract_type_option(typ: &syn::Type) -> Option<T2> {
pub fn extract_type_option(typ: &syn::Type) -> Option<TokenStream> {
if let syn::Type::Path(ref path) = typ {
path.path.segments.last().and_then(|v| {
if v.value().ident == "Option" {
if let syn::PathArguments::AngleBracketed(ref a) = v.value().arguments {
let args = &a.args;
Some(quote!{ #args })
} else {
None
}
} else {
None
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 })
}
})
} else {
None
}
}
pub fn is_parametric_type_def(typ: &syn::Type, default: bool) -> bool {
match *typ {
syn::Type::Path(ref path) => {
path.path.segments.iter().any(|v| {
if let syn::PathArguments::AngleBracketed(..) = v.arguments {
true
} else {
false
}
})
},
syn::Type::Slice(ref inner) => is_parametric_type_def(&inner.elem, default),
syn::Type::Array(ref inner) => is_parametric_type_def(&inner.elem, default),
syn::Type::Ptr(ref inner) => is_parametric_type_def(&inner.elem, default),
syn::Type::Reference(ref inner) => is_parametric_type_def(&inner.elem, default),
syn::Type::BareFn(ref inner) => inner.variadic.is_some(),
syn::Type::Never(..) => false,
syn::Type::Tuple(ref inner) =>
inner.elems.iter().any(|t| is_parametric_type_def(t, default)),
syn::Type::TraitObject(..) => true,
syn::Type::ImplTrait(..) => true,
syn::Type::Paren(ref inner) => is_parametric_type_def(&inner.elem, default),
syn::Type::Group(ref inner) => is_parametric_type_def(&inner.elem, default),
syn::Type::Infer(..) => true,
syn::Type::Macro(..) => default,
syn::Type::Verbatim(..) => default,
}
}
/// check if type has any type parameter, defaults to true for some cases.
pub fn is_parametric_type(typ: &syn::Type) -> bool {
is_parametric_type_def(typ, true)
}
fn has_parametric_type_def_in_path(path: &syn::Path, ident: &Ident, default: bool) -> bool {
path.segments.iter().any(|v| {
if ident == &v.ident {
return true;
}
if let syn::PathArguments::AngleBracketed(ref a) = v.arguments {
for arg in a.args.iter() {
if let syn::GenericArgument::Type(ref typ) = arg {
if has_parametric_type_def(typ, ident, default) {
return true;
}
}
// potentially missing matches here
}
None
}
/// Auxialary structure to check if a given `Ident` is contained in an ast.
struct ContainsIdent<'a> {
ident: &'a Ident,
result: bool,
}
impl<'ast> ContainsIdent<'ast> {
fn visit_tokenstream(&mut self, stream: TokenStream) {
stream.into_iter().for_each(|tt|
match tt {
TokenTree::Ident(id) => self.visit_ident(&id),
TokenTree::Group(ref group) => self.visit_tokenstream(group.stream()),
_ => {}
}
false
} else {
false
}
})
)
}
}
pub fn has_parametric_type_def(typ: &syn::Type, ident: &Ident, default: bool) -> bool {
match *typ {
syn::Type::Path(ref path) => has_parametric_type_def_in_path(&path.path, ident, default),
syn::Type::Slice(ref inner) => has_parametric_type_def(&inner.elem, ident, default),
syn::Type::Array(ref inner) => has_parametric_type_def(&inner.elem, ident, default),
syn::Type::Ptr(ref inner) => has_parametric_type_def(&inner.elem, ident, default),
syn::Type::Reference(ref inner) => has_parametric_type_def(&inner.elem, ident, default),
syn::Type::BareFn(ref inner) => inner.variadic.is_some(),
syn::Type::Never(..) => false,
syn::Type::Tuple(ref inner) =>
inner.elems.iter().any(|t| has_parametric_type_def(t, ident, default)),
syn::Type::TraitObject(ref to) => {
to.bounds.iter().any(|bound| {
if let syn::TypeParamBound::Trait(ref t) = bound {
has_parametric_type_def_in_path(&t.path, ident, default)
} else { false }
})
},
syn::Type::ImplTrait(ref it) => {
it.bounds.iter().any(|bound| {
if let syn::TypeParamBound::Trait(ref t) = bound {
has_parametric_type_def_in_path(&t.path, ident, default)
} else { false }
})
},
syn::Type::Paren(ref inner) => has_parametric_type_def(&inner.elem, ident, default),
syn::Type::Group(ref inner) => has_parametric_type_def(&inner.elem, ident, default),
syn::Type::Infer(..) => default,
syn::Type::Macro(..) => default,
syn::Type::Verbatim(..) => default,
fn visit_ident(&mut self, ident: &Ident) {
if ident == self.ident {
self.result = true;
}
}
}
/// check if type has a type parameter, defaults to true for some cases.
pub fn has_parametric_type(typ: &syn::Type, ident: &Ident) -> bool {
has_parametric_type_def(typ, ident, true)
impl<'ast> Visit<'ast> for ContainsIdent<'ast> {
fn visit_ident(&mut self, input: &'ast Ident) {
self.visit_ident(input);
}
fn visit_macro(&mut self, input: &'ast syn::Macro) {
self.visit_tokenstream(input.tts.clone());
visit::visit_macro(self, input);
}
}
/// Check if a `Type` contains the given `Ident`.
pub fn type_contains_ident(typ: &syn::Type, ident: &Ident) -> bool {
let mut visit = ContainsIdent {
result: false,
ident,
};
visit::visit_type(&mut visit, typ);
visit.result
}
/// Check if a `Expr` contains the given `Ident`.
pub fn expr_contains_ident(expr: &syn::Expr, ident: &Ident) -> bool {
let mut visit = ContainsIdent {
result: false,
ident,
};
visit::visit_expr(&mut visit, expr);
visit.result
}
+84 -32
View File
@@ -321,17 +321,15 @@ macro_rules! __events_to_metadata {
}
/// Constructs an Event type for a runtime. This is usually called automatically by the
/// construct_runtime macro. See also __create_decl_macro.
/// construct_runtime macro.
#[macro_export]
macro_rules! impl_outer_event {
// Macro transformations (to convert invocations with incomplete parameters to the canonical
// form)
(
$(#[$attr:meta])*
pub enum $name:ident for $runtime:ident {
$( $rest:tt $( <$t:ident $(, $rest_instance:path)? > )*, )*
$( $rest_event_without_system:tt )*
}
) => {
$crate::impl_outer_event!(
@@ -339,14 +337,14 @@ macro_rules! impl_outer_event {
$name;
$runtime;
system;
Modules { $( $rest $(<$t $(, $rest_instance)? >)*, )* };
Modules { $( $rest_event_without_system )* };
;
);
};
(
$(#[$attr:meta])*
pub enum $name:ident for $runtime:ident where system = $system:ident {
$( $rest:tt $( <$t:ident $(, $rest_instance:path)? > )*, )*
$( $rest_event_with_system:tt )*
}
) => {
$crate::impl_outer_event!(
@@ -354,30 +352,74 @@ macro_rules! impl_outer_event {
$name;
$runtime;
$system;
Modules { $( $rest $(<$t $(, $rest_instance)? >)*, )* };
Modules { $( $rest_event_with_system )* };
;
);
};
// Generic + Instance
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
$system:ident;
Modules {
$module:ident<T $(, $instance:path)? >,
$( $rest:tt $( <$t:ident $(, $rest_instance:path)? > )*, )*
$module:ident $instance:ident<T>,
$( $rest_event_generic_instance:tt )*
};
$( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*;
$( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*;
) => {
$crate::impl_outer_event!(
$( #[$attr] )*;
$name;
$runtime;
$system;
Modules { $( $rest $(<$t $(, $rest_instance)? >)*, )* };
$( $module_name::Event $( <$generic_param $(, $generic_instance)? > )*, )* $module::Event<$runtime $(, $instance)? >,;
Modules { $( $rest_event_generic_instance )* };
$( $module_name::Event $( <$generic_param> )? $( { $generic_instance } )?, )* $module::Event<$runtime>{ $instance },;
);
};
// Instance
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
$system:ident;
Modules {
$module:ident $instance:ident,
$( $rest_event_instance:tt )*
};
$( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*;
) => {
$crate::impl_outer_event!(
$( #[$attr] )*;
$name;
$runtime;
$system;
Modules { $( $rest_event_instance )* };
$( $module_name::Event $( <$generic_param> )* $( { $generic_instance } )?, )* $module::Event { $instance },;
);
};
// Generic
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
$system:ident;
Modules {
$module:ident<T>,
$( $rest_event_generic:tt )*
};
$( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*;
) => {
$crate::impl_outer_event!(
$( #[$attr] )*;
$name;
$runtime;
$system;
Modules { $( $rest_event_generic )* };
$( $module_name::Event $( <$generic_param> )? $( { $generic_instance } )?, )* $module::Event<$runtime>,;
);
};
// No Generic and no Instance
(
$(#[$attr:meta])*;
$name:ident;
@@ -385,30 +427,30 @@ macro_rules! impl_outer_event {
$system:ident;
Modules {
$module:ident,
$( $rest:tt )*
$( $rest_event_no_generic_no_instance:tt )*
};
$( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*;
$( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*;
) => {
$crate::impl_outer_event!(
$( #[$attr] )*;
$name;
$runtime;
$system;
Modules { $( $rest )* };
$( $module_name::Event $( <$generic_param $(, $generic_instance)? > )*, )* $module::Event,;
Modules { $( $rest_event_no_generic_no_instance )* };
$( $module_name::Event $( <$generic_param> )? $( { $generic_instance } )?, )* $module::Event,;
);
};
// The main macro expansion that actually renders the Event enum code.
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
$system:ident;
Modules {};
$( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*;
$( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*;
) => {
$crate::paste::item! {
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
@@ -417,7 +459,9 @@ macro_rules! impl_outer_event {
pub enum $name {
system($system::Event),
$(
$module_name( $module_name::Event $( <$generic_param $(, $generic_instance)? > )* ),
[< $module_name $(_ $generic_instance )? >](
$module_name::Event < $( $generic_param )? $(, $module_name::$generic_instance )? >
),
)*
}
impl From<$system::Event> for $name {
@@ -426,17 +470,22 @@ macro_rules! impl_outer_event {
}
}
$(
impl From<$module_name::Event $( <$generic_param $(, $generic_instance)? > )*> for $name {
fn from(x: $module_name::Event $( <$generic_param $(, $generic_instance)? > )*) -> Self {
$name::$module_name(x)
impl From<$module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >> for $name {
fn from(x: $module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >) -> Self {
$name::[< $module_name $(_ $generic_instance )? >](x)
}
}
)*
}
$crate::__impl_outer_event_json_metadata!(
$runtime;
$name;
$system;
$( $module_name::Event $( <$generic_param $(, $generic_instance)? > )*, )*;
$(
$module_name::Event
< $( $generic_param )? $(, $module_name::$generic_instance )? >
$( $generic_instance )?,
)*;
);
}
}
@@ -448,7 +497,7 @@ macro_rules! __impl_outer_event_json_metadata {
$runtime:ident;
$event_name:ident;
$system:ident;
$( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*;
$( $module_name:ident::Event < $( $generic_params:path ),* > $( $instance:ident )?, )*;
) => {
impl $runtime {
#[allow(dead_code)]
@@ -461,7 +510,7 @@ macro_rules! __impl_outer_event_json_metadata {
, (
stringify!($module_name),
$crate::event::FnEncode(
$module_name::Event $( ::<$generic_param $(, $generic_instance)? > )* ::metadata
$module_name::Event ::< $( $generic_params ),* > ::metadata
)
)
)*
@@ -472,14 +521,17 @@ macro_rules! __impl_outer_event_json_metadata {
pub fn __module_events_system() -> &'static [$crate::event::EventMetadata] {
system::Event::metadata()
}
$(
#[allow(dead_code)]
$crate::paste::item!{
pub fn [< __module_events_ $module_name >] () -> &'static [$crate::event::EventMetadata] {
$module_name::Event $( ::<$generic_param $(, $generic_instance)? > )* ::metadata()
$crate::paste::item! {
$(
#[allow(dead_code)]
pub fn [< __module_events_ $module_name $( _ $instance )? >] () ->
&'static [$crate::event::EventMetadata]
{
$module_name::Event ::< $( $generic_params ),* > ::metadata()
}
}
)*
)*
}
}
}
}
+7 -8
View File
@@ -34,7 +34,9 @@ pub use once_cell;
pub use paste;
pub use sr_primitives as runtime_primitives;
pub use self::storage::hashed::generator::{HashedStorage, Twox256, Twox128, Blake2_256, Blake2_128, Twox64Concat};
pub use self::storage::hashed::generator::{
HashedStorage, Twox256, Twox128, Blake2_256, Blake2_128, Twox64Concat
};
pub use self::storage::unhashed::generator::UnhashedStorage;
#[macro_use]
@@ -239,7 +241,6 @@ mod tests {
use super::*;
use codec::Codec;
use runtime_io::{with_externalities, Blake2Hasher};
use runtime_primitives::BuildStorage;
pub use srml_metadata::{
DecodeDifferent, StorageMetadata, StorageFunctionMetadata,
StorageFunctionType, StorageFunctionModifier,
@@ -258,9 +259,7 @@ mod tests {
use super::Trait;
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
}
pub struct Module<T: Trait> for enum Call where origin: T::Origin {}
}
}
use self::module::Module;
@@ -286,10 +285,10 @@ mod tests {
}
fn new_test_ext() -> runtime_io::TestExternalities<Blake2Hasher> {
GenesisConfig::<Test>::default().build_storage().unwrap().0.into()
GenesisConfig::default().build_storage().unwrap().0.into()
}
type Map = Data<Test>;
type Map = Data;
#[test]
fn linked_map_basic_insert_remove_should_work() {
@@ -372,7 +371,7 @@ mod tests {
#[test]
fn double_map_basic_insert_remove_remove_prefix_should_work() {
with_externalities(&mut new_test_ext(), || {
type DoubleMap = DataDM<Test>;
type DoubleMap = DataDM;
// initialized during genesis
assert_eq!(DoubleMap::get(&15u32, &16u32), 42u64);
+112 -40
View File
@@ -24,24 +24,24 @@ macro_rules! impl_outer_origin {
// Macro transformations (to convert invocations with incomplete parameters to the canonical
// form)
(
$(#[$attr:meta])*
pub enum $name:ident for $runtime:ident {
$( $module:ident $( <$generic:ident $(, $instance:path )? > )? ),* $(,)?
$( $rest_without_system:tt )*
}
) => {
$crate::impl_outer_origin! {
$(#[$attr])*
pub enum $name for $runtime where system = system {
$( $module $( <$generic $(, $instance )? > )?, )*
$( $rest_without_system )*
}
}
};
(
$(#[$attr:meta])*
pub enum $name:ident for $runtime:ident where system = $system:ident {
$( $module:ident $( <$generic:ident $(, $instance:path )?> )? ),* $(,)?
$( $rest_with_system:tt )*
}
) => {
$crate::impl_outer_origin!(
@@ -49,20 +49,41 @@ macro_rules! impl_outer_origin {
$name;
$runtime;
$system;
Modules { $( $module $( <$generic $(, $instance )? > )*, )* };
Modules { $( $rest_with_system )* };
);
};
// Replace generic param with runtime
// Generic + Instance
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
$system:ident;
Modules {
$module:ident $( <T $(, $instance:path )? > )?,
$( $rest_module:tt )*
$module:ident $instance:ident <T>
$(, $( $rest_module:tt )* )?
};
$( $parsed:tt )*
) => {
$crate::impl_outer_origin!(
$( #[$attr] )*;
$name;
$runtime;
$system;
Modules { $( $( $rest_module )* )? };
$( $parsed )* $module <$runtime> { $instance },
);
};
// Instance
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
$system:ident;
Modules {
$module:ident $instance:ident
$(, $rest_module:tt )*
};
$( $parsed:tt )*
) => {
@@ -72,33 +93,80 @@ macro_rules! impl_outer_origin {
$runtime;
$system;
Modules { $( $rest_module )* };
$( $parsed )* $module $( <$runtime $(, $instance )? > )?,
$( $parsed )* $module { $instance },
);
};
// Generic
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
$system:ident;
Modules {
$module:ident <T>
$(, $( $rest_module:tt )* )?
};
$( $parsed:tt )*
) => {
$crate::impl_outer_origin!(
$( #[$attr] )*;
$name;
$runtime;
$system;
Modules { $( $( $rest_module )* )? };
$( $parsed )* $module <$runtime>,
);
};
// No Generic and no Instance
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
$system:ident;
Modules {
$module:ident
$(, $( $rest_module:tt )* )?
};
$( $parsed:tt )*
) => {
$crate::impl_outer_origin!(
$( #[$attr] )*;
$name;
$runtime;
$system;
Modules { $( $( $rest_module )* )? };
$( $parsed )* $module,
);
};
// The main macro expansion that actually renders the Origin enum code.
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
$system:ident;
Modules { };
$( $module:ident $( <$generic_param:ident $(, $generic_instance:path )? > )* ,)*
$( $module:ident $( < $generic:ident > )? $( { $generic_instance:ident } )? ,)*
) => {
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug))]
$(#[$attr])*
#[allow(non_camel_case_types)]
pub enum $name {
system($system::Origin<$runtime>),
$(
$module($module::Origin $( <$generic_param $(, $generic_instance )? > )* ),
)*
#[allow(dead_code)]
Void($crate::Void)
$crate::paste::item! {
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug))]
$(#[$attr])*
#[allow(non_camel_case_types)]
pub enum $name {
system($system::Origin<$runtime>),
$(
[< $module $( _ $generic_instance )? >]
($module::Origin < $( $generic, )? $( $module::$generic_instance )? > ),
)*
#[allow(dead_code)]
Void($crate::Void)
}
}
#[allow(dead_code)]
impl $name {
pub const NONE: Self = $name::system($system::RawOrigin::None);
@@ -127,23 +195,27 @@ macro_rules! impl_outer_origin {
}
}
$(
impl From<$module::Origin $( <$generic_param $(, $generic_instance )? > )*> for $name {
fn from(x: $module::Origin $( <$generic_param $(, $generic_instance )? > )*) -> Self {
$name::$module(x)
$crate::paste::item! {
impl From<$module::Origin < $( $generic )? $(, $module::$generic_instance )? > > for $name {
fn from(x: $module::Origin < $( $generic )? $(, $module::$generic_instance )? >) -> Self {
$name::[< $module $( _ $generic_instance )? >](x)
}
}
}
impl Into<$crate::rstd::result::Result<
$module::Origin $( <$generic_param $(, $generic_instance )? > )*,
$name
>> for $name {
fn into(self) -> $crate::rstd::result::Result<
$module::Origin $( <$generic_param $(, $generic_instance )? > )*,
Self
> {
if let $name::$module(l) = self {
Ok(l)
} else {
Err(self)
impl Into<
$crate::rstd::result::Result<
$module::Origin < $( $generic )? $(, $module::$generic_instance )? >,
$name,
>>
for $name {
fn into(self) -> $crate::rstd::result::Result<
$module::Origin < $( $generic )? $(, $module::$generic_instance )? >,
Self,
> {
if let $name::[< $module $( _ $generic_instance )? >](l) = self {
Ok(l)
} else {
Err(self)
}
}
}
}
+58 -89
View File
@@ -61,9 +61,9 @@
/// - `Module`
/// - `Call`
/// - `Storage`
/// - `Event` or `Event<T>` (if the event is generic) or `Event<T, I>` (if also over instance)
/// - `Origin` or `Origin<T>` (if the origin is generic) or `Origin<T, I>` (if also over instance)
/// - `Config` or `Config<T>` (if the config is generic) or `Config<T, I>` (if also over instance)
/// - `Event` or `Event<T>` (if the event is generic)
/// - `Origin` or `Origin<T>` (if the origin is generic)
/// - `Config` or `Config<T>` (if the config is generic)
/// - `Inherent $( (CALL) )*` - If the module provides/can check inherents. The optional parameter
/// is for modules that use a `Call` from a different module as
/// inherent.
@@ -101,6 +101,7 @@ macro_rules! construct_runtime {
$( $rest )*
);
};
// No modules given, expand to the default module set.
(
{ $( $preset:tt )* };
{ $( $expanded:tt )* };
@@ -114,6 +115,7 @@ macro_rules! construct_runtime {
$( $rest )*
);
};
// `default` identifier given, expand to default + given extra modules
(
{ $( $preset:tt )* };
{ $( $expanded:tt )* };
@@ -121,7 +123,7 @@ macro_rules! construct_runtime {
default
$(,
$modules:ident
$( <$modules_generic:ident $(, $modules_instance:ident)?> )*
$( <$modules_generic:ident> )*
$( ( $( $modules_args:ident ),* ) )*
)*
},
@@ -129,21 +131,24 @@ macro_rules! construct_runtime {
) => {
$crate::construct_runtime!(
{ $( $preset )* };
{ $( $expanded )* };
$name: $module::{
Module, Call, Storage, Event<T>, Config<T>
$(,
$modules $( <$modules_generic $(, $modules_instance)?> )*
$( ( $( $modules_args ),* ) )*
)*
},
{
$( $expanded )*
$name: $module::{
Module, Call, Storage, Event<T>, Config<T>
$(,
$modules $( <$modules_generic> )*
$( ( $( $modules_args ),* ) )*
)*
},
};
$( $rest )*
);
};
// Take all modules as given by the user.
(
{ $( $preset:tt )* };
{ $( $expanded:tt )* };
$name:ident: $module:ident::{
$name:ident: $module:ident :: $( < $module_instance:ident >:: )? {
$(
$modules:ident
$( <$modules_generic:ident> )*
@@ -156,7 +161,7 @@ macro_rules! construct_runtime {
{ $( $preset )* };
{
$( $expanded )*
$name: $module::{
$name: $module:: $( < $module_instance >:: )? {
$(
$modules $( <$modules_generic> )*
$( ( $( $modules_args ),* ) )*
@@ -166,35 +171,7 @@ macro_rules! construct_runtime {
$( $rest )*
);
};
( // Instance module: we indicate the generic instance `I` with the full instance path
{ $( $preset:tt )* };
{ $( $expanded:tt )* };
$name:ident: $module:ident ::< $module_instance:ident >::{
$(
$modules:ident
$( <$modules_generic:ident $(, $modules_instance:ident )?> )*
$( ( $( $modules_args:ident ),* ) )*
),*
},
$( $rest:tt )*
) => {
$crate::construct_runtime!(
{ $( $preset )* };
{
$( $expanded )*
$name: $module::<$module_instance>::{
$(
$modules $( <$modules_generic $(, $modules_instance=$module::$module_instance)?> )*
$( ( $( $modules_args ),* ) )*
),*
},
};
$( $rest )*
);
};
// The main macro expansion that actually renders the Runtime code.
(
{
$runtime:ident;
@@ -207,7 +184,7 @@ macro_rules! construct_runtime {
$name:ident: $module:ident :: $( < $module_instance:ident >:: )? {
$(
$modules:ident
$( <$modules_generic:ident $(, I=$modules_instance:path)?> )*
$( <$modules_generic:ident> )*
$( ( $( $modules_args:ident ),* ) )*
),*
},
@@ -223,19 +200,20 @@ macro_rules! construct_runtime {
impl $crate::runtime_primitives::traits::GetRuntimeBlockType for $runtime {
type RuntimeBlock = $block;
}
$crate::__decl_instance_import!(
$( $( $module < $module_instance > )? )*
);
$crate::__decl_outer_event!(
$runtime;
$(
$name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* }
$name: $module:: $( < $module_instance >:: )? {
$( $modules $( <$modules_generic> )* ),*
}
),*
);
$crate::__decl_outer_origin!(
$runtime;
$(
$name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* }
$name: $module:: $( < $module_instance >:: )? {
$( $modules $( <$modules_generic> )* ),*
}
),*
);
$crate::__decl_all_modules!(
@@ -265,7 +243,7 @@ macro_rules! construct_runtime {
{};
$(
$name: $module:: $( < $module_instance >:: )? {
$( $modules $( <$modules_generic $(, $modules_instance)?> )* ),*
$( $modules $( <$modules_generic> )* ),*
},
)*
);
@@ -307,7 +285,7 @@ macro_rules! __create_decl_macro {
(
$runtime:ident;
$d( $name:ident : $module:ident:: $d( < $module_instance:ident >:: )? {
$d( $modules:ident $d( <$modules_generic:ident $d(, $modules_instance:path)?> ),* ),*
$d( $modules:ident $d( <$modules_generic:ident> ),* ),*
}),*
) => {
$d crate::$macro_name!(@inner
@@ -316,7 +294,7 @@ macro_rules! __create_decl_macro {
{};
$d(
$name: $module:: $d( < $module_instance >:: )? {
$d( $modules $d( <$modules_generic $d(, $modules_instance)?> )* ),*
$d( $modules $d( <$modules_generic> )* ),*
},
)*
);
@@ -342,7 +320,7 @@ macro_rules! __create_decl_macro {
$d( $system:ident )?;
{ $d( $parsed:tt )* };
$name:ident : $module:ident:: < $module_instance:ident >:: {
$macro_enum_name <$event_generic:ident, $event_instance:path> $d(, $ignore:ident $d( <$ignor:ident $d(, $ignore_instance:path)?> )* )*
$macro_enum_name <$event_generic:ident> $d(, $ingore:ident $d( <$ignor:ident> )* )*
},
$d( $rest:tt )*
) => {
@@ -351,33 +329,17 @@ macro_rules! __create_decl_macro {
$d( $system )?;
{
$d( $parsed )*
$module $module_instance <$event_generic, $event_instance>,
$module $module_instance <$event_generic>,
};
$d( $rest )*
);
};
(@inner
$runtime:ident;
$d( $system:ident )?;
{ $d( $parsed:tt )* };
$name:ident : $module:ident:: < $module_instance:ident >:: {
$macro_enum_name $d( <$event_generic:ident> )* $d(, $ignore:ident $d( <$ignor:ident $d(, $ignore_instance:path)?> )* )*
},
$d( $rest:tt )*
) => {
compile_error!{concat!{
"Module `", stringify!{$name}, "` must have `", stringify!{$macro_enum_name}, "<T, I>`",
" but has `", stringify!{$macro_enum_name} $d(, "<", stringify!{$event_generic}, ">")*, "`",
": Instantiated modules must have ", stringify!{$macro_enum_name},
" generic over instance to be able to convert to outer ", stringify!{$macro_enum_name}
}}
};
(@inner
$runtime:ident;
$d( $system:ident )?;
{ $d( $parsed:tt )* };
$name:ident : $module:ident:: {
$macro_enum_name $d( <$event_generic:ident $d(, $event_instance:path)?> )* $d(, $ignore:ident $d( <$ignor:ident $d(, $ignore_instance:path)?> )* )*
$macro_enum_name $d( <$event_generic:ident> )* $d(, $ignore:ident $d( <$ignor:ident> )* )*
},
$d( $rest:tt )*
) => {
@@ -386,7 +348,7 @@ macro_rules! __create_decl_macro {
$d( $system )?;
{
$d( $parsed )*
$module $d( <$event_generic $d(, $event_instance)?> )*,
$module $d( <$event_generic> )*,
};
$d( $rest )*
);
@@ -396,7 +358,7 @@ macro_rules! __create_decl_macro {
$d( $system:ident )?;
{ $d( $parsed:tt )* };
$name:ident : $module:ident:: $d( < $module_instance:ident >:: )? {
$ignore:ident $d( <$ignor:ident $d(, $ignore_instance:path)?> )* $d(, $modules:ident $d( <$modules_generic:ident $d(, $modules_instance:path)?> )* )*
$ingore:ident $d( <$ignor:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )*
},
$d( $rest:tt )*
) => {
@@ -404,7 +366,7 @@ macro_rules! __create_decl_macro {
$runtime;
$d( $system )?;
{ $d( $parsed )* };
$name: $module:: $d( < $module_instance >:: )? { $d( $modules $d( <$modules_generic $d(, $modules_instance)?> )* ),* },
$name: $module:: $d( < $module_instance >:: )? { $d( $modules $d( <$modules_generic> )* ),* },
$d( $rest )*
);
};
@@ -425,16 +387,13 @@ macro_rules! __create_decl_macro {
(@inner
$runtime:ident;
$system:ident;
{ $d( $parsed_modules:ident $d( $instance:ident )? $d( <$parsed_generic:ident $d(, $parsed_instance_full_path:path)?> )* ,)* };
{ $d( $parsed_modules:ident $d( $instance:ident )? $d( <$parsed_generic:ident> )? ,)* };
) => {
$d crate::paste::item! {
$d crate::$macro_outer_name! {
pub enum $macro_enum_name for $runtime where system = $system {
$d(
[< $parsed_modules $d(_ $instance )? >] $d( <$parsed_generic $d(, $parsed_instance_full_path)?> )*,
)*
}
$d crate::$macro_outer_name! {
pub enum $macro_enum_name for $runtime where system = $system {
$d(
$parsed_modules $d( $instance )? $d( <$parsed_generic> )?,
)*
}
}
}
@@ -668,7 +627,7 @@ macro_rules! __decl_runtime_metadata {
}
}
/// A private macro that generates GenesisConfig for the runtime. See impl_outer_config macro.
/// A private macro that generates GenesisConfig for the runtime. See `impl_outer_config!` macro.
#[macro_export]
#[doc(hidden)]
macro_rules! __decl_outer_config {
@@ -676,7 +635,8 @@ macro_rules! __decl_outer_config {
$runtime:ident;
{ $( $parsed:tt )* };
$name:ident: $module:ident:: $( < $module_instance:ident >:: )? {
Config $(< $config_generic:ident $(, $config_instance:path)?>)? $(, $modules:ident $( <$modules_generic:ident $(, $modules_instance:path)?> )* )*
Config $( <$config_generic:ident> )?
$(, $modules:ident $( <$modules_generic:ident> )* )*
},
$( $rest:tt )*
) => {
@@ -684,7 +644,7 @@ macro_rules! __decl_outer_config {
$runtime;
{
$( $parsed )*
$module::$name $( $module_instance )? $(<$config_generic $(, $config_instance)?>)?,
$module::$name $( $module_instance )? $( <$config_generic> )?,
};
$( $rest )*
);
@@ -693,14 +653,15 @@ macro_rules! __decl_outer_config {
$runtime:ident;
{ $( $parsed:tt )* };
$name:ident: $module:ident:: $( < $module_instance:ident >:: )? {
$ignore:ident $( <$ignor:ident $(, $ignore_instance:path)?> )* $(, $modules:ident $( <$modules_generic:ident $(, $modules_instance:path)?> )* )*
$ingore:ident $( <$ignore_gen:ident> )*
$(, $modules:ident $( <$modules_generic:ident> )* )*
},
$( $rest:tt )*
) => {
$crate::__decl_outer_config!(
$runtime;
{ $( $parsed )* };
$name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* },
$name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic> )* ),* },
$( $rest )*
);
};
@@ -718,13 +679,21 @@ macro_rules! __decl_outer_config {
};
(
$runtime:ident;
{$( $parsed_modules:ident :: $parsed_name:ident $( $parsed_instance:ident )? $( < $parsed_generic:ident $(, $parsed_instance_full_path:path)? > )* ,)* };
{
$(
$parsed_modules:ident :: $parsed_name:ident $( $parsed_instance:ident )?
$(
<$parsed_generic:ident>
)*
,)*
};
) => {
$crate::paste::item! {
$crate::runtime_primitives::impl_outer_config!(
pub struct GenesisConfig for $runtime {
$(
[< $parsed_name Config >] => [< $parsed_modules $( _ $parsed_instance)? >] $( < $parsed_generic $(, $parsed_instance_full_path)? > )*,
[< $parsed_name Config >] =>
$parsed_modules $( $parsed_instance )? $( <$parsed_generic> )*,
)*
}
);
@@ -346,7 +346,7 @@ mod tests {
// getters: pub / $default
// we need at least one type which uses T, otherwise GenesisConfig will complain.
GETU32 get(u32_getter): T::Origin;
pub PUBGETU32 get(pub_u32_getter) build(|config: &GenesisConfig<T>| config.u32_getter_with_config): u32;
pub PUBGETU32 get(pub_u32_getter) build(|config: &GenesisConfig| config.u32_getter_with_config): u32;
GETU32WITHCONFIG get(u32_getter_with_config) config(): u32;
pub PUBGETU32WITHCONFIG get(pub_u32_getter_with_config) config(): u32;
GETU32MYDEF get(u32_getter_mydef): Option<u32> = Some(4);
@@ -716,7 +716,7 @@ mod tests {
#[test]
fn check_genesis_config() {
let config = GenesisConfig::<TraitImpl>::default();
let config = GenesisConfig::default();
assert_eq!(config.u32_getter_with_config, 0u32);
assert_eq!(config.pub_u32_getter_with_config, 0u32);
@@ -820,13 +820,13 @@ mod test_map_vec_append {
use runtime_io::{with_externalities, TestExternalities};
with_externalities(&mut TestExternalities::default(), || {
let _ = <MapVec<Test>>::append(1, &[1, 2, 3]);
let _ = <MapVec<Test>>::append(1, &[4, 5]);
assert_eq!(<MapVec<Test>>::get(1), vec![1, 2, 3, 4, 5]);
let _ = MapVec::append(1, &[1, 2, 3]);
let _ = MapVec::append(1, &[4, 5]);
assert_eq!(MapVec::get(1), vec![1, 2, 3, 4, 5]);
let _ = <JustVec<Test>>::append(&[1, 2, 3]);
let _ = <JustVec<Test>>::append(&[4, 5]);
assert_eq!(<JustVec<Test>>::get(), vec![1, 2, 3, 4, 5]);
let _ = JustVec::append(&[1, 2, 3]);
let _ = JustVec::append(&[4, 5]);
assert_eq!(JustVec::get(), vec![1, 2, 3, 4, 5]);
});
}
}
@@ -17,7 +17,6 @@
use runtime_io::{with_externalities, Blake2Hasher};
use srml_support::{StorageValue, StorageMap, StorageDoubleMap};
use srml_support::storage::unhashed;
use srml_support::runtime_primitives::BuildStorage;
use parity_codec::{Encode, Decode};
pub trait Trait {
@@ -60,37 +59,37 @@ fn new_test_ext() -> runtime_io::TestExternalities<Blake2Hasher> {
#[test]
fn final_keys() {
with_externalities(&mut new_test_ext(), || {
<Value<Test>>::put(1);
Value::put(1);
assert_eq!(unhashed::get::<u32>(&runtime_io::twox_128(b"Module Value")), Some(1u32));
<Map<Test>>::insert(1, 2);
Map::insert(1, 2);
let mut k = b"Module Map".to_vec();
k.extend(1u32.encode());
assert_eq!(unhashed::get::<u32>(&runtime_io::blake2_256(&k)), Some(2u32));
<Map2<Test>>::insert(1, 2);
Map2::insert(1, 2);
let mut k = b"Module Map2".to_vec();
k.extend(1u32.encode());
assert_eq!(unhashed::get::<u32>(&runtime_io::twox_128(&k)), Some(2u32));
<LinkedMap<Test>>::insert(1, 2);
LinkedMap::insert(1, 2);
let mut k = b"Module LinkedMap".to_vec();
k.extend(1u32.encode());
assert_eq!(unhashed::get::<u32>(&runtime_io::blake2_256(&k)), Some(2u32));
<LinkedMap2<Test>>::insert(1, 2);
LinkedMap2::insert(1, 2);
let mut k = b"Module LinkedMap2".to_vec();
k.extend(1u32.encode());
assert_eq!(unhashed::get::<u32>(&runtime_io::twox_128(&k)), Some(2u32));
<DoubleMap<Test>>::insert(1, 2, 3);
DoubleMap::insert(1, 2, 3);
let mut k = b"Module DoubleMap".to_vec();
k.extend(1u32.encode());
let mut k = runtime_io::blake2_256(&k).to_vec();
k.extend(&runtime_io::blake2_256(&2u32.encode()));
assert_eq!(unhashed::get::<u32>(&k), Some(3u32));
<DoubleMap2<Test>>::insert(1, 2, 3);
DoubleMap2::insert(1, 2, 3);
let mut k = b"Module DoubleMap2".to_vec();
k.extend(1u32.encode());
let mut k = runtime_io::twox_128(&k).to_vec();
@@ -0,0 +1,44 @@
// 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/>.
pub trait Trait {
type BlockNumber: parity_codec::Codec + Default;
type Origin;
}
srml_support::decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {}
}
srml_support::decl_storage! {
trait Store for Module<T: Trait> as Example {
pub AppendableDM config(t): double_map u32, blake2_256(T::BlockNumber) => Vec<u32>;
}
}
struct Test;
impl Trait for Test {
type BlockNumber = u32;
type Origin = ();
}
#[test]
fn init_genesis_config() {
GenesisConfig::<Test> {
t: Default::default(),
};
}
+68 -124
View File
@@ -13,84 +13,22 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
#![recursion_limit="128"]
use runtime_io::{with_externalities, Blake2Hasher};
use srml_support::rstd::prelude::*;
use srml_support::rstd as rstd;
use srml_support::runtime_primitives::{generic, BuildStorage};
use srml_support::runtime_primitives::traits::{BlakeTwo256, Block as _, Verify};
use srml_support::Parameter;
use srml_support::{
Parameter,
runtime_primitives::{generic, BuildStorage, traits::{BlakeTwo256, Block as _, Verify}},
};
use inherents::{
ProvideInherent, InherentData, InherentIdentifier, RuntimeString, MakeFatalError
};
use srml_support::{StorageValue, StorageMap, StorageDoubleMap};
use primitives::{H256, sr25519};
pub trait Currency {
}
mod system;
// Mock
mod system {
use super::*;
pub trait Trait: 'static + Eq + Clone {
type Origin: Into<Result<RawOrigin<Self::AccountId>, Self::Origin>>
+ From<RawOrigin<Self::AccountId>>;
type BlockNumber;
type Hash;
type AccountId;
type Event: From<Event>;
}
pub type DigestItemOf<T> = generic::DigestItem<<T as Trait>::Hash>;
srml_support::decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
pub fn deposit_event(_event: T::Event) {
}
}
}
impl<T: Trait> Module<T> {
pub fn deposit_log(_item: DigestItemOf<T>) {
unimplemented!();
}
}
srml_support::decl_event!(
pub enum Event {
ExtrinsicSuccess,
ExtrinsicFailed,
}
);
/// Origin for the system module.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum RawOrigin<AccountId> {
Root,
Signed(AccountId),
None,
}
impl<AccountId> From<Option<AccountId>> for RawOrigin<AccountId> {
fn from(s: Option<AccountId>) -> RawOrigin<AccountId> {
match s {
Some(who) => RawOrigin::Signed(who),
None => RawOrigin::None,
}
}
}
pub type Origin<T> = RawOrigin<<T as Trait>::AccountId>;
pub fn ensure_root<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<(), &'static str>
where OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>
{
o.into().map(|_| ()).map_err(|_| "bad origin: expected to be a root origin")
}
}
pub trait Currency {}
// Test for:
// * No default instance
@@ -123,7 +61,7 @@ mod module1 {
}
srml_support::decl_event! {
pub enum Event<T, I> where Phantom = rstd::marker::PhantomData<T> {
pub enum Event<T, I> where Phantom = std::marker::PhantomData<T> {
_Phantom(Phantom),
AnotherVariant(u32),
}
@@ -133,7 +71,7 @@ mod module1 {
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Origin<T: Trait<I>, I> {
Members(u32),
_Phantom(rstd::marker::PhantomData<(T, I)>),
_Phantom(std::marker::PhantomData<(T, I)>),
}
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"12345678";
@@ -147,7 +85,7 @@ mod module1 {
unimplemented!();
}
fn check_inherent(_call: &Self::Call, _data: &InherentData) -> rstd::result::Result<(), Self::Error> {
fn check_inherent(_call: &Self::Call, _data: &InherentData) -> std::result::Result<(), Self::Error> {
unimplemented!();
}
}
@@ -180,7 +118,6 @@ mod module2 {
pub LinkedMap config(linked_map): linked_map u64 => u64;
pub DoubleMap config(double_map): double_map u64, blake2_256(u64) => u64;
}
extra_genesis_skip_phantom_data_field;
}
srml_support::decl_event! {
@@ -193,7 +130,7 @@ mod module2 {
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Origin<T: Trait<I>, I=DefaultInstance> {
Members(u32),
_Phantom(rstd::marker::PhantomData<(T, I)>),
_Phantom(std::marker::PhantomData<(T, I)>),
}
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"12345678";
@@ -207,7 +144,7 @@ mod module2 {
unimplemented!();
}
fn check_inherent(_call: &Self::Call, _data: &InherentData) -> rstd::result::Result<(), Self::Error> {
fn check_inherent(_call: &Self::Call, _data: &InherentData) -> std::result::Result<(), Self::Error> {
unimplemented!();
}
}
@@ -224,8 +161,7 @@ mod module3 {
}
srml_support::decl_module! {
pub struct Module<T: Trait> for enum Call where origin: <T as system::Trait>::Origin {
}
pub struct Module<T: Trait> for enum Call where origin: <T as system::Trait>::Origin {}
}
}
@@ -282,12 +218,22 @@ srml_support::construct_runtime!(
UncheckedExtrinsic = UncheckedExtrinsic
{
System: system::{Module, Call, Event},
Module1_1: module1::<Instance1>::{Module, Call, Storage, Event<T, I>, Config<T, I>, Origin<T, I>, Inherent},
Module1_2: module1::<Instance2>::{Module, Call, Storage, Event<T, I>, Config<T, I>, Origin<T, I>, Inherent},
Module1_1: module1::<Instance1>::{
Module, Call, Storage, Event<T>, Config, Origin<T>, Inherent
},
Module1_2: module1::<Instance2>::{
Module, Call, Storage, Event<T>, Config, Origin<T>, Inherent
},
Module2: module2::{Module, Call, Storage, Event<T>, Config<T>, Origin<T>, Inherent},
Module2_1: module2::<Instance1>::{Module, Call, Storage, Event<T, I>, Config<T, I>, Origin<T, I>, Inherent},
Module2_2: module2::<Instance2>::{Module, Call, Storage, Event<T, I>, Config<T, I>, Origin<T, I>, Inherent},
Module2_3: module2::<Instance3>::{Module, Call, Storage, Event<T, I>, Config<T, I>, Origin<T, I>, Inherent},
Module2_1: module2::<Instance1>::{
Module, Call, Storage, Event<T>, Config<T>, Origin<T>, Inherent
},
Module2_2: module2::<Instance2>::{
Module, Call, Storage, Event<T>, Config<T>, Origin<T>, Inherent
},
Module2_3: module2::<Instance3>::{
Module, Call, Storage, Event<T>, Config<T>, Origin<T>, Inherent
},
Module3: module3::{Module, Call},
}
);
@@ -300,11 +246,9 @@ fn new_test_ext() -> runtime_io::TestExternalities<Blake2Hasher> {
GenesisConfig{
module1_Instance1: Some(module1::GenesisConfig {
value: 3,
.. Default::default()
}),
module1_Instance2: Some(module1::GenesisConfig {
value: 4,
_genesis_phantom_data: Default::default(),
}),
module2: Some(module2::GenesisConfig {
value: 4,
@@ -326,48 +270,48 @@ fn new_test_ext() -> runtime_io::TestExternalities<Blake2Hasher> {
#[test]
fn storage_instance_independance() {
with_externalities(&mut new_test_ext(), || {
let mut map = rstd::collections::btree_map::BTreeMap::new();
let mut map = std::collections::btree_map::BTreeMap::new();
for key in [
module2::Value::<Runtime>::key().to_vec(),
module2::Value::<Runtime, module2::Instance1>::key().to_vec(),
module2::Value::<Runtime, module2::Instance2>::key().to_vec(),
module2::Value::<Runtime, module2::Instance3>::key().to_vec(),
module2::Map::<Runtime>::prefix().to_vec(),
module2::Map::<Runtime, module2::Instance1>::prefix().to_vec(),
module2::Map::<Runtime, module2::Instance2>::prefix().to_vec(),
module2::Map::<Runtime, module2::Instance3>::prefix().to_vec(),
module2::LinkedMap::<Runtime>::prefix().to_vec(),
module2::LinkedMap::<Runtime, module2::Instance1>::prefix().to_vec(),
module2::LinkedMap::<Runtime, module2::Instance2>::prefix().to_vec(),
module2::LinkedMap::<Runtime, module2::Instance3>::prefix().to_vec(),
module2::DoubleMap::<Runtime>::prefix().to_vec(),
module2::DoubleMap::<Runtime, module2::Instance1>::prefix().to_vec(),
module2::DoubleMap::<Runtime, module2::Instance2>::prefix().to_vec(),
module2::DoubleMap::<Runtime, module2::Instance3>::prefix().to_vec(),
module2::Map::<Runtime>::key_for(0),
module2::Map::<Runtime, module2::Instance1>::key_for(0).to_vec(),
module2::Map::<Runtime, module2::Instance2>::key_for(0).to_vec(),
module2::Map::<Runtime, module2::Instance3>::key_for(0).to_vec(),
module2::LinkedMap::<Runtime>::key_for(0),
module2::LinkedMap::<Runtime, module2::Instance1>::key_for(0).to_vec(),
module2::LinkedMap::<Runtime, module2::Instance2>::key_for(0).to_vec(),
module2::LinkedMap::<Runtime, module2::Instance3>::key_for(0).to_vec(),
module2::Map::<Runtime>::key_for(1),
module2::Map::<Runtime, module2::Instance1>::key_for(1).to_vec(),
module2::Map::<Runtime, module2::Instance2>::key_for(1).to_vec(),
module2::Map::<Runtime, module2::Instance3>::key_for(1).to_vec(),
module2::LinkedMap::<Runtime>::key_for(1),
module2::LinkedMap::<Runtime, module2::Instance1>::key_for(1).to_vec(),
module2::LinkedMap::<Runtime, module2::Instance2>::key_for(1).to_vec(),
module2::LinkedMap::<Runtime, module2::Instance3>::key_for(1).to_vec(),
module2::DoubleMap::<Runtime>::prefix_for(1),
module2::DoubleMap::<Runtime, module2::Instance1>::prefix_for(1).to_vec(),
module2::DoubleMap::<Runtime, module2::Instance2>::prefix_for(1).to_vec(),
module2::DoubleMap::<Runtime, module2::Instance3>::prefix_for(1).to_vec(),
module2::DoubleMap::<Runtime>::key_for(1, 1),
module2::DoubleMap::<Runtime, module2::Instance1>::key_for(1, 1).to_vec(),
module2::DoubleMap::<Runtime, module2::Instance2>::key_for(1, 1).to_vec(),
module2::DoubleMap::<Runtime, module2::Instance3>::key_for(1, 1).to_vec(),
module2::Map::<module2::DefaultInstance>::prefix().to_vec(),
module2::Map::<module2::Instance1>::prefix().to_vec(),
module2::Map::<module2::Instance2>::prefix().to_vec(),
module2::Map::<module2::Instance3>::prefix().to_vec(),
module2::LinkedMap::<module2::DefaultInstance>::prefix().to_vec(),
module2::LinkedMap::<module2::Instance1>::prefix().to_vec(),
module2::LinkedMap::<module2::Instance2>::prefix().to_vec(),
module2::LinkedMap::<module2::Instance3>::prefix().to_vec(),
module2::DoubleMap::<module2::DefaultInstance>::prefix().to_vec(),
module2::DoubleMap::<module2::Instance1>::prefix().to_vec(),
module2::DoubleMap::<module2::Instance2>::prefix().to_vec(),
module2::DoubleMap::<module2::Instance3>::prefix().to_vec(),
module2::Map::<module2::DefaultInstance>::key_for(0),
module2::Map::<module2::Instance1>::key_for(0).to_vec(),
module2::Map::<module2::Instance2>::key_for(0).to_vec(),
module2::Map::<module2::Instance3>::key_for(0).to_vec(),
module2::LinkedMap::<module2::DefaultInstance>::key_for(0),
module2::LinkedMap::<module2::Instance1>::key_for(0).to_vec(),
module2::LinkedMap::<module2::Instance2>::key_for(0).to_vec(),
module2::LinkedMap::<module2::Instance3>::key_for(0).to_vec(),
module2::Map::<module2::DefaultInstance>::key_for(1),
module2::Map::<module2::Instance1>::key_for(1).to_vec(),
module2::Map::<module2::Instance2>::key_for(1).to_vec(),
module2::Map::<module2::Instance3>::key_for(1).to_vec(),
module2::LinkedMap::<module2::DefaultInstance>::key_for(1),
module2::LinkedMap::<module2::Instance1>::key_for(1).to_vec(),
module2::LinkedMap::<module2::Instance2>::key_for(1).to_vec(),
module2::LinkedMap::<module2::Instance3>::key_for(1).to_vec(),
module2::DoubleMap::<module2::DefaultInstance>::prefix_for(1),
module2::DoubleMap::<module2::Instance1>::prefix_for(1).to_vec(),
module2::DoubleMap::<module2::Instance2>::prefix_for(1).to_vec(),
module2::DoubleMap::<module2::Instance3>::prefix_for(1).to_vec(),
module2::DoubleMap::<module2::DefaultInstance>::key_for(1, 1),
module2::DoubleMap::<module2::Instance1>::key_for(1, 1).to_vec(),
module2::DoubleMap::<module2::Instance2>::key_for(1, 1).to_vec(),
module2::DoubleMap::<module2::Instance3>::key_for(1, 1).to_vec(),
].iter() {
assert!(map.insert(key, ()).is_none())
}
@@ -378,9 +322,9 @@ fn storage_instance_independance() {
fn storage_with_instance_basic_operation() {
with_externalities(&mut new_test_ext(), || {
type Value = module2::Value<Runtime, module2::Instance1>;
type Map = module2::Map<Runtime, module2::Instance1>;
type LinkedMap = module2::LinkedMap<Runtime, module2::Instance1>;
type DoubleMap = module2::DoubleMap<Runtime, module2::Instance1>;
type Map = module2::Map<module2::Instance1>;
type LinkedMap = module2::LinkedMap<module2::Instance1>;
type DoubleMap = module2::DoubleMap<module2::Instance1>;
assert_eq!(Value::exists(), true);
assert_eq!(Value::get(), 4);
@@ -432,4 +376,4 @@ fn storage_with_instance_basic_operation() {
DoubleMap::remove(key1, key2);
assert_eq!(DoubleMap::get(key1, key2), 0);
});
}
}
@@ -0,0 +1,186 @@
// 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 srml_support::runtime_primitives::generic;
use srml_support::runtime_primitives::traits::{BlakeTwo256, Block as _, Verify};
use srml_support::codec::{Encode, Decode};
use primitives::{H256, sr25519};
use serde::{Serialize, Deserialize};
mod system;
mod module {
use super::*;
pub type Request<T> = (
<T as system::Trait>::AccountId,
Role,
<T as system::Trait>::BlockNumber,
);
pub type Requests<T> = Vec<Request<T>>;
#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Debug)]
pub enum Role {
Storage,
}
#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Debug)]
pub struct RoleParameters<T: Trait> {
// minimum actors to maintain - if role is unstaking
// and remaining actors would be less that this value - prevent or punish for unstaking
pub min_actors: u32,
// the maximum number of spots available to fill for a role
pub max_actors: u32,
// payouts are made at this block interval
pub reward_period: T::BlockNumber,
// minimum amount of time before being able to unstake
pub bonding_period: T::BlockNumber,
// how long tokens remain locked for after unstaking
pub unbonding_period: T::BlockNumber,
// minimum period required to be in service. unbonding before this time is highly penalized
pub min_service_period: T::BlockNumber,
// "startup" time allowed for roles that need to sync their infrastructure
// with other providers before they are considered in service and punishable for
// not delivering required level of service.
pub startup_grace_period: T::BlockNumber,
}
impl<T: Trait> Default for RoleParameters<T> {
fn default() -> Self {
Self {
max_actors: 10,
reward_period: T::BlockNumber::default(),
unbonding_period: T::BlockNumber::default(),
// not currently used
min_actors: 5,
bonding_period: T::BlockNumber::default(),
min_service_period: T::BlockNumber::default(),
startup_grace_period: T::BlockNumber::default(),
}
}
}
pub trait Trait: system::Trait {}
srml_support::decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {}
}
#[derive(Encode, Decode, Copy, Clone, Serialize, Deserialize)]
pub struct Data<T: Trait> {
pub data: T::BlockNumber,
}
impl<T: Trait> Default for Data<T> {
fn default() -> Self {
Self {
data: T::BlockNumber::default(),
}
}
}
srml_support::decl_storage! {
trait Store for Module<T: Trait> as Actors {
/// requirements to enter and maintain status in roles
pub Parameters get(parameters) build(|config: &GenesisConfig| {
if config.enable_storage_role {
let storage_params: RoleParameters<T> = Default::default();
vec![(Role::Storage, storage_params)]
} else {
vec![]
}
}): map Role => Option<RoleParameters<T>>;
/// the roles members can enter into
pub AvailableRoles get(available_roles) build(|config: &GenesisConfig| {
if config.enable_storage_role {
vec![(Role::Storage)]
} else {
vec![]
}
}): Vec<Role>;
/// Actors list
pub ActorAccountIds get(actor_account_ids) : Vec<T::AccountId>;
/// actor accounts associated with a role
pub AccountIdsByRole get(account_ids_by_role) : map Role => Vec<T::AccountId>;
/// tokens locked until given block number
pub Bondage get(bondage) : map T::AccountId => T::BlockNumber;
/// First step before enter a role is registering intent with a new account/key.
/// This is done by sending a role_entry_request() from the new account.
/// The member must then send a stake() transaction to approve the request and enter the desired role.
/// The account making the request will be bonded and must have
/// sufficient balance to cover the minimum stake for the role.
/// Bonding only occurs after successful entry into a role.
pub RoleEntryRequests get(role_entry_requests) : Requests<T>;
/// Entry request expires after this number of blocks
pub RequestLifeTime get(request_life_time) config(request_life_time) : u64 = 0;
}
add_extra_genesis {
config(enable_storage_role): bool;
}
}
}
pub type Signature = sr25519::Signature;
pub type AccountId = <Signature as Verify>::Signer;
pub type BlockNumber = u64;
pub type Index = u64;
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic<u32, Index, Call, Signature>;
impl system::Trait for Runtime {
type Hash = H256;
type Origin = Origin;
type BlockNumber = BlockNumber;
type AccountId = AccountId;
type Event = Event;
}
impl module::Trait for Runtime {}
srml_support::construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
System: system::{Module, Call, Event},
Module: module::{Module, Call, Storage, Config},
}
);
#[test]
fn create_genesis_config() {
GenesisConfig {
module: Some(module::GenesisConfig {
request_life_time: 0,
enable_storage_role: true,
})
};
}
@@ -0,0 +1,52 @@
use srml_support::codec::{Encode, Decode};
pub trait Trait: 'static + Eq + Clone {
type Origin: Into<Result<RawOrigin<Self::AccountId>, Self::Origin>>
+ From<RawOrigin<Self::AccountId>>;
type BlockNumber: Decode + Encode + Clone + Default;
type Hash;
type AccountId: Encode + Decode;
type Event: From<Event>;
}
srml_support::decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
pub fn deposit_event(_event: T::Event) {
}
}
}
srml_support::decl_event!(
pub enum Event {
ExtrinsicSuccess,
ExtrinsicFailed,
}
);
/// Origin for the system module.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum RawOrigin<AccountId> {
Root,
Signed(AccountId),
None,
}
impl<AccountId> From<Option<AccountId>> for RawOrigin<AccountId> {
fn from(s: Option<AccountId>) -> RawOrigin<AccountId> {
match s {
Some(who) => RawOrigin::Signed(who),
None => RawOrigin::None,
}
}
}
pub type Origin<T> = RawOrigin<<T as Trait>::AccountId>;
#[allow(dead_code)]
pub fn ensure_root<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<(), &'static str>
where OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>
{
o.into().map(|_| ()).map_err(|_| "bad origin: expected to be a root origin")
}