// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see .
//! Democracy pallet benchmarking.
use super::*;
use frame_benchmarking::{benchmarks, account};
use frame_support::traits::{Currency, Get, EnsureOrigin};
use frame_system::{RawOrigin, Module as System, self};
use sp_runtime::traits::{Bounded, One};
use crate::Module as Democracy;
const SEED: u32 = 0;
const MAX_USERS: u32 = 1000;
const MAX_REFERENDUMS: u32 = 100;
const MAX_PROPOSALS: u32 = 100;
const MAX_SECONDERS: u32 = 100;
const MAX_VETOERS: u32 = 100;
const MAX_BYTES: u32 = 16_384;
fn funded_account(name: &'static str, index: u32) -> T::AccountId {
let caller: T::AccountId = account(name, index, SEED);
T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value());
caller
}
fn add_proposal(n: u32) -> Result {
let other = funded_account::("proposer", n);
let value = T::MinimumDeposit::get();
let proposal_hash: T::Hash = T::Hashing::hash_of(&n);
Democracy::::propose(RawOrigin::Signed(other).into(), proposal_hash, value.into())?;
Ok(proposal_hash)
}
fn add_referendum(n: u32) -> Result {
let proposal_hash = add_proposal::(n)?;
let vote_threshold = VoteThreshold::SimpleMajority;
Democracy::::inject_referendum(
0.into(),
proposal_hash,
vote_threshold,
0.into(),
);
let referendum_index: ReferendumIndex = ReferendumCount::get() - 1;
let _ = T::Scheduler::schedule_named(
(DEMOCRACY_ID, referendum_index),
0.into(),
None,
63,
Call::enact_proposal(proposal_hash, referendum_index).into(),
);
Ok(referendum_index)
}
fn account_vote() -> AccountVote> {
let v = Vote {
aye: true,
conviction: Conviction::Locked1x,
};
AccountVote::Standard {
vote: v,
balance: BalanceOf::::one(),
}
}
fn open_activate_proxy(u: u32) -> Result {
let caller = funded_account::("caller", u);
let proxy = funded_account::("proxy", u);
Democracy::::open_proxy(RawOrigin::Signed(proxy.clone()).into(), caller.clone())?;
Democracy::::activate_proxy(RawOrigin::Signed(caller).into(), proxy.clone())?;
Ok(proxy)
}
benchmarks! {
_ { }
propose {
let p in 1 .. MAX_PROPOSALS;
// Add p proposals
for i in 0 .. p {
add_proposal::(i)?;
}
let caller = funded_account::("caller", 0);
let proposal_hash: T::Hash = T::Hashing::hash_of(&p);
let value = T::MinimumDeposit::get();
}: _(RawOrigin::Signed(caller), proposal_hash, value.into())
second {
let s in 0 .. MAX_SECONDERS;
// Create s existing "seconds"
for i in 0 .. s {
let seconder = funded_account::("seconder", i);
Democracy::::second(RawOrigin::Signed(seconder).into(), 0)?;
}
let caller = funded_account::("caller", 0);
let proposal_hash = add_proposal::(s)?;
}: _(RawOrigin::Signed(caller), 0)
vote {
let r in 1 .. MAX_REFERENDUMS;
let caller = funded_account::("caller", 0);
let account_vote = account_vote::();
for i in 0 .. r {
let ref_idx = add_referendum::(i)?;
Democracy::::vote(RawOrigin::Signed(caller.clone()).into(), ref_idx, account_vote.clone())?;
}
let referendum_index = r - 1;
}: _(RawOrigin::Signed(caller), referendum_index, account_vote)
proxy_vote {
let r in 1 .. MAX_REFERENDUMS;
let caller = funded_account::("caller", r);
let proxy = open_activate_proxy::(r)?;
let account_vote = account_vote::();
for i in 0 .. r {
let ref_idx = add_referendum::(i)?;
Democracy::::vote(RawOrigin::Signed(caller.clone()).into(), ref_idx, account_vote.clone())?;
}
let referendum_index = r - 1;
}: _(RawOrigin::Signed(proxy), referendum_index, account_vote)
emergency_cancel {
let u in 1 .. MAX_USERS;
let referendum_index = add_referendum::(u)?;
let origin = T::CancellationOrigin::successful_origin();
let call = Call::::emergency_cancel(referendum_index);
}: {
let _ = call.dispatch(origin)?;
}
external_propose {
let u in 1 .. MAX_USERS;
let origin = T::ExternalOrigin::successful_origin();
let proposal_hash = T::Hashing::hash_of(&u);
let call = Call::::external_propose(proposal_hash);
}: {
let _ = call.dispatch(origin)?;
}
external_propose_majority {
let u in 1 .. MAX_USERS;
let origin = T::ExternalMajorityOrigin::successful_origin();
let proposal_hash = T::Hashing::hash_of(&u);
let call = Call::::external_propose_majority(proposal_hash);
}: {
let _ = call.dispatch(origin)?;
}
external_propose_default {
let u in 1 .. MAX_USERS;
let origin = T::ExternalDefaultOrigin::successful_origin();
let proposal_hash = T::Hashing::hash_of(&u);
let call = Call::::external_propose_default(proposal_hash);
}: {
let _ = call.dispatch(origin)?;
}
fast_track {
let u in 1 .. MAX_USERS;
let origin_propose = T::ExternalDefaultOrigin::successful_origin();
let proposal_hash: T::Hash = T::Hashing::hash_of(&u);
Democracy::::external_propose_default(origin_propose, proposal_hash.clone())?;
let origin_fast_track = T::FastTrackOrigin::successful_origin();
let voting_period = T::FastTrackVotingPeriod::get();
let delay = 0;
let call = Call::::fast_track(proposal_hash, voting_period.into(), delay.into());
}: {
let _ = call.dispatch(origin_fast_track)?;
}
veto_external {
// Existing veto-ers
let v in 0 .. MAX_VETOERS;
let proposal_hash: T::Hash = T::Hashing::hash_of(&v);
let origin_propose = T::ExternalDefaultOrigin::successful_origin();
Democracy::::external_propose_default(origin_propose, proposal_hash.clone())?;
let mut vetoers: Vec = Vec::new();
for i in 0 .. v {
vetoers.push(account("vetoer", i, SEED));
}
Blacklist::::insert(proposal_hash, (T::BlockNumber::zero(), vetoers));
let call = Call::::veto_external(proposal_hash);
let origin = T::VetoOrigin::successful_origin();
}: {
let _ = call.dispatch(origin)?;
}
cancel_referendum {
let u in 1 .. MAX_USERS;
let referendum_index = add_referendum::(u)?;
}: _(RawOrigin::Root, referendum_index)
cancel_queued {
let u in 1 .. MAX_USERS;
let referendum_index = add_referendum::(u)?;
}: _(RawOrigin::Root, referendum_index)
open_proxy {
let u in 1 .. MAX_USERS;
let caller: T::AccountId = funded_account::("caller", u);
let proxy: T::AccountId = funded_account::("proxy", u);
}: _(RawOrigin::Signed(proxy), caller)
activate_proxy {
let u in 1 .. MAX_USERS;
let caller: T::AccountId = funded_account::("caller", u);
let proxy: T::AccountId = funded_account::("proxy", u);
Democracy::::open_proxy(RawOrigin::Signed(proxy.clone()).into(), caller.clone())?;
}: _(RawOrigin::Signed(caller), proxy)
close_proxy {
let u in 1 .. MAX_USERS;
let proxy = open_activate_proxy::(u)?;
}: _(RawOrigin::Signed(proxy))
deactivate_proxy {
let u in 1 .. MAX_USERS;
let caller = funded_account::("caller", u);
let proxy = open_activate_proxy::(u)?;
}: _(RawOrigin::Signed(caller), proxy)
delegate {
let u in 1 .. MAX_USERS;
let caller = funded_account::("caller", u);
let d: T::AccountId = funded_account::("delegate", u);
let balance = 1u32;
}: _(RawOrigin::Signed(caller), d.into(), Conviction::Locked1x, balance.into())
undelegate {
let r in 1 .. MAX_REFERENDUMS;
let other = funded_account::("other", 0);
let account_vote = account_vote::();
for i in 0 .. r {
let ref_idx = add_referendum::(i)?;
Democracy::::vote(RawOrigin::Signed(other.clone()).into(), ref_idx, account_vote.clone())?;
}
let delegator = funded_account::("delegator", r);
let conviction = Conviction::Locked1x;
let balance = 1u32;
Democracy::::delegate(RawOrigin::Signed(delegator.clone()).into(), other.clone().into(), conviction, balance.into())?;
}: _(RawOrigin::Signed(delegator))
clear_public_proposals {
let p in 0 .. MAX_PROPOSALS;
for i in 0 .. p {
add_proposal::(i)?;
}
}: _(RawOrigin::Root)
note_preimage {
// Num of bytes in encoded proposal
let b in 0 .. MAX_BYTES;
let caller = funded_account::("caller", b);
let encoded_proposal = vec![0; b as usize];
}: _(RawOrigin::Signed(caller), encoded_proposal)
note_imminent_preimage {
// Num of bytes in encoded proposal
let b in 0 .. MAX_BYTES;
// d + 1 to include the one we are testing
let encoded_proposal = vec![0; b as usize];
let proposal_hash = T::Hashing::hash(&encoded_proposal[..]);
let block_number = T::BlockNumber::one();
Preimages::::insert(&proposal_hash, PreimageStatus::Missing(block_number));
let caller = funded_account::("caller", b);
let encoded_proposal = vec![0; b as usize];
}: _(RawOrigin::Signed(caller), encoded_proposal)
reap_preimage {
// Num of bytes in encoded proposal
let b in 0 .. MAX_BYTES;
let encoded_proposal = vec![0; b as usize];
let proposal_hash = T::Hashing::hash(&encoded_proposal[..]);
let caller = funded_account::("caller", b);
Democracy::::note_preimage(RawOrigin::Signed(caller.clone()).into(), encoded_proposal.clone())?;
// We need to set this otherwise we get `Early` error.
let block_number = T::VotingPeriod::get() + T::EnactmentPeriod::get() + T::BlockNumber::one();
System::::set_block_number(block_number.into());
}: _(RawOrigin::Signed(caller), proposal_hash)
unlock {
let u in 1 .. MAX_USERS;
let caller = funded_account::("caller", u);
let locked_until = T::BlockNumber::zero();
Locks::::insert(&caller, locked_until);
T::Currency::extend_lock(
DEMOCRACY_ID,
&caller,
Bounded::max_value(),
WithdrawReason::Transfer.into()
);
let other = caller.clone();
}: _(RawOrigin::Signed(caller), other)
remove_vote {
let r in 1 .. MAX_REFERENDUMS;
let caller = funded_account::("caller", 0);
let account_vote = account_vote::();
for i in 0 .. r {
let ref_idx = add_referendum::(i)?;
Democracy::::vote(RawOrigin::Signed(caller.clone()).into(), ref_idx, account_vote.clone())?;
}
let referendum_index = r - 1;
}: _(RawOrigin::Signed(caller), referendum_index)
remove_other_vote {
let r in 1 .. MAX_REFERENDUMS;
let other = funded_account::("other", r);
let account_vote = account_vote::();
for i in 0 .. r {
let ref_idx = add_referendum::(i)?;
Democracy::::vote(RawOrigin::Signed(other.clone()).into(), ref_idx, account_vote.clone())?;
}
let referendum_index = r - 1;
ReferendumInfoOf::::insert(
referendum_index,
ReferendumInfo::Finished { end: T::BlockNumber::zero(), approved: true }
);
let caller = funded_account::("caller", r);
System::::set_block_number(T::EnactmentPeriod::get() * 10u32.into());
}: _(RawOrigin::Signed(caller), other, referendum_index)
proxy_delegate {
let u in 1 .. MAX_USERS;
let other: T::AccountId = account("other", u, SEED);
let proxy = open_activate_proxy::(u)?;
let conviction = Conviction::Locked1x;
let balance = 1u32;
}: _(RawOrigin::Signed(proxy), other, conviction, balance.into())
proxy_undelegate {
let r in 1 .. MAX_REFERENDUMS;
let other = funded_account::("other", 0);
let account_vote = account_vote::();
for i in 0 .. r {
let ref_idx = add_referendum::(i)?;
Democracy::::vote(RawOrigin::Signed(other.clone()).into(), ref_idx, account_vote.clone())?;
}
let proxy = open_activate_proxy::(r)?;
let conviction = Conviction::Locked1x;
let balance = 1u32;
Democracy::::proxy_delegate(RawOrigin::Signed(proxy.clone()).into(), other, conviction, balance.into())?;
}: _(RawOrigin::Signed(proxy))
proxy_remove_vote {
let u in 1 .. MAX_USERS;
let referendum_index = add_referendum::(u)?;
let account_vote = account_vote::();
let proxy = open_activate_proxy::(u)?;
Democracy::::proxy_vote(RawOrigin::Signed(proxy.clone()).into(), referendum_index, account_vote)?;
}: _(RawOrigin::Signed(proxy), referendum_index)
}