From b8f623084a2e9168b0d09e279cac42b0a4660852 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 29 Aug 2018 15:29:34 +0200 Subject: [PATCH 01/19] Initial commit. --- Cargo.toml | 1 + substrate/runtime/balances/Cargo.toml | 46 + substrate/runtime/balances/src/address.rs | 111 ++ .../runtime/balances/src/genesis_config.rs | 165 +++ substrate/runtime/balances/src/lib.rs | 1037 +++++++++++++++++ substrate/runtime/balances/src/mock.rs | 115 ++ substrate/runtime/balances/src/tests.rs | 770 ++++++++++++ substrate/runtime/staking/Cargo.toml | 2 + substrate/runtime/staking/src/lib.rs | 95 +- 9 files changed, 2300 insertions(+), 42 deletions(-) create mode 100644 substrate/runtime/balances/Cargo.toml create mode 100644 substrate/runtime/balances/src/address.rs create mode 100644 substrate/runtime/balances/src/genesis_config.rs create mode 100644 substrate/runtime/balances/src/lib.rs create mode 100644 substrate/runtime/balances/src/mock.rs create mode 100644 substrate/runtime/balances/src/tests.rs diff --git a/Cargo.toml b/Cargo.toml index e01d45d2d03d3..d853608a8f99d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ members = [ "substrate/runtime-sandbox", "substrate/runtime-std", "substrate/runtime-support", + "substrate/runtime/balances", "substrate/runtime/consensus", "substrate/runtime/contract", "substrate/runtime/council", diff --git a/substrate/runtime/balances/Cargo.toml b/substrate/runtime/balances/Cargo.toml new file mode 100644 index 0000000000000..1cde7ebf9833f --- /dev/null +++ b/substrate/runtime/balances/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "substrate-runtime-balances" +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 } +safe-mix = { version = "1.0", default_features = false} +substrate-keyring = { path = "../../keyring", optional = true } +substrate-codec = { path = "../../codec", default_features = false } +substrate-codec-derive = { path = "../../codec/derive", default_features = false } +substrate-primitives = { path = "../../primitives", default_features = false } +substrate-runtime-std = { path = "../../runtime-std", default_features = false } +substrate-runtime-io = { path = "../../runtime-io", default_features = false } +substrate-runtime-sandbox = { path = "../../runtime-sandbox", default_features = false } +substrate-runtime-support = { path = "../../runtime-support", default_features = false } +substrate-runtime-primitives = { path = "../primitives", default_features = false } +substrate-runtime-consensus = { path = "../consensus", default_features = false } +substrate-runtime-system = { path = "../system", default_features = false } +substrate-runtime-session = { path = "../session", default_features = false } +substrate-runtime-timestamp = { path = "../timestamp", default_features = false } + +[dev-dependencies] +wabt = "0.4" + +[features] +default = ["std"] +std = [ + "serde/std", + "serde_derive", + "safe-mix/std", + "substrate-keyring", + "substrate-codec/std", + "substrate-codec-derive/std", + "substrate-primitives/std", + "substrate-runtime-std/std", + "substrate-runtime-io/std", + "substrate-runtime-sandbox/std", + "substrate-runtime-support/std", + "substrate-runtime-primitives/std", + "substrate-runtime-session/std", + "substrate-runtime-system/std", + "substrate-runtime-timestamp/std" +] diff --git a/substrate/runtime/balances/src/address.rs b/substrate/runtime/balances/src/address.rs new file mode 100644 index 0000000000000..249e0b20db225 --- /dev/null +++ b/substrate/runtime/balances/src/address.rs @@ -0,0 +1,111 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo 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 Demo 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 Demo. If not, see . + +//! Address type that is union of index and id for an account. + +#[cfg(feature = "std")] +use std::fmt; +use super::{Member, Decode, Encode, As, Input, Output}; + +/// A vetted and verified extrinsic from the external world. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash))] +pub enum Address where + AccountId: Member, + AccountIndex: Member, +{ + /// It's an account ID (pubkey). + #[cfg_attr(feature = "std", serde(deserialize_with="AccountId::deserialize"))] + Id(AccountId), + /// It's an account index. + #[cfg_attr(feature = "std", serde(deserialize_with="AccountIndex::deserialize"))] + Index(AccountIndex), +} + +#[cfg(feature = "std")] +impl fmt::Display for Address where + AccountId: Member, + AccountIndex: Member, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "{:?}", self) + } +} + +impl From for Address where + AccountId: Member, + AccountIndex: Member, +{ + fn from(a: AccountId) -> Self { + Address::Id(a) + } +} + +fn need_more_than(a: T, b: T) -> Option { + if a < b { Some(a) } else { None } +} + +impl Decode for Address where + AccountId: Member + Decode, + AccountIndex: Member + Decode + PartialOrd + Ord + As + As + As + Copy, +{ + fn decode(input: &mut I) -> Option { + Some(match input.read_byte()? { + x @ 0x00...0xef => Address::Index(As::sa(x)), + 0xfc => Address::Index(As::sa(need_more_than(0xef, u16::decode(input)?)?)), + 0xfd => Address::Index(As::sa(need_more_than(0xffff, u32::decode(input)?)?)), + 0xfe => Address::Index(need_more_than(As::sa(0xffffffffu32), Decode::decode(input)?)?), + 0xff => Address::Id(Decode::decode(input)?), + _ => return None, + }) + } +} + +impl Encode for Address where + AccountId: Member + Encode, + AccountIndex: Member + Encode + PartialOrd + Ord + As + As + As + Copy, +{ + fn encode_to(&self, dest: &mut T) { + match *self { + Address::Id(ref i) => { + dest.push_byte(255); + dest.push(i); + } + Address::Index(i) if i > As::sa(0xffffffffu32) => { + dest.push_byte(254); + dest.push(&i); + } + Address::Index(i) if i > As::sa(0xffffu32) => { + dest.push_byte(253); + dest.push(&As::::as_(i)); + } + Address::Index(i) if i >= As::sa(0xf0u32) => { + dest.push_byte(252); + dest.push(&As::::as_(i)); + } + Address::Index(i) => dest.push_byte(As::::as_(i)), + } + } +} + +impl Default for Address where + AccountId: Member + Default, + AccountIndex: Member, +{ + fn default() -> Self { + Address::Id(Default::default()) + } +} diff --git a/substrate/runtime/balances/src/genesis_config.rs b/substrate/runtime/balances/src/genesis_config.rs new file mode 100644 index 0000000000000..8da72bf1d92ab --- /dev/null +++ b/substrate/runtime/balances/src/genesis_config.rs @@ -0,0 +1,165 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo 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 Demo 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 Demo. If not, see . + +//! Build a staking genesis block. + +#![cfg(feature = "std")] + +use std::collections::HashMap; +use rstd::prelude::*; +use codec::Encode; +use runtime_support::{StorageValue, StorageMap}; +use primitives::traits::{Zero, As}; +use substrate_primitives::KeccakHasher; +use {runtime_io, primitives}; +use super::{Trait, ENUM_SET_SIZE, EnumSet, NextEnumSet, Intentions, CurrentEra, + BondingDuration, CreationFee, TransferFee, ReclaimRebate, + ExistentialDeposit, TransactionByteFee, TransactionBaseFee, TotalStake, + SessionsPerEra, ValidatorCount, FreeBalance, SessionReward, EarlyEraSlash, + OfflineSlashGrace, MinimumValidatorCount}; + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct GenesisConfig { + pub sessions_per_era: T::BlockNumber, + pub current_era: T::BlockNumber, + pub balances: Vec<(T::AccountId, T::Balance)>, + pub intentions: Vec, + pub validator_count: u32, + pub minimum_validator_count: u32, + pub bonding_duration: T::BlockNumber, + pub transaction_base_fee: T::Balance, + pub transaction_byte_fee: T::Balance, + pub transfer_fee: T::Balance, + pub creation_fee: T::Balance, + pub reclaim_rebate: T::Balance, + pub existential_deposit: T::Balance, + pub session_reward: T::Balance, + pub early_era_slash: T::Balance, + pub offline_slash_grace: u32, +} + +impl GenesisConfig where T::AccountId: From { + pub fn simple() -> Self { + GenesisConfig { + sessions_per_era: T::BlockNumber::sa(2), + current_era: T::BlockNumber::sa(0), + balances: vec![(T::AccountId::from(1), T::Balance::sa(111))], + intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], + validator_count: 3, + minimum_validator_count: 1, + bonding_duration: T::BlockNumber::sa(0), + transaction_base_fee: T::Balance::sa(0), + transaction_byte_fee: T::Balance::sa(0), + transfer_fee: T::Balance::sa(0), + creation_fee: T::Balance::sa(0), + existential_deposit: T::Balance::sa(0), + reclaim_rebate: T::Balance::sa(0), + session_reward: T::Balance::sa(0), + early_era_slash: T::Balance::sa(0), + offline_slash_grace: 1, + } + } + + pub fn extended() -> Self { + GenesisConfig { + sessions_per_era: T::BlockNumber::sa(3), + current_era: T::BlockNumber::sa(1), + balances: vec![ + (T::AccountId::from(1), T::Balance::sa(10)), + (T::AccountId::from(2), T::Balance::sa(20)), + (T::AccountId::from(3), T::Balance::sa(30)), + (T::AccountId::from(4), T::Balance::sa(40)), + (T::AccountId::from(5), T::Balance::sa(50)), + (T::AccountId::from(6), T::Balance::sa(60)), + (T::AccountId::from(7), T::Balance::sa(1)) + ], + intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], + validator_count: 3, + minimum_validator_count: 1, + bonding_duration: T::BlockNumber::sa(0), + transaction_base_fee: T::Balance::sa(1), + transaction_byte_fee: T::Balance::sa(0), + transfer_fee: T::Balance::sa(0), + creation_fee: T::Balance::sa(0), + existential_deposit: T::Balance::sa(0), + reclaim_rebate: T::Balance::sa(0), + session_reward: T::Balance::sa(0), + early_era_slash: T::Balance::sa(0), + offline_slash_grace: 1, + } + } +} + +impl Default for GenesisConfig { + fn default() -> Self { + GenesisConfig { + sessions_per_era: T::BlockNumber::sa(1000), + current_era: T::BlockNumber::sa(0), + balances: vec![], + intentions: vec![], + validator_count: 0, + minimum_validator_count: 0, + bonding_duration: T::BlockNumber::sa(1000), + transaction_base_fee: T::Balance::sa(0), + transaction_byte_fee: T::Balance::sa(0), + transfer_fee: T::Balance::sa(0), + creation_fee: T::Balance::sa(0), + existential_deposit: T::Balance::sa(0), + reclaim_rebate: T::Balance::sa(0), + session_reward: T::Balance::sa(0), + early_era_slash: T::Balance::sa(0), + offline_slash_grace: 0, + } + } +} + +impl primitives::BuildStorage for GenesisConfig { + fn build_storage(self) -> ::std::result::Result, Vec>, String> { + let total_stake: T::Balance = self.balances.iter().fold(Zero::zero(), |acc, &(_, n)| acc + n); + + let mut r: runtime_io::TestExternalities = map![ + Self::hash(>::key()).to_vec() => T::AccountIndex::sa(self.balances.len() / ENUM_SET_SIZE).encode(), + Self::hash(>::key()).to_vec() => self.intentions.encode(), + Self::hash(>::key()).to_vec() => self.sessions_per_era.encode(), + Self::hash(>::key()).to_vec() => self.validator_count.encode(), + Self::hash(>::key()).to_vec() => self.minimum_validator_count.encode(), + Self::hash(>::key()).to_vec() => self.bonding_duration.encode(), + Self::hash(>::key()).to_vec() => self.transaction_base_fee.encode(), + Self::hash(>::key()).to_vec() => self.transaction_byte_fee.encode(), + Self::hash(>::key()).to_vec() => self.transfer_fee.encode(), + Self::hash(>::key()).to_vec() => self.creation_fee.encode(), + Self::hash(>::key()).to_vec() => self.existential_deposit.encode(), + Self::hash(>::key()).to_vec() => self.reclaim_rebate.encode(), + Self::hash(>::key()).to_vec() => self.current_era.encode(), + Self::hash(>::key()).to_vec() => self.session_reward.encode(), + Self::hash(>::key()).to_vec() => self.early_era_slash.encode(), + Self::hash(>::key()).to_vec() => self.offline_slash_grace.encode(), + Self::hash(>::key()).to_vec() => total_stake.encode() + ]; + + let ids: Vec<_> = self.balances.iter().map(|x| x.0.clone()).collect(); + for i in 0..(ids.len() + ENUM_SET_SIZE - 1) / ENUM_SET_SIZE { + r.insert(Self::hash(&>::key_for(T::AccountIndex::sa(i))).to_vec(), + ids[i * ENUM_SET_SIZE..ids.len().min((i + 1) * ENUM_SET_SIZE)].to_owned().encode()); + } + for (who, value) in self.balances.into_iter() { + r.insert(Self::hash(&>::key_for(who)).to_vec(), value.encode()); + } + Ok(r.into()) + } +} diff --git a/substrate/runtime/balances/src/lib.rs b/substrate/runtime/balances/src/lib.rs new file mode 100644 index 0000000000000..092a419cc74a2 --- /dev/null +++ b/substrate/runtime/balances/src/lib.rs @@ -0,0 +1,1037 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo 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 Demo 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 Demo. If not, see . + +//! Staking manager: Handles balances and periodically determines the best set of validators. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +extern crate serde; + +#[cfg(feature = "std")] +#[macro_use] +extern crate serde_derive; + +#[cfg(test)] +extern crate wabt; + +#[macro_use] +extern crate substrate_runtime_support as runtime_support; + +#[cfg_attr(feature = "std", macro_use)] +extern crate substrate_runtime_std as rstd; + +#[macro_use] +extern crate substrate_codec_derive; + +extern crate substrate_codec as codec; +extern crate substrate_primitives; +extern crate substrate_runtime_io as runtime_io; +extern crate substrate_runtime_primitives as primitives; +extern crate substrate_runtime_consensus as consensus; +extern crate substrate_runtime_sandbox as sandbox; +extern crate substrate_runtime_session as session; +extern crate substrate_runtime_system as system; +extern crate substrate_runtime_timestamp as timestamp; + +#[cfg(test)] use std::fmt::Debug; +use rstd::prelude::*; +use rstd::{cmp, result}; +use codec::{Encode, Decode, Codec, Input, Output}; +use runtime_support::{StorageValue, StorageMap, Parameter}; +use runtime_support::dispatch::Result; +use session::OnSessionChange; +use primitives::traits::{Zero, One, Bounded, RefInto, SimpleArithmetic, Executable, MakePayment, + As, AuxLookup, Member, CheckedAdd, CheckedSub, MaybeEmpty}; +use address::Address as RawAddress; + +mod mock; + +pub mod address; +mod tests; +mod genesis_config; + +#[cfg(feature = "std")] +pub use genesis_config::GenesisConfig; + +/// Number of account IDs stored per enum set. +const ENUM_SET_SIZE: usize = 64; + +/// The byte to identify intention to reclaim an existing account index. +const RECLAIM_INDEX_MAGIC: usize = 0x69; + +pub type Address = RawAddress<::AccountId, ::AccountIndex>; + +pub type Event = RawEvent< + ::AccountId, + ::AccountIndex +>; + +#[derive(PartialEq, Clone)] +#[cfg_attr(test, derive(Debug))] +pub enum LockStatus { + Liquid, + LockedUntil(BlockNumber), + Bonded, +} + +/// The account was the given id was killed. +pub trait OnFreeBalanceZero { + /// The account was the given id was killed. + fn on_free_balance_zero(who: &AccountId); +} + +impl OnFreeBalanceZero for () { + fn on_free_balance_zero(_who: &AccountId) {} +} + +pub trait Trait: system::Trait + session::Trait { + /// The balance of an account. + type Balance: Parameter + SimpleArithmetic + Codec + Default + Copy + As + As + As; + /// Type used for storing an account's index; implies the maximum number of accounts the system + /// can hold. + type AccountIndex: Parameter + Member + Codec + SimpleArithmetic + As + As + As + As + As + Copy; + /// A function which is invoked when the free-balance has fallen below the existential deposit and + /// has been reduced to zero. + /// + /// Gives a chance to clean up resources associated with the given account. + type OnFreeBalanceZero: OnFreeBalanceZero; + + /// The overarching event type. + type Event: From> + Into<::Event>; +} + +decl_module! { + pub struct Module; + + #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] + pub enum Call where aux: T::PublicAux { + fn transfer(aux, dest: RawAddress, value: T::Balance) -> Result = 0; + } + + #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] + pub enum PrivCall { + fn set_balance(who: RawAddress, free: T::Balance, reserved: T::Balance) -> Result = 0; + } +} + +/// An event in this module. +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[derive(Encode, Decode, PartialEq, Eq, Clone)] +pub enum RawEvent { + /// A new account was created. + NewAccount(AccountId, AccountIndex, NewAccountOutcome), + /// An account was reaped. + ReapedAccount(AccountId), +} + +impl From> for () { + fn from(_: RawEvent) -> () { () } +} + +decl_storage! { + trait Store for staking::Module { + + // Separate into Accounts module. + + // The length of the bonding duration in eras. + pub BondingDuration get(bonding_duration): required T::BlockNumber; + // The total amount of stake on the system. + pub TotalStake get(total_stake): required T::Balance; + // The minimum amount allowed to keep an account open. + pub ExistentialDeposit get(existential_deposit): required T::Balance; + // The amount credited to a destination's account whose index was reclaimed. + pub ReclaimRebate get(reclaim_rebate): required T::Balance; + // The fee required to make a transfer. + pub TransferFee get(transfer_fee): required T::Balance; + // The fee required to create an account. At least as big as ReclaimRebate. + pub CreationFee get(creation_fee): required T::Balance; + + // The next free enumeration set. + pub NextEnumSet get(next_enum_set): required T::AccountIndex; + // The enumeration sets. + pub EnumSet get(enum_set): default map [ T::AccountIndex => Vec ]; + + // The "free" balance of a given account. + // + // This is the only balance that matters in terms of most operations on tokens. It is + // alone used to determine the balance when in the contract execution environment. When this + // balance falls below the value of `ExistentialDeposit`, then the "current account" is + // deleted: specifically, `Bondage` and `FreeBalance`. Furthermore, `OnFreeBalanceZero` callback + // is invoked, giving a chance to external modules to cleanup data associated with + // the deleted account. + // + // `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets + // collapsed to zero if it ever becomes less than `ExistentialDeposit`. + pub FreeBalance get(free_balance): default map [ T::AccountId => T::Balance ]; + + // The amount of the balance of a given account that is exterally reserved; this can still get + // slashed, but gets slashed last of all. + // + // This balance is a "reserve" balance that other subsystems use in order to set aside tokens + // that are still "owned" by the account holder, but which are unspendable. This is different + // and wholly unrelated to the `Bondage` system used for staking. + // + // When this balance falls below the value of `ExistentialDeposit`, then this "reserve account" + // is deleted: specifically, `ReservedBalance`. + // + // `system::AccountNonce` is also deleted if `FreeBalance` is also zero (it also gets + // collapsed to zero if it ever becomes less than `ExistentialDeposit`. + pub ReservedBalance get(reserved_balance): default map [ T::AccountId => T::Balance ]; + + // The block at which the `who`'s funds become entirely liquid. + pub Bondage get(bondage): default map [ T::AccountId => T::BlockNumber ]; + + + // Separate into Payment module. + + // The fee to be paid for making a transaction; the base. + pub TransactionBaseFee get(transaction_base_fee): required T::Balance; + // The fee to be paid for making a transaction; the per-byte portion. + pub TransactionByteFee get(transaction_byte_fee): required T::Balance; + + + // Remains in Staking module + + // The ideal number of staking participants. + pub ValidatorCount get(validator_count): required u32; + // Minimum number of staking participants before emergency conditions are imposed. + pub MinimumValidatorCount: u32; + // The length of a staking era in sessions. + pub SessionsPerEra get(sessions_per_era): required T::BlockNumber; + + // Maximum reward, per validator, that is provided per acceptable session. + pub SessionReward get(session_reward): required T::Balance; + // Slash, per validator that is taken per abnormal era end. + pub EarlyEraSlash get(early_era_slash): required T::Balance; + // Number of instances of offline reports before slashing begins for validators. + pub OfflineSlashGrace get(offline_slash_grace): default u32; + + // The current era index. + pub CurrentEra get(current_era): required T::BlockNumber; + // Preference over how many times the validator should get slashed for being offline before they are automatically unstaked. + pub SlashPreferenceOf get(slash_preference_of): default map [ T::AccountId => SlashPreference ]; + // All the accounts with a desire to stake. + pub Intentions get(intentions): default Vec; + // All nominator -> nominee relationships. + pub Nominating get(nominating): map [ T::AccountId => T::AccountId ]; + // Nominators for a particular account. + pub NominatorsFor get(nominators_for): default map [ T::AccountId => Vec ]; + // Nominators for a particular account that is in action right now. + pub CurrentNominatorsFor get(current_nominators_for): default map [ T::AccountId => Vec ]; + // The next value of sessions per era. + pub NextSessionsPerEra get(next_sessions_per_era): T::BlockNumber; + // The session index at which the era length last changed. + pub LastEraLengthChange get(last_era_length_change): default T::BlockNumber; + + // The current era stake threshold - unused at present. Consider for removal. + pub StakeThreshold get(stake_threshold): required T::Balance; + + // The number of times a given validator has been reported offline. This gets decremented by one each era that passes. + pub SlashCount get(slash_count): default map [ T::AccountId => u32 ]; + + // We are forcing a new era. + pub ForcingNewEra get(forcing_new_era): (); + } +} + +/// Whatever happened about the hint given when creating the new account. +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[derive(Encode, Decode, PartialEq, Eq, Clone, Copy)] +pub enum NewAccountOutcome { + NoHint, + GoodHint, + BadHint, +} + +/// Outcome of a balance update. +pub enum UpdateBalanceOutcome { + /// Account balance was simply updated. + Updated, + /// The update has led to killing of the account. + AccountKilled, +} + +impl Module { + + // PUBLIC IMMUTABLES + + pub fn minimum_validator_count() -> usize { + >::get().map(|v| v as usize).unwrap_or(DEFAULT_MINIMUM_VALIDATOR_COUNT) + } + + /// The length of a staking era in blocks. + pub fn era_length() -> T::BlockNumber { + Self::sessions_per_era() * >::length() + } + + /// The combined balance of `who`. + pub fn voting_balance(who: &T::AccountId) -> T::Balance { + Self::free_balance(who) + Self::reserved_balance(who) + } + + /// Balance of a (potential) validator that includes all nominators. + pub fn nomination_balance(who: &T::AccountId) -> T::Balance { + Self::nominators_for(who).iter() + .map(Self::voting_balance) + .fold(Zero::zero(), |acc, x| acc + x) + } + + /// The total balance that can be slashed from an account. + pub fn slashable_balance(who: &T::AccountId) -> T::Balance { + Self::nominators_for(who).iter() + .map(Self::voting_balance) + .fold(Self::voting_balance(who), |acc, x| acc + x) + } + + /// Some result as `slash(who, value)` (but without the side-effects) assuming there are no + /// balance changes in the meantime and only the reserved balance is not taken into account. + pub fn can_slash(who: &T::AccountId, value: T::Balance) -> bool { + Self::free_balance(who) >= value + } + + /// Same result as `reserve(who, value)` (but without the side-effects) assuming there + /// are no balance changes in the meantime. + pub fn can_reserve(who: &T::AccountId, value: T::Balance) -> bool { + if let LockStatus::Liquid = Self::unlock_block(who) { + Self::free_balance(who) >= value + } else { + false + } + } + + /// Lookup an T::AccountIndex to get an Id, if there's one there. + pub fn lookup_index(index: T::AccountIndex) -> Option { + let enum_set_size = Self::enum_set_size(); + let set = Self::enum_set(index / enum_set_size); + let i: usize = (index % enum_set_size).as_(); + set.get(i).map(|x| x.clone()) + } + + /// `true` if the account `index` is ready for reclaim. + pub fn can_reclaim(try_index: T::AccountIndex) -> bool { + let enum_set_size = Self::enum_set_size(); + let try_set = Self::enum_set(try_index / enum_set_size); + let i = (try_index % enum_set_size).as_(); + i < try_set.len() && Self::voting_balance(&try_set[i]).is_zero() + } + + /// The block at which the `who`'s funds become entirely liquid. + pub fn unlock_block(who: &T::AccountId) -> LockStatus { + match Self::bondage(who) { + i if i == T::BlockNumber::max_value() => LockStatus::Bonded, + i if i <= >::block_number() => LockStatus::Liquid, + i => LockStatus::LockedUntil(i), + } + } + + /// Lookup an address to get an Id, if there's one there. + pub fn lookup_address(a: address::Address) -> Option { + match a { + address::Address::Id(i) => Some(i), + address::Address::Index(i) => Self::lookup_index(i), + } + } + + // PUBLIC DISPATCH + + /// Transfer some unlocked staking balance to another staker. + pub fn transfer(aux: &T::PublicAux, dest: Address, value: T::Balance) -> Result { + let dest = Self::lookup(dest)?; + + let transactor = aux.ref_into(); + let from_balance = Self::free_balance(transactor); + let would_create = from_balance.is_zero(); + let fee = if would_create { Self::creation_fee() } else { Self::transfer_fee() }; + let liability = value + fee; + + let new_from_balance = match from_balance.checked_sub(&liability) { + Some(b) => b, + None => return Err("balance too low to send value"), + }; + if would_create && value < Self::existential_deposit() { + return Err("value too low to create account"); + } + if >::get(transactor) > >::block_number() { + return Err("bondage too high to send value"); + } + + let to_balance = Self::free_balance(&dest); + let new_to_balance = match to_balance.checked_add(&value) { + Some(b) => b, + None => return Err("destination balance too high to receive value"), + }; + + if transactor != &dest { + Self::set_free_balance(transactor, new_from_balance); + Self::decrease_total_stake_by(fee); + Self::set_free_balance_creating(&dest, new_to_balance); + } + + Ok(()) + } + + /// Declare the desire to stake for the transactor. + /// + /// Effects will be felt at the beginning of the next era. + fn stake(aux: &T::PublicAux) -> Result { + let aux = aux.ref_into(); + ensure!(Self::nominating(aux).is_none(), "Cannot stake if already nominating."); + let mut intentions = >::get(); + // can't be in the list twice. + ensure!(intentions.iter().find(|&t| t == aux).is_none(), "Cannot stake if already staked."); + intentions.push(aux.clone()); + >::put(intentions); + >::insert(aux, T::BlockNumber::max_value()); + Ok(()) + } + + /// Retract the desire to stake for the transactor. + /// + /// Effects will be felt at the beginning of the next era. + fn unstake(aux: &T::PublicAux, intentions_index: u32) -> Result { + // unstake fails in degenerate case of having too few existing staked parties + if Self::intentions().len() <= Self::minimum_validator_count() { + return Err("cannot unstake when there are too few staked participants") + } + Self::apply_unstake(aux.ref_into(), intentions_index as usize) + } + + fn nominate(aux: &T::PublicAux, target: RawAddress) -> Result { + let target = Self::lookup(target)?; + let aux = aux.ref_into(); + + ensure!(Self::nominating(aux).is_none(), "Cannot nominate if already nominating."); + ensure!(Self::intentions().iter().find(|&t| t == aux.ref_into()).is_none(), "Cannot nominate if already staked."); + + // update nominators_for + let mut t = Self::nominators_for(&target); + t.push(aux.clone()); + >::insert(&target, t); + + // update nominating + >::insert(aux, &target); + + // Update bondage + >::insert(aux.ref_into(), T::BlockNumber::max_value()); + + Ok(()) + } + + /// Will panic if called when source isn't currently nominating target. + /// Updates Nominating, NominatorsFor and NominationBalance. + fn unnominate(aux: &T::PublicAux, target_index: u32) -> Result { + let source = aux.ref_into(); + let target_index = target_index as usize; + + let target = >::get(source).ok_or("Account must be nominating")?; + + let mut t = Self::nominators_for(&target); + if t.get(target_index) != Some(source) { + return Err("Invalid target index") + } + + // Ok - all valid. + + // update nominators_for + t.swap_remove(target_index); + >::insert(&target, t); + + // update nominating + >::remove(source); + + // update bondage + >::insert(aux.ref_into(), Self::current_era() + Self::bonding_duration()); + Ok(()) + } + + /// Set the given account's preference for slashing behaviour should they be a validator. + /// + /// An error (no-op) if `Self::intentions()[intentions_index] != aux`. + fn register_slash_preference( + aux: &T::PublicAux, + intentions_index: u32, + p: SlashPreference + ) -> Result { + let aux = aux.ref_into(); + + if Self::intentions().get(intentions_index as usize) != Some(aux) { + return Err("Invalid index") + } + + >::insert(aux, p); + + Ok(()) + } + + /// Note the previous block's validator missed their opportunity to propose a block. This only comes in + /// if 2/3+1 of the validators agree that no proposal was submitted. It's only relevant + /// for the previous block. + fn note_missed_proposal(aux: &T::PublicAux, offline_val_indices: Vec) -> Result { + assert!(aux.is_empty()); + assert!( + >::extrinsic_index() == Some(T::NOTE_MISSED_PROPOSAL_POSITION), + "note_missed_proposal extrinsic must be at position {} in the block", + T::NOTE_MISSED_PROPOSAL_POSITION + ); + + for validator_index in offline_val_indices.into_iter() { + let v = >::validators()[validator_index as usize].clone(); + let slash_count = Self::slash_count(&v); + >::insert(v.clone(), slash_count + 1); + let grace = Self::offline_slash_grace(); + + let event = if slash_count >= grace { + let instances = slash_count - grace; + let slash = Self::early_era_slash() << instances; + let next_slash = slash << 1u32; + let _ = Self::slash_validator(&v, slash); + if instances >= Self::slash_preference_of(&v).unstake_threshold + || Self::slashable_balance(&v) < next_slash + { + if let Some(pos) = Self::intentions().into_iter().position(|x| &x == &v) { + Self::apply_unstake(&v, pos) + .expect("pos derived correctly from Self::intentions(); \ + apply_unstake can only fail if pos wrong; \ + Self::intentions() doesn't change; qed"); + } + let _ = Self::force_new_era(false); + } + RawEvent::OfflineSlash(v, slash) + } else { + RawEvent::OfflineWarning(v, slash_count) + }; + Self::deposit_event(event); + } + + Ok(()) + } + + // PRIV DISPATCH + + /// Deposit one of this module's events. + fn deposit_event(event: Event) { + >::deposit_event(::Event::from(event).into()); + } + + /// Set the number of sessions in an era. + fn set_sessions_per_era(new: T::BlockNumber) -> Result { + >::put(&new); + Ok(()) + } + + /// The length of the bonding duration in eras. + fn set_bonding_duration(new: T::BlockNumber) -> Result { + >::put(&new); + Ok(()) + } + + /// The length of a staking era in sessions. + fn set_validator_count(new: u32) -> Result { + >::put(&new); + Ok(()) + } + + /// Force there to be a new era. This also forces a new session immediately after. + /// `apply_rewards` should be true for validators to get the session reward. + fn force_new_era(apply_rewards: bool) -> Result { + >::put(()); + >::force_new_session(apply_rewards) + } + + /// Set the offline slash grace period. + fn set_offline_slash_grace(new: u32) -> Result { + >::put(&new); + Ok(()) + } + + /// Set the balances of a given account. + fn set_balance(who: Address, free: T::Balance, reserved: T::Balance) -> Result { + let who = Self::lookup(who)?; + Self::set_free_balance(&who, free); + Self::set_reserved_balance(&who, reserved); + Ok(()) + } + + // PUBLIC MUTABLES (DANGEROUS) + + /// Set the free balance of an account to some new value. + /// + /// Will enforce ExistentialDeposit law, anulling the account as needed. + /// In that case it will return `AccountKilled`. + pub fn set_reserved_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { + if balance < Self::existential_deposit() { + >::insert(who, balance); + Self::on_reserved_too_low(who); + UpdateBalanceOutcome::AccountKilled + } else { + >::insert(who, balance); + UpdateBalanceOutcome::Updated + } + } + + /// Set the free balance of an account to some new value. Will enforce ExistentialDeposit + /// law anulling the account as needed. + /// + /// Doesn't do any preparatory work for creating a new account, so should only be used when it + /// is known that the account already exists. + /// + /// Returns if the account was successfully updated or update has led to killing of the account. + pub fn set_free_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { + // Commented out for no - but consider it instructive. + // assert!(!Self::voting_balance(who).is_zero()); + if balance < Self::existential_deposit() { + >::insert(who, balance); + Self::on_free_too_low(who); + UpdateBalanceOutcome::AccountKilled + } else { + >::insert(who, balance); + UpdateBalanceOutcome::Updated + } + } + + /// Set the free balance on an account to some new value. + /// + /// Same as [`set_free_balance`], but will create a new account. + /// + /// Returns if the account was successfully updated or update has led to killing of the account. + /// + /// [`set_free_balance`]: #method.set_free_balance + pub fn set_free_balance_creating(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { + let ed = >::existential_deposit(); + // If the balance is too low, then the account is reaped. + // NOTE: There are two balances for every account: `reserved_balance` and + // `free_balance`. This contract subsystem only cares about the latter: whenever + // the term "balance" is used *here* it should be assumed to mean "free balance" + // in the rest of the module. + // Free balance can never be less than ED. If that happens, it gets reduced to zero + // and the account information relevant to this subsystem is deleted (i.e. the + // account is reaped). + // NOTE: This is orthogonal to the `Bondage` value that an account has, a high + // value of which makes even the `free_balance` unspendable. + // TODO: enforce this for the other balance-altering functions. + if balance < ed { + Self::set_free_balance(who, balance); + UpdateBalanceOutcome::AccountKilled + } else { + if !>::exists(who) { + let outcome = Self::new_account(&who, balance); + let credit = match outcome { + NewAccountOutcome::GoodHint => balance + >::reclaim_rebate(), + _ => balance, + }; + Self::set_free_balance(who, credit); + Self::increase_total_stake_by(credit - balance); + } else { + Self::set_free_balance(who, balance); + } + + UpdateBalanceOutcome::Updated + } + } + + /// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the + /// free balance. This function cannot fail. + /// + /// As much funds up to `value` will be deducted as possible. If this is less than `value`, + /// then `Some(remaining)` will be returned. Full completion is given by `None`. + pub fn slash(who: &T::AccountId, value: T::Balance) -> Option { + let free_balance = Self::free_balance(who); + let free_slash = cmp::min(free_balance, value); + Self::set_free_balance(who, free_balance - free_slash); + Self::decrease_total_stake_by(free_slash); + if free_slash < value { + Self::slash_reserved(who, value - free_slash) + } else { + None + } + } + + /// Adds up to `value` to the free balance of `who`. + /// + /// If `who` doesn't exist, nothing is done and an Err returned. + pub fn reward(who: &T::AccountId, value: T::Balance) -> Result { + if Self::voting_balance(who).is_zero() { + return Err("beneficiary account must pre-exist"); + } + Self::set_free_balance(who, Self::free_balance(who) + value); + Self::increase_total_stake_by(value); + Ok(()) + } + + /// Moves `value` from balance to reserved balance. + /// + /// If the free balance is lower than `value`, then no funds will be moved and an `Err` will + /// be returned to notify of this. This is different behaviour to `unreserve`. + pub fn reserve(who: &T::AccountId, value: T::Balance) -> Result { + let b = Self::free_balance(who); + if b < value { + return Err("not enough free funds") + } + if Self::unlock_block(who) != LockStatus::Liquid { + return Err("free funds are still bonded") + } + Self::set_reserved_balance(who, Self::reserved_balance(who) + value); + Self::set_free_balance(who, b - value); + Ok(()) + } + + /// Moves up to `value` from reserved balance to balance. This function cannot fail. + /// + /// As much funds up to `value` will be deducted as possible. If this is less than `value`, + /// then `Some(remaining)` will be returned. Full completion is given by `None`. + /// NOTE: This is different to `reserve`. + pub fn unreserve(who: &T::AccountId, value: T::Balance) -> Option { + let b = Self::reserved_balance(who); + let actual = cmp::min(b, value); + Self::set_free_balance(who, Self::free_balance(who) + actual); + Self::set_reserved_balance(who, b - actual); + if actual == value { + None + } else { + Some(value - actual) + } + } + + /// Deducts up to `value` from reserved balance of `who`. This function cannot fail. + /// + /// As much funds up to `value` will be deducted as possible. If this is less than `value`, + /// then `Some(remaining)` will be returned. Full completion is given by `None`. + pub fn slash_reserved(who: &T::AccountId, value: T::Balance) -> Option { + let b = Self::reserved_balance(who); + let slash = cmp::min(b, value); + Self::set_reserved_balance(who, b - slash); + Self::decrease_total_stake_by(slash); + if value == slash { + None + } else { + Some(value - slash) + } + } + + /// Moves up to `value` from reserved balance of account `slashed` to free balance of account + /// `beneficiary`. `beneficiary` must exist for this to succeed. If it does not, `Err` will be + /// returned. + /// + /// As much funds up to `value` will be moved as possible. If this is less than `value`, then + /// `Ok(Some(remaining))` will be returned. Full completion is given by `Ok(None)`. + pub fn transfer_reserved( + slashed: &T::AccountId, + beneficiary: &T::AccountId, + value: T::Balance + ) -> result::Result, &'static str> { + if Self::voting_balance(beneficiary).is_zero() { + return Err("beneficiary account must pre-exist"); + } + let b = Self::reserved_balance(slashed); + let slash = cmp::min(b, value); + Self::set_free_balance(beneficiary, Self::free_balance(beneficiary) + slash); + Self::set_reserved_balance(slashed, b - slash); + if value == slash { + Ok(None) + } else { + Ok(Some(value - slash)) + } + } + + /// Slash a given validator by a specific amount. Removes the slash from their balance by preference, + /// and reduces the nominators' balance if needed. + fn slash_validator(v: &T::AccountId, slash: T::Balance) { + // skip the slash in degenerate case of having only 4 staking participants despite having a larger + // desired number of validators (validator_count). + if Self::intentions().len() <= Self::minimum_validator_count() { + return + } + + if let Some(rem) = Self::slash(v, slash) { + let noms = Self::current_nominators_for(v); + let total = noms.iter().map(Self::voting_balance).fold(T::Balance::zero(), |acc, x| acc + x); + if !total.is_zero() { + let safe_mul_rational = |b| b * rem / total;// TODO: avoid overflow + for n in noms.iter() { + let _ = Self::slash(n, safe_mul_rational(Self::voting_balance(n))); // best effort - not much that can be done on fail. + } + } + } + } + + /// Reward a given validator by a specific amount. Add the reward to their, and their nominators' + /// balance, pro-rata. + fn reward_validator(who: &T::AccountId, reward: T::Balance) { + let noms = Self::current_nominators_for(who); + let total = noms.iter().map(Self::voting_balance).fold(Self::voting_balance(who), |acc, x| acc + x); + if !total.is_zero() { + let safe_mul_rational = |b| b * reward / total;// TODO: avoid overflow + for n in noms.iter() { + let _ = Self::reward(n, safe_mul_rational(Self::voting_balance(n))); + } + let _ = Self::reward(who, safe_mul_rational(Self::voting_balance(who))); + } + } + + /// Actually carry out the unstake operation. + /// Assumes `intentions()[intentions_index] == who`. + fn apply_unstake(who: &T::AccountId, intentions_index: usize) -> Result { + let mut intentions = Self::intentions(); + if intentions.get(intentions_index) != Some(who) { + return Err("Invalid index"); + } + intentions.swap_remove(intentions_index); + >::put(intentions); + >::remove(who); + >::remove(who); + >::insert(who, Self::current_era() + Self::bonding_duration()); + Ok(()) + } + + /// Get the reward for the session, assuming it ends with this block. + fn this_session_reward(actual_elapsed: T::Moment) -> T::Balance { + let ideal_elapsed = >::ideal_session_duration(); + let per65536: u64 = (T::Moment::sa(65536u64) * ideal_elapsed.clone() / actual_elapsed.max(ideal_elapsed)).as_(); + Self::session_reward() * T::Balance::sa(per65536) / T::Balance::sa(65536u64) + } + + /// Session has just changed. We need to determine whether we pay a reward, slash and/or + /// move to a new era. + fn new_session(actual_elapsed: T::Moment, should_reward: bool) { + if should_reward { + // apply good session reward + let reward = Self::this_session_reward(actual_elapsed); + for v in >::validators().iter() { + Self::reward_validator(v, reward); + } + Self::deposit_event(RawEvent::Reward(reward)); + } + + let session_index = >::current_index(); + if >::take().is_some() + || ((session_index - Self::last_era_length_change()) % Self::sessions_per_era()).is_zero() + { + Self::new_era(); + } + } + + /// The era has changed - enact new staking set. + /// + /// NOTE: This always happens immediately before a session change to ensure that new validators + /// get a chance to set their session keys. + fn new_era() { + // Increment current era. + >::put(&(>::get() + One::one())); + + // Enact era length change. + if let Some(next_spe) = Self::next_sessions_per_era() { + if next_spe != Self::sessions_per_era() { + >::put(&next_spe); + >::put(&>::current_index()); + } + } + + // evaluate desired staking amounts and nominations and optimise to find the best + // combination of validators, then use session::internal::set_validators(). + // for now, this just orders would-be stakers by their balances and chooses the top-most + // >::get() of them. + // TODO: this is not sound. this should be moved to an off-chain solution mechanism. + let mut intentions = Self::intentions() + .into_iter() + .map(|v| (Self::slashable_balance(&v), v)) + .collect::>(); + + // Avoid reevaluate validator set if it would leave us with fewer than the minimum + // needed validators + if intentions.len() < Self::minimum_validator_count() { + return + } + + intentions.sort_unstable_by(|&(ref b1, _), &(ref b2, _)| b2.cmp(&b1)); + + >::put( + if !intentions.is_empty() { + let i = (>::get() as usize).min(intentions.len() - 1); + intentions[i].0.clone() + } else { Zero::zero() } + ); + let vals = &intentions.into_iter() + .map(|(_, v)| v) + .take(>::get() as usize) + .collect::>(); + for v in >::validators().iter() { + >::remove(v); + let slash_count = >::take(v); + if slash_count > 1 { + >::insert(v, slash_count - 1); + } + } + for v in vals.iter() { + >::insert(v, Self::nominators_for(v)); + } + >::set_validators(vals); + } + + fn enum_set_size() -> T::AccountIndex { + T::AccountIndex::sa(ENUM_SET_SIZE) + } + + /// Register a new account (with existential balance). + fn new_account(who: &T::AccountId, balance: T::Balance) -> NewAccountOutcome { + let enum_set_size = Self::enum_set_size(); + let next_set_index = Self::next_enum_set(); + let reclaim_index_magic = T::AccountIndex::sa(RECLAIM_INDEX_MAGIC); + let reclaim_index_modulus = T::AccountIndex::sa(256usize); + let quantization = T::AccountIndex::sa(256usize); + + // A little easter-egg for reclaiming dead indexes.. + let ret = { + // we quantise the number of accounts so it stays constant over a reasonable + // period of time. + let quantized_account_count: T::AccountIndex = (next_set_index * enum_set_size / quantization + One::one()) * quantization; + // then modify the starting balance to be modulo this to allow it to potentially + // identify an account index for reuse. + let maybe_try_index = balance % >::sa(quantized_account_count * reclaim_index_modulus); + let maybe_try_index = As::::as_(maybe_try_index); + + // this identifier must end with magic byte 0x69 to trigger this check (a minor + // optimisation to ensure we don't check most unintended account creations). + if maybe_try_index % reclaim_index_modulus == reclaim_index_magic { + // reuse is probably intended. first, remove magic byte. + let try_index = maybe_try_index / reclaim_index_modulus; + + // then check to see if this balance identifies a dead account index. + let set_index = try_index / enum_set_size; + let mut try_set = Self::enum_set(set_index); + let item_index = (try_index % enum_set_size).as_(); + if item_index < try_set.len() { + if Self::voting_balance(&try_set[item_index]).is_zero() { + // yup - this index refers to a dead account. can be reused. + try_set[item_index] = who.clone(); + >::insert(set_index, try_set); + + Self::deposit_event(RawEvent::NewAccount(who.clone(), try_index, NewAccountOutcome::GoodHint)); + + return NewAccountOutcome::GoodHint + } + } + NewAccountOutcome::BadHint + } else { + NewAccountOutcome::NoHint + } + }; + + // insert normally as a back up + let mut set_index = next_set_index; + // defensive only: this loop should never iterate since we keep NextEnumSet up to date later. + let mut set = loop { + let set = Self::enum_set(set_index); + if set.len() < ENUM_SET_SIZE { + break set; + } + set_index += One::one(); + }; + + let index = T::AccountIndex::sa(set_index.as_() * ENUM_SET_SIZE + set.len()); + + // update set. + set.push(who.clone()); + + // keep NextEnumSet up to date + if set.len() == ENUM_SET_SIZE { + >::put(set_index + One::one()); + } + + // write set. + >::insert(set_index, set); + + Self::deposit_event(RawEvent::NewAccount(who.clone(), index, ret)); + + ret + } + + fn reap_account(who: &T::AccountId) { + >::remove(who); + Self::deposit_event(RawEvent::ReapedAccount(who.clone())); + } + + /// Kill an account's free portion. + fn on_free_too_low(who: &T::AccountId) { + Self::decrease_total_stake_by(Self::free_balance(who)); + >::remove(who); + >::remove(who); + + T::OnFreeBalanceZero::on_free_balance_zero(who); + + if Self::reserved_balance(who).is_zero() { + Self::reap_account(who); + } + } + + /// Kill an account's reserved portion. + fn on_reserved_too_low(who: &T::AccountId) { + Self::decrease_total_stake_by(Self::reserved_balance(who)); + >::remove(who); + + if Self::free_balance(who).is_zero() { + Self::reap_account(who); + } + } + + /// Increase TotalStake by Value. + pub fn increase_total_stake_by(value: T::Balance) { + if let Some(v) = >::total_stake().checked_add(&value) { + >::put(v); + } + } + /// Decrease TotalStake by Value. + pub fn decrease_total_stake_by(value: T::Balance) { + if let Some(v) = >::total_stake().checked_sub(&value) { + >::put(v); + } + } +} + +impl Executable for Module { + fn execute() { + } +} + +impl OnSessionChange for Module { + fn on_session_change(elapsed: T::Moment, should_reward: bool) { + Self::new_session(elapsed, should_reward); + } +} + +impl AuxLookup for Module { + type Source = address::Address; + type Target = T::AccountId; + fn lookup(a: Self::Source) -> result::Result { + match a { + address::Address::Id(i) => Ok(i), + address::Address::Index(i) => >::lookup_index(i).ok_or("invalid account index"), + } + } +} + +impl MakePayment for Module { + fn make_payment(transactor: &T::AccountId, encoded_len: usize) -> Result { + let b = Self::free_balance(transactor); + let transaction_fee = Self::transaction_base_fee() + Self::transaction_byte_fee() * >::sa(encoded_len as u64); + if b < transaction_fee + Self::existential_deposit() { + return Err("not enough funds for transaction fee"); + } + Self::set_free_balance(transactor, b - transaction_fee); + Self::decrease_total_stake_by(transaction_fee); + Ok(()) + } +} diff --git a/substrate/runtime/balances/src/mock.rs b/substrate/runtime/balances/src/mock.rs new file mode 100644 index 0000000000000..7b3097010d7eb --- /dev/null +++ b/substrate/runtime/balances/src/mock.rs @@ -0,0 +1,115 @@ +// Copyright 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 . + +//! Test utilities + +#![cfg(test)] + +use primitives::BuildStorage; +use primitives::traits::{HasPublicAux, Identity}; +use primitives::testing::{Digest, Header}; +use substrate_primitives::{H256, KeccakHasher}; +use runtime_io; +use {GenesisConfig, Module, Trait, consensus, session, system, timestamp}; + +// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. +#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] +pub struct Test; +impl HasPublicAux for Test { + type PublicAux = u64; +} +impl consensus::Trait for Test { + type PublicAux = ::PublicAux; + type SessionKey = u64; +} +impl system::Trait for Test { + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = ::primitives::traits::BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Header = Header; + type Event = (); +} +impl session::Trait for Test { + type ConvertAccountIdToSessionKey = Identity; + type OnSessionChange = Staking; + type Event = (); +} +impl timestamp::Trait for Test { + const TIMESTAMP_SET_POSITION: u32 = 0; + type Moment = u64; +} +impl Trait for Test { + const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1; + type Balance = u64; + type AccountIndex = u64; + type OnFreeBalanceZero = (); + type Event = (); +} + +pub fn new_test_ext(ext_deposit: u64, session_length: u64, sessions_per_era: u64, current_era: u64, monied: bool, reward: u64) -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::::default().build_storage().unwrap(); + let balance_factor = if ext_deposit > 0 { + 256 + } else { + 1 + }; + t.extend(consensus::GenesisConfig::{ + code: vec![], + authorities: vec![], + }.build_storage().unwrap()); + t.extend(session::GenesisConfig::{ + session_length, + validators: vec![10, 20], + }.build_storage().unwrap()); + t.extend(GenesisConfig::{ + sessions_per_era, + current_era, + balances: if monied { + if reward > 0 { + vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor), (10, balance_factor), (20, balance_factor)] + } else { + vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor)] + } + } else { + vec![(10, balance_factor), (20, balance_factor)] + }, + intentions: vec![10, 20], + validator_count: 2, + minimum_validator_count: 0, + bonding_duration: 3, + transaction_base_fee: 0, + transaction_byte_fee: 0, + existential_deposit: ext_deposit, + transfer_fee: 0, + creation_fee: 0, + reclaim_rebate: 0, + session_reward: reward, + early_era_slash: if monied { 20 } else { 0 }, + offline_slash_grace: 0, + }.build_storage().unwrap()); + t.extend(timestamp::GenesisConfig::{ + period: 5 + }.build_storage().unwrap()); + t.into() +} + +pub type System = system::Module; +pub type Session = session::Module; +pub type Timestamp = timestamp::Module; +pub type Staking = Module; diff --git a/substrate/runtime/balances/src/tests.rs b/substrate/runtime/balances/src/tests.rs new file mode 100644 index 0000000000000..809838379ae12 --- /dev/null +++ b/substrate/runtime/balances/src/tests.rs @@ -0,0 +1,770 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo 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 Demo 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 Demo. If not, see . + +//! Tests for the module. + +#![cfg(test)] + +use super::*; +use runtime_io::with_externalities; +use mock::{Session, Staking, System, Timestamp, Test, new_test_ext}; + +#[test] +fn note_null_missed_proposal_should_work() { + with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { + assert_eq!(Staking::offline_slash_grace(), 0); + assert_eq!(Staking::slash_count(&10), 0); + assert_eq!(Staking::free_balance(&10), 1); + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![])); + assert_eq!(Staking::slash_count(&10), 0); + assert_eq!(Staking::free_balance(&10), 1); + assert!(Staking::forcing_new_era().is_none()); + }); +} + +#[test] +fn note_missed_proposal_should_work() { + with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { + Staking::set_free_balance(&10, 70); + assert_eq!(Staking::offline_slash_grace(), 0); + assert_eq!(Staking::slash_count(&10), 0); + assert_eq!(Staking::free_balance(&10), 70); + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); + assert_eq!(Staking::slash_count(&10), 1); + assert_eq!(Staking::free_balance(&10), 50); + assert!(Staking::forcing_new_era().is_none()); + }); +} + +#[test] +fn note_missed_proposal_exponent_should_work() { + with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { + Staking::set_free_balance(&10, 150); + assert_eq!(Staking::offline_slash_grace(), 0); + assert_eq!(Staking::slash_count(&10), 0); + assert_eq!(Staking::free_balance(&10), 150); + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); + assert_eq!(Staking::slash_count(&10), 1); + assert_eq!(Staking::free_balance(&10), 130); + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); + assert_eq!(Staking::slash_count(&10), 2); + assert_eq!(Staking::free_balance(&10), 90); + assert!(Staking::forcing_new_era().is_none()); + }); +} + +#[test] +fn note_missed_proposal_grace_should_work() { + with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { + Staking::set_free_balance(&10, 70); + Staking::set_free_balance(&20, 70); + assert_ok!(Staking::set_offline_slash_grace(1)); + assert_eq!(Staking::offline_slash_grace(), 1); + + assert_eq!(Staking::slash_count(&10), 0); + assert_eq!(Staking::free_balance(&10), 70); + + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); + assert_eq!(Staking::slash_count(&10), 1); + assert_eq!(Staking::free_balance(&10), 70); + assert_eq!(Staking::slash_count(&20), 0); + assert_eq!(Staking::free_balance(&20), 70); + + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); + assert_eq!(Staking::slash_count(&10), 2); + assert_eq!(Staking::free_balance(&10), 50); + assert_eq!(Staking::slash_count(&20), 1); + assert_eq!(Staking::free_balance(&20), 70); + assert!(Staking::forcing_new_era().is_none()); + }); +} + +#[test] +fn note_missed_proposal_force_unstake_session_change_should_work() { + with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { + Staking::set_free_balance(&10, 70); + Staking::set_free_balance(&20, 70); + assert_ok!(Staking::stake(&1)); + + assert_eq!(Staking::slash_count(&10), 0); + assert_eq!(Staking::free_balance(&10), 70); + assert_eq!(Staking::intentions(), vec![10, 20, 1]); + assert_eq!(Session::validators(), vec![10, 20]); + + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); + assert_eq!(Staking::free_balance(&10), 50); + assert_eq!(Staking::slash_count(&10), 1); + assert_eq!(Staking::intentions(), vec![10, 20, 1]); + + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); + assert_eq!(Staking::intentions(), vec![1, 20]); + assert_eq!(Staking::free_balance(&10), 10); + assert!(Staking::forcing_new_era().is_some()); + }); +} + +#[test] +fn note_missed_proposal_auto_unstake_session_change_should_work() { + with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { + Staking::set_free_balance(&10, 7000); + Staking::set_free_balance(&20, 7000); + assert_ok!(Staking::register_slash_preference(&10, 0, SlashPreference { unstake_threshold: 1 })); + + assert_eq!(Staking::intentions(), vec![10, 20]); + + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); + assert_eq!(Staking::free_balance(&10), 6980); + assert_eq!(Staking::free_balance(&20), 6980); + assert_eq!(Staking::intentions(), vec![10, 20]); + assert!(Staking::forcing_new_era().is_none()); + + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); + assert_eq!(Staking::free_balance(&10), 6940); + assert_eq!(Staking::free_balance(&20), 6940); + assert_eq!(Staking::intentions(), vec![20]); + assert!(Staking::forcing_new_era().is_some()); + + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![1])); + assert_eq!(Staking::free_balance(&10), 6940); + assert_eq!(Staking::free_balance(&20), 6860); + assert_eq!(Staking::intentions(), vec![20]); + + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![1])); + assert_eq!(Staking::free_balance(&10), 6940); + assert_eq!(Staking::free_balance(&20), 6700); + assert_eq!(Staking::intentions(), vec![0u64; 0]); + }); +} + +#[test] +fn reward_should_work() { + with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { + assert_eq!(Staking::voting_balance(&10), 1); + assert_ok!(Staking::reward(&10, 10)); + assert_eq!(Staking::voting_balance(&10), 11); + assert_eq!(>::get(), 112); + }); +} + +#[test] +fn rewards_should_work() { + with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { + assert_eq!(Staking::era_length(), 9); + assert_eq!(Staking::sessions_per_era(), 3); + assert_eq!(Staking::last_era_length_change(), 0); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 0); + assert_eq!(Staking::voting_balance(&10), 1); + + System::set_block_number(3); + Timestamp::set_timestamp(15); // on time. + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 1); + assert_eq!(Staking::voting_balance(&10), 11); + System::set_block_number(6); + Timestamp::set_timestamp(31); // a little late + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 2); + assert_eq!(Staking::voting_balance(&10), 20); // less reward + System::set_block_number(9); + Timestamp::set_timestamp(50); // very late + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 1); + assert_eq!(Session::current_index(), 3); + assert_eq!(Staking::voting_balance(&10), 27); // much less reward + }); +} + +#[test] +fn slashing_should_work() { + with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { + assert_eq!(Staking::era_length(), 9); + assert_eq!(Staking::sessions_per_era(), 3); + assert_eq!(Staking::last_era_length_change(), 0); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 0); + assert_eq!(Staking::voting_balance(&10), 1); + + System::set_block_number(3); + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 1); + assert_eq!(Staking::voting_balance(&10), 11); + + System::set_block_number(6); + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 2); + assert_eq!(Staking::voting_balance(&10), 21); + + System::set_block_number(7); + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); + assert_eq!(Staking::voting_balance(&10), 1); + }); +} + +#[test] +fn indexing_lookup_should_work() { + with_externalities(&mut new_test_ext(10, 1, 2, 0, true, 0), || { + assert_eq!(Staking::lookup_index(0), Some(1)); + assert_eq!(Staking::lookup_index(1), Some(2)); + assert_eq!(Staking::lookup_index(2), Some(3)); + assert_eq!(Staking::lookup_index(3), Some(4)); + assert_eq!(Staking::lookup_index(4), None); + }); +} + +#[test] +fn default_indexing_on_new_accounts_should_work() { + with_externalities(&mut new_test_ext(10, 1, 2, 0, true, 0), || { + assert_eq!(Staking::lookup_index(4), None); + assert_ok!(Staking::transfer(&1, 5.into(), 10)); + assert_eq!(Staking::lookup_index(4), Some(5)); + }); +} + +#[test] +fn dust_account_removal_should_work() { + with_externalities(&mut new_test_ext(256 * 10, 1, 2, 0, true, 0), || { + System::inc_account_nonce(&2); + assert_eq!(System::account_nonce(&2), 1); + assert_eq!(Staking::voting_balance(&2), 256 * 20); + + assert_ok!(Staking::transfer(&2, 5.into(), 256 * 10 + 1)); // index 1 (account 2) becomes zombie + assert_eq!(Staking::voting_balance(&2), 0); + assert_eq!(Staking::voting_balance(&5), 256 * 10 + 1); + assert_eq!(System::account_nonce(&2), 0); + }); +} + +#[test] +fn reclaim_indexing_on_new_accounts_should_work() { + with_externalities(&mut new_test_ext(256 * 1, 1, 2, 0, true, 0), || { + assert_eq!(Staking::lookup_index(1), Some(2)); + assert_eq!(Staking::lookup_index(4), None); + assert_eq!(Staking::voting_balance(&2), 256 * 20); + + assert_ok!(Staking::transfer(&2, 5.into(), 256 * 20)); // account 2 becomes zombie freeing index 1 for reclaim) + assert_eq!(Staking::voting_balance(&2), 0); + + assert_ok!(Staking::transfer(&5, 6.into(), 256 * 1 + 0x69)); // account 6 takes index 1. + assert_eq!(Staking::voting_balance(&6), 256 * 1 + 0x69); + assert_eq!(Staking::lookup_index(1), Some(6)); + }); +} + +#[test] +fn reserved_balance_should_prevent_reclaim_count() { + with_externalities(&mut new_test_ext(256 * 1, 1, 2, 0, true, 0), || { + System::inc_account_nonce(&2); + assert_eq!(Staking::lookup_index(1), Some(2)); + assert_eq!(Staking::lookup_index(4), None); + assert_eq!(Staking::voting_balance(&2), 256 * 20); + + assert_ok!(Staking::reserve(&2, 256 * 19 + 1)); // account 2 becomes mostly reserved + assert_eq!(Staking::free_balance(&2), 0); // "free" account deleted." + assert_eq!(Staking::voting_balance(&2), 256 * 19 + 1); // reserve still exists. + assert_eq!(System::account_nonce(&2), 1); + + assert_ok!(Staking::transfer(&4, 5.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 for account 5. + assert_eq!(Staking::voting_balance(&5), 256 * 1 + 0x69); + assert_eq!(Staking::lookup_index(1), Some(2)); // but fails. + assert_eq!(System::account_nonce(&2), 1); + + assert_eq!(Staking::slash(&2, 256 * 18 + 2), None); // account 2 gets slashed + assert_eq!(Staking::voting_balance(&2), 0); // "free" account deleted." + assert_eq!(System::account_nonce(&2), 0); + + assert_ok!(Staking::transfer(&4, 6.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 again for account 6. + assert_eq!(Staking::voting_balance(&6), 256 * 1 + 0x69); + assert_eq!(Staking::lookup_index(1), Some(6)); // and succeeds. + }); +} + +#[test] +fn staking_should_work() { + with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { + assert_eq!(Staking::era_length(), 2); + assert_eq!(Staking::validator_count(), 2); + assert_eq!(Staking::bonding_duration(), 3); + assert_eq!(Session::validators(), vec![10, 20]); + + // Block 1: Add three validators. No obvious change. + System::set_block_number(1); + assert_ok!(Staking::stake(&1)); + assert_ok!(Staking::stake(&2)); + assert_ok!(Staking::stake(&4)); + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::validators(), vec![10, 20]); + + // Block 2: New validator set now. + System::set_block_number(2); + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 1); + assert_eq!(Session::validators(), vec![4, 2]); + + // Block 3: Unstake highest, introduce another staker. No change yet. + System::set_block_number(3); + assert_ok!(Staking::stake(&3)); + assert_ok!(Staking::unstake(&4, Staking::intentions().iter().position(|&x| x == 4).unwrap() as u32)); + assert_eq!(Staking::current_era(), 1); + Session::check_rotate_session(); + + // Block 4: New era - validators change. + System::set_block_number(4); + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 2); + assert_eq!(Session::validators(), vec![3, 2]); + + // Block 5: Transfer stake from highest to lowest. No change yet. + System::set_block_number(5); + assert_ok!(Staking::transfer(&4, 1.into(), 40)); + Session::check_rotate_session(); + + // Block 6: Lowest now validator. + System::set_block_number(6); + Session::check_rotate_session(); + assert_eq!(Session::validators(), vec![1, 3]); + + // Block 7: Unstake three. No change yet. + System::set_block_number(7); + assert_ok!(Staking::unstake(&3, Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32)); + Session::check_rotate_session(); + assert_eq!(Session::validators(), vec![1, 3]); + + // Block 8: Back to one and two. + System::set_block_number(8); + Session::check_rotate_session(); + assert_eq!(Session::validators(), vec![1, 2]); + }); +} + +#[test] +fn nominating_and_rewards_should_work() { + with_externalities(&mut new_test_ext(0, 1, 1, 0, true, 10), || { + assert_eq!(Staking::era_length(), 1); + assert_eq!(Staking::validator_count(), 2); + assert_eq!(Staking::bonding_duration(), 3); + assert_eq!(Session::validators(), vec![10, 20]); + + System::set_block_number(1); + assert_ok!(Staking::stake(&1)); + assert_ok!(Staking::stake(&2)); + assert_ok!(Staking::stake(&3)); + assert_ok!(Staking::nominate(&4, 1.into())); + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 1); + assert_eq!(Session::validators(), vec![1, 3]); // 4 + 1, 3 + assert_eq!(Staking::voting_balance(&1), 10); + assert_eq!(Staking::voting_balance(&2), 20); + assert_eq!(Staking::voting_balance(&3), 30); + assert_eq!(Staking::voting_balance(&4), 40); + + System::set_block_number(2); + assert_ok!(Staking::unnominate(&4, 0)); + Session::check_rotate_session(); + assert_eq!(Staking::current_era(), 2); + assert_eq!(Session::validators(), vec![3, 2]); + assert_eq!(Staking::voting_balance(&1), 12); + assert_eq!(Staking::voting_balance(&2), 20); + assert_eq!(Staking::voting_balance(&3), 40); + assert_eq!(Staking::voting_balance(&4), 48); + + System::set_block_number(3); + assert_ok!(Staking::stake(&4)); + assert_ok!(Staking::unstake(&3, Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32)); + assert_ok!(Staking::nominate(&3, 1.into())); + Session::check_rotate_session(); + assert_eq!(Session::validators(), vec![1, 4]); + assert_eq!(Staking::voting_balance(&1), 12); + assert_eq!(Staking::voting_balance(&2), 30); + assert_eq!(Staking::voting_balance(&3), 50); + assert_eq!(Staking::voting_balance(&4), 48); + + System::set_block_number(4); + Session::check_rotate_session(); + assert_eq!(Staking::voting_balance(&1), 13); + assert_eq!(Staking::voting_balance(&2), 30); + assert_eq!(Staking::voting_balance(&3), 58); + assert_eq!(Staking::voting_balance(&4), 58); + }); +} + +#[test] +fn nominating_slashes_should_work() { + with_externalities(&mut new_test_ext(0, 2, 2, 0, true, 10), || { + assert_eq!(Staking::era_length(), 4); + assert_eq!(Staking::validator_count(), 2); + assert_eq!(Staking::bonding_duration(), 3); + assert_eq!(Session::validators(), vec![10, 20]); + + System::set_block_number(2); + Session::check_rotate_session(); + + Timestamp::set_timestamp(15); + System::set_block_number(4); + assert_ok!(Staking::stake(&1)); + assert_ok!(Staking::stake(&3)); + assert_ok!(Staking::nominate(&2, 3.into())); + assert_ok!(Staking::nominate(&4, 1.into())); + Session::check_rotate_session(); + + assert_eq!(Staking::current_era(), 1); + assert_eq!(Session::validators(), vec![1, 3]); // 1 + 4, 3 + 2 + assert_eq!(Staking::voting_balance(&1), 10); + assert_eq!(Staking::voting_balance(&2), 20); + assert_eq!(Staking::voting_balance(&3), 30); + assert_eq!(Staking::voting_balance(&4), 40); + + System::set_block_number(5); + ::system::ExtrinsicIndex::::put(1); + assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); + assert_eq!(Staking::voting_balance(&1), 0); + assert_eq!(Staking::voting_balance(&2), 20); + assert_eq!(Staking::voting_balance(&3), 10); + assert_eq!(Staking::voting_balance(&4), 30); + }); +} + +#[test] +fn double_staking_should_fail() { + with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { + System::set_block_number(1); + assert_ok!(Staking::stake(&1)); + assert_noop!(Staking::stake(&1), "Cannot stake if already staked."); + assert_noop!(Staking::nominate(&1, 1.into()), "Cannot nominate if already staked."); + assert_ok!(Staking::nominate(&2, 1.into())); + assert_noop!(Staking::stake(&2), "Cannot stake if already nominating."); + assert_noop!(Staking::nominate(&2, 1.into()), "Cannot nominate if already nominating."); + }); +} + +#[test] +fn staking_eras_work() { + with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { + assert_eq!(Staking::era_length(), 2); + assert_eq!(Staking::sessions_per_era(), 2); + assert_eq!(Staking::last_era_length_change(), 0); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 0); + + // Block 1: No change. + System::set_block_number(1); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 1); + assert_eq!(Staking::sessions_per_era(), 2); + assert_eq!(Staking::last_era_length_change(), 0); + assert_eq!(Staking::current_era(), 0); + + // Block 2: Simple era change. + System::set_block_number(2); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 2); + assert_eq!(Staking::sessions_per_era(), 2); + assert_eq!(Staking::last_era_length_change(), 0); + assert_eq!(Staking::current_era(), 1); + + // Block 3: Schedule an era length change; no visible changes. + System::set_block_number(3); + assert_ok!(Staking::set_sessions_per_era(3)); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 3); + assert_eq!(Staking::sessions_per_era(), 2); + assert_eq!(Staking::last_era_length_change(), 0); + assert_eq!(Staking::current_era(), 1); + + // Block 4: Era change kicks in. + System::set_block_number(4); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 4); + assert_eq!(Staking::sessions_per_era(), 3); + assert_eq!(Staking::last_era_length_change(), 4); + assert_eq!(Staking::current_era(), 2); + + // Block 5: No change. + System::set_block_number(5); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 5); + assert_eq!(Staking::sessions_per_era(), 3); + assert_eq!(Staking::last_era_length_change(), 4); + assert_eq!(Staking::current_era(), 2); + + // Block 6: No change. + System::set_block_number(6); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 6); + assert_eq!(Staking::sessions_per_era(), 3); + assert_eq!(Staking::last_era_length_change(), 4); + assert_eq!(Staking::current_era(), 2); + + // Block 7: Era increment. + System::set_block_number(7); + Session::check_rotate_session(); + assert_eq!(Session::current_index(), 7); + assert_eq!(Staking::sessions_per_era(), 3); + assert_eq!(Staking::last_era_length_change(), 4); + assert_eq!(Staking::current_era(), 3); + }); +} + +#[test] +fn staking_balance_works() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 42); + assert_eq!(Staking::free_balance(&1), 42); + assert_eq!(Staking::reserved_balance(&1), 0); + assert_eq!(Staking::voting_balance(&1), 42); + assert_eq!(Staking::free_balance(&2), 0); + assert_eq!(Staking::reserved_balance(&2), 0); + assert_eq!(Staking::voting_balance(&2), 0); + }); +} + +#[test] +fn staking_balance_transfer_works() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 111); + Staking::increase_total_stake_by(111); + assert_ok!(Staking::transfer(&1, 2.into(), 69)); + assert_eq!(Staking::voting_balance(&1), 42); + assert_eq!(Staking::voting_balance(&2), 69); + }); +} + +#[test] +fn staking_balance_transfer_when_bonded_should_not_work() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 111); + assert_ok!(Staking::stake(&1)); + assert_noop!(Staking::transfer(&1, 2.into(), 69), "bondage too high to send value"); + }); +} + +#[test] +fn reserving_balance_should_work() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 111); + + assert_eq!(Staking::voting_balance(&1), 111); + assert_eq!(Staking::free_balance(&1), 111); + assert_eq!(Staking::reserved_balance(&1), 0); + + assert_ok!(Staking::reserve(&1, 69)); + + assert_eq!(Staking::voting_balance(&1), 111); + assert_eq!(Staking::free_balance(&1), 42); + assert_eq!(Staking::reserved_balance(&1), 69); + }); +} + +#[test] +fn staking_balance_transfer_when_reserved_should_not_work() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 111); + assert_ok!(Staking::reserve(&1, 69)); + assert_noop!(Staking::transfer(&1, 2.into(), 69), "balance too low to send value"); + }); +} + +#[test] +fn deducting_balance_should_work() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 111); + assert_ok!(Staking::reserve(&1, 69)); + assert_eq!(Staking::free_balance(&1), 42); + }); +} + +#[test] +fn deducting_balance_when_bonded_should_not_work() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 111); + >::insert(1, 2); + System::set_block_number(1); + assert_eq!(Staking::unlock_block(&1), LockStatus::LockedUntil(2)); + assert_noop!(Staking::reserve(&1, 69), "free funds are still bonded"); + }); +} + +#[test] +fn refunding_balance_should_work() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 42); + Staking::set_reserved_balance(&1, 69); + Staking::unreserve(&1, 69); + assert_eq!(Staking::free_balance(&1), 111); + assert_eq!(Staking::reserved_balance(&1), 0); + }); +} + +#[test] +fn slashing_balance_should_work() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 111); + Staking::increase_total_stake_by(111); + assert_ok!(Staking::reserve(&1, 69)); + assert!(Staking::slash(&1, 69).is_none()); + assert_eq!(Staking::free_balance(&1), 0); + assert_eq!(Staking::reserved_balance(&1), 42); + assert_eq!(>::get(), 44); + }); +} + +#[test] +fn slashing_incomplete_balance_should_work() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 42); + Staking::increase_total_stake_by(42); + assert_ok!(Staking::reserve(&1, 21)); + assert!(Staking::slash(&1, 69).is_some()); + assert_eq!(Staking::free_balance(&1), 0); + assert_eq!(Staking::reserved_balance(&1), 0); + assert_eq!(>::get(), 2); + }); +} + +#[test] +fn unreserving_balance_should_work() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 111); + assert_ok!(Staking::reserve(&1, 111)); + Staking::unreserve(&1, 42); + assert_eq!(Staking::reserved_balance(&1), 69); + assert_eq!(Staking::free_balance(&1), 42); + }); +} + +#[test] +fn slashing_reserved_balance_should_work() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 111); + Staking::increase_total_stake_by(111); + assert_ok!(Staking::reserve(&1, 111)); + assert!(Staking::slash_reserved(&1, 42).is_none()); + assert_eq!(Staking::reserved_balance(&1), 69); + assert_eq!(Staking::free_balance(&1), 0); + assert_eq!(>::get(), 71); + }); +} + +#[test] +fn slashing_incomplete_reserved_balance_should_work() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 111); + Staking::increase_total_stake_by(111); + assert_ok!(Staking::reserve(&1, 42)); + assert!(Staking::slash_reserved(&1, 69).is_some()); + assert_eq!(Staking::free_balance(&1), 69); + assert_eq!(Staking::reserved_balance(&1), 0); + assert_eq!(>::get(), 71); + }); +} + +#[test] +fn transferring_reserved_balance_should_work() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 110); + Staking::set_free_balance(&2, 1); + assert_ok!(Staking::reserve(&1, 110)); + assert_ok!(Staking::transfer_reserved(&1, &2, 41), None); + assert_eq!(Staking::reserved_balance(&1), 69); + assert_eq!(Staking::free_balance(&1), 0); + assert_eq!(Staking::reserved_balance(&2), 0); + assert_eq!(Staking::free_balance(&2), 42); + }); +} + +#[test] +fn transferring_reserved_balance_to_nonexistent_should_fail() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 111); + assert_ok!(Staking::reserve(&1, 111)); + assert_noop!(Staking::transfer_reserved(&1, &2, 42), "beneficiary account must pre-exist"); + }); +} + +#[test] +fn transferring_incomplete_reserved_balance_should_work() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + Staking::set_free_balance(&1, 110); + Staking::set_free_balance(&2, 1); + assert_ok!(Staking::reserve(&1, 41)); + assert!(Staking::transfer_reserved(&1, &2, 69).unwrap().is_some()); + assert_eq!(Staking::reserved_balance(&1), 0); + assert_eq!(Staking::free_balance(&1), 69); + assert_eq!(Staking::reserved_balance(&2), 0); + assert_eq!(Staking::free_balance(&2), 42); + }); +} + +#[test] +fn transferring_too_high_value_should_not_panic() { + with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + >::insert(1, u64::max_value()); + >::insert(2, 1); + + assert_err!( + Staking::transfer(&1, 2.into(), u64::max_value()), + "destination balance too high to receive value" + ); + + assert_eq!(Staking::free_balance(&1), u64::max_value()); + assert_eq!(Staking::free_balance(&2), 1); + }); +} + +#[test] +fn account_removal_on_free_too_low() { + with_externalities(&mut new_test_ext(100, 1, 3, 1, false, 0), || { + // Setup two accounts with free balance above the exsistential threshold. + { + Staking::set_free_balance(&1, 110); + Staking::increase_total_stake_by(110); + + Staking::set_free_balance(&2, 110); + Staking::increase_total_stake_by(110); + + assert_eq!(>::get(), 732); + } + + // Transfer funds from account 1 of such amount that after this transfer + // the balance of account 1 will be below the exsistential threshold. + // This should lead to the removal of all balance of this account. + assert_ok!(Staking::transfer(&1, 2.into(), 20)); + + // Verify free balance removal of account 1. + assert_eq!(Staking::free_balance(&1), 0); + + // Verify that TotalStake tracks balance removal when free balance is too low. + assert_eq!(>::get(), 642); + }); +} diff --git a/substrate/runtime/staking/Cargo.toml b/substrate/runtime/staking/Cargo.toml index 7cffe09d01217..d4214862a73d3 100644 --- a/substrate/runtime/staking/Cargo.toml +++ b/substrate/runtime/staking/Cargo.toml @@ -17,6 +17,7 @@ substrate-runtime-io = { path = "../../runtime-io", default_features = false } substrate-runtime-sandbox = { path = "../../runtime-sandbox", default_features = false } substrate-runtime-support = { path = "../../runtime-support", default_features = false } substrate-runtime-primitives = { path = "../primitives", default_features = false } +substrate-runtime-balances = { path = "../balances", default_features = false } substrate-runtime-consensus = { path = "../consensus", default_features = false } substrate-runtime-system = { path = "../system", default_features = false } substrate-runtime-session = { path = "../session", default_features = false } @@ -40,6 +41,7 @@ std = [ "substrate-runtime-sandbox/std", "substrate-runtime-support/std", "substrate-runtime-primitives/std", + "substrate-runtime-balances/std", "substrate-runtime-session/std", "substrate-runtime-system/std", "substrate-runtime-timestamp/std" diff --git a/substrate/runtime/staking/src/lib.rs b/substrate/runtime/staking/src/lib.rs index 92c8f47faa244..bc058d3cae32d 100644 --- a/substrate/runtime/staking/src/lib.rs +++ b/substrate/runtime/staking/src/lib.rs @@ -192,21 +192,12 @@ impl From> for () { decl_storage! { trait Store for Module as Staking { + // Separate into Accounts module. + // The length of the bonding duration in eras. pub BondingDuration get(bonding_duration): required T::BlockNumber; - // The ideal number of staking participants. - pub ValidatorCount get(validator_count): required u32; - // Minimum number of staking participants before emergency conditions are imposed. - pub MinimumValidatorCount: u32; - // The length of a staking era in sessions. - pub SessionsPerEra get(sessions_per_era): required T::BlockNumber; // The total amount of stake on the system. - // TODO: this doesn't actually track total stake yet - it should do. pub TotalStake get(total_stake): required T::Balance; - // The fee to be paid for making a transaction; the base. - pub TransactionBaseFee get(transaction_base_fee): required T::Balance; - // The fee to be paid for making a transaction; the per-byte portion. - pub TransactionByteFee get(transaction_byte_fee): required T::Balance; // The minimum amount allowed to keep an account open. pub ExistentialDeposit get(existential_deposit): required T::Balance; // The amount credited to a destination's account whose index was reclaimed. @@ -215,43 +206,12 @@ decl_storage! { pub TransferFee get(transfer_fee): required T::Balance; // The fee required to create an account. At least as big as ReclaimRebate. pub CreationFee get(creation_fee): required T::Balance; - // Maximum reward, per validator, that is provided per acceptable session. - pub SessionReward get(session_reward): required T::Balance; - // Slash, per validator that is taken per abnormal era end. - pub EarlyEraSlash get(early_era_slash): required T::Balance; - // Number of instances of offline reports before slashing begins for validators. - pub OfflineSlashGrace get(offline_slash_grace): default u32; - - // The current era index. - pub CurrentEra get(current_era): required T::BlockNumber; - // Preference over how many times the validator should get slashed for being offline before they are automatically unstaked. - pub SlashPreferenceOf get(slash_preference_of): default map [ T::AccountId => SlashPreference ]; - // All the accounts with a desire to stake. - pub Intentions get(intentions): default Vec; - // All nominator -> nominee relationships. - pub Nominating get(nominating): map [ T::AccountId => T::AccountId ]; - // Nominators for a particular account. - pub NominatorsFor get(nominators_for): default map [ T::AccountId => Vec ]; - // Nominators for a particular account that is in action right now. - pub CurrentNominatorsFor get(current_nominators_for): default map [ T::AccountId => Vec ]; - // The next value of sessions per era. - pub NextSessionsPerEra get(next_sessions_per_era): T::BlockNumber; - // The session index at which the era length last changed. - pub LastEraLengthChange get(last_era_length_change): default T::BlockNumber; - // The current era stake threshold - pub StakeThreshold get(stake_threshold): required T::Balance; - - // The number of times a given validator has been reported offline. This gets decremented by one each era that passes. - pub SlashCount get(slash_count): default map [ T::AccountId => u32 ]; // The next free enumeration set. pub NextEnumSet get(next_enum_set): required T::AccountIndex; // The enumeration sets. pub EnumSet get(enum_set): default map [ T::AccountIndex => Vec ]; - // We are forcing a new era. - pub ForcingNewEra get(forcing_new_era): (); - // The "free" balance of a given account. // // This is the only balance that matters in terms of most operations on tokens. It is @@ -281,6 +241,57 @@ decl_storage! { // The block at which the `who`'s funds become entirely liquid. pub Bondage get(bondage): default map [ T::AccountId => T::BlockNumber ]; + + + // Separate into Payment module. + + // The fee to be paid for making a transaction; the base. + pub TransactionBaseFee get(transaction_base_fee): required T::Balance; + // The fee to be paid for making a transaction; the per-byte portion. + pub TransactionByteFee get(transaction_byte_fee): required T::Balance; + + + // Remains in Staking module + + // The ideal number of staking participants. + pub ValidatorCount get(validator_count): required u32; + // Minimum number of staking participants before emergency conditions are imposed. + pub MinimumValidatorCount: u32; + // The length of a staking era in sessions. + pub SessionsPerEra get(sessions_per_era): required T::BlockNumber; + + // Maximum reward, per validator, that is provided per acceptable session. + pub SessionReward get(session_reward): required T::Balance; + // Slash, per validator that is taken per abnormal era end. + pub EarlyEraSlash get(early_era_slash): required T::Balance; + // Number of instances of offline reports before slashing begins for validators. + pub OfflineSlashGrace get(offline_slash_grace): default u32; + + // The current era index. + pub CurrentEra get(current_era): required T::BlockNumber; + // Preference over how many times the validator should get slashed for being offline before they are automatically unstaked. + pub SlashPreferenceOf get(slash_preference_of): default map [ T::AccountId => SlashPreference ]; + // All the accounts with a desire to stake. + pub Intentions get(intentions): default Vec; + // All nominator -> nominee relationships. + pub Nominating get(nominating): map [ T::AccountId => T::AccountId ]; + // Nominators for a particular account. + pub NominatorsFor get(nominators_for): default map [ T::AccountId => Vec ]; + // Nominators for a particular account that is in action right now. + pub CurrentNominatorsFor get(current_nominators_for): default map [ T::AccountId => Vec ]; + // The next value of sessions per era. + pub NextSessionsPerEra get(next_sessions_per_era): T::BlockNumber; + // The session index at which the era length last changed. + pub LastEraLengthChange get(last_era_length_change): default T::BlockNumber; + + // The current era stake threshold - unused at present. Consider for removal. + pub StakeThreshold get(stake_threshold): required T::Balance; + + // The number of times a given validator has been reported offline. This gets decremented by one each era that passes. + pub SlashCount get(slash_count): default map [ T::AccountId => u32 ]; + + // We are forcing a new era. + pub ForcingNewEra get(forcing_new_era): (); } } From 7a76f9b58924afe83cbe00f6698d8c918293fa12 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 29 Aug 2018 19:27:00 +0200 Subject: [PATCH 02/19] Split out balances module --- Cargo.lock | 25 + .../runtime/balances/src/genesis_config.rs | 53 +- substrate/runtime/balances/src/lib.rs | 437 +---------- substrate/runtime/balances/src/mock.rs | 15 +- substrate/runtime/balances/src/tests.rs | 704 ++++-------------- 5 files changed, 197 insertions(+), 1037 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c8ef9e2a8c192..5a9a880c0c966 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2655,6 +2655,30 @@ dependencies = [ "substrate-runtime-primitives 0.1.0", ] +[[package]] +name = "substrate-runtime-balances" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-codec-derive 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-sandbox 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", + "wabt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-runtime-consensus" version = "0.1.0" @@ -2841,6 +2865,7 @@ dependencies = [ "substrate-codec-derive 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-balances 0.1.0", "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", diff --git a/substrate/runtime/balances/src/genesis_config.rs b/substrate/runtime/balances/src/genesis_config.rs index 8da72bf1d92ab..763c626f8db07 100644 --- a/substrate/runtime/balances/src/genesis_config.rs +++ b/substrate/runtime/balances/src/genesis_config.rs @@ -25,60 +25,38 @@ use runtime_support::{StorageValue, StorageMap}; use primitives::traits::{Zero, As}; use substrate_primitives::KeccakHasher; use {runtime_io, primitives}; -use super::{Trait, ENUM_SET_SIZE, EnumSet, NextEnumSet, Intentions, CurrentEra, - BondingDuration, CreationFee, TransferFee, ReclaimRebate, - ExistentialDeposit, TransactionByteFee, TransactionBaseFee, TotalStake, - SessionsPerEra, ValidatorCount, FreeBalance, SessionReward, EarlyEraSlash, - OfflineSlashGrace, MinimumValidatorCount}; +use super::{Trait, ENUM_SET_SIZE, EnumSet, NextEnumSet, CreationFee, TransferFee, + ReclaimRebate, ExistentialDeposit, TransactionByteFee, TransactionBaseFee, TotalStake, + FreeBalance}; #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] pub struct GenesisConfig { - pub sessions_per_era: T::BlockNumber, - pub current_era: T::BlockNumber, pub balances: Vec<(T::AccountId, T::Balance)>, - pub intentions: Vec, - pub validator_count: u32, - pub minimum_validator_count: u32, - pub bonding_duration: T::BlockNumber, pub transaction_base_fee: T::Balance, pub transaction_byte_fee: T::Balance, pub transfer_fee: T::Balance, pub creation_fee: T::Balance, pub reclaim_rebate: T::Balance, pub existential_deposit: T::Balance, - pub session_reward: T::Balance, - pub early_era_slash: T::Balance, - pub offline_slash_grace: u32, } impl GenesisConfig where T::AccountId: From { pub fn simple() -> Self { GenesisConfig { - sessions_per_era: T::BlockNumber::sa(2), - current_era: T::BlockNumber::sa(0), balances: vec![(T::AccountId::from(1), T::Balance::sa(111))], - intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], - validator_count: 3, - minimum_validator_count: 1, - bonding_duration: T::BlockNumber::sa(0), transaction_base_fee: T::Balance::sa(0), transaction_byte_fee: T::Balance::sa(0), transfer_fee: T::Balance::sa(0), creation_fee: T::Balance::sa(0), existential_deposit: T::Balance::sa(0), reclaim_rebate: T::Balance::sa(0), - session_reward: T::Balance::sa(0), - early_era_slash: T::Balance::sa(0), - offline_slash_grace: 1, } } pub fn extended() -> Self { GenesisConfig { - sessions_per_era: T::BlockNumber::sa(3), - current_era: T::BlockNumber::sa(1), balances: vec![ (T::AccountId::from(1), T::Balance::sa(10)), (T::AccountId::from(2), T::Balance::sa(20)), @@ -88,19 +66,12 @@ impl GenesisConfig where T::AccountId: From { (T::AccountId::from(6), T::Balance::sa(60)), (T::AccountId::from(7), T::Balance::sa(1)) ], - intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], - validator_count: 3, - minimum_validator_count: 1, - bonding_duration: T::BlockNumber::sa(0), transaction_base_fee: T::Balance::sa(1), transaction_byte_fee: T::Balance::sa(0), transfer_fee: T::Balance::sa(0), creation_fee: T::Balance::sa(0), existential_deposit: T::Balance::sa(0), reclaim_rebate: T::Balance::sa(0), - session_reward: T::Balance::sa(0), - early_era_slash: T::Balance::sa(0), - offline_slash_grace: 1, } } } @@ -108,22 +79,13 @@ impl GenesisConfig where T::AccountId: From { impl Default for GenesisConfig { fn default() -> Self { GenesisConfig { - sessions_per_era: T::BlockNumber::sa(1000), - current_era: T::BlockNumber::sa(0), balances: vec![], - intentions: vec![], - validator_count: 0, - minimum_validator_count: 0, - bonding_duration: T::BlockNumber::sa(1000), transaction_base_fee: T::Balance::sa(0), transaction_byte_fee: T::Balance::sa(0), transfer_fee: T::Balance::sa(0), creation_fee: T::Balance::sa(0), existential_deposit: T::Balance::sa(0), reclaim_rebate: T::Balance::sa(0), - session_reward: T::Balance::sa(0), - early_era_slash: T::Balance::sa(0), - offline_slash_grace: 0, } } } @@ -134,21 +96,12 @@ impl primitives::BuildStorage for GenesisConfig { let mut r: runtime_io::TestExternalities = map![ Self::hash(>::key()).to_vec() => T::AccountIndex::sa(self.balances.len() / ENUM_SET_SIZE).encode(), - Self::hash(>::key()).to_vec() => self.intentions.encode(), - Self::hash(>::key()).to_vec() => self.sessions_per_era.encode(), - Self::hash(>::key()).to_vec() => self.validator_count.encode(), - Self::hash(>::key()).to_vec() => self.minimum_validator_count.encode(), - Self::hash(>::key()).to_vec() => self.bonding_duration.encode(), Self::hash(>::key()).to_vec() => self.transaction_base_fee.encode(), Self::hash(>::key()).to_vec() => self.transaction_byte_fee.encode(), Self::hash(>::key()).to_vec() => self.transfer_fee.encode(), Self::hash(>::key()).to_vec() => self.creation_fee.encode(), Self::hash(>::key()).to_vec() => self.existential_deposit.encode(), Self::hash(>::key()).to_vec() => self.reclaim_rebate.encode(), - Self::hash(>::key()).to_vec() => self.current_era.encode(), - Self::hash(>::key()).to_vec() => self.session_reward.encode(), - Self::hash(>::key()).to_vec() => self.early_era_slash.encode(), - Self::hash(>::key()).to_vec() => self.offline_slash_grace.encode(), Self::hash(>::key()).to_vec() => total_stake.encode() ]; diff --git a/substrate/runtime/balances/src/lib.rs b/substrate/runtime/balances/src/lib.rs index 092a419cc74a2..1130182e04ae2 100644 --- a/substrate/runtime/balances/src/lib.rs +++ b/substrate/runtime/balances/src/lib.rs @@ -53,9 +53,8 @@ use rstd::{cmp, result}; use codec::{Encode, Decode, Codec, Input, Output}; use runtime_support::{StorageValue, StorageMap, Parameter}; use runtime_support::dispatch::Result; -use session::OnSessionChange; -use primitives::traits::{Zero, One, Bounded, RefInto, SimpleArithmetic, Executable, MakePayment, - As, AuxLookup, Member, CheckedAdd, CheckedSub, MaybeEmpty}; +use primitives::traits::{Zero, One, RefInto, SimpleArithmetic, Executable, MakePayment, + As, AuxLookup, Member, CheckedAdd, CheckedSub}; use address::Address as RawAddress; mod mock; @@ -97,6 +96,26 @@ pub trait OnFreeBalanceZero { impl OnFreeBalanceZero for () { fn on_free_balance_zero(_who: &AccountId) {} } +impl< + AccountId, + X: OnFreeBalanceZero, + Y: OnFreeBalanceZero, +> OnFreeBalanceZero for (X, Y) { + fn on_free_balance_zero(who: &AccountId) { + X::on_free_balance_zero(who); + Y::on_free_balance_zero(who); + } +} + +/// The account was the given id was killed. +pub trait IsAccountLiquid { + /// The account was the given id was killed. + fn is_account_liquid(who: &AccountId) -> bool; +} + +impl IsAccountLiquid for () { + fn is_account_liquid(_who: &AccountId) -> bool { true } +} pub trait Trait: system::Trait + session::Trait { /// The balance of an account. @@ -108,8 +127,12 @@ pub trait Trait: system::Trait + session::Trait { /// has been reduced to zero. /// /// Gives a chance to clean up resources associated with the given account. + // TODO gav: should ensure staking calls >::remove(who); on this. type OnFreeBalanceZero: OnFreeBalanceZero; + /// A function that returns true iff a given account can transfer its funds to another account. + type IsAccountLiquid: IsAccountLiquid; + /// The overarching event type. type Event: From> + Into<::Event>; } @@ -138,18 +161,14 @@ pub enum RawEvent { ReapedAccount(AccountId), } -impl From> for () { - fn from(_: RawEvent) -> () { () } +impl From> for () { + fn from(_: RawEvent) -> () { () } } decl_storage! { - trait Store for staking::Module { - - // Separate into Accounts module. - - // The length of the bonding duration in eras. - pub BondingDuration get(bonding_duration): required T::BlockNumber; + trait Store for Module as Balances { // The total amount of stake on the system. + // TODO gav: rename to TotalIssuance pub TotalStake get(total_stake): required T::Balance; // The minimum amount allowed to keep an account open. pub ExistentialDeposit get(existential_deposit): required T::Balance; @@ -192,9 +211,6 @@ decl_storage! { // collapsed to zero if it ever becomes less than `ExistentialDeposit`. pub ReservedBalance get(reserved_balance): default map [ T::AccountId => T::Balance ]; - // The block at which the `who`'s funds become entirely liquid. - pub Bondage get(bondage): default map [ T::AccountId => T::BlockNumber ]; - // Separate into Payment module. @@ -202,49 +218,6 @@ decl_storage! { pub TransactionBaseFee get(transaction_base_fee): required T::Balance; // The fee to be paid for making a transaction; the per-byte portion. pub TransactionByteFee get(transaction_byte_fee): required T::Balance; - - - // Remains in Staking module - - // The ideal number of staking participants. - pub ValidatorCount get(validator_count): required u32; - // Minimum number of staking participants before emergency conditions are imposed. - pub MinimumValidatorCount: u32; - // The length of a staking era in sessions. - pub SessionsPerEra get(sessions_per_era): required T::BlockNumber; - - // Maximum reward, per validator, that is provided per acceptable session. - pub SessionReward get(session_reward): required T::Balance; - // Slash, per validator that is taken per abnormal era end. - pub EarlyEraSlash get(early_era_slash): required T::Balance; - // Number of instances of offline reports before slashing begins for validators. - pub OfflineSlashGrace get(offline_slash_grace): default u32; - - // The current era index. - pub CurrentEra get(current_era): required T::BlockNumber; - // Preference over how many times the validator should get slashed for being offline before they are automatically unstaked. - pub SlashPreferenceOf get(slash_preference_of): default map [ T::AccountId => SlashPreference ]; - // All the accounts with a desire to stake. - pub Intentions get(intentions): default Vec; - // All nominator -> nominee relationships. - pub Nominating get(nominating): map [ T::AccountId => T::AccountId ]; - // Nominators for a particular account. - pub NominatorsFor get(nominators_for): default map [ T::AccountId => Vec ]; - // Nominators for a particular account that is in action right now. - pub CurrentNominatorsFor get(current_nominators_for): default map [ T::AccountId => Vec ]; - // The next value of sessions per era. - pub NextSessionsPerEra get(next_sessions_per_era): T::BlockNumber; - // The session index at which the era length last changed. - pub LastEraLengthChange get(last_era_length_change): default T::BlockNumber; - - // The current era stake threshold - unused at present. Consider for removal. - pub StakeThreshold get(stake_threshold): required T::Balance; - - // The number of times a given validator has been reported offline. This gets decremented by one each era that passes. - pub SlashCount get(slash_count): default map [ T::AccountId => u32 ]; - - // We are forcing a new era. - pub ForcingNewEra get(forcing_new_era): (); } } @@ -269,34 +242,12 @@ impl Module { // PUBLIC IMMUTABLES - pub fn minimum_validator_count() -> usize { - >::get().map(|v| v as usize).unwrap_or(DEFAULT_MINIMUM_VALIDATOR_COUNT) - } - - /// The length of a staking era in blocks. - pub fn era_length() -> T::BlockNumber { - Self::sessions_per_era() * >::length() - } - /// The combined balance of `who`. + // TODO gav: rename to total_balance pub fn voting_balance(who: &T::AccountId) -> T::Balance { Self::free_balance(who) + Self::reserved_balance(who) } - /// Balance of a (potential) validator that includes all nominators. - pub fn nomination_balance(who: &T::AccountId) -> T::Balance { - Self::nominators_for(who).iter() - .map(Self::voting_balance) - .fold(Zero::zero(), |acc, x| acc + x) - } - - /// The total balance that can be slashed from an account. - pub fn slashable_balance(who: &T::AccountId) -> T::Balance { - Self::nominators_for(who).iter() - .map(Self::voting_balance) - .fold(Self::voting_balance(who), |acc, x| acc + x) - } - /// Some result as `slash(who, value)` (but without the side-effects) assuming there are no /// balance changes in the meantime and only the reserved balance is not taken into account. pub fn can_slash(who: &T::AccountId, value: T::Balance) -> bool { @@ -306,7 +257,7 @@ impl Module { /// Same result as `reserve(who, value)` (but without the side-effects) assuming there /// are no balance changes in the meantime. pub fn can_reserve(who: &T::AccountId, value: T::Balance) -> bool { - if let LockStatus::Liquid = Self::unlock_block(who) { + if T::IsAccountLiquid::is_account_liquid(who) { Self::free_balance(who) >= value } else { false @@ -329,15 +280,6 @@ impl Module { i < try_set.len() && Self::voting_balance(&try_set[i]).is_zero() } - /// The block at which the `who`'s funds become entirely liquid. - pub fn unlock_block(who: &T::AccountId) -> LockStatus { - match Self::bondage(who) { - i if i == T::BlockNumber::max_value() => LockStatus::Bonded, - i if i <= >::block_number() => LockStatus::Liquid, - i => LockStatus::LockedUntil(i), - } - } - /// Lookup an address to get an Id, if there's one there. pub fn lookup_address(a: address::Address) -> Option { match a { @@ -365,11 +307,13 @@ impl Module { if would_create && value < Self::existential_deposit() { return Err("value too low to create account"); } - if >::get(transactor) > >::block_number() { + if !T::IsAccountLiquid::is_account_liquid(transactor) { return Err("bondage too high to send value"); } let to_balance = Self::free_balance(&dest); + // NOTE: total stake being stored in the same type means that this could never overflow + // but better to be safe than sorry. let new_to_balance = match to_balance.checked_add(&value) { Some(b) => b, None => return Err("destination balance too high to receive value"), @@ -384,142 +328,6 @@ impl Module { Ok(()) } - /// Declare the desire to stake for the transactor. - /// - /// Effects will be felt at the beginning of the next era. - fn stake(aux: &T::PublicAux) -> Result { - let aux = aux.ref_into(); - ensure!(Self::nominating(aux).is_none(), "Cannot stake if already nominating."); - let mut intentions = >::get(); - // can't be in the list twice. - ensure!(intentions.iter().find(|&t| t == aux).is_none(), "Cannot stake if already staked."); - intentions.push(aux.clone()); - >::put(intentions); - >::insert(aux, T::BlockNumber::max_value()); - Ok(()) - } - - /// Retract the desire to stake for the transactor. - /// - /// Effects will be felt at the beginning of the next era. - fn unstake(aux: &T::PublicAux, intentions_index: u32) -> Result { - // unstake fails in degenerate case of having too few existing staked parties - if Self::intentions().len() <= Self::minimum_validator_count() { - return Err("cannot unstake when there are too few staked participants") - } - Self::apply_unstake(aux.ref_into(), intentions_index as usize) - } - - fn nominate(aux: &T::PublicAux, target: RawAddress) -> Result { - let target = Self::lookup(target)?; - let aux = aux.ref_into(); - - ensure!(Self::nominating(aux).is_none(), "Cannot nominate if already nominating."); - ensure!(Self::intentions().iter().find(|&t| t == aux.ref_into()).is_none(), "Cannot nominate if already staked."); - - // update nominators_for - let mut t = Self::nominators_for(&target); - t.push(aux.clone()); - >::insert(&target, t); - - // update nominating - >::insert(aux, &target); - - // Update bondage - >::insert(aux.ref_into(), T::BlockNumber::max_value()); - - Ok(()) - } - - /// Will panic if called when source isn't currently nominating target. - /// Updates Nominating, NominatorsFor and NominationBalance. - fn unnominate(aux: &T::PublicAux, target_index: u32) -> Result { - let source = aux.ref_into(); - let target_index = target_index as usize; - - let target = >::get(source).ok_or("Account must be nominating")?; - - let mut t = Self::nominators_for(&target); - if t.get(target_index) != Some(source) { - return Err("Invalid target index") - } - - // Ok - all valid. - - // update nominators_for - t.swap_remove(target_index); - >::insert(&target, t); - - // update nominating - >::remove(source); - - // update bondage - >::insert(aux.ref_into(), Self::current_era() + Self::bonding_duration()); - Ok(()) - } - - /// Set the given account's preference for slashing behaviour should they be a validator. - /// - /// An error (no-op) if `Self::intentions()[intentions_index] != aux`. - fn register_slash_preference( - aux: &T::PublicAux, - intentions_index: u32, - p: SlashPreference - ) -> Result { - let aux = aux.ref_into(); - - if Self::intentions().get(intentions_index as usize) != Some(aux) { - return Err("Invalid index") - } - - >::insert(aux, p); - - Ok(()) - } - - /// Note the previous block's validator missed their opportunity to propose a block. This only comes in - /// if 2/3+1 of the validators agree that no proposal was submitted. It's only relevant - /// for the previous block. - fn note_missed_proposal(aux: &T::PublicAux, offline_val_indices: Vec) -> Result { - assert!(aux.is_empty()); - assert!( - >::extrinsic_index() == Some(T::NOTE_MISSED_PROPOSAL_POSITION), - "note_missed_proposal extrinsic must be at position {} in the block", - T::NOTE_MISSED_PROPOSAL_POSITION - ); - - for validator_index in offline_val_indices.into_iter() { - let v = >::validators()[validator_index as usize].clone(); - let slash_count = Self::slash_count(&v); - >::insert(v.clone(), slash_count + 1); - let grace = Self::offline_slash_grace(); - - let event = if slash_count >= grace { - let instances = slash_count - grace; - let slash = Self::early_era_slash() << instances; - let next_slash = slash << 1u32; - let _ = Self::slash_validator(&v, slash); - if instances >= Self::slash_preference_of(&v).unstake_threshold - || Self::slashable_balance(&v) < next_slash - { - if let Some(pos) = Self::intentions().into_iter().position(|x| &x == &v) { - Self::apply_unstake(&v, pos) - .expect("pos derived correctly from Self::intentions(); \ - apply_unstake can only fail if pos wrong; \ - Self::intentions() doesn't change; qed"); - } - let _ = Self::force_new_era(false); - } - RawEvent::OfflineSlash(v, slash) - } else { - RawEvent::OfflineWarning(v, slash_count) - }; - Self::deposit_event(event); - } - - Ok(()) - } - // PRIV DISPATCH /// Deposit one of this module's events. @@ -527,37 +335,6 @@ impl Module { >::deposit_event(::Event::from(event).into()); } - /// Set the number of sessions in an era. - fn set_sessions_per_era(new: T::BlockNumber) -> Result { - >::put(&new); - Ok(()) - } - - /// The length of the bonding duration in eras. - fn set_bonding_duration(new: T::BlockNumber) -> Result { - >::put(&new); - Ok(()) - } - - /// The length of a staking era in sessions. - fn set_validator_count(new: u32) -> Result { - >::put(&new); - Ok(()) - } - - /// Force there to be a new era. This also forces a new session immediately after. - /// `apply_rewards` should be true for validators to get the session reward. - fn force_new_era(apply_rewards: bool) -> Result { - >::put(()); - >::force_new_session(apply_rewards) - } - - /// Set the offline slash grace period. - fn set_offline_slash_grace(new: u32) -> Result { - >::put(&new); - Ok(()) - } - /// Set the balances of a given account. fn set_balance(who: Address, free: T::Balance, reserved: T::Balance) -> Result { let who = Self::lookup(who)?; @@ -681,7 +458,7 @@ impl Module { if b < value { return Err("not enough free funds") } - if Self::unlock_block(who) != LockStatus::Liquid { + if T::IsAccountLiquid::is_account_liquid(who) { return Err("free funds are still bonded") } Self::set_reserved_balance(who, Self::reserved_balance(who) + value); @@ -728,6 +505,7 @@ impl Module { /// /// As much funds up to `value` will be moved as possible. If this is less than `value`, then /// `Ok(Some(remaining))` will be returned. Full completion is given by `Ok(None)`. + // TODO gav: rename to repatriate_reserved. pub fn transfer_reserved( slashed: &T::AccountId, beneficiary: &T::AccountId, @@ -747,140 +525,6 @@ impl Module { } } - /// Slash a given validator by a specific amount. Removes the slash from their balance by preference, - /// and reduces the nominators' balance if needed. - fn slash_validator(v: &T::AccountId, slash: T::Balance) { - // skip the slash in degenerate case of having only 4 staking participants despite having a larger - // desired number of validators (validator_count). - if Self::intentions().len() <= Self::minimum_validator_count() { - return - } - - if let Some(rem) = Self::slash(v, slash) { - let noms = Self::current_nominators_for(v); - let total = noms.iter().map(Self::voting_balance).fold(T::Balance::zero(), |acc, x| acc + x); - if !total.is_zero() { - let safe_mul_rational = |b| b * rem / total;// TODO: avoid overflow - for n in noms.iter() { - let _ = Self::slash(n, safe_mul_rational(Self::voting_balance(n))); // best effort - not much that can be done on fail. - } - } - } - } - - /// Reward a given validator by a specific amount. Add the reward to their, and their nominators' - /// balance, pro-rata. - fn reward_validator(who: &T::AccountId, reward: T::Balance) { - let noms = Self::current_nominators_for(who); - let total = noms.iter().map(Self::voting_balance).fold(Self::voting_balance(who), |acc, x| acc + x); - if !total.is_zero() { - let safe_mul_rational = |b| b * reward / total;// TODO: avoid overflow - for n in noms.iter() { - let _ = Self::reward(n, safe_mul_rational(Self::voting_balance(n))); - } - let _ = Self::reward(who, safe_mul_rational(Self::voting_balance(who))); - } - } - - /// Actually carry out the unstake operation. - /// Assumes `intentions()[intentions_index] == who`. - fn apply_unstake(who: &T::AccountId, intentions_index: usize) -> Result { - let mut intentions = Self::intentions(); - if intentions.get(intentions_index) != Some(who) { - return Err("Invalid index"); - } - intentions.swap_remove(intentions_index); - >::put(intentions); - >::remove(who); - >::remove(who); - >::insert(who, Self::current_era() + Self::bonding_duration()); - Ok(()) - } - - /// Get the reward for the session, assuming it ends with this block. - fn this_session_reward(actual_elapsed: T::Moment) -> T::Balance { - let ideal_elapsed = >::ideal_session_duration(); - let per65536: u64 = (T::Moment::sa(65536u64) * ideal_elapsed.clone() / actual_elapsed.max(ideal_elapsed)).as_(); - Self::session_reward() * T::Balance::sa(per65536) / T::Balance::sa(65536u64) - } - - /// Session has just changed. We need to determine whether we pay a reward, slash and/or - /// move to a new era. - fn new_session(actual_elapsed: T::Moment, should_reward: bool) { - if should_reward { - // apply good session reward - let reward = Self::this_session_reward(actual_elapsed); - for v in >::validators().iter() { - Self::reward_validator(v, reward); - } - Self::deposit_event(RawEvent::Reward(reward)); - } - - let session_index = >::current_index(); - if >::take().is_some() - || ((session_index - Self::last_era_length_change()) % Self::sessions_per_era()).is_zero() - { - Self::new_era(); - } - } - - /// The era has changed - enact new staking set. - /// - /// NOTE: This always happens immediately before a session change to ensure that new validators - /// get a chance to set their session keys. - fn new_era() { - // Increment current era. - >::put(&(>::get() + One::one())); - - // Enact era length change. - if let Some(next_spe) = Self::next_sessions_per_era() { - if next_spe != Self::sessions_per_era() { - >::put(&next_spe); - >::put(&>::current_index()); - } - } - - // evaluate desired staking amounts and nominations and optimise to find the best - // combination of validators, then use session::internal::set_validators(). - // for now, this just orders would-be stakers by their balances and chooses the top-most - // >::get() of them. - // TODO: this is not sound. this should be moved to an off-chain solution mechanism. - let mut intentions = Self::intentions() - .into_iter() - .map(|v| (Self::slashable_balance(&v), v)) - .collect::>(); - - // Avoid reevaluate validator set if it would leave us with fewer than the minimum - // needed validators - if intentions.len() < Self::minimum_validator_count() { - return - } - - intentions.sort_unstable_by(|&(ref b1, _), &(ref b2, _)| b2.cmp(&b1)); - - >::put( - if !intentions.is_empty() { - let i = (>::get() as usize).min(intentions.len() - 1); - intentions[i].0.clone() - } else { Zero::zero() } - ); - let vals = &intentions.into_iter() - .map(|(_, v)| v) - .take(>::get() as usize) - .collect::>(); - for v in >::validators().iter() { - >::remove(v); - let slash_count = >::take(v); - if slash_count > 1 { - >::insert(v, slash_count - 1); - } - } - for v in vals.iter() { - >::insert(v, Self::nominators_for(v)); - } - >::set_validators(vals); - } - fn enum_set_size() -> T::AccountIndex { T::AccountIndex::sa(ENUM_SET_SIZE) } @@ -968,7 +612,6 @@ impl Module { fn on_free_too_low(who: &T::AccountId) { Self::decrease_total_stake_by(Self::free_balance(who)); >::remove(who); - >::remove(who); T::OnFreeBalanceZero::on_free_balance_zero(who); @@ -1006,12 +649,6 @@ impl Executable for Module { } } -impl OnSessionChange for Module { - fn on_session_change(elapsed: T::Moment, should_reward: bool) { - Self::new_session(elapsed, should_reward); - } -} - impl AuxLookup for Module { type Source = address::Address; type Target = T::AccountId; diff --git a/substrate/runtime/balances/src/mock.rs b/substrate/runtime/balances/src/mock.rs index 7b3097010d7eb..ba9cf0ead7f60 100644 --- a/substrate/runtime/balances/src/mock.rs +++ b/substrate/runtime/balances/src/mock.rs @@ -55,14 +55,14 @@ impl timestamp::Trait for Test { type Moment = u64; } impl Trait for Test { - const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1; type Balance = u64; type AccountIndex = u64; type OnFreeBalanceZero = (); + type IsAccountLiquid = (); type Event = (); } -pub fn new_test_ext(ext_deposit: u64, session_length: u64, sessions_per_era: u64, current_era: u64, monied: bool, reward: u64) -> runtime_io::TestExternalities { +pub fn new_test_ext(ext_deposit: u64, monied: bool) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap(); let balance_factor = if ext_deposit > 0 { 256 @@ -78,8 +78,6 @@ pub fn new_test_ext(ext_deposit: u64, session_length: u64, sessions_per_era: u64 validators: vec![10, 20], }.build_storage().unwrap()); t.extend(GenesisConfig::{ - sessions_per_era, - current_era, balances: if monied { if reward > 0 { vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor), (10, balance_factor), (20, balance_factor)] @@ -89,19 +87,12 @@ pub fn new_test_ext(ext_deposit: u64, session_length: u64, sessions_per_era: u64 } else { vec![(10, balance_factor), (20, balance_factor)] }, - intentions: vec![10, 20], - validator_count: 2, - minimum_validator_count: 0, - bonding_duration: 3, transaction_base_fee: 0, transaction_byte_fee: 0, existential_deposit: ext_deposit, transfer_fee: 0, creation_fee: 0, reclaim_rebate: 0, - session_reward: reward, - early_era_slash: if monied { 20 } else { 0 }, - offline_slash_grace: 0, }.build_storage().unwrap()); t.extend(timestamp::GenesisConfig::{ period: 5 @@ -112,4 +103,4 @@ pub fn new_test_ext(ext_deposit: u64, session_length: u64, sessions_per_era: u64 pub type System = system::Module; pub type Session = session::Module; pub type Timestamp = timestamp::Module; -pub type Staking = Module; +pub type Balances = Module; diff --git a/substrate/runtime/balances/src/tests.rs b/substrate/runtime/balances/src/tests.rs index 809838379ae12..346950fb52cf0 100644 --- a/substrate/runtime/balances/src/tests.rs +++ b/substrate/runtime/balances/src/tests.rs @@ -20,234 +20,35 @@ use super::*; use runtime_io::with_externalities; -use mock::{Session, Staking, System, Timestamp, Test, new_test_ext}; - -#[test] -fn note_null_missed_proposal_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - assert_eq!(Staking::offline_slash_grace(), 0); - assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Staking::free_balance(&10), 1); - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![])); - assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Staking::free_balance(&10), 1); - assert!(Staking::forcing_new_era().is_none()); - }); -} - -#[test] -fn note_missed_proposal_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - Staking::set_free_balance(&10, 70); - assert_eq!(Staking::offline_slash_grace(), 0); - assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Staking::free_balance(&10), 70); - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); - assert_eq!(Staking::slash_count(&10), 1); - assert_eq!(Staking::free_balance(&10), 50); - assert!(Staking::forcing_new_era().is_none()); - }); -} - -#[test] -fn note_missed_proposal_exponent_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - Staking::set_free_balance(&10, 150); - assert_eq!(Staking::offline_slash_grace(), 0); - assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Staking::free_balance(&10), 150); - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); - assert_eq!(Staking::slash_count(&10), 1); - assert_eq!(Staking::free_balance(&10), 130); - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); - assert_eq!(Staking::slash_count(&10), 2); - assert_eq!(Staking::free_balance(&10), 90); - assert!(Staking::forcing_new_era().is_none()); - }); -} - -#[test] -fn note_missed_proposal_grace_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - Staking::set_free_balance(&10, 70); - Staking::set_free_balance(&20, 70); - assert_ok!(Staking::set_offline_slash_grace(1)); - assert_eq!(Staking::offline_slash_grace(), 1); - - assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Staking::free_balance(&10), 70); - - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); - assert_eq!(Staking::slash_count(&10), 1); - assert_eq!(Staking::free_balance(&10), 70); - assert_eq!(Staking::slash_count(&20), 0); - assert_eq!(Staking::free_balance(&20), 70); - - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); - assert_eq!(Staking::slash_count(&10), 2); - assert_eq!(Staking::free_balance(&10), 50); - assert_eq!(Staking::slash_count(&20), 1); - assert_eq!(Staking::free_balance(&20), 70); - assert!(Staking::forcing_new_era().is_none()); - }); -} - -#[test] -fn note_missed_proposal_force_unstake_session_change_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - Staking::set_free_balance(&10, 70); - Staking::set_free_balance(&20, 70); - assert_ok!(Staking::stake(&1)); - - assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Staking::free_balance(&10), 70); - assert_eq!(Staking::intentions(), vec![10, 20, 1]); - assert_eq!(Session::validators(), vec![10, 20]); - - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); - assert_eq!(Staking::free_balance(&10), 50); - assert_eq!(Staking::slash_count(&10), 1); - assert_eq!(Staking::intentions(), vec![10, 20, 1]); - - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); - assert_eq!(Staking::intentions(), vec![1, 20]); - assert_eq!(Staking::free_balance(&10), 10); - assert!(Staking::forcing_new_era().is_some()); - }); -} - -#[test] -fn note_missed_proposal_auto_unstake_session_change_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - Staking::set_free_balance(&10, 7000); - Staking::set_free_balance(&20, 7000); - assert_ok!(Staking::register_slash_preference(&10, 0, SlashPreference { unstake_threshold: 1 })); - - assert_eq!(Staking::intentions(), vec![10, 20]); - - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); - assert_eq!(Staking::free_balance(&10), 6980); - assert_eq!(Staking::free_balance(&20), 6980); - assert_eq!(Staking::intentions(), vec![10, 20]); - assert!(Staking::forcing_new_era().is_none()); - - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); - assert_eq!(Staking::free_balance(&10), 6940); - assert_eq!(Staking::free_balance(&20), 6940); - assert_eq!(Staking::intentions(), vec![20]); - assert!(Staking::forcing_new_era().is_some()); - - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![1])); - assert_eq!(Staking::free_balance(&10), 6940); - assert_eq!(Staking::free_balance(&20), 6860); - assert_eq!(Staking::intentions(), vec![20]); - - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![1])); - assert_eq!(Staking::free_balance(&10), 6940); - assert_eq!(Staking::free_balance(&20), 6700); - assert_eq!(Staking::intentions(), vec![0u64; 0]); - }); -} +use mock::{Session, Balances, System, Timestamp, Test, new_test_ext}; #[test] fn reward_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - assert_eq!(Staking::voting_balance(&10), 1); - assert_ok!(Staking::reward(&10, 10)); - assert_eq!(Staking::voting_balance(&10), 11); + assert_eq!(Balances::voting_balance(&10), 1); + assert_ok!(Balances::reward(&10, 10)); + assert_eq!(Balances::voting_balance(&10), 11); assert_eq!(>::get(), 112); }); } -#[test] -fn rewards_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - assert_eq!(Staking::era_length(), 9); - assert_eq!(Staking::sessions_per_era(), 3); - assert_eq!(Staking::last_era_length_change(), 0); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 0); - assert_eq!(Staking::voting_balance(&10), 1); - - System::set_block_number(3); - Timestamp::set_timestamp(15); // on time. - Session::check_rotate_session(); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 1); - assert_eq!(Staking::voting_balance(&10), 11); - System::set_block_number(6); - Timestamp::set_timestamp(31); // a little late - Session::check_rotate_session(); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 2); - assert_eq!(Staking::voting_balance(&10), 20); // less reward - System::set_block_number(9); - Timestamp::set_timestamp(50); // very late - Session::check_rotate_session(); - assert_eq!(Staking::current_era(), 1); - assert_eq!(Session::current_index(), 3); - assert_eq!(Staking::voting_balance(&10), 27); // much less reward - }); -} - -#[test] -fn slashing_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - assert_eq!(Staking::era_length(), 9); - assert_eq!(Staking::sessions_per_era(), 3); - assert_eq!(Staking::last_era_length_change(), 0); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 0); - assert_eq!(Staking::voting_balance(&10), 1); - - System::set_block_number(3); - Session::check_rotate_session(); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 1); - assert_eq!(Staking::voting_balance(&10), 11); - - System::set_block_number(6); - Session::check_rotate_session(); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 2); - assert_eq!(Staking::voting_balance(&10), 21); - - System::set_block_number(7); - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); - assert_eq!(Staking::voting_balance(&10), 1); - }); -} - #[test] fn indexing_lookup_should_work() { with_externalities(&mut new_test_ext(10, 1, 2, 0, true, 0), || { - assert_eq!(Staking::lookup_index(0), Some(1)); - assert_eq!(Staking::lookup_index(1), Some(2)); - assert_eq!(Staking::lookup_index(2), Some(3)); - assert_eq!(Staking::lookup_index(3), Some(4)); - assert_eq!(Staking::lookup_index(4), None); + assert_eq!(Balances::lookup_index(0), Some(1)); + assert_eq!(Balances::lookup_index(1), Some(2)); + assert_eq!(Balances::lookup_index(2), Some(3)); + assert_eq!(Balances::lookup_index(3), Some(4)); + assert_eq!(Balances::lookup_index(4), None); }); } #[test] fn default_indexing_on_new_accounts_should_work() { with_externalities(&mut new_test_ext(10, 1, 2, 0, true, 0), || { - assert_eq!(Staking::lookup_index(4), None); - assert_ok!(Staking::transfer(&1, 5.into(), 10)); - assert_eq!(Staking::lookup_index(4), Some(5)); + assert_eq!(Balances::lookup_index(4), None); + assert_ok!(Balances::transfer(&1, 5.into(), 10)); + assert_eq!(Balances::lookup_index(4), Some(5)); }); } @@ -256,11 +57,11 @@ fn dust_account_removal_should_work() { with_externalities(&mut new_test_ext(256 * 10, 1, 2, 0, true, 0), || { System::inc_account_nonce(&2); assert_eq!(System::account_nonce(&2), 1); - assert_eq!(Staking::voting_balance(&2), 256 * 20); + assert_eq!(Balances::voting_balance(&2), 256 * 20); - assert_ok!(Staking::transfer(&2, 5.into(), 256 * 10 + 1)); // index 1 (account 2) becomes zombie - assert_eq!(Staking::voting_balance(&2), 0); - assert_eq!(Staking::voting_balance(&5), 256 * 10 + 1); + assert_ok!(Balances::transfer(&2, 5.into(), 256 * 10 + 1)); // index 1 (account 2) becomes zombie + assert_eq!(Balances::voting_balance(&2), 0); + assert_eq!(Balances::voting_balance(&5), 256 * 10 + 1); assert_eq!(System::account_nonce(&2), 0); }); } @@ -268,16 +69,16 @@ fn dust_account_removal_should_work() { #[test] fn reclaim_indexing_on_new_accounts_should_work() { with_externalities(&mut new_test_ext(256 * 1, 1, 2, 0, true, 0), || { - assert_eq!(Staking::lookup_index(1), Some(2)); - assert_eq!(Staking::lookup_index(4), None); - assert_eq!(Staking::voting_balance(&2), 256 * 20); + assert_eq!(Balances::lookup_index(1), Some(2)); + assert_eq!(Balances::lookup_index(4), None); + assert_eq!(Balances::voting_balance(&2), 256 * 20); - assert_ok!(Staking::transfer(&2, 5.into(), 256 * 20)); // account 2 becomes zombie freeing index 1 for reclaim) - assert_eq!(Staking::voting_balance(&2), 0); + assert_ok!(Balances::transfer(&2, 5.into(), 256 * 20)); // account 2 becomes zombie freeing index 1 for reclaim) + assert_eq!(Balances::voting_balance(&2), 0); - assert_ok!(Staking::transfer(&5, 6.into(), 256 * 1 + 0x69)); // account 6 takes index 1. - assert_eq!(Staking::voting_balance(&6), 256 * 1 + 0x69); - assert_eq!(Staking::lookup_index(1), Some(6)); + assert_ok!(Balances::transfer(&5, 6.into(), 256 * 1 + 0x69)); // account 6 takes index 1. + assert_eq!(Balances::voting_balance(&6), 256 * 1 + 0x69); + assert_eq!(Balances::lookup_index(1), Some(6)); }); } @@ -285,356 +86,109 @@ fn reclaim_indexing_on_new_accounts_should_work() { fn reserved_balance_should_prevent_reclaim_count() { with_externalities(&mut new_test_ext(256 * 1, 1, 2, 0, true, 0), || { System::inc_account_nonce(&2); - assert_eq!(Staking::lookup_index(1), Some(2)); - assert_eq!(Staking::lookup_index(4), None); - assert_eq!(Staking::voting_balance(&2), 256 * 20); + assert_eq!(Balances::lookup_index(1), Some(2)); + assert_eq!(Balances::lookup_index(4), None); + assert_eq!(Balances::voting_balance(&2), 256 * 20); - assert_ok!(Staking::reserve(&2, 256 * 19 + 1)); // account 2 becomes mostly reserved - assert_eq!(Staking::free_balance(&2), 0); // "free" account deleted." - assert_eq!(Staking::voting_balance(&2), 256 * 19 + 1); // reserve still exists. + assert_ok!(Balances::reserve(&2, 256 * 19 + 1)); // account 2 becomes mostly reserved + assert_eq!(Balances::free_balance(&2), 0); // "free" account deleted." + assert_eq!(Balances::voting_balance(&2), 256 * 19 + 1); // reserve still exists. assert_eq!(System::account_nonce(&2), 1); - assert_ok!(Staking::transfer(&4, 5.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 for account 5. - assert_eq!(Staking::voting_balance(&5), 256 * 1 + 0x69); - assert_eq!(Staking::lookup_index(1), Some(2)); // but fails. + assert_ok!(Balances::transfer(&4, 5.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 for account 5. + assert_eq!(Balances::voting_balance(&5), 256 * 1 + 0x69); + assert_eq!(Balances::lookup_index(1), Some(2)); // but fails. assert_eq!(System::account_nonce(&2), 1); - assert_eq!(Staking::slash(&2, 256 * 18 + 2), None); // account 2 gets slashed - assert_eq!(Staking::voting_balance(&2), 0); // "free" account deleted." + assert_eq!(Balances::slash(&2, 256 * 18 + 2), None); // account 2 gets slashed + assert_eq!(Balances::voting_balance(&2), 0); // "free" account deleted." assert_eq!(System::account_nonce(&2), 0); - assert_ok!(Staking::transfer(&4, 6.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 again for account 6. - assert_eq!(Staking::voting_balance(&6), 256 * 1 + 0x69); - assert_eq!(Staking::lookup_index(1), Some(6)); // and succeeds. - }); -} - -#[test] -fn staking_should_work() { - with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { - assert_eq!(Staking::era_length(), 2); - assert_eq!(Staking::validator_count(), 2); - assert_eq!(Staking::bonding_duration(), 3); - assert_eq!(Session::validators(), vec![10, 20]); - - // Block 1: Add three validators. No obvious change. - System::set_block_number(1); - assert_ok!(Staking::stake(&1)); - assert_ok!(Staking::stake(&2)); - assert_ok!(Staking::stake(&4)); - Session::check_rotate_session(); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::validators(), vec![10, 20]); - - // Block 2: New validator set now. - System::set_block_number(2); - Session::check_rotate_session(); - assert_eq!(Staking::current_era(), 1); - assert_eq!(Session::validators(), vec![4, 2]); - - // Block 3: Unstake highest, introduce another staker. No change yet. - System::set_block_number(3); - assert_ok!(Staking::stake(&3)); - assert_ok!(Staking::unstake(&4, Staking::intentions().iter().position(|&x| x == 4).unwrap() as u32)); - assert_eq!(Staking::current_era(), 1); - Session::check_rotate_session(); - - // Block 4: New era - validators change. - System::set_block_number(4); - Session::check_rotate_session(); - assert_eq!(Staking::current_era(), 2); - assert_eq!(Session::validators(), vec![3, 2]); - - // Block 5: Transfer stake from highest to lowest. No change yet. - System::set_block_number(5); - assert_ok!(Staking::transfer(&4, 1.into(), 40)); - Session::check_rotate_session(); - - // Block 6: Lowest now validator. - System::set_block_number(6); - Session::check_rotate_session(); - assert_eq!(Session::validators(), vec![1, 3]); - - // Block 7: Unstake three. No change yet. - System::set_block_number(7); - assert_ok!(Staking::unstake(&3, Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32)); - Session::check_rotate_session(); - assert_eq!(Session::validators(), vec![1, 3]); - - // Block 8: Back to one and two. - System::set_block_number(8); - Session::check_rotate_session(); - assert_eq!(Session::validators(), vec![1, 2]); - }); -} - -#[test] -fn nominating_and_rewards_should_work() { - with_externalities(&mut new_test_ext(0, 1, 1, 0, true, 10), || { - assert_eq!(Staking::era_length(), 1); - assert_eq!(Staking::validator_count(), 2); - assert_eq!(Staking::bonding_duration(), 3); - assert_eq!(Session::validators(), vec![10, 20]); - - System::set_block_number(1); - assert_ok!(Staking::stake(&1)); - assert_ok!(Staking::stake(&2)); - assert_ok!(Staking::stake(&3)); - assert_ok!(Staking::nominate(&4, 1.into())); - Session::check_rotate_session(); - assert_eq!(Staking::current_era(), 1); - assert_eq!(Session::validators(), vec![1, 3]); // 4 + 1, 3 - assert_eq!(Staking::voting_balance(&1), 10); - assert_eq!(Staking::voting_balance(&2), 20); - assert_eq!(Staking::voting_balance(&3), 30); - assert_eq!(Staking::voting_balance(&4), 40); - - System::set_block_number(2); - assert_ok!(Staking::unnominate(&4, 0)); - Session::check_rotate_session(); - assert_eq!(Staking::current_era(), 2); - assert_eq!(Session::validators(), vec![3, 2]); - assert_eq!(Staking::voting_balance(&1), 12); - assert_eq!(Staking::voting_balance(&2), 20); - assert_eq!(Staking::voting_balance(&3), 40); - assert_eq!(Staking::voting_balance(&4), 48); - - System::set_block_number(3); - assert_ok!(Staking::stake(&4)); - assert_ok!(Staking::unstake(&3, Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32)); - assert_ok!(Staking::nominate(&3, 1.into())); - Session::check_rotate_session(); - assert_eq!(Session::validators(), vec![1, 4]); - assert_eq!(Staking::voting_balance(&1), 12); - assert_eq!(Staking::voting_balance(&2), 30); - assert_eq!(Staking::voting_balance(&3), 50); - assert_eq!(Staking::voting_balance(&4), 48); - - System::set_block_number(4); - Session::check_rotate_session(); - assert_eq!(Staking::voting_balance(&1), 13); - assert_eq!(Staking::voting_balance(&2), 30); - assert_eq!(Staking::voting_balance(&3), 58); - assert_eq!(Staking::voting_balance(&4), 58); - }); -} - -#[test] -fn nominating_slashes_should_work() { - with_externalities(&mut new_test_ext(0, 2, 2, 0, true, 10), || { - assert_eq!(Staking::era_length(), 4); - assert_eq!(Staking::validator_count(), 2); - assert_eq!(Staking::bonding_duration(), 3); - assert_eq!(Session::validators(), vec![10, 20]); - - System::set_block_number(2); - Session::check_rotate_session(); - - Timestamp::set_timestamp(15); - System::set_block_number(4); - assert_ok!(Staking::stake(&1)); - assert_ok!(Staking::stake(&3)); - assert_ok!(Staking::nominate(&2, 3.into())); - assert_ok!(Staking::nominate(&4, 1.into())); - Session::check_rotate_session(); - - assert_eq!(Staking::current_era(), 1); - assert_eq!(Session::validators(), vec![1, 3]); // 1 + 4, 3 + 2 - assert_eq!(Staking::voting_balance(&1), 10); - assert_eq!(Staking::voting_balance(&2), 20); - assert_eq!(Staking::voting_balance(&3), 30); - assert_eq!(Staking::voting_balance(&4), 40); - - System::set_block_number(5); - ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); - assert_eq!(Staking::voting_balance(&1), 0); - assert_eq!(Staking::voting_balance(&2), 20); - assert_eq!(Staking::voting_balance(&3), 10); - assert_eq!(Staking::voting_balance(&4), 30); - }); -} - -#[test] -fn double_staking_should_fail() { - with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { - System::set_block_number(1); - assert_ok!(Staking::stake(&1)); - assert_noop!(Staking::stake(&1), "Cannot stake if already staked."); - assert_noop!(Staking::nominate(&1, 1.into()), "Cannot nominate if already staked."); - assert_ok!(Staking::nominate(&2, 1.into())); - assert_noop!(Staking::stake(&2), "Cannot stake if already nominating."); - assert_noop!(Staking::nominate(&2, 1.into()), "Cannot nominate if already nominating."); - }); -} - -#[test] -fn staking_eras_work() { - with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { - assert_eq!(Staking::era_length(), 2); - assert_eq!(Staking::sessions_per_era(), 2); - assert_eq!(Staking::last_era_length_change(), 0); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 0); - - // Block 1: No change. - System::set_block_number(1); - Session::check_rotate_session(); - assert_eq!(Session::current_index(), 1); - assert_eq!(Staking::sessions_per_era(), 2); - assert_eq!(Staking::last_era_length_change(), 0); - assert_eq!(Staking::current_era(), 0); - - // Block 2: Simple era change. - System::set_block_number(2); - Session::check_rotate_session(); - assert_eq!(Session::current_index(), 2); - assert_eq!(Staking::sessions_per_era(), 2); - assert_eq!(Staking::last_era_length_change(), 0); - assert_eq!(Staking::current_era(), 1); - - // Block 3: Schedule an era length change; no visible changes. - System::set_block_number(3); - assert_ok!(Staking::set_sessions_per_era(3)); - Session::check_rotate_session(); - assert_eq!(Session::current_index(), 3); - assert_eq!(Staking::sessions_per_era(), 2); - assert_eq!(Staking::last_era_length_change(), 0); - assert_eq!(Staking::current_era(), 1); - - // Block 4: Era change kicks in. - System::set_block_number(4); - Session::check_rotate_session(); - assert_eq!(Session::current_index(), 4); - assert_eq!(Staking::sessions_per_era(), 3); - assert_eq!(Staking::last_era_length_change(), 4); - assert_eq!(Staking::current_era(), 2); - - // Block 5: No change. - System::set_block_number(5); - Session::check_rotate_session(); - assert_eq!(Session::current_index(), 5); - assert_eq!(Staking::sessions_per_era(), 3); - assert_eq!(Staking::last_era_length_change(), 4); - assert_eq!(Staking::current_era(), 2); - - // Block 6: No change. - System::set_block_number(6); - Session::check_rotate_session(); - assert_eq!(Session::current_index(), 6); - assert_eq!(Staking::sessions_per_era(), 3); - assert_eq!(Staking::last_era_length_change(), 4); - assert_eq!(Staking::current_era(), 2); - - // Block 7: Era increment. - System::set_block_number(7); - Session::check_rotate_session(); - assert_eq!(Session::current_index(), 7); - assert_eq!(Staking::sessions_per_era(), 3); - assert_eq!(Staking::last_era_length_change(), 4); - assert_eq!(Staking::current_era(), 3); - }); -} - -#[test] -fn staking_balance_works() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 42); - assert_eq!(Staking::free_balance(&1), 42); - assert_eq!(Staking::reserved_balance(&1), 0); - assert_eq!(Staking::voting_balance(&1), 42); - assert_eq!(Staking::free_balance(&2), 0); - assert_eq!(Staking::reserved_balance(&2), 0); - assert_eq!(Staking::voting_balance(&2), 0); + assert_ok!(Balances::transfer(&4, 6.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 again for account 6. + assert_eq!(Balances::voting_balance(&6), 256 * 1 + 0x69); + assert_eq!(Balances::lookup_index(1), Some(6)); // and succeeds. }); } #[test] -fn staking_balance_transfer_works() { +fn balance_works() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - Staking::increase_total_stake_by(111); - assert_ok!(Staking::transfer(&1, 2.into(), 69)); - assert_eq!(Staking::voting_balance(&1), 42); - assert_eq!(Staking::voting_balance(&2), 69); + Balances::set_free_balance(&1, 42); + assert_eq!(Balances::free_balance(&1), 42); + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::voting_balance(&1), 42); + assert_eq!(Balances::free_balance(&2), 0); + assert_eq!(Balances::reserved_balance(&2), 0); + assert_eq!(Balances::voting_balance(&2), 0); }); } #[test] -fn staking_balance_transfer_when_bonded_should_not_work() { +fn balance_transfer_works() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - assert_ok!(Staking::stake(&1)); - assert_noop!(Staking::transfer(&1, 2.into(), 69), "bondage too high to send value"); + Balances::set_free_balance(&1, 111); + Balances::increase_total_stake_by(111); + assert_ok!(Balances::transfer(&1, 2.into(), 69)); + assert_eq!(Balances::voting_balance(&1), 42); + assert_eq!(Balances::voting_balance(&2), 69); }); } #[test] fn reserving_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); + Balances::set_free_balance(&1, 111); - assert_eq!(Staking::voting_balance(&1), 111); - assert_eq!(Staking::free_balance(&1), 111); - assert_eq!(Staking::reserved_balance(&1), 0); + assert_eq!(Balances::voting_balance(&1), 111); + assert_eq!(Balances::free_balance(&1), 111); + assert_eq!(Balances::reserved_balance(&1), 0); - assert_ok!(Staking::reserve(&1, 69)); + assert_ok!(Balances::reserve(&1, 69)); - assert_eq!(Staking::voting_balance(&1), 111); - assert_eq!(Staking::free_balance(&1), 42); - assert_eq!(Staking::reserved_balance(&1), 69); + assert_eq!(Balances::voting_balance(&1), 111); + assert_eq!(Balances::free_balance(&1), 42); + assert_eq!(Balances::reserved_balance(&1), 69); }); } #[test] -fn staking_balance_transfer_when_reserved_should_not_work() { +fn balance_transfer_when_reserved_should_not_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - assert_ok!(Staking::reserve(&1, 69)); - assert_noop!(Staking::transfer(&1, 2.into(), 69), "balance too low to send value"); + Balances::set_free_balance(&1, 111); + assert_ok!(Balances::reserve(&1, 69)); + assert_noop!(Balances::transfer(&1, 2.into(), 69), "balance too low to send value"); }); } #[test] fn deducting_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - assert_ok!(Staking::reserve(&1, 69)); - assert_eq!(Staking::free_balance(&1), 42); - }); -} - -#[test] -fn deducting_balance_when_bonded_should_not_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - >::insert(1, 2); - System::set_block_number(1); - assert_eq!(Staking::unlock_block(&1), LockStatus::LockedUntil(2)); - assert_noop!(Staking::reserve(&1, 69), "free funds are still bonded"); + Balances::set_free_balance(&1, 111); + assert_ok!(Balances::reserve(&1, 69)); + assert_eq!(Balances::free_balance(&1), 42); }); } #[test] fn refunding_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 42); - Staking::set_reserved_balance(&1, 69); - Staking::unreserve(&1, 69); - assert_eq!(Staking::free_balance(&1), 111); - assert_eq!(Staking::reserved_balance(&1), 0); + Balances::set_free_balance(&1, 42); + Balances::set_reserved_balance(&1, 69); + Balances::unreserve(&1, 69); + assert_eq!(Balances::free_balance(&1), 111); + assert_eq!(Balances::reserved_balance(&1), 0); }); } #[test] fn slashing_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - Staking::increase_total_stake_by(111); - assert_ok!(Staking::reserve(&1, 69)); - assert!(Staking::slash(&1, 69).is_none()); - assert_eq!(Staking::free_balance(&1), 0); - assert_eq!(Staking::reserved_balance(&1), 42); + Balances::set_free_balance(&1, 111); + Balances::increase_total_stake_by(111); + assert_ok!(Balances::reserve(&1, 69)); + assert!(Balances::slash(&1, 69).is_none()); + assert_eq!(Balances::free_balance(&1), 0); + assert_eq!(Balances::reserved_balance(&1), 42); assert_eq!(>::get(), 44); }); } @@ -642,12 +196,12 @@ fn slashing_balance_should_work() { #[test] fn slashing_incomplete_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 42); - Staking::increase_total_stake_by(42); - assert_ok!(Staking::reserve(&1, 21)); - assert!(Staking::slash(&1, 69).is_some()); - assert_eq!(Staking::free_balance(&1), 0); - assert_eq!(Staking::reserved_balance(&1), 0); + Balances::set_free_balance(&1, 42); + Balances::increase_total_stake_by(42); + assert_ok!(Balances::reserve(&1, 21)); + assert!(Balances::slash(&1, 69).is_some()); + assert_eq!(Balances::free_balance(&1), 0); + assert_eq!(Balances::reserved_balance(&1), 0); assert_eq!(>::get(), 2); }); } @@ -655,23 +209,23 @@ fn slashing_incomplete_balance_should_work() { #[test] fn unreserving_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - assert_ok!(Staking::reserve(&1, 111)); - Staking::unreserve(&1, 42); - assert_eq!(Staking::reserved_balance(&1), 69); - assert_eq!(Staking::free_balance(&1), 42); + Balances::set_free_balance(&1, 111); + assert_ok!(Balances::reserve(&1, 111)); + Balances::unreserve(&1, 42); + assert_eq!(Balances::reserved_balance(&1), 69); + assert_eq!(Balances::free_balance(&1), 42); }); } #[test] fn slashing_reserved_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - Staking::increase_total_stake_by(111); - assert_ok!(Staking::reserve(&1, 111)); - assert!(Staking::slash_reserved(&1, 42).is_none()); - assert_eq!(Staking::reserved_balance(&1), 69); - assert_eq!(Staking::free_balance(&1), 0); + Balances::set_free_balance(&1, 111); + Balances::increase_total_stake_by(111); + assert_ok!(Balances::reserve(&1, 111)); + assert!(Balances::slash_reserved(&1, 42).is_none()); + assert_eq!(Balances::reserved_balance(&1), 69); + assert_eq!(Balances::free_balance(&1), 0); assert_eq!(>::get(), 71); }); } @@ -679,12 +233,12 @@ fn slashing_reserved_balance_should_work() { #[test] fn slashing_incomplete_reserved_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - Staking::increase_total_stake_by(111); - assert_ok!(Staking::reserve(&1, 42)); - assert!(Staking::slash_reserved(&1, 69).is_some()); - assert_eq!(Staking::free_balance(&1), 69); - assert_eq!(Staking::reserved_balance(&1), 0); + Balances::set_free_balance(&1, 111); + Balances::increase_total_stake_by(111); + assert_ok!(Balances::reserve(&1, 42)); + assert!(Balances::slash_reserved(&1, 69).is_some()); + assert_eq!(Balances::free_balance(&1), 69); + assert_eq!(Balances::reserved_balance(&1), 0); assert_eq!(>::get(), 71); }); } @@ -692,37 +246,37 @@ fn slashing_incomplete_reserved_balance_should_work() { #[test] fn transferring_reserved_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 110); - Staking::set_free_balance(&2, 1); - assert_ok!(Staking::reserve(&1, 110)); - assert_ok!(Staking::transfer_reserved(&1, &2, 41), None); - assert_eq!(Staking::reserved_balance(&1), 69); - assert_eq!(Staking::free_balance(&1), 0); - assert_eq!(Staking::reserved_balance(&2), 0); - assert_eq!(Staking::free_balance(&2), 42); + Balances::set_free_balance(&1, 110); + Balances::set_free_balance(&2, 1); + assert_ok!(Balances::reserve(&1, 110)); + assert_ok!(Balances::transfer_reserved(&1, &2, 41), None); + assert_eq!(Balances::reserved_balance(&1), 69); + assert_eq!(Balances::free_balance(&1), 0); + assert_eq!(Balances::reserved_balance(&2), 0); + assert_eq!(Balances::free_balance(&2), 42); }); } #[test] fn transferring_reserved_balance_to_nonexistent_should_fail() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - assert_ok!(Staking::reserve(&1, 111)); - assert_noop!(Staking::transfer_reserved(&1, &2, 42), "beneficiary account must pre-exist"); + Balances::set_free_balance(&1, 111); + assert_ok!(Balances::reserve(&1, 111)); + assert_noop!(Balances::transfer_reserved(&1, &2, 42), "beneficiary account must pre-exist"); }); } #[test] fn transferring_incomplete_reserved_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 110); - Staking::set_free_balance(&2, 1); - assert_ok!(Staking::reserve(&1, 41)); - assert!(Staking::transfer_reserved(&1, &2, 69).unwrap().is_some()); - assert_eq!(Staking::reserved_balance(&1), 0); - assert_eq!(Staking::free_balance(&1), 69); - assert_eq!(Staking::reserved_balance(&2), 0); - assert_eq!(Staking::free_balance(&2), 42); + Balances::set_free_balance(&1, 110); + Balances::set_free_balance(&2, 1); + assert_ok!(Balances::reserve(&1, 41)); + assert!(Balances::transfer_reserved(&1, &2, 69).unwrap().is_some()); + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::free_balance(&1), 69); + assert_eq!(Balances::reserved_balance(&2), 0); + assert_eq!(Balances::free_balance(&2), 42); }); } @@ -733,12 +287,12 @@ fn transferring_too_high_value_should_not_panic() { >::insert(2, 1); assert_err!( - Staking::transfer(&1, 2.into(), u64::max_value()), + Balances::transfer(&1, 2.into(), u64::max_value()), "destination balance too high to receive value" ); - assert_eq!(Staking::free_balance(&1), u64::max_value()); - assert_eq!(Staking::free_balance(&2), 1); + assert_eq!(Balances::free_balance(&1), u64::max_value()); + assert_eq!(Balances::free_balance(&2), 1); }); } @@ -747,11 +301,11 @@ fn account_removal_on_free_too_low() { with_externalities(&mut new_test_ext(100, 1, 3, 1, false, 0), || { // Setup two accounts with free balance above the exsistential threshold. { - Staking::set_free_balance(&1, 110); - Staking::increase_total_stake_by(110); + Balances::set_free_balance(&1, 110); + Balances::increase_total_stake_by(110); - Staking::set_free_balance(&2, 110); - Staking::increase_total_stake_by(110); + Balances::set_free_balance(&2, 110); + Balances::increase_total_stake_by(110); assert_eq!(>::get(), 732); } @@ -759,10 +313,10 @@ fn account_removal_on_free_too_low() { // Transfer funds from account 1 of such amount that after this transfer // the balance of account 1 will be below the exsistential threshold. // This should lead to the removal of all balance of this account. - assert_ok!(Staking::transfer(&1, 2.into(), 20)); + assert_ok!(Balances::transfer(&1, 2.into(), 20)); // Verify free balance removal of account 1. - assert_eq!(Staking::free_balance(&1), 0); + assert_eq!(Balances::free_balance(&1), 0); // Verify that TotalStake tracks balance removal when free balance is too low. assert_eq!(>::get(), 642); From 8d5e964864a8931cc2fd7aefc9f4d95c6318c6bd Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 29 Aug 2018 19:41:09 +0200 Subject: [PATCH 03/19] Minimise Balances trait requirements --- demo/runtime/src/lib.rs | 2 +- substrate/runtime/balances/src/lib.rs | 2 +- substrate/runtime/balances/src/mock.rs | 2 +- substrate/runtime/consensus/src/lib.rs | 1 - substrate/runtime/contract/src/tests.rs | 2 +- substrate/runtime/council/src/lib.rs | 2 +- substrate/runtime/democracy/src/lib.rs | 2 +- substrate/runtime/executive/src/lib.rs | 2 +- substrate/runtime/session/src/lib.rs | 2 +- substrate/runtime/staking/src/mock.rs | 2 +- substrate/runtime/system/src/lib.rs | 3 ++- substrate/runtime/timestamp/src/lib.rs | 4 ++-- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/demo/runtime/src/lib.rs b/demo/runtime/src/lib.rs index 46101f8463595..a672ef105bd1e 100644 --- a/demo/runtime/src/lib.rs +++ b/demo/runtime/src/lib.rs @@ -88,6 +88,7 @@ impl HasPublicAux for Concrete { } impl system::Trait for Concrete { + type PublicAux = ::PublicAux; type Index = Index; type BlockNumber = BlockNumber; type Hash = Hash; @@ -102,7 +103,6 @@ impl system::Trait for Concrete { pub type System = system::Module; impl consensus::Trait for Concrete { - type PublicAux = ::PublicAux; type SessionKey = SessionKey; } diff --git a/substrate/runtime/balances/src/lib.rs b/substrate/runtime/balances/src/lib.rs index 1130182e04ae2..fc0b5922cfbf2 100644 --- a/substrate/runtime/balances/src/lib.rs +++ b/substrate/runtime/balances/src/lib.rs @@ -117,7 +117,7 @@ impl IsAccountLiquid for () { fn is_account_liquid(_who: &AccountId) -> bool { true } } -pub trait Trait: system::Trait + session::Trait { +pub trait Trait: system::Trait { /// The balance of an account. type Balance: Parameter + SimpleArithmetic + Codec + Default + Copy + As + As + As; /// Type used for storing an account's index; implies the maximum number of accounts the system diff --git a/substrate/runtime/balances/src/mock.rs b/substrate/runtime/balances/src/mock.rs index ba9cf0ead7f60..654f64dc6e09b 100644 --- a/substrate/runtime/balances/src/mock.rs +++ b/substrate/runtime/balances/src/mock.rs @@ -32,10 +32,10 @@ impl HasPublicAux for Test { type PublicAux = u64; } impl consensus::Trait for Test { - type PublicAux = ::PublicAux; type SessionKey = u64; } impl system::Trait for Test { + type PublicAux = ::PublicAux; type Index = u64; type BlockNumber = u64; type Hash = H256; diff --git a/substrate/runtime/consensus/src/lib.rs b/substrate/runtime/consensus/src/lib.rs index 3b9e2554b4631..3540980ead214 100644 --- a/substrate/runtime/consensus/src/lib.rs +++ b/substrate/runtime/consensus/src/lib.rs @@ -64,7 +64,6 @@ pub const CODE: &'static [u8] = b":code"; pub type KeyValue = (Vec, Vec); pub trait Trait: system::Trait { - type PublicAux: RefInto + MaybeEmpty; // MaybeEmpty is for Timestamp's usage. type SessionKey: Parameter + Default + MaybeSerializeDebug; } diff --git a/substrate/runtime/contract/src/tests.rs b/substrate/runtime/contract/src/tests.rs index 5f1014243a046..69b85b9f4707f 100644 --- a/substrate/runtime/contract/src/tests.rs +++ b/substrate/runtime/contract/src/tests.rs @@ -33,10 +33,10 @@ impl HasPublicAux for Test { type PublicAux = u64; } impl consensus::Trait for Test { - type PublicAux = ::PublicAux; type SessionKey = u64; } impl system::Trait for Test { + type PublicAux = ::PublicAux; type Index = u64; type BlockNumber = u64; type Hash = H256; diff --git a/substrate/runtime/council/src/lib.rs b/substrate/runtime/council/src/lib.rs index 103679e8a7f0f..68eab58ac472a 100644 --- a/substrate/runtime/council/src/lib.rs +++ b/substrate/runtime/council/src/lib.rs @@ -641,10 +641,10 @@ mod tests { type PublicAux = u64; } impl consensus::Trait for Test { - type PublicAux = ::PublicAux; type SessionKey = u64; } impl system::Trait for Test { + type PublicAux = ::PublicAux; type Index = u64; type BlockNumber = u64; type Hash = H256; diff --git a/substrate/runtime/democracy/src/lib.rs b/substrate/runtime/democracy/src/lib.rs index bc04fe877acd0..da239061e57c1 100644 --- a/substrate/runtime/democracy/src/lib.rs +++ b/substrate/runtime/democracy/src/lib.rs @@ -383,10 +383,10 @@ mod tests { type PublicAux = u64; } impl consensus::Trait for Test { - type PublicAux = ::PublicAux; type SessionKey = u64; } impl system::Trait for Test { + type PublicAux = ::PublicAux; type Index = u64; type BlockNumber = u64; type Hash = H256; diff --git a/substrate/runtime/executive/src/lib.rs b/substrate/runtime/executive/src/lib.rs index 4f7d6bd27822e..e0334aa35b3cc 100644 --- a/substrate/runtime/executive/src/lib.rs +++ b/substrate/runtime/executive/src/lib.rs @@ -253,10 +253,10 @@ mod tests { type PublicAux = u64; } impl consensus::Trait for Test { - type PublicAux = ::PublicAux; type SessionKey = u64; } impl system::Trait for Test { + type PublicAux = ::PublicAux; type Index = u64; type BlockNumber = u64; type Hash = substrate_primitives::H256; diff --git a/substrate/runtime/session/src/lib.rs b/substrate/runtime/session/src/lib.rs index 1530723907086..053c82cb5bb45 100644 --- a/substrate/runtime/session/src/lib.rs +++ b/substrate/runtime/session/src/lib.rs @@ -302,10 +302,10 @@ mod tests { type PublicAux = u64; } impl consensus::Trait for Test { - type PublicAux = ::PublicAux; type SessionKey = u64; } impl system::Trait for Test { + type PublicAux = ::PublicAux; type Index = u64; type BlockNumber = u64; type Hash = H256; diff --git a/substrate/runtime/staking/src/mock.rs b/substrate/runtime/staking/src/mock.rs index 7b3097010d7eb..559cbbdca222b 100644 --- a/substrate/runtime/staking/src/mock.rs +++ b/substrate/runtime/staking/src/mock.rs @@ -32,10 +32,10 @@ impl HasPublicAux for Test { type PublicAux = u64; } impl consensus::Trait for Test { - type PublicAux = ::PublicAux; type SessionKey = u64; } impl system::Trait for Test { + type PublicAux = ::PublicAux; type Index = u64; type BlockNumber = u64; type Hash = H256; diff --git a/substrate/runtime/system/src/lib.rs b/substrate/runtime/system/src/lib.rs index c91799dc93952..ef8b043b15d8d 100644 --- a/substrate/runtime/system/src/lib.rs +++ b/substrate/runtime/system/src/lib.rs @@ -45,7 +45,7 @@ extern crate safe_mix; use rstd::prelude::*; use primitives::traits::{self, CheckEqual, SimpleArithmetic, SimpleBitOps, Zero, One, Bounded, - Hash, Member, MaybeDisplay}; + Hash, Member, MaybeDisplay, RefInto, MaybeEmpty}; use runtime_support::{StorageValue, StorageMap, Parameter}; use safe_mix::TripletMix; @@ -69,6 +69,7 @@ pub fn extrinsics_data_root(xts: Vec>) -> H::Output { } pub trait Trait: Eq + Clone { + type PublicAux: RefInto + MaybeEmpty; // MaybeEmpty is for Timestamp's usage. type Index: Parameter + Member + Default + MaybeDisplay + SimpleArithmetic + Copy; type BlockNumber: Parameter + Member + MaybeDisplay + SimpleArithmetic + Default + Bounded + Copy + rstd::hash::Hash; type Hash: Parameter + Member + MaybeDisplay + SimpleBitOps + Default + Copy + CheckEqual + rstd::hash::Hash + AsRef<[u8]>; diff --git a/substrate/runtime/timestamp/src/lib.rs b/substrate/runtime/timestamp/src/lib.rs index db1c7e1281128..e632e8103dc5e 100644 --- a/substrate/runtime/timestamp/src/lib.rs +++ b/substrate/runtime/timestamp/src/lib.rs @@ -43,7 +43,7 @@ use runtime_support::dispatch::Result; use runtime_primitives::traits::{Executable, MaybeEmpty, SimpleArithmetic, As, Zero}; pub trait Trait: consensus::Trait where - ::PublicAux: MaybeEmpty + ::PublicAux: MaybeEmpty { // the position of the required timestamp-set extrinsic. const TIMESTAMP_SET_POSITION: u32; @@ -152,6 +152,7 @@ mod tests { type PublicAux = u64; } impl system::Trait for Test { + type PublicAux = u64; type Index = u64; type BlockNumber = u64; type Hash = H256; @@ -162,7 +163,6 @@ mod tests { type Event = (); } impl consensus::Trait for Test { - type PublicAux = u64; type SessionKey = u64; } impl Trait for Test { From 318fda26ad8134a4893aa2dc154f240c2838cca7 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 29 Aug 2018 21:03:31 +0200 Subject: [PATCH 04/19] Fix up balances, remove balances stuff from staking --- substrate/runtime/balances/src/lib.rs | 3 +- substrate/runtime/balances/src/mock.rs | 28 +- substrate/runtime/balances/src/tests.rs | 54 +- substrate/runtime/contract/src/lib.rs | 3 +- substrate/runtime/staking/src/address.rs | 111 ---- .../runtime/staking/src/genesis_config.rs | 64 +- substrate/runtime/staking/src/lib.rs | 563 +----------------- substrate/runtime/staking/src/mock.rs | 29 +- substrate/runtime/staking/src/tests.rs | 438 +++----------- 9 files changed, 152 insertions(+), 1141 deletions(-) delete mode 100644 substrate/runtime/staking/src/address.rs diff --git a/substrate/runtime/balances/src/lib.rs b/substrate/runtime/balances/src/lib.rs index fc0b5922cfbf2..413e1c674a9f1 100644 --- a/substrate/runtime/balances/src/lib.rs +++ b/substrate/runtime/balances/src/lib.rs @@ -47,7 +47,6 @@ extern crate substrate_runtime_session as session; extern crate substrate_runtime_system as system; extern crate substrate_runtime_timestamp as timestamp; -#[cfg(test)] use std::fmt::Debug; use rstd::prelude::*; use rstd::{cmp, result}; use codec::{Encode, Decode, Codec, Input, Output}; @@ -458,7 +457,7 @@ impl Module { if b < value { return Err("not enough free funds") } - if T::IsAccountLiquid::is_account_liquid(who) { + if !T::IsAccountLiquid::is_account_liquid(who) { return Err("free funds are still bonded") } Self::set_reserved_balance(who, Self::reserved_balance(who) + value); diff --git a/substrate/runtime/balances/src/mock.rs b/substrate/runtime/balances/src/mock.rs index 654f64dc6e09b..c356ef854deef 100644 --- a/substrate/runtime/balances/src/mock.rs +++ b/substrate/runtime/balances/src/mock.rs @@ -19,11 +19,11 @@ #![cfg(test)] use primitives::BuildStorage; -use primitives::traits::{HasPublicAux, Identity}; +use primitives::traits::HasPublicAux; use primitives::testing::{Digest, Header}; use substrate_primitives::{H256, KeccakHasher}; use runtime_io; -use {GenesisConfig, Module, Trait, consensus, session, system, timestamp}; +use {GenesisConfig, Module, Trait, consensus, system}; // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] @@ -45,15 +45,6 @@ impl system::Trait for Test { type Header = Header; type Event = (); } -impl session::Trait for Test { - type ConvertAccountIdToSessionKey = Identity; - type OnSessionChange = Staking; - type Event = (); -} -impl timestamp::Trait for Test { - const TIMESTAMP_SET_POSITION: u32 = 0; - type Moment = u64; -} impl Trait for Test { type Balance = u64; type AccountIndex = u64; @@ -73,17 +64,9 @@ pub fn new_test_ext(ext_deposit: u64, monied: bool) -> runtime_io::TestExternali code: vec![], authorities: vec![], }.build_storage().unwrap()); - t.extend(session::GenesisConfig::{ - session_length, - validators: vec![10, 20], - }.build_storage().unwrap()); t.extend(GenesisConfig::{ balances: if monied { - if reward > 0 { - vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor), (10, balance_factor), (20, balance_factor)] - } else { - vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor)] - } + vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor)] } else { vec![(10, balance_factor), (20, balance_factor)] }, @@ -94,13 +77,8 @@ pub fn new_test_ext(ext_deposit: u64, monied: bool) -> runtime_io::TestExternali creation_fee: 0, reclaim_rebate: 0, }.build_storage().unwrap()); - t.extend(timestamp::GenesisConfig::{ - period: 5 - }.build_storage().unwrap()); t.into() } pub type System = system::Module; -pub type Session = session::Module; -pub type Timestamp = timestamp::Module; pub type Balances = Module; diff --git a/substrate/runtime/balances/src/tests.rs b/substrate/runtime/balances/src/tests.rs index 346950fb52cf0..a78aa6e67825f 100644 --- a/substrate/runtime/balances/src/tests.rs +++ b/substrate/runtime/balances/src/tests.rs @@ -20,21 +20,21 @@ use super::*; use runtime_io::with_externalities; -use mock::{Session, Balances, System, Timestamp, Test, new_test_ext}; +use mock::{Balances, System, Test, new_test_ext}; #[test] fn reward_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - assert_eq!(Balances::voting_balance(&10), 1); - assert_ok!(Balances::reward(&10, 10)); - assert_eq!(Balances::voting_balance(&10), 11); - assert_eq!(>::get(), 112); + with_externalities(&mut new_test_ext(0, true), || { + assert_eq!(Balances::voting_balance(&1), 10); + assert_ok!(Balances::reward(&1, 10)); + assert_eq!(Balances::voting_balance(&1), 20); + assert_eq!(>::get(), 110); }); } #[test] fn indexing_lookup_should_work() { - with_externalities(&mut new_test_ext(10, 1, 2, 0, true, 0), || { + with_externalities(&mut new_test_ext(10, true), || { assert_eq!(Balances::lookup_index(0), Some(1)); assert_eq!(Balances::lookup_index(1), Some(2)); assert_eq!(Balances::lookup_index(2), Some(3)); @@ -45,7 +45,7 @@ fn indexing_lookup_should_work() { #[test] fn default_indexing_on_new_accounts_should_work() { - with_externalities(&mut new_test_ext(10, 1, 2, 0, true, 0), || { + with_externalities(&mut new_test_ext(10, true), || { assert_eq!(Balances::lookup_index(4), None); assert_ok!(Balances::transfer(&1, 5.into(), 10)); assert_eq!(Balances::lookup_index(4), Some(5)); @@ -54,7 +54,7 @@ fn default_indexing_on_new_accounts_should_work() { #[test] fn dust_account_removal_should_work() { - with_externalities(&mut new_test_ext(256 * 10, 1, 2, 0, true, 0), || { + with_externalities(&mut new_test_ext(256 * 10, true), || { System::inc_account_nonce(&2); assert_eq!(System::account_nonce(&2), 1); assert_eq!(Balances::voting_balance(&2), 256 * 20); @@ -68,7 +68,7 @@ fn dust_account_removal_should_work() { #[test] fn reclaim_indexing_on_new_accounts_should_work() { - with_externalities(&mut new_test_ext(256 * 1, 1, 2, 0, true, 0), || { + with_externalities(&mut new_test_ext(256 * 1, true), || { assert_eq!(Balances::lookup_index(1), Some(2)); assert_eq!(Balances::lookup_index(4), None); assert_eq!(Balances::voting_balance(&2), 256 * 20); @@ -84,7 +84,7 @@ fn reclaim_indexing_on_new_accounts_should_work() { #[test] fn reserved_balance_should_prevent_reclaim_count() { - with_externalities(&mut new_test_ext(256 * 1, 1, 2, 0, true, 0), || { + with_externalities(&mut new_test_ext(256 * 1, true), || { System::inc_account_nonce(&2); assert_eq!(Balances::lookup_index(1), Some(2)); assert_eq!(Balances::lookup_index(4), None); @@ -112,7 +112,7 @@ fn reserved_balance_should_prevent_reclaim_count() { #[test] fn balance_works() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 42); assert_eq!(Balances::free_balance(&1), 42); assert_eq!(Balances::reserved_balance(&1), 0); @@ -125,7 +125,7 @@ fn balance_works() { #[test] fn balance_transfer_works() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 111); Balances::increase_total_stake_by(111); assert_ok!(Balances::transfer(&1, 2.into(), 69)); @@ -136,7 +136,7 @@ fn balance_transfer_works() { #[test] fn reserving_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 111); assert_eq!(Balances::voting_balance(&1), 111); @@ -153,7 +153,7 @@ fn reserving_balance_should_work() { #[test] fn balance_transfer_when_reserved_should_not_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 111); assert_ok!(Balances::reserve(&1, 69)); assert_noop!(Balances::transfer(&1, 2.into(), 69), "balance too low to send value"); @@ -162,7 +162,7 @@ fn balance_transfer_when_reserved_should_not_work() { #[test] fn deducting_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 111); assert_ok!(Balances::reserve(&1, 69)); assert_eq!(Balances::free_balance(&1), 42); @@ -171,7 +171,7 @@ fn deducting_balance_should_work() { #[test] fn refunding_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 42); Balances::set_reserved_balance(&1, 69); Balances::unreserve(&1, 69); @@ -182,7 +182,7 @@ fn refunding_balance_should_work() { #[test] fn slashing_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 111); Balances::increase_total_stake_by(111); assert_ok!(Balances::reserve(&1, 69)); @@ -195,7 +195,7 @@ fn slashing_balance_should_work() { #[test] fn slashing_incomplete_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 42); Balances::increase_total_stake_by(42); assert_ok!(Balances::reserve(&1, 21)); @@ -208,7 +208,7 @@ fn slashing_incomplete_balance_should_work() { #[test] fn unreserving_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 111); assert_ok!(Balances::reserve(&1, 111)); Balances::unreserve(&1, 42); @@ -219,7 +219,7 @@ fn unreserving_balance_should_work() { #[test] fn slashing_reserved_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 111); Balances::increase_total_stake_by(111); assert_ok!(Balances::reserve(&1, 111)); @@ -232,7 +232,7 @@ fn slashing_reserved_balance_should_work() { #[test] fn slashing_incomplete_reserved_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 111); Balances::increase_total_stake_by(111); assert_ok!(Balances::reserve(&1, 42)); @@ -245,7 +245,7 @@ fn slashing_incomplete_reserved_balance_should_work() { #[test] fn transferring_reserved_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 110); Balances::set_free_balance(&2, 1); assert_ok!(Balances::reserve(&1, 110)); @@ -259,7 +259,7 @@ fn transferring_reserved_balance_should_work() { #[test] fn transferring_reserved_balance_to_nonexistent_should_fail() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 111); assert_ok!(Balances::reserve(&1, 111)); assert_noop!(Balances::transfer_reserved(&1, &2, 42), "beneficiary account must pre-exist"); @@ -268,7 +268,7 @@ fn transferring_reserved_balance_to_nonexistent_should_fail() { #[test] fn transferring_incomplete_reserved_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 110); Balances::set_free_balance(&2, 1); assert_ok!(Balances::reserve(&1, 41)); @@ -282,7 +282,7 @@ fn transferring_incomplete_reserved_balance_should_work() { #[test] fn transferring_too_high_value_should_not_panic() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(0, false), || { >::insert(1, u64::max_value()); >::insert(2, 1); @@ -298,7 +298,7 @@ fn transferring_too_high_value_should_not_panic() { #[test] fn account_removal_on_free_too_low() { - with_externalities(&mut new_test_ext(100, 1, 3, 1, false, 0), || { + with_externalities(&mut new_test_ext(100, false), || { // Setup two accounts with free balance above the exsistential threshold. { Balances::set_free_balance(&1, 110); diff --git a/substrate/runtime/contract/src/lib.rs b/substrate/runtime/contract/src/lib.rs index 7479686ddc453..dbb5146aa9ecd 100644 --- a/substrate/runtime/contract/src/lib.rs +++ b/substrate/runtime/contract/src/lib.rs @@ -71,6 +71,7 @@ extern crate substrate_runtime_sandbox as sandbox; extern crate substrate_runtime_std as rstd; extern crate substrate_runtime_consensus as consensus; +extern crate substrate_runtime_balances as balances; extern crate substrate_runtime_staking as staking; extern crate substrate_runtime_system as system; @@ -269,7 +270,7 @@ impl Module { } } -impl staking::OnFreeBalanceZero for Module { +impl balances::OnFreeBalanceZero for Module { fn on_free_balance_zero(who: &T::AccountId) { >::remove(who); >::remove_prefix(who.clone()); diff --git a/substrate/runtime/staking/src/address.rs b/substrate/runtime/staking/src/address.rs deleted file mode 100644 index 249e0b20db225..0000000000000 --- a/substrate/runtime/staking/src/address.rs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. - -// Substrate Demo 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 Demo 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 Demo. If not, see . - -//! Address type that is union of index and id for an account. - -#[cfg(feature = "std")] -use std::fmt; -use super::{Member, Decode, Encode, As, Input, Output}; - -/// A vetted and verified extrinsic from the external world. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash))] -pub enum Address where - AccountId: Member, - AccountIndex: Member, -{ - /// It's an account ID (pubkey). - #[cfg_attr(feature = "std", serde(deserialize_with="AccountId::deserialize"))] - Id(AccountId), - /// It's an account index. - #[cfg_attr(feature = "std", serde(deserialize_with="AccountIndex::deserialize"))] - Index(AccountIndex), -} - -#[cfg(feature = "std")] -impl fmt::Display for Address where - AccountId: Member, - AccountIndex: Member, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "{:?}", self) - } -} - -impl From for Address where - AccountId: Member, - AccountIndex: Member, -{ - fn from(a: AccountId) -> Self { - Address::Id(a) - } -} - -fn need_more_than(a: T, b: T) -> Option { - if a < b { Some(a) } else { None } -} - -impl Decode for Address where - AccountId: Member + Decode, - AccountIndex: Member + Decode + PartialOrd + Ord + As + As + As + Copy, -{ - fn decode(input: &mut I) -> Option { - Some(match input.read_byte()? { - x @ 0x00...0xef => Address::Index(As::sa(x)), - 0xfc => Address::Index(As::sa(need_more_than(0xef, u16::decode(input)?)?)), - 0xfd => Address::Index(As::sa(need_more_than(0xffff, u32::decode(input)?)?)), - 0xfe => Address::Index(need_more_than(As::sa(0xffffffffu32), Decode::decode(input)?)?), - 0xff => Address::Id(Decode::decode(input)?), - _ => return None, - }) - } -} - -impl Encode for Address where - AccountId: Member + Encode, - AccountIndex: Member + Encode + PartialOrd + Ord + As + As + As + Copy, -{ - fn encode_to(&self, dest: &mut T) { - match *self { - Address::Id(ref i) => { - dest.push_byte(255); - dest.push(i); - } - Address::Index(i) if i > As::sa(0xffffffffu32) => { - dest.push_byte(254); - dest.push(&i); - } - Address::Index(i) if i > As::sa(0xffffu32) => { - dest.push_byte(253); - dest.push(&As::::as_(i)); - } - Address::Index(i) if i >= As::sa(0xf0u32) => { - dest.push_byte(252); - dest.push(&As::::as_(i)); - } - Address::Index(i) => dest.push_byte(As::::as_(i)), - } - } -} - -impl Default for Address where - AccountId: Member + Default, - AccountIndex: Member, -{ - fn default() -> Self { - Address::Id(Default::default()) - } -} diff --git a/substrate/runtime/staking/src/genesis_config.rs b/substrate/runtime/staking/src/genesis_config.rs index 8da72bf1d92ab..2728badd62841 100644 --- a/substrate/runtime/staking/src/genesis_config.rs +++ b/substrate/runtime/staking/src/genesis_config.rs @@ -25,11 +25,8 @@ use runtime_support::{StorageValue, StorageMap}; use primitives::traits::{Zero, As}; use substrate_primitives::KeccakHasher; use {runtime_io, primitives}; -use super::{Trait, ENUM_SET_SIZE, EnumSet, NextEnumSet, Intentions, CurrentEra, - BondingDuration, CreationFee, TransferFee, ReclaimRebate, - ExistentialDeposit, TransactionByteFee, TransactionBaseFee, TotalStake, - SessionsPerEra, ValidatorCount, FreeBalance, SessionReward, EarlyEraSlash, - OfflineSlashGrace, MinimumValidatorCount}; +use super::{Trait, Intentions, CurrentEra, OfflineSlashGrace, MinimumValidatorCount, + BondingDuration, SessionsPerEra, ValidatorCount, SessionReward, EarlyEraSlash}; #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -37,17 +34,10 @@ use super::{Trait, ENUM_SET_SIZE, EnumSet, NextEnumSet, Intentions, CurrentEra, pub struct GenesisConfig { pub sessions_per_era: T::BlockNumber, pub current_era: T::BlockNumber, - pub balances: Vec<(T::AccountId, T::Balance)>, pub intentions: Vec, pub validator_count: u32, pub minimum_validator_count: u32, pub bonding_duration: T::BlockNumber, - pub transaction_base_fee: T::Balance, - pub transaction_byte_fee: T::Balance, - pub transfer_fee: T::Balance, - pub creation_fee: T::Balance, - pub reclaim_rebate: T::Balance, - pub existential_deposit: T::Balance, pub session_reward: T::Balance, pub early_era_slash: T::Balance, pub offline_slash_grace: u32, @@ -58,17 +48,10 @@ impl GenesisConfig where T::AccountId: From { GenesisConfig { sessions_per_era: T::BlockNumber::sa(2), current_era: T::BlockNumber::sa(0), - balances: vec![(T::AccountId::from(1), T::Balance::sa(111))], intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], validator_count: 3, minimum_validator_count: 1, bonding_duration: T::BlockNumber::sa(0), - transaction_base_fee: T::Balance::sa(0), - transaction_byte_fee: T::Balance::sa(0), - transfer_fee: T::Balance::sa(0), - creation_fee: T::Balance::sa(0), - existential_deposit: T::Balance::sa(0), - reclaim_rebate: T::Balance::sa(0), session_reward: T::Balance::sa(0), early_era_slash: T::Balance::sa(0), offline_slash_grace: 1, @@ -79,25 +62,10 @@ impl GenesisConfig where T::AccountId: From { GenesisConfig { sessions_per_era: T::BlockNumber::sa(3), current_era: T::BlockNumber::sa(1), - balances: vec![ - (T::AccountId::from(1), T::Balance::sa(10)), - (T::AccountId::from(2), T::Balance::sa(20)), - (T::AccountId::from(3), T::Balance::sa(30)), - (T::AccountId::from(4), T::Balance::sa(40)), - (T::AccountId::from(5), T::Balance::sa(50)), - (T::AccountId::from(6), T::Balance::sa(60)), - (T::AccountId::from(7), T::Balance::sa(1)) - ], intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], validator_count: 3, minimum_validator_count: 1, bonding_duration: T::BlockNumber::sa(0), - transaction_base_fee: T::Balance::sa(1), - transaction_byte_fee: T::Balance::sa(0), - transfer_fee: T::Balance::sa(0), - creation_fee: T::Balance::sa(0), - existential_deposit: T::Balance::sa(0), - reclaim_rebate: T::Balance::sa(0), session_reward: T::Balance::sa(0), early_era_slash: T::Balance::sa(0), offline_slash_grace: 1, @@ -110,17 +78,10 @@ impl Default for GenesisConfig { GenesisConfig { sessions_per_era: T::BlockNumber::sa(1000), current_era: T::BlockNumber::sa(0), - balances: vec![], intentions: vec![], validator_count: 0, minimum_validator_count: 0, bonding_duration: T::BlockNumber::sa(1000), - transaction_base_fee: T::Balance::sa(0), - transaction_byte_fee: T::Balance::sa(0), - transfer_fee: T::Balance::sa(0), - creation_fee: T::Balance::sa(0), - existential_deposit: T::Balance::sa(0), - reclaim_rebate: T::Balance::sa(0), session_reward: T::Balance::sa(0), early_era_slash: T::Balance::sa(0), offline_slash_grace: 0, @@ -130,36 +91,17 @@ impl Default for GenesisConfig { impl primitives::BuildStorage for GenesisConfig { fn build_storage(self) -> ::std::result::Result, Vec>, String> { - let total_stake: T::Balance = self.balances.iter().fold(Zero::zero(), |acc, &(_, n)| acc + n); - let mut r: runtime_io::TestExternalities = map![ - Self::hash(>::key()).to_vec() => T::AccountIndex::sa(self.balances.len() / ENUM_SET_SIZE).encode(), Self::hash(>::key()).to_vec() => self.intentions.encode(), Self::hash(>::key()).to_vec() => self.sessions_per_era.encode(), Self::hash(>::key()).to_vec() => self.validator_count.encode(), Self::hash(>::key()).to_vec() => self.minimum_validator_count.encode(), Self::hash(>::key()).to_vec() => self.bonding_duration.encode(), - Self::hash(>::key()).to_vec() => self.transaction_base_fee.encode(), - Self::hash(>::key()).to_vec() => self.transaction_byte_fee.encode(), - Self::hash(>::key()).to_vec() => self.transfer_fee.encode(), - Self::hash(>::key()).to_vec() => self.creation_fee.encode(), - Self::hash(>::key()).to_vec() => self.existential_deposit.encode(), - Self::hash(>::key()).to_vec() => self.reclaim_rebate.encode(), Self::hash(>::key()).to_vec() => self.current_era.encode(), Self::hash(>::key()).to_vec() => self.session_reward.encode(), Self::hash(>::key()).to_vec() => self.early_era_slash.encode(), - Self::hash(>::key()).to_vec() => self.offline_slash_grace.encode(), - Self::hash(>::key()).to_vec() => total_stake.encode() + Self::hash(>::key()).to_vec() => self.offline_slash_grace.encode() ]; - - let ids: Vec<_> = self.balances.iter().map(|x| x.0.clone()).collect(); - for i in 0..(ids.len() + ENUM_SET_SIZE - 1) / ENUM_SET_SIZE { - r.insert(Self::hash(&>::key_for(T::AccountIndex::sa(i))).to_vec(), - ids[i * ENUM_SET_SIZE..ids.len().min((i + 1) * ENUM_SET_SIZE)].to_owned().encode()); - } - for (who, value) in self.balances.into_iter() { - r.insert(Self::hash(&>::key_for(who)).to_vec(), value.encode()); - } Ok(r.into()) } } diff --git a/substrate/runtime/staking/src/lib.rs b/substrate/runtime/staking/src/lib.rs index bc058d3cae32d..1bd06e15a8f16 100644 --- a/substrate/runtime/staking/src/lib.rs +++ b/substrate/runtime/staking/src/lib.rs @@ -41,6 +41,7 @@ extern crate substrate_codec as codec; extern crate substrate_primitives; extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_primitives as primitives; +extern crate substrate_runtime_balances as balances; extern crate substrate_runtime_consensus as consensus; extern crate substrate_runtime_sandbox as sandbox; extern crate substrate_runtime_session as session; @@ -60,7 +61,6 @@ use address::Address as RawAddress; mod mock; -pub mod address; mod tests; mod genesis_config; @@ -69,18 +69,9 @@ pub use genesis_config::GenesisConfig; const DEFAULT_MINIMUM_VALIDATOR_COUNT: usize = 4; -/// Number of account IDs stored per enum set. -const ENUM_SET_SIZE: usize = 64; - -/// The byte to identify intention to reclaim an existing account index. -const RECLAIM_INDEX_MAGIC: usize = 0x69; - -pub type Address = RawAddress<::AccountId, ::AccountIndex>; - pub type Event = RawEvent< ::Balance, - ::AccountId, - ::AccountIndex + ::AccountId >; #[cfg(test)] @@ -99,16 +90,6 @@ pub enum LockStatus { Staked, } -/// The account was the given id was killed. -pub trait OnFreeBalanceZero { - /// The account was the given id was killed. - fn on_free_balance_zero(who: &AccountId); -} - -impl OnFreeBalanceZero for () { - fn on_free_balance_zero(_who: &AccountId) {} -} - /// Preference of what happens on a slash event. #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] #[derive(Encode, Decode, Eq, PartialEq, Clone, Copy)] @@ -125,21 +106,10 @@ impl Default for SlashPreference { } } -pub trait Trait: system::Trait + session::Trait { +pub trait Trait: balances::Trait + session::Trait { /// The allowed extrinsic position for `missed_proposal` inherent. const NOTE_MISSED_PROPOSAL_POSITION: u32; - /// The balance of an account. - type Balance: Parameter + SimpleArithmetic + Codec + Default + Copy + As + As + As; - /// Type used for storing an account's index; implies the maximum number of accounts the system - /// can hold. - type AccountIndex: Parameter + Member + Codec + SimpleArithmetic + As + As + As + As + As + Copy; - /// A function which is invoked when the free-balance has fallen below the existential deposit and - /// has been reduced to zero. - /// - /// Gives a chance to clean up resources associated with the given account. - type OnFreeBalanceZero: OnFreeBalanceZero; - /// The overarching event type. type Event: From> + Into<::Event>; } @@ -149,13 +119,12 @@ decl_module! { #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum Call where aux: T::PublicAux { - fn transfer(aux, dest: RawAddress, value: T::Balance) -> Result = 0; + fn note_missed_proposal(aux, offline_val_indices: Vec) -> Result = 0; fn stake(aux) -> Result = 1; fn unstake(aux, intentions_index: u32) -> Result = 2; fn nominate(aux, target: RawAddress) -> Result = 3; fn unnominate(aux, target_index: u32) -> Result = 4; fn register_slash_preference(aux, intentions_index: u32, p: SlashPreference) -> Result = 5; - fn note_missed_proposal(aux, offline_val_indices: Vec) -> Result = 6; } #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -165,14 +134,13 @@ decl_module! { fn set_validator_count(new: u32) -> Result = 2; fn force_new_era(apply_rewards: bool) -> Result = 3; fn set_offline_slash_grace(new: u32) -> Result = 4; - fn set_balance(who: RawAddress, free: T::Balance, reserved: T::Balance) -> Result = 5; } } /// An event in this module. #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] #[derive(Encode, Decode, PartialEq, Eq, Clone)] -pub enum RawEvent { +pub enum RawEvent { /// All validators have been rewarded by the given balance. Reward(Balance), /// One validator (and their nominators) has been given a offline-warning (they're still within @@ -180,92 +148,29 @@ pub enum RawEvent { OfflineWarning(AccountId, u32), /// One validator (and their nominators) has been slashed by the given amount. OfflineSlash(AccountId, Balance), - /// A new account was created. - NewAccount(AccountId, AccountIndex, NewAccountOutcome), - /// An account was reaped. - ReapedAccount(AccountId), } -impl From> for () { - fn from(_: RawEvent) -> () { () } +impl From> for () { + fn from(_: RawEvent) -> () { () } } decl_storage! { trait Store for Module as Staking { - // Separate into Accounts module. - - // The length of the bonding duration in eras. - pub BondingDuration get(bonding_duration): required T::BlockNumber; - // The total amount of stake on the system. - pub TotalStake get(total_stake): required T::Balance; - // The minimum amount allowed to keep an account open. - pub ExistentialDeposit get(existential_deposit): required T::Balance; - // The amount credited to a destination's account whose index was reclaimed. - pub ReclaimRebate get(reclaim_rebate): required T::Balance; - // The fee required to make a transfer. - pub TransferFee get(transfer_fee): required T::Balance; - // The fee required to create an account. At least as big as ReclaimRebate. - pub CreationFee get(creation_fee): required T::Balance; - - // The next free enumeration set. - pub NextEnumSet get(next_enum_set): required T::AccountIndex; - // The enumeration sets. - pub EnumSet get(enum_set): default map [ T::AccountIndex => Vec ]; - - // The "free" balance of a given account. - // - // This is the only balance that matters in terms of most operations on tokens. It is - // alone used to determine the balance when in the contract execution environment. When this - // balance falls below the value of `ExistentialDeposit`, then the "current account" is - // deleted: specifically, `Bondage` and `FreeBalance`. Furthermore, `OnFreeBalanceZero` callback - // is invoked, giving a chance to external modules to cleanup data associated with - // the deleted account. - // - // `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets - // collapsed to zero if it ever becomes less than `ExistentialDeposit`. - pub FreeBalance get(free_balance): default map [ T::AccountId => T::Balance ]; - - // The amount of the balance of a given account that is exterally reserved; this can still get - // slashed, but gets slashed last of all. - // - // This balance is a "reserve" balance that other subsystems use in order to set aside tokens - // that are still "owned" by the account holder, but which are unspendable. This is different - // and wholly unrelated to the `Bondage` system used for staking. - // - // When this balance falls below the value of `ExistentialDeposit`, then this "reserve account" - // is deleted: specifically, `ReservedBalance`. - // - // `system::AccountNonce` is also deleted if `FreeBalance` is also zero (it also gets - // collapsed to zero if it ever becomes less than `ExistentialDeposit`. - pub ReservedBalance get(reserved_balance): default map [ T::AccountId => T::Balance ]; - - // The block at which the `who`'s funds become entirely liquid. - pub Bondage get(bondage): default map [ T::AccountId => T::BlockNumber ]; - - - // Separate into Payment module. - - // The fee to be paid for making a transaction; the base. - pub TransactionBaseFee get(transaction_base_fee): required T::Balance; - // The fee to be paid for making a transaction; the per-byte portion. - pub TransactionByteFee get(transaction_byte_fee): required T::Balance; - - - // Remains in Staking module - // The ideal number of staking participants. pub ValidatorCount get(validator_count): required u32; // Minimum number of staking participants before emergency conditions are imposed. pub MinimumValidatorCount: u32; // The length of a staking era in sessions. pub SessionsPerEra get(sessions_per_era): required T::BlockNumber; - // Maximum reward, per validator, that is provided per acceptable session. pub SessionReward get(session_reward): required T::Balance; // Slash, per validator that is taken per abnormal era end. pub EarlyEraSlash get(early_era_slash): required T::Balance; // Number of instances of offline reports before slashing begins for validators. pub OfflineSlashGrace get(offline_slash_grace): default u32; + // The length of the bonding duration in eras. + // TODO gav: switch to blocks or time. + pub BondingDuration get(bonding_duration): required T::BlockNumber; // The current era index. pub CurrentEra get(current_era): required T::BlockNumber; @@ -287,6 +192,8 @@ decl_storage! { // The current era stake threshold - unused at present. Consider for removal. pub StakeThreshold get(stake_threshold): required T::Balance; + // The block at which the `who`'s funds become entirely liquid. + pub Bondage get(bondage): default map [ T::AccountId => T::BlockNumber ]; // The number of times a given validator has been reported offline. This gets decremented by one each era that passes. pub SlashCount get(slash_count): default map [ T::AccountId => u32 ]; @@ -295,23 +202,6 @@ decl_storage! { } } -/// Whatever happened about the hint given when creating the new account. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone, Copy)] -pub enum NewAccountOutcome { - NoHint, - GoodHint, - BadHint, -} - -/// Outcome of a balance update. -pub enum UpdateBalanceOutcome { - /// Account balance was simply updated. - Updated, - /// The update has led to killing of the account. - AccountKilled, -} - impl Module { // PUBLIC IMMUTABLES @@ -325,55 +215,18 @@ impl Module { Self::sessions_per_era() * >::length() } - /// The combined balance of `who`. - pub fn voting_balance(who: &T::AccountId) -> T::Balance { - Self::free_balance(who) + Self::reserved_balance(who) - } - /// Balance of a (potential) validator that includes all nominators. pub fn nomination_balance(who: &T::AccountId) -> T::Balance { Self::nominators_for(who).iter() - .map(Self::voting_balance) + .map(>::voting_balance) .fold(Zero::zero(), |acc, x| acc + x) } /// The total balance that can be slashed from an account. pub fn slashable_balance(who: &T::AccountId) -> T::Balance { Self::nominators_for(who).iter() - .map(Self::voting_balance) - .fold(Self::voting_balance(who), |acc, x| acc + x) - } - - /// Some result as `slash(who, value)` (but without the side-effects) assuming there are no - /// balance changes in the meantime and only the reserved balance is not taken into account. - pub fn can_slash(who: &T::AccountId, value: T::Balance) -> bool { - Self::free_balance(who) >= value - } - - /// Same result as `reserve(who, value)` (but without the side-effects) assuming there - /// are no balance changes in the meantime. - pub fn can_reserve(who: &T::AccountId, value: T::Balance) -> bool { - if let LockStatus::Liquid = Self::unlock_block(who) { - Self::free_balance(who) >= value - } else { - false - } - } - - /// Lookup an T::AccountIndex to get an Id, if there's one there. - pub fn lookup_index(index: T::AccountIndex) -> Option { - let enum_set_size = Self::enum_set_size(); - let set = Self::enum_set(index / enum_set_size); - let i: usize = (index % enum_set_size).as_(); - set.get(i).map(|x| x.clone()) - } - - /// `true` if the account `index` is ready for reclaim. - pub fn can_reclaim(try_index: T::AccountIndex) -> bool { - let enum_set_size = Self::enum_set_size(); - let try_set = Self::enum_set(try_index / enum_set_size); - let i = (try_index % enum_set_size).as_(); - i < try_set.len() && Self::voting_balance(&try_set[i]).is_zero() + .map(>::voting_balance) + .fold(>::voting_balance(who), |acc, x| acc + x) } /// The block at which the `who`'s funds become entirely liquid. @@ -385,52 +238,8 @@ impl Module { } } - /// Lookup an address to get an Id, if there's one there. - pub fn lookup_address(a: address::Address) -> Option { - match a { - address::Address::Id(i) => Some(i), - address::Address::Index(i) => Self::lookup_index(i), - } - } - // PUBLIC DISPATCH - /// Transfer some unlocked staking balance to another staker. - pub fn transfer(aux: &T::PublicAux, dest: Address, value: T::Balance) -> Result { - let dest = Self::lookup(dest)?; - - let transactor = aux.ref_into(); - let from_balance = Self::free_balance(transactor); - let would_create = from_balance.is_zero(); - let fee = if would_create { Self::creation_fee() } else { Self::transfer_fee() }; - let liability = value + fee; - - let new_from_balance = match from_balance.checked_sub(&liability) { - Some(b) => b, - None => return Err("balance too low to send value"), - }; - if would_create && value < Self::existential_deposit() { - return Err("value too low to create account"); - } - if >::get(transactor) > >::block_number() { - return Err("bondage too high to send value"); - } - - let to_balance = Self::free_balance(&dest); - let new_to_balance = match to_balance.checked_add(&value) { - Some(b) => b, - None => return Err("destination balance too high to receive value"), - }; - - if transactor != &dest { - Self::set_free_balance(transactor, new_from_balance); - Self::decrease_total_stake_by(fee); - Self::set_free_balance_creating(&dest, new_to_balance); - } - - Ok(()) - } - /// Declare the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. @@ -605,195 +414,8 @@ impl Module { Ok(()) } - /// Set the balances of a given account. - fn set_balance(who: Address, free: T::Balance, reserved: T::Balance) -> Result { - let who = Self::lookup(who)?; - Self::set_free_balance(&who, free); - Self::set_reserved_balance(&who, reserved); - Ok(()) - } - // PUBLIC MUTABLES (DANGEROUS) - /// Set the free balance of an account to some new value. - /// - /// Will enforce ExistentialDeposit law, anulling the account as needed. - /// In that case it will return `AccountKilled`. - pub fn set_reserved_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { - if balance < Self::existential_deposit() { - >::insert(who, balance); - Self::on_reserved_too_low(who); - UpdateBalanceOutcome::AccountKilled - } else { - >::insert(who, balance); - UpdateBalanceOutcome::Updated - } - } - - /// Set the free balance of an account to some new value. Will enforce ExistentialDeposit - /// law anulling the account as needed. - /// - /// Doesn't do any preparatory work for creating a new account, so should only be used when it - /// is known that the account already exists. - /// - /// Returns if the account was successfully updated or update has led to killing of the account. - pub fn set_free_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { - // Commented out for no - but consider it instructive. - // assert!(!Self::voting_balance(who).is_zero()); - if balance < Self::existential_deposit() { - >::insert(who, balance); - Self::on_free_too_low(who); - UpdateBalanceOutcome::AccountKilled - } else { - >::insert(who, balance); - UpdateBalanceOutcome::Updated - } - } - - /// Set the free balance on an account to some new value. - /// - /// Same as [`set_free_balance`], but will create a new account. - /// - /// Returns if the account was successfully updated or update has led to killing of the account. - /// - /// [`set_free_balance`]: #method.set_free_balance - pub fn set_free_balance_creating(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { - let ed = >::existential_deposit(); - // If the balance is too low, then the account is reaped. - // NOTE: There are two balances for every account: `reserved_balance` and - // `free_balance`. This contract subsystem only cares about the latter: whenever - // the term "balance" is used *here* it should be assumed to mean "free balance" - // in the rest of the module. - // Free balance can never be less than ED. If that happens, it gets reduced to zero - // and the account information relevant to this subsystem is deleted (i.e. the - // account is reaped). - // NOTE: This is orthogonal to the `Bondage` value that an account has, a high - // value of which makes even the `free_balance` unspendable. - // TODO: enforce this for the other balance-altering functions. - if balance < ed { - Self::set_free_balance(who, balance); - UpdateBalanceOutcome::AccountKilled - } else { - if !>::exists(who) { - let outcome = Self::new_account(&who, balance); - let credit = match outcome { - NewAccountOutcome::GoodHint => balance + >::reclaim_rebate(), - _ => balance, - }; - Self::set_free_balance(who, credit); - Self::increase_total_stake_by(credit - balance); - } else { - Self::set_free_balance(who, balance); - } - - UpdateBalanceOutcome::Updated - } - } - - /// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the - /// free balance. This function cannot fail. - /// - /// As much funds up to `value` will be deducted as possible. If this is less than `value`, - /// then `Some(remaining)` will be returned. Full completion is given by `None`. - pub fn slash(who: &T::AccountId, value: T::Balance) -> Option { - let free_balance = Self::free_balance(who); - let free_slash = cmp::min(free_balance, value); - Self::set_free_balance(who, free_balance - free_slash); - Self::decrease_total_stake_by(free_slash); - if free_slash < value { - Self::slash_reserved(who, value - free_slash) - } else { - None - } - } - - /// Adds up to `value` to the free balance of `who`. - /// - /// If `who` doesn't exist, nothing is done and an Err returned. - pub fn reward(who: &T::AccountId, value: T::Balance) -> Result { - if Self::voting_balance(who).is_zero() { - return Err("beneficiary account must pre-exist"); - } - Self::set_free_balance(who, Self::free_balance(who) + value); - Self::increase_total_stake_by(value); - Ok(()) - } - - /// Moves `value` from balance to reserved balance. - /// - /// If the free balance is lower than `value`, then no funds will be moved and an `Err` will - /// be returned to notify of this. This is different behaviour to `unreserve`. - pub fn reserve(who: &T::AccountId, value: T::Balance) -> Result { - let b = Self::free_balance(who); - if b < value { - return Err("not enough free funds") - } - if Self::unlock_block(who) != LockStatus::Liquid { - return Err("free funds are still bonded") - } - Self::set_reserved_balance(who, Self::reserved_balance(who) + value); - Self::set_free_balance(who, b - value); - Ok(()) - } - - /// Moves up to `value` from reserved balance to balance. This function cannot fail. - /// - /// As much funds up to `value` will be deducted as possible. If this is less than `value`, - /// then `Some(remaining)` will be returned. Full completion is given by `None`. - /// NOTE: This is different to `reserve`. - pub fn unreserve(who: &T::AccountId, value: T::Balance) -> Option { - let b = Self::reserved_balance(who); - let actual = cmp::min(b, value); - Self::set_free_balance(who, Self::free_balance(who) + actual); - Self::set_reserved_balance(who, b - actual); - if actual == value { - None - } else { - Some(value - actual) - } - } - - /// Deducts up to `value` from reserved balance of `who`. This function cannot fail. - /// - /// As much funds up to `value` will be deducted as possible. If this is less than `value`, - /// then `Some(remaining)` will be returned. Full completion is given by `None`. - pub fn slash_reserved(who: &T::AccountId, value: T::Balance) -> Option { - let b = Self::reserved_balance(who); - let slash = cmp::min(b, value); - Self::set_reserved_balance(who, b - slash); - Self::decrease_total_stake_by(slash); - if value == slash { - None - } else { - Some(value - slash) - } - } - - /// Moves up to `value` from reserved balance of account `slashed` to free balance of account - /// `beneficiary`. `beneficiary` must exist for this to succeed. If it does not, `Err` will be - /// returned. - /// - /// As much funds up to `value` will be moved as possible. If this is less than `value`, then - /// `Ok(Some(remaining))` will be returned. Full completion is given by `Ok(None)`. - pub fn transfer_reserved( - slashed: &T::AccountId, - beneficiary: &T::AccountId, - value: T::Balance - ) -> result::Result, &'static str> { - if Self::voting_balance(beneficiary).is_zero() { - return Err("beneficiary account must pre-exist"); - } - let b = Self::reserved_balance(slashed); - let slash = cmp::min(b, value); - Self::set_free_balance(beneficiary, Self::free_balance(beneficiary) + slash); - Self::set_reserved_balance(slashed, b - slash); - if value == slash { - Ok(None) - } else { - Ok(Some(value - slash)) - } - } - /// Slash a given validator by a specific amount. Removes the slash from their balance by preference, /// and reduces the nominators' balance if needed. fn slash_validator(v: &T::AccountId, slash: T::Balance) { @@ -803,13 +425,13 @@ impl Module { return } - if let Some(rem) = Self::slash(v, slash) { + if let Some(rem) = >::slash(v, slash) { let noms = Self::current_nominators_for(v); - let total = noms.iter().map(Self::voting_balance).fold(T::Balance::zero(), |acc, x| acc + x); + let total = noms.iter().map(>::voting_balance).fold(T::Balance::zero(), |acc, x| acc + x); if !total.is_zero() { let safe_mul_rational = |b| b * rem / total;// TODO: avoid overflow for n in noms.iter() { - let _ = Self::slash(n, safe_mul_rational(Self::voting_balance(n))); // best effort - not much that can be done on fail. + let _ = >::slash(n, safe_mul_rational(>::voting_balance(n))); // best effort - not much that can be done on fail. } } } @@ -819,13 +441,13 @@ impl Module { /// balance, pro-rata. fn reward_validator(who: &T::AccountId, reward: T::Balance) { let noms = Self::current_nominators_for(who); - let total = noms.iter().map(Self::voting_balance).fold(Self::voting_balance(who), |acc, x| acc + x); + let total = noms.iter().map(>::voting_balance).fold(>::voting_balance(who), |acc, x| acc + x); if !total.is_zero() { let safe_mul_rational = |b| b * reward / total;// TODO: avoid overflow for n in noms.iter() { - let _ = Self::reward(n, safe_mul_rational(Self::voting_balance(n))); + let _ = >::reward(n, safe_mul_rational(>::voting_balance(n))); } - let _ = Self::reward(who, safe_mul_rational(Self::voting_balance(who))); + let _ = >::reward(who, safe_mul_rational(>::voting_balance(who))); } } @@ -927,125 +549,6 @@ impl Module { } >::set_validators(vals); } - - fn enum_set_size() -> T::AccountIndex { - T::AccountIndex::sa(ENUM_SET_SIZE) - } - - /// Register a new account (with existential balance). - fn new_account(who: &T::AccountId, balance: T::Balance) -> NewAccountOutcome { - let enum_set_size = Self::enum_set_size(); - let next_set_index = Self::next_enum_set(); - let reclaim_index_magic = T::AccountIndex::sa(RECLAIM_INDEX_MAGIC); - let reclaim_index_modulus = T::AccountIndex::sa(256usize); - let quantization = T::AccountIndex::sa(256usize); - - // A little easter-egg for reclaiming dead indexes.. - let ret = { - // we quantise the number of accounts so it stays constant over a reasonable - // period of time. - let quantized_account_count: T::AccountIndex = (next_set_index * enum_set_size / quantization + One::one()) * quantization; - // then modify the starting balance to be modulo this to allow it to potentially - // identify an account index for reuse. - let maybe_try_index = balance % >::sa(quantized_account_count * reclaim_index_modulus); - let maybe_try_index = As::::as_(maybe_try_index); - - // this identifier must end with magic byte 0x69 to trigger this check (a minor - // optimisation to ensure we don't check most unintended account creations). - if maybe_try_index % reclaim_index_modulus == reclaim_index_magic { - // reuse is probably intended. first, remove magic byte. - let try_index = maybe_try_index / reclaim_index_modulus; - - // then check to see if this balance identifies a dead account index. - let set_index = try_index / enum_set_size; - let mut try_set = Self::enum_set(set_index); - let item_index = (try_index % enum_set_size).as_(); - if item_index < try_set.len() { - if Self::voting_balance(&try_set[item_index]).is_zero() { - // yup - this index refers to a dead account. can be reused. - try_set[item_index] = who.clone(); - >::insert(set_index, try_set); - - Self::deposit_event(RawEvent::NewAccount(who.clone(), try_index, NewAccountOutcome::GoodHint)); - - return NewAccountOutcome::GoodHint - } - } - NewAccountOutcome::BadHint - } else { - NewAccountOutcome::NoHint - } - }; - - // insert normally as a back up - let mut set_index = next_set_index; - // defensive only: this loop should never iterate since we keep NextEnumSet up to date later. - let mut set = loop { - let set = Self::enum_set(set_index); - if set.len() < ENUM_SET_SIZE { - break set; - } - set_index += One::one(); - }; - - let index = T::AccountIndex::sa(set_index.as_() * ENUM_SET_SIZE + set.len()); - - // update set. - set.push(who.clone()); - - // keep NextEnumSet up to date - if set.len() == ENUM_SET_SIZE { - >::put(set_index + One::one()); - } - - // write set. - >::insert(set_index, set); - - Self::deposit_event(RawEvent::NewAccount(who.clone(), index, ret)); - - ret - } - - fn reap_account(who: &T::AccountId) { - >::remove(who); - Self::deposit_event(RawEvent::ReapedAccount(who.clone())); - } - - /// Kill an account's free portion. - fn on_free_too_low(who: &T::AccountId) { - Self::decrease_total_stake_by(Self::free_balance(who)); - >::remove(who); - >::remove(who); - - T::OnFreeBalanceZero::on_free_balance_zero(who); - - if Self::reserved_balance(who).is_zero() { - Self::reap_account(who); - } - } - - /// Kill an account's reserved portion. - fn on_reserved_too_low(who: &T::AccountId) { - Self::decrease_total_stake_by(Self::reserved_balance(who)); - >::remove(who); - - if Self::free_balance(who).is_zero() { - Self::reap_account(who); - } - } - - /// Increase TotalStake by Value. - pub fn increase_total_stake_by(value: T::Balance) { - if let Some(v) = >::total_stake().checked_add(&value) { - >::put(v); - } - } - /// Decrease TotalStake by Value. - pub fn decrease_total_stake_by(value: T::Balance) { - if let Some(v) = >::total_stake().checked_sub(&value) { - >::put(v); - } - } } impl Executable for Module { @@ -1059,26 +562,14 @@ impl OnSessionChange for Module { } } -impl AuxLookup for Module { - type Source = address::Address; - type Target = T::AccountId; - fn lookup(a: Self::Source) -> result::Result { - match a { - address::Address::Id(i) => Ok(i), - address::Address::Index(i) => >::lookup_index(i).ok_or("invalid account index"), - } +impl balances::IsAccountLiquid for Module { + fn is_account_liquid(who: &T::AccountId) -> bool { + Self::bondage(who) <= >::block_number() } } -impl MakePayment for Module { - fn make_payment(transactor: &T::AccountId, encoded_len: usize) -> Result { - let b = Self::free_balance(transactor); - let transaction_fee = Self::transaction_base_fee() + Self::transaction_byte_fee() * >::sa(encoded_len as u64); - if b < transaction_fee + Self::existential_deposit() { - return Err("not enough funds for transaction fee"); - } - Self::set_free_balance(transactor, b - transaction_fee); - Self::decrease_total_stake_by(transaction_fee); - Ok(()) +impl balances::OnFreeBalanceZero for Module { + fn on_free_balance_zero(who: &T::AccountId) { + >::remove(who); } } diff --git a/substrate/runtime/staking/src/mock.rs b/substrate/runtime/staking/src/mock.rs index 559cbbdca222b..43a531d818eb5 100644 --- a/substrate/runtime/staking/src/mock.rs +++ b/substrate/runtime/staking/src/mock.rs @@ -23,7 +23,7 @@ use primitives::traits::{HasPublicAux, Identity}; use primitives::testing::{Digest, Header}; use substrate_primitives::{H256, KeccakHasher}; use runtime_io; -use {GenesisConfig, Module, Trait, consensus, session, system, timestamp}; +use {GenesisConfig, Module, Trait, consensus, session, system, timestamp, balance}; // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] @@ -45,6 +45,13 @@ impl system::Trait for Test { type Header = Header; type Event = (); } +impl balances::Trait for Test { + type Balance = u64; + type AccountIndex = u64; + type OnFreeBalanceZero = Staking; + type IsAccountLiquid = Staking; + type Event = (); +} impl session::Trait for Test { type ConvertAccountIdToSessionKey = Identity; type OnSessionChange = Staking; @@ -56,9 +63,6 @@ impl timestamp::Trait for Test { } impl Trait for Test { const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1; - type Balance = u64; - type AccountIndex = u64; - type OnFreeBalanceZero = (); type Event = (); } @@ -77,9 +81,7 @@ pub fn new_test_ext(ext_deposit: u64, session_length: u64, sessions_per_era: u64 session_length, validators: vec![10, 20], }.build_storage().unwrap()); - t.extend(GenesisConfig::{ - sessions_per_era, - current_era, + t.extend(balances::GenesisConfig::{ balances: if monied { if reward > 0 { vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor), (10, balance_factor), (20, balance_factor)] @@ -89,16 +91,20 @@ pub fn new_test_ext(ext_deposit: u64, session_length: u64, sessions_per_era: u64 } else { vec![(10, balance_factor), (20, balance_factor)] }, - intentions: vec![10, 20], - validator_count: 2, - minimum_validator_count: 0, - bonding_duration: 3, transaction_base_fee: 0, transaction_byte_fee: 0, existential_deposit: ext_deposit, transfer_fee: 0, creation_fee: 0, reclaim_rebate: 0, + }.build_storage().unwrap()); + t.extend(GenesisConfig::{ + sessions_per_era, + current_era, + intentions: vec![10, 20], + validator_count: 2, + minimum_validator_count: 0, + bonding_duration: 3, session_reward: reward, early_era_slash: if monied { 20 } else { 0 }, offline_slash_grace: 0, @@ -110,6 +116,7 @@ pub fn new_test_ext(ext_deposit: u64, session_length: u64, sessions_per_era: u64 } pub type System = system::Module; +pub type Balances = balances::Module; pub type Session = session::Module; pub type Timestamp = timestamp::Module; pub type Staking = Module; diff --git a/substrate/runtime/staking/src/tests.rs b/substrate/runtime/staking/src/tests.rs index 809838379ae12..285d7d4b41c0c 100644 --- a/substrate/runtime/staking/src/tests.rs +++ b/substrate/runtime/staking/src/tests.rs @@ -20,18 +20,18 @@ use super::*; use runtime_io::with_externalities; -use mock::{Session, Staking, System, Timestamp, Test, new_test_ext}; +use mock::{Balances, Session, Staking, System, Timestamp, Test, new_test_ext}; #[test] fn note_null_missed_proposal_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { assert_eq!(Staking::offline_slash_grace(), 0); assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Staking::free_balance(&10), 1); + assert_eq!(Balances::free_balance(&10), 1); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![])); assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Staking::free_balance(&10), 1); + assert_eq!(Balances::free_balance(&10), 1); assert!(Staking::forcing_new_era().is_none()); }); } @@ -39,14 +39,14 @@ fn note_null_missed_proposal_should_work() { #[test] fn note_missed_proposal_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - Staking::set_free_balance(&10, 70); + Balances::set_free_balance(&10, 70); assert_eq!(Staking::offline_slash_grace(), 0); assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Staking::free_balance(&10), 70); + assert_eq!(Balances::free_balance(&10), 70); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); assert_eq!(Staking::slash_count(&10), 1); - assert_eq!(Staking::free_balance(&10), 50); + assert_eq!(Balances::free_balance(&10), 50); assert!(Staking::forcing_new_era().is_none()); }); } @@ -54,18 +54,18 @@ fn note_missed_proposal_should_work() { #[test] fn note_missed_proposal_exponent_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - Staking::set_free_balance(&10, 150); + Balances::set_free_balance(&10, 150); assert_eq!(Staking::offline_slash_grace(), 0); assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Staking::free_balance(&10), 150); + assert_eq!(Balances::free_balance(&10), 150); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); assert_eq!(Staking::slash_count(&10), 1); - assert_eq!(Staking::free_balance(&10), 130); + assert_eq!(Balances::free_balance(&10), 130); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); assert_eq!(Staking::slash_count(&10), 2); - assert_eq!(Staking::free_balance(&10), 90); + assert_eq!(Balances::free_balance(&10), 90); assert!(Staking::forcing_new_era().is_none()); }); } @@ -73,27 +73,27 @@ fn note_missed_proposal_exponent_should_work() { #[test] fn note_missed_proposal_grace_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - Staking::set_free_balance(&10, 70); - Staking::set_free_balance(&20, 70); + Balances::set_free_balance(&10, 70); + Balances::set_free_balance(&20, 70); assert_ok!(Staking::set_offline_slash_grace(1)); assert_eq!(Staking::offline_slash_grace(), 1); assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Staking::free_balance(&10), 70); + assert_eq!(Balances::free_balance(&10), 70); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); assert_eq!(Staking::slash_count(&10), 1); - assert_eq!(Staking::free_balance(&10), 70); + assert_eq!(Balances::free_balance(&10), 70); assert_eq!(Staking::slash_count(&20), 0); - assert_eq!(Staking::free_balance(&20), 70); + assert_eq!(Balances::free_balance(&20), 70); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); assert_eq!(Staking::slash_count(&10), 2); - assert_eq!(Staking::free_balance(&10), 50); + assert_eq!(Balances::free_balance(&10), 50); assert_eq!(Staking::slash_count(&20), 1); - assert_eq!(Staking::free_balance(&20), 70); + assert_eq!(Balances::free_balance(&20), 70); assert!(Staking::forcing_new_era().is_none()); }); } @@ -101,25 +101,25 @@ fn note_missed_proposal_grace_should_work() { #[test] fn note_missed_proposal_force_unstake_session_change_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - Staking::set_free_balance(&10, 70); - Staking::set_free_balance(&20, 70); + Balances::set_free_balance(&10, 70); + Balances::set_free_balance(&20, 70); assert_ok!(Staking::stake(&1)); assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Staking::free_balance(&10), 70); + assert_eq!(Balances::free_balance(&10), 70); assert_eq!(Staking::intentions(), vec![10, 20, 1]); assert_eq!(Session::validators(), vec![10, 20]); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); - assert_eq!(Staking::free_balance(&10), 50); + assert_eq!(Balances::free_balance(&10), 50); assert_eq!(Staking::slash_count(&10), 1); assert_eq!(Staking::intentions(), vec![10, 20, 1]); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); assert_eq!(Staking::intentions(), vec![1, 20]); - assert_eq!(Staking::free_balance(&10), 10); + assert_eq!(Balances::free_balance(&10), 10); assert!(Staking::forcing_new_era().is_some()); }); } @@ -127,49 +127,42 @@ fn note_missed_proposal_force_unstake_session_change_should_work() { #[test] fn note_missed_proposal_auto_unstake_session_change_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - Staking::set_free_balance(&10, 7000); - Staking::set_free_balance(&20, 7000); + Balances::set_free_balance(&10, 7000); + Balances::set_free_balance(&20, 7000); assert_ok!(Staking::register_slash_preference(&10, 0, SlashPreference { unstake_threshold: 1 })); assert_eq!(Staking::intentions(), vec![10, 20]); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); - assert_eq!(Staking::free_balance(&10), 6980); - assert_eq!(Staking::free_balance(&20), 6980); + assert_eq!(Balances::free_balance(&10), 6980); + assert_eq!(Balances::free_balance(&20), 6980); assert_eq!(Staking::intentions(), vec![10, 20]); assert!(Staking::forcing_new_era().is_none()); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); - assert_eq!(Staking::free_balance(&10), 6940); - assert_eq!(Staking::free_balance(&20), 6940); + assert_eq!(Balances::free_balance(&10), 6940); + assert_eq!(Balances::free_balance(&20), 6940); assert_eq!(Staking::intentions(), vec![20]); assert!(Staking::forcing_new_era().is_some()); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![1])); - assert_eq!(Staking::free_balance(&10), 6940); - assert_eq!(Staking::free_balance(&20), 6860); + assert_eq!(Balances::free_balance(&10), 6940); + assert_eq!(Balances::free_balance(&20), 6860); assert_eq!(Staking::intentions(), vec![20]); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![1])); - assert_eq!(Staking::free_balance(&10), 6940); - assert_eq!(Staking::free_balance(&20), 6700); + assert_eq!(Balances::free_balance(&10), 6940); + assert_eq!(Balances::free_balance(&20), 6700); assert_eq!(Staking::intentions(), vec![0u64; 0]); }); } -#[test] -fn reward_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - assert_eq!(Staking::voting_balance(&10), 1); - assert_ok!(Staking::reward(&10, 10)); - assert_eq!(Staking::voting_balance(&10), 11); - assert_eq!(>::get(), 112); - }); -} + + #[test] fn rewards_should_work() { @@ -179,26 +172,26 @@ fn rewards_should_work() { assert_eq!(Staking::last_era_length_change(), 0); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 0); - assert_eq!(Staking::voting_balance(&10), 1); + assert_eq!(Balances::voting_balance(&10), 1); System::set_block_number(3); Timestamp::set_timestamp(15); // on time. Session::check_rotate_session(); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 1); - assert_eq!(Staking::voting_balance(&10), 11); + assert_eq!(Balances::voting_balance(&10), 11); System::set_block_number(6); Timestamp::set_timestamp(31); // a little late Session::check_rotate_session(); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 2); - assert_eq!(Staking::voting_balance(&10), 20); // less reward + assert_eq!(Balances::voting_balance(&10), 20); // less reward System::set_block_number(9); Timestamp::set_timestamp(50); // very late Session::check_rotate_session(); assert_eq!(Staking::current_era(), 1); assert_eq!(Session::current_index(), 3); - assert_eq!(Staking::voting_balance(&10), 27); // much less reward + assert_eq!(Balances::voting_balance(&10), 27); // much less reward }); } @@ -210,104 +203,28 @@ fn slashing_should_work() { assert_eq!(Staking::last_era_length_change(), 0); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 0); - assert_eq!(Staking::voting_balance(&10), 1); + assert_eq!(Balances::voting_balance(&10), 1); System::set_block_number(3); Session::check_rotate_session(); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 1); - assert_eq!(Staking::voting_balance(&10), 11); + assert_eq!(Balances::voting_balance(&10), 11); System::set_block_number(6); Session::check_rotate_session(); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 2); - assert_eq!(Staking::voting_balance(&10), 21); + assert_eq!(Balances::voting_balance(&10), 21); System::set_block_number(7); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); - assert_eq!(Staking::voting_balance(&10), 1); + assert_eq!(Balances::voting_balance(&10), 1); }); } -#[test] -fn indexing_lookup_should_work() { - with_externalities(&mut new_test_ext(10, 1, 2, 0, true, 0), || { - assert_eq!(Staking::lookup_index(0), Some(1)); - assert_eq!(Staking::lookup_index(1), Some(2)); - assert_eq!(Staking::lookup_index(2), Some(3)); - assert_eq!(Staking::lookup_index(3), Some(4)); - assert_eq!(Staking::lookup_index(4), None); - }); -} -#[test] -fn default_indexing_on_new_accounts_should_work() { - with_externalities(&mut new_test_ext(10, 1, 2, 0, true, 0), || { - assert_eq!(Staking::lookup_index(4), None); - assert_ok!(Staking::transfer(&1, 5.into(), 10)); - assert_eq!(Staking::lookup_index(4), Some(5)); - }); -} - -#[test] -fn dust_account_removal_should_work() { - with_externalities(&mut new_test_ext(256 * 10, 1, 2, 0, true, 0), || { - System::inc_account_nonce(&2); - assert_eq!(System::account_nonce(&2), 1); - assert_eq!(Staking::voting_balance(&2), 256 * 20); - - assert_ok!(Staking::transfer(&2, 5.into(), 256 * 10 + 1)); // index 1 (account 2) becomes zombie - assert_eq!(Staking::voting_balance(&2), 0); - assert_eq!(Staking::voting_balance(&5), 256 * 10 + 1); - assert_eq!(System::account_nonce(&2), 0); - }); -} - -#[test] -fn reclaim_indexing_on_new_accounts_should_work() { - with_externalities(&mut new_test_ext(256 * 1, 1, 2, 0, true, 0), || { - assert_eq!(Staking::lookup_index(1), Some(2)); - assert_eq!(Staking::lookup_index(4), None); - assert_eq!(Staking::voting_balance(&2), 256 * 20); - - assert_ok!(Staking::transfer(&2, 5.into(), 256 * 20)); // account 2 becomes zombie freeing index 1 for reclaim) - assert_eq!(Staking::voting_balance(&2), 0); - - assert_ok!(Staking::transfer(&5, 6.into(), 256 * 1 + 0x69)); // account 6 takes index 1. - assert_eq!(Staking::voting_balance(&6), 256 * 1 + 0x69); - assert_eq!(Staking::lookup_index(1), Some(6)); - }); -} - -#[test] -fn reserved_balance_should_prevent_reclaim_count() { - with_externalities(&mut new_test_ext(256 * 1, 1, 2, 0, true, 0), || { - System::inc_account_nonce(&2); - assert_eq!(Staking::lookup_index(1), Some(2)); - assert_eq!(Staking::lookup_index(4), None); - assert_eq!(Staking::voting_balance(&2), 256 * 20); - - assert_ok!(Staking::reserve(&2, 256 * 19 + 1)); // account 2 becomes mostly reserved - assert_eq!(Staking::free_balance(&2), 0); // "free" account deleted." - assert_eq!(Staking::voting_balance(&2), 256 * 19 + 1); // reserve still exists. - assert_eq!(System::account_nonce(&2), 1); - - assert_ok!(Staking::transfer(&4, 5.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 for account 5. - assert_eq!(Staking::voting_balance(&5), 256 * 1 + 0x69); - assert_eq!(Staking::lookup_index(1), Some(2)); // but fails. - assert_eq!(System::account_nonce(&2), 1); - - assert_eq!(Staking::slash(&2, 256 * 18 + 2), None); // account 2 gets slashed - assert_eq!(Staking::voting_balance(&2), 0); // "free" account deleted." - assert_eq!(System::account_nonce(&2), 0); - - assert_ok!(Staking::transfer(&4, 6.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 again for account 6. - assert_eq!(Staking::voting_balance(&6), 256 * 1 + 0x69); - assert_eq!(Staking::lookup_index(1), Some(6)); // and succeeds. - }); -} #[test] fn staking_should_work() { @@ -347,7 +264,7 @@ fn staking_should_work() { // Block 5: Transfer stake from highest to lowest. No change yet. System::set_block_number(5); - assert_ok!(Staking::transfer(&4, 1.into(), 40)); + assert_ok!(Balances::transfer(&4, 1.into(), 40)); Session::check_rotate_session(); // Block 6: Lowest now validator. @@ -384,20 +301,20 @@ fn nominating_and_rewards_should_work() { Session::check_rotate_session(); assert_eq!(Staking::current_era(), 1); assert_eq!(Session::validators(), vec![1, 3]); // 4 + 1, 3 - assert_eq!(Staking::voting_balance(&1), 10); - assert_eq!(Staking::voting_balance(&2), 20); - assert_eq!(Staking::voting_balance(&3), 30); - assert_eq!(Staking::voting_balance(&4), 40); + assert_eq!(Balances::voting_balance(&1), 10); + assert_eq!(Balances::voting_balance(&2), 20); + assert_eq!(Balances::voting_balance(&3), 30); + assert_eq!(Balances::voting_balance(&4), 40); System::set_block_number(2); assert_ok!(Staking::unnominate(&4, 0)); Session::check_rotate_session(); assert_eq!(Staking::current_era(), 2); assert_eq!(Session::validators(), vec![3, 2]); - assert_eq!(Staking::voting_balance(&1), 12); - assert_eq!(Staking::voting_balance(&2), 20); - assert_eq!(Staking::voting_balance(&3), 40); - assert_eq!(Staking::voting_balance(&4), 48); + assert_eq!(Balances::voting_balance(&1), 12); + assert_eq!(Balances::voting_balance(&2), 20); + assert_eq!(Balances::voting_balance(&3), 40); + assert_eq!(Balances::voting_balance(&4), 48); System::set_block_number(3); assert_ok!(Staking::stake(&4)); @@ -405,17 +322,17 @@ fn nominating_and_rewards_should_work() { assert_ok!(Staking::nominate(&3, 1.into())); Session::check_rotate_session(); assert_eq!(Session::validators(), vec![1, 4]); - assert_eq!(Staking::voting_balance(&1), 12); - assert_eq!(Staking::voting_balance(&2), 30); - assert_eq!(Staking::voting_balance(&3), 50); - assert_eq!(Staking::voting_balance(&4), 48); + assert_eq!(Balances::voting_balance(&1), 12); + assert_eq!(Balances::voting_balance(&2), 30); + assert_eq!(Balances::voting_balance(&3), 50); + assert_eq!(Balances::voting_balance(&4), 48); System::set_block_number(4); Session::check_rotate_session(); - assert_eq!(Staking::voting_balance(&1), 13); - assert_eq!(Staking::voting_balance(&2), 30); - assert_eq!(Staking::voting_balance(&3), 58); - assert_eq!(Staking::voting_balance(&4), 58); + assert_eq!(Balances::voting_balance(&1), 13); + assert_eq!(Balances::voting_balance(&2), 30); + assert_eq!(Balances::voting_balance(&3), 58); + assert_eq!(Balances::voting_balance(&4), 58); }); } @@ -440,18 +357,18 @@ fn nominating_slashes_should_work() { assert_eq!(Staking::current_era(), 1); assert_eq!(Session::validators(), vec![1, 3]); // 1 + 4, 3 + 2 - assert_eq!(Staking::voting_balance(&1), 10); - assert_eq!(Staking::voting_balance(&2), 20); - assert_eq!(Staking::voting_balance(&3), 30); - assert_eq!(Staking::voting_balance(&4), 40); + assert_eq!(Balances::voting_balance(&1), 10); + assert_eq!(Balances::voting_balance(&2), 20); + assert_eq!(Balances::voting_balance(&3), 30); + assert_eq!(Balances::voting_balance(&4), 40); System::set_block_number(5); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); - assert_eq!(Staking::voting_balance(&1), 0); - assert_eq!(Staking::voting_balance(&2), 20); - assert_eq!(Staking::voting_balance(&3), 10); - assert_eq!(Staking::voting_balance(&4), 30); + assert_eq!(Balances::voting_balance(&1), 0); + assert_eq!(Balances::voting_balance(&2), 20); + assert_eq!(Balances::voting_balance(&3), 10); + assert_eq!(Balances::voting_balance(&4), 30); }); } @@ -536,235 +453,22 @@ fn staking_eras_work() { }); } -#[test] -fn staking_balance_works() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 42); - assert_eq!(Staking::free_balance(&1), 42); - assert_eq!(Staking::reserved_balance(&1), 0); - assert_eq!(Staking::voting_balance(&1), 42); - assert_eq!(Staking::free_balance(&2), 0); - assert_eq!(Staking::reserved_balance(&2), 0); - assert_eq!(Staking::voting_balance(&2), 0); - }); -} - -#[test] -fn staking_balance_transfer_works() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - Staking::increase_total_stake_by(111); - assert_ok!(Staking::transfer(&1, 2.into(), 69)); - assert_eq!(Staking::voting_balance(&1), 42); - assert_eq!(Staking::voting_balance(&2), 69); - }); -} - #[test] fn staking_balance_transfer_when_bonded_should_not_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); + Balances::set_free_balance(&1, 111); assert_ok!(Staking::stake(&1)); - assert_noop!(Staking::transfer(&1, 2.into(), 69), "bondage too high to send value"); - }); -} - -#[test] -fn reserving_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - - assert_eq!(Staking::voting_balance(&1), 111); - assert_eq!(Staking::free_balance(&1), 111); - assert_eq!(Staking::reserved_balance(&1), 0); - - assert_ok!(Staking::reserve(&1, 69)); - - assert_eq!(Staking::voting_balance(&1), 111); - assert_eq!(Staking::free_balance(&1), 42); - assert_eq!(Staking::reserved_balance(&1), 69); - }); -} - -#[test] -fn staking_balance_transfer_when_reserved_should_not_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - assert_ok!(Staking::reserve(&1, 69)); - assert_noop!(Staking::transfer(&1, 2.into(), 69), "balance too low to send value"); - }); -} - -#[test] -fn deducting_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - assert_ok!(Staking::reserve(&1, 69)); - assert_eq!(Staking::free_balance(&1), 42); + assert_noop!(Balances::transfer(&1, 2.into(), 69), "bondage too high to send value"); }); } #[test] fn deducting_balance_when_bonded_should_not_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); + Balances::set_free_balance(&1, 111); >::insert(1, 2); System::set_block_number(1); assert_eq!(Staking::unlock_block(&1), LockStatus::LockedUntil(2)); - assert_noop!(Staking::reserve(&1, 69), "free funds are still bonded"); - }); -} - -#[test] -fn refunding_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 42); - Staking::set_reserved_balance(&1, 69); - Staking::unreserve(&1, 69); - assert_eq!(Staking::free_balance(&1), 111); - assert_eq!(Staking::reserved_balance(&1), 0); - }); -} - -#[test] -fn slashing_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - Staking::increase_total_stake_by(111); - assert_ok!(Staking::reserve(&1, 69)); - assert!(Staking::slash(&1, 69).is_none()); - assert_eq!(Staking::free_balance(&1), 0); - assert_eq!(Staking::reserved_balance(&1), 42); - assert_eq!(>::get(), 44); - }); -} - -#[test] -fn slashing_incomplete_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 42); - Staking::increase_total_stake_by(42); - assert_ok!(Staking::reserve(&1, 21)); - assert!(Staking::slash(&1, 69).is_some()); - assert_eq!(Staking::free_balance(&1), 0); - assert_eq!(Staking::reserved_balance(&1), 0); - assert_eq!(>::get(), 2); - }); -} - -#[test] -fn unreserving_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - assert_ok!(Staking::reserve(&1, 111)); - Staking::unreserve(&1, 42); - assert_eq!(Staking::reserved_balance(&1), 69); - assert_eq!(Staking::free_balance(&1), 42); - }); -} - -#[test] -fn slashing_reserved_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - Staking::increase_total_stake_by(111); - assert_ok!(Staking::reserve(&1, 111)); - assert!(Staking::slash_reserved(&1, 42).is_none()); - assert_eq!(Staking::reserved_balance(&1), 69); - assert_eq!(Staking::free_balance(&1), 0); - assert_eq!(>::get(), 71); - }); -} - -#[test] -fn slashing_incomplete_reserved_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - Staking::increase_total_stake_by(111); - assert_ok!(Staking::reserve(&1, 42)); - assert!(Staking::slash_reserved(&1, 69).is_some()); - assert_eq!(Staking::free_balance(&1), 69); - assert_eq!(Staking::reserved_balance(&1), 0); - assert_eq!(>::get(), 71); - }); -} - -#[test] -fn transferring_reserved_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 110); - Staking::set_free_balance(&2, 1); - assert_ok!(Staking::reserve(&1, 110)); - assert_ok!(Staking::transfer_reserved(&1, &2, 41), None); - assert_eq!(Staking::reserved_balance(&1), 69); - assert_eq!(Staking::free_balance(&1), 0); - assert_eq!(Staking::reserved_balance(&2), 0); - assert_eq!(Staking::free_balance(&2), 42); - }); -} - -#[test] -fn transferring_reserved_balance_to_nonexistent_should_fail() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 111); - assert_ok!(Staking::reserve(&1, 111)); - assert_noop!(Staking::transfer_reserved(&1, &2, 42), "beneficiary account must pre-exist"); - }); -} - -#[test] -fn transferring_incomplete_reserved_balance_should_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Staking::set_free_balance(&1, 110); - Staking::set_free_balance(&2, 1); - assert_ok!(Staking::reserve(&1, 41)); - assert!(Staking::transfer_reserved(&1, &2, 69).unwrap().is_some()); - assert_eq!(Staking::reserved_balance(&1), 0); - assert_eq!(Staking::free_balance(&1), 69); - assert_eq!(Staking::reserved_balance(&2), 0); - assert_eq!(Staking::free_balance(&2), 42); - }); -} - -#[test] -fn transferring_too_high_value_should_not_panic() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - >::insert(1, u64::max_value()); - >::insert(2, 1); - - assert_err!( - Staking::transfer(&1, 2.into(), u64::max_value()), - "destination balance too high to receive value" - ); - - assert_eq!(Staking::free_balance(&1), u64::max_value()); - assert_eq!(Staking::free_balance(&2), 1); - }); -} - -#[test] -fn account_removal_on_free_too_low() { - with_externalities(&mut new_test_ext(100, 1, 3, 1, false, 0), || { - // Setup two accounts with free balance above the exsistential threshold. - { - Staking::set_free_balance(&1, 110); - Staking::increase_total_stake_by(110); - - Staking::set_free_balance(&2, 110); - Staking::increase_total_stake_by(110); - - assert_eq!(>::get(), 732); - } - - // Transfer funds from account 1 of such amount that after this transfer - // the balance of account 1 will be below the exsistential threshold. - // This should lead to the removal of all balance of this account. - assert_ok!(Staking::transfer(&1, 2.into(), 20)); - - // Verify free balance removal of account 1. - assert_eq!(Staking::free_balance(&1), 0); - - // Verify that TotalStake tracks balance removal when free balance is too low. - assert_eq!(>::get(), 642); + assert_noop!(Balances::reserve(&1, 69), "free funds are still bonded"); }); } From 5c7937818eb4b88cafef6dc8d3095dc41a16b2f9 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 29 Aug 2018 21:10:12 +0200 Subject: [PATCH 05/19] Split off and fix up staking module --- substrate/runtime/council/src/lib.rs | 8 ++++---- .../runtime/staking/src/genesis_config.rs | 6 +++--- substrate/runtime/staking/src/lib.rs | 20 +++++++++---------- substrate/runtime/staking/src/mock.rs | 2 +- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/substrate/runtime/council/src/lib.rs b/substrate/runtime/council/src/lib.rs index 68eab58ac472a..4fedb1b977041 100644 --- a/substrate/runtime/council/src/lib.rs +++ b/substrate/runtime/council/src/lib.rs @@ -45,7 +45,7 @@ use rstd::prelude::*; use primitives::traits::{Zero, One, RefInto, As, AuxLookup}; use substrate_runtime_support::{StorageValue, StorageMap}; use substrate_runtime_support::dispatch::Result; -use staking::address::Address; +use balances::address::Address; #[cfg(any(feature = "std", test))] use std::collections::HashMap; @@ -270,7 +270,7 @@ impl Module { who_index: u32, assumed_vote_index: VoteIndex ) -> Result { - let who = >::lookup(who)?; + let who = >::lookup(who)?; ensure!(!Self::presentation_active(), "cannot reap during presentation period"); ensure!(Self::voter_last_active(aux.ref_into()).is_some(), "reaper must be a voter"); let last_active = Self::voter_last_active(&who).ok_or("target for inactivity cleanup must be active")?; @@ -359,7 +359,7 @@ impl Module { total: T::Balance, index: VoteIndex ) -> Result { - let candidate = >::lookup(candidate)?; + let candidate = >::lookup(candidate)?; ensure!(index == Self::vote_index(), "index not current"); let (_, _, expiring) = Self::next_finalise().ok_or("cannot present outside of presentation period")?; let stakes = Self::snapshoted_stakes(); @@ -413,7 +413,7 @@ impl Module { /// period) to fill the seat if removal means that the desired members are not met. /// This is effective immediately. fn remove_member(who: Address) -> Result { - let who = >::lookup(who)?; + let who = >::lookup(who)?; let new_council: Vec<(T::AccountId, T::BlockNumber)> = Self::active_council() .into_iter() .filter(|i| i.0 != who) diff --git a/substrate/runtime/staking/src/genesis_config.rs b/substrate/runtime/staking/src/genesis_config.rs index 2728badd62841..da0d898bb3592 100644 --- a/substrate/runtime/staking/src/genesis_config.rs +++ b/substrate/runtime/staking/src/genesis_config.rs @@ -21,8 +21,8 @@ use std::collections::HashMap; use rstd::prelude::*; use codec::Encode; -use runtime_support::{StorageValue, StorageMap}; -use primitives::traits::{Zero, As}; +use runtime_support::StorageValue; +use primitives::traits::As; use substrate_primitives::KeccakHasher; use {runtime_io, primitives}; use super::{Trait, Intentions, CurrentEra, OfflineSlashGrace, MinimumValidatorCount, @@ -91,7 +91,7 @@ impl Default for GenesisConfig { impl primitives::BuildStorage for GenesisConfig { fn build_storage(self) -> ::std::result::Result, Vec>, String> { - let mut r: runtime_io::TestExternalities = map![ + let r: runtime_io::TestExternalities = map![ Self::hash(>::key()).to_vec() => self.intentions.encode(), Self::hash(>::key()).to_vec() => self.sessions_per_era.encode(), Self::hash(>::key()).to_vec() => self.validator_count.encode(), diff --git a/substrate/runtime/staking/src/lib.rs b/substrate/runtime/staking/src/lib.rs index 1bd06e15a8f16..671f9ab2b2a7f 100644 --- a/substrate/runtime/staking/src/lib.rs +++ b/substrate/runtime/staking/src/lib.rs @@ -50,14 +50,12 @@ extern crate substrate_runtime_timestamp as timestamp; #[cfg(test)] use std::fmt::Debug; use rstd::prelude::*; -use rstd::{cmp, result}; -use codec::{Encode, Decode, Codec, Input, Output}; -use runtime_support::{StorageValue, StorageMap, Parameter}; +use runtime_support::{StorageValue, StorageMap}; use runtime_support::dispatch::Result; use session::OnSessionChange; -use primitives::traits::{Zero, One, Bounded, RefInto, SimpleArithmetic, Executable, MakePayment, - As, AuxLookup, Member, CheckedAdd, CheckedSub, MaybeEmpty}; -use address::Address as RawAddress; +use primitives::traits::{Zero, One, Bounded, RefInto, Executable, + As, AuxLookup, MaybeEmpty}; +use balances::address::Address; mod mock; @@ -70,7 +68,7 @@ pub use genesis_config::GenesisConfig; const DEFAULT_MINIMUM_VALIDATOR_COUNT: usize = 4; pub type Event = RawEvent< - ::Balance, + ::Balance, ::AccountId >; @@ -122,7 +120,7 @@ decl_module! { fn note_missed_proposal(aux, offline_val_indices: Vec) -> Result = 0; fn stake(aux) -> Result = 1; fn unstake(aux, intentions_index: u32) -> Result = 2; - fn nominate(aux, target: RawAddress) -> Result = 3; + fn nominate(aux, target: Address) -> Result = 3; fn unnominate(aux, target_index: u32) -> Result = 4; fn register_slash_preference(aux, intentions_index: u32, p: SlashPreference) -> Result = 5; } @@ -266,8 +264,8 @@ impl Module { Self::apply_unstake(aux.ref_into(), intentions_index as usize) } - fn nominate(aux: &T::PublicAux, target: RawAddress) -> Result { - let target = Self::lookup(target)?; + fn nominate(aux: &T::PublicAux, target: Address) -> Result { + let target = >::lookup(target)?; let aux = aux.ref_into(); ensure!(Self::nominating(aux).is_none(), "Cannot nominate if already nominating."); @@ -570,6 +568,6 @@ impl balances::IsAccountLiquid for Module { impl balances::OnFreeBalanceZero for Module { fn on_free_balance_zero(who: &T::AccountId) { - >::remove(who); + >::remove(who); } } diff --git a/substrate/runtime/staking/src/mock.rs b/substrate/runtime/staking/src/mock.rs index 43a531d818eb5..39f990c6fe7ba 100644 --- a/substrate/runtime/staking/src/mock.rs +++ b/substrate/runtime/staking/src/mock.rs @@ -23,7 +23,7 @@ use primitives::traits::{HasPublicAux, Identity}; use primitives::testing::{Digest, Header}; use substrate_primitives::{H256, KeccakHasher}; use runtime_io; -use {GenesisConfig, Module, Trait, consensus, session, system, timestamp, balance}; +use {GenesisConfig, Module, Trait, consensus, session, system, timestamp, balances}; // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] From f8f11a8827d622e225fde754f3ac821827bb5378 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 29 Aug 2018 21:28:14 +0200 Subject: [PATCH 06/19] Fix executive tests --- Cargo.lock | 1 + substrate/runtime/consensus/src/lib.rs | 2 +- substrate/runtime/executive/Cargo.toml | 1 + substrate/runtime/executive/src/lib.rs | 44 ++++++++++++++++---------- 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5a9a880c0c966..fafee7a249b71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2775,6 +2775,7 @@ dependencies = [ "substrate-codec 0.1.0", "substrate-codec-derive 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-balances 0.1.0", "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", diff --git a/substrate/runtime/consensus/src/lib.rs b/substrate/runtime/consensus/src/lib.rs index 3540980ead214..b8e80f6a13aaf 100644 --- a/substrate/runtime/consensus/src/lib.rs +++ b/substrate/runtime/consensus/src/lib.rs @@ -42,7 +42,7 @@ use rstd::prelude::*; use runtime_support::{storage, Parameter}; use runtime_support::dispatch::Result; use runtime_support::storage::unhashed::StorageVec; -use primitives::traits::{RefInto, MaybeSerializeDebug, MaybeEmpty}; +use primitives::traits::MaybeSerializeDebug; use primitives::bft::MisbehaviorReport; #[cfg(any(feature = "std", test))] diff --git a/substrate/runtime/executive/Cargo.toml b/substrate/runtime/executive/Cargo.toml index 20d913e92553a..74a10d18f8642 100644 --- a/substrate/runtime/executive/Cargo.toml +++ b/substrate/runtime/executive/Cargo.toml @@ -17,6 +17,7 @@ substrate-runtime-system = { path = "../system", default_features = false } [dev-dependencies] substrate-primitives = { path = "../../primitives" } +substrate-runtime-balances = { path = "../balances" } substrate-runtime-session = { path = "../session" } substrate-runtime-staking = { path = "../staking" } substrate-runtime-consensus = { path = "../consensus" } diff --git a/substrate/runtime/executive/src/lib.rs b/substrate/runtime/executive/src/lib.rs index e0334aa35b3cc..bb7cee50883c7 100644 --- a/substrate/runtime/executive/src/lib.rs +++ b/substrate/runtime/executive/src/lib.rs @@ -53,6 +53,9 @@ extern crate substrate_runtime_consensus as consensus; #[cfg(test)] extern crate substrate_runtime_session as session; +#[cfg(test)] +extern crate substrate_runtime_balances as balances; + #[cfg(test)] extern crate substrate_runtime_staking as staking; @@ -224,7 +227,7 @@ impl< #[cfg(test)] mod tests { use super::*; - use staking::Call; + use balances::Call; use runtime_io::with_externalities; use substrate_primitives::{H256, KeccakHasher}; use primitives::BuildStorage; @@ -242,7 +245,7 @@ mod tests { impl_outer_event!{ pub enum MetaEvent for Test { - session, staking + balances, session, staking } } @@ -255,6 +258,13 @@ mod tests { impl consensus::Trait for Test { type SessionKey = u64; } + impl balances::Trait for Test { + type Balance = u64; + type AccountIndex = u64; + type OnFreeBalanceZero = staking::Module; + type IsAccountLiquid = staking::Module; + type Event = MetaEvent; + } impl system::Trait for Test { type PublicAux = ::PublicAux; type Index = u64; @@ -273,9 +283,6 @@ mod tests { } impl staking::Trait for Test { const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1; - type Balance = u64; - type AccountIndex = u64; - type OnFreeBalanceZero = (); type Event = MetaEvent; } impl timestamp::Trait for Test { @@ -284,25 +291,27 @@ mod tests { } type TestXt = primitives::testing::TestXt>; - type Executive = super::Executive, NullLookup, staking::Module, (session::Module, staking::Module)>; + type Executive = super::Executive, NullLookup, balances::Module, (session::Module, staking::Module)>; #[test] fn staking_balance_transfer_dispatch_works() { let mut t = system::GenesisConfig::::default().build_storage().unwrap(); - t.extend(staking::GenesisConfig:: { - sessions_per_era: 0, - current_era: 0, + t.extend(balances::GenesisConfig:: { balances: vec![(1, 111)], - intentions: vec![], - validator_count: 0, - minimum_validator_count: 0, - bonding_duration: 0, transaction_base_fee: 10, transaction_byte_fee: 0, existential_deposit: 0, transfer_fee: 0, creation_fee: 0, reclaim_rebate: 0, + }.build_storage().unwrap()); + t.extend(staking::GenesisConfig:: { + sessions_per_era: 0, + current_era: 0, + intentions: vec![], + validator_count: 0, + minimum_validator_count: 0, + bonding_duration: 0, early_era_slash: 0, session_reward: 0, offline_slash_grace: 0, @@ -312,13 +321,14 @@ mod tests { with_externalities(&mut t, || { Executive::initialise_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); Executive::apply_extrinsic(xt).unwrap(); - assert_eq!(>::voting_balance(&1), 32); - assert_eq!(>::voting_balance(&2), 69); + assert_eq!(>::voting_balance(&1), 32); + assert_eq!(>::voting_balance(&2), 69); }); } fn new_test_ext() -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap(); + t.extend(balances::GenesisConfig::::default().build_storage().unwrap()); t.extend(consensus::GenesisConfig::::default().build_storage().unwrap()); t.extend(session::GenesisConfig::::default().build_storage().unwrap()); t.extend(staking::GenesisConfig::::default().build_storage().unwrap()); @@ -336,7 +346,7 @@ mod tests { // Blake // state_root: hex!("02532989c613369596025dfcfc821339fc9861987003924913a5a1382f87034a").into(), // Keccak - state_root: hex!("e576ed2adacdc09b61844b5106bfaa18d2a4bfd7feb56d7af97c3421cdefca48").into(), + state_root: hex!("5b846f849bf38ef5acd96e1c999cd61619408015919f06ab575384d83cf45aa7").into(), extrinsics_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), digest: Digest { logs: vec![], }, }, @@ -370,7 +380,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("e576ed2adacdc09b61844b5106bfaa18d2a4bfd7feb56d7af97c3421cdefca48").into(), + state_root: hex!("5b846f849bf38ef5acd96e1c999cd61619408015919f06ab575384d83cf45aa7").into(), extrinsics_root: [0u8; 32].into(), digest: Digest { logs: vec![], }, }, From d7202c0c908f1aae38ed0b31f567a9a53f170775 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 29 Aug 2018 21:38:38 +0200 Subject: [PATCH 07/19] Fix up democracy module --- Cargo.lock | 1 + substrate/runtime/democracy/Cargo.toml | 8 ++-- substrate/runtime/democracy/src/lib.rs | 65 +++++++++++++++----------- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fafee7a249b71..ffb589cea7925 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2754,6 +2754,7 @@ dependencies = [ "substrate-codec 0.1.0", "substrate-codec-derive 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-balances 0.1.0", "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", diff --git a/substrate/runtime/democracy/Cargo.toml b/substrate/runtime/democracy/Cargo.toml index bf144eece6346..3e77bc3b694bb 100644 --- a/substrate/runtime/democracy/Cargo.toml +++ b/substrate/runtime/democracy/Cargo.toml @@ -15,13 +15,14 @@ substrate-runtime-std = { path = "../../runtime-std", default_features = false } substrate-runtime-io = { path = "../../runtime-io", default_features = false } substrate-runtime-support = { path = "../../runtime-support", default_features = false } substrate-runtime-primitives = { path = "../primitives", default_features = false } +substrate-runtime-balances = { path = "../balances", default_features = false } substrate-runtime-consensus = { path = "../consensus", default_features = false } -substrate-runtime-session = { path = "../session", default_features = false } -substrate-runtime-staking = { path = "../staking", default_features = false } substrate-runtime-system = { path = "../system", default_features = false } [dev-dependencies] substrate-runtime-timestamp = { path = "../timestamp" } +substrate-runtime-session = { path = "../session" } +substrate-runtime-staking = { path = "../staking" } [features] default = ["std"] @@ -36,7 +37,6 @@ std = [ "substrate-runtime-support/std", "substrate-runtime-primitives/std", "substrate-runtime-consensus/std", - "substrate-runtime-session/std", - "substrate-runtime-staking/std", + "substrate-runtime-balances/std", "substrate-runtime-system/std", ] diff --git a/substrate/runtime/democracy/src/lib.rs b/substrate/runtime/democracy/src/lib.rs index da239061e57c1..2079681ae6dbe 100644 --- a/substrate/runtime/democracy/src/lib.rs +++ b/substrate/runtime/democracy/src/lib.rs @@ -38,10 +38,14 @@ extern crate substrate_runtime_support; extern crate substrate_codec as codec; extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_primitives as primitives; +extern crate substrate_runtime_balances as balances; extern crate substrate_runtime_consensus as consensus; +extern crate substrate_runtime_system as system; + +#[cfg(test)] extern crate substrate_runtime_session as session; +#[cfg(test)] extern crate substrate_runtime_staking as staking; -extern crate substrate_runtime_system as system; #[cfg(test)] extern crate substrate_runtime_timestamp as timestamp; @@ -62,7 +66,7 @@ pub type PropIndex = u32; /// A referendum index. pub type ReferendumIndex = u32; -pub trait Trait: staking::Trait + Sized { +pub trait Trait: balances::Trait + Sized { type Proposal: Parameter + Dispatchable + IsSubType> + MaybeSerializeDebug; } @@ -152,7 +156,7 @@ impl Module { /// Get the voters for the current proposal. pub fn tally(ref_index: ReferendumIndex) -> (T::Balance, T::Balance) { Self::voters_for(ref_index).iter() - .map(|a| (>::voting_balance(a), Self::vote_of((ref_index, a.clone())).unwrap_or(false)/*defensive only: all items come from `voters`; for an item to be in `voters` there must be a vote registered; qed*/)) + .map(|a| (>::voting_balance(a), Self::vote_of((ref_index, a.clone())).unwrap_or(false)/*defensive only: all items come from `voters`; for an item to be in `voters` there must be a vote registered; qed*/)) .map(|(bal, vote)| if vote { (bal, Zero::zero()) } else { (Zero::zero(), bal) }) .fold((Zero::zero(), Zero::zero()), |(a, b), (c, d)| (a + c, b + d)) } @@ -162,7 +166,7 @@ impl Module { /// Propose a sensitive action to be taken. fn propose(aux: &T::PublicAux, proposal: Box, value: T::Balance) -> Result { ensure!(value >= Self::minimum_deposit(), "value too low"); - >::reserve(aux.ref_into(), value) + >::reserve(aux.ref_into(), value) .map_err(|_| "proposer's balance too low")?; let index = Self::public_prop_count(); @@ -179,7 +183,7 @@ impl Module { fn second(aux: &T::PublicAux, proposal: PropIndex) -> Result { let mut deposit = Self::deposit_of(proposal) .ok_or("can only second an existing proposal")?; - >::reserve(aux.ref_into(), deposit.0) + >::reserve(aux.ref_into(), deposit.0) .map_err(|_| "seconder's balance too low")?; deposit.1.push(aux.ref_into().clone()); >::insert(proposal, deposit); @@ -190,7 +194,7 @@ impl Module { /// false would be a vote to keep the status quo.. fn vote(aux: &T::PublicAux, ref_index: ReferendumIndex, approve_proposal: bool) -> Result { ensure!(Self::is_active_referendum(ref_index), "vote given for invalid referendum."); - ensure!(!>::voting_balance(aux.ref_into()).is_zero(), + ensure!(!>::voting_balance(aux.ref_into()).is_zero(), "transactor must have balance to signal approval."); if !>::exists(&(ref_index, aux.ref_into().clone())) { let mut voters = Self::voters_for(ref_index); @@ -268,7 +272,7 @@ impl Module { if let Some((deposit, depositors)) = >::take(prop_index) {//: (T::Balance, Vec) = // refund depositors for d in &depositors { - >::unreserve(d, deposit); + >::unreserve(d, deposit); } >::put(public_props); Self::inject_referendum(now + Self::voting_period(), proposal, VoteThreshold::SuperMajorityApprove)?; @@ -281,7 +285,7 @@ impl Module { // tally up votes for any expiring referenda. for (index, _, proposal, vote_threshold) in Self::maturing_referendums_at(now) { let (approve, against) = Self::tally(index); - let total_stake = >::total_stake(); + let total_stake = >::total_stake(); Self::clear_referendum(index); if vote_threshold.approved(approve, against, total_stake) { proposal.dispatch()?; @@ -396,16 +400,20 @@ mod tests { type Header = Header; type Event = (); } + impl balances::Trait for Test { + type Balance = u64; + type AccountIndex = u64; + type OnFreeBalanceZero = Staking; + type IsAccountLiquid = Staking; + type Event = (); + } impl session::Trait for Test { type ConvertAccountIdToSessionKey = Identity; - type OnSessionChange = staking::Module; + type OnSessionChange = Staking; type Event = (); } impl staking::Trait for Test { const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1; - type Balance = u64; - type AccountIndex = u64; - type OnFreeBalanceZero = (); type Event = (); } impl timestamp::Trait for Test { @@ -426,20 +434,22 @@ mod tests { session_length: 1, //??? or 2? validators: vec![10, 20], }.build_storage().unwrap()); - t.extend(staking::GenesisConfig::{ - sessions_per_era: 1, - current_era: 0, + t.extend(balances::GenesisConfig::{ balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], - intentions: vec![], - validator_count: 2, - minimum_validator_count: 0, - bonding_duration: 3, transaction_base_fee: 0, transaction_byte_fee: 0, existential_deposit: 0, transfer_fee: 0, creation_fee: 0, reclaim_rebate: 0, + }.build_storage().unwrap()); + t.extend(staking::GenesisConfig::{ + sessions_per_era: 1, + current_era: 0, + intentions: vec![], + validator_count: 2, + minimum_validator_count: 0, + bonding_duration: 3, early_era_slash: 0, session_reward: 0, offline_slash_grace: 0, @@ -454,6 +464,7 @@ mod tests { } type System = system::Module; + type Balances = balances::Module; type Session = session::Module; type Staking = staking::Module; type Democracy = Module; @@ -466,7 +477,7 @@ mod tests { assert_eq!(Democracy::minimum_deposit(), 1); assert_eq!(Democracy::referendum_count(), 0); assert_eq!(Staking::sessions_per_era(), 1); - assert_eq!(Staking::total_stake(), 210); + assert_eq!(Balances::total_stake(), 210); }); } @@ -519,9 +530,9 @@ mod tests { assert_ok!(Democracy::second(&5, 0)); assert_ok!(Democracy::second(&5, 0)); assert_ok!(Democracy::second(&5, 0)); - assert_eq!(Staking::free_balance(&1), 5); - assert_eq!(Staking::free_balance(&2), 15); - assert_eq!(Staking::free_balance(&5), 35); + assert_eq!(Balances::free_balance(&1), 5); + assert_eq!(Balances::free_balance(&2), 15); + assert_eq!(Balances::free_balance(&5), 35); }); } @@ -535,9 +546,9 @@ mod tests { assert_ok!(Democracy::second(&5, 0)); assert_ok!(Democracy::second(&5, 0)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - assert_eq!(Staking::free_balance(&1), 10); - assert_eq!(Staking::free_balance(&2), 20); - assert_eq!(Staking::free_balance(&5), 50); + assert_eq!(Balances::free_balance(&1), 10); + assert_eq!(Balances::free_balance(&2), 20); + assert_eq!(Balances::free_balance(&5), 50); }); } @@ -696,7 +707,7 @@ mod tests { fn passing_low_turnout_voting_should_work() { with_externalities(&mut new_test_ext(), || { assert_eq!(Staking::era_length(), 1); - assert_eq!(Staking::total_stake(), 210); + assert_eq!(Balances::total_stake(), 210); System::set_block_number(1); let r = Democracy::inject_referendum(1, sessions_per_era_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); From e82ec0d86c3adb6f0c00ec075d284de8a84ac8d5 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 29 Aug 2018 21:52:26 +0200 Subject: [PATCH 08/19] make council work again --- Cargo.lock | 1 + substrate/runtime/council/Cargo.toml | 5 +- substrate/runtime/council/src/lib.rs | 81 ++++++++++--------------- substrate/runtime/council/src/voting.rs | 36 +++++------ 4 files changed, 53 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ffb589cea7925..d8577f21376b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2731,6 +2731,7 @@ dependencies = [ "substrate-codec 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-balances 0.1.0", "substrate-runtime-consensus 0.1.0", "substrate-runtime-democracy 0.1.0", "substrate-runtime-io 0.1.0", diff --git a/substrate/runtime/council/Cargo.toml b/substrate/runtime/council/Cargo.toml index aaffa4ba1af96..8710a846cc9a9 100644 --- a/substrate/runtime/council/Cargo.toml +++ b/substrate/runtime/council/Cargo.toml @@ -17,13 +17,14 @@ substrate-runtime-io = { path = "../../runtime-io", default_features = false } substrate-runtime-support = { path = "../../runtime-support", default_features = false } substrate-runtime-primitives = { path = "../primitives", default_features = false } substrate-runtime-consensus = { path = "../consensus", default_features = false } +substrate-runtime-balances = { path = "../balances", default_features = false } substrate-runtime-democracy = { path = "../democracy", default_features = false } -substrate-runtime-session = { path = "../session", default_features = false } -substrate-runtime-staking = { path = "../staking", default_features = false } substrate-runtime-system = { path = "../system", default_features = false } [dev-dependencies] substrate-runtime-timestamp = { path = "../timestamp" } +substrate-runtime-session = { path = "../session" } +substrate-runtime-staking = { path = "../staking" } [features] default = ["std"] diff --git a/substrate/runtime/council/src/lib.rs b/substrate/runtime/council/src/lib.rs index 4fedb1b977041..e2dd48de4974f 100644 --- a/substrate/runtime/council/src/lib.rs +++ b/substrate/runtime/council/src/lib.rs @@ -33,11 +33,15 @@ extern crate substrate_primitives; extern crate substrate_runtime_io as runtime_io; #[macro_use] extern crate substrate_runtime_support; extern crate substrate_runtime_primitives as primitives; +extern crate substrate_runtime_balances as balances; extern crate substrate_runtime_consensus as consensus; extern crate substrate_runtime_democracy as democracy; +extern crate substrate_runtime_system as system; + +#[cfg(test)] extern crate substrate_runtime_session as session; +#[cfg(test)] extern crate substrate_runtime_staking as staking; -extern crate substrate_runtime_system as system; #[cfg(test)] extern crate substrate_runtime_timestamp as timestamp; @@ -245,7 +249,7 @@ impl Module { if !>::exists(aux.ref_into()) { // not yet a voter - deduct bond. // NOTE: this must be the last potential bailer, since it changes state. - >::reserve(aux.ref_into(), Self::voting_bond())?; + >::reserve(aux.ref_into(), Self::voting_bond())?; >::put({ let mut v = Self::voters(); @@ -300,9 +304,9 @@ impl Module { if valid { // This only fails if `who` doesn't exist, which it clearly must do since its the aux. // Still, it's no more harmful to propagate any error at this point. - >::transfer_reserved(&who, aux.ref_into(), Self::voting_bond())?; + >::transfer_reserved(&who, aux.ref_into(), Self::voting_bond())?; } else { - >::slash_reserved(aux.ref_into(), Self::voting_bond()); + >::slash_reserved(aux.ref_into(), Self::voting_bond()); } Ok(()) } @@ -317,7 +321,7 @@ impl Module { ensure!(&voters[index] == aux.ref_into(), "retraction index mismatch"); Self::remove_voter(aux.ref_into(), index, voters); - >::unreserve(aux.ref_into(), Self::voting_bond()); + >::unreserve(aux.ref_into(), Self::voting_bond()); Ok(()) } @@ -335,7 +339,7 @@ impl Module { "invalid candidate slot" ); // NOTE: This must be last as it has side-effects. - >::reserve(aux.ref_into(), Self::candidacy_bond()) + >::reserve(aux.ref_into(), Self::candidacy_bond()) .map_err(|_| "candidate has not enough funds")?; let mut candidates = candidates; @@ -365,7 +369,7 @@ impl Module { let stakes = Self::snapshoted_stakes(); let voters = Self::voters(); let bad_presentation_punishment = Self::present_slash_per_voter() * T::Balance::sa(voters.len() as u64); - ensure!(>::can_slash(aux.ref_into(), bad_presentation_punishment), "presenter must have sufficient slashable funds"); + ensure!(>::can_slash(aux.ref_into(), bad_presentation_punishment), "presenter must have sufficient slashable funds"); let mut leaderboard = Self::leaderboard().ok_or("leaderboard must exist while present phase active")?; ensure!(total > leaderboard[0].0, "candidate not worthy of leaderboard"); @@ -396,7 +400,7 @@ impl Module { } else { // we can rest assured it will be Ok since we checked `can_slash` earlier; still // better safe than sorry. - let _ = >::slash(aux.ref_into(), bad_presentation_punishment); + let _ = >::slash(aux.ref_into(), bad_presentation_punishment); Err(if dupe { "duplicate presentation" } else { "incorrect total" }) } } @@ -473,7 +477,7 @@ impl Module { >::put((number + Self::presentation_duration(), empty_seats as u32, expiring)); let voters = Self::voters(); - let votes = voters.iter().map(>::voting_balance).collect::>(); + let votes = voters.iter().map(>::voting_balance).collect::>(); >::put(votes); // initialise leaderboard. @@ -500,7 +504,7 @@ impl Module { .take_while(|&&(b, _)| !b.is_zero()) .take(coming as usize) { - >::unreserve(w, candidacy_bond); + >::unreserve(w, candidacy_bond); } // set the new council. @@ -622,14 +626,14 @@ mod tests { pub use runtime_io::with_externalities; pub use substrate_primitives::H256; use primitives::BuildStorage; - use primitives::traits::{HasPublicAux, Identity, BlakeTwo256}; + use primitives::traits::{HasPublicAux, BlakeTwo256}; use primitives::testing::{Digest, Header}; use substrate_primitives::KeccakHasher; impl_outer_dispatch! { #[derive(Debug, Clone, Eq, Serialize, Deserialize, PartialEq)] pub enum Proposal { - Staking = 0, + Balances = 0, Democracy = 1, } } @@ -654,25 +658,16 @@ mod tests { type Header = Header; type Event = (); } - impl session::Trait for Test { - type ConvertAccountIdToSessionKey = Identity; - type OnSessionChange = staking::Module; - type Event = (); - } - impl staking::Trait for Test { - const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1; + impl balances::Trait for Test { type Balance = u64; type AccountIndex = u64; type OnFreeBalanceZero = (); + type IsAccountLiquid = (); type Event = (); } impl democracy::Trait for Test { type Proposal = Proposal; } - impl timestamp::Trait for Test { - const TIMESTAMP_SET_POSITION: u32 = 0; - type Moment = u64; - } impl Trait for Test {} pub fn new_test_ext(with_council: bool) -> runtime_io::TestExternalities { @@ -681,27 +676,14 @@ mod tests { code: vec![], authorities: vec![], }.build_storage().unwrap()); - t.extend(session::GenesisConfig::{ - session_length: 1, //??? or 2? - validators: vec![10, 20], - }.build_storage().unwrap()); - t.extend(staking::GenesisConfig::{ - sessions_per_era: 1, - current_era: 0, + t.extend(balances::GenesisConfig::{ balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], - intentions: vec![], - validator_count: 2, - minimum_validator_count: 0, - bonding_duration: 0, transaction_base_fee: 0, transaction_byte_fee: 0, existential_deposit: 0, transfer_fee: 0, creation_fee: 0, reclaim_rebate: 0, - early_era_slash: 0, - session_reward: 0, - offline_slash_grace: 0, }.build_storage().unwrap()); t.extend(democracy::GenesisConfig::{ launch_period: 1, @@ -726,12 +708,11 @@ mod tests { cooloff_period: 2, voting_period: 1, }.build_storage().unwrap()); - t.extend(timestamp::GenesisConfig::::default().build_storage().unwrap()); t.into() } pub type System = system::Module; - pub type Staking = staking::Module; + pub type Balances = balances::Module; pub type Democracy = democracy::Module; pub type Council = Module; @@ -1045,7 +1026,7 @@ mod tests { #[test] fn double_presentations_should_be_punished() { with_externalities(&mut new_test_ext(false), || { - assert!(Staking::can_slash(&4, 10)); + assert!(Balances::can_slash(&4, 10)); System::set_block_number(4); assert_ok!(Council::submit_candidacy(&2, 0)); @@ -1061,7 +1042,7 @@ mod tests { assert_ok!(Council::end_block(System::block_number())); assert_eq!(Council::active_council(), vec![(5, 11), (2, 11)]); - assert_eq!(Staking::voting_balance(&4), 38); + assert_eq!(Balances::voting_balance(&4), 38); }); } @@ -1094,8 +1075,8 @@ mod tests { assert_eq!(Council::voters(), vec![5]); assert_eq!(Council::approvals_of(2).len(), 0); - assert_eq!(Staking::voting_balance(&2), 17); - assert_eq!(Staking::voting_balance(&5), 53); + assert_eq!(Balances::voting_balance(&2), 17); + assert_eq!(Balances::voting_balance(&5), 53); }); } @@ -1153,8 +1134,8 @@ mod tests { assert_eq!(Council::voters(), vec![5]); assert_eq!(Council::approvals_of(2).len(), 0); - assert_eq!(Staking::voting_balance(&2), 17); - assert_eq!(Staking::voting_balance(&5), 53); + assert_eq!(Balances::voting_balance(&2), 17); + assert_eq!(Balances::voting_balance(&5), 53); }); } @@ -1254,7 +1235,7 @@ mod tests { assert_eq!(Council::voters(), vec![2, 3, 5]); assert_eq!(Council::approvals_of(4).len(), 0); - assert_eq!(Staking::voting_balance(&4), 37); + assert_eq!(Balances::voting_balance(&4), 37); }); } @@ -1381,8 +1362,8 @@ mod tests { assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_eq!(Staking::free_balance(&1), 1); - assert_eq!(Staking::reserved_balance(&1), 9); + assert_eq!(Balances::free_balance(&1), 1); + assert_eq!(Balances::reserved_balance(&1), 9); assert_noop!(Council::present_winner(&1, 1.into(), 20, 0), "presenter must have sufficient slashable funds"); }); } @@ -1392,7 +1373,7 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); assert!(!Council::presentation_active()); - assert_eq!(Staking::voting_balance(&4), 40); + assert_eq!(Balances::voting_balance(&4), 40); assert_ok!(Council::submit_candidacy(&2, 0)); assert_ok!(Council::submit_candidacy(&5, 1)); @@ -1403,7 +1384,7 @@ mod tests { System::set_block_number(6); assert_err!(Council::present_winner(&4, 2.into(), 80, 0), "incorrect total"); - assert_eq!(Staking::voting_balance(&4), 38); + assert_eq!(Balances::voting_balance(&4), 38); }); } diff --git a/substrate/runtime/council/src/voting.rs b/substrate/runtime/council/src/voting.rs index b26df57e604f8..3d0c0d7268404 100644 --- a/substrate/runtime/council/src/voting.rs +++ b/substrate/runtime/council/src/voting.rs @@ -227,7 +227,7 @@ mod tests { fn basic_environment_works() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - assert_eq!(Staking::bonding_duration(), 0); + assert_eq!(Balances::free_balance(&42), 0); assert_eq!(CouncilVoting::cooloff_period(), 2); assert_eq!(CouncilVoting::voting_period(), 1); assert_eq!(CouncilVoting::will_still_be_councillor_at(&1, 1), true); @@ -243,8 +243,8 @@ mod tests { }); } - fn bonding_duration_proposal(value: u64) -> Proposal { - Proposal::Staking(staking::PrivCall::set_bonding_duration(value)) + fn set_balance_proposal(value: u64) -> Proposal { + Proposal::Balances(balances::PrivCall::set_balance(balances::address::Address::Id(42), value, 0)) } fn cancel_referendum_proposal(id: u32) -> Proposal { @@ -255,7 +255,7 @@ mod tests { fn referendum_cancellation_should_work_when_unanimous() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - let proposal = bonding_duration_proposal(42); + let proposal = set_balance_proposal(42); assert_ok!(Democracy::internal_start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove), 0); assert_eq!(Democracy::active_referendums(), vec![(0, 4, proposal, VoteThreshold::SuperMajorityApprove)]); @@ -270,7 +270,7 @@ mod tests { System::set_block_number(2); assert_ok!(CouncilVoting::end_block(System::block_number())); assert_eq!(Democracy::active_referendums(), vec![]); - assert_eq!(Staking::bonding_duration(), 0); + assert_eq!(Balances::free_balance(&42), 0); }); } @@ -278,7 +278,7 @@ mod tests { fn referendum_cancellation_should_fail_when_not_unanimous() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - let proposal = bonding_duration_proposal(42); + let proposal = set_balance_proposal(42); assert_ok!(Democracy::internal_start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove), 0); let cancellation = cancel_referendum_proposal(0); @@ -298,7 +298,7 @@ mod tests { fn referendum_cancellation_should_fail_when_abstentions() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - let proposal = bonding_duration_proposal(42); + let proposal = set_balance_proposal(42); assert_ok!(Democracy::internal_start_referendum(proposal.clone(), VoteThreshold::SuperMajorityApprove), 0); let cancellation = cancel_referendum_proposal(0); @@ -317,7 +317,7 @@ mod tests { fn veto_should_work() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - let proposal = bonding_duration_proposal(42); + let proposal = set_balance_proposal(42); let hash = proposal.blake2_256().into(); assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); assert_ok!(CouncilVoting::veto(&2, hash)); @@ -330,7 +330,7 @@ mod tests { fn double_veto_should_not_work() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - let proposal = bonding_duration_proposal(42); + let proposal = set_balance_proposal(42); let hash = proposal.blake2_256().into(); assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); assert_ok!(CouncilVoting::veto(&2, hash)); @@ -345,7 +345,7 @@ mod tests { fn retry_in_cooloff_should_not_work() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - let proposal = bonding_duration_proposal(42); + let proposal = set_balance_proposal(42); let hash = proposal.blake2_256().into(); assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); assert_ok!(CouncilVoting::veto(&2, hash)); @@ -359,7 +359,7 @@ mod tests { fn retry_after_cooloff_should_work() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - let proposal = bonding_duration_proposal(42); + let proposal = set_balance_proposal(42); let hash = proposal.blake2_256().into(); assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); assert_ok!(CouncilVoting::veto(&2, hash)); @@ -373,7 +373,7 @@ mod tests { System::set_block_number(4); assert_ok!(CouncilVoting::end_block(System::block_number())); assert_eq!(CouncilVoting::proposals().len(), 0); - assert_eq!(Democracy::active_referendums(), vec![(0, 7, bonding_duration_proposal(42), VoteThreshold::SimpleMajority)]); + assert_eq!(Democracy::active_referendums(), vec![(0, 7, set_balance_proposal(42), VoteThreshold::SimpleMajority)]); }); } @@ -381,7 +381,7 @@ mod tests { fn alternative_double_veto_should_work() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - let proposal = bonding_duration_proposal(42); + let proposal = set_balance_proposal(42); let hash = proposal.blake2_256().into(); assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); assert_ok!(CouncilVoting::veto(&2, hash)); @@ -398,7 +398,7 @@ mod tests { fn simple_propose_should_work() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - let proposal = bonding_duration_proposal(42); + let proposal = set_balance_proposal(42); let hash = proposal.blake2_256().into(); assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); assert_eq!(CouncilVoting::proposals().len(), 1); @@ -412,7 +412,7 @@ mod tests { fn unvoted_proposal_should_expire_without_action() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - let proposal = bonding_duration_proposal(42); + let proposal = set_balance_proposal(42); assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); assert_eq!(CouncilVoting::tally(&proposal.blake2_256().into()), (1, 0, 2)); assert_ok!(CouncilVoting::end_block(System::block_number())); @@ -428,7 +428,7 @@ mod tests { fn unanimous_proposal_should_expire_with_biased_referendum() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - let proposal = bonding_duration_proposal(42); + let proposal = set_balance_proposal(42); assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); assert_ok!(CouncilVoting::vote(&2, proposal.blake2_256().into(), true)); assert_ok!(CouncilVoting::vote(&3, proposal.blake2_256().into(), true)); @@ -446,7 +446,7 @@ mod tests { fn majority_proposal_should_expire_with_unbiased_referendum() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - let proposal = bonding_duration_proposal(42); + let proposal = set_balance_proposal(42); assert_ok!(CouncilVoting::propose(&1, Box::new(proposal.clone()))); assert_ok!(CouncilVoting::vote(&2, proposal.blake2_256().into(), true)); assert_ok!(CouncilVoting::vote(&3, proposal.blake2_256().into(), false)); @@ -464,7 +464,7 @@ mod tests { fn propose_by_public_should_not_work() { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); - let proposal = bonding_duration_proposal(42); + let proposal = set_balance_proposal(42); assert_noop!(CouncilVoting::propose(&4, Box::new(proposal)), "proposer would not be on council"); }); } From fafaf19305f91747b70e5c58a723d520acecf24b Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 29 Aug 2018 22:02:14 +0200 Subject: [PATCH 09/19] Remove unneeded cruft from democracy --- substrate/runtime/council/src/lib.rs | 7 -- substrate/runtime/democracy/src/lib.rs | 135 ++++++++----------------- 2 files changed, 40 insertions(+), 102 deletions(-) diff --git a/substrate/runtime/council/src/lib.rs b/substrate/runtime/council/src/lib.rs index e2dd48de4974f..057c668656fca 100644 --- a/substrate/runtime/council/src/lib.rs +++ b/substrate/runtime/council/src/lib.rs @@ -644,9 +644,6 @@ mod tests { impl HasPublicAux for Test { type PublicAux = u64; } - impl consensus::Trait for Test { - type SessionKey = u64; - } impl system::Trait for Test { type PublicAux = ::PublicAux; type Index = u64; @@ -672,10 +669,6 @@ mod tests { pub fn new_test_ext(with_council: bool) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap(); - t.extend(consensus::GenesisConfig::{ - code: vec![], - authorities: vec![], - }.build_storage().unwrap()); t.extend(balances::GenesisConfig::{ balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], transaction_base_fee: 0, diff --git a/substrate/runtime/democracy/src/lib.rs b/substrate/runtime/democracy/src/lib.rs index 2079681ae6dbe..12f0a32753cff 100644 --- a/substrate/runtime/democracy/src/lib.rs +++ b/substrate/runtime/democracy/src/lib.rs @@ -367,16 +367,14 @@ mod tests { use runtime_io::with_externalities; use substrate_primitives::{H256, KeccakHasher}; use primitives::BuildStorage; - use primitives::traits::{HasPublicAux, Identity, BlakeTwo256}; + use primitives::traits::{HasPublicAux, BlakeTwo256}; use primitives::testing::{Digest, Header}; - use session::OnSessionChange; impl_outer_dispatch! { #[derive(Debug, Clone, Eq, Serialize, Deserialize, PartialEq)] pub enum Proposal { - Session = 0, - Staking = 1, - Democracy = 2, + Balances = 0, + Democracy = 1, } } @@ -386,9 +384,6 @@ mod tests { impl HasPublicAux for Test { type PublicAux = u64; } - impl consensus::Trait for Test { - type SessionKey = u64; - } impl system::Trait for Test { type PublicAux = ::PublicAux; type Index = u64; @@ -403,37 +398,16 @@ mod tests { impl balances::Trait for Test { type Balance = u64; type AccountIndex = u64; - type OnFreeBalanceZero = Staking; - type IsAccountLiquid = Staking; - type Event = (); - } - impl session::Trait for Test { - type ConvertAccountIdToSessionKey = Identity; - type OnSessionChange = Staking; - type Event = (); - } - impl staking::Trait for Test { - const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1; + type OnFreeBalanceZero = (); + type IsAccountLiquid = (); type Event = (); } - impl timestamp::Trait for Test { - const TIMESTAMP_SET_POSITION: u32 = 0; - type Moment = u64; - } impl Trait for Test { type Proposal = Proposal; } fn new_test_ext() -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap(); - t.extend(consensus::GenesisConfig::{ - code: vec![], - authorities: vec![], - }.build_storage().unwrap()); - t.extend(session::GenesisConfig::{ - session_length: 1, //??? or 2? - validators: vec![10, 20], - }.build_storage().unwrap()); t.extend(balances::GenesisConfig::{ balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], transaction_base_fee: 0, @@ -443,30 +417,16 @@ mod tests { creation_fee: 0, reclaim_rebate: 0, }.build_storage().unwrap()); - t.extend(staking::GenesisConfig::{ - sessions_per_era: 1, - current_era: 0, - intentions: vec![], - validator_count: 2, - minimum_validator_count: 0, - bonding_duration: 3, - early_era_slash: 0, - session_reward: 0, - offline_slash_grace: 0, - }.build_storage().unwrap()); t.extend(GenesisConfig::{ launch_period: 1, voting_period: 1, minimum_deposit: 1, }.build_storage().unwrap()); - t.extend(timestamp::GenesisConfig::::default().build_storage().unwrap()); t.into() } type System = system::Module; type Balances = balances::Module; - type Session = session::Module; - type Staking = staking::Module; type Democracy = Module; #[test] @@ -476,22 +436,26 @@ mod tests { assert_eq!(Democracy::voting_period(), 1); assert_eq!(Democracy::minimum_deposit(), 1); assert_eq!(Democracy::referendum_count(), 0); - assert_eq!(Staking::sessions_per_era(), 1); + assert_eq!(Balances::free_balance(&42), 0); assert_eq!(Balances::total_stake(), 210); }); } - fn propose_sessions_per_era(who: u64, value: u64, locked: u64) -> super::Result { - Democracy::propose(&who, Box::new(Proposal::Staking(staking::PrivCall::set_sessions_per_era(value))), locked) + fn set_balance_proposal(value: u64) -> Proposal { + Proposal::Balances(balances::PrivCall::set_balance(balances::address::Address::Id(42), value, 0)) + } + + fn propose_set_balance(who: u64, value: u64, locked: u64) -> super::Result { + Democracy::propose(&who, Box::new(set_balance_proposal(value)), locked) } #[test] fn locked_for_should_work() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - assert_ok!(propose_sessions_per_era(1, 2, 2)); - assert_ok!(propose_sessions_per_era(1, 4, 4)); - assert_ok!(propose_sessions_per_era(1, 3, 3)); + assert_ok!(propose_set_balance(1, 2, 2)); + assert_ok!(propose_set_balance(1, 4, 4)); + assert_ok!(propose_set_balance(1, 3, 3)); assert_eq!(Democracy::locked_for(0), Some(2)); assert_eq!(Democracy::locked_for(1), Some(4)); assert_eq!(Democracy::locked_for(2), Some(3)); @@ -502,7 +466,7 @@ mod tests { fn single_proposal_should_work() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - assert_ok!(propose_sessions_per_era(1, 2, 1)); + assert_ok!(propose_set_balance(1, 2, 1)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); System::set_block_number(2); @@ -515,9 +479,8 @@ mod tests { assert_eq!(Democracy::tally(r), (10, 0)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::on_session_change(0, true); - assert_eq!(Staking::era_length(), 2); + assert_eq!(Balances::free_balance(&42), 2); }); } @@ -525,7 +488,7 @@ mod tests { fn deposit_for_proposals_should_be_taken() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - assert_ok!(propose_sessions_per_era(1, 2, 5)); + assert_ok!(propose_set_balance(1, 2, 5)); assert_ok!(Democracy::second(&2, 0)); assert_ok!(Democracy::second(&5, 0)); assert_ok!(Democracy::second(&5, 0)); @@ -540,7 +503,7 @@ mod tests { fn deposit_for_proposals_should_be_returned() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - assert_ok!(propose_sessions_per_era(1, 2, 5)); + assert_ok!(propose_set_balance(1, 2, 5)); assert_ok!(Democracy::second(&2, 0)); assert_ok!(Democracy::second(&5, 0)); assert_ok!(Democracy::second(&5, 0)); @@ -556,7 +519,7 @@ mod tests { fn proposal_with_deposit_below_minimum_should_not_work() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - assert_noop!(propose_sessions_per_era(1, 2, 0), "value too low"); + assert_noop!(propose_set_balance(1, 2, 0), "value too low"); }); } @@ -564,7 +527,7 @@ mod tests { fn poor_proposer_should_not_work() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - assert_noop!(propose_sessions_per_era(1, 2, 11), "proposer\'s balance too low"); + assert_noop!(propose_set_balance(1, 2, 11), "proposer\'s balance too low"); }); } @@ -572,53 +535,41 @@ mod tests { fn poor_seconder_should_not_work() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - assert_ok!(propose_sessions_per_era(2, 2, 11)); + assert_ok!(propose_set_balance(2, 2, 11)); assert_noop!(Democracy::second(&1, 0), "seconder\'s balance too low"); }); } - fn propose_bonding_duration(who: u64, value: u64, locked: u64) -> super::Result { - Democracy::propose(&who, Box::new(Proposal::Staking(staking::PrivCall::set_bonding_duration(value))), locked) - } - #[test] fn runners_up_should_come_after() { with_externalities(&mut new_test_ext(), || { System::set_block_number(0); - assert_ok!(propose_bonding_duration(1, 2, 2)); - assert_ok!(propose_bonding_duration(1, 4, 4)); - assert_ok!(propose_bonding_duration(1, 3, 3)); + assert_ok!(propose_set_balance(1, 2, 2)); + assert_ok!(propose_set_balance(1, 4, 4)); + assert_ok!(propose_set_balance(1, 3, 3)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); System::set_block_number(1); assert_ok!(Democracy::vote(&1, 0, true)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::on_session_change(0, true); - assert_eq!(Staking::bonding_duration(), 4); + assert_eq!(Balances::free_balance(&42), 4); System::set_block_number(2); assert_ok!(Democracy::vote(&1, 1, true)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::on_session_change(0, true); - assert_eq!(Staking::bonding_duration(), 3); + assert_eq!(Balances::free_balance(&42), 3); System::set_block_number(3); assert_ok!(Democracy::vote(&1, 2, true)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::on_session_change(0, true); - assert_eq!(Staking::bonding_duration(), 2); }); } - fn sessions_per_era_proposal(value: u64) -> Proposal { - Proposal::Staking(staking::PrivCall::set_sessions_per_era(value)) - } - #[test] fn simple_passing_should_work() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - let r = Democracy::inject_referendum(1, sessions_per_era_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); + let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); assert_ok!(Democracy::vote(&1, r, true)); assert_eq!(Democracy::voters_for(r), vec![1]); @@ -626,9 +577,8 @@ mod tests { assert_eq!(Democracy::tally(r), (10, 0)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::on_session_change(0, true); - assert_eq!(Staking::era_length(), 2); + assert_eq!(Balances::free_balance(&42), 2); }); } @@ -636,14 +586,13 @@ mod tests { fn cancel_referendum_should_work() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - let r = Democracy::inject_referendum(1, sessions_per_era_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); + let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); assert_ok!(Democracy::vote(&1, r, true)); assert_ok!(Democracy::cancel_referendum(r)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::on_session_change(0, true); - assert_eq!(Staking::era_length(), 1); + assert_eq!(Balances::free_balance(&42), 0); }); } @@ -651,7 +600,7 @@ mod tests { fn simple_failing_should_work() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - let r = Democracy::inject_referendum(1, sessions_per_era_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); + let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); assert_ok!(Democracy::vote(&1, r, false)); assert_eq!(Democracy::voters_for(r), vec![1]); @@ -659,9 +608,8 @@ mod tests { assert_eq!(Democracy::tally(r), (0, 10)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::on_session_change(0, true); - assert_eq!(Staking::era_length(), 1); + assert_eq!(Balances::free_balance(&42), 0); }); } @@ -669,7 +617,7 @@ mod tests { fn controversial_voting_should_work() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - let r = Democracy::inject_referendum(1, sessions_per_era_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); + let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); assert_ok!(Democracy::vote(&1, r, true)); assert_ok!(Democracy::vote(&2, r, false)); assert_ok!(Democracy::vote(&3, r, false)); @@ -680,9 +628,8 @@ mod tests { assert_eq!(Democracy::tally(r), (110, 100)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::on_session_change(0, true); - assert_eq!(Staking::era_length(), 2); + assert_eq!(Balances::free_balance(&42), 2); }); } @@ -690,27 +637,26 @@ mod tests { fn controversial_low_turnout_voting_should_work() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - let r = Democracy::inject_referendum(1, sessions_per_era_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); + let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); assert_ok!(Democracy::vote(&5, r, false)); assert_ok!(Democracy::vote(&6, r, true)); assert_eq!(Democracy::tally(r), (60, 50)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::on_session_change(0, true); - assert_eq!(Staking::era_length(), 1); + assert_eq!(Balances::free_balance(&42), 0); }); } #[test] fn passing_low_turnout_voting_should_work() { with_externalities(&mut new_test_ext(), || { - assert_eq!(Staking::era_length(), 1); + assert_eq!(Balances::free_balance(&42), 0); assert_eq!(Balances::total_stake(), 210); System::set_block_number(1); - let r = Democracy::inject_referendum(1, sessions_per_era_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); + let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove).unwrap(); assert_ok!(Democracy::vote(&4, r, true)); assert_ok!(Democracy::vote(&5, r, false)); assert_ok!(Democracy::vote(&6, r, true)); @@ -718,9 +664,8 @@ mod tests { assert_eq!(Democracy::tally(r), (100, 50)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - Staking::on_session_change(0, true); - assert_eq!(Staking::era_length(), 2); + assert_eq!(Balances::free_balance(&42), 2); }); } } From 8fcee6eadd9254959e468492238bcd67960d6d1a Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 29 Aug 2018 22:16:06 +0200 Subject: [PATCH 10/19] Fix up contract module --- Cargo.lock | 11 +- substrate/runtime/contract/Cargo.toml | 10 +- substrate/runtime/contract/src/account_db.rs | 9 +- substrate/runtime/contract/src/exec.rs | 11 +- substrate/runtime/contract/src/gas.rs | 16 +- substrate/runtime/contract/src/lib.rs | 13 +- substrate/runtime/contract/src/tests.rs | 164 +++++++------------ substrate/runtime/contract/src/vm/mod.rs | 6 +- substrate/runtime/council/Cargo.toml | 8 - substrate/runtime/council/src/lib.rs | 8 - substrate/runtime/democracy/Cargo.toml | 6 - substrate/runtime/democracy/src/lib.rs | 8 - 12 files changed, 87 insertions(+), 183 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d8577f21376b3..6c15be4a53ad8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2706,16 +2706,13 @@ dependencies = [ "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-primitives 0.1.0", - "substrate-runtime-consensus 0.1.0", + "substrate-runtime-balances 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", "substrate-runtime-sandbox 0.1.0", - "substrate-runtime-session 0.1.0", - "substrate-runtime-staking 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", - "substrate-runtime-timestamp 0.1.0", "wabt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2736,12 +2733,9 @@ dependencies = [ "substrate-runtime-democracy 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", - "substrate-runtime-session 0.1.0", - "substrate-runtime-staking 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", - "substrate-runtime-timestamp 0.1.0", ] [[package]] @@ -2759,12 +2753,9 @@ dependencies = [ "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", - "substrate-runtime-session 0.1.0", - "substrate-runtime-staking 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", - "substrate-runtime-timestamp 0.1.0", ] [[package]] diff --git a/substrate/runtime/contract/Cargo.toml b/substrate/runtime/contract/Cargo.toml index 0658425c06cb4..f72c2b490ed75 100644 --- a/substrate/runtime/contract/Cargo.toml +++ b/substrate/runtime/contract/Cargo.toml @@ -8,16 +8,13 @@ serde = { version = "1.0", default_features = false } serde_derive = { version = "1.0", optional = true } substrate-codec = { path = "../../codec", default_features = false } substrate-primitives = { path = "../../primitives" } -substrate-runtime-consensus = { path = "../../runtime/consensus", default_features = false } substrate-runtime-primitives = { path = "../../runtime/primitives" } substrate-runtime-io = { path = "../../runtime-io", default_features = false } substrate-runtime-std = { path = "../../runtime-std", default_features = false } substrate-runtime-sandbox = { path = "../../runtime-sandbox", default_features = false } -substrate-runtime-staking = { path = "../../runtime/staking", default_features = false } substrate-runtime-support = { path = "../../runtime-support", default_features = false } substrate-runtime-system = { path = "../../runtime/system", default_features = false } -substrate-runtime-session = { path = "../session", default_features = false } -substrate-runtime-timestamp = { path = "../timestamp", default_features = false } +substrate-runtime-balances = { path = "../balances", default_features = false } parity-wasm = { version = "0.31", default_features = false } pwasm-utils = { version = "0.3", default_features = false } @@ -32,15 +29,12 @@ std = [ "serde/std", "substrate-codec/std", "substrate-runtime-primitives/std", - "substrate-runtime-consensus/std", "substrate-runtime-io/std", "substrate-runtime-std/std", + "substrate-runtime-balances/std", "substrate-runtime-sandbox/std", - "substrate-runtime-staking/std", "substrate-runtime-support/std", "substrate-runtime-system/std", - "substrate-runtime-timestamp/std", - "substrate-runtime-session/std", "parity-wasm/std", "pwasm-utils/std", ] diff --git a/substrate/runtime/contract/src/account_db.rs b/substrate/runtime/contract/src/account_db.rs index e5ad0e2b88391..d7ff094003c97 100644 --- a/substrate/runtime/contract/src/account_db.rs +++ b/substrate/runtime/contract/src/account_db.rs @@ -22,8 +22,7 @@ use rstd::cell::RefCell; use rstd::collections::btree_map::{BTreeMap, Entry}; use rstd::prelude::*; use runtime_support::StorageMap; -use staking; -use system; +use {balances, system}; pub struct ChangeEntry { balance: Option, @@ -61,13 +60,13 @@ impl AccountDb for DirectAccountDb { >::get(account) } fn get_balance(&self, account: &T::AccountId) -> T::Balance { - staking::Module::::free_balance(account) + balances::Module::::free_balance(account) } fn commit(&mut self, s: ChangeSet) { for (address, changed) in s.into_iter() { if let Some(balance) = changed.balance { - if let staking::UpdateBalanceOutcome::AccountKilled = - staking::Module::::set_free_balance_creating(&address, balance) + if let balances::UpdateBalanceOutcome::AccountKilled = + balances::Module::::set_free_balance_creating(&address, balance) { // Account killed. This will ultimately lead to calling `OnFreeBalanceZero` callback // which will make removal of CodeOf and StorageOf for this account. diff --git a/substrate/runtime/contract/src/exec.rs b/substrate/runtime/contract/src/exec.rs index a62e2ce97f972..5cd461647926f 100644 --- a/substrate/runtime/contract/src/exec.rs +++ b/substrate/runtime/contract/src/exec.rs @@ -22,8 +22,7 @@ use vm; use rstd::prelude::*; use runtime_primitives::traits::{Zero, CheckedAdd, CheckedSub}; use runtime_support::{StorageMap, StorageValue}; -use staking; -use system; +use balances::{self, IsAccountLiquid}; pub struct CreateReceipt { pub address: T::AccountId, @@ -185,9 +184,9 @@ fn transfer( >::contract_fee() } else { if would_create { - >::creation_fee() + >::creation_fee() } else { - >::transfer_fee() + >::transfer_fee() } }; @@ -200,10 +199,10 @@ fn transfer( Some(b) => b, None => return Err("balance too low to send value"), }; - if would_create && value < >::existential_deposit() { + if would_create && value < >::existential_deposit() { return Err("value too low to create account"); } - if >::bondage(transactor) > >::block_number() { + if !::IsAccountLiquid::is_account_liquid(transactor) { return Err("bondage too high to send value"); } diff --git a/substrate/runtime/contract/src/gas.rs b/substrate/runtime/contract/src/gas.rs index b405e31d7fd59..9d1978f7a527c 100644 --- a/substrate/runtime/contract/src/gas.rs +++ b/substrate/runtime/contract/src/gas.rs @@ -17,7 +17,7 @@ use {Trait, Module, GasSpent}; use runtime_primitives::traits::{As, CheckedMul, CheckedSub, Zero}; use runtime_support::StorageValue; -use staking; +use balances; #[must_use] #[derive(Debug, PartialEq, Eq)] @@ -146,15 +146,15 @@ pub fn buy_gas( // Buy the specified amount of gas. let gas_price = >::gas_price(); - let b = >::free_balance(transactor); + let b = >::free_balance(transactor); let cost = >::as_(gas_limit.clone()) .checked_mul(&gas_price) .ok_or("overflow multiplying gas limit by price")?; - if b < cost + >::existential_deposit() { + if b < cost + >::existential_deposit() { return Err("not enough funds for transaction fee"); } - >::set_free_balance(transactor, b - cost); - >::decrease_total_stake_by(cost); + >::set_free_balance(transactor, b - cost); + >::decrease_total_stake_by(cost); Ok(GasMeter { limit: gas_limit, gas_left: gas_limit, @@ -171,8 +171,8 @@ pub fn refund_unused_gas(transactor: &T::AccountId, gas_meter: GasMete >::put(gas_spent); // Refund gas left by the price it was bought. - let b = >::free_balance(transactor); + let b = >::free_balance(transactor); let refund = >::as_(gas_meter.gas_left) * gas_meter.gas_price; - >::set_free_balance(transactor, b + refund); - >::increase_total_stake_by(refund); + >::set_free_balance(transactor, b + refund); + >::increase_total_stake_by(refund); } diff --git a/substrate/runtime/contract/src/lib.rs b/substrate/runtime/contract/src/lib.rs index dbb5146aa9ecd..9f77b07fb8816 100644 --- a/substrate/runtime/contract/src/lib.rs +++ b/substrate/runtime/contract/src/lib.rs @@ -70,16 +70,9 @@ extern crate substrate_runtime_sandbox as sandbox; #[cfg_attr(feature = "std", macro_use)] extern crate substrate_runtime_std as rstd; -extern crate substrate_runtime_consensus as consensus; extern crate substrate_runtime_balances as balances; -extern crate substrate_runtime_staking as staking; extern crate substrate_runtime_system as system; -#[cfg(test)] -extern crate substrate_runtime_timestamp as timestamp; -#[cfg(test)] -extern crate substrate_runtime_session as session; - #[macro_use] extern crate substrate_runtime_support as runtime_support; @@ -113,7 +106,7 @@ use runtime_primitives::traits::{As, RefInto, SimpleArithmetic, Executable}; use runtime_support::dispatch::Result; use runtime_support::{Parameter, StorageMap, StorageValue}; -pub trait Trait: system::Trait + staking::Trait + consensus::Trait { +pub trait Trait: balances::Trait { /// Function type to get the contract address given the creator. type DetermineContractAddress: ContractAddressFor; @@ -189,7 +182,7 @@ impl double_map::StorageDoubleMap for StorageOf { impl Module { /// Make a call to a specified account, optionally transferring some balance. fn call( - aux: &::PublicAux, + aux: &::PublicAux, dest: T::AccountId, value: T::Balance, gas_limit: T::Gas, @@ -234,7 +227,7 @@ impl Module { /// after the execution is saved as the `code` of the account. That code will be invoked /// upon any message received by this account. fn create( - aux: &::PublicAux, + aux: &::PublicAux, endowment: T::Balance, gas_limit: T::Gas, ctor_code: Vec, diff --git a/substrate/runtime/contract/src/tests.rs b/substrate/runtime/contract/src/tests.rs index 69b85b9f4707f..21e89202b22fd 100644 --- a/substrate/runtime/contract/src/tests.rs +++ b/substrate/runtime/contract/src/tests.rs @@ -17,13 +17,13 @@ use double_map::StorageDoubleMap; use runtime_io::with_externalities; use runtime_primitives::testing::{Digest, H256, Header}; -use runtime_primitives::traits::{BlakeTwo256, HasPublicAux, Identity}; +use runtime_primitives::traits::{BlakeTwo256, HasPublicAux}; use runtime_primitives::BuildStorage; use runtime_support::StorageMap; use substrate_primitives::KeccakHasher; use wabt; use { - consensus, runtime_io, session, staking, system, timestamp, CodeOf, ContractAddressFor, + runtime_io, balances, system, CodeOf, ContractAddressFor, GenesisConfig, Module, StorageOf, Trait, }; @@ -32,9 +32,6 @@ pub struct Test; impl HasPublicAux for Test { type PublicAux = u64; } -impl consensus::Trait for Test { - type SessionKey = u64; -} impl system::Trait for Test { type PublicAux = ::PublicAux; type Index = u64; @@ -46,20 +43,11 @@ impl system::Trait for Test { type Header = Header; type Event = (); } -impl timestamp::Trait for Test { - const TIMESTAMP_SET_POSITION: u32 = 0; - type Moment = u64; -} -impl staking::Trait for Test { - const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1; +impl balances::Trait for Test { type Balance = u64; type AccountIndex = u64; type OnFreeBalanceZero = Contract; - type Event = (); -} -impl session::Trait for Test { - type ConvertAccountIdToSessionKey = Identity; - type OnSessionChange = Staking; + type IsAccountLiquid = (); type Event = (); } impl Trait for Test { @@ -67,7 +55,7 @@ impl Trait for Test { type DetermineContractAddress = DummyContractAddressFor; } -type Staking = staking::Module; +type Balances = balances::Module; type Contract = Module; pub struct DummyContractAddressFor; @@ -109,45 +97,17 @@ impl ExtBuilder { .build_storage() .unwrap(); t.extend( - consensus::GenesisConfig:: { - code: vec![], - authorities: vec![], - }.build_storage() - .unwrap(), - ); - t.extend( - session::GenesisConfig:: { - session_length: 1, - validators: vec![10, 20], - }.build_storage() - .unwrap(), - ); - t.extend( - staking::GenesisConfig:: { - sessions_per_era: 1, - current_era: 0, + balances::GenesisConfig:: { balances: vec![], - intentions: vec![], - validator_count: 2, - minimum_validator_count: 0, - bonding_duration: 0, transaction_base_fee: 0, transaction_byte_fee: 0, existential_deposit: self.existential_deposit, transfer_fee: 0, creation_fee: 0, reclaim_rebate: 0, - early_era_slash: 0, - session_reward: 0, - offline_slash_grace: 0, }.build_storage() .unwrap(), ); - t.extend( - timestamp::GenesisConfig::::default() - .build_storage() - .unwrap(), - ); t.extend( GenesisConfig:: { contract_fee: 21, @@ -195,15 +155,15 @@ fn contract_transfer() { with_externalities(&mut ExtBuilder::default().build(), || { >::insert(1, code_transfer.to_vec()); - Staking::set_free_balance(&0, 100_000_000); - Staking::increase_total_stake_by(100_000_000); - Staking::set_free_balance(&1, 11); - Staking::increase_total_stake_by(11); + Balances::set_free_balance(&0, 100_000_000); + Balances::increase_total_stake_by(100_000_000); + Balances::set_free_balance(&1, 11); + Balances::increase_total_stake_by(11); assert_ok!(Contract::call(&0, 1, 3, 100_000, Vec::new())); assert_eq!( - Staking::free_balance(&0), + Balances::free_balance(&0), // 3 - value sent with the transaction // 2 * 6 - gas used by the contract (6) multiplied by gas price (2) // 2 * 135 - base gas fee for call (by transaction) @@ -211,11 +171,11 @@ fn contract_transfer() { 100_000_000 - 3 - (2 * 6) - (2 * 135) - (2 * 135), ); assert_eq!( - Staking::free_balance(&1), + Balances::free_balance(&1), 11 + 3 - CONTRACT_SHOULD_TRANSFER_VALUE, ); assert_eq!( - Staking::free_balance(&CONTRACT_SHOULD_TRANSFER_TO), + Balances::free_balance(&CONTRACT_SHOULD_TRANSFER_TO), CONTRACT_SHOULD_TRANSFER_VALUE, ); }); @@ -230,10 +190,10 @@ fn contract_transfer_oog() { with_externalities(&mut ExtBuilder::default().build(), || { >::insert(1, code_transfer.to_vec()); - Staking::set_free_balance(&0, 100_000_000); - Staking::increase_total_stake_by(100_000_000); - Staking::set_free_balance(&1, 11); - Staking::increase_total_stake_by(11); + Balances::set_free_balance(&0, 100_000_000); + Balances::increase_total_stake_by(100_000_000); + Balances::set_free_balance(&1, 11); + Balances::increase_total_stake_by(11); assert_err!( Contract::call(&0, 1, 3, 276, Vec::new()), @@ -241,15 +201,15 @@ fn contract_transfer_oog() { ); assert_eq!( - Staking::free_balance(&0), + Balances::free_balance(&0), // 3 - value sent with the transaction // 2 * 6 - gas used by the contract (6) multiplied by gas price (2) // 2 * 135 - base gas fee for call (by transaction) // 2 * 135 - base gas fee for call (by contract) 100_000_000 - (2 * 6) - (2 * 135) - (2 * 135), ); - assert_eq!(Staking::free_balance(&1), 11); - assert_eq!(Staking::free_balance(&CONTRACT_SHOULD_TRANSFER_TO), 0); + assert_eq!(Balances::free_balance(&1), 11); + assert_eq!(Balances::free_balance(&CONTRACT_SHOULD_TRANSFER_TO), 0); }); } @@ -262,10 +222,10 @@ fn contract_transfer_max_depth() { with_externalities(&mut ExtBuilder::default().build(), || { >::insert(CONTRACT_SHOULD_TRANSFER_TO, code_transfer.to_vec()); - Staking::set_free_balance(&0, 100_000_000); - Staking::increase_total_stake_by(100_000_000); - Staking::set_free_balance(&CONTRACT_SHOULD_TRANSFER_TO, 11); - Staking::increase_total_stake_by(11); + Balances::set_free_balance(&0, 100_000_000); + Balances::increase_total_stake_by(100_000_000); + Balances::set_free_balance(&CONTRACT_SHOULD_TRANSFER_TO, 11); + Balances::increase_total_stake_by(11); assert_err!( Contract::call(&0, CONTRACT_SHOULD_TRANSFER_TO, 3, 100_000, Vec::new()), @@ -273,14 +233,14 @@ fn contract_transfer_max_depth() { ); assert_eq!( - Staking::free_balance(&0), + Balances::free_balance(&0), // 3 - value sent with the transaction // 2 * 6 * 100 - gas used by the contract (6) multiplied by gas price (2) // multiplied by max depth (100). // 2 * 135 * 100 - base gas fee for call (by transaction) multiplied by max depth (100). 100_000_000 - (2 * 135 * 100) - (2 * 6 * 100), ); - assert_eq!(Staking::free_balance(&CONTRACT_SHOULD_TRANSFER_TO), 11); + assert_eq!(Balances::free_balance(&CONTRACT_SHOULD_TRANSFER_TO), 11); }); } @@ -360,11 +320,11 @@ fn contract_create() { let code_create = wabt::wat2wasm(&code_create(&code_ctor_transfer)).unwrap(); with_externalities(&mut ExtBuilder::default().build(), || { - Staking::set_free_balance(&0, 100_000_000); - Staking::increase_total_stake_by(100_000_000); - Staking::set_free_balance(&1, 0); - Staking::set_free_balance(&9, 30); - Staking::increase_total_stake_by(30); + Balances::set_free_balance(&0, 100_000_000); + Balances::increase_total_stake_by(100_000_000); + Balances::set_free_balance(&1, 0); + Balances::set_free_balance(&9, 30); + Balances::increase_total_stake_by(30); >::insert(1, code_create.to_vec()); @@ -383,23 +343,23 @@ fn contract_create() { // ((21 / 2) * 2) - price per account creation let expected_gas_after_create = 100_000_000 - 11 - (2 * 128) - (2 * 135) - (2 * 175) - ((21 / 2) * 2); - assert_eq!(Staking::free_balance(&0), expected_gas_after_create); - assert_eq!(Staking::free_balance(&1), 8); - assert_eq!(Staking::free_balance(&derived_address), 3); + assert_eq!(Balances::free_balance(&0), expected_gas_after_create); + assert_eq!(Balances::free_balance(&1), 8); + assert_eq!(Balances::free_balance(&derived_address), 3); // Initiate transfer to the newly created contract. assert_ok!(Contract::call(&0, derived_address, 22, 100_000, Vec::new())); assert_eq!( - Staking::free_balance(&0), + Balances::free_balance(&0), // 22 - value sent with the transaction // (2 * 6) - gas used by the contract // (2 * 135) - base gas fee for call (top level) // (2 * 135) - base gas fee for call (by transfer contract) expected_gas_after_create - 22 - (2 * 6) - (2 * 135) - (2 * 135), ); - assert_eq!(Staking::free_balance(&derived_address), 22 - 3); - assert_eq!(Staking::free_balance(&9), 36); + assert_eq!(Balances::free_balance(&derived_address), 22 - 3); + assert_eq!(Balances::free_balance(&9), 36); }); } @@ -414,10 +374,10 @@ fn top_level_create() { &0, ); - Staking::set_free_balance(&0, 100_000_000); - Staking::increase_total_stake_by(100_000_000); - Staking::set_free_balance(&derived_address, 30); - Staking::increase_total_stake_by(30); + Balances::set_free_balance(&0, 100_000_000); + Balances::increase_total_stake_by(100_000_000); + Balances::set_free_balance(&derived_address, 30); + Balances::increase_total_stake_by(30); assert_ok!(Contract::create( &0, @@ -432,10 +392,10 @@ fn top_level_create() { // (3 * 175) - base gas fee for create (175) (top level) multipled by gas price (3) // ((21 / 3) * 3) - price for contract creation assert_eq!( - Staking::free_balance(&0), + Balances::free_balance(&0), 100_000_000 - 11 - (3 * 122) - (3 * 175) - ((21 / 3) * 3) ); - assert_eq!(Staking::free_balance(&derived_address), 30 + 11); + assert_eq!(Balances::free_balance(&derived_address), 30 + 11); assert_eq!(>::get(&derived_address), code_transfer); }); @@ -456,12 +416,12 @@ fn refunds_unused_gas() { with_externalities(&mut ExtBuilder::default().build(), || { >::insert(1, code_nop.to_vec()); - Staking::set_free_balance(&0, 100_000_000); - Staking::increase_total_stake_by(100_000_000); + Balances::set_free_balance(&0, 100_000_000); + Balances::increase_total_stake_by(100_000_000); assert_ok!(Contract::call(&0, 1, 0, 100_000, Vec::new())); - assert_eq!(Staking::free_balance(&0), 100_000_000 - 4 - (2 * 135)); + assert_eq!(Balances::free_balance(&0), 100_000_000 - 4 - (2 * 135)); }); } @@ -470,12 +430,12 @@ fn call_with_zero_value() { with_externalities(&mut ExtBuilder::default().build(), || { >::insert(1, vec![]); - Staking::set_free_balance(&0, 100_000_000); - Staking::increase_total_stake_by(100_000_000); + Balances::set_free_balance(&0, 100_000_000); + Balances::increase_total_stake_by(100_000_000); assert_ok!(Contract::call(&0, 1, 0, 100_000, Vec::new())); - assert_eq!(Staking::free_balance(&0), 100_000_000 - (2 * 135)); + assert_eq!(Balances::free_balance(&0), 100_000_000 - (2 * 135)); }); } @@ -484,13 +444,13 @@ fn create_with_zero_endowment() { let code_nop = wabt::wat2wasm(CODE_NOP).unwrap(); with_externalities(&mut ExtBuilder::default().build(), || { - Staking::set_free_balance(&0, 100_000_000); - Staking::increase_total_stake_by(100_000_000); + Balances::set_free_balance(&0, 100_000_000); + Balances::increase_total_stake_by(100_000_000); assert_ok!(Contract::create(&0, 0, 100_000, code_nop, Vec::new())); assert_eq!( - Staking::free_balance(&0), + Balances::free_balance(&0), // 4 - for the gas spent by the constructor // 2 * 175 - base gas fee for create (175) multiplied by gas price (2) (top level) 100_000_000 - 4 - (2 * 175), @@ -505,13 +465,13 @@ fn account_removal_removes_storage() { || { // Setup two accounts with free balance above than exsistential threshold. { - Staking::set_free_balance(&1, 110); - Staking::increase_total_stake_by(110); + Balances::set_free_balance(&1, 110); + Balances::increase_total_stake_by(110); >::insert(1, b"foo".to_vec(), b"1".to_vec()); >::insert(1, b"bar".to_vec(), b"2".to_vec()); - Staking::set_free_balance(&2, 110); - Staking::increase_total_stake_by(110); + Balances::set_free_balance(&2, 110); + Balances::increase_total_stake_by(110); >::insert(2, b"hello".to_vec(), b"3".to_vec()); >::insert(2, b"world".to_vec(), b"4".to_vec()); } @@ -520,7 +480,7 @@ fn account_removal_removes_storage() { // the balance of account 1 is will be below than exsistential threshold. // // This should lead to the removal of all storage associated with this account. - assert_ok!(Staking::transfer(&1, 2.into(), 20)); + assert_ok!(Balances::transfer(&1, 2.into(), 20)); // Verify that all entries from account 1 is removed, while // entries from account 2 is in place. @@ -556,15 +516,15 @@ fn top_level_call_refunds_even_if_fails() { with_externalities(&mut ExtBuilder::default().gas_price(4).build(), || { >::insert(1, code_unreachable.to_vec()); - Staking::set_free_balance(&0, 100_000_000); - Staking::increase_total_stake_by(100_000_000); + Balances::set_free_balance(&0, 100_000_000); + Balances::increase_total_stake_by(100_000_000); assert_err!( Contract::call(&0, 1, 0, 100_000, Vec::new()), "vm execute returned error while call" ); - assert_eq!(Staking::free_balance(&0), 100_000_000 - (4 * 3) - (4 * 135)); + assert_eq!(Balances::free_balance(&0), 100_000_000 - (4 * 3) - (4 * 135)); }); } @@ -586,8 +546,8 @@ fn block_gas_limit() { || { >::insert(1, code_loop.to_vec()); - Staking::set_free_balance(&0, 100_000_000); - Staking::increase_total_stake_by(100_000_000); + Balances::set_free_balance(&0, 100_000_000); + Balances::increase_total_stake_by(100_000_000); // Spend 50_000 units of gas (OOG). assert_err!( diff --git a/substrate/runtime/contract/src/vm/mod.rs b/substrate/runtime/contract/src/vm/mod.rs index ec26fb2daabfb..5b3318e6fcc8a 100644 --- a/substrate/runtime/contract/src/vm/mod.rs +++ b/substrate/runtime/contract/src/vm/mod.rs @@ -21,12 +21,10 @@ use exec::{CallReceipt, CreateReceipt}; use gas::{GasMeter, GasMeterResult}; use rstd::prelude::*; use runtime_primitives::traits::{As, CheckedMul}; -use sandbox; -use staking; -use system; +use {sandbox, balances, system}; use Trait; -type BalanceOf = ::Balance; +type BalanceOf = ::Balance; type AccountIdOf = ::AccountId; mod prepare; diff --git a/substrate/runtime/council/Cargo.toml b/substrate/runtime/council/Cargo.toml index 8710a846cc9a9..4e9977ec576b8 100644 --- a/substrate/runtime/council/Cargo.toml +++ b/substrate/runtime/council/Cargo.toml @@ -21,11 +21,6 @@ substrate-runtime-balances = { path = "../balances", default_features = false } substrate-runtime-democracy = { path = "../democracy", default_features = false } substrate-runtime-system = { path = "../system", default_features = false } -[dev-dependencies] -substrate-runtime-timestamp = { path = "../timestamp" } -substrate-runtime-session = { path = "../session" } -substrate-runtime-staking = { path = "../staking" } - [features] default = ["std"] std = [ @@ -39,9 +34,6 @@ std = [ "substrate-runtime-io/std", "substrate-runtime-support/std", "substrate-runtime-primitives/std", - "substrate-runtime-consensus/std", "substrate-runtime-democracy/std", - "substrate-runtime-session/std", - "substrate-runtime-staking/std", "substrate-runtime-system/std", ] diff --git a/substrate/runtime/council/src/lib.rs b/substrate/runtime/council/src/lib.rs index 057c668656fca..2b2f4783b9c3a 100644 --- a/substrate/runtime/council/src/lib.rs +++ b/substrate/runtime/council/src/lib.rs @@ -34,17 +34,9 @@ extern crate substrate_runtime_io as runtime_io; #[macro_use] extern crate substrate_runtime_support; extern crate substrate_runtime_primitives as primitives; extern crate substrate_runtime_balances as balances; -extern crate substrate_runtime_consensus as consensus; extern crate substrate_runtime_democracy as democracy; extern crate substrate_runtime_system as system; -#[cfg(test)] -extern crate substrate_runtime_session as session; -#[cfg(test)] -extern crate substrate_runtime_staking as staking; -#[cfg(test)] -extern crate substrate_runtime_timestamp as timestamp; - use rstd::prelude::*; use primitives::traits::{Zero, One, RefInto, As, AuxLookup}; use substrate_runtime_support::{StorageValue, StorageMap}; diff --git a/substrate/runtime/democracy/Cargo.toml b/substrate/runtime/democracy/Cargo.toml index 3e77bc3b694bb..602bf1adb4190 100644 --- a/substrate/runtime/democracy/Cargo.toml +++ b/substrate/runtime/democracy/Cargo.toml @@ -19,11 +19,6 @@ substrate-runtime-balances = { path = "../balances", default_features = false } substrate-runtime-consensus = { path = "../consensus", default_features = false } substrate-runtime-system = { path = "../system", default_features = false } -[dev-dependencies] -substrate-runtime-timestamp = { path = "../timestamp" } -substrate-runtime-session = { path = "../session" } -substrate-runtime-staking = { path = "../staking" } - [features] default = ["std"] std = [ @@ -36,7 +31,6 @@ std = [ "substrate-runtime-io/std", "substrate-runtime-support/std", "substrate-runtime-primitives/std", - "substrate-runtime-consensus/std", "substrate-runtime-balances/std", "substrate-runtime-system/std", ] diff --git a/substrate/runtime/democracy/src/lib.rs b/substrate/runtime/democracy/src/lib.rs index 12f0a32753cff..87e84b7e73f19 100644 --- a/substrate/runtime/democracy/src/lib.rs +++ b/substrate/runtime/democracy/src/lib.rs @@ -39,16 +39,8 @@ extern crate substrate_codec as codec; extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_primitives as primitives; extern crate substrate_runtime_balances as balances; -extern crate substrate_runtime_consensus as consensus; extern crate substrate_runtime_system as system; -#[cfg(test)] -extern crate substrate_runtime_session as session; -#[cfg(test)] -extern crate substrate_runtime_staking as staking; -#[cfg(test)] -extern crate substrate_runtime_timestamp as timestamp; - use rstd::prelude::*; use rstd::result; use primitives::traits::{Zero, Executable, RefInto, As, MaybeSerializeDebug}; From 3c5f4a2075bb419e28151d86d10c41e445f55fe3 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 29 Aug 2018 23:04:59 +0200 Subject: [PATCH 11/19] Fix up rest of tests --- Cargo.lock | 2 + demo/cli/src/lib.rs | 20 +-- demo/executor/Cargo.toml | 1 + demo/executor/src/lib.rs | 151 +++++++++--------- demo/runtime/Cargo.toml | 2 + demo/runtime/src/lib.rs | 40 +++-- demo/runtime/wasm/Cargo.lock | 31 +++- demo/runtime/wasm/Cargo.toml | 2 + .../release/demo_runtime.compact.wasm | Bin 280201 -> 296537 bytes .../release/demo_runtime.wasm | Bin 280288 -> 296621 bytes .../release/runtime_test.compact.wasm | Bin 48146 -> 48096 bytes .../release/runtime_test.wasm | Bin 48356 -> 48306 bytes substrate/runtime/balances/src/lib.rs | 2 +- substrate/runtime/session/src/lib.rs | 1 - substrate/runtime/staking/src/lib.rs | 2 +- substrate/runtime/system/src/lib.rs | 1 + .../substrate_test_runtime.compact.wasm | Bin 51163 -> 51113 bytes .../release/substrate_test_runtime.wasm | Bin 51295 -> 51245 bytes 18 files changed, 151 insertions(+), 104 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c15be4a53ad8..c70ee12588e75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -451,6 +451,7 @@ dependencies = [ "substrate-executor 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-balances 0.1.0", "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", @@ -491,6 +492,7 @@ dependencies = [ "substrate-codec-derive 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-balances 0.1.0", "substrate-runtime-consensus 0.1.0", "substrate-runtime-council 0.1.0", "substrate-runtime-democracy 0.1.0", diff --git a/demo/cli/src/lib.rs b/demo/cli/src/lib.rs index 8346e9aaa6b3a..c1f87d98b04de 100644 --- a/demo/cli/src/lib.rs +++ b/demo/cli/src/lib.rs @@ -50,8 +50,8 @@ pub mod error; use std::sync::Arc; use demo_primitives::{AccountId, Hash}; use demo_runtime::{Block, BlockId, GenesisConfig, - ConsensusConfig, CouncilConfig, DemocracyConfig, SessionConfig, StakingConfig, - TimestampConfig}; + BalancesConfig, ConsensusConfig, CouncilConfig, DemocracyConfig, SessionConfig, + StakingConfig, TimestampConfig}; use futures::{Future, Sink, Stream}; use tokio::runtime::Runtime; use demo_executor::NativeExecutor; @@ -164,13 +164,7 @@ pub fn run(args: I) -> error::Result<()> where authorities: vec![god_key.clone().into()], }), system: None, - session: Some(SessionConfig { - validators: vec![god_key.clone().into()], - session_length: 720, // that's 1 hour per session. - }), - staking: Some(StakingConfig { - current_era: 0, - intentions: vec![], + balances: Some(BalancesConfig { transaction_base_fee: 100, transaction_byte_fee: 1, transfer_fee: 0, @@ -178,6 +172,14 @@ pub fn run(args: I) -> error::Result<()> where reclaim_rebate: 0, existential_deposit: 500, balances: vec![(god_key.clone().into(), 1u64 << 63)].into_iter().collect(), + }), + session: Some(SessionConfig { + validators: vec![god_key.clone().into()], + session_length: 720, // that's 1 hour per session. + }), + staking: Some(StakingConfig { + current_era: 0, + intentions: vec![], validator_count: 12, minimum_validator_count: 4, sessions_per_era: 24, // 24 hours per era. diff --git a/demo/executor/Cargo.toml b/demo/executor/Cargo.toml index 96b547af13f9b..c07fb3887841d 100644 --- a/demo/executor/Cargo.toml +++ b/demo/executor/Cargo.toml @@ -20,6 +20,7 @@ demo-runtime = { path = "../runtime" } [dev-dependencies] substrate-keyring = { path = "../../substrate/keyring" } substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" } +substrate-runtime-balances = { path = "../../substrate/runtime/balances" } substrate-runtime-session = { path = "../../substrate/runtime/session" } substrate-runtime-staking = { path = "../../substrate/runtime/staking" } substrate-runtime-system = { path = "../../substrate/runtime/system" } diff --git a/demo/executor/src/lib.rs b/demo/executor/src/lib.rs index 89ab8de55974e..3b3a80eca1865 100644 --- a/demo/executor/src/lib.rs +++ b/demo/executor/src/lib.rs @@ -30,6 +30,7 @@ extern crate triehash; #[cfg(test)] extern crate substrate_keyring as keyring; #[cfg(test)] extern crate substrate_runtime_primitives as runtime_primitives; #[cfg(test)] extern crate substrate_runtime_support as runtime_support; +#[cfg(test)] extern crate substrate_runtime_balances as balances; #[cfg(test)] extern crate substrate_runtime_session as session; #[cfg(test)] extern crate substrate_runtime_staking as staking; #[cfg(test)] extern crate substrate_runtime_system as system; @@ -52,10 +53,10 @@ mod tests { use demo_primitives::{Hash, BlockNumber, AccountId}; use runtime_primitives::traits::Header as HeaderT; use runtime_primitives::{ApplyOutcome, ApplyError, ApplyResult, MaybeUnsigned}; - use {staking, session, system, consensus}; + use {balances, staking, session, system, consensus}; use system::{EventRecord, Phase}; - use demo_runtime::{Header, Block, UncheckedExtrinsic, Extrinsic, Call, Concrete, Staking, - BuildStorage, GenesisConfig, SessionConfig, StakingConfig, BareExtrinsic, System, Event}; + use demo_runtime::{Header, Block, UncheckedExtrinsic, Extrinsic, Call, Concrete, Balances, + BuildStorage, GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, BareExtrinsic, System, Event}; use ed25519::{Public, Pair}; const BLOATY_CODE: &[u8] = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm"); @@ -80,7 +81,7 @@ mod tests { let extrinsic = BareExtrinsic { signed: alice(), index: 0, - function: Call::Staking(staking::Call::transfer::(bob().into(), 69)), + function: Call::Balances(balances::Call::transfer::(bob().into(), 69)), }; let signature = MaybeUnsigned(Keyring::from_raw_public(extrinsic.signed.0.clone()).unwrap() .sign(&extrinsic.encode()).into()); @@ -103,13 +104,13 @@ mod tests { #[test] fn panic_execution_with_foreign_code_gives_error() { let mut t: TestExternalities = map![ - twox_128(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![70u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![70u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; @@ -123,13 +124,13 @@ mod tests { #[test] fn bad_extrinsic_with_native_equivalent_code_gives_error() { let mut t: TestExternalities = map![ - twox_128(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![70u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![70u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; @@ -143,13 +144,13 @@ mod tests { #[test] fn successful_execution_with_native_equivalent_code_gives_ok() { let mut t: TestExternalities = map![ - twox_128(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; @@ -159,21 +160,21 @@ mod tests { assert!(r.is_ok()); runtime_io::with_externalities(&mut t, || { - assert_eq!(Staking::voting_balance(&alice()), 42); - assert_eq!(Staking::voting_balance(&bob()), 69); + assert_eq!(Balances::voting_balance(&alice()), 42); + assert_eq!(Balances::voting_balance(&bob()), 69); }); } #[test] fn successful_execution_with_foreign_code_gives_ok() { let mut t: TestExternalities = map![ - twox_128(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; @@ -183,8 +184,8 @@ mod tests { assert!(r.is_ok()); runtime_io::with_externalities(&mut t, || { - assert_eq!(Staking::voting_balance(&alice()), 42); - assert_eq!(Staking::voting_balance(&bob()), 69); + assert_eq!(Balances::voting_balance(&alice()), 42); + assert_eq!(Balances::voting_balance(&bob()), 69); }); } @@ -194,6 +195,15 @@ mod tests { GenesisConfig { consensus: Some(Default::default()), system: Some(Default::default()), + balances: Some(BalancesConfig { + balances: vec![(alice(), 111)], + transaction_base_fee: 1, + transaction_byte_fee: 0, + existential_deposit: 0, + transfer_fee: 0, + creation_fee: 0, + reclaim_rebate: 0, + }), session: Some(SessionConfig { session_length: 2, validators: vec![One.to_raw_public().into(), Two.to_raw_public().into(), three], @@ -201,17 +211,10 @@ mod tests { staking: Some(StakingConfig { sessions_per_era: 2, current_era: 0, - balances: vec![(alice(), 111)], intentions: vec![alice(), bob(), Charlie.to_raw_public().into()], validator_count: 3, minimum_validator_count: 0, bonding_duration: 0, - transaction_base_fee: 1, - transaction_byte_fee: 0, - existential_deposit: 0, - transfer_fee: 0, - creation_fee: 0, - reclaim_rebate: 0, early_era_slash: 0, session_reward: 0, offline_slash_grace: 0, @@ -257,11 +260,11 @@ mod tests { // Blake // hex!("3437bf4b182ab17bb322af5c67e55f6be487a77084ad2b4e27ddac7242e4ad21").into(), // Keccak - hex!("0b401681b95d04e91dbe53835867bdcb5d9e0590b54ae06bd7b347d49f9a737f").into(), + hex!("d80a4a89e0a02864b5624ea9abb00f75285b8148c169c859d330b573914f1784").into(), vec![BareExtrinsic { signed: alice(), index: 0, - function: Call::Staking(staking::Call::transfer(bob().into(), 69)), + function: Call::Balances(balances::Call::transfer(bob().into(), 69)), }] ) } @@ -273,17 +276,17 @@ mod tests { // Blake // hex!("741fcb660e6fa9f625fbcd993b49f6c1cc4040f5e0cc8727afdedf11fd3c464b").into(), // Keccak - hex!("03f051dc4f588fdc713145772486a129d33c7f178c133b5801fa79c3ecca2dc9").into(), + hex!("83e23a6dfbcf783ceb8eb4704344b8ec0478159fc670fa7a9f0c368a28eb8b74").into(), vec![ BareExtrinsic { signed: bob(), index: 0, - function: Call::Staking(staking::Call::transfer(alice().into(), 5)), + function: Call::Balances(balances::Call::transfer(alice().into(), 5)), }, BareExtrinsic { signed: alice(), index: 1, - function: Call::Staking(staking::Call::transfer(bob().into(), 15)), + function: Call::Balances(balances::Call::transfer(bob().into(), 15)), } ] ) @@ -296,7 +299,7 @@ mod tests { // Blake // hex!("2c7231a9c210a7aa4bea169d944bc4aaacd517862b244b8021236ffa7f697991").into(), // Keccak - hex!("6e3b6aaf0be927394b520e3ebc0c34a7c26519711bc836e116e371273c3aca44").into(), + hex!("bd24909630b9431ca0e07492f880a5622c5f3c1471a0b0a2653b8c8e341df40b").into(), vec![BareExtrinsic { signed: alice(), index: 0, @@ -312,12 +315,12 @@ mod tests { executor().call(&mut t, COMPACT_CODE, "execute_block", &block1().0, true).0.unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Staking::voting_balance(&alice()), 41); - assert_eq!(Staking::voting_balance(&bob()), 69); + assert_eq!(Balances::voting_balance(&alice()), 41); + assert_eq!(Balances::voting_balance(&bob()), 69); assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - event: Event::staking(staking::RawEvent::NewAccount(bob(), 1, staking::NewAccountOutcome::NoHint)) + event: Event::balances(balances::RawEvent::NewAccount(bob(), 1, balances::NewAccountOutcome::NoHint)) } ]); }); @@ -325,8 +328,8 @@ mod tests { executor().call(&mut t, COMPACT_CODE, "execute_block", &block2().0, true).0.unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Staking::voting_balance(&alice()), 30); - assert_eq!(Staking::voting_balance(&bob()), 78); + assert_eq!(Balances::voting_balance(&alice()), 30); + assert_eq!(Balances::voting_balance(&bob()), 78); assert_eq!(System::events(), vec![ EventRecord { phase: Phase::Finalization, @@ -347,15 +350,15 @@ mod tests { WasmExecutor::new(8).call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Staking::voting_balance(&alice()), 41); - assert_eq!(Staking::voting_balance(&bob()), 69); + assert_eq!(Balances::voting_balance(&alice()), 41); + assert_eq!(Balances::voting_balance(&bob()), 69); }); WasmExecutor::new(8).call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Staking::voting_balance(&alice()), 30); - assert_eq!(Staking::voting_balance(&bob()), 78); + assert_eq!(Balances::voting_balance(&alice()), 30); + assert_eq!(Balances::voting_balance(&bob()), 78); }); } @@ -386,13 +389,13 @@ mod tests { #[test] fn panic_execution_gives_error() { let mut t: TestExternalities = map![ - twox_128(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![70u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![70u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; @@ -407,13 +410,13 @@ mod tests { #[test] fn successful_execution_gives_ok() { let mut t: TestExternalities = map![ - twox_128(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], - twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], + twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] ]; @@ -425,8 +428,8 @@ mod tests { assert_eq!(r, Ok(ApplyOutcome::Success)); runtime_io::with_externalities(&mut t, || { - assert_eq!(Staking::voting_balance(&alice()), 42); - assert_eq!(Staking::voting_balance(&bob()), 69); + assert_eq!(Balances::voting_balance(&alice()), 42); + assert_eq!(Balances::voting_balance(&bob()), 69); }); } } diff --git a/demo/runtime/Cargo.toml b/demo/runtime/Cargo.toml index a13a87469cb61..105c505e8db75 100644 --- a/demo/runtime/Cargo.toml +++ b/demo/runtime/Cargo.toml @@ -17,6 +17,7 @@ substrate-runtime-io = { path = "../../substrate/runtime-io" } substrate-runtime-support = { path = "../../substrate/runtime-support" } substrate-primitives = { path = "../../substrate/primitives" } substrate-keyring = { path = "../../substrate/keyring" } +substrate-runtime-balances = { path = "../../substrate/runtime/balances" } substrate-runtime-consensus = { path = "../../substrate/runtime/consensus" } substrate-runtime-council = { path = "../../substrate/runtime/council" } substrate-runtime-democracy = { path = "../../substrate/runtime/democracy" } @@ -37,6 +38,7 @@ std = [ "substrate-runtime-std/std", "substrate-runtime-io/std", "substrate-runtime-support/std", + "substrate-runtime-balances/std", "substrate-runtime-consensus/std", "substrate-runtime-council/std", "substrate-runtime-democracy/std", diff --git a/demo/runtime/src/lib.rs b/demo/runtime/src/lib.rs index a672ef105bd1e..2d5250458f9a4 100644 --- a/demo/runtime/src/lib.rs +++ b/demo/runtime/src/lib.rs @@ -40,6 +40,7 @@ extern crate substrate_codec as codec; extern crate substrate_codec_derive; extern crate substrate_runtime_std as rstd; +extern crate substrate_runtime_balances as balances; extern crate substrate_runtime_consensus as consensus; extern crate substrate_runtime_council as council; extern crate substrate_runtime_democracy as democracy; @@ -102,6 +103,17 @@ impl system::Trait for Concrete { /// System module for this concrete runtime. pub type System = system::Module; +impl balances::Trait for Concrete { + type Balance = Balance; + type AccountIndex = AccountIndex; + type OnFreeBalanceZero = Staking; + type IsAccountLiquid = Staking; + type Event = Event; +} + +/// Staking module for this concrete runtime. +pub type Balances = balances::Module; + impl consensus::Trait for Concrete { type SessionKey = SessionKey; } @@ -137,9 +149,6 @@ pub type Session = session::Module; impl staking::Trait for Concrete { const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1; - type Balance = Balance; - type AccountIndex = AccountIndex; - type OnFreeBalanceZero = (); type Event = Event; } @@ -162,7 +171,7 @@ pub type CouncilVoting = council::voting::Module; impl_outer_event! { pub enum Event for Concrete { - session, staking + balances, session, staking } } @@ -171,9 +180,10 @@ impl_outer_dispatch! { #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] pub enum Call where aux: ::PublicAux { Consensus = 0, - Session = 1, - Staking = 2, - Timestamp = 3, + Balances = 1, + Session = 2, + Staking = 3, + Timestamp = 4, Democracy = 5, Council = 6, CouncilVoting = 7, @@ -183,16 +193,17 @@ impl_outer_dispatch! { #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] pub enum PrivCall { Consensus = 0, - Session = 1, - Staking = 2, - Democracy = 5, - Council = 6, - CouncilVoting = 7, + Balances = 1, + Session = 2, + Staking = 3, + Democracy = 4, + Council = 5, + CouncilVoting = 6, } } /// The address format for describing accounts. -pub type Address = staking::Address; +pub type Address = balances::Address; /// Block header type as expected by this runtime. pub type Header = generic::Header>; /// Block type as expected by this runtime. @@ -206,13 +217,14 @@ pub type Extrinsic = generic::Extrinsic; /// Extrinsic type that is signed. pub type BareExtrinsic = generic::Extrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = executive::Executive; impl_outer_config! { pub struct GenesisConfig for Concrete { ConsensusConfig => consensus, SystemConfig => system, + BalancesConfig => balances, SessionConfig => session, StakingConfig => staking, DemocracyConfig => democracy, diff --git a/demo/runtime/wasm/Cargo.lock b/demo/runtime/wasm/Cargo.lock index 8f831386d6db7..9bdb08220eccf 100644 --- a/demo/runtime/wasm/Cargo.lock +++ b/demo/runtime/wasm/Cargo.lock @@ -103,6 +103,7 @@ dependencies = [ "substrate-codec 0.1.0", "substrate-codec-derive 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-balances 0.1.0", "substrate-runtime-consensus 0.1.0", "substrate-runtime-council 0.1.0", "substrate-runtime-democracy 0.1.0", @@ -639,6 +640,29 @@ dependencies = [ "wasmi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "substrate-runtime-balances" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-codec-derive 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-consensus 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-runtime-primitives 0.1.0", + "substrate-runtime-sandbox 0.1.0", + "substrate-runtime-session 0.1.0", + "substrate-runtime-std 0.1.0", + "substrate-runtime-support 0.1.0", + "substrate-runtime-system 0.1.0", + "substrate-runtime-timestamp 0.1.0", +] + [[package]] name = "substrate-runtime-consensus" version = "0.1.0" @@ -667,12 +691,11 @@ dependencies = [ "substrate-codec 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-balances 0.1.0", "substrate-runtime-consensus 0.1.0", "substrate-runtime-democracy 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", - "substrate-runtime-session 0.1.0", - "substrate-runtime-staking 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", @@ -689,11 +712,10 @@ dependencies = [ "substrate-codec 0.1.0", "substrate-codec-derive 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-balances 0.1.0", "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", - "substrate-runtime-session 0.1.0", - "substrate-runtime-staking 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", @@ -791,6 +813,7 @@ dependencies = [ "substrate-codec-derive 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-balances 0.1.0", "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", diff --git a/demo/runtime/wasm/Cargo.toml b/demo/runtime/wasm/Cargo.toml index 965c818788870..59cb7b4f720c8 100644 --- a/demo/runtime/wasm/Cargo.toml +++ b/demo/runtime/wasm/Cargo.toml @@ -15,6 +15,7 @@ substrate-primitives = { path = "../../../substrate/primitives", default-feature substrate-runtime-std = { path = "../../../substrate/runtime-std", default-features = false } substrate-runtime-io = { path = "../../../substrate/runtime-io", default-features = false } substrate-runtime-support = { path = "../../../substrate/runtime-support", default-features = false } +substrate-runtime-balances = { path = "../../../substrate/runtime/balances", default-features = false } substrate-runtime-consensus = { path = "../../../substrate/runtime/consensus", default-features = false } substrate-runtime-council = { path = "../../../substrate/runtime/council", default-features = false } substrate-runtime-democracy = { path = "../../../substrate/runtime/democracy", default-features = false } @@ -36,6 +37,7 @@ std = [ "substrate-runtime-std/std", "substrate-runtime-io/std", "substrate-runtime-support/std", + "substrate-runtime-balances/std", "substrate-runtime-consensus/std", "substrate-runtime-council/std", "substrate-runtime-democracy/std", diff --git a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm index 02a7fed93297ca8be98e28a866f4cdc1e6f3b73a..d8c65a2b92f609b3ea993f3d7e5a5962d780e995 100644 GIT binary patch literal 296537 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%0A3GsP36`I49{)e@`x6m~0cg$)A?p2)tEIc6*aQ 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≺#anbGm)ECzkXilRE28Os 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 literal 280201 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 diff --git a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm index b3376fd74f7cd380e73b365a0720d858878c4408..aa64b1799fb6fe28c48cdee91b15f53e31c010a7 100755 GIT binary patch literal 296621 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∋PQb;&Fl>YB3| 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 literal 280288 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 G3H~4SFrwK2 diff --git a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index dc23e6a75f3dd9383d293b2f173e345885ce7c58..ed66e54638bdbcafd4e804e894115f7de481b020 100644 GIT binary patch delta 2500 zcmZuyYm8M_6+ZXQ3@MbyzLa60JRIl%1M=AK2d^^J(Y6pjYHhskRnm=h--WWNu zT7Kv+1OGbl=F9uO)ST4bQ|tby-qN$~b+-2WdEe_*PYaoemlHO2 z);jBCW^>o%W3^g0JTd-<_$0aW@lA>*a=IXe0lgtyshwd1$_AAS8E5G>%Ms3s5%pHe#2Z`n!ni~@8~^&uf2+K z9phIRzsL9h?h4t+YXZ2dHCZuR@C}o!QSPy z0ob-zk26%Wz>QIzoH9F)+IieIZ|*(XLR6&M%fO41IqB@c?^{Q-Fq&J&GvL}mVe!^;W@xGJU*4{al7a`LQer`J)>}RL_(RaxKWDPVi-#Y2 zoKa@hCrn#;MRio!8(-k`{v{-4Lo?0VW*umd4E~A_l~oZl*F_uUnJwTBEFm_#ph9Fk z2O2|h@T~*O2)EfYs&tT%GZhT{5+91>Md2xGk9#xen==nS&_bxTN(kjjFxp#TVb5Vb zN#tmC(k?0)m36eY+P-1kmNk7(?br^74o`sh5050yORJ48CMqqZwa^N?hzUt*ixqh( zTwn?g!A7DZrXjUXG34xghC7dZdbBLbddnm$#TXBtIr4d8g%a9XshCL_{|sl3^buK# z)gkLlF>5RkrXRhJ1e-aRGTEdHqLyLD(Io`arC5r!CY!`#f*&2dcMR9rWX6QmjAb5x zJinGuJcv7=7?WJnoZ#!vf0LBVV~8<1R(O$0LHn^)q*xvieusx;M3=+PV{1vq8%`C= z4r`T3!u!WoHMmDqk!+D7Dm2Gl#Hpi0^x-LHJ+jJTRwX%}Z4LsS{?6itO3FFRvpA|S zBijp82WiLlt(!Bxp+iW*Bf=;#X@iE*gZGa~M&y#2O%g#*9P%J*uw+rN90B%JpaOc~ zmG5`M+k;;w)YvR?#{YZVh#6RNd=tTXjWof9Kr_CT;Og<%z;?lnxe_cIR8j7Q_s&m+ z2Tv?$cPirUB4H}bzU z!;}|i5IR&1+6G5Bl28#IdGTgL=qQBeNe7FP9Ac;Q!gx?;<`5rEDpaY+EO**O*m{N% z8KW%0ikt*P4O)2h%%U+lFyl1E-zXAP;2&r1ZNyYG&qbg!C1IHSkJ@1ESvp3VEE0+{ z*=Ur>aQbX73DGC%F*WL)a>~Hp&SC-%HCM0$9UdBmhxzB`bWyLe)FLU5{g=7utZ20I;+A=5Uyl82ir?^5PF3~u=E0YCjI2EYZ5J4StF8J!$1a5zF1$PZ>|L!} z{N`Lc-rW7#W3@556x^FCBUmUU!ylRpZU=GNMM;>lSelpI<)MCShh0}D!tRUX2$}*b zDOn*iLjy=~_M#)sM)VtOZLc{`XtW<(Tzq?V<`PZ}Nx60i4d&b_%=rj($y*#PoR{A=- z=L;rh!>}v*cE(m-=_I$317Eu`zk?T?Xby$!Jx)kzXKY&2wery}xQUSMy|$!5i^)oc z7<>vj8afl+xwg0=y)$Tu0-ZTy59C>J;|gz>p?%QH0<{zeTIz;RuB>fH>=7KW%qO7} zdcthjdUgHSLS@bt@eXLpx`a7TL*La$V9~V+#0X(1(yR;GvlkJjTz{q^ipCM{oJIkg zfKv);EgkUs^+SXY?T+a?V{tZN>-rm%2uHmz%9(`Ij|B>6ZYZJ|XD%2Mvvx*s27kIS F_usnU_BsFn delta 2498 zcmZuzdyJJw6~EuzT~eyc&RrH*D9G|&Ufp?qGqb?brCzl{3Q`-bErD-duz)-kHZ(yb z5i2d0683cE4FXLnF^$l>gZIi8CzMCEJlNQnje;p<+wjM78$4Bhq^;6Fuw&<17uWY~Sv#<0SKpRU znov7do|HAsnl}BxAJ(omEUPp(mzEv=;Ly82z4iOw9Nk+RHLf><(d|FZX2UPq7iM#6 ze{X+3%Q|a!CXH+8yjyN)+M9i|ymv;amu{NgIJ4Bz*!!pbKP&Y%ka_sozOf_gD3f`$ zt>cem<=LfL_L&`{D|0)VdLP)>d$)e>Q@xF3Ztb}_{f${C+?#(hn*%o%e3;FyU0v8W zC2OipU*47Bw0cF+gwybs(&#Y*l~UuOx-^o@yZ_FH~W;s(t(U=8Py& z7#|(8n)+Z8ubq9Nr%b#qBBv=7K}KO@0q=eHW)?`yG%s{?oaRCb?xm}iR;~OBqhDT` zOUMq+nqvRAWO{>_$`~s-!$1qFIc$IF5u%mh!t!JThG23BKgZ47=E3o(RWOk|9cz_C zk2MfeP|ku)M)2sASFmv~C)&oMNK#ngCG{@C#lbGZa}!y@u%&j2Q3dY}?jb@MbY!A% zPFREPzX2Nw+TzkNswK0=DFgq2`D09SA{B;7&9pSo_44C{Y2{r?OeBdTNjUiOHsW!Q zd6{!>qtI4B^U$N{CKg;pO`{hyqMLO?ODY8wB2U&?#k^H9Re`-W0p1##(}HhOUUJ3q zsFKd%!=ZIV2IW|hC!RE;&g8J^d(V+*y)oWdNtLn5`oSYl5UH(l($EyqFd_;5$hs-2 zNVyD_2H|uFDX*4x@AjLw?ilEgd-lMzp>|kt?qNa|wJ8Llx$wyc3wO^<9*ZDx9evKI z2uU#`iU{%O;<_IUJt|t{h@gmY>8K%`b8VQwO%d@O96mVug%(U%GG0?IXu(*7RmT{y zl;%9-E{0(041mMO_LHcYvcYg3^T252(0P0lQ8LzzAngBmJ!3ajg6*bJE$6N~vADwuN z2re*!U|D1q>7wAPCqGY&DQuyPqts($GQf{co+gFJxh@h0DJ7bZTa24Q}rz0^4 zTq>B*#s?Y;4LxU`A}UggCv(L$)-uxJ)iai8bWbT`8uKS4X8-P)C4{@EBe(ckrIch8 zmVEz4tK<>cs9l{nN#>zig4>tcVCvcVBuSp<&IN|zQFyfcwX>8cq#bIKNWmIjL<`5y zE~=ntDS^DhXUM`^T7{kqd&o8PJ_%jxZM8n)z9;WIUTXIz=g>lKD>f_ty4?m3Ti!`W+Io6b+ zTteTlB}!>5CPkTNUYMN1>%)uh5AEN>t6DLGsIR$BIohSvOjhu>4Q)U!lgfsXIKj{x zvs*^M3U9yB(K-^1sZV@tgx-hf%FDe=MgTy3v-IO<_~Ny36{)d`R8%H-t&=M{VcWG$m3l$2 zLQ?FVR7x4=!V6cPX-!l)hy4ky#Dp?GZ#hQL4lP$_kRVY?ghKr*xG^%qU#{)0sDSdK z6ve5?DYX>tlqbMTZyv4(Y>dFO^{$kQ1YOrDiAgX+y^M*`0$st@>xwY^6A+xD=ucXz JDGXm<@E`i%`RD)u diff --git a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm index c1ef690b3fa2c28cd6cf6d5a7c4b880994bfef91..971048d5470b129abab11b07d2dd8e43b6964005 100755 GIT binary patch delta 2501 zcmZuyYm8M_6~5=r&~}h^&K(O=tl|g*8Cqs$zaKn1kf~A{T1$x*YKQ&gRUUysQKS4o zENuz|R(X%S24kAo@VGptQ&Kh6AKJtit+CNR));MU0wgsWQbS!g>Yu@zth>+I=bW|I z`o3?i_2*mFi?^!hpQzqd+|@e1xfzyMZPVYY?XbVPxPHB=ig7(%Gspk3KC?O3CQPU- z-2b=TA0Pket1o<|J~Xkf=(<^L8n>hPc6G(cJgf7k*snYbv|(@_}_7 zMMt&luHXLj;iBk;KTP@&{vU7eE=c|7?f)zaTK~!9iB0t*Q?|6!W_66~yJubB&Bo`S z=xZ)#)gSEI(p*s3JL|22z*F5H6}|PPJ!?NxRO=&4dJA0Mf8343<*}!7%YB2jO68?W zrE;yKQn}FqZ?1f`Wdhz-@OBAoe)em{zWV#mF1oi$Idrd^g-dV8cW^-OEo!3Z_o#B?)LpZA@EO{EM(IpJBhB1M%f{ON_&rQ%vKL#bj`3+os>vwL&z?gR?=A2b_^-sNcZ&6aAIpN9#&#B5x*7ZyCt7Xh45g(mR zQ6#N2?0WgF1`3bu(T!#2o`t2HsQLsVI5>8Qytikl``FMXgac@liKaQD7PN@kLyL@F-=qta{m5^nP7 zcxEvuhrX$B^&jk8+*A@}B1}TCxmcXOXTUsZK(kkm9l@P|j zF8J1D?W0fzGjM`iPi22)W7msFsDUu=-hj*1ZvEW09 zmS&cPlyK^u5})~I>PiJB;ohREPAM`?{lg9>E`up=Bb&<{Q5y5PxU&y_@*#8ble9Xg^K-aNLx z#C)~T-g-|GeigwU4>ha|bj&2DL8FdRKMcG!1>Qc6tlPj1YbeV_=0bq+L$gbd5VI_E zBGLxq4Lm(WOUnrnRC2(csYLLdHW^hwjE#!JJ13th1$D+|6QgrH zaYJF=DO(Fh3nvH`0hYKH|6vzSoSI&eMmE?U7{U>`4Dg#%*J@k^&K--&8&qP0l+za` z!Ijewl`iO*iIjmFW|a;8BNeqC+HaNFMV)PI1G(AE3MS9Z5RWvD7B1*XYtU$ z9h@6}sFOIEgyK;;EW5;be!t( zfx>$i=C^l_tNfp1=fjkX@3wsS$>xo2Ln=O~e|&LI(W-Jr-$ZIoea;DvU+TRR#NS^M zC6xwKbAs8_D6`4%#K>g0eQCl21ODrSY4+?j*b``u(QuI{)_;VRmu+cHz;=U`?G$4X zJMG!a%kRvx<;s(7Oc16*jx<{BNe|~~@W;!O;QE!j z+r|P`ZujC7P^xq_u5 zJ?$*xAhW1z=WrwnGi&`o=i^Uz!d^sh`RKeF$vR2lgLl!Vph-6jkIt_t=_M_7p~6 zUtem@H9^8v#{TShfE%OVtnsXHTwAM9%Gw*N;kl-EIPk{)Hr8;Aky~wWTp7AxJ`~qJ z_t~`Zs{?N9*0g01sppnBuBFux=OOjvkwuMn;Lx?UQc*^&*E%F+HOEOka&6YX0T8GF AfB*mh delta 2492 zcmZuzX^fUv75?5~21_ZO`vHSPpzS~rr)8GAzW3gt0~y+n7BQtMB{l&a?#fb}P6v>- z+PI*CL?GpqeP^%{e<<*=mr9c+Mw_~YA9aZ}7}97Yu^JOYjLR8+)D-&TG}E!|3Ka8ykz!u%y9`+B~WiUT#=0u{yMV?Ye%SR;(K6Uq7&6)j+IF zssE;-ESfsnAGq`9^_Iq59XGBr@8z4@uU~oR+VA#!xxT5TuYfJBuNR&0*yPTltNw+_ z|0s&?`oNTyQSjqQQ}1GJjeV`F+lsaZ!s_o&+FdksR_b57ckP%eZENbgV|CyAo8GAO zjqPhBv_86hsIlmV7dqZ7x}dl7pG9ZgcCEUnXsQn{>@M)Q`f1mMhk7!PxqE%JQrS|e zRDRZ0sT9-T#L^RE#^K|5eEcjdUACb(TEDvN;c*RILhI@dJnHjT%R5>Q;AbaMUPJj6 z${$c}!1kg0s%!DrlEzBqEtC=C|EXUY+D?i~uxR7LVm<8NIIq|T?`|w7M#(Z~nXxub zndzja6OFfjedj3Ryb!_%&NHQw`T#%Ow1NaLZJBH;l~p370FP|$sYVg04OwebTH``l zgOlI=IJ~-f5pgmEs)dx?DQCE{LF$T6^W9tqhK8r4V?4H@40ui5guxC4>`RvQWac~%B*<^ z0iMQ7&7Dr3(^5#mgY@v7ZM{>2RK{4z87AbY=C#Tbi$25XQ;QfkaB|xxW-H_qvuJhXcG52)pu-PFp3yQIg2(M!IM`(!Jl`O zMBC(Cmcoi4Y48acbQ4~h#4;8|YOfeoFbFRZp$x`glJH(wqdEKwRuiK&mYC2hj}xX<@HsP)B}$fX_s&5Q@Qwvp@?ewDR=~EM52KspxJsI) zAZS82*LL<2M};V}^;WT9Rm#w{Yi=`!qk`m$l}Tk?!k2a}Co(F}T$y>+jCxbTja}a$ z$p&MBw~{Jjvkmao-HVCTR(WY?PG}S{hU>eR6XkL#qoq-J9b+!xsXdDcRn+Dfh2|pU z5G_1+Wacg#MO}#yi&TT(AMSwuy<-XITpK3vjY#O5 z!;5<#YsL~~6Ex+5I>r+Gaxbe|N=qI~pJFs4JgLFQe$WoH_kE5e&6JIX^HfGg6NeM~ zo*_!65sL_|3z)iu8T$jF0=p(igCDm_?o_`1OHDi80PPWjv(; zQLg0I_t5hs32QmkK^w`U4-{TKG>2#< z7z@D#DiF`i;qQm$lf(l@Y%`}S3$7x3>Ts$WL@hfev8MTq8KloJ2H@$bxF8VEOQagrTAm z+H0IeXv@I9;RmNNgB`^!GL&g=XsT7>(6fX6xRwUjxR4&232sdb{Bd}8)!}Pw7m0?s zu^jo@d%6ZM9G^m{N&jmE;Y-ScuyFkN{nG{Bs;E;gy+pKWt&*M}OkrJrcB|H;SgBmE z|LOSpyNWf?e~L|*(Ny^;$Hg4jerhhfcj}!nHzqU=xX-8Jdi_VIw-(JfV@u?jr!in# zYVc>eZ?EXlGm?~Qgc!zWj|)NA$#Bnw$?)$p6Oo3AMwPJ6nlc=-F#W70N@;8_MOk1$ zn3BRXXP4Zb-!INSL9mQCmrI>XG)}1jdhR1YT5)b>^DUUdfpcx+Z^dHfVwkpLBFsNW z;BV*JZo_oi`M$ZgV%k0{JUf(ndIr}G_4IrQw4R=ox5E0sBk-5u8SwUbf}8WhIKqwd zZRA$8VCsdg@zzqSsNfMdQ!re1^nt_Tbzf|)1|*ix$Q+!?nF`$rPhVVK<-*5=>lAxP zkJP*iesXc;c&V{@R8l4et+RLCFTz_FpM;&4TB{??z?`JGQ>m0PQCNCm+4xMA_qdtR zO3FCk*+LAy6|P;lpG1kXL@1nujvFHryngA6%_`!2QHtW>N=o6;*S. -//! Staking manager: Handles balances and periodically determines the best set of validators. +//! Balances: Handles balances. #![cfg_attr(not(feature = "std"), no_std)] diff --git a/substrate/runtime/session/src/lib.rs b/substrate/runtime/session/src/lib.rs index 053c82cb5bb45..c87bec3ae2cd1 100644 --- a/substrate/runtime/session/src/lib.rs +++ b/substrate/runtime/session/src/lib.rs @@ -327,7 +327,6 @@ mod tests { type System = system::Module; type Consensus = consensus::Module; - type Timestamp = timestamp::Module; type Session = Module; fn new_test_ext() -> runtime_io::TestExternalities { diff --git a/substrate/runtime/staking/src/lib.rs b/substrate/runtime/staking/src/lib.rs index 671f9ab2b2a7f..5359a9ec660c4 100644 --- a/substrate/runtime/staking/src/lib.rs +++ b/substrate/runtime/staking/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Substrate Demo. If not, see . -//! Staking manager: Handles balances and periodically determines the best set of validators. +//! Staking manager: Periodically determines the best set of validators. #![cfg_attr(not(feature = "std"), no_std)] diff --git a/substrate/runtime/system/src/lib.rs b/substrate/runtime/system/src/lib.rs index ef8b043b15d8d..d23aa05c3d2c6 100644 --- a/substrate/runtime/system/src/lib.rs +++ b/substrate/runtime/system/src/lib.rs @@ -288,6 +288,7 @@ mod tests { #[derive(Clone, Eq, PartialEq)] pub struct Test; impl Trait for Test { + type PublicAux = u64; type Index = u64; type BlockNumber = u64; type Hash = H256; diff --git a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index 7d2f104d0966a541ae8c43a747f71e22157011bc..625a093a6d41b355265e3b42b40b9e2de6c07a84 100644 GIT binary patch delta 2985 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 F{TB*+o+JPO diff --git a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm index 5618789cf379b570bb2f6e2d80c4e0d069a00cf7..874a7a2da0c3f640b3238887bada703f0bc868c7 100755 GIT binary patch delta 2910 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 Date: Wed, 29 Aug 2018 23:31:51 +0200 Subject: [PATCH 12/19] Fix minor TODOs --- demo/cli/src/lib.rs | 2 +- demo/executor/src/lib.rs | 40 ++++++------ .../runtime/balances/src/genesis_config.rs | 4 +- substrate/runtime/balances/src/lib.rs | 36 ++++------- substrate/runtime/balances/src/tests.rs | 60 ++++++++--------- substrate/runtime/council/src/lib.rs | 20 +++--- substrate/runtime/democracy/src/lib.rs | 4 +- substrate/runtime/executive/src/lib.rs | 4 +- substrate/runtime/staking/src/lib.rs | 42 +++++------- substrate/runtime/staking/src/tests.rs | 64 +++++++++---------- 10 files changed, 127 insertions(+), 149 deletions(-) diff --git a/demo/cli/src/lib.rs b/demo/cli/src/lib.rs index c1f87d98b04de..4260f7d1cd0fe 100644 --- a/demo/cli/src/lib.rs +++ b/demo/cli/src/lib.rs @@ -183,7 +183,7 @@ pub fn run(args: I) -> error::Result<()> where validator_count: 12, minimum_validator_count: 4, sessions_per_era: 24, // 24 hours per era. - bonding_duration: 90, // 90 days per bond. + bonding_duration: 90 * 24 * 720, // 90 days per bond. early_era_slash: 10000, session_reward: 100, offline_slash_grace: 0, diff --git a/demo/executor/src/lib.rs b/demo/executor/src/lib.rs index 3b3a80eca1865..b73e80b0feb8e 100644 --- a/demo/executor/src/lib.rs +++ b/demo/executor/src/lib.rs @@ -105,7 +105,7 @@ mod tests { fn panic_execution_with_foreign_code_gives_error() { let mut t: TestExternalities = map![ twox_128(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], twox_128(>::key()).to_vec() => vec![70u8; 8], twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(>::key()).to_vec() => vec![0u8; 8], @@ -125,7 +125,7 @@ mod tests { fn bad_extrinsic_with_native_equivalent_code_gives_error() { let mut t: TestExternalities = map![ twox_128(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], twox_128(>::key()).to_vec() => vec![70u8; 8], twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(>::key()).to_vec() => vec![0u8; 8], @@ -145,7 +145,7 @@ mod tests { fn successful_execution_with_native_equivalent_code_gives_ok() { let mut t: TestExternalities = map![ twox_128(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(>::key()).to_vec() => vec![0u8; 8], @@ -160,8 +160,8 @@ mod tests { assert!(r.is_ok()); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::voting_balance(&alice()), 42); - assert_eq!(Balances::voting_balance(&bob()), 69); + assert_eq!(Balances::total_balance(&alice()), 42); + assert_eq!(Balances::total_balance(&bob()), 69); }); } @@ -169,7 +169,7 @@ mod tests { fn successful_execution_with_foreign_code_gives_ok() { let mut t: TestExternalities = map![ twox_128(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(>::key()).to_vec() => vec![0u8; 8], @@ -184,8 +184,8 @@ mod tests { assert!(r.is_ok()); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::voting_balance(&alice()), 42); - assert_eq!(Balances::voting_balance(&bob()), 69); + assert_eq!(Balances::total_balance(&alice()), 42); + assert_eq!(Balances::total_balance(&bob()), 69); }); } @@ -315,8 +315,8 @@ mod tests { executor().call(&mut t, COMPACT_CODE, "execute_block", &block1().0, true).0.unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::voting_balance(&alice()), 41); - assert_eq!(Balances::voting_balance(&bob()), 69); + assert_eq!(Balances::total_balance(&alice()), 41); + assert_eq!(Balances::total_balance(&bob()), 69); assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), @@ -328,8 +328,8 @@ mod tests { executor().call(&mut t, COMPACT_CODE, "execute_block", &block2().0, true).0.unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::voting_balance(&alice()), 30); - assert_eq!(Balances::voting_balance(&bob()), 78); + assert_eq!(Balances::total_balance(&alice()), 30); + assert_eq!(Balances::total_balance(&bob()), 78); assert_eq!(System::events(), vec![ EventRecord { phase: Phase::Finalization, @@ -350,15 +350,15 @@ mod tests { WasmExecutor::new(8).call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::voting_balance(&alice()), 41); - assert_eq!(Balances::voting_balance(&bob()), 69); + assert_eq!(Balances::total_balance(&alice()), 41); + assert_eq!(Balances::total_balance(&bob()), 69); }); WasmExecutor::new(8).call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::voting_balance(&alice()), 30); - assert_eq!(Balances::voting_balance(&bob()), 78); + assert_eq!(Balances::total_balance(&alice()), 30); + assert_eq!(Balances::total_balance(&bob()), 78); }); } @@ -390,7 +390,7 @@ mod tests { fn panic_execution_gives_error() { let mut t: TestExternalities = map![ twox_128(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0], twox_128(>::key()).to_vec() => vec![70u8; 8], twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(>::key()).to_vec() => vec![0u8; 8], @@ -411,7 +411,7 @@ mod tests { fn successful_execution_gives_ok() { let mut t: TestExternalities = map![ twox_128(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], + twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0], twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(>::key()).to_vec() => vec![0u8; 8], twox_128(>::key()).to_vec() => vec![0u8; 8], @@ -428,8 +428,8 @@ mod tests { assert_eq!(r, Ok(ApplyOutcome::Success)); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::voting_balance(&alice()), 42); - assert_eq!(Balances::voting_balance(&bob()), 69); + assert_eq!(Balances::total_balance(&alice()), 42); + assert_eq!(Balances::total_balance(&bob()), 69); }); } } diff --git a/substrate/runtime/balances/src/genesis_config.rs b/substrate/runtime/balances/src/genesis_config.rs index 763c626f8db07..ddf9d03521d92 100644 --- a/substrate/runtime/balances/src/genesis_config.rs +++ b/substrate/runtime/balances/src/genesis_config.rs @@ -26,7 +26,7 @@ use primitives::traits::{Zero, As}; use substrate_primitives::KeccakHasher; use {runtime_io, primitives}; use super::{Trait, ENUM_SET_SIZE, EnumSet, NextEnumSet, CreationFee, TransferFee, - ReclaimRebate, ExistentialDeposit, TransactionByteFee, TransactionBaseFee, TotalStake, + ReclaimRebate, ExistentialDeposit, TransactionByteFee, TransactionBaseFee, TotalIssuance, FreeBalance}; #[derive(Serialize, Deserialize)] @@ -102,7 +102,7 @@ impl primitives::BuildStorage for GenesisConfig { Self::hash(>::key()).to_vec() => self.creation_fee.encode(), Self::hash(>::key()).to_vec() => self.existential_deposit.encode(), Self::hash(>::key()).to_vec() => self.reclaim_rebate.encode(), - Self::hash(>::key()).to_vec() => total_stake.encode() + Self::hash(>::key()).to_vec() => total_stake.encode() ]; let ids: Vec<_> = self.balances.iter().map(|x| x.0.clone()).collect(); diff --git a/substrate/runtime/balances/src/lib.rs b/substrate/runtime/balances/src/lib.rs index f47ad764039aa..812b35a7d2239 100644 --- a/substrate/runtime/balances/src/lib.rs +++ b/substrate/runtime/balances/src/lib.rs @@ -78,14 +78,6 @@ pub type Event = RawEvent< ::AccountIndex >; -#[derive(PartialEq, Clone)] -#[cfg_attr(test, derive(Debug))] -pub enum LockStatus { - Liquid, - LockedUntil(BlockNumber), - Bonded, -} - /// The account was the given id was killed. pub trait OnFreeBalanceZero { /// The account was the given id was killed. @@ -126,7 +118,6 @@ pub trait Trait: system::Trait { /// has been reduced to zero. /// /// Gives a chance to clean up resources associated with the given account. - // TODO gav: should ensure staking calls >::remove(who); on this. type OnFreeBalanceZero: OnFreeBalanceZero; /// A function that returns true iff a given account can transfer its funds to another account. @@ -167,8 +158,7 @@ impl From> for () { decl_storage! { trait Store for Module as Balances { // The total amount of stake on the system. - // TODO gav: rename to TotalIssuance - pub TotalStake get(total_stake): required T::Balance; + pub TotalIssuance get(total_stake): required T::Balance; // The minimum amount allowed to keep an account open. pub ExistentialDeposit get(existential_deposit): required T::Balance; // The amount credited to a destination's account whose index was reclaimed. @@ -242,8 +232,7 @@ impl Module { // PUBLIC IMMUTABLES /// The combined balance of `who`. - // TODO gav: rename to total_balance - pub fn voting_balance(who: &T::AccountId) -> T::Balance { + pub fn total_balance(who: &T::AccountId) -> T::Balance { Self::free_balance(who) + Self::reserved_balance(who) } @@ -276,7 +265,7 @@ impl Module { let enum_set_size = Self::enum_set_size(); let try_set = Self::enum_set(try_index / enum_set_size); let i = (try_index % enum_set_size).as_(); - i < try_set.len() && Self::voting_balance(&try_set[i]).is_zero() + i < try_set.len() && Self::total_balance(&try_set[i]).is_zero() } /// Lookup an address to get an Id, if there's one there. @@ -368,7 +357,7 @@ impl Module { /// Returns if the account was successfully updated or update has led to killing of the account. pub fn set_free_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { // Commented out for no - but consider it instructive. - // assert!(!Self::voting_balance(who).is_zero()); + // assert!(!Self::total_balance(who).is_zero()); if balance < Self::existential_deposit() { >::insert(who, balance); Self::on_free_too_low(who); @@ -440,7 +429,7 @@ impl Module { /// /// If `who` doesn't exist, nothing is done and an Err returned. pub fn reward(who: &T::AccountId, value: T::Balance) -> Result { - if Self::voting_balance(who).is_zero() { + if Self::total_balance(who).is_zero() { return Err("beneficiary account must pre-exist"); } Self::set_free_balance(who, Self::free_balance(who) + value); @@ -504,13 +493,12 @@ impl Module { /// /// As much funds up to `value` will be moved as possible. If this is less than `value`, then /// `Ok(Some(remaining))` will be returned. Full completion is given by `Ok(None)`. - // TODO gav: rename to repatriate_reserved. - pub fn transfer_reserved( + pub fn repatriate_reserved( slashed: &T::AccountId, beneficiary: &T::AccountId, value: T::Balance ) -> result::Result, &'static str> { - if Self::voting_balance(beneficiary).is_zero() { + if Self::total_balance(beneficiary).is_zero() { return Err("beneficiary account must pre-exist"); } let b = Self::reserved_balance(slashed); @@ -557,7 +545,7 @@ impl Module { let mut try_set = Self::enum_set(set_index); let item_index = (try_index % enum_set_size).as_(); if item_index < try_set.len() { - if Self::voting_balance(&try_set[item_index]).is_zero() { + if Self::total_balance(&try_set[item_index]).is_zero() { // yup - this index refers to a dead account. can be reused. try_set[item_index] = who.clone(); >::insert(set_index, try_set); @@ -629,16 +617,16 @@ impl Module { } } - /// Increase TotalStake by Value. + /// Increase TotalIssuance by Value. pub fn increase_total_stake_by(value: T::Balance) { if let Some(v) = >::total_stake().checked_add(&value) { - >::put(v); + >::put(v); } } - /// Decrease TotalStake by Value. + /// Decrease TotalIssuance by Value. pub fn decrease_total_stake_by(value: T::Balance) { if let Some(v) = >::total_stake().checked_sub(&value) { - >::put(v); + >::put(v); } } } diff --git a/substrate/runtime/balances/src/tests.rs b/substrate/runtime/balances/src/tests.rs index a78aa6e67825f..6305411d0737d 100644 --- a/substrate/runtime/balances/src/tests.rs +++ b/substrate/runtime/balances/src/tests.rs @@ -25,10 +25,10 @@ use mock::{Balances, System, Test, new_test_ext}; #[test] fn reward_should_work() { with_externalities(&mut new_test_ext(0, true), || { - assert_eq!(Balances::voting_balance(&1), 10); + assert_eq!(Balances::total_balance(&1), 10); assert_ok!(Balances::reward(&1, 10)); - assert_eq!(Balances::voting_balance(&1), 20); - assert_eq!(>::get(), 110); + assert_eq!(Balances::total_balance(&1), 20); + assert_eq!(>::get(), 110); }); } @@ -57,11 +57,11 @@ fn dust_account_removal_should_work() { with_externalities(&mut new_test_ext(256 * 10, true), || { System::inc_account_nonce(&2); assert_eq!(System::account_nonce(&2), 1); - assert_eq!(Balances::voting_balance(&2), 256 * 20); + assert_eq!(Balances::total_balance(&2), 256 * 20); assert_ok!(Balances::transfer(&2, 5.into(), 256 * 10 + 1)); // index 1 (account 2) becomes zombie - assert_eq!(Balances::voting_balance(&2), 0); - assert_eq!(Balances::voting_balance(&5), 256 * 10 + 1); + assert_eq!(Balances::total_balance(&2), 0); + assert_eq!(Balances::total_balance(&5), 256 * 10 + 1); assert_eq!(System::account_nonce(&2), 0); }); } @@ -71,13 +71,13 @@ fn reclaim_indexing_on_new_accounts_should_work() { with_externalities(&mut new_test_ext(256 * 1, true), || { assert_eq!(Balances::lookup_index(1), Some(2)); assert_eq!(Balances::lookup_index(4), None); - assert_eq!(Balances::voting_balance(&2), 256 * 20); + assert_eq!(Balances::total_balance(&2), 256 * 20); assert_ok!(Balances::transfer(&2, 5.into(), 256 * 20)); // account 2 becomes zombie freeing index 1 for reclaim) - assert_eq!(Balances::voting_balance(&2), 0); + assert_eq!(Balances::total_balance(&2), 0); assert_ok!(Balances::transfer(&5, 6.into(), 256 * 1 + 0x69)); // account 6 takes index 1. - assert_eq!(Balances::voting_balance(&6), 256 * 1 + 0x69); + assert_eq!(Balances::total_balance(&6), 256 * 1 + 0x69); assert_eq!(Balances::lookup_index(1), Some(6)); }); } @@ -88,24 +88,24 @@ fn reserved_balance_should_prevent_reclaim_count() { System::inc_account_nonce(&2); assert_eq!(Balances::lookup_index(1), Some(2)); assert_eq!(Balances::lookup_index(4), None); - assert_eq!(Balances::voting_balance(&2), 256 * 20); + assert_eq!(Balances::total_balance(&2), 256 * 20); assert_ok!(Balances::reserve(&2, 256 * 19 + 1)); // account 2 becomes mostly reserved assert_eq!(Balances::free_balance(&2), 0); // "free" account deleted." - assert_eq!(Balances::voting_balance(&2), 256 * 19 + 1); // reserve still exists. + assert_eq!(Balances::total_balance(&2), 256 * 19 + 1); // reserve still exists. assert_eq!(System::account_nonce(&2), 1); assert_ok!(Balances::transfer(&4, 5.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 for account 5. - assert_eq!(Balances::voting_balance(&5), 256 * 1 + 0x69); + assert_eq!(Balances::total_balance(&5), 256 * 1 + 0x69); assert_eq!(Balances::lookup_index(1), Some(2)); // but fails. assert_eq!(System::account_nonce(&2), 1); assert_eq!(Balances::slash(&2, 256 * 18 + 2), None); // account 2 gets slashed - assert_eq!(Balances::voting_balance(&2), 0); // "free" account deleted." + assert_eq!(Balances::total_balance(&2), 0); // "free" account deleted." assert_eq!(System::account_nonce(&2), 0); assert_ok!(Balances::transfer(&4, 6.into(), 256 * 1 + 0x69)); // account 4 tries to take index 1 again for account 6. - assert_eq!(Balances::voting_balance(&6), 256 * 1 + 0x69); + assert_eq!(Balances::total_balance(&6), 256 * 1 + 0x69); assert_eq!(Balances::lookup_index(1), Some(6)); // and succeeds. }); } @@ -116,10 +116,10 @@ fn balance_works() { Balances::set_free_balance(&1, 42); assert_eq!(Balances::free_balance(&1), 42); assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(Balances::voting_balance(&1), 42); + assert_eq!(Balances::total_balance(&1), 42); assert_eq!(Balances::free_balance(&2), 0); assert_eq!(Balances::reserved_balance(&2), 0); - assert_eq!(Balances::voting_balance(&2), 0); + assert_eq!(Balances::total_balance(&2), 0); }); } @@ -129,8 +129,8 @@ fn balance_transfer_works() { Balances::set_free_balance(&1, 111); Balances::increase_total_stake_by(111); assert_ok!(Balances::transfer(&1, 2.into(), 69)); - assert_eq!(Balances::voting_balance(&1), 42); - assert_eq!(Balances::voting_balance(&2), 69); + assert_eq!(Balances::total_balance(&1), 42); + assert_eq!(Balances::total_balance(&2), 69); }); } @@ -139,13 +139,13 @@ fn reserving_balance_should_work() { with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 111); - assert_eq!(Balances::voting_balance(&1), 111); + assert_eq!(Balances::total_balance(&1), 111); assert_eq!(Balances::free_balance(&1), 111); assert_eq!(Balances::reserved_balance(&1), 0); assert_ok!(Balances::reserve(&1, 69)); - assert_eq!(Balances::voting_balance(&1), 111); + assert_eq!(Balances::total_balance(&1), 111); assert_eq!(Balances::free_balance(&1), 42); assert_eq!(Balances::reserved_balance(&1), 69); }); @@ -189,7 +189,7 @@ fn slashing_balance_should_work() { assert!(Balances::slash(&1, 69).is_none()); assert_eq!(Balances::free_balance(&1), 0); assert_eq!(Balances::reserved_balance(&1), 42); - assert_eq!(>::get(), 44); + assert_eq!(>::get(), 44); }); } @@ -202,7 +202,7 @@ fn slashing_incomplete_balance_should_work() { assert!(Balances::slash(&1, 69).is_some()); assert_eq!(Balances::free_balance(&1), 0); assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(>::get(), 2); + assert_eq!(>::get(), 2); }); } @@ -226,7 +226,7 @@ fn slashing_reserved_balance_should_work() { assert!(Balances::slash_reserved(&1, 42).is_none()); assert_eq!(Balances::reserved_balance(&1), 69); assert_eq!(Balances::free_balance(&1), 0); - assert_eq!(>::get(), 71); + assert_eq!(>::get(), 71); }); } @@ -239,7 +239,7 @@ fn slashing_incomplete_reserved_balance_should_work() { assert!(Balances::slash_reserved(&1, 69).is_some()); assert_eq!(Balances::free_balance(&1), 69); assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(>::get(), 71); + assert_eq!(>::get(), 71); }); } @@ -249,7 +249,7 @@ fn transferring_reserved_balance_should_work() { Balances::set_free_balance(&1, 110); Balances::set_free_balance(&2, 1); assert_ok!(Balances::reserve(&1, 110)); - assert_ok!(Balances::transfer_reserved(&1, &2, 41), None); + assert_ok!(Balances::repatriate_reserved(&1, &2, 41), None); assert_eq!(Balances::reserved_balance(&1), 69); assert_eq!(Balances::free_balance(&1), 0); assert_eq!(Balances::reserved_balance(&2), 0); @@ -262,7 +262,7 @@ fn transferring_reserved_balance_to_nonexistent_should_fail() { with_externalities(&mut new_test_ext(0, false), || { Balances::set_free_balance(&1, 111); assert_ok!(Balances::reserve(&1, 111)); - assert_noop!(Balances::transfer_reserved(&1, &2, 42), "beneficiary account must pre-exist"); + assert_noop!(Balances::repatriate_reserved(&1, &2, 42), "beneficiary account must pre-exist"); }); } @@ -272,7 +272,7 @@ fn transferring_incomplete_reserved_balance_should_work() { Balances::set_free_balance(&1, 110); Balances::set_free_balance(&2, 1); assert_ok!(Balances::reserve(&1, 41)); - assert!(Balances::transfer_reserved(&1, &2, 69).unwrap().is_some()); + assert!(Balances::repatriate_reserved(&1, &2, 69).unwrap().is_some()); assert_eq!(Balances::reserved_balance(&1), 0); assert_eq!(Balances::free_balance(&1), 69); assert_eq!(Balances::reserved_balance(&2), 0); @@ -307,7 +307,7 @@ fn account_removal_on_free_too_low() { Balances::set_free_balance(&2, 110); Balances::increase_total_stake_by(110); - assert_eq!(>::get(), 732); + assert_eq!(>::get(), 732); } // Transfer funds from account 1 of such amount that after this transfer @@ -318,7 +318,7 @@ fn account_removal_on_free_too_low() { // Verify free balance removal of account 1. assert_eq!(Balances::free_balance(&1), 0); - // Verify that TotalStake tracks balance removal when free balance is too low. - assert_eq!(>::get(), 642); + // Verify that TotalIssuance tracks balance removal when free balance is too low. + assert_eq!(>::get(), 642); }); } diff --git a/substrate/runtime/council/src/lib.rs b/substrate/runtime/council/src/lib.rs index 2b2f4783b9c3a..898c49862f5c0 100644 --- a/substrate/runtime/council/src/lib.rs +++ b/substrate/runtime/council/src/lib.rs @@ -296,7 +296,7 @@ impl Module { if valid { // This only fails if `who` doesn't exist, which it clearly must do since its the aux. // Still, it's no more harmful to propagate any error at this point. - >::transfer_reserved(&who, aux.ref_into(), Self::voting_bond())?; + >::repatriate_reserved(&who, aux.ref_into(), Self::voting_bond())?; } else { >::slash_reserved(aux.ref_into(), Self::voting_bond()); } @@ -469,7 +469,7 @@ impl Module { >::put((number + Self::presentation_duration(), empty_seats as u32, expiring)); let voters = Self::voters(); - let votes = voters.iter().map(>::voting_balance).collect::>(); + let votes = voters.iter().map(>::total_balance).collect::>(); >::put(votes); // initialise leaderboard. @@ -1027,7 +1027,7 @@ mod tests { assert_ok!(Council::end_block(System::block_number())); assert_eq!(Council::active_council(), vec![(5, 11), (2, 11)]); - assert_eq!(Balances::voting_balance(&4), 38); + assert_eq!(Balances::total_balance(&4), 38); }); } @@ -1060,8 +1060,8 @@ mod tests { assert_eq!(Council::voters(), vec![5]); assert_eq!(Council::approvals_of(2).len(), 0); - assert_eq!(Balances::voting_balance(&2), 17); - assert_eq!(Balances::voting_balance(&5), 53); + assert_eq!(Balances::total_balance(&2), 17); + assert_eq!(Balances::total_balance(&5), 53); }); } @@ -1119,8 +1119,8 @@ mod tests { assert_eq!(Council::voters(), vec![5]); assert_eq!(Council::approvals_of(2).len(), 0); - assert_eq!(Balances::voting_balance(&2), 17); - assert_eq!(Balances::voting_balance(&5), 53); + assert_eq!(Balances::total_balance(&2), 17); + assert_eq!(Balances::total_balance(&5), 53); }); } @@ -1220,7 +1220,7 @@ mod tests { assert_eq!(Council::voters(), vec![2, 3, 5]); assert_eq!(Council::approvals_of(4).len(), 0); - assert_eq!(Balances::voting_balance(&4), 37); + assert_eq!(Balances::total_balance(&4), 37); }); } @@ -1358,7 +1358,7 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); assert!(!Council::presentation_active()); - assert_eq!(Balances::voting_balance(&4), 40); + assert_eq!(Balances::total_balance(&4), 40); assert_ok!(Council::submit_candidacy(&2, 0)); assert_ok!(Council::submit_candidacy(&5, 1)); @@ -1369,7 +1369,7 @@ mod tests { System::set_block_number(6); assert_err!(Council::present_winner(&4, 2.into(), 80, 0), "incorrect total"); - assert_eq!(Balances::voting_balance(&4), 38); + assert_eq!(Balances::total_balance(&4), 38); }); } diff --git a/substrate/runtime/democracy/src/lib.rs b/substrate/runtime/democracy/src/lib.rs index 87e84b7e73f19..9ff8b7f85a1a9 100644 --- a/substrate/runtime/democracy/src/lib.rs +++ b/substrate/runtime/democracy/src/lib.rs @@ -148,7 +148,7 @@ impl Module { /// Get the voters for the current proposal. pub fn tally(ref_index: ReferendumIndex) -> (T::Balance, T::Balance) { Self::voters_for(ref_index).iter() - .map(|a| (>::voting_balance(a), Self::vote_of((ref_index, a.clone())).unwrap_or(false)/*defensive only: all items come from `voters`; for an item to be in `voters` there must be a vote registered; qed*/)) + .map(|a| (>::total_balance(a), Self::vote_of((ref_index, a.clone())).unwrap_or(false)/*defensive only: all items come from `voters`; for an item to be in `voters` there must be a vote registered; qed*/)) .map(|(bal, vote)| if vote { (bal, Zero::zero()) } else { (Zero::zero(), bal) }) .fold((Zero::zero(), Zero::zero()), |(a, b), (c, d)| (a + c, b + d)) } @@ -186,7 +186,7 @@ impl Module { /// false would be a vote to keep the status quo.. fn vote(aux: &T::PublicAux, ref_index: ReferendumIndex, approve_proposal: bool) -> Result { ensure!(Self::is_active_referendum(ref_index), "vote given for invalid referendum."); - ensure!(!>::voting_balance(aux.ref_into()).is_zero(), + ensure!(!>::total_balance(aux.ref_into()).is_zero(), "transactor must have balance to signal approval."); if !>::exists(&(ref_index, aux.ref_into().clone())) { let mut voters = Self::voters_for(ref_index); diff --git a/substrate/runtime/executive/src/lib.rs b/substrate/runtime/executive/src/lib.rs index bb7cee50883c7..46024b0a1f4d7 100644 --- a/substrate/runtime/executive/src/lib.rs +++ b/substrate/runtime/executive/src/lib.rs @@ -321,8 +321,8 @@ mod tests { with_externalities(&mut t, || { Executive::initialise_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); Executive::apply_extrinsic(xt).unwrap(); - assert_eq!(>::voting_balance(&1), 32); - assert_eq!(>::voting_balance(&2), 69); + assert_eq!(>::total_balance(&1), 32); + assert_eq!(>::total_balance(&2), 69); }); } diff --git a/substrate/runtime/staking/src/lib.rs b/substrate/runtime/staking/src/lib.rs index 5359a9ec660c4..f9c43b2e70d12 100644 --- a/substrate/runtime/staking/src/lib.rs +++ b/substrate/runtime/staking/src/lib.rs @@ -48,9 +48,8 @@ extern crate substrate_runtime_session as session; extern crate substrate_runtime_system as system; extern crate substrate_runtime_timestamp as timestamp; -#[cfg(test)] use std::fmt::Debug; use rstd::prelude::*; -use runtime_support::{StorageValue, StorageMap}; +use runtime_support::{Parameter, StorageValue, StorageMap}; use runtime_support::dispatch::Result; use session::OnSessionChange; use primitives::traits::{Zero, One, Bounded, RefInto, Executable, @@ -72,20 +71,12 @@ pub type Event = RawEvent< ::AccountId >; -#[cfg(test)] -#[derive(Debug, PartialEq, Clone)] -pub enum LockStatus { - Liquid, - LockedUntil(BlockNumber), - Staked, -} - -#[cfg(not(test))] #[derive(PartialEq, Clone)] -pub enum LockStatus { +#[cfg_attr(test, derive(Debug))] +pub enum LockStatus { Liquid, LockedUntil(BlockNumber), - Staked, + Bonded, } /// Preference of what happens on a slash event. @@ -166,8 +157,7 @@ decl_storage! { pub EarlyEraSlash get(early_era_slash): required T::Balance; // Number of instances of offline reports before slashing begins for validators. pub OfflineSlashGrace get(offline_slash_grace): default u32; - // The length of the bonding duration in eras. - // TODO gav: switch to blocks or time. + // The length of the bonding duration in blocks. pub BondingDuration get(bonding_duration): required T::BlockNumber; // The current era index. @@ -216,21 +206,21 @@ impl Module { /// Balance of a (potential) validator that includes all nominators. pub fn nomination_balance(who: &T::AccountId) -> T::Balance { Self::nominators_for(who).iter() - .map(>::voting_balance) + .map(>::total_balance) .fold(Zero::zero(), |acc, x| acc + x) } /// The total balance that can be slashed from an account. pub fn slashable_balance(who: &T::AccountId) -> T::Balance { Self::nominators_for(who).iter() - .map(>::voting_balance) - .fold(>::voting_balance(who), |acc, x| acc + x) + .map(>::total_balance) + .fold(>::total_balance(who), |acc, x| acc + x) } /// The block at which the `who`'s funds become entirely liquid. pub fn unlock_block(who: &T::AccountId) -> LockStatus { match Self::bondage(who) { - i if i == T::BlockNumber::max_value() => LockStatus::Staked, + i if i == T::BlockNumber::max_value() => LockStatus::Bonded, i if i <= >::block_number() => LockStatus::Liquid, i => LockStatus::LockedUntil(i), } @@ -308,7 +298,7 @@ impl Module { >::remove(source); // update bondage - >::insert(aux.ref_into(), Self::current_era() + Self::bonding_duration()); + >::insert(aux.ref_into(), >::block_number() + Self::bonding_duration()); Ok(()) } @@ -425,11 +415,11 @@ impl Module { if let Some(rem) = >::slash(v, slash) { let noms = Self::current_nominators_for(v); - let total = noms.iter().map(>::voting_balance).fold(T::Balance::zero(), |acc, x| acc + x); + let total = noms.iter().map(>::total_balance).fold(T::Balance::zero(), |acc, x| acc + x); if !total.is_zero() { let safe_mul_rational = |b| b * rem / total;// TODO: avoid overflow for n in noms.iter() { - let _ = >::slash(n, safe_mul_rational(>::voting_balance(n))); // best effort - not much that can be done on fail. + let _ = >::slash(n, safe_mul_rational(>::total_balance(n))); // best effort - not much that can be done on fail. } } } @@ -439,13 +429,13 @@ impl Module { /// balance, pro-rata. fn reward_validator(who: &T::AccountId, reward: T::Balance) { let noms = Self::current_nominators_for(who); - let total = noms.iter().map(>::voting_balance).fold(>::voting_balance(who), |acc, x| acc + x); + let total = noms.iter().map(>::total_balance).fold(>::total_balance(who), |acc, x| acc + x); if !total.is_zero() { let safe_mul_rational = |b| b * reward / total;// TODO: avoid overflow for n in noms.iter() { - let _ = >::reward(n, safe_mul_rational(>::voting_balance(n))); + let _ = >::reward(n, safe_mul_rational(>::total_balance(n))); } - let _ = >::reward(who, safe_mul_rational(>::voting_balance(who))); + let _ = >::reward(who, safe_mul_rational(>::total_balance(who))); } } @@ -460,7 +450,7 @@ impl Module { >::put(intentions); >::remove(who); >::remove(who); - >::insert(who, Self::current_era() + Self::bonding_duration()); + >::insert(who, >::block_number() + Self::bonding_duration()); Ok(()) } diff --git a/substrate/runtime/staking/src/tests.rs b/substrate/runtime/staking/src/tests.rs index 285d7d4b41c0c..6c99cb6e0f0e8 100644 --- a/substrate/runtime/staking/src/tests.rs +++ b/substrate/runtime/staking/src/tests.rs @@ -172,26 +172,26 @@ fn rewards_should_work() { assert_eq!(Staking::last_era_length_change(), 0); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 0); - assert_eq!(Balances::voting_balance(&10), 1); + assert_eq!(Balances::total_balance(&10), 1); System::set_block_number(3); Timestamp::set_timestamp(15); // on time. Session::check_rotate_session(); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 1); - assert_eq!(Balances::voting_balance(&10), 11); + assert_eq!(Balances::total_balance(&10), 11); System::set_block_number(6); Timestamp::set_timestamp(31); // a little late Session::check_rotate_session(); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 2); - assert_eq!(Balances::voting_balance(&10), 20); // less reward + assert_eq!(Balances::total_balance(&10), 20); // less reward System::set_block_number(9); Timestamp::set_timestamp(50); // very late Session::check_rotate_session(); assert_eq!(Staking::current_era(), 1); assert_eq!(Session::current_index(), 3); - assert_eq!(Balances::voting_balance(&10), 27); // much less reward + assert_eq!(Balances::total_balance(&10), 27); // much less reward }); } @@ -203,24 +203,24 @@ fn slashing_should_work() { assert_eq!(Staking::last_era_length_change(), 0); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 0); - assert_eq!(Balances::voting_balance(&10), 1); + assert_eq!(Balances::total_balance(&10), 1); System::set_block_number(3); Session::check_rotate_session(); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 1); - assert_eq!(Balances::voting_balance(&10), 11); + assert_eq!(Balances::total_balance(&10), 11); System::set_block_number(6); Session::check_rotate_session(); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 2); - assert_eq!(Balances::voting_balance(&10), 21); + assert_eq!(Balances::total_balance(&10), 21); System::set_block_number(7); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); - assert_eq!(Balances::voting_balance(&10), 1); + assert_eq!(Balances::total_balance(&10), 1); }); } @@ -301,20 +301,20 @@ fn nominating_and_rewards_should_work() { Session::check_rotate_session(); assert_eq!(Staking::current_era(), 1); assert_eq!(Session::validators(), vec![1, 3]); // 4 + 1, 3 - assert_eq!(Balances::voting_balance(&1), 10); - assert_eq!(Balances::voting_balance(&2), 20); - assert_eq!(Balances::voting_balance(&3), 30); - assert_eq!(Balances::voting_balance(&4), 40); + assert_eq!(Balances::total_balance(&1), 10); + assert_eq!(Balances::total_balance(&2), 20); + assert_eq!(Balances::total_balance(&3), 30); + assert_eq!(Balances::total_balance(&4), 40); System::set_block_number(2); assert_ok!(Staking::unnominate(&4, 0)); Session::check_rotate_session(); assert_eq!(Staking::current_era(), 2); assert_eq!(Session::validators(), vec![3, 2]); - assert_eq!(Balances::voting_balance(&1), 12); - assert_eq!(Balances::voting_balance(&2), 20); - assert_eq!(Balances::voting_balance(&3), 40); - assert_eq!(Balances::voting_balance(&4), 48); + assert_eq!(Balances::total_balance(&1), 12); + assert_eq!(Balances::total_balance(&2), 20); + assert_eq!(Balances::total_balance(&3), 40); + assert_eq!(Balances::total_balance(&4), 48); System::set_block_number(3); assert_ok!(Staking::stake(&4)); @@ -322,17 +322,17 @@ fn nominating_and_rewards_should_work() { assert_ok!(Staking::nominate(&3, 1.into())); Session::check_rotate_session(); assert_eq!(Session::validators(), vec![1, 4]); - assert_eq!(Balances::voting_balance(&1), 12); - assert_eq!(Balances::voting_balance(&2), 30); - assert_eq!(Balances::voting_balance(&3), 50); - assert_eq!(Balances::voting_balance(&4), 48); + assert_eq!(Balances::total_balance(&1), 12); + assert_eq!(Balances::total_balance(&2), 30); + assert_eq!(Balances::total_balance(&3), 50); + assert_eq!(Balances::total_balance(&4), 48); System::set_block_number(4); Session::check_rotate_session(); - assert_eq!(Balances::voting_balance(&1), 13); - assert_eq!(Balances::voting_balance(&2), 30); - assert_eq!(Balances::voting_balance(&3), 58); - assert_eq!(Balances::voting_balance(&4), 58); + assert_eq!(Balances::total_balance(&1), 13); + assert_eq!(Balances::total_balance(&2), 30); + assert_eq!(Balances::total_balance(&3), 58); + assert_eq!(Balances::total_balance(&4), 58); }); } @@ -357,18 +357,18 @@ fn nominating_slashes_should_work() { assert_eq!(Staking::current_era(), 1); assert_eq!(Session::validators(), vec![1, 3]); // 1 + 4, 3 + 2 - assert_eq!(Balances::voting_balance(&1), 10); - assert_eq!(Balances::voting_balance(&2), 20); - assert_eq!(Balances::voting_balance(&3), 30); - assert_eq!(Balances::voting_balance(&4), 40); + assert_eq!(Balances::total_balance(&1), 10); + assert_eq!(Balances::total_balance(&2), 20); + assert_eq!(Balances::total_balance(&3), 30); + assert_eq!(Balances::total_balance(&4), 40); System::set_block_number(5); ::system::ExtrinsicIndex::::put(1); assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); - assert_eq!(Balances::voting_balance(&1), 0); - assert_eq!(Balances::voting_balance(&2), 20); - assert_eq!(Balances::voting_balance(&3), 10); - assert_eq!(Balances::voting_balance(&4), 30); + assert_eq!(Balances::total_balance(&1), 0); + assert_eq!(Balances::total_balance(&2), 20); + assert_eq!(Balances::total_balance(&3), 10); + assert_eq!(Balances::total_balance(&4), 30); }); } From bfdf79debc8e1ce5d13b508a17a07cfa0b27564c Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 29 Aug 2018 23:43:35 +0200 Subject: [PATCH 13/19] Fix tests --- demo/executor/src/lib.rs | 6 +++--- .../release/demo_runtime.compact.wasm | Bin 296537 -> 296539 bytes .../release/demo_runtime.wasm | Bin 296621 -> 296624 bytes substrate/runtime/executive/src/lib.rs | 4 ++-- substrate/runtime/staking/src/mock.rs | 2 +- substrate/runtime/staking/src/tests.rs | 7 +++++-- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/demo/executor/src/lib.rs b/demo/executor/src/lib.rs index b73e80b0feb8e..64289234b8070 100644 --- a/demo/executor/src/lib.rs +++ b/demo/executor/src/lib.rs @@ -260,7 +260,7 @@ mod tests { // Blake // hex!("3437bf4b182ab17bb322af5c67e55f6be487a77084ad2b4e27ddac7242e4ad21").into(), // Keccak - hex!("d80a4a89e0a02864b5624ea9abb00f75285b8148c169c859d330b573914f1784").into(), + hex!("a3f5ce86e303f4001d14124ab690428d10cd9e60d21699b42096358c2422445f").into(), vec![BareExtrinsic { signed: alice(), index: 0, @@ -276,7 +276,7 @@ mod tests { // Blake // hex!("741fcb660e6fa9f625fbcd993b49f6c1cc4040f5e0cc8727afdedf11fd3c464b").into(), // Keccak - hex!("83e23a6dfbcf783ceb8eb4704344b8ec0478159fc670fa7a9f0c368a28eb8b74").into(), + hex!("72dc147d2619a978adc38a38abc85bb77e25b0095ad38b15f97d56ccb66f36e8").into(), vec![ BareExtrinsic { signed: bob(), @@ -299,7 +299,7 @@ mod tests { // Blake // hex!("2c7231a9c210a7aa4bea169d944bc4aaacd517862b244b8021236ffa7f697991").into(), // Keccak - hex!("bd24909630b9431ca0e07492f880a5622c5f3c1471a0b0a2653b8c8e341df40b").into(), + hex!("7aa14ff631321ca5aa22e6fa53e3569faa732758993fa82e2dbde31a1b720391").into(), vec![BareExtrinsic { signed: alice(), index: 0, diff --git a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm index d8c65a2b92f609b3ea993f3d7e5a5962d780e995..675b08559e4927dcd503016dcf0670be299051f3 100644 GIT binary patch delta 7166 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 delta 7136 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 diff --git a/substrate/runtime/executive/src/lib.rs b/substrate/runtime/executive/src/lib.rs index 46024b0a1f4d7..015c6fa0cb52c 100644 --- a/substrate/runtime/executive/src/lib.rs +++ b/substrate/runtime/executive/src/lib.rs @@ -346,7 +346,7 @@ mod tests { // Blake // state_root: hex!("02532989c613369596025dfcfc821339fc9861987003924913a5a1382f87034a").into(), // Keccak - state_root: hex!("5b846f849bf38ef5acd96e1c999cd61619408015919f06ab575384d83cf45aa7").into(), + state_root: hex!("ffe27b4c3a8b421fa10592be61fb28eca7ebbe04cbfa99cdda9f703f35522569").into(), extrinsics_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), digest: Digest { logs: vec![], }, }, @@ -380,7 +380,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("5b846f849bf38ef5acd96e1c999cd61619408015919f06ab575384d83cf45aa7").into(), + state_root: hex!("ffe27b4c3a8b421fa10592be61fb28eca7ebbe04cbfa99cdda9f703f35522569").into(), extrinsics_root: [0u8; 32].into(), digest: Digest { logs: vec![], }, }, diff --git a/substrate/runtime/staking/src/mock.rs b/substrate/runtime/staking/src/mock.rs index 39f990c6fe7ba..05bea85659b2b 100644 --- a/substrate/runtime/staking/src/mock.rs +++ b/substrate/runtime/staking/src/mock.rs @@ -104,7 +104,7 @@ pub fn new_test_ext(ext_deposit: u64, session_length: u64, sessions_per_era: u64 intentions: vec![10, 20], validator_count: 2, minimum_validator_count: 0, - bonding_duration: 3, + bonding_duration: sessions_per_era * session_length * 3, session_reward: reward, early_era_slash: if monied { 20 } else { 0 }, offline_slash_grace: 0, diff --git a/substrate/runtime/staking/src/tests.rs b/substrate/runtime/staking/src/tests.rs index 6c99cb6e0f0e8..366d3b5d9481a 100644 --- a/substrate/runtime/staking/src/tests.rs +++ b/substrate/runtime/staking/src/tests.rs @@ -229,10 +229,13 @@ fn slashing_should_work() { #[test] fn staking_should_work() { with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { + assert_eq!(Staking::era_length(), 2); assert_eq!(Staking::validator_count(), 2); - assert_eq!(Staking::bonding_duration(), 3); assert_eq!(Session::validators(), vec![10, 20]); + + assert_ok!(Staking::set_bonding_duration(2)); + assert_eq!(Staking::bonding_duration(), 2); // Block 1: Add three validators. No obvious change. System::set_block_number(1); @@ -341,7 +344,7 @@ fn nominating_slashes_should_work() { with_externalities(&mut new_test_ext(0, 2, 2, 0, true, 10), || { assert_eq!(Staking::era_length(), 4); assert_eq!(Staking::validator_count(), 2); - assert_eq!(Staking::bonding_duration(), 3); + assert_eq!(Staking::bonding_duration(), 12); assert_eq!(Session::validators(), vec![10, 20]); System::set_block_number(2); From 7c8f8dfdbdc2d837cf0bc6740b186b0376806d3b Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 29 Aug 2018 23:54:27 +0200 Subject: [PATCH 14/19] Remove superfluous code --- .../runtime/balances/src/genesis_config.rs | 34 ------------------- substrate/runtime/democracy/src/lib.rs | 8 ----- .../runtime/staking/src/genesis_config.rs | 30 ---------------- 3 files changed, 72 deletions(-) diff --git a/substrate/runtime/balances/src/genesis_config.rs b/substrate/runtime/balances/src/genesis_config.rs index ddf9d03521d92..010fee948240e 100644 --- a/substrate/runtime/balances/src/genesis_config.rs +++ b/substrate/runtime/balances/src/genesis_config.rs @@ -42,40 +42,6 @@ pub struct GenesisConfig { pub existential_deposit: T::Balance, } -impl GenesisConfig where T::AccountId: From { - pub fn simple() -> Self { - GenesisConfig { - balances: vec![(T::AccountId::from(1), T::Balance::sa(111))], - transaction_base_fee: T::Balance::sa(0), - transaction_byte_fee: T::Balance::sa(0), - transfer_fee: T::Balance::sa(0), - creation_fee: T::Balance::sa(0), - existential_deposit: T::Balance::sa(0), - reclaim_rebate: T::Balance::sa(0), - } - } - - pub fn extended() -> Self { - GenesisConfig { - balances: vec![ - (T::AccountId::from(1), T::Balance::sa(10)), - (T::AccountId::from(2), T::Balance::sa(20)), - (T::AccountId::from(3), T::Balance::sa(30)), - (T::AccountId::from(4), T::Balance::sa(40)), - (T::AccountId::from(5), T::Balance::sa(50)), - (T::AccountId::from(6), T::Balance::sa(60)), - (T::AccountId::from(7), T::Balance::sa(1)) - ], - transaction_base_fee: T::Balance::sa(1), - transaction_byte_fee: T::Balance::sa(0), - transfer_fee: T::Balance::sa(0), - creation_fee: T::Balance::sa(0), - existential_deposit: T::Balance::sa(0), - reclaim_rebate: T::Balance::sa(0), - } - } -} - impl Default for GenesisConfig { fn default() -> Self { GenesisConfig { diff --git a/substrate/runtime/democracy/src/lib.rs b/substrate/runtime/democracy/src/lib.rs index 9ff8b7f85a1a9..f626d099988a3 100644 --- a/substrate/runtime/democracy/src/lib.rs +++ b/substrate/runtime/democracy/src/lib.rs @@ -315,14 +315,6 @@ impl GenesisConfig { minimum_deposit: T::Balance::sa(1), } } - - pub fn extended() -> Self { - GenesisConfig { - launch_period: T::BlockNumber::sa(1), - voting_period: T::BlockNumber::sa(3), - minimum_deposit: T::Balance::sa(1), - } - } } #[cfg(any(feature = "std", test))] diff --git a/substrate/runtime/staking/src/genesis_config.rs b/substrate/runtime/staking/src/genesis_config.rs index da0d898bb3592..ce9adda2223df 100644 --- a/substrate/runtime/staking/src/genesis_config.rs +++ b/substrate/runtime/staking/src/genesis_config.rs @@ -43,36 +43,6 @@ pub struct GenesisConfig { pub offline_slash_grace: u32, } -impl GenesisConfig where T::AccountId: From { - pub fn simple() -> Self { - GenesisConfig { - sessions_per_era: T::BlockNumber::sa(2), - current_era: T::BlockNumber::sa(0), - intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], - validator_count: 3, - minimum_validator_count: 1, - bonding_duration: T::BlockNumber::sa(0), - session_reward: T::Balance::sa(0), - early_era_slash: T::Balance::sa(0), - offline_slash_grace: 1, - } - } - - pub fn extended() -> Self { - GenesisConfig { - sessions_per_era: T::BlockNumber::sa(3), - current_era: T::BlockNumber::sa(1), - intentions: vec![T::AccountId::from(1), T::AccountId::from(2), T::AccountId::from(3)], - validator_count: 3, - minimum_validator_count: 1, - bonding_duration: T::BlockNumber::sa(0), - session_reward: T::Balance::sa(0), - early_era_slash: T::Balance::sa(0), - offline_slash_grace: 1, - } - } -} - impl Default for GenesisConfig { fn default() -> Self { GenesisConfig { From 5769344e4e7165bbd852555ac420ee9ca57b5b5c Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 30 Aug 2018 10:57:15 +0200 Subject: [PATCH 15/19] Move offline inherents to consensus module. Fixes #630 --- demo/runtime/src/lib.rs | 3 +- substrate/runtime/balances/src/mock.rs | 9 +-- substrate/runtime/consensus/src/lib.rs | 35 +++++++++- substrate/runtime/executive/src/lib.rs | 3 +- substrate/runtime/session/src/lib.rs | 2 + substrate/runtime/staking/src/lib.rs | 90 +++++++++++--------------- substrate/runtime/staking/src/mock.rs | 3 +- substrate/runtime/staking/src/tests.rs | 45 +++++++------ substrate/runtime/timestamp/src/lib.rs | 2 + 9 files changed, 106 insertions(+), 86 deletions(-) diff --git a/demo/runtime/src/lib.rs b/demo/runtime/src/lib.rs index 2d5250458f9a4..9fb45eb88ed1f 100644 --- a/demo/runtime/src/lib.rs +++ b/demo/runtime/src/lib.rs @@ -115,7 +115,9 @@ impl balances::Trait for Concrete { pub type Balances = balances::Module; impl consensus::Trait for Concrete { + const NOTE_OFFLINE_POSITION: u32 = 1; type SessionKey = SessionKey; + type OnOfflineValidator = Staking; } /// Consensus module for this concrete runtime. @@ -148,7 +150,6 @@ impl session::Trait for Concrete { pub type Session = session::Module; impl staking::Trait for Concrete { - const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1; type Event = Event; } diff --git a/substrate/runtime/balances/src/mock.rs b/substrate/runtime/balances/src/mock.rs index c356ef854deef..747dbd16eb1c7 100644 --- a/substrate/runtime/balances/src/mock.rs +++ b/substrate/runtime/balances/src/mock.rs @@ -23,7 +23,7 @@ use primitives::traits::HasPublicAux; use primitives::testing::{Digest, Header}; use substrate_primitives::{H256, KeccakHasher}; use runtime_io; -use {GenesisConfig, Module, Trait, consensus, system}; +use {GenesisConfig, Module, Trait, system}; // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] @@ -31,9 +31,6 @@ pub struct Test; impl HasPublicAux for Test { type PublicAux = u64; } -impl consensus::Trait for Test { - type SessionKey = u64; -} impl system::Trait for Test { type PublicAux = ::PublicAux; type Index = u64; @@ -60,10 +57,6 @@ pub fn new_test_ext(ext_deposit: u64, monied: bool) -> runtime_io::TestExternali } else { 1 }; - t.extend(consensus::GenesisConfig::{ - code: vec![], - authorities: vec![], - }.build_storage().unwrap()); t.extend(GenesisConfig::{ balances: if monied { vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor)] diff --git a/substrate/runtime/consensus/src/lib.rs b/substrate/runtime/consensus/src/lib.rs index b8e80f6a13aaf..cc8f2433ab0d2 100644 --- a/substrate/runtime/consensus/src/lib.rs +++ b/substrate/runtime/consensus/src/lib.rs @@ -42,7 +42,7 @@ use rstd::prelude::*; use runtime_support::{storage, Parameter}; use runtime_support::dispatch::Result; use runtime_support::storage::unhashed::StorageVec; -use primitives::traits::MaybeSerializeDebug; +use primitives::traits::{MaybeSerializeDebug, MaybeEmpty}; use primitives::bft::MisbehaviorReport; #[cfg(any(feature = "std", test))] @@ -63,8 +63,20 @@ pub const CODE: &'static [u8] = b":code"; pub type KeyValue = (Vec, Vec); +pub trait OnOfflineValidator { + fn on_offline_validator(validator_index: usize); +} + +impl OnOfflineValidator for () { + fn on_offline_validator(_validator_index: usize) {} +} + pub trait Trait: system::Trait { + /// The allowed extrinsic position for `note_offline` inherent. + const NOTE_OFFLINE_POSITION: u32; + type SessionKey: Parameter + Default + MaybeSerializeDebug; + type OnOfflineValidator: OnOfflineValidator; } decl_module! { @@ -73,7 +85,8 @@ decl_module! { #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum Call where aux: T::PublicAux { fn report_misbehavior(aux, report: MisbehaviorReport) -> Result = 0; - fn remark(aux, remark: Vec) -> Result = 1; + fn note_offline(aux, offline_val_indices: Vec) -> Result = 1; + fn remark(aux, remark: Vec) -> Result = 2; } #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -109,6 +122,24 @@ impl Module { Ok(()) } + /// Note the previous block's validator missed their opportunity to propose a block. This only comes in + /// if 2/3+1 of the validators agree that no proposal was submitted. It's only relevant + /// for the previous block. + fn note_offline(aux: &T::PublicAux, offline_val_indices: Vec) -> Result { + assert!(aux.is_empty()); + assert!( + >::extrinsic_index() == Some(T::NOTE_OFFLINE_POSITION), + "note_offline extrinsic must be at position {} in the block", + T::NOTE_OFFLINE_POSITION + ); + + for validator_index in offline_val_indices.into_iter() { + T::OnOfflineValidator::on_offline_validator(validator_index as usize); + } + + Ok(()) + } + /// Make some on-chain remark. fn remark(_aux: &T::PublicAux, _remark: Vec) -> Result { Ok(()) diff --git a/substrate/runtime/executive/src/lib.rs b/substrate/runtime/executive/src/lib.rs index 015c6fa0cb52c..4220e50abbf52 100644 --- a/substrate/runtime/executive/src/lib.rs +++ b/substrate/runtime/executive/src/lib.rs @@ -256,7 +256,9 @@ mod tests { type PublicAux = u64; } impl consensus::Trait for Test { + const NOTE_OFFLINE_POSITION: u32 = 1; type SessionKey = u64; + type OnOfflineValidator = staking::Module; } impl balances::Trait for Test { type Balance = u64; @@ -282,7 +284,6 @@ mod tests { type Event = MetaEvent; } impl staking::Trait for Test { - const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1; type Event = MetaEvent; } impl timestamp::Trait for Test { diff --git a/substrate/runtime/session/src/lib.rs b/substrate/runtime/session/src/lib.rs index c87bec3ae2cd1..3308ec6e551fe 100644 --- a/substrate/runtime/session/src/lib.rs +++ b/substrate/runtime/session/src/lib.rs @@ -302,7 +302,9 @@ mod tests { type PublicAux = u64; } impl consensus::Trait for Test { + const NOTE_OFFLINE_POSITION: u32 = 1; type SessionKey = u64; + type OnOfflineValidator = (); } impl system::Trait for Test { type PublicAux = ::PublicAux; diff --git a/substrate/runtime/staking/src/lib.rs b/substrate/runtime/staking/src/lib.rs index f9c43b2e70d12..a5f813a7350ea 100644 --- a/substrate/runtime/staking/src/lib.rs +++ b/substrate/runtime/staking/src/lib.rs @@ -53,7 +53,7 @@ use runtime_support::{Parameter, StorageValue, StorageMap}; use runtime_support::dispatch::Result; use session::OnSessionChange; use primitives::traits::{Zero, One, Bounded, RefInto, Executable, - As, AuxLookup, MaybeEmpty}; + As, AuxLookup}; use balances::address::Address; mod mock; @@ -96,9 +96,6 @@ impl Default for SlashPreference { } pub trait Trait: balances::Trait + session::Trait { - /// The allowed extrinsic position for `missed_proposal` inherent. - const NOTE_MISSED_PROPOSAL_POSITION: u32; - /// The overarching event type. type Event: From> + Into<::Event>; } @@ -108,12 +105,11 @@ decl_module! { #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum Call where aux: T::PublicAux { - fn note_missed_proposal(aux, offline_val_indices: Vec) -> Result = 0; - fn stake(aux) -> Result = 1; - fn unstake(aux, intentions_index: u32) -> Result = 2; - fn nominate(aux, target: Address) -> Result = 3; - fn unnominate(aux, target_index: u32) -> Result = 4; - fn register_slash_preference(aux, intentions_index: u32, p: SlashPreference) -> Result = 5; + fn stake(aux) -> Result = 0; + fn unstake(aux, intentions_index: u32) -> Result = 1; + fn nominate(aux, target: Address) -> Result = 2; + fn unnominate(aux, target_index: u32) -> Result = 3; + fn register_slash_preference(aux, intentions_index: u32, p: SlashPreference) -> Result = 4; } #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -321,49 +317,6 @@ impl Module { Ok(()) } - /// Note the previous block's validator missed their opportunity to propose a block. This only comes in - /// if 2/3+1 of the validators agree that no proposal was submitted. It's only relevant - /// for the previous block. - fn note_missed_proposal(aux: &T::PublicAux, offline_val_indices: Vec) -> Result { - assert!(aux.is_empty()); - assert!( - >::extrinsic_index() == Some(T::NOTE_MISSED_PROPOSAL_POSITION), - "note_missed_proposal extrinsic must be at position {} in the block", - T::NOTE_MISSED_PROPOSAL_POSITION - ); - - for validator_index in offline_val_indices.into_iter() { - let v = >::validators()[validator_index as usize].clone(); - let slash_count = Self::slash_count(&v); - >::insert(v.clone(), slash_count + 1); - let grace = Self::offline_slash_grace(); - - let event = if slash_count >= grace { - let instances = slash_count - grace; - let slash = Self::early_era_slash() << instances; - let next_slash = slash << 1u32; - let _ = Self::slash_validator(&v, slash); - if instances >= Self::slash_preference_of(&v).unstake_threshold - || Self::slashable_balance(&v) < next_slash - { - if let Some(pos) = Self::intentions().into_iter().position(|x| &x == &v) { - Self::apply_unstake(&v, pos) - .expect("pos derived correctly from Self::intentions(); \ - apply_unstake can only fail if pos wrong; \ - Self::intentions() doesn't change; qed"); - } - let _ = Self::force_new_era(false); - } - RawEvent::OfflineSlash(v, slash) - } else { - RawEvent::OfflineWarning(v, slash_count) - }; - Self::deposit_event(event); - } - - Ok(()) - } - // PRIV DISPATCH /// Deposit one of this module's events. @@ -561,3 +514,34 @@ impl balances::OnFreeBalanceZero for Module { >::remove(who); } } + +impl consensus::OnOfflineValidator for Module { + fn on_offline_validator(validator_index: usize) { + let v = >::validators()[validator_index].clone(); + let slash_count = Self::slash_count(&v); + >::insert(v.clone(), slash_count + 1); + let grace = Self::offline_slash_grace(); + + let event = if slash_count >= grace { + let instances = slash_count - grace; + let slash = Self::early_era_slash() << instances; + let next_slash = slash << 1u32; + let _ = Self::slash_validator(&v, slash); + if instances >= Self::slash_preference_of(&v).unstake_threshold + || Self::slashable_balance(&v) < next_slash + { + if let Some(pos) = Self::intentions().into_iter().position(|x| &x == &v) { + Self::apply_unstake(&v, pos) + .expect("pos derived correctly from Self::intentions(); \ + apply_unstake can only fail if pos wrong; \ + Self::intentions() doesn't change; qed"); + } + let _ = Self::force_new_era(false); + } + RawEvent::OfflineSlash(v, slash) + } else { + RawEvent::OfflineWarning(v, slash_count) + }; + Self::deposit_event(event); + } +} diff --git a/substrate/runtime/staking/src/mock.rs b/substrate/runtime/staking/src/mock.rs index 05bea85659b2b..fa6124e5c37b4 100644 --- a/substrate/runtime/staking/src/mock.rs +++ b/substrate/runtime/staking/src/mock.rs @@ -32,7 +32,9 @@ impl HasPublicAux for Test { type PublicAux = u64; } impl consensus::Trait for Test { + const NOTE_OFFLINE_POSITION: u32 = 1; type SessionKey = u64; + type OnOfflineValidator = (); } impl system::Trait for Test { type PublicAux = ::PublicAux; @@ -62,7 +64,6 @@ impl timestamp::Trait for Test { type Moment = u64; } impl Trait for Test { - const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1; type Event = (); } diff --git a/substrate/runtime/staking/src/tests.rs b/substrate/runtime/staking/src/tests.rs index 366d3b5d9481a..47fff7b561f10 100644 --- a/substrate/runtime/staking/src/tests.rs +++ b/substrate/runtime/staking/src/tests.rs @@ -19,17 +19,17 @@ #![cfg(test)] use super::*; +use consensus::OnOfflineValidator; use runtime_io::with_externalities; use mock::{Balances, Session, Staking, System, Timestamp, Test, new_test_ext}; #[test] -fn note_null_missed_proposal_should_work() { +fn note_null_offline_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { assert_eq!(Staking::offline_slash_grace(), 0); assert_eq!(Staking::slash_count(&10), 0); assert_eq!(Balances::free_balance(&10), 1); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![])); assert_eq!(Staking::slash_count(&10), 0); assert_eq!(Balances::free_balance(&10), 1); assert!(Staking::forcing_new_era().is_none()); @@ -37,14 +37,14 @@ fn note_null_missed_proposal_should_work() { } #[test] -fn note_missed_proposal_should_work() { +fn note_offline_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { Balances::set_free_balance(&10, 70); assert_eq!(Staking::offline_slash_grace(), 0); assert_eq!(Staking::slash_count(&10), 0); assert_eq!(Balances::free_balance(&10), 70); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); + Staking::on_offline_validator(0); assert_eq!(Staking::slash_count(&10), 1); assert_eq!(Balances::free_balance(&10), 50); assert!(Staking::forcing_new_era().is_none()); @@ -52,18 +52,18 @@ fn note_missed_proposal_should_work() { } #[test] -fn note_missed_proposal_exponent_should_work() { +fn note_offline_exponent_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { Balances::set_free_balance(&10, 150); assert_eq!(Staking::offline_slash_grace(), 0); assert_eq!(Staking::slash_count(&10), 0); assert_eq!(Balances::free_balance(&10), 150); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); + Staking::on_offline_validator(0); assert_eq!(Staking::slash_count(&10), 1); assert_eq!(Balances::free_balance(&10), 130); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); + Staking::on_offline_validator(0); assert_eq!(Staking::slash_count(&10), 2); assert_eq!(Balances::free_balance(&10), 90); assert!(Staking::forcing_new_era().is_none()); @@ -71,7 +71,7 @@ fn note_missed_proposal_exponent_should_work() { } #[test] -fn note_missed_proposal_grace_should_work() { +fn note_offline_grace_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { Balances::set_free_balance(&10, 70); Balances::set_free_balance(&20, 70); @@ -82,14 +82,15 @@ fn note_missed_proposal_grace_should_work() { assert_eq!(Balances::free_balance(&10), 70); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); + Staking::on_offline_validator(0); assert_eq!(Staking::slash_count(&10), 1); assert_eq!(Balances::free_balance(&10), 70); assert_eq!(Staking::slash_count(&20), 0); assert_eq!(Balances::free_balance(&20), 70); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); + Staking::on_offline_validator(0); + Staking::on_offline_validator(1); assert_eq!(Staking::slash_count(&10), 2); assert_eq!(Balances::free_balance(&10), 50); assert_eq!(Staking::slash_count(&20), 1); @@ -99,7 +100,7 @@ fn note_missed_proposal_grace_should_work() { } #[test] -fn note_missed_proposal_force_unstake_session_change_should_work() { +fn note_offline_force_unstake_session_change_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { Balances::set_free_balance(&10, 70); Balances::set_free_balance(&20, 70); @@ -111,13 +112,13 @@ fn note_missed_proposal_force_unstake_session_change_should_work() { assert_eq!(Session::validators(), vec![10, 20]); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); + Staking::on_offline_validator(0); assert_eq!(Balances::free_balance(&10), 50); assert_eq!(Staking::slash_count(&10), 1); assert_eq!(Staking::intentions(), vec![10, 20, 1]); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0])); + Staking::on_offline_validator(0); assert_eq!(Staking::intentions(), vec![1, 20]); assert_eq!(Balances::free_balance(&10), 10); assert!(Staking::forcing_new_era().is_some()); @@ -125,7 +126,7 @@ fn note_missed_proposal_force_unstake_session_change_should_work() { } #[test] -fn note_missed_proposal_auto_unstake_session_change_should_work() { +fn note_offline_auto_unstake_session_change_should_work() { with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { Balances::set_free_balance(&10, 7000); Balances::set_free_balance(&20, 7000); @@ -134,27 +135,29 @@ fn note_missed_proposal_auto_unstake_session_change_should_work() { assert_eq!(Staking::intentions(), vec![10, 20]); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); + Staking::on_offline_validator(0); + Staking::on_offline_validator(1); assert_eq!(Balances::free_balance(&10), 6980); assert_eq!(Balances::free_balance(&20), 6980); assert_eq!(Staking::intentions(), vec![10, 20]); assert!(Staking::forcing_new_era().is_none()); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); + Staking::on_offline_validator(0); + Staking::on_offline_validator(1); assert_eq!(Balances::free_balance(&10), 6940); assert_eq!(Balances::free_balance(&20), 6940); assert_eq!(Staking::intentions(), vec![20]); assert!(Staking::forcing_new_era().is_some()); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![1])); + Staking::on_offline_validator(1); assert_eq!(Balances::free_balance(&10), 6940); assert_eq!(Balances::free_balance(&20), 6860); assert_eq!(Staking::intentions(), vec![20]); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![1])); + Staking::on_offline_validator(1); assert_eq!(Balances::free_balance(&10), 6940); assert_eq!(Balances::free_balance(&20), 6700); assert_eq!(Staking::intentions(), vec![0u64; 0]); @@ -219,7 +222,8 @@ fn slashing_should_work() { System::set_block_number(7); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); + Staking::on_offline_validator(0); + Staking::on_offline_validator(1); assert_eq!(Balances::total_balance(&10), 1); }); } @@ -367,7 +371,8 @@ fn nominating_slashes_should_work() { System::set_block_number(5); ::system::ExtrinsicIndex::::put(1); - assert_ok!(Staking::note_missed_proposal(&Default::default(), vec![0, 1])); + Staking::on_offline_validator(0); + Staking::on_offline_validator(1); assert_eq!(Balances::total_balance(&1), 0); assert_eq!(Balances::total_balance(&2), 20); assert_eq!(Balances::total_balance(&3), 10); diff --git a/substrate/runtime/timestamp/src/lib.rs b/substrate/runtime/timestamp/src/lib.rs index e632e8103dc5e..a2ffca9a090bf 100644 --- a/substrate/runtime/timestamp/src/lib.rs +++ b/substrate/runtime/timestamp/src/lib.rs @@ -163,7 +163,9 @@ mod tests { type Event = (); } impl consensus::Trait for Test { + const NOTE_OFFLINE_POSITION: u32 = 1; type SessionKey = u64; + type OnOfflineValidator = (); } impl Trait for Test { const TIMESTAMP_SET_POSITION: u32 = 0; From 1094091245decf1b358db85763910a03368fdac1 Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 30 Aug 2018 12:58:07 +0200 Subject: [PATCH 16/19] Version needs Decode. --- substrate/runtime/version/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/runtime/version/src/lib.rs b/substrate/runtime/version/src/lib.rs index 1dbf4aa2da2f5..f69454264cef3 100644 --- a/substrate/runtime/version/src/lib.rs +++ b/substrate/runtime/version/src/lib.rs @@ -64,8 +64,8 @@ macro_rules! ver_str { /// This triplet have different semantics and mis-interpretation could cause problems. /// In particular: bug fixes should result in an increment of `spec_version` and possibly `authoring_version`, /// absolutely not `impl_version` since they change the semantics of the runtime. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize, Decode))] +#[derive(Clone, PartialEq, Eq, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] pub struct RuntimeVersion { /// Identifies the different Substrate runtimes. There'll be at least polkadot and demo. /// A different on-chain spec_name to that of the native runtime would normally result From e9410f5765e01d733e7b80e8df238474bae1a917 Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 30 Aug 2018 13:11:32 +0200 Subject: [PATCH 17/19] Move Decode back --- substrate/runtime/version/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/runtime/version/src/lib.rs b/substrate/runtime/version/src/lib.rs index f69454264cef3..1dbf4aa2da2f5 100644 --- a/substrate/runtime/version/src/lib.rs +++ b/substrate/runtime/version/src/lib.rs @@ -64,8 +64,8 @@ macro_rules! ver_str { /// This triplet have different semantics and mis-interpretation could cause problems. /// In particular: bug fixes should result in an increment of `spec_version` and possibly `authoring_version`, /// absolutely not `impl_version` since they change the semantics of the runtime. -#[derive(Clone, PartialEq, Eq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize, Decode))] pub struct RuntimeVersion { /// Identifies the different Substrate runtimes. There'll be at least polkadot and demo. /// A different on-chain spec_name to that of the native runtime would normally result From 750848e9052e0decd5ed331f11ef4c5a2a656d12 Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 30 Aug 2018 16:39:25 +0200 Subject: [PATCH 18/19] Fix nits --- Cargo.lock | 4 --- substrate/runtime-support/src/dispatch.rs | 8 ++--- substrate/runtime/balances/Cargo.toml | 10 ------ substrate/runtime/balances/src/address.rs | 8 ++--- .../runtime/balances/src/genesis_config.rs | 10 +++--- substrate/runtime/balances/src/lib.rs | 33 ++++++++----------- substrate/runtime/balances/src/tests.rs | 8 ++--- substrate/runtime/consensus/src/lib.rs | 8 ++--- substrate/runtime/contract/src/double_map.rs | 8 ++--- substrate/runtime/contract/src/exec.rs | 2 +- substrate/runtime/council/Cargo.toml | 1 + substrate/runtime/council/src/lib.rs | 8 ++--- substrate/runtime/council/src/voting.rs | 8 ++--- substrate/runtime/democracy/src/lib.rs | 8 ++--- .../runtime/democracy/src/vote_threshold.rs | 8 ++--- substrate/runtime/executive/src/lib.rs | 8 ++--- substrate/runtime/primitives/src/generic.rs | 8 ++--- substrate/runtime/primitives/src/lib.rs | 8 ++--- substrate/runtime/primitives/src/testing.rs | 8 ++--- substrate/runtime/primitives/src/traits.rs | 8 ++--- substrate/runtime/session/src/lib.rs | 8 ++--- .../runtime/staking/src/genesis_config.rs | 8 ++--- substrate/runtime/staking/src/lib.rs | 8 ++--- substrate/runtime/staking/src/tests.rs | 10 +++--- substrate/runtime/system/src/lib.rs | 12 ++++--- substrate/runtime/timestamp/src/lib.rs | 8 ++--- substrate/runtime/version/src/lib.rs | 8 ++--- 27 files changed, 108 insertions(+), 126 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c70ee12588e75..dfc645c05db09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2669,15 +2669,11 @@ dependencies = [ "substrate-codec-derive 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", - "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", - "substrate-runtime-sandbox 0.1.0", - "substrate-runtime-session 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", - "substrate-runtime-timestamp 0.1.0", "wabt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/substrate/runtime-support/src/dispatch.rs b/substrate/runtime-support/src/dispatch.rs index 9b26493839bff..62e34ecb09ca7 100644 --- a/substrate/runtime-support/src/dispatch.rs +++ b/substrate/runtime-support/src/dispatch.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Dispatch system. Just dispatches calls. diff --git a/substrate/runtime/balances/Cargo.toml b/substrate/runtime/balances/Cargo.toml index 1cde7ebf9833f..5a86a99c11f30 100644 --- a/substrate/runtime/balances/Cargo.toml +++ b/substrate/runtime/balances/Cargo.toml @@ -14,16 +14,9 @@ substrate-codec-derive = { path = "../../codec/derive", default_features = false substrate-primitives = { path = "../../primitives", default_features = false } substrate-runtime-std = { path = "../../runtime-std", default_features = false } substrate-runtime-io = { path = "../../runtime-io", default_features = false } -substrate-runtime-sandbox = { path = "../../runtime-sandbox", default_features = false } substrate-runtime-support = { path = "../../runtime-support", default_features = false } substrate-runtime-primitives = { path = "../primitives", default_features = false } -substrate-runtime-consensus = { path = "../consensus", default_features = false } substrate-runtime-system = { path = "../system", default_features = false } -substrate-runtime-session = { path = "../session", default_features = false } -substrate-runtime-timestamp = { path = "../timestamp", default_features = false } - -[dev-dependencies] -wabt = "0.4" [features] default = ["std"] @@ -37,10 +30,7 @@ std = [ "substrate-primitives/std", "substrate-runtime-std/std", "substrate-runtime-io/std", - "substrate-runtime-sandbox/std", "substrate-runtime-support/std", "substrate-runtime-primitives/std", - "substrate-runtime-session/std", "substrate-runtime-system/std", - "substrate-runtime-timestamp/std" ] diff --git a/substrate/runtime/balances/src/address.rs b/substrate/runtime/balances/src/address.rs index 249e0b20db225..01fb25439507b 100644 --- a/substrate/runtime/balances/src/address.rs +++ b/substrate/runtime/balances/src/address.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Address type that is union of index and id for an account. diff --git a/substrate/runtime/balances/src/genesis_config.rs b/substrate/runtime/balances/src/genesis_config.rs index 010fee948240e..677db1aaec20e 100644 --- a/substrate/runtime/balances/src/genesis_config.rs +++ b/substrate/runtime/balances/src/genesis_config.rs @@ -1,20 +1,20 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . -//! Build a staking genesis block. +//! Build a balances genesis block. #![cfg(feature = "std")] diff --git a/substrate/runtime/balances/src/lib.rs b/substrate/runtime/balances/src/lib.rs index 812b35a7d2239..4efdf3bfd90d1 100644 --- a/substrate/runtime/balances/src/lib.rs +++ b/substrate/runtime/balances/src/lib.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Balances: Handles balances. @@ -25,9 +25,6 @@ extern crate serde; #[macro_use] extern crate serde_derive; -#[cfg(test)] -extern crate wabt; - #[macro_use] extern crate substrate_runtime_support as runtime_support; @@ -41,11 +38,7 @@ extern crate substrate_codec as codec; extern crate substrate_primitives; extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_primitives as primitives; -extern crate substrate_runtime_consensus as consensus; -extern crate substrate_runtime_sandbox as sandbox; -extern crate substrate_runtime_session as session; extern crate substrate_runtime_system as system; -extern crate substrate_runtime_timestamp as timestamp; use rstd::prelude::*; use rstd::{cmp, result}; @@ -78,7 +71,7 @@ pub type Event = RawEvent< ::AccountIndex >; -/// The account was the given id was killed. +/// The account with the given id was killed. pub trait OnFreeBalanceZero { /// The account was the given id was killed. fn on_free_balance_zero(who: &AccountId); @@ -98,9 +91,9 @@ impl< } } -/// The account was the given id was killed. +/// Determinator for whether a given account is able to transfer balance. pub trait IsAccountLiquid { - /// The account was the given id was killed. + /// `true` iff the account is able to transfer funds normally. fn is_account_liquid(who: &AccountId) -> bool; } @@ -178,7 +171,7 @@ decl_storage! { // This is the only balance that matters in terms of most operations on tokens. It is // alone used to determine the balance when in the contract execution environment. When this // balance falls below the value of `ExistentialDeposit`, then the "current account" is - // deleted: specifically, `Bondage` and `FreeBalance`. Furthermore, `OnFreeBalanceZero` callback + // deleted: specifically `FreeBalance`. Furthermore, `OnFreeBalanceZero` callback // is invoked, giving a chance to external modules to cleanup data associated with // the deleted account. // @@ -190,8 +183,8 @@ decl_storage! { // slashed, but gets slashed last of all. // // This balance is a "reserve" balance that other subsystems use in order to set aside tokens - // that are still "owned" by the account holder, but which are unspendable. This is different - // and wholly unrelated to the `Bondage` system used for staking. + // that are still "owned" by the account holder, but which are unspendable. (This is different + // and wholly unrelated to the `Bondage` system used in the staking module.) // // When this balance falls below the value of `ExistentialDeposit`, then this "reserve account" // is deleted: specifically, `ReservedBalance`. @@ -201,7 +194,7 @@ decl_storage! { pub ReservedBalance get(reserved_balance): default map [ T::AccountId => T::Balance ]; - // Separate into Payment module. + // Payment stuff. // The fee to be paid for making a transaction; the base. pub TransactionBaseFee get(transaction_base_fee): required T::Balance; @@ -278,7 +271,7 @@ impl Module { // PUBLIC DISPATCH - /// Transfer some unlocked staking balance to another staker. + /// Transfer some liquid free balance to another staker. pub fn transfer(aux: &T::PublicAux, dest: Address, value: T::Balance) -> Result { let dest = Self::lookup(dest)?; @@ -296,7 +289,7 @@ impl Module { return Err("value too low to create account"); } if !T::IsAccountLiquid::is_account_liquid(transactor) { - return Err("bondage too high to send value"); + return Err("cannot transfer illiquid funds"); } let to_balance = Self::free_balance(&dest); diff --git a/substrate/runtime/balances/src/tests.rs b/substrate/runtime/balances/src/tests.rs index 6305411d0737d..7f3a740a931a9 100644 --- a/substrate/runtime/balances/src/tests.rs +++ b/substrate/runtime/balances/src/tests.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Tests for the module. diff --git a/substrate/runtime/consensus/src/lib.rs b/substrate/runtime/consensus/src/lib.rs index cc8f2433ab0d2..df6d034c8f555 100644 --- a/substrate/runtime/consensus/src/lib.rs +++ b/substrate/runtime/consensus/src/lib.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Conensus module for runtime; manages the authority set ready for the native code. diff --git a/substrate/runtime/contract/src/double_map.rs b/substrate/runtime/contract/src/double_map.rs index 505fe9e6a29a0..6867d2a5c697c 100644 --- a/substrate/runtime/contract/src/double_map.rs +++ b/substrate/runtime/contract/src/double_map.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! An implementation of double map backed by storage. //! diff --git a/substrate/runtime/contract/src/exec.rs b/substrate/runtime/contract/src/exec.rs index 5cd461647926f..2449f4e90d697 100644 --- a/substrate/runtime/contract/src/exec.rs +++ b/substrate/runtime/contract/src/exec.rs @@ -203,7 +203,7 @@ fn transfer( return Err("value too low to create account"); } if !::IsAccountLiquid::is_account_liquid(transactor) { - return Err("bondage too high to send value"); + return Err("cannot transfer illiquid funds"); } let to_balance = overlay.get_balance(dest); diff --git a/substrate/runtime/council/Cargo.toml b/substrate/runtime/council/Cargo.toml index 4e9977ec576b8..1f85d467d4863 100644 --- a/substrate/runtime/council/Cargo.toml +++ b/substrate/runtime/council/Cargo.toml @@ -34,6 +34,7 @@ std = [ "substrate-runtime-io/std", "substrate-runtime-support/std", "substrate-runtime-primitives/std", + "substrate-runtime-balances/std", "substrate-runtime-democracy/std", "substrate-runtime-system/std", ] diff --git a/substrate/runtime/council/src/lib.rs b/substrate/runtime/council/src/lib.rs index 898c49862f5c0..e7e2ed35602be 100644 --- a/substrate/runtime/council/src/lib.rs +++ b/substrate/runtime/council/src/lib.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Council system: Handles the voting in and maintenance of council members. diff --git a/substrate/runtime/council/src/voting.rs b/substrate/runtime/council/src/voting.rs index 3d0c0d7268404..5569adc9e4faf 100644 --- a/substrate/runtime/council/src/voting.rs +++ b/substrate/runtime/council/src/voting.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Council voting system. diff --git a/substrate/runtime/democracy/src/lib.rs b/substrate/runtime/democracy/src/lib.rs index f626d099988a3..15afcf6da9d8b 100644 --- a/substrate/runtime/democracy/src/lib.rs +++ b/substrate/runtime/democracy/src/lib.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Democratic system: Handles administration of general stakeholder voting. diff --git a/substrate/runtime/democracy/src/vote_threshold.rs b/substrate/runtime/democracy/src/vote_threshold.rs index 0027f7c0060e0..ce46149222055 100644 --- a/substrate/runtime/democracy/src/vote_threshold.rs +++ b/substrate/runtime/democracy/src/vote_threshold.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Voting thresholds. diff --git a/substrate/runtime/executive/src/lib.rs b/substrate/runtime/executive/src/lib.rs index 4220e50abbf52..7ee3dc275b2f3 100644 --- a/substrate/runtime/executive/src/lib.rs +++ b/substrate/runtime/executive/src/lib.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Executive: Handles all of the top-level stuff; essentially just executing blocks/extrinsics. diff --git a/substrate/runtime/primitives/src/generic.rs b/substrate/runtime/primitives/src/generic.rs index f1a9448c8fafc..efcc52fbecb49 100644 --- a/substrate/runtime/primitives/src/generic.rs +++ b/substrate/runtime/primitives/src/generic.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Generic implementations of Extrinsic/Header/Block. diff --git a/substrate/runtime/primitives/src/lib.rs b/substrate/runtime/primitives/src/lib.rs index a1ff760f7608f..87553942b921e 100644 --- a/substrate/runtime/primitives/src/lib.rs +++ b/substrate/runtime/primitives/src/lib.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! System manager: Handles all of the top-level stuff; executing block/transaction, setting code //! and depositing logs. diff --git a/substrate/runtime/primitives/src/testing.rs b/substrate/runtime/primitives/src/testing.rs index eab978d3b8951..b1dcef2eadbef 100644 --- a/substrate/runtime/primitives/src/testing.rs +++ b/substrate/runtime/primitives/src/testing.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Testing utilities. diff --git a/substrate/runtime/primitives/src/traits.rs b/substrate/runtime/primitives/src/traits.rs index 4026fa7cf7670..b64aa678f2867 100644 --- a/substrate/runtime/primitives/src/traits.rs +++ b/substrate/runtime/primitives/src/traits.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Primitives for the runtime modules. diff --git a/substrate/runtime/session/src/lib.rs b/substrate/runtime/session/src/lib.rs index 3308ec6e551fe..75dad0adae76d 100644 --- a/substrate/runtime/session/src/lib.rs +++ b/substrate/runtime/session/src/lib.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Session manager: is told the validators and allows them to manage their session keys for the //! consensus module. diff --git a/substrate/runtime/staking/src/genesis_config.rs b/substrate/runtime/staking/src/genesis_config.rs index ce9adda2223df..7577e125c259d 100644 --- a/substrate/runtime/staking/src/genesis_config.rs +++ b/substrate/runtime/staking/src/genesis_config.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Build a staking genesis block. diff --git a/substrate/runtime/staking/src/lib.rs b/substrate/runtime/staking/src/lib.rs index a5f813a7350ea..0124ec15ebc2e 100644 --- a/substrate/runtime/staking/src/lib.rs +++ b/substrate/runtime/staking/src/lib.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Staking manager: Periodically determines the best set of validators. diff --git a/substrate/runtime/staking/src/tests.rs b/substrate/runtime/staking/src/tests.rs index 47fff7b561f10..1f2bef2e38dde 100644 --- a/substrate/runtime/staking/src/tests.rs +++ b/substrate/runtime/staking/src/tests.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Tests for the module. @@ -466,7 +466,7 @@ fn staking_balance_transfer_when_bonded_should_not_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { Balances::set_free_balance(&1, 111); assert_ok!(Staking::stake(&1)); - assert_noop!(Balances::transfer(&1, 2.into(), 69), "bondage too high to send value"); + assert_noop!(Balances::transfer(&1, 2.into(), 69), "cannot transfer illiquid funds"); }); } diff --git a/substrate/runtime/system/src/lib.rs b/substrate/runtime/system/src/lib.rs index d23aa05c3d2c6..420192468f2f0 100644 --- a/substrate/runtime/system/src/lib.rs +++ b/substrate/runtime/system/src/lib.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! System manager: Handles lowest level stuff like depositing logs, basic set up and take down of //! temporary storage entries, access to old block hashes. @@ -69,7 +69,9 @@ pub fn extrinsics_data_root(xts: Vec>) -> H::Output { } pub trait Trait: Eq + Clone { - type PublicAux: RefInto + MaybeEmpty; // MaybeEmpty is for Timestamp's usage. + // We require that PublicAux impl MaybeEmpty, since we require that inherents - or unsigned + // user-level extrinsics - can exist. + type PublicAux: RefInto + MaybeEmpty; type Index: Parameter + Member + Default + MaybeDisplay + SimpleArithmetic + Copy; type BlockNumber: Parameter + Member + MaybeDisplay + SimpleArithmetic + Default + Bounded + Copy + rstd::hash::Hash; type Hash: Parameter + Member + MaybeDisplay + SimpleBitOps + Default + Copy + CheckEqual + rstd::hash::Hash + AsRef<[u8]>; diff --git a/substrate/runtime/timestamp/src/lib.rs b/substrate/runtime/timestamp/src/lib.rs index a2ffca9a090bf..80781ab075b64 100644 --- a/substrate/runtime/timestamp/src/lib.rs +++ b/substrate/runtime/timestamp/src/lib.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Timestamp manager: just handles the current timestamp. diff --git a/substrate/runtime/version/src/lib.rs b/substrate/runtime/version/src/lib.rs index 1dbf4aa2da2f5..ab66ecc88d25d 100644 --- a/substrate/runtime/version/src/lib.rs +++ b/substrate/runtime/version/src/lib.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Substrate Demo. +// This file is part of Substrate. -// Substrate Demo is free software: you can redistribute it and/or modify +// 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 Demo is distributed in the hope that it will be useful, +// 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 Demo. If not, see . +// along with Substrate. If not, see . //! Version module for runtime; Provide a function that returns runtime version. From 0fe3e877562510f7a869c6be9e7fe6aedce0f51e Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 30 Aug 2018 18:25:07 +0200 Subject: [PATCH 19/19] Refactor to allow custom message --- Cargo.lock | 1 - demo/runtime/src/lib.rs | 2 +- substrate/runtime/balances/src/lib.rs | 23 ++++++++++------------- substrate/runtime/balances/src/mock.rs | 2 +- substrate/runtime/contract/src/exec.rs | 6 ++---- substrate/runtime/contract/src/tests.rs | 2 +- substrate/runtime/council/src/lib.rs | 2 +- substrate/runtime/democracy/src/lib.rs | 2 +- substrate/runtime/executive/src/lib.rs | 2 +- substrate/runtime/staking/src/lib.rs | 10 +++++++--- substrate/runtime/staking/src/mock.rs | 2 +- substrate/runtime/staking/src/tests.rs | 2 +- 12 files changed, 27 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dfc645c05db09..3e7386758f495 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2674,7 +2674,6 @@ dependencies = [ "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", - "wabt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/demo/runtime/src/lib.rs b/demo/runtime/src/lib.rs index 9fb45eb88ed1f..f0c39af85d198 100644 --- a/demo/runtime/src/lib.rs +++ b/demo/runtime/src/lib.rs @@ -107,7 +107,7 @@ impl balances::Trait for Concrete { type Balance = Balance; type AccountIndex = AccountIndex; type OnFreeBalanceZero = Staking; - type IsAccountLiquid = Staking; + type EnsureAccountLiquid = Staking; type Event = Event; } diff --git a/substrate/runtime/balances/src/lib.rs b/substrate/runtime/balances/src/lib.rs index 4efdf3bfd90d1..00c4fd04c320c 100644 --- a/substrate/runtime/balances/src/lib.rs +++ b/substrate/runtime/balances/src/lib.rs @@ -92,13 +92,14 @@ impl< } /// Determinator for whether a given account is able to transfer balance. -pub trait IsAccountLiquid { - /// `true` iff the account is able to transfer funds normally. - fn is_account_liquid(who: &AccountId) -> bool; +pub trait EnsureAccountLiquid { + /// Returns `Ok` iff the account is able to transfer funds normally. `Err(...)` + /// with the reason why not otherwise. + fn ensure_account_liquid(who: &AccountId) -> Result; } -impl IsAccountLiquid for () { - fn is_account_liquid(_who: &AccountId) -> bool { true } +impl EnsureAccountLiquid for () { + fn ensure_account_liquid(_who: &AccountId) -> Result { Ok(()) } } pub trait Trait: system::Trait { @@ -114,7 +115,7 @@ pub trait Trait: system::Trait { type OnFreeBalanceZero: OnFreeBalanceZero; /// A function that returns true iff a given account can transfer its funds to another account. - type IsAccountLiquid: IsAccountLiquid; + type EnsureAccountLiquid: EnsureAccountLiquid; /// The overarching event type. type Event: From> + Into<::Event>; @@ -238,7 +239,7 @@ impl Module { /// Same result as `reserve(who, value)` (but without the side-effects) assuming there /// are no balance changes in the meantime. pub fn can_reserve(who: &T::AccountId, value: T::Balance) -> bool { - if T::IsAccountLiquid::is_account_liquid(who) { + if T::EnsureAccountLiquid::ensure_account_liquid(who).is_ok() { Self::free_balance(who) >= value } else { false @@ -288,9 +289,7 @@ impl Module { if would_create && value < Self::existential_deposit() { return Err("value too low to create account"); } - if !T::IsAccountLiquid::is_account_liquid(transactor) { - return Err("cannot transfer illiquid funds"); - } + T::EnsureAccountLiquid::ensure_account_liquid(transactor)?; let to_balance = Self::free_balance(&dest); // NOTE: total stake being stored in the same type means that this could never overflow @@ -439,9 +438,7 @@ impl Module { if b < value { return Err("not enough free funds") } - if !T::IsAccountLiquid::is_account_liquid(who) { - return Err("free funds are still bonded") - } + T::EnsureAccountLiquid::ensure_account_liquid(who)?; Self::set_reserved_balance(who, Self::reserved_balance(who) + value); Self::set_free_balance(who, b - value); Ok(()) diff --git a/substrate/runtime/balances/src/mock.rs b/substrate/runtime/balances/src/mock.rs index 747dbd16eb1c7..b7066a704fa16 100644 --- a/substrate/runtime/balances/src/mock.rs +++ b/substrate/runtime/balances/src/mock.rs @@ -46,7 +46,7 @@ impl Trait for Test { type Balance = u64; type AccountIndex = u64; type OnFreeBalanceZero = (); - type IsAccountLiquid = (); + type EnsureAccountLiquid = (); type Event = (); } diff --git a/substrate/runtime/contract/src/exec.rs b/substrate/runtime/contract/src/exec.rs index 2449f4e90d697..4779e959c17f4 100644 --- a/substrate/runtime/contract/src/exec.rs +++ b/substrate/runtime/contract/src/exec.rs @@ -22,7 +22,7 @@ use vm; use rstd::prelude::*; use runtime_primitives::traits::{Zero, CheckedAdd, CheckedSub}; use runtime_support::{StorageMap, StorageValue}; -use balances::{self, IsAccountLiquid}; +use balances::{self, EnsureAccountLiquid}; pub struct CreateReceipt { pub address: T::AccountId, @@ -202,9 +202,7 @@ fn transfer( if would_create && value < >::existential_deposit() { return Err("value too low to create account"); } - if !::IsAccountLiquid::is_account_liquid(transactor) { - return Err("cannot transfer illiquid funds"); - } + ::EnsureAccountLiquid::ensure_account_liquid(transactor)?; let to_balance = overlay.get_balance(dest); let new_to_balance = match to_balance.checked_add(&value) { diff --git a/substrate/runtime/contract/src/tests.rs b/substrate/runtime/contract/src/tests.rs index 21e89202b22fd..d12b137d41e82 100644 --- a/substrate/runtime/contract/src/tests.rs +++ b/substrate/runtime/contract/src/tests.rs @@ -47,7 +47,7 @@ impl balances::Trait for Test { type Balance = u64; type AccountIndex = u64; type OnFreeBalanceZero = Contract; - type IsAccountLiquid = (); + type EnsureAccountLiquid = (); type Event = (); } impl Trait for Test { diff --git a/substrate/runtime/council/src/lib.rs b/substrate/runtime/council/src/lib.rs index e7e2ed35602be..f13f637b3a259 100644 --- a/substrate/runtime/council/src/lib.rs +++ b/substrate/runtime/council/src/lib.rs @@ -651,7 +651,7 @@ mod tests { type Balance = u64; type AccountIndex = u64; type OnFreeBalanceZero = (); - type IsAccountLiquid = (); + type EnsureAccountLiquid = (); type Event = (); } impl democracy::Trait for Test { diff --git a/substrate/runtime/democracy/src/lib.rs b/substrate/runtime/democracy/src/lib.rs index 15afcf6da9d8b..7f3846ad9755f 100644 --- a/substrate/runtime/democracy/src/lib.rs +++ b/substrate/runtime/democracy/src/lib.rs @@ -383,7 +383,7 @@ mod tests { type Balance = u64; type AccountIndex = u64; type OnFreeBalanceZero = (); - type IsAccountLiquid = (); + type EnsureAccountLiquid = (); type Event = (); } impl Trait for Test { diff --git a/substrate/runtime/executive/src/lib.rs b/substrate/runtime/executive/src/lib.rs index 7ee3dc275b2f3..1d832b73e3fbd 100644 --- a/substrate/runtime/executive/src/lib.rs +++ b/substrate/runtime/executive/src/lib.rs @@ -264,7 +264,7 @@ mod tests { type Balance = u64; type AccountIndex = u64; type OnFreeBalanceZero = staking::Module; - type IsAccountLiquid = staking::Module; + type EnsureAccountLiquid = staking::Module; type Event = MetaEvent; } impl system::Trait for Test { diff --git a/substrate/runtime/staking/src/lib.rs b/substrate/runtime/staking/src/lib.rs index 0124ec15ebc2e..3c3c2cd9df138 100644 --- a/substrate/runtime/staking/src/lib.rs +++ b/substrate/runtime/staking/src/lib.rs @@ -503,9 +503,13 @@ impl OnSessionChange for Module { } } -impl balances::IsAccountLiquid for Module { - fn is_account_liquid(who: &T::AccountId) -> bool { - Self::bondage(who) <= >::block_number() +impl balances::EnsureAccountLiquid for Module { + fn ensure_account_liquid(who: &T::AccountId) -> Result { + if Self::bondage(who) <= >::block_number() { + Ok(()) + } else { + Err("cannot transfer illiquid funds") + } } } diff --git a/substrate/runtime/staking/src/mock.rs b/substrate/runtime/staking/src/mock.rs index fa6124e5c37b4..25447c39cbe23 100644 --- a/substrate/runtime/staking/src/mock.rs +++ b/substrate/runtime/staking/src/mock.rs @@ -51,7 +51,7 @@ impl balances::Trait for Test { type Balance = u64; type AccountIndex = u64; type OnFreeBalanceZero = Staking; - type IsAccountLiquid = Staking; + type EnsureAccountLiquid = Staking; type Event = (); } impl session::Trait for Test { diff --git a/substrate/runtime/staking/src/tests.rs b/substrate/runtime/staking/src/tests.rs index 1f2bef2e38dde..e60a7b129b833 100644 --- a/substrate/runtime/staking/src/tests.rs +++ b/substrate/runtime/staking/src/tests.rs @@ -477,6 +477,6 @@ fn deducting_balance_when_bonded_should_not_work() { >::insert(1, 2); System::set_block_number(1); assert_eq!(Staking::unlock_block(&1), LockStatus::LockedUntil(2)); - assert_noop!(Balances::reserve(&1, 69), "free funds are still bonded"); + assert_noop!(Balances::reserve(&1, 69), "cannot transfer illiquid funds"); }); }