diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index a580a8450e..48a6e8942a 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -2568,6 +2568,23 @@ dependencies = [ "sr-std 0.1.0", ] +[[package]] +name = "srml-assets" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-primitives 0.1.0", +] + [[package]] name = "srml-balances" version = "0.1.0" diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index 869309d6aa..f47fa42507 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -39,6 +39,7 @@ members = [ "core/transaction-pool", "core/transaction-pool/graph", "srml/support", + "srml/assets", "srml/balances", "srml/consensus", "srml/contract", diff --git a/substrate/core/client/db/src/lib.rs b/substrate/core/client/db/src/lib.rs index 2bdb9f7500..f35dd8a05d 100644 --- a/substrate/core/client/db/src/lib.rs +++ b/substrate/core/client/db/src/lib.rs @@ -791,7 +791,7 @@ impl client::backend::Backend for Backend whe match self.storage.state_db.revert_one() { Some(commit) => { apply_state_commit(&mut transaction, commit); - let removed = best.clone(); + let _removed = best.clone(); best -= As::sa(1); let header = self.blockchain.header(BlockId::Number(best))?.ok_or_else( || client::error::ErrorKind::UnknownBlock( diff --git a/substrate/core/sr-primitives/src/lib.rs b/substrate/core/sr-primitives/src/lib.rs index aac96bc40f..15b86484a6 100644 --- a/substrate/core/sr-primitives/src/lib.rs +++ b/substrate/core/sr-primitives/src/lib.rs @@ -269,19 +269,32 @@ pub fn verify_encoded_lazy(sig: &V, item: &T, signe #[macro_export] macro_rules! __impl_outer_config_types { - ($concrete:ident $config:ident $snake:ident $($rest:ident)*) => { + ( + $concrete:ident $config:ident $snake:ident < $ignore:ident > $( $rest:tt )* + ) => { #[cfg(any(feature = "std", test))] pub type $config = $snake::GenesisConfig<$concrete>; __impl_outer_config_types! {$concrete $($rest)*} }; + ( + $concrete:ident $config:ident $snake:ident $( $rest:tt )* + ) => { + #[cfg(any(feature = "std", test))] + pub type $config = $snake::GenesisConfig; + __impl_outer_config_types! {$concrete $($rest)*} + }; ($concrete:ident) => () } #[macro_export] /// Implement the output "meta" module configuration struct. macro_rules! impl_outer_config { - ( pub struct $main:ident for $concrete:ident { $( $config:ident => $snake:ident, )* } ) => { - __impl_outer_config_types! { $concrete $( $config $snake )* } + ( + pub struct $main:ident for $concrete:ident { + $( $config:ident => $snake:ident $( < $generic:ident > )*, )* + } + ) => { + __impl_outer_config_types! { $concrete $( $config $snake $( < $generic > )* )* } #[cfg(any(feature = "std", test))] #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] diff --git a/substrate/core/sr-primitives/src/traits.rs b/substrate/core/sr-primitives/src/traits.rs index 6c188c35f4..4fc09f3e9e 100644 --- a/substrate/core/sr-primitives/src/traits.rs +++ b/substrate/core/sr-primitives/src/traits.rs @@ -566,5 +566,5 @@ pub trait ProvideInherent { pub trait Extrinsic { /// Is this `Extrinsic` signed? /// If no information are available about signed/unsigned, `None` should be returned. - fn is_signed(&self) -> Option; + fn is_signed(&self) -> Option { None } } diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index 81a5ddea2e..36dcd347b9 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -197,18 +197,18 @@ construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic { System: system::{default, Log(ChangesTrieRoot)}, - Consensus: consensus::{Module, Call, Storage, Config, Log(AuthoritiesChange), Inherent}, + Consensus: consensus::{Module, Call, Storage, Config, Log(AuthoritiesChange), Inherent}, Balances: balances, - Timestamp: timestamp::{Module, Call, Storage, Config, Inherent}, + Timestamp: timestamp::{Module, Call, Storage, Config, Inherent}, Session: session, Staking: staking, Democracy: democracy, Council: council::{Module, Call, Storage, Event}, CouncilVoting: council_voting, CouncilMotions: council_motions::{Module, Call, Storage, Event, Origin}, - CouncilSeats: council_seats::{Config}, + CouncilSeats: council_seats::{Config}, Treasury: treasury, - Contract: contract::{Module, Call, Config, Event}, + Contract: contract::{Module, Call, Config, Event}, } ); diff --git a/substrate/srml/assets/Cargo.toml b/substrate/srml/assets/Cargo.toml new file mode 100644 index 0000000000..58d84fb9bb --- /dev/null +++ b/substrate/srml/assets/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "srml-assets" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +hex-literal = "0.1.0" +serde = { version = "1.0", default-features = false } +serde_derive = { version = "1.0", optional = true } +parity-codec = { version = "2.1", default-features = false } +parity-codec-derive = { version = "2.1", default-features = false } +substrate-primitives = { path = "../../core/primitives", default-features = false } +sr-std = { path = "../../core/sr-std", default-features = false } +sr-io = { path = "../../core/sr-io", default-features = false } +sr-primitives = { path = "../../core/sr-primitives", default-features = false } +srml-support = { path = "../support", default-features = false } +srml-system = { path = "../system", default-features = false } + +[features] +default = ["std"] +std = [ + "serde/std", + "serde_derive", + "parity-codec/std", + "parity-codec-derive/std", + "substrate-primitives/std", + "sr-std/std", + "sr-io/std", + "sr-primitives/std", + "srml-support/std", + "srml-system/std", +] diff --git a/substrate/srml/assets/src/lib.rs b/substrate/srml/assets/src/lib.rs new file mode 100644 index 0000000000..61b36dc3c1 --- /dev/null +++ b/substrate/srml/assets/src/lib.rs @@ -0,0 +1,223 @@ +// Copyright 2017-2018 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 . + +//! A simple, secure module for dealing with fungible assets. + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +// Assert macros used in tests. +extern crate sr_std; + +// Needed for tests (`with_externalities`). +#[cfg(test)] +extern crate sr_io as runtime_io; + +// Needed for the set of mock primitives used in our tests. +#[cfg(test)] +extern crate substrate_primitives; + +// Needed for deriving `Serialize` and `Deserialize` for various types. +// We only implement the serde traits for std builds - they're unneeded +// in the wasm runtime. +#[cfg(feature = "std")] +#[macro_use] +extern crate serde_derive; + +// Needed for deriving `Encode` and `Decode` for `RawEvent`. +#[macro_use] +extern crate parity_codec_derive; +extern crate parity_codec as codec; + +// Needed for type-safe access to storage DB. +#[macro_use] +extern crate srml_support as runtime_support; + +// Needed for various traits. In our case, `OnFinalise`. +extern crate sr_primitives as primitives; +// `system` module provides us with all sorts of useful stuff and macros +// depend on it being around. +extern crate srml_system as system; + +use primitives::traits::OnFinalise; +use runtime_support::{StorageValue, StorageMap, dispatch::Result, Parameter}; +use primitives::traits::{Member, SimpleArithmetic, Zero}; +use system::ensure_signed; + +pub trait Trait: system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// The units in which we record balances. + type Balance: Member + Parameter + SimpleArithmetic + Default + Copy; +} + +type AssetId = u32; + +decl_module! { + // Simple declaration of the `Module` type. Lets the macro know what its working on. + pub struct Module for enum Call where origin: T::Origin { + /// Issue a new class of fungible assets. There are, and will only ever be, `total` + /// such assets and they'll all belong to the `origin` initially. It will have an + /// identifier `AssetId` instance: this will be specified in the `Issued` event. + fn issue(origin, total: T::Balance) -> Result; + + /// Move some assets from one holder to another. + fn transfer(origin, id: AssetId, target: T::AccountId, total: T::Balance) -> Result; + + /// Destroy any assets of `id` owned by `origin`. + fn destroy(origin, id: AssetId) -> Result; + } +} + +/// An event in this module. Events are simple means of reporting specific conditions and +/// circumstances that have happened that users, Dapps and/or chain explorers would find +/// interesting and otherwise difficult to detect. +decl_event!( + pub enum Event where ::AccountId, ::Balance { + /// Some assets were issued. + Issued(AssetId, AccountId, Balance), + /// Some assets were transfered. + Transfered(AssetId, AccountId, AccountId, Balance), + /// Some assets were destroyed. + Destroyed(AssetId, AccountId, Balance), + } +); + +decl_storage! { + trait Store for Module as Assets { + /// The number of units of assets held by any given account. + Balances: map (AssetId, T::AccountId) => T::Balance; + /// The next asset identifier up for grabs. + NextAssetId get(next_asset_id): AssetId; + } +} + +// The main implementation block for the module. +impl Module { + /// Deposit one of this module's events. + // TODO: move into `decl_module` macro. + fn deposit_event(event: Event) { + >::deposit_event(::Event::from(event).into()); + } + + // Public immutables + + /// Get the asset `id` balance of `who`. + pub fn balance(id: AssetId, who: T::AccountId) -> T::Balance { + >::get((id, who)) + } + + // Implement Calls and add public immutables and private mutables. + + fn issue(origin: T::Origin, total: T::Balance) -> Result { + let origin = ensure_signed(origin)?; + + let id = Self::next_asset_id(); + >::mutate(|id| *id += 1); + + + >::insert((id, origin.clone()), total); + + Self::deposit_event(RawEvent::Issued(id, origin, total)); + Ok(()) + } + + fn transfer(origin: T::Origin, id: AssetId, target: T::AccountId, amount: T::Balance) -> Result { + let origin = ensure_signed(origin)?; + let origin_account = (id, origin.clone()); + let origin_balance = >::get(&origin_account); + ensure!(origin_balance >= amount, "origin account balance must be greater than amount"); + + Self::deposit_event(RawEvent::Transfered(id, origin, target.clone(), amount)); + >::insert(origin_account, origin_balance - amount); + >::mutate((id, target), |balance| *balance += amount); + + Ok(()) + } + + fn destroy(origin: T::Origin, id: AssetId) -> Result { + let origin = ensure_signed(origin)?; + + let balance = >::take((id, origin.clone())); + ensure!(!balance.is_zero(), "origin balance should be non-zero"); + + Self::deposit_event(RawEvent::Destroyed(id, origin, balance)); + + Ok(()) + } +} + +// This trait expresses what should happen when the block is finalised. +impl OnFinalise for Module {} + +#[cfg(test)] +mod tests { + use super::*; + + use runtime_io::with_externalities; + use substrate_primitives::{H256, Blake2Hasher}; + // The testing primitives are very useful for avoiding having to work with signatures + // or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. + use primitives::{BuildStorage, traits::{BlakeTwo256}, testing::{Digest, DigestItem, Header}}; + + impl_outer_origin! { + pub enum Origin for Test {} + } + + // For testing the module, we construct most of a mock runtime. This means + // first constructing a configuration type (`Test`) which `impl`s each of the + // configuration traits of modules we want to use. + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Header = Header; + type Event = (); + type Log = DigestItem; + } + impl Trait for Test { + type Event = (); + type Balance = u64; + } + type Assets = Module; + + // This function basically just builds a genesis storage key/value store according to + // our desired mockup. + fn new_test_ext() -> runtime_io::TestExternalities { + system::GenesisConfig::::default().build_storage().unwrap().into() + } + + #[test] + fn it_works() { + with_externalities(&mut new_test_ext(), || { + assert_ok!(Assets::issue(Origin::signed(1), 100)); + assert_eq!(Assets::balance(0, 1), 100); + assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 50)); + assert_eq!(Assets::balance(0, 1), 50); + assert_eq!(Assets::balance(0, 2), 50); + assert_ok!(Assets::destroy(Origin::signed(2), 0)); + assert_eq!(Assets::balance(0, 2), 0); + assert_noop!(Assets::transfer(Origin::signed(2), 0, 1, 50), "origin account balance must be greater than amount"); + }); + } +} diff --git a/substrate/srml/example/Cargo.toml b/substrate/srml/example/Cargo.toml index ae2174ca23..34d8d058d1 100644 --- a/substrate/srml/example/Cargo.toml +++ b/substrate/srml/example/Cargo.toml @@ -20,15 +20,15 @@ srml-balances = { path = "../balances", default-features = false } [features] default = ["std"] std = [ - "sr-std/std", - "sr-io/std", - "srml-support/std", - "sr-primitives/std", - "srml-balances/std", "serde/std", "serde_derive", "parity-codec/std", "parity-codec-derive/std", + "sr-std/std", + "sr-io/std", + "sr-primitives/std", "substrate-primitives/std", + "srml-support/std", "srml-system/std", + "srml-balances/std", ] diff --git a/substrate/srml/example/src/lib.rs b/substrate/srml/example/src/lib.rs index 8952893540..f60168d37b 100644 --- a/substrate/srml/example/src/lib.rs +++ b/substrate/srml/example/src/lib.rs @@ -25,12 +25,15 @@ extern crate sr_std; // Needed for tests (`with_externalities`). #[cfg(test)] -extern crate sr_io as runtime_io; +extern crate sr_io; // Needed for the set of mock primitives used in our tests. #[cfg(test)] extern crate substrate_primitives; +// Needed for various traits. In our case, `OnFinalise`. +extern crate sr_primitives; + // Needed for deriving `Serialize` and `Deserialize` for various types. // We only implement the serde traits for std builds - they're unneeded // in the wasm runtime. @@ -45,10 +48,7 @@ extern crate parity_codec as codec; // Needed for type-safe access to storage DB. #[macro_use] -extern crate srml_support as runtime_support; - -// Needed for various traits. In our case, `OnFinalise`. -extern crate sr_primitives as runtime_primitives; +extern crate srml_support as support; // `system` module provides us with all sorts of useful stuff and macros // depend on it being around. extern crate srml_system as system; @@ -57,8 +57,8 @@ extern crate srml_system as system; // might find it useful). extern crate srml_balances as balances; -use runtime_primitives::traits::OnFinalise; -use runtime_support::{StorageValue, dispatch::Result}; +use sr_primitives::traits::OnFinalise; +use support::{StorageValue, dispatch::Result}; use system::ensure_signed; /// Our module's configuration trait. All our types and consts go in here. If the @@ -147,8 +147,8 @@ decl_storage! { // e.g. pub Bar get(bar): map T::AccountId => Vec<(T::Balance, u64)>; // // For basic value items, you'll get a type which implements - // `runtime_support::StorageValue`. For map items, you'll get a type which - // implements `runtime_support::StorageMap`. + // `support::StorageValue`. For map items, you'll get a type which + // implements `support::StorageMap`. // // If they have a getter (`get(getter_name)`), then your module will come // equipped with `fn getter_name() -> Type` for basic value items or @@ -241,6 +241,7 @@ impl Module { Ok(()) } + #[allow(dead_code)] fn accumulate_foo(origin: T::Origin, increase_by: T::Balance) -> Result { let _sender = ensure_signed(origin)?; @@ -278,15 +279,11 @@ impl OnFinalise for Module { mod tests { use super::*; - use runtime_io::with_externalities; + use sr_io::with_externalities; use substrate_primitives::{H256, Blake2Hasher}; - use runtime_primitives::BuildStorage; - use runtime_primitives::traits::{BlakeTwo256}; - use runtime_primitives::testing::DigestItem; - // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. - use runtime_primitives::testing::{Digest, Header}; + use sr_primitives::{BuildStorage, traits::{BlakeTwo256}, testing::{Digest, DigestItem, Header}}; impl_outer_origin! { pub enum Origin for Test {} @@ -323,7 +320,7 @@ mod tests { // This function basically just builds a genesis storage key/value store according to // our desired mockup. - fn new_test_ext() -> runtime_io::TestExternalities { + fn new_test_ext() -> sr_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap(); // We use default for brevity, but you can configure as desired if needed. t.extend(balances::GenesisConfig::::default().build_storage().unwrap()); diff --git a/substrate/srml/support/src/runtime.rs b/substrate/srml/support/src/runtime.rs index 75cf0eaf24..3e42e1970e 100644 --- a/substrate/srml/support/src/runtime.rs +++ b/substrate/srml/support/src/runtime.rs @@ -42,7 +42,7 @@ /// - `Storage` /// - `Event` or `Event` (if the event is generic) /// - `Origin` or `Origin` (if the origin is generic) -/// - `Config` +/// - `Config` or `Config` (if the config is generic) /// - `Log( $(IDENT),* )` #[macro_export] macro_rules! construct_runtime { @@ -102,7 +102,7 @@ macro_rules! construct_runtime { $( ( $( $expanded_modules_args ),* ) )* ),* }, - )* $name: $module::{Module, Call, Storage, Event, Config}; + )* $name: $module::{Module, Call, Storage, Event, Config}; $( $rest_name: $rest_module $( ::{ @@ -165,7 +165,7 @@ macro_rules! construct_runtime { }, )* $name: $module::{ - Module, Call, Storage, Event, Config, + Module, Call, Storage, Event, Config, $( $modules $( <$modules_generic> )* $( ( $( $modules_args ),* ) )* ),* @@ -952,7 +952,7 @@ macro_rules! __decl_outer_log { macro_rules! __decl_outer_config { ( $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident ),*; + $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; $name:ident: $module:ident::{ Config $(, $modules:ident $( <$modules_generic:ident> )* )* } @@ -962,7 +962,7 @@ macro_rules! __decl_outer_config { ) => { __decl_outer_config!( $runtime; - $( $parsed_modules :: $parsed_name, )* $module::$name; + $( $parsed_modules :: $parsed_name $( < $parsed_generic > )*, )* $module::$name; $( $rest_name: $rest_module::{ $( $rest_modules $( <$rest_modules_generic> )* ),* @@ -972,7 +972,27 @@ macro_rules! __decl_outer_config { }; ( $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident ),*; + $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; + $name:ident: $module:ident::{ + Config $(, $modules:ident $( <$modules_generic:ident> )* )* + } + $(, $rest_name:ident : $rest_module:ident::{ + $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* + })*; + ) => { + __decl_outer_config!( + $runtime; + $( $parsed_modules :: $parsed_name $( < $parsed_generic > )*, )* $module::$name; + $( + $rest_name: $rest_module::{ + $( $rest_modules $( <$rest_modules_generic> )* ),* + } + ),*; + ); + }; + ( + $runtime:ident; + $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; $name:ident: $module:ident::{ $ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )* } @@ -982,7 +1002,7 @@ macro_rules! __decl_outer_config { ) => { __decl_outer_config!( $runtime; - $( $parsed_modules :: $parsed_name ),*; + $( $parsed_modules :: $parsed_name $( < $parsed_generic > )*),*; $name: $module::{ $( $modules $( <$modules_generic> )* ),* } $( , $rest_name: $rest_module::{ @@ -993,7 +1013,7 @@ macro_rules! __decl_outer_config { }; ( $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident ),*; + $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; $name:ident: $module:ident::{} $(, $rest_name:ident : $rest_module:ident::{ $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* @@ -1001,7 +1021,7 @@ macro_rules! __decl_outer_config { ) => { __decl_outer_config!( $runtime; - $( $parsed_modules :: $parsed_name ),*; + $( $parsed_modules :: $parsed_name $( < $parsed_generic > )*),*; $( $rest_name: $rest_module::{ $( $rest_modules $( <$rest_modules_generic> )* ),* @@ -1011,14 +1031,14 @@ macro_rules! __decl_outer_config { }; ( $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident ),*; + $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; ; ) => { substrate_generate_ident_name! { impl_outer_config!( pub struct GenesisConfig for $runtime { $( - "config-ident" $parsed_name => $parsed_modules, + "config-ident" $parsed_name => $parsed_modules $( < $parsed_generic > )*, )* } ); diff --git a/substrate/srml/support/src/storage/generator.rs b/substrate/srml/support/src/storage/generator.rs index 2c6c96e600..8398819ebe 100644 --- a/substrate/srml/support/src/storage/generator.rs +++ b/substrate/srml/support/src/storage/generator.rs @@ -590,6 +590,21 @@ macro_rules! __generate_genesis_config { ); }; + // Do not generate any `GenesisConfig`, if we not require it. + (@GEN + [$traittype:ident $traitinstance:ident] + // normal getters + [] + // for normal builders + [$( $normalclassname:ident ($normalbuild:expr) ;)*] + // for map builders + [$( $mapclassname:ident ($mapbuild:expr) ;)*] + // extra genesis fields + [] + // final build storage call + [$call:expr] + ) => {}; + (@GEN [$traittype:ident $traitinstance:ident] // normal getters diff --git a/substrate/srml/timestamp/src/lib.rs b/substrate/srml/timestamp/src/lib.rs index 02514289b5..c13972c7da 100644 --- a/substrate/srml/timestamp/src/lib.rs +++ b/substrate/srml/timestamp/src/lib.rs @@ -33,7 +33,7 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[macro_use] +#[cfg_attr(not(feature = "std"), macro_use)] extern crate sr_std as rstd; #[macro_use]