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
+3 -5
View File
@@ -21,8 +21,8 @@ use sp_core::{Pair, Public, crypto::UncheckedInto, sr25519};
use serde::{Serialize, Deserialize};
use node_runtime::{
AuthorityDiscoveryConfig, BabeConfig, BalancesConfig, ContractsConfig, CouncilConfig, DemocracyConfig,
GrandpaConfig, ImOnlineConfig, IndicesConfig, SessionConfig, SessionKeys, StakerStatus, StakingConfig,
SocietyConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, WASM_BINARY,
GrandpaConfig, ImOnlineConfig, SessionConfig, SessionKeys, StakerStatus, StakingConfig,
IndicesConfig, SocietyConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, WASM_BINARY,
};
use node_runtime::Block;
use node_runtime::constants::currency::*;
@@ -239,9 +239,7 @@ pub fn testnet_genesis(
.collect(),
}),
pallet_indices: Some(IndicesConfig {
ids: endowed_accounts.iter().cloned()
.chain(initial_authorities.iter().map(|x| x.0.clone()))
.collect::<Vec<_>>(),
indices: vec![],
}),
pallet_session: Some(SessionConfig {
keys: initial_authorities.iter().map(|x| {
+20 -36
View File
@@ -35,7 +35,7 @@ use frame_system::{self, EventRecord, Phase};
use node_runtime::{
Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances,
System, TransactionPayment, Event, TransactionBaseFee, TransactionByteFee, CreationFee,
System, TransactionPayment, Event, TransactionBaseFee, TransactionByteFee,
constants::currency::*,
};
use node_primitives::{Balance, Hash};
@@ -163,15 +163,12 @@ fn block_with_size(time: u64, nonce: u32, size: usize) -> (Vec<u8>, Hash) {
fn panic_execution_with_foreign_code_gives_error() {
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(BLOATY_CODE, Storage {
top: map![
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
<frame_system::Account<Runtime>>::hashed_key_for(alice()) => {
(69u128, 0u128, 0u128, 0u128).encode()
},
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
69_u128.encode()
},
<pallet_indices::NextEnumSet<Runtime>>::hashed_key().to_vec() => {
0_u128.encode()
},
<frame_system::BlockHash<Runtime>>::hashed_key_for(0) => {
vec![0u8; 32]
}
@@ -202,15 +199,12 @@ fn panic_execution_with_foreign_code_gives_error() {
fn bad_extrinsic_with_native_equivalent_code_gives_error() {
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, Storage {
top: map![
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
(69u128, 0u128, 0u128, 0u128).encode()
<frame_system::Account<Runtime>>::hashed_key_for(alice()) => {
(0u32, 69u128, 0u128, 0u128, 0u128).encode()
},
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
69_u128.encode()
},
<pallet_indices::NextEnumSet<Runtime>>::hashed_key().to_vec() => {
0_u128.encode()
},
<frame_system::BlockHash<Runtime>>::hashed_key_for(0) => {
vec![0u8; 32]
}
@@ -241,13 +235,12 @@ fn bad_extrinsic_with_native_equivalent_code_gives_error() {
fn successful_execution_with_native_equivalent_code_gives_ok() {
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, Storage {
top: map![
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
(111 * DOLLARS, 0u128, 0u128, 0u128).encode()
<frame_system::Account<Runtime>>::hashed_key_for(alice()) => {
(0u32, 111 * DOLLARS, 0u128, 0u128, 0u128).encode()
},
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
(111 * DOLLARS).encode()
},
<pallet_indices::NextEnumSet<Runtime>>::hashed_key().to_vec() => vec![0u8; 16],
<frame_system::BlockHash<Runtime>>::hashed_key_for(0) => vec![0u8; 32]
],
children: map![],
@@ -274,7 +267,7 @@ fn successful_execution_with_native_equivalent_code_gives_ok() {
assert!(r.is_ok());
t.execute_with(|| {
let fees = transfer_fee(&xt(), fm) + CreationFee::get();
let fees = transfer_fee(&xt(), fm);
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS);
});
@@ -284,13 +277,12 @@ fn successful_execution_with_native_equivalent_code_gives_ok() {
fn successful_execution_with_foreign_code_gives_ok() {
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(BLOATY_CODE, Storage {
top: map![
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
(111 * DOLLARS, 0u128, 0u128, 0u128).encode()
<frame_system::Account<Runtime>>::hashed_key_for(alice()) => {
(0u32, 111 * DOLLARS, 0u128, 0u128, 0u128).encode()
},
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
(111 * DOLLARS).encode()
},
<pallet_indices::NextEnumSet<Runtime>>::hashed_key().to_vec() => vec![0u8; 16],
<frame_system::BlockHash<Runtime>>::hashed_key_for(0) => vec![0u8; 32]
],
children: map![],
@@ -317,7 +309,7 @@ fn successful_execution_with_foreign_code_gives_ok() {
assert!(r.is_ok());
t.execute_with(|| {
let fees = transfer_fee(&xt(), fm) + CreationFee::get();
let fees = transfer_fee(&xt(), fm);
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS);
});
@@ -348,7 +340,7 @@ fn full_native_block_import_works() {
let events = vec![
EventRecord {
phase: Phase::ApplyExtrinsic(0),
event: Event::system(frame_system::Event::ExtrinsicSuccess(
event: Event::frame_system(frame_system::RawEvent::ExtrinsicSuccess(
DispatchInfo { weight: 10000, class: DispatchClass::Operational, pays_fee: true }
)),
topics: vec![],
@@ -364,13 +356,12 @@ fn full_native_block_import_works() {
alice().into(),
bob().into(),
69 * DOLLARS,
0,
)),
topics: vec![],
},
EventRecord {
phase: Phase::ApplyExtrinsic(1),
event: Event::system(frame_system::Event::ExtrinsicSuccess(
event: Event::frame_system(frame_system::RawEvent::ExtrinsicSuccess(
DispatchInfo { weight: 1000000, class: DispatchClass::Normal, pays_fee: true }
)),
topics: vec![],
@@ -401,7 +392,7 @@ fn full_native_block_import_works() {
let events = vec![
EventRecord {
phase: Phase::ApplyExtrinsic(0),
event: Event::system(frame_system::Event::ExtrinsicSuccess(
event: Event::frame_system(frame_system::RawEvent::ExtrinsicSuccess(
DispatchInfo { weight: 10000, class: DispatchClass::Operational, pays_fee: true }
)),
topics: vec![],
@@ -418,14 +409,13 @@ fn full_native_block_import_works() {
bob().into(),
alice().into(),
5 * DOLLARS,
0,
)
),
topics: vec![],
},
EventRecord {
phase: Phase::ApplyExtrinsic(1),
event: Event::system(frame_system::Event::ExtrinsicSuccess(
event: Event::frame_system(frame_system::RawEvent::ExtrinsicSuccess(
DispatchInfo { weight: 1000000, class: DispatchClass::Normal, pays_fee: true }
)),
topics: vec![],
@@ -442,14 +432,13 @@ fn full_native_block_import_works() {
alice().into(),
bob().into(),
15 * DOLLARS,
0,
)
),
topics: vec![],
},
EventRecord {
phase: Phase::ApplyExtrinsic(2),
event: Event::system(frame_system::Event::ExtrinsicSuccess(
event: Event::frame_system(frame_system::RawEvent::ExtrinsicSuccess(
DispatchInfo { weight: 1000000, class: DispatchClass::Normal, pays_fee: true }
)),
topics: vec![],
@@ -712,13 +701,9 @@ fn native_big_block_import_fails_on_fallback() {
fn panic_execution_gives_error() {
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(BLOATY_CODE, Storage {
top: map![
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
(0_u128, 0_u128, 0_u128, 0_u128).encode()
},
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
0_u128.encode()
},
<pallet_indices::NextEnumSet<Runtime>>::hashed_key().to_vec() => vec![0u8; 16],
<frame_system::BlockHash<Runtime>>::hashed_key_for(0) => vec![0u8; 32]
],
children: map![],
@@ -747,13 +732,12 @@ fn panic_execution_gives_error() {
fn successful_execution_gives_ok() {
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, Storage {
top: map![
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
(111 * DOLLARS, 0u128, 0u128, 0u128).encode()
<frame_system::Account<Runtime>>::hashed_key_for(alice()) => {
(0u32, 111 * DOLLARS, 0u128, 0u128, 0u128).encode()
},
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
(111 * DOLLARS).encode()
},
<pallet_indices::NextEnumSet<Runtime>>::hashed_key().to_vec() => vec![0u8; 16],
<frame_system::BlockHash<Runtime>>::hashed_key_for(0) => vec![0u8; 32]
],
children: map![],
@@ -777,11 +761,11 @@ fn successful_execution_gives_ok() {
).0.unwrap().into_encoded();
ApplyExtrinsicResult::decode(&mut &r[..])
.unwrap()
.expect("Extrinsic could be applied")
.expect("Extrinsic did not fail");
.expect("Extrinsic could not be applied")
.expect("Extrinsic failed");
t.execute_with(|| {
let fees = transfer_fee(&xt(), fm) + CreationFee::get();
let fees = transfer_fee(&xt(), fm);
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS);
});
+5 -6
View File
@@ -134,16 +134,15 @@ fn transaction_fee_is_correct_ultimate() {
// (this baed on assigning 0.1 CENT to the cheapest tx with `weight = 100`)
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, Storage {
top: map![
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
(100 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode()
<frame_system::Account<Runtime>>::hashed_key_for(alice()) => {
(0u32, 100 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode()
},
<pallet_balances::Account<Runtime>>::hashed_key_for(bob()) => {
(10 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode()
<frame_system::Account<Runtime>>::hashed_key_for(bob()) => {
(0u32, 10 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode()
},
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
(110 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode()
(110 * DOLLARS).encode()
},
<pallet_indices::NextEnumSet<Runtime>>::hashed_key().to_vec() => vec![0u8; 16],
<frame_system::BlockHash<Runtime>>::hashed_key_for(0) => vec![0u8; 32]
],
children: map![],
@@ -168,7 +168,7 @@ fn submitted_transaction_should_be_valid() {
let author = extrinsic.signature.clone().unwrap().0;
let address = Indices::lookup(author).unwrap();
let account = pallet_balances::AccountData { free: 5_000_000_000_000, ..Default::default() };
<pallet_balances::Account<Runtime, _>>::insert(&address, account);
<frame_system::Account<Runtime>>::insert(&address, (0u32, account));
// check validity
let res = Executive::validate_transaction(extrinsic);
+34 -34
View File
@@ -82,8 +82,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// and set impl_version to 0. If only runtime
// implementation changes and behavior does not, then leave spec_version as
// is and increment impl_version.
spec_version: 217,
impl_version: 1,
spec_version: 218,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
};
@@ -130,6 +130,9 @@ impl frame_system::Trait for Runtime {
type AvailableBlockRatio = AvailableBlockRatio;
type Version = Version;
type ModuleToIndex = ModuleToIndex;
type AccountData = pallet_balances::AccountData<Balance>;
type OnNewAccount = ();
type OnReapAccount = (Balances, Staking, Contracts, Session, Recovery);
}
parameter_types! {
@@ -160,27 +163,27 @@ impl pallet_babe::Trait for Runtime {
type EpochChangeTrigger = pallet_babe::ExternalTrigger;
}
parameter_types! {
pub const IndexDeposit: Balance = 1 * DOLLARS;
}
impl pallet_indices::Trait for Runtime {
type AccountIndex = AccountIndex;
type IsDeadAccount = Balances;
type ResolveHint = pallet_indices::SimpleResolveHint<Self::AccountId, Self::AccountIndex>;
type Event = Event;
type Currency = Balances;
type Deposit = IndexDeposit;
}
parameter_types! {
pub const ExistentialDeposit: Balance = 1 * DOLLARS;
pub const CreationFee: Balance = 1 * CENTS;
}
impl pallet_balances::Trait for Runtime {
type Balance = Balance;
type OnReapAccount = ((((System, Staking), Contracts), Session), Recovery);
type OnNewAccount = Indices;
type Event = Event;
type DustRemoval = ();
type TransferPayment = ();
type Event = Event;
type ExistentialDeposit = ExistentialDeposit;
type CreationFee = CreationFee;
type AccountStore = frame_system::Module<Runtime>;
}
parameter_types! {
@@ -235,13 +238,13 @@ parameter_types! {
}
impl pallet_session::Trait for Runtime {
type SessionManager = Staking;
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type ShouldEndSession = Babe;
type Event = Event;
type Keys = SessionKeys;
type ValidatorId = <Self as frame_system::Trait>::AccountId;
type ValidatorIdOf = pallet_staking::StashOf<Self>;
type ShouldEndSession = Babe;
type SessionManager = Staking;
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = SessionKeys;
type DisabledValidatorsThreshold = DisabledValidatorsThreshold;
}
@@ -303,7 +306,6 @@ impl pallet_democracy::Trait for Runtime {
type EnactmentPeriod = EnactmentPeriod;
type LaunchPeriod = LaunchPeriod;
type VotingPeriod = VotingPeriod;
type EmergencyVotingPeriod = EmergencyVotingPeriod;
type MinimumDeposit = MinimumDeposit;
/// A straight majority of the council can decide what their next motion is.
type ExternalOrigin = pallet_collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>;
@@ -315,6 +317,7 @@ impl pallet_democracy::Trait for Runtime {
/// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote
/// be tabled immediately and with a shorter voting/enactment period.
type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, TechnicalCollective>;
type EmergencyVotingPeriod = EmergencyVotingPeriod;
// To cancel a proposal which has been passed, 2/3 of the council must agree to it.
type CancellationOrigin = pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilCollective>;
// Any single technical committee member may veto a coming council proposal, however they can
@@ -343,16 +346,16 @@ parameter_types! {
impl pallet_elections_phragmen::Trait for Runtime {
type Event = Event;
type Currency = Balances;
type ChangeMembers = Council;
type CurrencyToVote = CurrencyToVoteHandler;
type CandidacyBond = CandidacyBond;
type VotingBond = VotingBond;
type TermDuration = TermDuration;
type DesiredMembers = DesiredMembers;
type DesiredRunnersUp = DesiredRunnersUp;
type LoserCandidate = ();
type BadReport = ();
type KickedMember = ();
type ChangeMembers = Council;
type DesiredMembers = DesiredMembers;
type DesiredRunnersUp = DesiredRunnersUp;
type TermDuration = TermDuration;
}
type TechnicalCollective = pallet_collective::Instance2;
@@ -387,22 +390,20 @@ impl pallet_treasury::Trait for Runtime {
type Currency = Balances;
type ApproveOrigin = pallet_collective::EnsureMembers<_4, AccountId, CouncilCollective>;
type RejectOrigin = pallet_collective::EnsureMembers<_2, AccountId, CouncilCollective>;
type Tippers = Elections;
type TipCountdown = TipCountdown;
type TipFindersFee = TipFindersFee;
type TipReportDepositBase = TipReportDepositBase;
type TipReportDepositPerByte = TipReportDepositPerByte;
type Event = Event;
type ProposalRejection = ();
type ProposalBond = ProposalBond;
type ProposalBondMinimum = ProposalBondMinimum;
type SpendPeriod = SpendPeriod;
type Burn = Burn;
type Tippers = Elections;
type TipCountdown = TipCountdown;
type TipFindersFee = TipFindersFee;
type TipReportDepositBase = TipReportDepositBase;
type TipReportDepositPerByte = TipReportDepositPerByte;
}
parameter_types! {
pub const ContractTransferFee: Balance = 1 * CENTS;
pub const ContractCreationFee: Balance = 1 * CENTS;
pub const ContractTransactionBaseFee: Balance = 1 * CENTS;
pub const ContractTransactionByteFee: Balance = 10 * MILLICENTS;
pub const ContractFee: Balance = 1 * CENTS;
@@ -429,7 +430,6 @@ impl pallet_contracts::Trait for Runtime {
type RentByteFee = RentByteFee;
type RentDepositOffset = RentDepositOffset;
type SurchargeReward = SurchargeReward;
type CreationFee = ContractCreationFee;
type TransactionBaseFee = ContractTransactionBaseFee;
type TransactionByteFee = ContractTransactionByteFee;
type ContractFee = ContractFee;
@@ -454,11 +454,11 @@ parameter_types! {
impl pallet_im_online::Trait for Runtime {
type AuthorityId = ImOnlineId;
type Call = Call;
type Event = Event;
type Call = Call;
type SubmitTransaction = SubmitTransaction;
type ReportUnresponsiveness = Offences;
type SessionDuration = SessionDuration;
type ReportUnresponsiveness = Offences;
}
impl pallet_offences::Trait for Runtime {
@@ -495,14 +495,14 @@ parameter_types! {
impl pallet_identity::Trait for Runtime {
type Event = Event;
type Currency = Balances;
type Slashed = Treasury;
type BasicDeposit = BasicDeposit;
type FieldDeposit = FieldDeposit;
type SubAccountDeposit = SubAccountDeposit;
type MaxSubAccounts = MaxSubAccounts;
type MaxAdditionalFields = MaxAdditionalFields;
type RegistrarOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>;
type Slashed = Treasury;
type ForceOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>;
type RegistrarOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>;
}
impl frame_system::offchain::CreateTransaction<Runtime, UncheckedExtrinsic> for Runtime {
@@ -600,13 +600,13 @@ construct_runtime!(
NodeBlock = node_primitives::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
System: frame_system::{Module, Call, Storage, Config, Event},
System: frame_system::{Module, Call, Config, Storage, Event<T>},
Utility: pallet_utility::{Module, Call, Storage, Event<T>},
Babe: pallet_babe::{Module, Call, Storage, Config, Inherent(Timestamp)},
Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},
Authorship: pallet_authorship::{Module, Call, Storage, Inherent},
Indices: pallet_indices,
Balances: pallet_balances,
Indices: pallet_indices::{Module, Call, Storage, Config<T>, Event<T>},
Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},
TransactionPayment: pallet_transaction_payment::{Module, Storage},
Staking: pallet_staking,
Session: pallet_session::{Module, Call, Storage, Event, Config<T>},
+1 -1
View File
@@ -62,7 +62,7 @@ pub fn config_endowed(
code: code.map(|x| x.to_vec()).unwrap_or_else(|| WASM_BINARY.to_vec()),
}),
pallet_indices: Some(IndicesConfig {
ids: vec![alice(), bob(), charlie(), dave(), eve(), ferdie()],
indices: vec![],
}),
pallet_balances: Some(BalancesConfig {
balances: endowed,