Remove Default bound for AccountId (#10403)

* Remove Default for AccountId

* More removals of default

* Update frame/authorship/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update frame/authorship/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update frame/authorship/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update frame/authorship/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* More work

* More work

* Remove old code

* More work

* pallet-asset-tx-payment

* tips

* sc-consensus-babe

* sc-finality-grandpa

* sc-consensus-babe-rpc

* sc-cli

* make npos crates accept non-default account (#10420)

* minimal changes to make npos pallets all work

* make this pesky reduce.rs a bit cleaner

* more work

* more work

* Tests build

* Fix imonline tests

* Formatting

* Fixes

* Fixes

* Fix bench

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Formatting

* Fixes

* Formatting

* Fixes

* Formatting

* Fixes

* Formatting

* Fixes

* Formatting

* Update client/keystore/src/local.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update client/finality-grandpa/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update client/keystore/src/local.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update client/keystore/src/local.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update frame/staking/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update frame/staking/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update primitives/runtime/src/traits.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Formatting

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: kianenigma <kian@parity.io>
This commit is contained in:
Gavin Wood
2021-12-13 15:03:59 +01:00
committed by GitHub
parent a4ccc26e33
commit 1e24e45ea1
118 changed files with 998 additions and 4181 deletions
-1
View File
@@ -69,7 +69,6 @@ pub mod pallet {
type AuthorityId: Member
+ Parameter
+ RuntimeAppPublic
+ Default
+ MaybeSerializeDeserialize
+ MaxEncodedLen;
/// The maximum number of authorities that the pallet can hold.
+15 -16
View File
@@ -170,7 +170,9 @@ pub mod pallet {
<DidSetUncles<T>>::put(false);
T::EventHandler::note_author(Self::author());
if let Some(author) = Self::author() {
T::EventHandler::note_author(author);
}
0
}
@@ -300,20 +302,18 @@ impl<T: Config> Pallet<T> {
///
/// This is safe to invoke in `on_initialize` implementations, as well
/// as afterwards.
pub fn author() -> T::AccountId {
pub fn author() -> Option<T::AccountId> {
// Check the memoized storage value.
if let Some(author) = <Author<T>>::get() {
return author
return Some(author)
}
let digest = <frame_system::Pallet<T>>::digest();
let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime());
if let Some(author) = T::FindAuthor::find_author(pre_runtime_digests) {
<Author<T>>::put(&author);
author
} else {
Default::default()
}
T::FindAuthor::find_author(pre_runtime_digests).map(|a| {
<Author<T>>::put(&a);
a
})
}
fn verify_and_import_uncles(new_uncles: Vec<T::Header>) -> dispatch::DispatchResult {
@@ -329,14 +329,13 @@ impl<T: Config> Pallet<T> {
UncleEntryItem::InclusionHeight(_) => None,
UncleEntryItem::Uncle(h, _) => Some(h),
});
let author = Self::verify_uncle(&uncle, prev_uncles, &mut acc)?;
let maybe_author = Self::verify_uncle(&uncle, prev_uncles, &mut acc)?;
let hash = uncle.hash();
T::EventHandler::note_uncle(
author.clone().unwrap_or_default(),
now - uncle.number().clone(),
);
uncles.push(UncleEntryItem::Uncle(hash, author));
if let Some(author) = maybe_author.clone() {
T::EventHandler::note_uncle(author, now - uncle.number().clone());
}
uncles.push(UncleEntryItem::Uncle(hash, maybe_author));
}
<Uncles<T>>::put(&uncles);
@@ -693,7 +692,7 @@ mod tests {
header.digest_mut().pop(); // pop the seal off.
System::initialize(&1, &Default::default(), header.digest(), Default::default());
assert_eq!(Authorship::author(), author);
assert_eq!(Authorship::author(), Some(author));
});
}
+1 -1
View File
@@ -176,7 +176,7 @@ where
}
fn block_author() -> Option<T::AccountId> {
Some(<pallet_authorship::Pallet<T>>::author())
<pallet_authorship::Pallet<T>>::author()
}
}
+1 -1
View File
@@ -31,7 +31,7 @@ use frame_support::{
weights::{Pays, Weight},
BoundedVec, WeakBoundedVec,
};
use sp_application_crypto::Public;
use sp_application_crypto::ByteArray;
use sp_runtime::{
generic::DigestItem,
traits::{IsMember, One, SaturatedConversion, Saturating, Zero},
+1 -1
View File
@@ -72,7 +72,7 @@ where
pub struct BeefyEcdsaToEthereum;
impl Convert<beefy_primitives::crypto::AuthorityId, Vec<u8>> for BeefyEcdsaToEthereum {
fn convert(a: beefy_primitives::crypto::AuthorityId) -> Vec<u8> {
use sp_core::crypto::Public;
use sp_core::crypto::ByteArray;
let compressed_key = a.as_slice();
libsecp256k1::PublicKey::parse_slice(
+1 -1
View File
@@ -47,7 +47,7 @@ pub mod pallet {
#[pallet::config]
pub trait Config: frame_system::Config {
/// Authority identifier type
type BeefyId: Member + Parameter + RuntimeAppPublic + Default + MaybeSerializeDeserialize;
type BeefyId: Member + Parameter + RuntimeAppPublic + MaybeSerializeDeserialize;
}
#[pallet::pallet]
+5 -7
View File
@@ -23,6 +23,7 @@ use frame_support::{
traits::StorageInfo,
};
use sp_io::hashing::blake2_256;
use sp_runtime::traits::TrailingZeroInput;
use sp_std::{prelude::Box, vec::Vec};
use sp_storage::TrackedStorageKey;
@@ -321,17 +322,14 @@ pub trait BenchmarkingSetup<T, I = ()> {
}
/// Grab an account, seeded by a name and index.
pub fn account<AccountId: Decode + Default>(
name: &'static str,
index: u32,
seed: u32,
) -> AccountId {
pub fn account<AccountId: Decode>(name: &'static str, index: u32, seed: u32) -> AccountId {
let entropy = (name, index, seed).using_encoded(blake2_256);
AccountId::decode(&mut &entropy[..]).unwrap_or_default()
Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref()))
.expect("infinite length input; no invalid inputs for type; qed")
}
/// This caller account is automatically whitelisted for DB reads/writes by the benchmarking macro.
pub fn whitelisted_caller<AccountId: Decode + Default>() -> AccountId {
pub fn whitelisted_caller<AccountId: Decode>() -> AccountId {
account::<AccountId>("whitelisted_caller", 0, 0)
}
+1 -1
View File
@@ -123,7 +123,7 @@ pub struct Bounty<AccountId, Balance, BlockNumber> {
status: BountyStatus<AccountId, BlockNumber>,
}
impl<AccountId: PartialEq + Clone + Ord + Default, Balance, BlockNumber: Clone>
impl<AccountId: PartialEq + Clone + Ord, Balance, BlockNumber: Clone>
Bounty<AccountId, Balance, BlockNumber>
{
/// Getter for bounty status, to be used for child bounties.
+18 -18
View File
@@ -43,9 +43,9 @@ benchmarks_instance_pallet! {
// Set old members.
// We compute the difference of old and new members, so it should influence timing.
let mut old_members = vec![];
let mut last_old_member = T::AccountId::default();
let mut last_old_member = account::<T::AccountId>("old member", 0, SEED);
for i in 0 .. m {
last_old_member = account("old member", i, SEED);
last_old_member = account::<T::AccountId>("old member", i, SEED);
old_members.push(last_old_member.clone());
}
let old_members_count = old_members.len() as u32;
@@ -91,9 +91,9 @@ benchmarks_instance_pallet! {
// Construct `new_members`.
// It should influence timing since it will sort this vector.
let mut new_members = vec![];
let mut last_member = T::AccountId::default();
let mut last_member = account::<T::AccountId>("member", 0, SEED);
for i in 0 .. n {
last_member = account("member", i, SEED);
last_member = account::<T::AccountId>("member", i, SEED);
new_members.push(last_member.clone());
}
@@ -112,7 +112,7 @@ benchmarks_instance_pallet! {
// Construct `members`.
let mut members = vec![];
for i in 0 .. m - 1 {
let member = account("member", i, SEED);
let member = account::<T::AccountId>("member", i, SEED);
members.push(member);
}
@@ -142,7 +142,7 @@ benchmarks_instance_pallet! {
// Construct `members`.
let mut members = vec![];
for i in 0 .. m - 1 {
let member = account("member", i, SEED);
let member = account::<T::AccountId>("member", i, SEED);
members.push(member);
}
@@ -174,7 +174,7 @@ benchmarks_instance_pallet! {
// Construct `members`.
let mut members = vec![];
for i in 0 .. m - 1 {
let member = account("member", i, SEED);
let member = account::<T::AccountId>("member", i, SEED);
members.push(member);
}
let caller: T::AccountId = whitelisted_caller();
@@ -216,13 +216,13 @@ benchmarks_instance_pallet! {
// Construct `members`.
let mut members = vec![];
let proposer: T::AccountId = account("proposer", 0, SEED);
let proposer: T::AccountId = account::<T::AccountId>("proposer", 0, SEED);
members.push(proposer.clone());
for i in 1 .. m - 1 {
let member = account("member", i, SEED);
let member = account::<T::AccountId>("member", i, SEED);
members.push(member);
}
let voter: T::AccountId = account("voter", 0, SEED);
let voter: T::AccountId = account::<T::AccountId>("voter", 0, SEED);
members.push(voter.clone());
Collective::<T, I>::set_members(SystemOrigin::Root.into(), members.clone(), None, T::MaxMembers::get())?;
@@ -291,13 +291,13 @@ benchmarks_instance_pallet! {
// Construct `members`.
let mut members = vec![];
let proposer: T::AccountId = account("proposer", 0, SEED);
let proposer = account::<T::AccountId>("proposer", 0, SEED);
members.push(proposer.clone());
for i in 1 .. m - 1 {
let member = account("member", i, SEED);
let member = account::<T::AccountId>("member", i, SEED);
members.push(member);
}
let voter: T::AccountId = account("voter", 0, SEED);
let voter = account::<T::AccountId>("voter", 0, SEED);
members.push(voter.clone());
Collective::<T, I>::set_members(SystemOrigin::Root.into(), members.clone(), None, T::MaxMembers::get())?;
@@ -373,7 +373,7 @@ benchmarks_instance_pallet! {
// Construct `members`.
let mut members = vec![];
for i in 0 .. m - 1 {
let member = account("member", i, SEED);
let member = account::<T::AccountId>("member", i, SEED);
members.push(member);
}
let caller: T::AccountId = whitelisted_caller();
@@ -454,7 +454,7 @@ benchmarks_instance_pallet! {
// Construct `members`.
let mut members = vec![];
for i in 0 .. m - 1 {
let member = account("member", i, SEED);
let member = account::<T::AccountId>("member", i, SEED);
members.push(member);
}
let caller: T::AccountId = whitelisted_caller();
@@ -528,7 +528,7 @@ benchmarks_instance_pallet! {
// Construct `members`.
let mut members = vec![];
for i in 0 .. m - 1 {
let member = account("member", i, SEED);
let member = account::<T::AccountId>("member", i, SEED);
members.push(member);
}
let caller: T::AccountId = whitelisted_caller();
@@ -599,10 +599,10 @@ benchmarks_instance_pallet! {
// Construct `members`.
let mut members = vec![];
for i in 0 .. m - 1 {
let member = account("member", i, SEED);
let member = account::<T::AccountId>("member", i, SEED);
members.push(member);
}
let caller: T::AccountId = account("caller", 0, SEED);
let caller = account::<T::AccountId>("caller", 0, SEED);
members.push(caller.clone());
Collective::<T, I>::set_members(
SystemOrigin::Root.into(),
+4 -1
View File
@@ -224,13 +224,16 @@ mod v6 {
})
});
let nobody = T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes())
.expect("Infinite input; no dead input space; qed");
<CodeStorage<T>>::translate(|key, old: OldPrefabWasmModule| {
weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 2));
<OwnerInfoOf<T>>::insert(
key,
OwnerInfo {
refcount: old.refcount,
owner: Default::default(),
owner: nobody.clone(),
deposit: Default::default(),
},
);
@@ -239,9 +239,14 @@ benchmarks! {
let origin = T::ExternalOrigin::successful_origin();
let proposal_hash = T::Hashing::hash_of(&0);
// Add proposal to blacklist with block number 0
let addresses = (0..v)
.into_iter()
.map(|i| account::<T::AccountId>("blacklist", i, SEED))
.collect::<Vec<_>>();
Blacklist::<T>::insert(
proposal_hash,
(T::BlockNumber::zero(), vec![T::AccountId::default(); v as usize])
(T::BlockNumber::zero(), addresses),
);
}: _<T::Origin>(origin, proposal_hash)
verify {
@@ -292,7 +297,7 @@ benchmarks! {
let mut vetoers: Vec<T::AccountId> = Vec::new();
for i in 0 .. v {
vetoers.push(account("vetoer", i, SEED));
vetoers.push(account::<T::AccountId>("vetoer", i, SEED));
}
vetoers.sort();
Blacklist::<T>::insert(proposal_hash, (T::BlockNumber::zero(), vetoers));
@@ -209,7 +209,11 @@ frame_benchmarking::benchmarks! {
let receiver = account("receiver", 0, SEED);
let initial_balance = T::Currency::minimum_balance() * 10u32.into();
T::Currency::make_free_balance_be(&receiver, initial_balance);
let ready: ReadySolution<T::AccountId> = Default::default();
let ready = ReadySolution {
supports: vec![],
score: Default::default(),
compute: Default::default()
};
let deposit: BalanceOf<T> = 10u32.into();
let reward: BalanceOf<T> = 20u32.into();
@@ -314,7 +318,12 @@ frame_benchmarking::benchmarks! {
score: [(10_000_000 + i).into(), 0, 0],
..Default::default()
};
let signed_submission = SignedSubmission { raw_solution, ..Default::default() };
let signed_submission = SignedSubmission {
raw_solution,
who: account("submitters", i, SEED),
deposit: Default::default(),
reward: Default::default(),
};
signed_submissions.insert(signed_submission);
}
signed_submissions.put();
@@ -1189,7 +1189,7 @@ pub mod pallet {
/// affect; we shouldn't need a cryptographically secure hasher.
#[pallet::storage]
pub(crate) type SignedSubmissionsMap<T: Config> =
StorageMap<_, Twox64Concat, u32, SignedSubmissionOf<T>, ValueQuery>;
StorageMap<_, Twox64Concat, u32, SignedSubmissionOf<T>, OptionQuery>;
// `SignedSubmissions` items end here.
@@ -42,7 +42,7 @@ use sp_std::{
/// A raw, unchecked signed submission.
///
/// This is just a wrapper around [`RawSolution`] and some additional info.
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, Default, scale_info::TypeInfo)]
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)]
pub struct SignedSubmission<AccountId, Balance: HasCompact, Solution> {
/// Who submitted this solution.
pub who: AccountId,
@@ -167,17 +167,17 @@ impl<T: Config> SignedSubmissions<T> {
}
/// Get the submission at a particular index.
fn get_submission(&self, idx: u32) -> Option<SignedSubmissionOf<T>> {
if self.deletion_overlay.contains(&idx) {
fn get_submission(&self, index: u32) -> Option<SignedSubmissionOf<T>> {
if self.deletion_overlay.contains(&index) {
// Note: can't actually remove the item from the insertion overlay (if present)
// because we don't want to use `&mut self` here. There may be some kind of
// `RefCell` optimization possible here in the future.
None
} else {
self.insertion_overlay
.get(&idx)
.get(&index)
.cloned()
.or_else(|| SignedSubmissionsMap::<T>::try_get(idx).ok())
.or_else(|| SignedSubmissionsMap::<T>::get(index))
}
}
@@ -200,18 +200,18 @@ impl<T: Config> SignedSubmissions<T> {
remove_score: ElectionScore,
insert: Option<(ElectionScore, u32)>,
) -> Option<SignedSubmissionOf<T>> {
let remove_idx = self.indices.remove(&remove_score)?;
let remove_index = self.indices.remove(&remove_score)?;
if let Some((insert_score, insert_idx)) = insert {
self.indices
.try_insert(insert_score, insert_idx)
.expect("just removed an item, we must be under capacity; qed");
}
self.insertion_overlay.remove(&remove_idx).or_else(|| {
(!self.deletion_overlay.contains(&remove_idx))
self.insertion_overlay.remove(&remove_index).or_else(|| {
(!self.deletion_overlay.contains(&remove_index))
.then(|| {
self.deletion_overlay.insert(remove_idx);
SignedSubmissionsMap::<T>::try_get(remove_idx).ok()
self.deletion_overlay.insert(remove_index);
SignedSubmissionsMap::<T>::get(remove_index)
})
.flatten()
})
+15 -2
View File
@@ -147,7 +147,7 @@ pub enum Renouncing {
}
/// An active voter.
#[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq, TypeInfo)]
#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, TypeInfo)]
pub struct Voter<AccountId, Balance> {
/// The members being backed.
pub votes: Vec<AccountId>,
@@ -159,6 +159,12 @@ pub struct Voter<AccountId, Balance> {
pub deposit: Balance,
}
impl<AccountId, Balance: Default> Default for Voter<AccountId, Balance> {
fn default() -> Self {
Self { votes: vec![], stake: Default::default(), deposit: Default::default() }
}
}
/// A holder of a seat as either a member or a runner-up.
#[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq, TypeInfo)]
pub struct SeatHolder<AccountId, Balance> {
@@ -1087,7 +1093,14 @@ impl<T: Config> SortedMembers<T::AccountId> for Pallet<T> {
fn add(who: &T::AccountId) {
Members::<T>::mutate(|members| match members.binary_search_by(|m| m.who.cmp(who)) {
Ok(_) => (),
Err(pos) => members.insert(pos, SeatHolder { who: who.clone(), ..Default::default() }),
Err(pos) => {
let s = SeatHolder {
who: who.clone(),
stake: Default::default(),
deposit: Default::default(),
};
members.insert(pos, s)
},
})
}
}
-42
View File
@@ -1,42 +0,0 @@
[package]
name = "pallet-elections"
version = "4.0.0-dev"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
license = "Apache-2.0"
homepage = "https://substrate.io"
repository = "https://github.com/paritytech/substrate/"
description = "FRAME pallet for elections"
readme = "README.md"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
"derive",
] }
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
sp-core = { version = "4.1.0-dev", default-features = false, path = "../../primitives/core" }
sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" }
sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
[dev-dependencies]
pallet-balances = { version = "4.0.0-dev", path = "../balances" }
[features]
default = ["std"]
std = [
"codec/std",
"scale-info/std",
"sp-core/std",
"sp-std/std",
"sp-io/std",
"frame-support/std",
"sp-runtime/std",
"frame-system/std",
]
try-runtime = ["frame-support/try-runtime"]
-7
View File
@@ -1,7 +0,0 @@
Election module for stake-weighted membership selection of a collective.
The composition of a set of account IDs works according to one or more approval votes
weighted by stake. There is a partial carry-over facility to give greater weight to those
whose voting is serially unsuccessful.
License: Apache-2.0
File diff suppressed because it is too large Load Diff
-274
View File
@@ -1,274 +0,0 @@
// This file is part of Substrate.
// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Mock file for election module.
#![cfg(test)]
use crate as elections;
use frame_support::{
assert_ok, parameter_types,
traits::{ChangeMembers, Currency, LockIdentifier},
};
use sp_core::H256;
use sp_runtime::{
testing::Header,
traits::{BlakeTwo256, IdentityLookup},
BuildStorage,
};
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub BlockWeights: frame_system::limits::BlockWeights =
frame_system::limits::BlockWeights::simple_max(1024);
}
impl frame_system::Config for Test {
type BaseCallFilter = frame_support::traits::Everything;
type BlockWeights = ();
type BlockLength = ();
type DbWeight = ();
type Origin = Origin;
type Call = Call;
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = Event;
type BlockHashCount = BlockHashCount;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<u64>;
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = ();
type OnSetCode = ();
type MaxConsumers = frame_support::traits::ConstU32<16>;
}
parameter_types! {
pub const ExistentialDeposit: u64 = 1;
}
impl pallet_balances::Config for Test {
type MaxLocks = ();
type MaxReserves = ();
type ReserveIdentifier = [u8; 8];
type Balance = u64;
type DustRemoval = ();
type Event = Event;
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
type WeightInfo = ();
}
parameter_types! {
pub const CandidacyBond: u64 = 3;
pub const CarryCount: u32 = 2;
pub const InactiveGracePeriod: u32 = 1;
pub const VotingPeriod: u64 = 4;
pub const MinimumVotingLock: u64 = 5;
pub static VotingBond: u64 = 0;
pub static VotingFee: u64 = 0;
pub static PresentSlashPerVoter: u64 = 0;
pub static DecayRatio: u32 = 0;
pub static Members: Vec<u64> = vec![];
}
pub struct TestChangeMembers;
impl ChangeMembers<u64> for TestChangeMembers {
fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) {
let mut old_plus_incoming = MEMBERS.with(|m| m.borrow().to_vec());
old_plus_incoming.extend_from_slice(incoming);
old_plus_incoming.sort();
let mut new_plus_outgoing = new.to_vec();
new_plus_outgoing.extend_from_slice(outgoing);
new_plus_outgoing.sort();
assert_eq!(old_plus_incoming, new_plus_outgoing);
MEMBERS.with(|m| *m.borrow_mut() = new.to_vec());
}
}
parameter_types! {
pub const ElectionPalletId: LockIdentifier = *b"py/elect";
}
impl elections::Config for Test {
type Event = Event;
type Currency = Balances;
type BadPresentation = ();
type BadReaper = ();
type BadVoterIndex = ();
type LoserCandidate = ();
type ChangeMembers = TestChangeMembers;
type CandidacyBond = CandidacyBond;
type VotingBond = VotingBond;
type VotingFee = VotingFee;
type MinimumVotingLock = MinimumVotingLock;
type PresentSlashPerVoter = PresentSlashPerVoter;
type CarryCount = CarryCount;
type InactiveGracePeriod = InactiveGracePeriod;
type VotingPeriod = VotingPeriod;
type DecayRatio = DecayRatio;
type PalletId = ElectionPalletId;
}
pub type Block = sp_runtime::generic::Block<Header, UncheckedExtrinsic>;
pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic<u32, u64, Call, ()>;
use frame_system as system;
frame_support::construct_runtime!(
pub enum Test where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
System: system::{Pallet, Call, Event<T>},
Balances: pallet_balances::{Pallet, Call, Event<T>, Config<T>},
Elections: elections::{Pallet, Call, Event<T>, Config<T>},
}
);
pub struct ExtBuilder {
balance_factor: u64,
decay_ratio: u32,
desired_seats: u32,
voting_fee: u64,
voting_bond: u64,
bad_presentation_punishment: u64,
}
impl Default for ExtBuilder {
fn default() -> Self {
Self {
balance_factor: 1,
decay_ratio: 24,
desired_seats: 2,
voting_fee: 0,
voting_bond: 0,
bad_presentation_punishment: 1,
}
}
}
impl ExtBuilder {
pub fn balance_factor(mut self, factor: u64) -> Self {
self.balance_factor = factor;
self
}
pub fn decay_ratio(mut self, ratio: u32) -> Self {
self.decay_ratio = ratio;
self
}
pub fn voting_fee(mut self, fee: u64) -> Self {
self.voting_fee = fee;
self
}
pub fn bad_presentation_punishment(mut self, fee: u64) -> Self {
self.bad_presentation_punishment = fee;
self
}
pub fn voting_bond(mut self, fee: u64) -> Self {
self.voting_bond = fee;
self
}
pub fn desired_seats(mut self, seats: u32) -> Self {
self.desired_seats = seats;
self
}
pub fn build(self) -> sp_io::TestExternalities {
VOTING_BOND.with(|v| *v.borrow_mut() = self.voting_bond);
VOTING_FEE.with(|v| *v.borrow_mut() = self.voting_fee);
PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow_mut() = self.bad_presentation_punishment);
DECAY_RATIO.with(|v| *v.borrow_mut() = self.decay_ratio);
let mut ext: sp_io::TestExternalities = GenesisConfig {
balances: pallet_balances::GenesisConfig::<Test> {
balances: vec![
(1, 10 * self.balance_factor),
(2, 20 * self.balance_factor),
(3, 30 * self.balance_factor),
(4, 40 * self.balance_factor),
(5, 50 * self.balance_factor),
(6, 60 * self.balance_factor),
],
},
elections: elections::GenesisConfig::<Test> {
members: vec![],
desired_seats: self.desired_seats,
presentation_duration: 2,
term_duration: 5,
},
}
.build_storage()
.unwrap()
.into();
ext.execute_with(|| System::set_block_number(1));
ext
}
}
pub(crate) fn voter_ids() -> Vec<u64> {
Elections::all_voters().iter().map(|v| v.unwrap_or(0)).collect::<Vec<u64>>()
}
pub(crate) fn vote(i: u64, l: usize) {
let _ = Balances::make_free_balance_be(&i, 20);
assert_ok!(Elections::set_approvals(
Origin::signed(i),
(0..l).map(|_| true).collect::<Vec<bool>>(),
0,
0,
20,
));
}
pub(crate) fn vote_at(i: u64, l: usize, index: elections::VoteIndex) {
let _ = Balances::make_free_balance_be(&i, 20);
assert_ok!(Elections::set_approvals(
Origin::signed(i),
(0..l).map(|_| true).collect::<Vec<bool>>(),
0,
index,
20,
));
}
pub(crate) fn create_candidate(i: u64, index: u32) {
let _ = Balances::make_free_balance_be(&i, 20);
assert_ok!(Elections::submit_candidacy(Origin::signed(i), index));
}
pub(crate) fn balances(who: &u64) -> (u64, u64) {
(Balances::free_balance(who), Balances::reserved_balance(who))
}
pub(crate) fn locks(who: &u64) -> Vec<u64> {
Balances::locks(who).iter().map(|l| l.amount).collect::<Vec<u64>>()
}
pub(crate) fn new_test_ext_with_candidate_holes() -> sp_io::TestExternalities {
let mut t = ExtBuilder::default().build();
t.execute_with(|| {
<elections::Candidates<Test>>::put(vec![0, 0, 1]);
elections::CandidateCount::<Test>::put(1);
<elections::RegisterInfoOf<Test>>::insert(1, (0, 2));
});
t
}
File diff suppressed because it is too large Load Diff
+10
View File
@@ -731,6 +731,16 @@ where
Ok(())
}
fn pre_dispatch(
self,
who: &Self::AccountId,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
Ok(self.validate(who, call, info, len).map(|_| ())?)
}
fn validate(
&self,
_who: &Self::AccountId,
@@ -233,7 +233,7 @@ pub mod pallet {
// Retrieve sender of the transaction.
let who = ensure_signed(origin)?;
// Add the price to the on-chain list.
Self::add_price(who, price);
Self::add_price(Some(who), price);
Ok(().into())
}
@@ -262,7 +262,7 @@ pub mod pallet {
// This ensures that the function can only be called via unsigned transaction.
ensure_none(origin)?;
// Add the price to the on-chain list, but mark it as coming from an empty address.
Self::add_price(Default::default(), price);
Self::add_price(None, price);
// now increment the block number at which we expect next unsigned transaction.
let current_block = <system::Pallet<T>>::block_number();
<NextUnsignedAt<T>>::put(current_block + T::UnsignedInterval::get());
@@ -278,7 +278,7 @@ pub mod pallet {
// This ensures that the function can only be called via unsigned transaction.
ensure_none(origin)?;
// Add the price to the on-chain list, but mark it as coming from an empty address.
Self::add_price(Default::default(), price_payload.price);
Self::add_price(None, price_payload.price);
// now increment the block number at which we expect next unsigned transaction.
let current_block = <system::Pallet<T>>::block_number();
<NextUnsignedAt<T>>::put(current_block + T::UnsignedInterval::get());
@@ -291,7 +291,7 @@ pub mod pallet {
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// Event generated when new price is accepted to contribute to the average.
NewPrice { price: u32, who: T::AccountId },
NewPrice { price: u32, maybe_who: Option<T::AccountId> },
}
#[pallet::validate_unsigned]
@@ -641,7 +641,7 @@ impl<T: Config> Pallet<T> {
}
/// Add new price to the list.
fn add_price(who: T::AccountId, price: u32) {
fn add_price(maybe_who: Option<T::AccountId>, price: u32) {
log::info!("Adding to the average: {}", price);
<Prices<T>>::mutate(|prices| {
const MAX_LEN: usize = 64;
@@ -657,7 +657,7 @@ impl<T: Config> Pallet<T> {
.expect("The average is not empty, because it was just mutated; qed");
log::info!("Current average price is: {}", average);
// here we are raising the NewPrice event
Self::deposit_event(Event::NewPrice { price, who });
Self::deposit_event(Event::NewPrice { price, maybe_who });
}
/// Calculate current average price.
@@ -125,15 +125,19 @@ impl Config for Test {
type UnsignedPriority = UnsignedPriority;
}
fn test_pub() -> sp_core::sr25519::Public {
sp_core::sr25519::Public::from_raw([1u8; 32])
}
#[test]
fn it_aggregates_the_price() {
sp_io::TestExternalities::default().execute_with(|| {
assert_eq!(Example::average_price(), None);
assert_ok!(Example::submit_price(Origin::signed(Default::default()), 27));
assert_ok!(Example::submit_price(Origin::signed(test_pub()), 27));
assert_eq!(Example::average_price(), Some(27));
assert_ok!(Example::submit_price(Origin::signed(Default::default()), 43));
assert_ok!(Example::submit_price(Origin::signed(test_pub()), 43));
assert_eq!(Example::average_price(), Some(35));
});
}
+4 -4
View File
@@ -105,13 +105,13 @@ pub struct EnlistedParticipant {
impl EnlistedParticipant {
fn verify(&self, event_id: &[u8]) -> bool {
use sp_core::Public;
use sp_core::ByteArray;
use sp_runtime::traits::Verify;
match sp_core::sr25519::Signature::try_from(&self.signature[..]) {
Ok(signature) => {
let public = sp_core::sr25519::Public::from_slice(self.account.as_ref());
signature.verify(event_id, &public)
Ok(signature) => match sp_core::sr25519::Public::from_slice(self.account.as_ref()) {
Err(()) => false,
Ok(signer) => signature.verify(event_id, &signer),
},
_ => false,
}
+12 -7
View File
@@ -81,6 +81,14 @@ impl Config for Test {
type Call = Call;
}
fn test_pub(n: u8) -> sp_core::sr25519::Public {
sp_core::sr25519::Public::from_raw([n; 32])
}
fn test_origin(n: u8) -> Origin {
Origin::signed(test_pub(n))
}
#[test]
fn it_can_enlist() {
use sp_core::Pair;
@@ -91,8 +99,7 @@ fn it_can_enlist() {
let event_name = b"test";
Example::run_event(Origin::signed(Default::default()), event_name.to_vec())
.expect("Failed to enlist");
Example::run_event(test_origin(1), event_name.to_vec()).expect("Failed to enlist");
let participants = vec![
EnlistedParticipant {
@@ -105,7 +112,7 @@ fn it_can_enlist() {
},
];
Example::enlist_participants(Origin::signed(Default::default()), participants)
Example::enlist_participants(Origin::signed(test_pub(1)), participants)
.expect("Failed to enlist");
assert_eq!(Example::participants().len(), 2);
@@ -123,8 +130,7 @@ fn one_wrong_will_not_enlist_anyone() {
let event_name = b"test";
Example::run_event(Origin::signed(Default::default()), event_name.to_vec())
.expect("Failed to enlist");
Example::run_event(test_origin(1), event_name.to_vec()).expect("Failed to enlist");
let participants = vec![
EnlistedParticipant {
@@ -142,8 +148,7 @@ fn one_wrong_will_not_enlist_anyone() {
},
];
Example::enlist_participants(Origin::signed(Default::default()), participants)
.expect("Failed to enlist");
Example::enlist_participants(test_origin(1), participants).expect("Failed to enlist");
assert_eq!(Example::participants().len(), 0);
});
+1 -1
View File
@@ -185,7 +185,7 @@ where
}
fn block_author() -> Option<T::AccountId> {
Some(<pallet_authorship::Pallet<T>>::author())
<pallet_authorship::Pallet<T>>::author()
}
}
-1
View File
@@ -324,7 +324,6 @@ pub mod pallet {
type AuthorityId: Member
+ Parameter
+ RuntimeAppPublic
+ Default
+ Ord
+ MaybeSerializeDeserialize
+ MaxEncodedLen;
+9 -1
View File
@@ -106,7 +106,15 @@ impl ReportOffence<u64, IdentificationTuple, Offence> for OffenceHandler {
pub fn new_test_ext() -> sp_io::TestExternalities {
let t = frame_system::GenesisConfig::default().build_storage::<Runtime>().unwrap();
t.into()
let mut result: sp_io::TestExternalities = t.into();
// Set the default keys, otherwise session will discard the validator.
result.execute_with(|| {
for i in 1..=6 {
System::inc_providers(&i);
assert_eq!(Session::set_keys(Origin::signed(i), (i - 1).into(), vec![]), Ok(()));
}
});
result
}
parameter_types! {
+3 -2
View File
@@ -64,7 +64,7 @@ use frame_system::{self as system, RawOrigin};
use scale_info::TypeInfo;
use sp_io::hashing::blake2_256;
use sp_runtime::{
traits::{Dispatchable, Zero},
traits::{Dispatchable, TrailingZeroInput, Zero},
DispatchError,
};
use sp_std::prelude::*;
@@ -508,7 +508,8 @@ impl<T: Config> Pallet<T> {
/// NOTE: `who` must be sorted. If it is not, then you'll get the wrong answer.
pub fn multi_account_id(who: &[T::AccountId], threshold: u16) -> T::AccountId {
let entropy = (b"modlpy/utilisuba", who, threshold).using_encoded(blake2_256);
T::AccountId::decode(&mut &entropy[..]).unwrap_or_default()
Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref()))
.expect("infinite length input; no invalid inputs for type; qed")
}
fn operate(
+3 -2
View File
@@ -45,7 +45,7 @@ use frame_system::{self as system};
use scale_info::TypeInfo;
use sp_io::hashing::blake2_256;
use sp_runtime::{
traits::{Dispatchable, Hash, Saturating, Zero},
traits::{Dispatchable, Hash, Saturating, TrailingZeroInput, Zero},
DispatchResult,
};
use sp_std::{convert::TryInto, prelude::*};
@@ -653,7 +653,8 @@ impl<T: Config> Pallet<T> {
});
let entropy = (b"modlpy/proxy____", who, height, ext_index, proxy_type, index)
.using_encoded(blake2_256);
T::AccountId::decode(&mut &entropy[..]).unwrap_or_default()
Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref()))
.expect("infinite length input; no invalid inputs for type; qed")
}
/// Register a proxy account for the delegator that is able to make calls on its behalf.
@@ -22,7 +22,7 @@
mod mock;
use sp_runtime::traits::{One, StaticLookup};
use sp_runtime::traits::{One, StaticLookup, TrailingZeroInput};
use sp_std::{prelude::*, vec};
use frame_benchmarking::benchmarks;
@@ -61,7 +61,8 @@ benchmarks! {
RewardDestination::Staked,
)?;
let v_controller = pallet_staking::Pallet::<T>::bonded(&v_stash).ok_or("not stash")?;
let keys = T::Keys::default();
let keys = T::Keys::decode(&mut TrailingZeroInput::zeroes()).unwrap();
let proof: Vec<u8> = vec![0,1,2,3];
// Whitelist controller account from further DB operations.
let v_controller_key = frame_system::Account::<T>::hashed_key_for(&v_controller);
@@ -77,7 +78,7 @@ benchmarks! {
RewardDestination::Staked
)?;
let v_controller = pallet_staking::Pallet::<T>::bonded(&v_stash).ok_or("not stash")?;
let keys = T::Keys::default();
let keys = T::Keys::decode(&mut TrailingZeroInput::zeroes()).unwrap();
let proof: Vec<u8> = vec![0,1,2,3];
Session::<T>::set_keys(RawOrigin::Signed(v_controller.clone()).into(), keys, proof)?;
// Whitelist controller account from further DB operations.
+23 -14
View File
@@ -312,8 +312,10 @@ impl<AId> SessionHandler<AId> for Tuple {
for_tuples!(
#(
let our_keys: Box<dyn Iterator<Item=_>> = Box::new(validators.iter()
.map(|k| (&k.0, k.1.get::<Tuple::Key>(<Tuple::Key as RuntimeAppPublic>::ID)
.unwrap_or_default())));
.filter_map(|k|
k.1.get::<Tuple::Key>(<Tuple::Key as RuntimeAppPublic>::ID).map(|k1| (&k.0, k1))
)
);
Tuple::on_genesis_session(our_keys);
)*
@@ -328,11 +330,13 @@ impl<AId> SessionHandler<AId> for Tuple {
for_tuples!(
#(
let our_keys: Box<dyn Iterator<Item=_>> = Box::new(validators.iter()
.map(|k| (&k.0, k.1.get::<Tuple::Key>(<Tuple::Key as RuntimeAppPublic>::ID)
.unwrap_or_default())));
.filter_map(|k|
k.1.get::<Tuple::Key>(<Tuple::Key as RuntimeAppPublic>::ID).map(|k1| (&k.0, k1))
));
let queued_keys: Box<dyn Iterator<Item=_>> = Box::new(queued_validators.iter()
.map(|k| (&k.0, k.1.get::<Tuple::Key>(<Tuple::Key as RuntimeAppPublic>::ID)
.unwrap_or_default())));
.filter_map(|k|
k.1.get::<Tuple::Key>(<Tuple::Key as RuntimeAppPublic>::ID).map(|k1| (&k.0, k1))
));
Tuple::on_new_session(changed, our_keys, queued_keys);
)*
)
@@ -403,7 +407,7 @@ pub mod pallet {
type SessionHandler: SessionHandler<Self::ValidatorId>;
/// The keys.
type Keys: OpaqueKeys + Member + Parameter + Default + MaybeSerializeDeserialize;
type Keys: OpaqueKeys + Member + Parameter + MaybeSerializeDeserialize;
/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
@@ -476,13 +480,18 @@ pub mod pallet {
let queued_keys: Vec<_> = initial_validators_1
.iter()
.cloned()
.map(|v| (v.clone(), <Pallet<T>>::load_keys(&v).unwrap_or_default()))
.filter_map(|v| {
Some((
v.clone(),
Pallet::<T>::load_keys(&v).expect("Validator in session 1 missing keys!"),
))
})
.collect();
// Tell everyone about the genesis session keys
T::SessionHandler::on_genesis_session::<T::Keys>(&queued_keys);
<Validators<T>>::put(initial_validators_0);
Validators::<T>::put(initial_validators_0);
<QueuedKeys<T>>::put(queued_keys);
T::SessionManager::start_session(0);
@@ -641,7 +650,7 @@ impl<T: Config> Pallet<T> {
let session_keys = <QueuedKeys<T>>::get();
let validators =
session_keys.iter().map(|(validator, _)| validator.clone()).collect::<Vec<_>>();
<Validators<T>>::put(&validators);
Validators::<T>::put(&validators);
if changed {
// reset disabled validators
@@ -663,7 +672,7 @@ impl<T: Config> Pallet<T> {
// same as before, as underlying economic conditions may have changed.
(validators, true)
} else {
(<Validators<T>>::get(), false)
(Validators::<T>::get(), false)
};
// Queue next session keys.
@@ -689,10 +698,10 @@ impl<T: Config> Pallet<T> {
};
let queued_amalgamated = next_validators
.into_iter()
.map(|a| {
let k = Self::load_keys(&a).unwrap_or_default();
.filter_map(|a| {
let k = Self::load_keys(&a)?;
check_next_changed(&k);
(a, k)
Some((a, k))
})
.collect::<Vec<_>>();
+16 -6
View File
@@ -21,6 +21,7 @@ use super::*;
use crate::Pallet as Staking;
use testing_utils::*;
use codec::Decode;
use frame_election_provider_support::SortedListProvider;
use frame_support::{
dispatch::UnfilteredDispatchable,
@@ -28,7 +29,7 @@ use frame_support::{
traits::{Currency, CurrencyToVote, Get, Imbalance},
};
use sp_runtime::{
traits::{Bounded, One, StaticLookup, Zero},
traits::{Bounded, One, StaticLookup, TrailingZeroInput, Zero},
Perbill, Percent,
};
use sp_staking::SessionIndex;
@@ -535,8 +536,9 @@ benchmarks! {
let s in 1 .. MAX_SLASHES;
let mut unapplied_slashes = Vec::new();
let era = EraIndex::one();
let dummy = || T::AccountId::decode(&mut TrailingZeroInput::zeroes()).unwrap();
for _ in 0 .. MAX_SLASHES {
unapplied_slashes.push(UnappliedSlash::<T::AccountId, BalanceOf<T>>::default());
unapplied_slashes.push(UnappliedSlash::<T::AccountId, BalanceOf<T>>::default_from(dummy()));
}
UnappliedSlashes::<T>::insert(era, &unapplied_slashes);
@@ -667,10 +669,11 @@ benchmarks! {
let e in 1 .. 100;
HistoryDepth::<T>::put(e);
CurrentEra::<T>::put(e);
let dummy = || -> T::AccountId { codec::Decode::decode(&mut TrailingZeroInput::zeroes()).unwrap() };
for i in 0 .. e {
<ErasStakers<T>>::insert(i, T::AccountId::default(), Exposure::<T::AccountId, BalanceOf<T>>::default());
<ErasStakersClipped<T>>::insert(i, T::AccountId::default(), Exposure::<T::AccountId, BalanceOf<T>>::default());
<ErasValidatorPrefs<T>>::insert(i, T::AccountId::default(), ValidatorPrefs::default());
<ErasStakers<T>>::insert(i, dummy(), Exposure::<T::AccountId, BalanceOf<T>>::default());
<ErasStakersClipped<T>>::insert(i, dummy(), Exposure::<T::AccountId, BalanceOf<T>>::default());
<ErasValidatorPrefs<T>>::insert(i, dummy(), ValidatorPrefs::default());
<ErasValidatorReward<T>>::insert(i, BalanceOf::<T>::one());
<ErasRewardPoints<T>>::insert(i, EraRewardPoints::<T::AccountId>::default());
<ErasTotalStake<T>>::insert(i, BalanceOf::<T>::one());
@@ -695,7 +698,14 @@ benchmarks! {
let stash = scenario.origin_stash1.clone();
add_slashing_spans::<T>(&stash, s);
Ledger::<T>::insert(&controller, StakingLedger { active: T::Currency::minimum_balance() - One::one(), total: T::Currency::minimum_balance() - One::one(), ..Default::default() });
let l = StakingLedger {
stash: stash.clone(),
active: T::Currency::minimum_balance() - One::one(),
total: T::Currency::minimum_balance() - One::one(),
unlocking: vec![],
claimed_rewards: vec![],
};
Ledger::<T>::insert(&controller, l);
assert!(Bonded::<T>::contains_key(&stash));
assert!(T::SortedListProvider::contains(&stash));
+41 -8
View File
@@ -364,7 +364,7 @@ pub struct ActiveEraInfo {
/// Reward points of an era. Used to split era total payout between validators.
///
/// This points will be used to reward validators and their respective nominators.
#[derive(PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo)]
#[derive(PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct EraRewardPoints<AccountId: Ord> {
/// Total number of points. Equals the sum of reward points for each validator.
total: RewardPoint,
@@ -372,9 +372,15 @@ pub struct EraRewardPoints<AccountId: Ord> {
individual: BTreeMap<AccountId, RewardPoint>,
}
impl<AccountId: Ord> Default for EraRewardPoints<AccountId> {
fn default() -> Self {
EraRewardPoints { total: Default::default(), individual: BTreeMap::new() }
}
}
/// Indicates the initial status of the staker.
#[derive(RuntimeDebug, TypeInfo)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize, Clone))]
pub enum StakerStatus<AccountId> {
/// Chilling.
Idle,
@@ -436,7 +442,6 @@ pub struct UnlockChunk<Balance: HasCompact> {
}
/// The ledger of a (bonded) stash.
#[cfg_attr(feature = "runtime-benchmarks", derive(Default))]
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct StakingLedger<AccountId, Balance: HasCompact> {
/// The stash account whose balance is actually locked and at stake.
@@ -457,9 +462,20 @@ pub struct StakingLedger<AccountId, Balance: HasCompact> {
pub claimed_rewards: Vec<EraIndex>,
}
impl<AccountId, Balance: HasCompact + Copy + Saturating + AtLeast32BitUnsigned>
impl<AccountId, Balance: HasCompact + Copy + Saturating + AtLeast32BitUnsigned + Zero>
StakingLedger<AccountId, Balance>
{
/// Initializes the default object using the given `validator`.
pub fn default_from(stash: AccountId) -> Self {
Self {
stash,
total: Zero::zero(),
active: Zero::zero(),
unlocking: vec![],
claimed_rewards: vec![],
}
}
/// Remove entries from `unlocking` that are sufficiently old and reduce the
/// total by the sum of their balances.
fn consolidate_unlocked(self, current_era: EraIndex) -> Self {
@@ -593,9 +609,7 @@ pub struct IndividualExposure<AccountId, Balance: HasCompact> {
}
/// A snapshot of the stake backing a single validator in the system.
#[derive(
PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo,
)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct Exposure<AccountId, Balance: HasCompact> {
/// The total balance backing this validator.
#[codec(compact)]
@@ -607,9 +621,15 @@ pub struct Exposure<AccountId, Balance: HasCompact> {
pub others: Vec<IndividualExposure<AccountId, Balance>>,
}
impl<AccountId, Balance: Default + HasCompact> Default for Exposure<AccountId, Balance> {
fn default() -> Self {
Self { total: Default::default(), own: Default::default(), others: vec![] }
}
}
/// A pending slash record. The value of the slash has been computed but not applied yet,
/// rather deferred for several eras.
#[derive(Encode, Decode, Default, RuntimeDebug, TypeInfo)]
#[derive(Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct UnappliedSlash<AccountId, Balance: HasCompact> {
/// The stash ID of the offending validator.
validator: AccountId,
@@ -623,6 +643,19 @@ pub struct UnappliedSlash<AccountId, Balance: HasCompact> {
payout: Balance,
}
impl<AccountId, Balance: HasCompact + Zero> UnappliedSlash<AccountId, Balance> {
/// Initializes the default object using the given `validator`.
pub fn default_from(validator: AccountId) -> Self {
Self {
validator,
own: Zero::zero(),
others: vec![],
reporters: vec![],
payout: Zero::zero(),
}
}
}
/// Means for interacting with a specialized version of the `session` trait.
///
/// This is needed because `Staking` sets the `ValidatorIdOf` of the `pallet_session::Config`
+8 -4
View File
@@ -480,7 +480,7 @@ impl ExtBuilder {
}
let _ = pallet_staking::GenesisConfig::<Test> {
stakers,
stakers: stakers.clone(),
validator_count: self.validator_count,
minimum_validator_count: self.minimum_validator_count,
invulnerables: self.invulnerables,
@@ -493,12 +493,15 @@ impl ExtBuilder {
let _ = pallet_session::GenesisConfig::<Test> {
keys: if self.has_stakers {
// genesis election will overwrite this, no worries.
Default::default()
// set the keys for the first session.
stakers
.into_iter()
.map(|(id, ..)| (id, id, SessionKeys { other: id.into() }))
.collect()
} else {
// set some dummy validators in genesis.
(0..self.validator_count as u64)
.map(|x| (x, x, SessionKeys { other: UintAuthorityId(x as u64) }))
.map(|id| (id, id, SessionKeys { other: id.into() }))
.collect()
},
}
@@ -644,6 +647,7 @@ pub(crate) fn bond(stash: AccountId, ctrl: AccountId, val: Balance) {
pub(crate) fn bond_validator(stash: AccountId, ctrl: AccountId, val: Balance) {
bond(stash, ctrl, val);
assert_ok!(Staking::validate(Origin::signed(ctrl), ValidatorPrefs::default()));
assert_ok!(Session::set_keys(Origin::signed(ctrl), SessionKeys { other: ctrl.into() }, vec![]));
}
pub(crate) fn bond_nominator(
+14 -4
View File
@@ -1089,8 +1089,13 @@ where
fn note_author(author: T::AccountId) {
Self::reward_by_ids(vec![(author, 20)])
}
fn note_uncle(author: T::AccountId, _age: T::BlockNumber) {
Self::reward_by_ids(vec![(<pallet_authorship::Pallet<T>>::author(), 2), (author, 1)])
fn note_uncle(uncle_author: T::AccountId, _age: T::BlockNumber) {
// defensive-only: block author must exist.
if let Some(block_author) = <pallet_authorship::Pallet<T>>::author() {
Self::reward_by_ids(vec![(block_author, 2), (uncle_author, 1)])
} else {
crate::log!(warn, "block author not set, this should never happen");
}
}
}
@@ -1238,8 +1243,13 @@ impl<T: Config> VoteWeightProvider<T::AccountId> for Pallet<T> {
// this will clearly results in an inconsistent state, but it should not matter for a
// benchmark.
let active: BalanceOf<T> = weight.try_into().map_err(|_| ()).unwrap();
let mut ledger = Self::ledger(who).unwrap_or_default();
ledger.active = active;
let ledger = match Self::ledger(who) {
None => StakingLedger::default_from(who.clone()),
Some(mut l) => {
l.active = active;
l
},
};
<Ledger<T>>::insert(who, ledger);
<Bonded<T>>::insert(who, who);
+33 -25
View File
@@ -217,16 +217,17 @@ fn rewards_should_work() {
Payee::<Test>::insert(21, RewardDestination::Controller);
Payee::<Test>::insert(101, RewardDestination::Controller);
<Pallet<Test>>::reward_by_ids(vec![(11, 50)]);
<Pallet<Test>>::reward_by_ids(vec![(11, 50)]);
Pallet::<Test>::reward_by_ids(vec![(11, 50)]);
Pallet::<Test>::reward_by_ids(vec![(11, 50)]);
// This is the second validator of the current elected set.
<Pallet<Test>>::reward_by_ids(vec![(21, 50)]);
Pallet::<Test>::reward_by_ids(vec![(21, 50)]);
// Compute total payout now for whole duration of the session.
let total_payout_0 = current_total_payout_for_duration(reward_time_per_era());
let maximum_payout = maximum_payout_for_duration(reward_time_per_era());
start_session(1);
assert_eq_uvec!(Session::validators(), vec![11, 21]);
assert_eq!(Balances::total_balance(&10), init_balance_10);
assert_eq!(Balances::total_balance(&11), init_balance_11);
@@ -234,7 +235,6 @@ fn rewards_should_work() {
assert_eq!(Balances::total_balance(&21), init_balance_21);
assert_eq!(Balances::total_balance(&100), init_balance_100);
assert_eq!(Balances::total_balance(&101), init_balance_101);
assert_eq_uvec!(Session::validators(), vec![11, 21]);
assert_eq!(
Staking::eras_reward_points(active_era()),
EraRewardPoints {
@@ -283,7 +283,7 @@ fn rewards_should_work() {
assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2);
assert_eq_uvec!(Session::validators(), vec![11, 21]);
<Pallet<Test>>::reward_by_ids(vec![(11, 1)]);
Pallet::<Test>::reward_by_ids(vec![(11, 1)]);
// Compute total payout now for whole duration as other parameter won't change
let total_payout_1 = current_total_payout_for_duration(reward_time_per_era());
@@ -338,6 +338,7 @@ fn staking_should_work() {
// add a new candidate for being a validator. account 3 controlled by 4.
assert_ok!(Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller));
assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default()));
assert_ok!(Session::set_keys(Origin::signed(4), SessionKeys { other: 4.into() }, vec![]));
// No effects will be seen so far.
assert_eq_uvec!(validator_controllers(), vec![20, 10]);
@@ -519,8 +520,8 @@ fn nominating_and_rewards_should_work() {
// the total reward for era 0
let total_payout_0 = current_total_payout_for_duration(reward_time_per_era());
<Pallet<Test>>::reward_by_ids(vec![(41, 1)]);
<Pallet<Test>>::reward_by_ids(vec![(21, 1)]);
Pallet::<Test>::reward_by_ids(vec![(41, 1)]);
Pallet::<Test>::reward_by_ids(vec![(21, 1)]);
mock::start_active_era(1);
@@ -561,8 +562,8 @@ fn nominating_and_rewards_should_work() {
// the total reward for era 1
let total_payout_1 = current_total_payout_for_duration(reward_time_per_era());
<Pallet<Test>>::reward_by_ids(vec![(21, 2)]);
<Pallet<Test>>::reward_by_ids(vec![(11, 1)]);
Pallet::<Test>::reward_by_ids(vec![(21, 2)]);
Pallet::<Test>::reward_by_ids(vec![(11, 1)]);
mock::start_active_era(2);
@@ -942,7 +943,7 @@ fn reward_destination_works() {
// Compute total payout now for whole duration as other parameter won't change
let total_payout_0 = current_total_payout_for_duration(reward_time_per_era());
<Pallet<Test>>::reward_by_ids(vec![(11, 1)]);
Pallet::<Test>::reward_by_ids(vec![(11, 1)]);
mock::start_active_era(1);
mock::make_all_reward_payment(0);
@@ -968,7 +969,7 @@ fn reward_destination_works() {
// Compute total payout now for whole duration as other parameter won't change
let total_payout_1 = current_total_payout_for_duration(reward_time_per_era());
<Pallet<Test>>::reward_by_ids(vec![(11, 1)]);
Pallet::<Test>::reward_by_ids(vec![(11, 1)]);
mock::start_active_era(2);
mock::make_all_reward_payment(1);
@@ -999,7 +1000,7 @@ fn reward_destination_works() {
// Compute total payout now for whole duration as other parameter won't change
let total_payout_2 = current_total_payout_for_duration(reward_time_per_era());
<Pallet<Test>>::reward_by_ids(vec![(11, 1)]);
Pallet::<Test>::reward_by_ids(vec![(11, 1)]);
mock::start_active_era(3);
mock::make_all_reward_payment(2);
@@ -1049,7 +1050,7 @@ fn validator_payment_prefs_work() {
// Compute total payout now for whole duration as other parameter won't change
let total_payout_1 = current_total_payout_for_duration(reward_time_per_era());
let exposure_1 = Staking::eras_stakers(active_era(), 11);
<Pallet<Test>>::reward_by_ids(vec![(11, 1)]);
Pallet::<Test>::reward_by_ids(vec![(11, 1)]);
mock::start_active_era(2);
mock::make_all_reward_payment(1);
@@ -1610,8 +1611,8 @@ fn reward_to_stake_works() {
// Compute total payout now for whole duration as other parameter won't change
let total_payout_0 = current_total_payout_for_duration(reward_time_per_era());
<Pallet<Test>>::reward_by_ids(vec![(11, 1)]);
<Pallet<Test>>::reward_by_ids(vec![(21, 1)]);
Pallet::<Test>::reward_by_ids(vec![(11, 1)]);
Pallet::<Test>::reward_by_ids(vec![(21, 1)]);
// New era --> rewards are paid --> stakes are changed
mock::start_active_era(1);
@@ -1707,6 +1708,7 @@ fn switching_roles() {
// add a new validator candidate
assert_ok!(Staking::bond(Origin::signed(5), 6, 1000, RewardDestination::Controller));
assert_ok!(Staking::validate(Origin::signed(6), ValidatorPrefs::default()));
assert_ok!(Session::set_keys(Origin::signed(6), SessionKeys { other: 6.into() }, vec![]));
mock::start_active_era(1);
@@ -1715,6 +1717,7 @@ fn switching_roles() {
// 2 decides to be a validator. Consequences:
assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default()));
assert_ok!(Session::set_keys(Origin::signed(2), SessionKeys { other: 2.into() }, vec![]));
// new stakes:
// 10: 1000 self vote
// 20: 1000 self vote + 250 vote
@@ -1819,6 +1822,11 @@ fn bond_with_little_staked_value_bounded() {
// Stingy validator.
assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller));
assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default()));
assert_ok!(Session::set_keys(
Origin::signed(2),
SessionKeys { other: 2.into() },
vec![]
));
// 1 era worth of reward. BUT, we set the timestamp after on_initialize, so outdated by
// one block.
@@ -2051,12 +2059,12 @@ fn reward_from_authorship_event_handler_works() {
ExtBuilder::default().build_and_execute(|| {
use pallet_authorship::EventHandler;
assert_eq!(<pallet_authorship::Pallet<Test>>::author(), 11);
assert_eq!(<pallet_authorship::Pallet<Test>>::author(), Some(11));
<Pallet<Test>>::note_author(11);
<Pallet<Test>>::note_uncle(21, 1);
Pallet::<Test>::note_author(11);
Pallet::<Test>::note_uncle(21, 1);
// Rewarding the same two times works.
<Pallet<Test>>::note_uncle(11, 1);
Pallet::<Test>::note_uncle(11, 1);
// Not mandatory but must be coherent with rewards
assert_eq_uvec!(Session::validators(), vec![11, 21]);
@@ -2079,9 +2087,9 @@ fn add_reward_points_fns_works() {
// Not mandatory but must be coherent with rewards
assert_eq_uvec!(Session::validators(), vec![21, 11]);
<Pallet<Test>>::reward_by_ids(vec![(21, 1), (11, 1), (11, 1)]);
Pallet::<Test>::reward_by_ids(vec![(21, 1), (11, 1), (11, 1)]);
<Pallet<Test>>::reward_by_ids(vec![(21, 1), (11, 1), (11, 1)]);
Pallet::<Test>::reward_by_ids(vec![(21, 1), (11, 1), (11, 1)]);
assert_eq!(
ErasRewardPoints::<Test>::get(active_era()),
@@ -3091,13 +3099,13 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() {
Payee::<Test>::insert(11, RewardDestination::Controller);
Payee::<Test>::insert(101, RewardDestination::Controller);
<Pallet<Test>>::reward_by_ids(vec![(11, 1)]);
Pallet::<Test>::reward_by_ids(vec![(11, 1)]);
// Compute total payout now for whole duration as other parameter won't change
let total_payout_0 = current_total_payout_for_duration(reward_time_per_era());
mock::start_active_era(1);
<Pallet<Test>>::reward_by_ids(vec![(11, 1)]);
Pallet::<Test>::reward_by_ids(vec![(11, 1)]);
// Change total issuance in order to modify total payout
let _ = Balances::deposit_creating(&999, 1_000_000_000);
// Compute total payout now for whole duration as other parameter won't change
@@ -3106,7 +3114,7 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() {
mock::start_active_era(2);
<Pallet<Test>>::reward_by_ids(vec![(11, 1)]);
Pallet::<Test>::reward_by_ids(vec![(11, 1)]);
// Change total issuance in order to modify total payout
let _ = Balances::deposit_creating(&999, 1_000_000_000);
// Compute total payout now for whole duration as other parameter won't change
@@ -3266,7 +3274,7 @@ fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward(
}
mock::start_active_era(1);
<Pallet<Test>>::reward_by_ids(vec![(11, 1)]);
Pallet::<Test>::reward_by_ids(vec![(11, 1)]);
// compute and ensure the reward amount is greater than zero.
let _ = current_total_payout_for_duration(reward_time_per_era());
+14 -12
View File
@@ -146,7 +146,7 @@ pub mod pallet {
) -> DispatchResultWithPostInfo {
// This is a public call, so we ensure that the origin is some signed account.
let sender = ensure_signed(origin)?;
ensure!(sender == Self::key(), Error::<T>::RequireSudo);
ensure!(Self::key().map_or(false, |k| sender == k), Error::<T>::RequireSudo);
let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into());
Self::deposit_event(Event::Sudid { sudo_result: res.map(|_| ()).map_err(|e| e.error) });
@@ -172,7 +172,7 @@ pub mod pallet {
) -> DispatchResultWithPostInfo {
// This is a public call, so we ensure that the origin is some signed account.
let sender = ensure_signed(origin)?;
ensure!(sender == Self::key(), Error::<T>::RequireSudo);
ensure!(Self::key().map_or(false, |k| sender == k), Error::<T>::RequireSudo);
let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into());
Self::deposit_event(Event::Sudid { sudo_result: res.map(|_| ()).map_err(|e| e.error) });
@@ -197,11 +197,11 @@ pub mod pallet {
) -> DispatchResultWithPostInfo {
// This is a public call, so we ensure that the origin is some signed account.
let sender = ensure_signed(origin)?;
ensure!(sender == Self::key(), Error::<T>::RequireSudo);
ensure!(Self::key().map_or(false, |k| sender == k), Error::<T>::RequireSudo);
let new = T::Lookup::lookup(new)?;
Self::deposit_event(Event::KeyChanged { new_sudoer: Self::key() });
<Key<T>>::put(new);
Self::deposit_event(Event::KeyChanged { old_sudoer: Key::<T>::get() });
Key::<T>::put(&new);
// Sudo user does not pay a fee.
Ok(Pays::No.into())
}
@@ -234,7 +234,7 @@ pub mod pallet {
) -> DispatchResultWithPostInfo {
// This is a public call, so we ensure that the origin is some signed account.
let sender = ensure_signed(origin)?;
ensure!(sender == Self::key(), Error::<T>::RequireSudo);
ensure!(Self::key().map_or(false, |k| sender == k), Error::<T>::RequireSudo);
let who = T::Lookup::lookup(who)?;
@@ -253,8 +253,8 @@ pub mod pallet {
pub enum Event<T: Config> {
/// A sudo just took place. \[result\]
Sudid { sudo_result: DispatchResult },
/// The \[sudoer\] just switched identity; the old key is supplied.
KeyChanged { new_sudoer: T::AccountId },
/// The \[sudoer\] just switched identity; the old key is supplied if one existed.
KeyChanged { old_sudoer: Option<T::AccountId> },
/// A sudo just took place. \[result\]
SudoAsDone { sudo_result: DispatchResult },
}
@@ -269,25 +269,27 @@ pub mod pallet {
/// The `AccountId` of the sudo key.
#[pallet::storage]
#[pallet::getter(fn key)]
pub(super) type Key<T: Config> = StorageValue<_, T::AccountId, ValueQuery>;
pub(super) type Key<T: Config> = StorageValue<_, T::AccountId, OptionQuery>;
#[pallet::genesis_config]
pub struct GenesisConfig<T: Config> {
/// The `AccountId` of the sudo key.
pub key: T::AccountId,
pub key: Option<T::AccountId>,
}
#[cfg(feature = "std")]
impl<T: Config> Default for GenesisConfig<T> {
fn default() -> Self {
Self { key: Default::default() }
Self { key: None }
}
}
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
fn build(&self) {
<Key<T>>::put(&self.key);
if let Some(ref key) = self.key {
Key::<T>::put(key);
}
}
}
}
+1 -1
View File
@@ -165,7 +165,7 @@ pub type LoggerCall = logger::Call<Test>;
// Build test environment by setting the root `key` for the Genesis.
pub fn new_test_ext(root_key: u64) -> sp_io::TestExternalities {
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
sudo::GenesisConfig::<Test> { key: root_key }
sudo::GenesisConfig::<Test> { key: Some(root_key) }
.assimilate_storage(&mut t)
.unwrap();
t.into()
+4 -4
View File
@@ -28,7 +28,7 @@ use mock::{
fn test_setup_works() {
// Environment setup, logger storage, and sudo `key` retrieval should work as expected.
new_test_ext(1).execute_with(|| {
assert_eq!(Sudo::key(), 1u64);
assert_eq!(Sudo::key(), Some(1u64));
assert!(Logger::i32_log().is_empty());
assert!(Logger::account_log().is_empty());
});
@@ -105,7 +105,7 @@ fn set_key_basics() {
new_test_ext(1).execute_with(|| {
// A root `key` can change the root `key`
assert_ok!(Sudo::set_key(Origin::signed(1), 2));
assert_eq!(Sudo::key(), 2u64);
assert_eq!(Sudo::key(), Some(2u64));
});
new_test_ext(1).execute_with(|| {
@@ -123,10 +123,10 @@ fn set_key_emits_events_correctly() {
// A root `key` can change the root `key`.
assert_ok!(Sudo::set_key(Origin::signed(1), 2));
System::assert_has_event(TestEvent::Sudo(Event::KeyChanged { new_sudoer: 1 }));
System::assert_has_event(TestEvent::Sudo(Event::KeyChanged { old_sudoer: Some(1) }));
// Double check.
assert_ok!(Sudo::set_key(Origin::signed(2), 4));
System::assert_has_event(TestEvent::Sudo(Event::KeyChanged { new_sudoer: 2 }));
System::assert_has_event(TestEvent::Sudo(Event::KeyChanged { old_sudoer: Some(2) }));
});
}
@@ -77,7 +77,7 @@ pub trait VerifySeal<Header, Author> {
/// A session handler for specific key type.
pub trait OneSessionHandler<ValidatorId>: BoundToRuntimeAppPublic {
/// The key type expected.
type Key: Decode + Default + RuntimeAppPublic;
type Key: Decode + RuntimeAppPublic;
/// The given validator set will be used for the genesis session.
/// It is guaranteed that the given validator set will also be used
@@ -229,6 +229,10 @@ pub type AccountId = <Signature as Verify>::Signer;
pub type BlockNumber = u64;
pub type Index = u64;
fn test_pub() -> AccountId {
AccountId::from_raw([0; 32])
}
impl system::Config for Runtime {
type BaseCallFilter = frame_support::traits::Everything;
type Hash = H256;
@@ -451,13 +455,13 @@ fn event_codec() {
let event = system::Event::<Runtime>::ExtrinsicSuccess;
assert_eq!(Event::from(event).encode()[0], 30);
let event = module1::Event::<Runtime, module1::Instance1>::A(Default::default());
let event = module1::Event::<Runtime, module1::Instance1>::A(test_pub());
assert_eq!(Event::from(event).encode()[0], 31);
let event = module2::Event::A;
assert_eq!(Event::from(event).encode()[0], 32);
let event = module1::Event::<Runtime, module1::Instance2>::A(Default::default());
let event = module1::Event::<Runtime, module1::Instance2>::A(test_pub());
assert_eq!(Event::from(event).encode()[0], 33);
let event = nested::module3::Event::A;
@@ -466,19 +470,19 @@ fn event_codec() {
let event = module3::Event::A;
assert_eq!(Event::from(event).encode()[0], 35);
let event = module1::Event::<Runtime, module1::Instance5>::A(Default::default());
let event = module1::Event::<Runtime, module1::Instance5>::A(test_pub());
assert_eq!(Event::from(event).encode()[0], 4);
let event = module1::Event::<Runtime, module1::Instance6>::A(Default::default());
let event = module1::Event::<Runtime, module1::Instance6>::A(test_pub());
assert_eq!(Event::from(event).encode()[0], 1);
let event = module1::Event::<Runtime, module1::Instance7>::A(Default::default());
let event = module1::Event::<Runtime, module1::Instance7>::A(test_pub());
assert_eq!(Event::from(event).encode()[0], 2);
let event = module1::Event::<Runtime, module1::Instance8>::A(Default::default());
let event = module1::Event::<Runtime, module1::Instance8>::A(test_pub());
assert_eq!(Event::from(event).encode()[0], 12);
let event = module1::Event::<Runtime, module1::Instance9>::A(Default::default());
let event = module1::Event::<Runtime, module1::Instance9>::A(test_pub());
assert_eq!(Event::from(event).encode()[0], 13);
}
@@ -19,7 +19,7 @@ use crate::{Config, Pallet};
use codec::{Decode, Encode};
use scale_info::TypeInfo;
use sp_runtime::{
traits::{SignedExtension, Zero},
traits::{DispatchInfoOf, SignedExtension, Zero},
transaction_validity::TransactionValidityError,
};
@@ -62,4 +62,14 @@ impl<T: Config + Send + Sync> SignedExtension for CheckGenesis<T> {
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
Ok(<Pallet<T>>::block_hash(T::BlockNumber::zero()))
}
fn pre_dispatch(
self,
who: &Self::AccountId,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
Ok(self.validate(who, call, info, len).map(|_| ())?)
}
}
@@ -85,6 +85,16 @@ impl<T: Config + Send + Sync> SignedExtension for CheckMortality<T> {
Ok(<Pallet<T>>::block_hash(n))
}
}
fn pre_dispatch(
self,
who: &Self::AccountId,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
Ok(self.validate(who, call, info, len).map(|_| ())?)
}
}
#[cfg(test)]
@@ -65,6 +65,16 @@ where
Ok(())
}
fn pre_dispatch(
self,
who: &Self::AccountId,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
Ok(self.validate(who, call, info, len).map(|_| ())?)
}
fn validate(
&self,
who: &Self::AccountId,
@@ -18,7 +18,10 @@
use crate::{Config, Pallet};
use codec::{Decode, Encode};
use scale_info::TypeInfo;
use sp_runtime::{traits::SignedExtension, transaction_validity::TransactionValidityError};
use sp_runtime::{
traits::{DispatchInfoOf, SignedExtension},
transaction_validity::TransactionValidityError,
};
/// Ensure the runtime version registered in the transaction is the same as at present.
///
@@ -59,4 +62,14 @@ impl<T: Config + Send + Sync> SignedExtension for CheckSpecVersion<T> {
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
Ok(<Pallet<T>>::runtime_version().spec_version)
}
fn pre_dispatch(
self,
who: &Self::AccountId,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
Ok(self.validate(who, call, info, len).map(|_| ())?)
}
}
@@ -18,7 +18,10 @@
use crate::{Config, Pallet};
use codec::{Decode, Encode};
use scale_info::TypeInfo;
use sp_runtime::{traits::SignedExtension, transaction_validity::TransactionValidityError};
use sp_runtime::{
traits::{DispatchInfoOf, SignedExtension},
transaction_validity::TransactionValidityError,
};
/// Ensure the transaction version registered in the transaction is the same as at present.
///
@@ -59,4 +62,13 @@ impl<T: Config + Send + Sync> SignedExtension for CheckTxVersion<T> {
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
Ok(<Pallet<T>>::runtime_version().transaction_version)
}
fn pre_dispatch(
self,
who: &Self::AccountId,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
Ok(self.validate(who, call, info, len).map(|_| ())?)
}
}
@@ -223,7 +223,7 @@ where
}
fn post_dispatch(
_pre: Self::Pre,
_pre: Option<Self::Pre>,
info: &DispatchInfoOf<Self::Call>,
post_info: &PostDispatchInfoOf<Self::Call>,
_len: usize,
@@ -563,7 +563,13 @@ mod tests {
let pre = CheckWeight::<Test>(PhantomData).pre_dispatch(&1, CALL, &info, len).unwrap();
assert_eq!(BlockWeight::<Test>::get().total(), info.weight + 256);
assert_ok!(CheckWeight::<Test>::post_dispatch(pre, &info, &post_info, len, &Ok(())));
assert_ok!(CheckWeight::<Test>::post_dispatch(
Some(pre),
&info,
&post_info,
len,
&Ok(())
));
assert_eq!(BlockWeight::<Test>::get().total(), post_info.actual_weight.unwrap() + 256);
})
}
@@ -587,7 +593,13 @@ mod tests {
info.weight + 128 + block_weights().get(DispatchClass::Normal).base_extrinsic,
);
assert_ok!(CheckWeight::<Test>::post_dispatch(pre, &info, &post_info, len, &Ok(())));
assert_ok!(CheckWeight::<Test>::post_dispatch(
Some(pre),
&info,
&post_info,
len,
&Ok(())
));
assert_eq!(
BlockWeight::<Test>::get().total(),
info.weight + 128 + block_weights().get(DispatchClass::Normal).base_extrinsic,
-1
View File
@@ -238,7 +238,6 @@ pub mod pallet {
+ Debug
+ MaybeDisplay
+ Ord
+ Default
+ MaxEncodedLen;
/// Converting trait to take a source type and convert to `AccountId`.
+5 -2
View File
@@ -61,7 +61,7 @@ pub mod migrations;
pub mod weights;
use sp_runtime::{
traits::{AccountIdConversion, BadOrigin, Hash, Zero},
traits::{AccountIdConversion, BadOrigin, Hash, TrailingZeroInput, Zero},
Percent, RuntimeDebug,
};
use sp_std::prelude::*;
@@ -580,6 +580,9 @@ impl<T: Config> Pallet<T> {
use frame_support::{migration::storage_key_iter, Twox64Concat};
let zero_account = T::AccountId::decode(&mut TrailingZeroInput::new(&[][..]))
.expect("infinite input; qed");
for (hash, old_tip) in storage_key_iter::<
T::Hash,
OldOpenTip<T::AccountId, BalanceOf<T>, T::BlockNumber, T::Hash>,
@@ -589,7 +592,7 @@ impl<T: Config> Pallet<T> {
{
let (finder, deposit, finders_fee) = match old_tip.finder {
Some((finder, deposit)) => (finder, deposit, true),
None => (T::AccountId::default(), Zero::zero(), false),
None => (zero_account.clone(), Zero::zero(), false),
};
let new_tip = OpenTip {
reason: old_tip.reason,
@@ -244,43 +244,44 @@ where
}
fn post_dispatch(
pre: Self::Pre,
pre: Option<Self::Pre>,
info: &DispatchInfoOf<Self::Call>,
post_info: &PostDispatchInfoOf<Self::Call>,
len: usize,
result: &DispatchResult,
) -> Result<(), TransactionValidityError> {
let (tip, who, initial_payment) = pre;
match initial_payment {
InitialPayment::Native(already_withdrawn) => {
pallet_transaction_payment::ChargeTransactionPayment::<T>::post_dispatch(
(tip, who, already_withdrawn),
info,
post_info,
len,
result,
)?;
},
InitialPayment::Asset(already_withdrawn) => {
let actual_fee = pallet_transaction_payment::Pallet::<T>::compute_actual_fee(
len as u32, info, post_info, tip,
);
T::OnChargeAssetTransaction::correct_and_deposit_fee(
&who,
info,
post_info,
actual_fee.into(),
tip.into(),
already_withdrawn.into(),
)?;
},
InitialPayment::Nothing => {
// `actual_fee` should be zero here for any signed extrinsic. It would be non-zero
// here in case of unsigned extrinsics as they don't pay fees but
// `compute_actual_fee` is not aware of them. In both cases it's fine to just move
// ahead without adjusting the fee, though, so we do nothing.
debug_assert!(tip.is_zero(), "tip should be zero if initial fee was zero.");
},
if let Some((tip, who, initial_payment)) = pre {
match initial_payment {
InitialPayment::Native(already_withdrawn) => {
pallet_transaction_payment::ChargeTransactionPayment::<T>::post_dispatch(
Some((tip, who, already_withdrawn)),
info,
post_info,
len,
result,
)?;
},
InitialPayment::Asset(already_withdrawn) => {
let actual_fee = pallet_transaction_payment::Pallet::<T>::compute_actual_fee(
len as u32, info, post_info, tip,
);
T::OnChargeAssetTransaction::correct_and_deposit_fee(
&who,
info,
post_info,
actual_fee.into(),
tip.into(),
already_withdrawn.into(),
)?;
},
InitialPayment::Nothing => {
// `actual_fee` should be zero here for any signed extrinsic. It would be
// non-zero here in case of unsigned extrinsics as they don't pay fees but
// `compute_actual_fee` is not aware of them. In both cases it's fine to just
// move ahead without adjusting the fee, though, so we do nothing.
debug_assert!(tip.is_zero(), "tip should be zero if initial fee was zero.");
},
}
}
Ok(())
@@ -201,10 +201,11 @@ impl pallet_authorship::Config for Runtime {
pub struct CreditToBlockAuthor;
impl HandleCredit<AccountId, Assets> for CreditToBlockAuthor {
fn handle_credit(credit: CreditOf<AccountId, Assets>) {
let author = pallet_authorship::Pallet::<Runtime>::author();
// What to do in case paying the author fails (e.g. because `fee < min_balance`)
// default: drop the result which will trigger the `OnDrop` of the imbalance.
let _ = <Assets as Balanced<AccountId>>::resolve(&author, credit);
if let Some(author) = pallet_authorship::Pallet::<Runtime>::author() {
// What to do in case paying the author fails (e.g. because `fee < min_balance`)
// default: drop the result which will trigger the `OnDrop` of the imbalance.
let _ = <Assets as Balanced<AccountId>>::resolve(&author, credit);
}
}
}
@@ -304,7 +305,7 @@ fn transaction_payment_in_native_possible() {
assert_eq!(Balances::free_balance(1), initial_balance - 5 - 5 - 10);
assert_ok!(ChargeAssetTxPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_weight(5),
&default_post_info(),
len,
@@ -319,7 +320,7 @@ fn transaction_payment_in_native_possible() {
assert_eq!(Balances::free_balance(2), initial_balance_for_2 - 5 - 10 - 100 - 5);
assert_ok!(ChargeAssetTxPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_weight(100),
&post_info_from_weight(50),
len,
@@ -370,7 +371,7 @@ fn transaction_payment_in_asset_possible() {
assert_eq!(Assets::balance(asset_id, BLOCK_AUTHOR), 0);
assert_ok!(ChargeAssetTxPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_weight(weight),
&default_post_info(),
len,
@@ -423,7 +424,7 @@ fn transaction_payment_without_fee() {
assert_eq!(Assets::balance(asset_id, BLOCK_AUTHOR), 0);
assert_ok!(ChargeAssetTxPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_weight(weight),
&post_info_from_pays(Pays::No),
len,
@@ -475,7 +476,7 @@ fn asset_transaction_payment_with_tip_and_refund() {
let final_weight = 50;
assert_ok!(ChargeAssetTxPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_weight(weight),
&post_info_from_weight(final_weight),
len,
@@ -528,7 +529,7 @@ fn payment_from_account_with_only_assets() {
assert_eq!(Assets::balance(asset_id, caller), balance - fee);
assert_ok!(ChargeAssetTxPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_weight(weight),
&default_post_info(),
len,
@@ -612,7 +613,7 @@ fn converted_fee_is_never_zero_if_input_fee_is_not() {
assert_eq!(Assets::balance(asset_id, caller), balance);
assert_ok!(ChargeAssetTxPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_pays(Pays::No),
&post_info_from_pays(Pays::No),
len,
@@ -627,7 +628,7 @@ fn converted_fee_is_never_zero_if_input_fee_is_not() {
assert_eq!(Assets::balance(asset_id, caller), balance - 1);
assert_ok!(ChargeAssetTxPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_weight(weight),
&default_post_info(),
len,
@@ -684,7 +685,7 @@ fn post_dispatch_fee_is_zero_if_pre_dispatch_fee_is_zero() {
// `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the
// initial fee)
assert_ok!(ChargeAssetTxPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_pays(Pays::No),
&post_info_from_pays(Pays::Yes),
len,
@@ -721,7 +722,7 @@ fn post_dispatch_fee_is_zero_if_unsigned_pre_dispatch_fee_is_zero() {
assert_eq!(Assets::balance(asset_id, caller), balance);
let weight = 1;
let len = 1;
let pre = ChargeAssetTxPayment::<Runtime>::pre_dispatch_unsigned(
ChargeAssetTxPayment::<Runtime>::pre_dispatch_unsigned(
CALL,
&info_from_weight(weight),
len,
@@ -729,17 +730,11 @@ fn post_dispatch_fee_is_zero_if_unsigned_pre_dispatch_fee_is_zero() {
.unwrap();
assert_eq!(Assets::balance(asset_id, caller), balance);
let (_tip, _who, initial_payment) = &pre;
let not_paying = match initial_payment {
&InitialPayment::Nothing => true,
_ => false,
};
assert!(not_paying, "initial payment is Nothing for unsigned extrinsics");
// `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the
// initial fee)
assert_ok!(ChargeAssetTxPayment::<Runtime>::post_dispatch(
pre,
None,
&info_from_weight(weight),
&post_info_from_pays(Pays::Yes),
len,
+16 -15
View File
@@ -704,7 +704,7 @@ where
type Pre = (
// tip
BalanceOf<T>,
// who paid the fee
// who paid the fee - this is an option to allow for a Default impl.
Self::AccountId,
// imbalance resulting from withdrawing the fee
<<T as Config>::OnChargeTransaction as OnChargeTransaction<T>>::LiquidityInfo,
@@ -740,17 +740,18 @@ where
}
fn post_dispatch(
pre: Self::Pre,
maybe_pre: Option<Self::Pre>,
info: &DispatchInfoOf<Self::Call>,
post_info: &PostDispatchInfoOf<Self::Call>,
len: usize,
_result: &DispatchResult,
) -> Result<(), TransactionValidityError> {
let (tip, who, imbalance) = pre;
let actual_fee = Pallet::<T>::compute_actual_fee(len as u32, info, post_info, tip);
T::OnChargeTransaction::correct_and_deposit_fee(
&who, info, post_info, actual_fee, tip, imbalance,
)?;
if let Some((tip, who, imbalance)) = maybe_pre {
let actual_fee = Pallet::<T>::compute_actual_fee(len as u32, info, post_info, tip);
T::OnChargeTransaction::correct_and_deposit_fee(
&who, info, post_info, actual_fee, tip, imbalance,
)?;
}
Ok(())
}
}
@@ -1014,7 +1015,7 @@ mod tests {
assert_eq!(Balances::free_balance(1), 100 - 5 - 5 - 10);
assert_ok!(ChargeTransactionPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_weight(5),
&default_post_info(),
len,
@@ -1032,7 +1033,7 @@ mod tests {
assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5);
assert_ok!(ChargeTransactionPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_weight(100),
&post_info_from_weight(50),
len,
@@ -1061,7 +1062,7 @@ mod tests {
assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 150 - 5);
assert_ok!(ChargeTransactionPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_weight(100),
&post_info_from_weight(50),
len,
@@ -1356,7 +1357,7 @@ mod tests {
assert_eq!(Balances::free_balance(2), 0);
assert_ok!(ChargeTransactionPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_weight(100),
&post_info_from_weight(50),
len,
@@ -1390,7 +1391,7 @@ mod tests {
assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5);
assert_ok!(ChargeTransactionPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info_from_weight(100),
&post_info_from_weight(101),
len,
@@ -1418,7 +1419,7 @@ mod tests {
.unwrap();
assert_eq!(Balances::total_balance(&user), 0);
assert_ok!(ChargeTransactionPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&dispatch_info,
&default_post_info(),
len,
@@ -1450,7 +1451,7 @@ mod tests {
.unwrap();
ChargeTransactionPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info,
&post_info,
len,
@@ -1601,7 +1602,7 @@ mod tests {
.unwrap();
ChargeTransactionPayment::<Runtime>::post_dispatch(
pre,
Some(pre),
&info,
&post_info,
len,
+3 -2
View File
@@ -65,7 +65,7 @@ use frame_support::{
};
use sp_core::TypeId;
use sp_io::hashing::blake2_256;
use sp_runtime::traits::Dispatchable;
use sp_runtime::traits::{Dispatchable, TrailingZeroInput};
use sp_std::prelude::*;
pub use weights::WeightInfo;
@@ -400,6 +400,7 @@ impl<T: Config> Pallet<T> {
/// Derive a derivative account ID from the owner account and the sub-account index.
pub fn derivative_account_id(who: T::AccountId, index: u16) -> T::AccountId {
let entropy = (b"modlpy/utilisuba", who, index).using_encoded(blake2_256);
T::AccountId::decode(&mut &entropy[..]).unwrap_or_default()
Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref()))
.expect("infinite length input; no invalid inputs for type; qed")
}
}