mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-20 11:41:02 +00:00
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:
@@ -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.
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ where
|
||||
}
|
||||
|
||||
fn block_author() -> Option<T::AccountId> {
|
||||
Some(<pallet_authorship::Pallet<T>>::author())
|
||||
<pallet_authorship::Pallet<T>>::author()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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()
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"]
|
||||
@@ -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
@@ -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
@@ -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));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -185,7 +185,7 @@ where
|
||||
}
|
||||
|
||||
fn block_author() -> Option<T::AccountId> {
|
||||
Some(<pallet_authorship::Pallet<T>>::author())
|
||||
<pallet_authorship::Pallet<T>>::author()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -324,7 +324,6 @@ pub mod pallet {
|
||||
type AuthorityId: Member
|
||||
+ Parameter
|
||||
+ RuntimeAppPublic
|
||||
+ Default
|
||||
+ Ord
|
||||
+ MaybeSerializeDeserialize
|
||||
+ MaxEncodedLen;
|
||||
|
||||
@@ -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! {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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<_>>();
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -238,7 +238,6 @@ pub mod pallet {
|
||||
+ Debug
|
||||
+ MaybeDisplay
|
||||
+ Ord
|
||||
+ Default
|
||||
+ MaxEncodedLen;
|
||||
|
||||
/// Converting trait to take a source type and convert to `AccountId`.
|
||||
|
||||
@@ -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) = ⪯
|
||||
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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user