Add weight annotations to Timestamp, Sudo, Democracy, Treasury, et al. (#2694)

* Add some initial weighting notes

* Add Democracy and Sudo

* Add flags, fix formatting

* Add comments on finality-tracker

* Add a few mode modules.

* Update srml/democracy/src/lib.rs

Co-Authored-By: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update srml/democracy/src/lib.rs

Co-Authored-By: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update srml/system/src/lib.rs

Co-Authored-By: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update srml/system/src/lib.rs

Co-Authored-By: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update srml/system/src/lib.rs

Co-Authored-By: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update srml/system/src/lib.rs

Co-Authored-By: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update srml/treasury/src/lib.rs

Co-Authored-By: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update and merge changes

* Update srml/system/src/lib.rs

Co-Authored-By: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Remove unneeded comment

* Remove comment line

* Fix comment

* Fix formatting overall

* Apply suggestions from code review

Co-Authored-By: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Apply suggestions from code review

Co-Authored-By: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Clean up and polish

* Update srml/indices/src/lib.rs

* Update srml/staking/src/lib.rs

Co-Authored-By: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Final nits.
This commit is contained in:
lsaether
2019-06-12 09:03:23 +02:00
committed by Bastian Köcher
parent 6feab51069
commit f0f32f9250
11 changed files with 239 additions and 15 deletions
+24
View File
@@ -346,6 +346,21 @@ decl_module! {
/// of the transfer, the account will be reaped.
///
/// The dispatch origin for this call must be `Signed` by the transactor.
///
/// # <weight>
/// - Dependent on arguments but not critical, given proper implementations for
/// input config types. See related functions below.
/// - It contains a limited number of reads and writes internally and no complex computation.
///
/// Related functions:
///
/// - `ensure_can_withdraw` is always called internally but has a bounded complexity.
/// - Transferring balances to accounts that did not exist before will cause
/// `T::OnNewAccount::on_new_account` to be called.
/// - Removing enough funds from an account will trigger
/// `T::DustRemoval::on_unbalanced` and `T::OnFreeBalanceZero::on_free_balance_zero`.
///
/// # </weight>
pub fn transfer(
origin,
dest: <T::Lookup as StaticLookup>::Source,
@@ -364,6 +379,11 @@ decl_module! {
/// and reset the account nonce (`system::AccountNonce`).
///
/// The dispatch origin for this call is `root`.
///
/// # <weight>
/// - Independent of the arguments.
/// - Contains a limited number of reads and writes.
/// # </weight>
fn set_balance(
who: <T::Lookup as StaticLookup>::Source,
#[compact] free: T::Balance,
@@ -700,6 +720,10 @@ where
<FreeBalance<T, I>>::get(who)
}
// # <weight>
// Despite iterating over a list of locks, they are limited by the number of
// lock IDs, which means the number of runtime modules that intend to use and create locks.
// # </weight>
fn ensure_can_withdraw(
who: &T::AccountId,
_amount: T::Balance,
+8
View File
@@ -120,6 +120,10 @@ decl_module! {
Self::deposit_event(RawEvent::MemberExecuted(proposal_hash, ok));
}
/// # <weight>
/// - Bounded storage reads and writes.
/// - Argument `threshold` has bearing on weight.
/// # </weight>
fn propose(origin, #[compact] threshold: MemberCount, proposal: Box<<T as Trait>::Proposal>) {
let who = ensure_signed(origin)?;
@@ -145,6 +149,10 @@ decl_module! {
}
}
/// # <weight>
/// - Bounded storage read and writes.
/// - Will be slightly heavier if the proposal is approved / disapproved after the vote.
/// # </weight>
fn vote(origin, proposal: T::Hash, #[compact] index: ProposalIndex, approve: bool) {
let who = ensure_signed(origin)?;
+30
View File
@@ -171,6 +171,12 @@ decl_module! {
///
/// Note that any trailing `false` votes in `votes` is ignored; In approval voting, not voting for a candidate
/// and voting false, are equal.
///
/// # <weight>
/// - O(1).
/// - Two extra DB entries, one DB change.
/// - Argument `votes` is limited in length to number of candidates.
/// # </weight>
fn set_approvals(origin, votes: Vec<bool>, #[compact] index: VoteIndex, hint: SetIndex) -> Result {
let who = ensure_signed(origin)?;
Self::do_set_approvals(who, votes, index, hint)
@@ -178,6 +184,10 @@ decl_module! {
/// Set candidate approvals from a proxy. Approval slots stay valid as long as candidates in those slots
/// are registered.
///
/// # <weight>
/// - Same as `set_approvals` with one additional storage read.
/// # </weight>
fn proxy_set_approvals(origin, votes: Vec<bool>, #[compact] index: VoteIndex, hint: SetIndex) -> Result {
let who = <democracy::Module<T>>::proxy(ensure_signed(origin)?).ok_or("not a proxy")?;
Self::do_set_approvals(who, votes, index, hint)
@@ -190,6 +200,11 @@ decl_module! {
/// Both indices must be provided as explained in [`voter_at`] function.
///
/// May be called by anyone. Returns the voter deposit to `signed`.
///
/// # <weight>
/// - O(1).
/// - Two fewer DB entries, one DB change.
/// # </weight>
fn reap_inactive_voter(
origin,
#[compact] reporter_index: u32,
@@ -258,6 +273,11 @@ decl_module! {
/// The index must be provided as explained in [`voter_at`] function.
///
/// Also removes the lock on the balance of the voter. See [`do_set_approvals()`].
///
/// # <weight>
/// - O(1).
/// - Two fewer DB entries, one DB change.
/// # </weight>
fn retract_voter(origin, #[compact] index: u32) {
let who = ensure_signed(origin)?;
@@ -280,6 +300,11 @@ decl_module! {
/// it will NOT have any usable funds to pass candidacy bond and must first retract.
/// Note that setting approvals will lock the entire balance of the voter until
/// retraction or being reported.
///
/// # <weight>
/// - Independent of input.
/// - Three DB changes.
/// # </weight>
fn submit_candidacy(origin, #[compact] slot: u32) {
let who = ensure_signed(origin)?;
@@ -310,6 +335,11 @@ decl_module! {
/// Claim that `signed` is one of the top Self::carry_count() + current_vote().1 candidates.
/// Only works if the `block_number >= current_vote().0` and `< current_vote().0 + presentation_duration()`
/// `signed` should have at least
///
/// # <weight>
/// - O(voters) compute.
/// - One DB change.
/// # </weight>
fn present_winner(
origin,
candidate: <T::Lookup as StaticLookup>::Source,
+40
View File
@@ -321,6 +321,11 @@ decl_module! {
fn deposit_event<T>() = default;
/// Propose a sensitive action to be taken.
///
/// # <weight>
/// - O(1).
/// - Two DB changes, one DB entry.
/// # </weight>
fn propose(origin,
proposal: Box<T::Proposal>,
#[compact] value: BalanceOf<T>
@@ -343,6 +348,11 @@ decl_module! {
}
/// Propose a sensitive action to be taken.
///
/// # <weight>
/// - O(1).
/// - One DB entry.
/// # </weight>
fn second(origin, #[compact] proposal: PropIndex) {
let who = ensure_signed(origin)?;
let mut deposit = Self::deposit_of(proposal)
@@ -355,6 +365,11 @@ decl_module! {
/// Vote in a referendum. If `vote.is_aye()`, the vote is to enact the proposal;
/// otherwise it is a vote to keep the status quo.
///
/// # <weight>
/// - O(1).
/// - One DB change, one DB entry.
/// # </weight>
fn vote(origin,
#[compact] ref_index: ReferendumIndex,
vote: Vote
@@ -365,6 +380,11 @@ decl_module! {
/// Vote in a referendum on behalf of a stash. If `vote.is_aye()`, the vote is to enact
/// the proposal; otherwise it is a vote to keep the status quo.
///
/// # <weight>
/// - O(1).
/// - One DB change, one DB entry.
/// # </weight>
fn proxy_vote(origin,
#[compact] ref_index: ReferendumIndex,
vote: Vote
@@ -492,6 +512,10 @@ decl_module! {
}
/// Specify a proxy. Called by the stash.
///
/// # <weight>
/// - One extra DB entry.
/// # </weight>
fn set_proxy(origin, proxy: T::AccountId) {
let who = ensure_signed(origin)?;
ensure!(!<Proxy<T>>::exists(&proxy), "already a proxy");
@@ -499,12 +523,20 @@ decl_module! {
}
/// Clear the proxy. Called by the proxy.
///
/// # <weight>
/// - One DB clear.
/// # </weight>
fn resign_proxy(origin) {
let who = ensure_signed(origin)?;
<Proxy<T>>::remove(who);
}
/// Clear the proxy. Called by the stash.
///
/// # <weight>
/// - One DB clear.
/// # </weight>
fn remove_proxy(origin, proxy: T::AccountId) {
let who = ensure_signed(origin)?;
ensure!(&Self::proxy(&proxy).ok_or("not a proxy")? == &who, "wrong proxy");
@@ -512,6 +544,10 @@ decl_module! {
}
/// Delegate vote.
///
/// # <weight>
/// - One extra DB entry.
/// # </weight>
pub fn delegate(origin, to: T::AccountId, conviction: Conviction) {
let who = ensure_signed(origin)?;
<Delegations<T>>::insert(who.clone(), (to.clone(), conviction));
@@ -527,6 +563,10 @@ decl_module! {
}
/// Undelegate vote.
///
/// # <weight>
/// - O(1).
/// # </weight>
fn undelegate(origin) {
let who = ensure_signed(origin)?;
ensure!(<Delegations<T>>::exists(&who), "not delegated");
+15
View File
@@ -156,6 +156,21 @@ impl<T: Trait> Module<T> {
}
impl<T: Trait> OnNewAccount<T::AccountId> for Module<T> {
// Implementation of the config type managing the creation of new accounts.
// See Balances module for a concrete example.
//
// # <weight>
// - Independent of the arguments.
// - Given the correct value of `Self::next_enum_set`, it always has a limited
// number of reads and writes and no complex computation.
//
// As for storage, calling this function with _non-dead-indices_ will linearly grow the length of
// of `Self::enum_set`. Appropriate economic incentives should exist to make callers of this
// function provide a `who` argument that reclaims a dead account.
//
// At the time of this writing, only the Balances module calls this function upon creation
// of new accounts.
// # </weight>
fn on_new_account(who: &T::AccountId) {
let enum_set_size = Self::enum_set_size();
let next_set_index = Self::next_enum_set();
+13 -1
View File
@@ -161,8 +161,16 @@ decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
fn deposit_event<T>() = default;
/// Sets the session key of a validator (function caller) to `key`.
/// Sets the session key of the function caller to `key`.
/// Allows an account to set its session key prior to becoming a validator.
/// This doesn't take effect until the next session.
///
/// The dispatch origin of this function must be signed.
///
/// # <weight>
/// - O(1).
/// - One extra DB entry.
/// # </weight>
fn set_key(origin, key: T::SessionKey) {
let who = ensure_signed(origin)?;
// set new value for next session
@@ -170,11 +178,15 @@ decl_module! {
}
/// Set a new session length. Won't kick in until the next session change (at current length).
///
/// Dispatch origin of this call must be _root_.
fn set_length(#[compact] new: T::BlockNumber) {
<NextSessionLength<T>>::put(new);
}
/// Forces a new session.
///
/// Dispatch origin of this call must be _root_.
fn force_new_session(apply_rewards: bool) -> Result {
Self::apply_force_new_session(apply_rewards)
}
+77 -3
View File
@@ -155,7 +155,7 @@
//!
//! The term [`SlotStake`](./struct.Module.html#method.slot_stake) will be used throughout this section. It refers
//! to a value calculated at the end of each era, containing the _minimum value at stake among all validators._
//! Note that a validator's value at stake might be a combination of The validator's own stake
//! Note that a validator's value at stake might be a combination of the validator's own stake
//! and the votes it received. See [`Exposure`](./struct.Exposure.html) for more details.
//!
//! ### Reward Calculation
@@ -226,7 +226,7 @@
//!
//! The election algorithm, aside from electing the validators with the most stake value and votes, tries to divide
//! the nominator votes among candidates in an equal manner. To further assure this, an optional post-processing
//! can be applied that iteractively normalizes the nominator staked values until the total difference among
//! can be applied that iteratively normalizes the nominator staked values until the total difference among
//! votes of a particular nominator are less than a threshold.
//!
//! ## GenesisConfig
@@ -569,6 +569,19 @@ decl_module! {
/// account that controls it.
///
/// The dispatch origin for this call must be _Signed_ by the stash account.
///
/// # <weight>
/// - Independent of the arguments. Moderate complexity.
/// - O(1).
/// - Three extra DB entries.
///
/// NOTE: Two of the storage writes (`Self::bonded`, `Self::payee`) are _never_ cleaned unless
/// the `origin` falls below _existential deposit_ and gets removed as dust.
///
/// NOTE: At the moment, there are no financial restrictions to bond
/// (which creates a bunch of storage items for an account). In essence, nothing prevents many accounts from
/// spamming `Staking` storage by bonding 1 UNIT. See test case: `bond_with_no_staked_value`.
/// # </weight>
fn bond(origin, controller: <T::Lookup as StaticLookup>::Source, #[compact] value: BalanceOf<T>, payee: RewardDestination) {
let stash = ensure_signed(origin)?;
@@ -583,7 +596,7 @@ decl_module! {
}
// You're auto-bonded forever, here. We might improve this by only bonding when
// you actually validate/nominate.
// you actually validate/nominate and remove once you unbond __everything__.
<Bonded<T>>::insert(&stash, controller.clone());
<Payee<T>>::insert(&stash, payee);
@@ -598,6 +611,12 @@ decl_module! {
/// Use this if there are additional funds in your stash account that you wish to bond.
///
/// The dispatch origin for this call must be _Signed_ by the stash, not the controller.
///
/// # <weight>
/// - Independent of the arguments. Insignificant complexity.
/// - O(1).
/// - One DB entry.
/// # </weight>
fn bond_extra(origin, #[compact] max_additional: BalanceOf<T>) {
let stash = ensure_signed(origin)?;
@@ -628,6 +647,15 @@ decl_module! {
/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
///
/// See also [`Call::withdraw_unbonded`].
///
/// # <weight>
/// - Independent of the arguments. Limited but potentially exploitable complexity.
/// - Contains a limited number of reads.
/// - Each call (requires the remainder of the bonded balance to be above `minimum_balance`)
/// will cause a new entry to be inserted into a vector (`Ledger.unlocking`) kept in storage.
/// The only way to clean the aforementioned storage item is also user-controlled via `withdraw_unbonded`.
/// - One DB entry.
/// </weight>
fn unbond(origin, #[compact] value: BalanceOf<T>) {
let controller = ensure_signed(origin)?;
let mut ledger = Self::ledger(&controller).ok_or("not a controller")?;
@@ -661,6 +689,14 @@ decl_module! {
/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
///
/// See also [`Call::unbond`].
///
/// # <weight>
/// - Could be dependent on the `origin` argument and how much `unlocking` chunks exist. It implies
/// `consolidate_unlocked` which loops over `Ledger.unlocking`, which is indirectly
/// user-controlled. See [`unbond`] for more detail.
/// - Contains a limited number of reads, yet the size of which could be large based on `ledger`.
/// - Writes are limited to the `origin` account key.
/// # </weight>
fn withdraw_unbonded(origin) {
let controller = ensure_signed(origin)?;
let ledger = Self::ledger(&controller).ok_or("not a controller")?;
@@ -673,6 +709,12 @@ decl_module! {
/// Effects will be felt at the beginning of the next era.
///
/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
///
/// # <weight>
/// - Independent of the arguments. Insignificant complexity.
/// - Contains a limited number of reads.
/// - Writes are limited to the `origin` account key.
/// # </weight>
fn validate(origin, prefs: ValidatorPrefs<BalanceOf<T>>) {
let controller = ensure_signed(origin)?;
let ledger = Self::ledger(&controller).ok_or("not a controller")?;
@@ -687,6 +729,12 @@ decl_module! {
/// Effects will be felt at the beginning of the next era.
///
/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
///
/// # <weight>
/// - The transaction's complexity is proportional to the size of `targets`,
/// which is capped at `MAX_NOMINATIONS`.
/// - Both the reads and writes follow a similar pattern.
/// # </weight>
fn nominate(origin, targets: Vec<<T::Lookup as StaticLookup>::Source>) {
let controller = ensure_signed(origin)?;
let ledger = Self::ledger(&controller).ok_or("not a controller")?;
@@ -706,6 +754,12 @@ decl_module! {
/// Effects will be felt at the beginning of the next era.
///
/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
///
/// # <weight>
/// - Independent of the arguments. Insignificant complexity.
/// - Contains one read.
/// - Writes are limited to the `origin` account key.
/// # </weight>
fn chill(origin) {
let controller = ensure_signed(origin)?;
let ledger = Self::ledger(&controller).ok_or("not a controller")?;
@@ -719,6 +773,12 @@ decl_module! {
/// Effects will be felt at the beginning of the next era.
///
/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
///
/// # <weight>
/// - Independent of the arguments. Insignificant complexity.
/// - Contains a limited number of reads.
/// - Writes are limited to the `origin` account key.
/// # </weight>
fn set_payee(origin, payee: RewardDestination) {
let controller = ensure_signed(origin)?;
let ledger = Self::ledger(&controller).ok_or("not a controller")?;
@@ -731,6 +791,12 @@ decl_module! {
/// Effects will be felt at the beginning of the next era.
///
/// The dispatch origin for this call must be _Signed_ by the stash, not the controller.
///
/// # <weight>
/// - Independent of the arguments. Insignificant complexity.
/// - Contains a limited number of reads.
/// - Writes are limited to the `origin` account key.
/// # </weight>
fn set_controller(origin, controller: <T::Lookup as StaticLookup>::Source) {
let stash = ensure_signed(origin)?;
let old_controller = Self::bonded(&stash).ok_or("not a stash")?;
@@ -744,6 +810,8 @@ decl_module! {
}
}
// ----- Root calls.
/// Set the number of sessions in an era.
fn set_sessions_per_era(#[compact] new: T::BlockNumber) {
<NextSessionsPerEra<T>>::put(new);
@@ -761,6 +829,12 @@ decl_module! {
/// Force there to be a new era. This also forces a new session immediately after.
/// `apply_rewards` should be true for validators to get the session reward.
///
/// # <weight>
/// - Independent of the arguments.
/// - Triggers the Phragmen election. Expensive but not user-controlled.
/// - Depends on state: `O(|edges| * |validators|)`.
/// # </weight>
fn force_new_era(apply_rewards: bool) -> Result {
Self::apply_force_new_era(apply_rewards)
}
+1 -10
View File
@@ -1669,20 +1669,15 @@ fn bond_with_no_staked_value() {
System::set_block_number(1);
Session::check_rotate_session(System::block_number());
// Not elected even though we want 3.
assert_eq_uvec!(Session::validators(), vec![30, 20, 10]);
// min of 10, 20 and 30 (30 got a payout into staking so it raised it from 1 to 11).
assert_eq!(Staking::slot_stake(), 11);
// let's make the stingy one elected.
// make the stingy one elected.
assert_ok!(Staking::bond(Origin::signed(3), 4, 500, RewardDestination::Controller));
assert_ok!(Staking::nominate(Origin::signed(4), vec![1]));
// no rewards paid to 2 and 4 yet
assert_eq!(Balances::free_balance(&2), initial_balance_2);
assert_eq!(Balances::free_balance(&4), initial_balance_4);
System::set_block_number(2);
Session::check_rotate_session(System::block_number());
@@ -1692,10 +1687,6 @@ fn bond_with_no_staked_value() {
// New slot stake.
assert_eq!(Staking::slot_stake(), 501);
// no rewards paid to 2 and 4 yet
assert_eq!(Balances::free_balance(&2), initial_balance_2);
assert_eq!(Balances::free_balance(&4), initial_balance_4);
System::set_block_number(3);
Session::check_rotate_session(System::block_number());
+12
View File
@@ -110,6 +110,12 @@ decl_module! {
/// Authenticates the sudo key and dispatches a function call with `Root` origin.
///
/// The dispatch origin for this call must be _Signed_.
///
/// # <weight>
/// - O(1).
/// - Limited storage reads.
/// - No DB writes.
/// # </weight>
fn sudo(origin, proposal: Box<T::Proposal>) {
// This is a public call, so we ensure that the origin is some signed account.
let sender = ensure_signed(origin)?;
@@ -129,6 +135,12 @@ decl_module! {
/// Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo key.
///
/// The dispatch origin for this call must be _Signed_.
///
/// # <weight>
/// - O(1).
/// - Limited storage reads.
/// - One DB change.
/// # </weight>
fn set_key(origin, new: <T::Lookup as StaticLookup>::Source) {
// This is a public call, so we ensure that the origin is some signed account.
let sender = ensure_signed(origin)?;
+1 -1
View File
@@ -475,7 +475,7 @@ impl<T: Trait> Module<T> {
/// Deposits an event into this block's event record adding this event
/// to the corresponding topic indexes.
///
/// This will update storage entries that correpond to the specified topics.
/// This will update storage entries that correspond to the specified topics.
/// It is expected that light-clients could subscribe to this topics.
pub fn deposit_event_indexed(topics: &[T::Hash], event: T::Event) {
let extrinsic_index = Self::extrinsic_index();
+18
View File
@@ -110,6 +110,12 @@ decl_module! {
/// Put forward a suggestion for spending. A deposit proportional to the value
/// is reserved and slashed if the proposal is rejected. It is returned once the
/// proposal is awarded.
///
/// # <weight>
/// - O(1).
/// - Limited storage reads.
/// - One DB change, one extra DB entry.
/// # </weight>
fn propose_spend(
origin,
#[compact] value: BalanceOf<T>,
@@ -149,6 +155,12 @@ decl_module! {
}
/// Reject a proposed spend. The original deposit will be slashed.
///
/// # <weight>
/// - O(1).
/// - Limited storage reads.
/// - One DB clear.
/// # </weight>
fn reject_proposal(origin, #[compact] proposal_id: ProposalIndex) {
T::RejectOrigin::ensure_origin(origin)?;
let proposal = <Proposals<T>>::take(proposal_id).ok_or("No proposal at that index")?;
@@ -160,6 +172,12 @@ decl_module! {
/// Approve a proposal. At a later time, the proposal will be allocated to the beneficiary
/// and the original deposit will be returned.
///
/// # <weight>
/// - O(1).
/// - Limited storage reads.
/// - One DB change.
/// # </weight>
fn approve_proposal(origin, #[compact] proposal_id: ProposalIndex) {
T::ApproveOrigin::ensure_origin(origin)?;