Composite accounts (#4820)

* Basic account composition.

* Add try_mutate_exists

* De-duplicate

* Refactor away the UpdateBalanceOutcome

* Expunge final UpdateBalanceOutcome refs

* Refactor transfer

* Refactor reservable currency stuff.

* Test with the alternative setup.

* Fixes

* Test with both setups.

* Fixes

* Fix

* Fix macros

* Make indices opt-in

* Remove CreationFee, and make indices opt-in.

* Fix construct_runtime

* Fix last few bits

* Fix tests

* Update trait impls

* Don't hardcode the system event

* Make tests build and fix some stuff.

* Pointlessly bump runtime version

* Fix benchmark

* Another fix

* Whitespace

* Make indices module economically safe

* Migrations for indices.

* Fix

* Whilespace

* Trim defunct migrations

* Remove unused storage item

* More contains_key fixes

* Docs.

* Bump runtime

* Remove unneeded code

* Fix test

* Fix test

* Update frame/balances/src/lib.rs

Co-Authored-By: Shawn Tabrizi <shawntabrizi@gmail.com>

* Fix ED logic

* Repatriate reserved logic

* Typo

* Fix typo

* Update frame/system/src/lib.rs

Co-Authored-By: Shawn Tabrizi <shawntabrizi@gmail.com>

* Update frame/system/src/lib.rs

Co-Authored-By: Shawn Tabrizi <shawntabrizi@gmail.com>

* Last few fixes

* Another fix

* Build fix

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
Co-authored-by: Jaco Greeff <jacogr@gmail.com>
Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
Gavin Wood
2020-02-14 00:47:51 +00:00
committed by GitHub
parent d3fa8c91af
commit 5b7512e2e4
79 changed files with 2459 additions and 2100 deletions
+4 -9
View File
@@ -250,7 +250,6 @@
mod mock;
#[cfg(test)]
mod tests;
mod migration;
mod slashing;
pub mod inflation;
@@ -761,9 +760,6 @@ decl_storage! {
/// The earliest era for which we have a pending, unapplied slash.
EarliestUnappliedSlash: Option<EraIndex>;
/// The version of storage for upgrade.
StorageVersion: u32;
}
add_extra_genesis {
config(stakers):
@@ -795,8 +791,6 @@ decl_storage! {
}, _ => Ok(())
};
}
StorageVersion::put(migration::CURRENT_VERSION);
});
}
}
@@ -1298,9 +1292,10 @@ impl<T: Trait> Module<T> {
}
/// Ensures storage is upgraded to most recent necessary state.
fn ensure_storage_upgraded() {
migration::perform_migrations::<T>();
}
///
/// Right now it's a no-op as all networks that are supported by Substrate Frame Core are
/// running with the latest staking storage scheme.
fn ensure_storage_upgraded() {}
/// Actually make a payment to a staker. This uses the currency's reward function
/// to pay the right payee for the given staker account.
-140
View File
@@ -1,140 +0,0 @@
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Storage migrations for srml-staking.
/// Indicator of a version of a storage layout.
pub type VersionNumber = u32;
// the current expected version of the storage
pub const CURRENT_VERSION: VersionNumber = 2;
/// The inner logic of migrations.
#[cfg(any(test, feature = "migrate"))]
pub mod inner {
use crate::{Store, Module, Trait};
use frame_support::{StorageLinkedMap, StoragePrefixedMap, StorageValue};
use codec::{Encode, Decode};
use sp_std::vec::Vec;
use super::{CURRENT_VERSION, VersionNumber};
// the minimum supported version of the migration logic.
const MIN_SUPPORTED_VERSION: VersionNumber = 0;
// migrate storage from v0 to v1.
//
// this upgrades the `Nominators` linked_map value type from `Vec<T::AccountId>` to
// `Option<Nominations<T::AccountId>>`
pub fn to_v1<T: Trait>(version: &mut VersionNumber) {
if *version != 0 { return }
*version += 1;
let now = <Module<T>>::current_era();
let res = <Module<T> as Store>::Nominators::translate::<T::AccountId, Vec<T::AccountId>, _, _>(
|key| key,
|targets| crate::Nominations {
targets,
submitted_in: now,
suppressed: false,
},
);
if let Err(e) = res {
frame_support::print("Encountered error in migration of Staking::Nominators map.");
if e.is_none() {
frame_support::print("Staking::Nominators map reinitialized");
}
}
frame_support::print("Finished migrating Staking storage to v1.");
}
// migrate storage from v1 to v2: adds another field to the `SlashingSpans`
// struct.
pub fn to_v2<T: Trait>(version: &mut VersionNumber) {
use crate::{EraIndex, slashing::SpanIndex};
#[derive(Decode)]
struct V1SlashingSpans {
span_index: SpanIndex,
last_start: EraIndex,
prior: Vec<EraIndex>,
}
#[derive(Encode)]
struct V2SlashingSpans {
span_index: SpanIndex,
last_start: EraIndex,
last_nonzero_slash: EraIndex,
prior: Vec<EraIndex>,
}
if *version != 1 { return }
*version += 1;
let prefix = <Module<T> as Store>::SlashingSpans::final_prefix();
let mut current_key = prefix.to_vec();
loop {
let maybe_next_key = sp_io::storage::next_key(&current_key[..])
.filter(|v| v.starts_with(&prefix[..]));
match maybe_next_key {
Some(next_key) => {
let maybe_spans = sp_io::storage::get(&next_key[..])
.and_then(|v| V1SlashingSpans::decode(&mut &v[..]).ok());
if let Some(spans) = maybe_spans {
let new_val = V2SlashingSpans {
span_index: spans.span_index,
last_start: spans.last_start,
last_nonzero_slash: spans.last_start,
prior: spans.prior,
}.encode();
sp_io::storage::set(&next_key[..], &new_val[..]);
}
current_key = next_key;
}
None => break,
}
}
}
pub(super) fn perform_migrations<T: Trait>() {
<Module<T> as Store>::StorageVersion::mutate(|version| {
if *version < MIN_SUPPORTED_VERSION {
frame_support::print("Cannot migrate staking storage because version is less than\
minimum.");
frame_support::print(*version);
return
}
if *version == CURRENT_VERSION { return }
to_v1::<T>(version);
to_v2::<T>(version);
});
}
}
#[cfg(not(any(test, feature = "migrate")))]
mod inner {
pub(super) fn perform_migrations<T>() { }
}
/// Perform all necessary storage migrations to get storage into the expected stsate for current
/// logic. No-op if fully upgraded.
pub(crate) fn perform_migrations<T: crate::Trait>() {
inner::perform_migrations::<T>();
}
+4 -7
View File
@@ -138,19 +138,16 @@ impl frame_system::Trait for Test {
type MaximumBlockLength = MaximumBlockLength;
type Version = ();
type ModuleToIndex = ();
}
parameter_types! {
pub const CreationFee: Balance = 0;
type AccountData = pallet_balances::AccountData<u64>;
type OnNewAccount = ();
type OnReapAccount = (Balances, Staking, Session);
}
impl pallet_balances::Trait for Test {
type Balance = Balance;
type OnReapAccount = (System, Staking);
type OnNewAccount = ();
type Event = ();
type TransferPayment = ();
type DustRemoval = ();
type ExistentialDeposit = ExistentialDeposit;
type CreationFee = CreationFee;
type AccountStore = System;
}
parameter_types! {
pub const Period: BlockNumber = 1;
-58
View File
@@ -18,7 +18,6 @@
use super::*;
use mock::*;
use codec::Encode;
use sp_runtime::{assert_eq_error_rate, traits::{OnInitialize, BadOrigin}};
use sp_staking::offence::OffenceDetails;
use frame_support::{
@@ -2671,13 +2670,6 @@ fn remove_multi_deferred() {
})
}
#[test]
fn version_initialized() {
ExtBuilder::default().build().execute_with(|| {
assert_eq!(<Staking as Store>::StorageVersion::get(), crate::migration::CURRENT_VERSION);
});
}
#[test]
fn slash_kicks_validators_not_nominators() {
ExtBuilder::default().build().execute_with(|| {
@@ -2717,56 +2709,6 @@ fn slash_kicks_validators_not_nominators() {
});
}
#[test]
fn migration_v2() {
ExtBuilder::default().build().execute_with(|| {
use crate::{EraIndex, slashing::SpanIndex};
#[derive(Encode)]
struct V1SlashingSpans {
span_index: SpanIndex,
last_start: EraIndex,
prior: Vec<EraIndex>,
}
// inject old-style values directly into storage.
let set = |stash, spans: V1SlashingSpans| {
let key = <Staking as Store>::SlashingSpans::hashed_key_for(stash);
sp_io::storage::set(&key, &spans.encode());
};
let spans_11 = V1SlashingSpans {
span_index: 10,
last_start: 1,
prior: vec![0],
};
let spans_21 = V1SlashingSpans {
span_index: 1,
last_start: 5,
prior: vec![],
};
set(11, spans_11);
set(21, spans_21);
<Staking as Store>::StorageVersion::put(1);
// perform migration.
crate::migration::inner::to_v2::<Test>(&mut 1);
assert_eq!(
<Staking as Store>::SlashingSpans::get(&11).unwrap().last_nonzero_slash(),
1,
);
assert_eq!(
<Staking as Store>::SlashingSpans::get(&21).unwrap().last_nonzero_slash(),
5,
);
});
}
#[test]
fn zero_slash_keeps_nominators() {
ExtBuilder::default().build().execute_with(|| {