mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 14:11:09 +00:00
Bound uses of Call (#11649)
* Introduce preimages module in traits * Multisize Preimages * Len not actually necessary * Tweaks to the preimage API * Fixes * Get Scheduler building with new API * Scheduler tests pass * Bounded Scheduler 🎉 * Use Agenda holes and introduce IncompleteSince to avoid need to reschedule * Tests pass with new weight system * New benchmarks * Add missing file * Drop preimage when permenantly overeight * Drop preimage when permenantly overeight * Referenda uses latest preimage API * Testing ok * Adding tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add preimage migration Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Docs * Remove dbg * Refactor Democracy * Refactor Democracy * Add final MEL * Remove silly maps * Fixes * Minor refactor * Formatting * Fixes * Fixes * Fixes * Update frame/preimage/src/lib.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Add migrations to Democracy * WIP Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Resolve conflicts Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Revert "Resolve conflicts" This reverts commit 734d66d69e54553471ffa54fa52e3e304dc8f106. * Undo wrong resolves... Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * WIP Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Make compile Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * massage clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * clippy annoyance Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * clippy annoyance Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix benchmarks Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * add missing file * Test <Preimage as QueryPreimage> Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Clippy harassment Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixup tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove old stuff Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test <Scheduler as Anon> trait functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update pallet-ui tests Why is this needed? Should not be the case unless master is broken... Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More scheduler trait test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Apply review suggestion Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Beauty fixes Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add Scheduler test migration_v3_to_v4_works Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Merge fixup Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Keep referenda benchmarks instantiatable Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update weights Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use new scheduler weight functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use new democracy weight functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use weight compare functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update pallet-ui tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More renaming… Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More renaming… Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add comment Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Implement OnRuntimeUpgrade for scheduler::v3_to_v4 migration Put the migration into a proper `MigrateToV4` struct and implement the OnRuntimeUpgrade hooks for it. Also move the test to use that instead. This should make it easier for adding it to Polkadot. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Handle undecodable Agendas Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove trash Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use new OnRuntimeUpgrade functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fix test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix BoundedSlice::truncate_from Co-authored-by: jakoblell Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix pre_upgrade hook return values Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add more error logging Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Find too large preimages in the pre_upgrade hook Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test that too large Calls in agendas are ignored Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use new OnRuntimeUpgrade hooks Why did the CI not catch this?! Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * works fine - just more logs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix staking migration Causing issues on Kusama... Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix UI tests No idea why this is needed. This is actually undoing an earlier change. Maybe the CI has different rustc versions!? Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove multisig's Calls (#12072) * Remove multisig's Calls * Multisig: Fix tests and re-introduce reserve logic (#12241) * Fix tests and re-introduce reserve logic * fix benches * add todo * remove irrelevant bench * [Feature] Add a migration that drains and refunds stored calls (#12313) * [Feature] Add a migration that drains and refunds stored calls * migration fixes * fixes * address review comments * consume the whole block weight * fix assertions * license header * fix interface Co-authored-by: parity-processbot <> Co-authored-by: parity-processbot <> Co-authored-by: Roman Useinov <roman.useinov@gmail.com> * Fix test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix multisig benchmarks Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * ".git/.scripts/bench-bot.sh" pallet dev pallet_democracy * ".git/.scripts/bench-bot.sh" pallet dev pallet_scheduler * ".git/.scripts/bench-bot.sh" pallet dev pallet_preimage Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> Co-authored-by: parity-processbot <> Co-authored-by: Roman Useinov <roman.useinov@gmail.com>
This commit is contained in:
Generated
+4
@@ -5581,7 +5581,9 @@ dependencies = [
|
||||
"frame-benchmarking",
|
||||
"frame-support",
|
||||
"frame-system",
|
||||
"log",
|
||||
"pallet-balances",
|
||||
"pallet-preimage",
|
||||
"pallet-scheduler",
|
||||
"parity-scale-codec",
|
||||
"scale-info",
|
||||
@@ -5899,6 +5901,7 @@ dependencies = [
|
||||
"frame-benchmarking",
|
||||
"frame-support",
|
||||
"frame-system",
|
||||
"log",
|
||||
"pallet-balances",
|
||||
"parity-scale-codec",
|
||||
"scale-info",
|
||||
@@ -6065,6 +6068,7 @@ dependencies = [
|
||||
"frame-benchmarking",
|
||||
"frame-support",
|
||||
"frame-system",
|
||||
"log",
|
||||
"pallet-balances",
|
||||
"parity-scale-codec",
|
||||
"scale-info",
|
||||
|
||||
@@ -340,8 +340,6 @@ impl pallet_proxy::Config for Runtime {
|
||||
parameter_types! {
|
||||
pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) *
|
||||
RuntimeBlockWeights::get().max_block;
|
||||
// Retry a scheduled item every 10 blocks (1 minute) until the preimage exists.
|
||||
pub const NoPreimagePostponement: Option<u32> = Some(10);
|
||||
}
|
||||
|
||||
impl pallet_scheduler::Config for Runtime {
|
||||
@@ -351,11 +349,10 @@ impl pallet_scheduler::Config for Runtime {
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type MaximumWeight = MaximumSchedulerWeight;
|
||||
type ScheduleOrigin = EnsureRoot<AccountId>;
|
||||
type MaxScheduledPerBlock = ConstU32<50>;
|
||||
type MaxScheduledPerBlock = ConstU32<512>;
|
||||
type WeightInfo = pallet_scheduler::weights::SubstrateWeight<Runtime>;
|
||||
type OriginPrivilegeCmp = EqualPrivilegeOnly;
|
||||
type PreimageProvider = Preimage;
|
||||
type NoPreimagePostponement = NoPreimagePostponement;
|
||||
type Preimages = Preimage;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
@@ -370,7 +367,6 @@ impl pallet_preimage::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Currency = Balances;
|
||||
type ManagerOrigin = EnsureRoot<AccountId>;
|
||||
type MaxSize = PreimageMaxSize;
|
||||
type BaseDeposit = PreimageBaseDeposit;
|
||||
type ByteDeposit = PreimageByteDeposit;
|
||||
}
|
||||
@@ -862,6 +858,7 @@ impl pallet_referenda::Config for Runtime {
|
||||
type UndecidingTimeout = UndecidingTimeout;
|
||||
type AlarmInterval = AlarmInterval;
|
||||
type Tracks = TracksInfo;
|
||||
type Preimages = Preimage;
|
||||
}
|
||||
|
||||
impl pallet_referenda::Config<pallet_referenda::Instance2> for Runtime {
|
||||
@@ -881,6 +878,7 @@ impl pallet_referenda::Config<pallet_referenda::Instance2> for Runtime {
|
||||
type UndecidingTimeout = UndecidingTimeout;
|
||||
type AlarmInterval = AlarmInterval;
|
||||
type Tracks = TracksInfo;
|
||||
type Preimages = Preimage;
|
||||
}
|
||||
|
||||
impl pallet_ranked_collective::Config for Runtime {
|
||||
@@ -909,7 +907,6 @@ parameter_types! {
|
||||
}
|
||||
|
||||
impl pallet_democracy::Config for Runtime {
|
||||
type Proposal = RuntimeCall;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Currency = Balances;
|
||||
type EnactmentPeriod = EnactmentPeriod;
|
||||
@@ -949,14 +946,15 @@ impl pallet_democracy::Config for Runtime {
|
||||
// only do it once and it lasts only for the cool-off period.
|
||||
type VetoOrigin = pallet_collective::EnsureMember<AccountId, TechnicalCollective>;
|
||||
type CooloffPeriod = CooloffPeriod;
|
||||
type PreimageByteDeposit = PreimageByteDeposit;
|
||||
type OperationalPreimageOrigin = pallet_collective::EnsureMember<AccountId, CouncilCollective>;
|
||||
type Slash = Treasury;
|
||||
type Scheduler = Scheduler;
|
||||
type PalletsOrigin = OriginCaller;
|
||||
type MaxVotes = ConstU32<100>;
|
||||
type WeightInfo = pallet_democracy::weights::SubstrateWeight<Runtime>;
|
||||
type MaxProposals = MaxProposals;
|
||||
type Preimages = Preimage;
|
||||
type MaxDeposits = ConstU32<100>;
|
||||
type MaxBlacklisted = ConstU32<100>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -819,7 +819,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
value: BalanceOf<T, I>,
|
||||
) -> DispatchResult {
|
||||
let bounded_description: BoundedVec<_, _> =
|
||||
description.try_into().map_err(|()| Error::<T, I>::ReasonTooBig)?;
|
||||
description.try_into().map_err(|_| Error::<T, I>::ReasonTooBig)?;
|
||||
ensure!(value >= T::BountyValueMinimum::get(), Error::<T, I>::InvalidValue);
|
||||
|
||||
let index = Self::bounty_count();
|
||||
|
||||
@@ -340,7 +340,7 @@ where
|
||||
let queue: Vec<DeletedContract> = (0..T::DeletionQueueDepth::get())
|
||||
.map(|_| DeletedContract { trie_id: TrieId::default() })
|
||||
.collect();
|
||||
let bounded: BoundedVec<_, _> = queue.try_into().unwrap();
|
||||
let bounded: BoundedVec<_, _> = queue.try_into().map_err(|_| ()).unwrap();
|
||||
<DeletionQueue<T>>::put(bounded);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
Err(i) => {
|
||||
votes
|
||||
.try_insert(i, (poll_index, vote))
|
||||
.map_err(|()| Error::<T, I>::MaxVotesReached)?;
|
||||
.map_err(|_| Error::<T, I>::MaxVotesReached)?;
|
||||
},
|
||||
}
|
||||
// Shouldn't be possible to fail, but we handle it gracefully.
|
||||
|
||||
@@ -24,11 +24,13 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys
|
||||
sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" }
|
||||
sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" }
|
||||
sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" }
|
||||
sp-core = { version = "6.0.0", default-features = false, path = "../../primitives/core" }
|
||||
log = { version = "0.4.17", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
pallet-balances = { version = "4.0.0-dev", path = "../balances" }
|
||||
pallet-scheduler = { version = "4.0.0-dev", path = "../scheduler" }
|
||||
sp-core = { version = "6.0.0", path = "../../primitives/core" }
|
||||
pallet-preimage = { version = "4.0.0-dev", path = "../preimage" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
@@ -42,6 +44,7 @@ std = [
|
||||
"sp-io/std",
|
||||
"sp-runtime/std",
|
||||
"sp-std/std",
|
||||
"sp-core/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"frame-benchmarking/runtime-benchmarks",
|
||||
@@ -49,4 +52,4 @@ runtime-benchmarks = [
|
||||
"frame-system/runtime-benchmarks",
|
||||
"sp-runtime/runtime-benchmarks",
|
||||
]
|
||||
try-runtime = ["frame-support/try-runtime"]
|
||||
try-runtime = ["frame-support/try-runtime",]
|
||||
|
||||
@@ -22,24 +22,16 @@ use super::*;
|
||||
use frame_benchmarking::{account, benchmarks, whitelist_account};
|
||||
use frame_support::{
|
||||
assert_noop, assert_ok,
|
||||
codec::Decode,
|
||||
traits::{
|
||||
schedule::DispatchTime, Currency, EnsureOrigin, Get, OnInitialize, UnfilteredDispatchable,
|
||||
},
|
||||
traits::{Currency, EnsureOrigin, Get, OnInitialize, UnfilteredDispatchable},
|
||||
};
|
||||
use frame_system::{Pallet as System, RawOrigin};
|
||||
use sp_runtime::traits::{BadOrigin, Bounded, One};
|
||||
use frame_system::RawOrigin;
|
||||
use sp_core::H256;
|
||||
use sp_runtime::{traits::Bounded, BoundedVec};
|
||||
|
||||
use crate::Pallet as Democracy;
|
||||
|
||||
const REFERENDUM_COUNT_HINT: u32 = 10;
|
||||
const SEED: u32 = 0;
|
||||
const MAX_REFERENDUMS: u32 = 99;
|
||||
const MAX_SECONDERS: u32 = 100;
|
||||
const MAX_BYTES: u32 = 16_384;
|
||||
|
||||
fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
|
||||
frame_system::Pallet::<T>::assert_last_event(generic_event.into());
|
||||
}
|
||||
|
||||
fn funded_account<T: Config>(name: &'static str, index: u32) -> T::AccountId {
|
||||
let caller: T::AccountId = account(name, index, SEED);
|
||||
@@ -49,37 +41,32 @@ fn funded_account<T: Config>(name: &'static str, index: u32) -> T::AccountId {
|
||||
caller
|
||||
}
|
||||
|
||||
fn add_proposal<T: Config>(n: u32) -> Result<T::Hash, &'static str> {
|
||||
let other = funded_account::<T>("proposer", n);
|
||||
let value = T::MinimumDeposit::get();
|
||||
let proposal_hash: T::Hash = T::Hashing::hash_of(&n);
|
||||
|
||||
Democracy::<T>::propose(RawOrigin::Signed(other).into(), proposal_hash, value)?;
|
||||
|
||||
Ok(proposal_hash)
|
||||
fn make_proposal<T: Config>(n: u32) -> BoundedCallOf<T> {
|
||||
let call: CallOf<T> = frame_system::Call::remark { remark: n.encode() }.into();
|
||||
<T as Config>::Preimages::bound(call).unwrap()
|
||||
}
|
||||
|
||||
fn add_referendum<T: Config>(n: u32) -> Result<ReferendumIndex, &'static str> {
|
||||
let proposal_hash: T::Hash = T::Hashing::hash_of(&n);
|
||||
let vote_threshold = VoteThreshold::SimpleMajority;
|
||||
fn add_proposal<T: Config>(n: u32) -> Result<H256, &'static str> {
|
||||
let other = funded_account::<T>("proposer", n);
|
||||
let value = T::MinimumDeposit::get();
|
||||
let proposal = make_proposal::<T>(n);
|
||||
Democracy::<T>::propose(RawOrigin::Signed(other).into(), proposal.clone(), value)?;
|
||||
Ok(proposal.hash())
|
||||
}
|
||||
|
||||
Democracy::<T>::inject_referendum(
|
||||
T::LaunchPeriod::get(),
|
||||
proposal_hash,
|
||||
vote_threshold,
|
||||
0u32.into(),
|
||||
);
|
||||
let referendum_index: ReferendumIndex = ReferendumCount::<T>::get() - 1;
|
||||
T::Scheduler::schedule_named(
|
||||
(DEMOCRACY_ID, referendum_index).encode(),
|
||||
DispatchTime::At(2u32.into()),
|
||||
None,
|
||||
63,
|
||||
frame_system::RawOrigin::Root.into(),
|
||||
Call::enact_proposal { proposal_hash, index: referendum_index }.into(),
|
||||
fn add_referendum<T: Config>(n: u32) -> (ReferendumIndex, H256) {
|
||||
let vote_threshold = VoteThreshold::SimpleMajority;
|
||||
let proposal = make_proposal::<T>(n);
|
||||
let hash = proposal.hash();
|
||||
(
|
||||
Democracy::<T>::inject_referendum(
|
||||
T::LaunchPeriod::get(),
|
||||
proposal,
|
||||
vote_threshold,
|
||||
0u32.into(),
|
||||
),
|
||||
hash,
|
||||
)
|
||||
.map_err(|_| "failed to schedule named")?;
|
||||
Ok(referendum_index)
|
||||
}
|
||||
|
||||
fn account_vote<T: Config>(b: BalanceOf<T>) -> AccountVote<BalanceOf<T>> {
|
||||
@@ -97,95 +84,90 @@ benchmarks! {
|
||||
}
|
||||
|
||||
let caller = funded_account::<T>("caller", 0);
|
||||
let proposal_hash: T::Hash = T::Hashing::hash_of(&0);
|
||||
let proposal = make_proposal::<T>(0);
|
||||
let value = T::MinimumDeposit::get();
|
||||
whitelist_account!(caller);
|
||||
}: _(RawOrigin::Signed(caller), proposal_hash, value)
|
||||
}: _(RawOrigin::Signed(caller), proposal, value)
|
||||
verify {
|
||||
assert_eq!(Democracy::<T>::public_props().len(), p as usize, "Proposals not created.");
|
||||
}
|
||||
|
||||
second {
|
||||
let s in 0 .. MAX_SECONDERS;
|
||||
|
||||
let caller = funded_account::<T>("caller", 0);
|
||||
let proposal_hash = add_proposal::<T>(s)?;
|
||||
add_proposal::<T>(0)?;
|
||||
|
||||
// Create s existing "seconds"
|
||||
for i in 0 .. s {
|
||||
// we must reserve one deposit for the `proposal` and one for our benchmarked `second` call.
|
||||
for i in 0 .. T::MaxDeposits::get() - 2 {
|
||||
let seconder = funded_account::<T>("seconder", i);
|
||||
Democracy::<T>::second(RawOrigin::Signed(seconder).into(), 0, u32::MAX)?;
|
||||
Democracy::<T>::second(RawOrigin::Signed(seconder).into(), 0)?;
|
||||
}
|
||||
|
||||
let deposits = Democracy::<T>::deposit_of(0).ok_or("Proposal not created")?;
|
||||
assert_eq!(deposits.0.len(), (s + 1) as usize, "Seconds not recorded");
|
||||
assert_eq!(deposits.0.len(), (T::MaxDeposits::get() - 1) as usize, "Seconds not recorded");
|
||||
whitelist_account!(caller);
|
||||
}: _(RawOrigin::Signed(caller), 0, u32::MAX)
|
||||
}: _(RawOrigin::Signed(caller), 0)
|
||||
verify {
|
||||
let deposits = Democracy::<T>::deposit_of(0).ok_or("Proposal not created")?;
|
||||
assert_eq!(deposits.0.len(), (s + 2) as usize, "`second` benchmark did not work");
|
||||
assert_eq!(deposits.0.len(), (T::MaxDeposits::get()) as usize, "`second` benchmark did not work");
|
||||
}
|
||||
|
||||
vote_new {
|
||||
let r in 1 .. MAX_REFERENDUMS;
|
||||
|
||||
let caller = funded_account::<T>("caller", 0);
|
||||
let account_vote = account_vote::<T>(100u32.into());
|
||||
|
||||
// We need to create existing direct votes
|
||||
for i in 0 .. r {
|
||||
let ref_idx = add_referendum::<T>(i)?;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(caller.clone()).into(), ref_idx, account_vote)?;
|
||||
for i in 0 .. T::MaxVotes::get() - 1 {
|
||||
let ref_index = add_referendum::<T>(i).0;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(caller.clone()).into(), ref_index, account_vote)?;
|
||||
}
|
||||
let votes = match VotingOf::<T>::get(&caller) {
|
||||
Voting::Direct { votes, .. } => votes,
|
||||
_ => return Err("Votes are not direct".into()),
|
||||
};
|
||||
assert_eq!(votes.len(), r as usize, "Votes were not recorded.");
|
||||
assert_eq!(votes.len(), (T::MaxVotes::get() - 1) as usize, "Votes were not recorded.");
|
||||
|
||||
let referendum_index = add_referendum::<T>(r)?;
|
||||
let ref_index = add_referendum::<T>(T::MaxVotes::get() - 1).0;
|
||||
whitelist_account!(caller);
|
||||
}: vote(RawOrigin::Signed(caller.clone()), referendum_index, account_vote)
|
||||
}: vote(RawOrigin::Signed(caller.clone()), ref_index, account_vote)
|
||||
verify {
|
||||
let votes = match VotingOf::<T>::get(&caller) {
|
||||
Voting::Direct { votes, .. } => votes,
|
||||
_ => return Err("Votes are not direct".into()),
|
||||
};
|
||||
assert_eq!(votes.len(), (r + 1) as usize, "Vote was not recorded.");
|
||||
assert_eq!(votes.len(), T::MaxVotes::get() as usize, "Vote was not recorded.");
|
||||
}
|
||||
|
||||
vote_existing {
|
||||
let r in 1 .. MAX_REFERENDUMS;
|
||||
|
||||
let caller = funded_account::<T>("caller", 0);
|
||||
let account_vote = account_vote::<T>(100u32.into());
|
||||
|
||||
// We need to create existing direct votes
|
||||
for i in 0 ..=r {
|
||||
let ref_idx = add_referendum::<T>(i)?;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(caller.clone()).into(), ref_idx, account_vote)?;
|
||||
for i in 0..T::MaxVotes::get() {
|
||||
let ref_index = add_referendum::<T>(i).0;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(caller.clone()).into(), ref_index, account_vote)?;
|
||||
}
|
||||
let votes = match VotingOf::<T>::get(&caller) {
|
||||
Voting::Direct { votes, .. } => votes,
|
||||
_ => return Err("Votes are not direct".into()),
|
||||
};
|
||||
assert_eq!(votes.len(), (r + 1) as usize, "Votes were not recorded.");
|
||||
assert_eq!(votes.len(), T::MaxVotes::get() as usize, "Votes were not recorded.");
|
||||
|
||||
// Change vote from aye to nay
|
||||
let nay = Vote { aye: false, conviction: Conviction::Locked1x };
|
||||
let new_vote = AccountVote::Standard { vote: nay, balance: 1000u32.into() };
|
||||
let referendum_index = Democracy::<T>::referendum_count() - 1;
|
||||
let ref_index = Democracy::<T>::referendum_count() - 1;
|
||||
|
||||
// This tests when a user changes a vote
|
||||
whitelist_account!(caller);
|
||||
}: vote(RawOrigin::Signed(caller.clone()), referendum_index, new_vote)
|
||||
}: vote(RawOrigin::Signed(caller.clone()), ref_index, new_vote)
|
||||
verify {
|
||||
let votes = match VotingOf::<T>::get(&caller) {
|
||||
Voting::Direct { votes, .. } => votes,
|
||||
_ => return Err("Votes are not direct".into()),
|
||||
};
|
||||
assert_eq!(votes.len(), (r + 1) as usize, "Vote was incorrectly added");
|
||||
let referendum_info = Democracy::<T>::referendum_info(referendum_index)
|
||||
assert_eq!(votes.len(), T::MaxVotes::get() as usize, "Vote was incorrectly added");
|
||||
let referendum_info = Democracy::<T>::referendum_info(ref_index)
|
||||
.ok_or("referendum doesn't exist")?;
|
||||
let tally = match referendum_info {
|
||||
ReferendumInfo::Ongoing(r) => r.tally,
|
||||
@@ -196,61 +178,55 @@ benchmarks! {
|
||||
|
||||
emergency_cancel {
|
||||
let origin = T::CancellationOrigin::successful_origin();
|
||||
let referendum_index = add_referendum::<T>(0)?;
|
||||
assert_ok!(Democracy::<T>::referendum_status(referendum_index));
|
||||
}: _<T::RuntimeOrigin>(origin, referendum_index)
|
||||
let ref_index = add_referendum::<T>(0).0;
|
||||
assert_ok!(Democracy::<T>::referendum_status(ref_index));
|
||||
}: _<T::RuntimeOrigin>(origin, ref_index)
|
||||
verify {
|
||||
// Referendum has been canceled
|
||||
assert_noop!(
|
||||
Democracy::<T>::referendum_status(referendum_index),
|
||||
Democracy::<T>::referendum_status(ref_index),
|
||||
Error::<T>::ReferendumInvalid,
|
||||
);
|
||||
}
|
||||
|
||||
blacklist {
|
||||
let p in 1 .. T::MaxProposals::get();
|
||||
|
||||
// Place our proposal at the end to make sure it's worst case.
|
||||
for i in 0 .. p - 1 {
|
||||
for i in 0 .. T::MaxProposals::get() - 1 {
|
||||
add_proposal::<T>(i)?;
|
||||
}
|
||||
// We should really add a lot of seconds here, but we're not doing it elsewhere.
|
||||
|
||||
// Add a referendum of our proposal.
|
||||
let (ref_index, hash) = add_referendum::<T>(0);
|
||||
assert_ok!(Democracy::<T>::referendum_status(ref_index));
|
||||
// Place our proposal in the external queue, too.
|
||||
let hash = T::Hashing::hash_of(&0);
|
||||
assert_ok!(
|
||||
Democracy::<T>::external_propose(T::ExternalOrigin::successful_origin(), hash)
|
||||
Democracy::<T>::external_propose(T::ExternalOrigin::successful_origin(), make_proposal::<T>(0))
|
||||
);
|
||||
let origin = T::BlacklistOrigin::successful_origin();
|
||||
// Add a referendum of our proposal.
|
||||
let referendum_index = add_referendum::<T>(0)?;
|
||||
assert_ok!(Democracy::<T>::referendum_status(referendum_index));
|
||||
}: _<T::RuntimeOrigin>(origin, hash, Some(referendum_index))
|
||||
}: _<T::RuntimeOrigin>(origin, hash, Some(ref_index))
|
||||
verify {
|
||||
// Referendum has been canceled
|
||||
assert_noop!(
|
||||
Democracy::<T>::referendum_status(referendum_index),
|
||||
Democracy::<T>::referendum_status(ref_index),
|
||||
Error::<T>::ReferendumInvalid
|
||||
);
|
||||
}
|
||||
|
||||
// Worst case scenario, we external propose a previously blacklisted proposal
|
||||
external_propose {
|
||||
let v in 1 .. MAX_VETOERS as u32;
|
||||
|
||||
let origin = T::ExternalOrigin::successful_origin();
|
||||
let proposal_hash = T::Hashing::hash_of(&0);
|
||||
let proposal = make_proposal::<T>(0);
|
||||
// Add proposal to blacklist with block number 0
|
||||
|
||||
let addresses = (0..v)
|
||||
let addresses: BoundedVec<_, _> = (0..(T::MaxBlacklisted::get() - 1))
|
||||
.into_iter()
|
||||
.map(|i| account::<T::AccountId>("blacklist", i, SEED))
|
||||
.collect::<Vec<_>>();
|
||||
Blacklist::<T>::insert(
|
||||
proposal_hash,
|
||||
(T::BlockNumber::zero(), addresses),
|
||||
);
|
||||
}: _<T::RuntimeOrigin>(origin, proposal_hash)
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
Blacklist::<T>::insert(proposal.hash(), (T::BlockNumber::zero(), addresses));
|
||||
}: _<T::RuntimeOrigin>(origin, proposal)
|
||||
verify {
|
||||
// External proposal created
|
||||
ensure!(<NextExternal<T>>::exists(), "External proposal didn't work");
|
||||
@@ -258,8 +234,8 @@ benchmarks! {
|
||||
|
||||
external_propose_majority {
|
||||
let origin = T::ExternalMajorityOrigin::successful_origin();
|
||||
let proposal_hash = T::Hashing::hash_of(&0);
|
||||
}: _<T::RuntimeOrigin>(origin, proposal_hash)
|
||||
let proposal = make_proposal::<T>(0);
|
||||
}: _<T::RuntimeOrigin>(origin, proposal)
|
||||
verify {
|
||||
// External proposal created
|
||||
ensure!(<NextExternal<T>>::exists(), "External proposal didn't work");
|
||||
@@ -267,8 +243,8 @@ benchmarks! {
|
||||
|
||||
external_propose_default {
|
||||
let origin = T::ExternalDefaultOrigin::successful_origin();
|
||||
let proposal_hash = T::Hashing::hash_of(&0);
|
||||
}: _<T::RuntimeOrigin>(origin, proposal_hash)
|
||||
let proposal = make_proposal::<T>(0);
|
||||
}: _<T::RuntimeOrigin>(origin, proposal)
|
||||
verify {
|
||||
// External proposal created
|
||||
ensure!(<NextExternal<T>>::exists(), "External proposal didn't work");
|
||||
@@ -276,8 +252,9 @@ benchmarks! {
|
||||
|
||||
fast_track {
|
||||
let origin_propose = T::ExternalDefaultOrigin::successful_origin();
|
||||
let proposal_hash: T::Hash = T::Hashing::hash_of(&0);
|
||||
Democracy::<T>::external_propose_default(origin_propose, proposal_hash)?;
|
||||
let proposal = make_proposal::<T>(0);
|
||||
let proposal_hash = proposal.hash();
|
||||
Democracy::<T>::external_propose_default(origin_propose, proposal)?;
|
||||
|
||||
// NOTE: Instant origin may invoke a little bit more logic, but may not always succeed.
|
||||
let origin_fast_track = T::FastTrackOrigin::successful_origin();
|
||||
@@ -289,17 +266,15 @@ benchmarks! {
|
||||
}
|
||||
|
||||
veto_external {
|
||||
// Existing veto-ers
|
||||
let v in 0 .. MAX_VETOERS as u32;
|
||||
|
||||
let proposal_hash: T::Hash = T::Hashing::hash_of(&v);
|
||||
let proposal = make_proposal::<T>(0);
|
||||
let proposal_hash = proposal.hash();
|
||||
|
||||
let origin_propose = T::ExternalDefaultOrigin::successful_origin();
|
||||
Democracy::<T>::external_propose_default(origin_propose, proposal_hash)?;
|
||||
Democracy::<T>::external_propose_default(origin_propose, proposal)?;
|
||||
|
||||
let mut vetoers: Vec<T::AccountId> = Vec::new();
|
||||
for i in 0 .. v {
|
||||
vetoers.push(account::<T::AccountId>("vetoer", i, SEED));
|
||||
let mut vetoers: BoundedVec<T::AccountId, _> = Default::default();
|
||||
for i in 0 .. (T::MaxBlacklisted::get() - 1) {
|
||||
vetoers.try_push(account::<T::AccountId>("vetoer", i, SEED)).unwrap();
|
||||
}
|
||||
vetoers.sort();
|
||||
Blacklist::<T>::insert(proposal_hash, (T::BlockNumber::zero(), vetoers));
|
||||
@@ -310,42 +285,27 @@ benchmarks! {
|
||||
verify {
|
||||
assert!(NextExternal::<T>::get().is_none());
|
||||
let (_, new_vetoers) = <Blacklist<T>>::get(&proposal_hash).ok_or("no blacklist")?;
|
||||
assert_eq!(new_vetoers.len(), (v + 1) as usize, "vetoers not added");
|
||||
assert_eq!(new_vetoers.len(), T::MaxBlacklisted::get() as usize, "vetoers not added");
|
||||
}
|
||||
|
||||
cancel_proposal {
|
||||
let p in 1 .. T::MaxProposals::get();
|
||||
|
||||
// Place our proposal at the end to make sure it's worst case.
|
||||
for i in 0 .. p {
|
||||
for i in 0 .. T::MaxProposals::get() {
|
||||
add_proposal::<T>(i)?;
|
||||
}
|
||||
|
||||
let cancel_origin = T::CancelProposalOrigin::successful_origin();
|
||||
}: _<T::RuntimeOrigin>(cancel_origin, 0)
|
||||
|
||||
cancel_referendum {
|
||||
let referendum_index = add_referendum::<T>(0)?;
|
||||
}: _(RawOrigin::Root, referendum_index)
|
||||
let ref_index = add_referendum::<T>(0).0;
|
||||
}: _(RawOrigin::Root, ref_index)
|
||||
|
||||
cancel_queued {
|
||||
let r in 1 .. MAX_REFERENDUMS;
|
||||
|
||||
for i in 0..r {
|
||||
add_referendum::<T>(i)?; // This add one element in the scheduler
|
||||
}
|
||||
|
||||
let referendum_index = add_referendum::<T>(r)?;
|
||||
}: _(RawOrigin::Root, referendum_index)
|
||||
|
||||
// This measures the path of `launch_next` external. Not currently used as we simply
|
||||
// assume the weight is `MaxBlockWeight` when executing.
|
||||
#[extra]
|
||||
on_initialize_external {
|
||||
let r in 0 .. MAX_REFERENDUMS;
|
||||
let r in 0 .. REFERENDUM_COUNT_HINT;
|
||||
|
||||
for i in 0..r {
|
||||
add_referendum::<T>(i)?;
|
||||
add_referendum::<T>(i);
|
||||
}
|
||||
|
||||
assert_eq!(Democracy::<T>::referendum_count(), r, "referenda not created");
|
||||
@@ -354,8 +314,8 @@ benchmarks! {
|
||||
LastTabledWasExternal::<T>::put(false);
|
||||
|
||||
let origin = T::ExternalMajorityOrigin::successful_origin();
|
||||
let proposal_hash = T::Hashing::hash_of(&r);
|
||||
let call = Call::<T>::external_propose_majority { proposal_hash };
|
||||
let proposal = make_proposal::<T>(r);
|
||||
let call = Call::<T>::external_propose_majority { proposal };
|
||||
call.dispatch_bypass_filter(origin)?;
|
||||
// External proposal created
|
||||
ensure!(<NextExternal<T>>::exists(), "External proposal didn't work");
|
||||
@@ -379,14 +339,12 @@ benchmarks! {
|
||||
}
|
||||
}
|
||||
|
||||
// This measures the path of `launch_next` public. Not currently used as we simply
|
||||
// assume the weight is `MaxBlockWeight` when executing.
|
||||
#[extra]
|
||||
on_initialize_public {
|
||||
let r in 1 .. MAX_REFERENDUMS;
|
||||
let r in 0 .. (T::MaxVotes::get() - 1);
|
||||
|
||||
for i in 0..r {
|
||||
add_referendum::<T>(i)?;
|
||||
add_referendum::<T>(i);
|
||||
}
|
||||
|
||||
assert_eq!(Democracy::<T>::referendum_count(), r, "referenda not created");
|
||||
@@ -415,10 +373,10 @@ benchmarks! {
|
||||
|
||||
// No launch no maturing referenda.
|
||||
on_initialize_base {
|
||||
let r in 1 .. MAX_REFERENDUMS;
|
||||
let r in 0 .. (T::MaxVotes::get() - 1);
|
||||
|
||||
for i in 0..r {
|
||||
add_referendum::<T>(i)?;
|
||||
add_referendum::<T>(i);
|
||||
}
|
||||
|
||||
for (key, mut info) in ReferendumInfoOf::<T>::iter() {
|
||||
@@ -445,10 +403,10 @@ benchmarks! {
|
||||
}
|
||||
|
||||
on_initialize_base_with_launch_period {
|
||||
let r in 1 .. MAX_REFERENDUMS;
|
||||
let r in 0 .. (T::MaxVotes::get() - 1);
|
||||
|
||||
for i in 0..r {
|
||||
add_referendum::<T>(i)?;
|
||||
add_referendum::<T>(i);
|
||||
}
|
||||
|
||||
for (key, mut info) in ReferendumInfoOf::<T>::iter() {
|
||||
@@ -477,7 +435,7 @@ benchmarks! {
|
||||
}
|
||||
|
||||
delegate {
|
||||
let r in 1 .. MAX_REFERENDUMS;
|
||||
let r in 0 .. (T::MaxVotes::get() - 1);
|
||||
|
||||
let initial_balance: BalanceOf<T> = 100u32.into();
|
||||
let delegated_balance: BalanceOf<T> = 1000u32.into();
|
||||
@@ -504,8 +462,8 @@ benchmarks! {
|
||||
let account_vote = account_vote::<T>(initial_balance);
|
||||
// We need to create existing direct votes for the `new_delegate`
|
||||
for i in 0..r {
|
||||
let ref_idx = add_referendum::<T>(i)?;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(new_delegate.clone()).into(), ref_idx, account_vote)?;
|
||||
let ref_index = add_referendum::<T>(i).0;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(new_delegate.clone()).into(), ref_index, account_vote)?;
|
||||
}
|
||||
let votes = match VotingOf::<T>::get(&new_delegate) {
|
||||
Voting::Direct { votes, .. } => votes,
|
||||
@@ -529,7 +487,7 @@ benchmarks! {
|
||||
}
|
||||
|
||||
undelegate {
|
||||
let r in 1 .. MAX_REFERENDUMS;
|
||||
let r in 0 .. (T::MaxVotes::get() - 1);
|
||||
|
||||
let initial_balance: BalanceOf<T> = 100u32.into();
|
||||
let delegated_balance: BalanceOf<T> = 1000u32.into();
|
||||
@@ -553,10 +511,10 @@ benchmarks! {
|
||||
// We need to create votes direct votes for the `delegate`
|
||||
let account_vote = account_vote::<T>(initial_balance);
|
||||
for i in 0..r {
|
||||
let ref_idx = add_referendum::<T>(i)?;
|
||||
let ref_index = add_referendum::<T>(i).0;
|
||||
Democracy::<T>::vote(
|
||||
RawOrigin::Signed(the_delegate.clone()).into(),
|
||||
ref_idx,
|
||||
ref_index,
|
||||
account_vote
|
||||
)?;
|
||||
}
|
||||
@@ -580,71 +538,9 @@ benchmarks! {
|
||||
|
||||
}: _(RawOrigin::Root)
|
||||
|
||||
note_preimage {
|
||||
// Num of bytes in encoded proposal
|
||||
let b in 0 .. MAX_BYTES;
|
||||
|
||||
let caller = funded_account::<T>("caller", 0);
|
||||
let encoded_proposal = vec![1; b as usize];
|
||||
whitelist_account!(caller);
|
||||
}: _(RawOrigin::Signed(caller), encoded_proposal.clone())
|
||||
verify {
|
||||
let proposal_hash = T::Hashing::hash(&encoded_proposal[..]);
|
||||
match Preimages::<T>::get(proposal_hash) {
|
||||
Some(PreimageStatus::Available { .. }) => (),
|
||||
_ => return Err("preimage not available".into())
|
||||
}
|
||||
}
|
||||
|
||||
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![1; b as usize];
|
||||
let proposal_hash = T::Hashing::hash(&encoded_proposal[..]);
|
||||
let block_number = T::BlockNumber::one();
|
||||
Preimages::<T>::insert(&proposal_hash, PreimageStatus::Missing(block_number));
|
||||
|
||||
let caller = funded_account::<T>("caller", 0);
|
||||
let encoded_proposal = vec![1; b as usize];
|
||||
whitelist_account!(caller);
|
||||
}: _(RawOrigin::Signed(caller), encoded_proposal.clone())
|
||||
verify {
|
||||
let proposal_hash = T::Hashing::hash(&encoded_proposal[..]);
|
||||
match Preimages::<T>::get(proposal_hash) {
|
||||
Some(PreimageStatus::Available { .. }) => (),
|
||||
_ => return Err("preimage not available".into())
|
||||
}
|
||||
}
|
||||
|
||||
reap_preimage {
|
||||
// Num of bytes in encoded proposal
|
||||
let b in 0 .. MAX_BYTES;
|
||||
|
||||
let encoded_proposal = vec![1; b as usize];
|
||||
let proposal_hash = T::Hashing::hash(&encoded_proposal[..]);
|
||||
|
||||
let submitter = funded_account::<T>("submitter", b);
|
||||
Democracy::<T>::note_preimage(RawOrigin::Signed(submitter).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::<T>::set_block_number(block_number);
|
||||
|
||||
assert!(Preimages::<T>::contains_key(proposal_hash));
|
||||
|
||||
let caller = funded_account::<T>("caller", 0);
|
||||
whitelist_account!(caller);
|
||||
}: _(RawOrigin::Signed(caller), proposal_hash, u32::MAX)
|
||||
verify {
|
||||
let proposal_hash = T::Hashing::hash(&encoded_proposal[..]);
|
||||
assert!(!Preimages::<T>::contains_key(proposal_hash));
|
||||
}
|
||||
|
||||
// Test when unlock will remove locks
|
||||
unlock_remove {
|
||||
let r in 1 .. MAX_REFERENDUMS;
|
||||
let r in 0 .. (T::MaxVotes::get() - 1);
|
||||
|
||||
let locker = funded_account::<T>("locker", 0);
|
||||
let locker_lookup = T::Lookup::unlookup(locker.clone());
|
||||
@@ -653,9 +549,9 @@ benchmarks! {
|
||||
let small_vote = account_vote::<T>(base_balance);
|
||||
// Vote and immediately unvote
|
||||
for i in 0 .. r {
|
||||
let ref_idx = add_referendum::<T>(i)?;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(locker.clone()).into(), ref_idx, small_vote)?;
|
||||
Democracy::<T>::remove_vote(RawOrigin::Signed(locker.clone()).into(), ref_idx)?;
|
||||
let ref_index = add_referendum::<T>(i).0;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(locker.clone()).into(), ref_index, small_vote)?;
|
||||
Democracy::<T>::remove_vote(RawOrigin::Signed(locker.clone()).into(), ref_index)?;
|
||||
}
|
||||
|
||||
let caller = funded_account::<T>("caller", 0);
|
||||
@@ -669,7 +565,7 @@ benchmarks! {
|
||||
|
||||
// Test when unlock will set a new value
|
||||
unlock_set {
|
||||
let r in 1 .. MAX_REFERENDUMS;
|
||||
let r in 0 .. (T::MaxVotes::get() - 1);
|
||||
|
||||
let locker = funded_account::<T>("locker", 0);
|
||||
let locker_lookup = T::Lookup::unlookup(locker.clone());
|
||||
@@ -677,14 +573,14 @@ benchmarks! {
|
||||
let base_balance: BalanceOf<T> = 100u32.into();
|
||||
let small_vote = account_vote::<T>(base_balance);
|
||||
for i in 0 .. r {
|
||||
let ref_idx = add_referendum::<T>(i)?;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(locker.clone()).into(), ref_idx, small_vote)?;
|
||||
let ref_index = add_referendum::<T>(i).0;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(locker.clone()).into(), ref_index, small_vote)?;
|
||||
}
|
||||
|
||||
// Create a big vote so lock increases
|
||||
let big_vote = account_vote::<T>(base_balance * 10u32.into());
|
||||
let referendum_index = add_referendum::<T>(r)?;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(locker.clone()).into(), referendum_index, big_vote)?;
|
||||
let ref_index = add_referendum::<T>(r).0;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(locker.clone()).into(), ref_index, big_vote)?;
|
||||
|
||||
let votes = match VotingOf::<T>::get(&locker) {
|
||||
Voting::Direct { votes, .. } => votes,
|
||||
@@ -695,7 +591,7 @@ benchmarks! {
|
||||
let voting = VotingOf::<T>::get(&locker);
|
||||
assert_eq!(voting.locked_balance(), base_balance * 10u32.into());
|
||||
|
||||
Democracy::<T>::remove_vote(RawOrigin::Signed(locker.clone()).into(), referendum_index)?;
|
||||
Democracy::<T>::remove_vote(RawOrigin::Signed(locker.clone()).into(), ref_index)?;
|
||||
|
||||
let caller = funded_account::<T>("caller", 0);
|
||||
whitelist_account!(caller);
|
||||
@@ -709,18 +605,18 @@ benchmarks! {
|
||||
|
||||
let voting = VotingOf::<T>::get(&locker);
|
||||
// Note that we may want to add a `get_lock` api to actually verify
|
||||
assert_eq!(voting.locked_balance(), base_balance);
|
||||
assert_eq!(voting.locked_balance(), if r > 0 { base_balance } else { 0u32.into() });
|
||||
}
|
||||
|
||||
remove_vote {
|
||||
let r in 1 .. MAX_REFERENDUMS;
|
||||
let r in 1 .. T::MaxVotes::get();
|
||||
|
||||
let caller = funded_account::<T>("caller", 0);
|
||||
let account_vote = account_vote::<T>(100u32.into());
|
||||
|
||||
for i in 0 .. r {
|
||||
let ref_idx = add_referendum::<T>(i)?;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(caller.clone()).into(), ref_idx, account_vote)?;
|
||||
let ref_index = add_referendum::<T>(i).0;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(caller.clone()).into(), ref_index, account_vote)?;
|
||||
}
|
||||
|
||||
let votes = match VotingOf::<T>::get(&caller) {
|
||||
@@ -729,9 +625,9 @@ benchmarks! {
|
||||
};
|
||||
assert_eq!(votes.len(), r as usize, "Votes not created");
|
||||
|
||||
let referendum_index = r - 1;
|
||||
let ref_index = r - 1;
|
||||
whitelist_account!(caller);
|
||||
}: _(RawOrigin::Signed(caller.clone()), referendum_index)
|
||||
}: _(RawOrigin::Signed(caller.clone()), ref_index)
|
||||
verify {
|
||||
let votes = match VotingOf::<T>::get(&caller) {
|
||||
Voting::Direct { votes, .. } => votes,
|
||||
@@ -742,15 +638,15 @@ benchmarks! {
|
||||
|
||||
// Worst case is when target == caller and referendum is ongoing
|
||||
remove_other_vote {
|
||||
let r in 1 .. MAX_REFERENDUMS;
|
||||
let r in 1 .. T::MaxVotes::get();
|
||||
|
||||
let caller = funded_account::<T>("caller", r);
|
||||
let caller_lookup = T::Lookup::unlookup(caller.clone());
|
||||
let account_vote = account_vote::<T>(100u32.into());
|
||||
|
||||
for i in 0 .. r {
|
||||
let ref_idx = add_referendum::<T>(i)?;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(caller.clone()).into(), ref_idx, account_vote)?;
|
||||
let ref_index = add_referendum::<T>(i).0;
|
||||
Democracy::<T>::vote(RawOrigin::Signed(caller.clone()).into(), ref_index, account_vote)?;
|
||||
}
|
||||
|
||||
let votes = match VotingOf::<T>::get(&caller) {
|
||||
@@ -759,9 +655,9 @@ benchmarks! {
|
||||
};
|
||||
assert_eq!(votes.len(), r as usize, "Votes not created");
|
||||
|
||||
let referendum_index = r - 1;
|
||||
let ref_index = r - 1;
|
||||
whitelist_account!(caller);
|
||||
}: _(RawOrigin::Signed(caller.clone()), caller_lookup, referendum_index)
|
||||
}: _(RawOrigin::Signed(caller.clone()), caller_lookup, ref_index)
|
||||
verify {
|
||||
let votes = match VotingOf::<T>::get(&caller) {
|
||||
Voting::Direct { votes, .. } => votes,
|
||||
@@ -770,54 +666,6 @@ benchmarks! {
|
||||
assert_eq!(votes.len(), (r - 1) as usize, "Vote was not removed");
|
||||
}
|
||||
|
||||
#[extra]
|
||||
enact_proposal_execute {
|
||||
// Num of bytes in encoded proposal
|
||||
let b in 0 .. MAX_BYTES;
|
||||
|
||||
let proposer = funded_account::<T>("proposer", 0);
|
||||
let raw_call = Call::note_preimage { encoded_proposal: vec![1; b as usize] };
|
||||
let generic_call: T::Proposal = raw_call.into();
|
||||
let encoded_proposal = generic_call.encode();
|
||||
let proposal_hash = T::Hashing::hash(&encoded_proposal[..]);
|
||||
Democracy::<T>::note_preimage(RawOrigin::Signed(proposer).into(), encoded_proposal)?;
|
||||
|
||||
match Preimages::<T>::get(proposal_hash) {
|
||||
Some(PreimageStatus::Available { .. }) => (),
|
||||
_ => return Err("preimage not available".into())
|
||||
}
|
||||
}: enact_proposal(RawOrigin::Root, proposal_hash, 0)
|
||||
verify {
|
||||
// Fails due to mismatched origin
|
||||
assert_last_event::<T>(Event::<T>::Executed { ref_index: 0, result: Err(BadOrigin.into()) }.into());
|
||||
}
|
||||
|
||||
#[extra]
|
||||
enact_proposal_slash {
|
||||
// Num of bytes in encoded proposal
|
||||
let b in 0 .. MAX_BYTES;
|
||||
|
||||
let proposer = funded_account::<T>("proposer", 0);
|
||||
// Random invalid bytes
|
||||
let encoded_proposal = vec![200; b as usize];
|
||||
let proposal_hash = T::Hashing::hash(&encoded_proposal[..]);
|
||||
Democracy::<T>::note_preimage(RawOrigin::Signed(proposer).into(), encoded_proposal)?;
|
||||
|
||||
match Preimages::<T>::get(proposal_hash) {
|
||||
Some(PreimageStatus::Available { .. }) => (),
|
||||
_ => return Err("preimage not available".into())
|
||||
}
|
||||
let origin = RawOrigin::Root.into();
|
||||
let call = Call::<T>::enact_proposal { proposal_hash, index: 0 }.encode();
|
||||
}: {
|
||||
assert_eq!(
|
||||
<Call<T> as Decode>::decode(&mut &*call)
|
||||
.expect("call is encoded above, encoding must be correct")
|
||||
.dispatch_bypass_filter(origin),
|
||||
Err(Error::<T>::PreimageInvalid.into())
|
||||
);
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(
|
||||
Democracy,
|
||||
crate::tests::new_test_ext(),
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//! The conviction datatype.
|
||||
|
||||
use crate::types::Delegations;
|
||||
use codec::{Decode, Encode};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{
|
||||
traits::{Bounded, CheckedDiv, CheckedMul, Zero},
|
||||
@@ -27,7 +27,19 @@ use sp_runtime::{
|
||||
use sp_std::{prelude::*, result::Result};
|
||||
|
||||
/// A value denoting the strength of conviction of a vote.
|
||||
#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug, TypeInfo)]
|
||||
#[derive(
|
||||
Encode,
|
||||
MaxEncodedLen,
|
||||
Decode,
|
||||
Copy,
|
||||
Clone,
|
||||
Eq,
|
||||
PartialEq,
|
||||
Ord,
|
||||
PartialOrd,
|
||||
RuntimeDebug,
|
||||
TypeInfo,
|
||||
)]
|
||||
pub enum Conviction {
|
||||
/// 0.1x votes, unlocked.
|
||||
None,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,236 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2022 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.
|
||||
|
||||
//! Storage migrations for the preimage pallet.
|
||||
|
||||
use super::*;
|
||||
use frame_support::{pallet_prelude::*, storage_alias, traits::OnRuntimeUpgrade, BoundedVec};
|
||||
use sp_core::H256;
|
||||
|
||||
/// The log target.
|
||||
const TARGET: &'static str = "runtime::democracy::migration::v1";
|
||||
|
||||
/// The original data layout of the democracy pallet without a specific version number.
|
||||
mod v0 {
|
||||
use super::*;
|
||||
|
||||
#[storage_alias]
|
||||
pub type PublicProps<T: Config> = StorageValue<
|
||||
Pallet<T>,
|
||||
Vec<(PropIndex, <T as frame_system::Config>::Hash, <T as frame_system::Config>::AccountId)>,
|
||||
ValueQuery,
|
||||
>;
|
||||
|
||||
#[storage_alias]
|
||||
pub type NextExternal<T: Config> =
|
||||
StorageValue<Pallet<T>, (<T as frame_system::Config>::Hash, VoteThreshold)>;
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
#[storage_alias]
|
||||
pub type ReferendumInfoOf<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
frame_support::Twox64Concat,
|
||||
ReferendumIndex,
|
||||
ReferendumInfo<
|
||||
<T as frame_system::Config>::BlockNumber,
|
||||
<T as frame_system::Config>::Hash,
|
||||
BalanceOf<T>,
|
||||
>,
|
||||
>;
|
||||
}
|
||||
|
||||
pub mod v1 {
|
||||
use super::*;
|
||||
|
||||
/// Migration for translating bare `Hash`es into `Bounded<Call>`s.
|
||||
pub struct Migration<T>(sp_std::marker::PhantomData<T>);
|
||||
|
||||
impl<T: Config + frame_system::Config<Hash = H256>> OnRuntimeUpgrade for Migration<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 0, "can only upgrade from version 0");
|
||||
|
||||
let props_count = v0::PublicProps::<T>::get().len();
|
||||
log::info!(target: TARGET, "{} public proposals will be migrated.", props_count,);
|
||||
ensure!(props_count <= T::MaxProposals::get() as usize, "too many proposals");
|
||||
|
||||
let referenda_count = v0::ReferendumInfoOf::<T>::iter().count();
|
||||
log::info!(target: TARGET, "{} referenda will be migrated.", referenda_count);
|
||||
|
||||
Ok((props_count as u32, referenda_count as u32).encode())
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let mut weight = T::DbWeight::get().reads(1);
|
||||
if StorageVersion::get::<Pallet<T>>() != 0 {
|
||||
log::warn!(
|
||||
target: TARGET,
|
||||
"skipping on_runtime_upgrade: executed on wrong storage version.\
|
||||
Expected version 0"
|
||||
);
|
||||
return weight
|
||||
}
|
||||
|
||||
ReferendumInfoOf::<T>::translate(
|
||||
|index, old: ReferendumInfo<T::BlockNumber, T::Hash, BalanceOf<T>>| {
|
||||
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
|
||||
log::info!(target: TARGET, "migrating referendum #{:?}", &index);
|
||||
Some(match old {
|
||||
ReferendumInfo::Ongoing(status) =>
|
||||
ReferendumInfo::Ongoing(ReferendumStatus {
|
||||
end: status.end,
|
||||
proposal: Bounded::from_legacy_hash(status.proposal),
|
||||
threshold: status.threshold,
|
||||
delay: status.delay,
|
||||
tally: status.tally,
|
||||
}),
|
||||
ReferendumInfo::Finished { approved, end } =>
|
||||
ReferendumInfo::Finished { approved, end },
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
let props = v0::PublicProps::<T>::take()
|
||||
.into_iter()
|
||||
.map(|(i, hash, a)| (i, Bounded::from_legacy_hash(hash), a))
|
||||
.collect::<Vec<_>>();
|
||||
let bounded = BoundedVec::<_, T::MaxProposals>::truncate_from(props.clone());
|
||||
PublicProps::<T>::put(bounded);
|
||||
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
|
||||
|
||||
if props.len() as u32 > T::MaxProposals::get() {
|
||||
log::error!(
|
||||
target: TARGET,
|
||||
"truncated {} public proposals to {}; continuing",
|
||||
props.len(),
|
||||
T::MaxProposals::get()
|
||||
);
|
||||
}
|
||||
|
||||
if let Some((hash, threshold)) = v0::NextExternal::<T>::take() {
|
||||
log::info!(target: TARGET, "migrating next external proposal");
|
||||
NextExternal::<T>::put((Bounded::from_legacy_hash(hash), threshold));
|
||||
}
|
||||
|
||||
StorageVersion::new(1).put::<Pallet<T>>();
|
||||
|
||||
weight.saturating_add(T::DbWeight::get().reads_writes(1, 2))
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 1, "must upgrade");
|
||||
|
||||
let (old_props_count, old_ref_count): (u32, u32) =
|
||||
Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed");
|
||||
let new_props_count = crate::PublicProps::<T>::get().len() as u32;
|
||||
assert_eq!(new_props_count, old_props_count, "must migrate all public proposals");
|
||||
let new_ref_count = crate::ReferendumInfoOf::<T>::iter().count() as u32;
|
||||
assert_eq!(new_ref_count, old_ref_count, "must migrate all referenda");
|
||||
|
||||
log::info!(
|
||||
target: TARGET,
|
||||
"{} public proposals migrated, {} referenda migrated",
|
||||
new_props_count,
|
||||
new_ref_count,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "try-runtime")]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::{
|
||||
tests::{Test as T, *},
|
||||
types::*,
|
||||
};
|
||||
use frame_support::bounded_vec;
|
||||
|
||||
#[allow(deprecated)]
|
||||
#[test]
|
||||
fn migration_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 0);
|
||||
// Insert some values into the v0 storage:
|
||||
|
||||
// Case 1: Ongoing referendum
|
||||
let hash = H256::repeat_byte(1);
|
||||
let status = ReferendumStatus {
|
||||
end: 1u32.into(),
|
||||
proposal: hash.clone(),
|
||||
threshold: VoteThreshold::SuperMajorityApprove,
|
||||
delay: 1u32.into(),
|
||||
tally: Tally { ayes: 1u32.into(), nays: 1u32.into(), turnout: 1u32.into() },
|
||||
};
|
||||
v0::ReferendumInfoOf::<T>::insert(1u32, ReferendumInfo::Ongoing(status));
|
||||
|
||||
// Case 2: Finished referendum
|
||||
v0::ReferendumInfoOf::<T>::insert(
|
||||
2u32,
|
||||
ReferendumInfo::Finished { approved: true, end: 123u32.into() },
|
||||
);
|
||||
|
||||
// Case 3: Public proposals
|
||||
let hash2 = H256::repeat_byte(2);
|
||||
v0::PublicProps::<T>::put(vec![
|
||||
(3u32, hash.clone(), 123u64),
|
||||
(4u32, hash2.clone(), 123u64),
|
||||
]);
|
||||
|
||||
// Case 4: Next external
|
||||
v0::NextExternal::<T>::put((hash.clone(), VoteThreshold::SuperMajorityApprove));
|
||||
|
||||
// Migrate.
|
||||
let state = v1::Migration::<T>::pre_upgrade().unwrap();
|
||||
let _weight = v1::Migration::<T>::on_runtime_upgrade();
|
||||
v1::Migration::<T>::post_upgrade(state).unwrap();
|
||||
// Check that all values got migrated.
|
||||
|
||||
// Case 1: Ongoing referendum
|
||||
assert_eq!(
|
||||
ReferendumInfoOf::<T>::get(1u32),
|
||||
Some(ReferendumInfo::Ongoing(ReferendumStatus {
|
||||
end: 1u32.into(),
|
||||
proposal: Bounded::from_legacy_hash(hash),
|
||||
threshold: VoteThreshold::SuperMajorityApprove,
|
||||
delay: 1u32.into(),
|
||||
tally: Tally { ayes: 1u32.into(), nays: 1u32.into(), turnout: 1u32.into() },
|
||||
}))
|
||||
);
|
||||
// Case 2: Finished referendum
|
||||
assert_eq!(
|
||||
ReferendumInfoOf::<T>::get(2u32),
|
||||
Some(ReferendumInfo::Finished { approved: true, end: 123u32.into() })
|
||||
);
|
||||
// Case 3: Public proposals
|
||||
let props: BoundedVec<_, <Test as Config>::MaxProposals> = bounded_vec![
|
||||
(3u32, Bounded::from_legacy_hash(hash), 123u64),
|
||||
(4u32, Bounded::from_legacy_hash(hash2), 123u64)
|
||||
];
|
||||
assert_eq!(PublicProps::<T>::get(), props);
|
||||
// Case 4: Next external
|
||||
assert_eq!(
|
||||
NextExternal::<T>::get(),
|
||||
Some((Bounded::from_legacy_hash(hash), VoteThreshold::SuperMajorityApprove))
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
use super::*;
|
||||
use crate as pallet_democracy;
|
||||
use codec::Encode;
|
||||
use frame_support::{
|
||||
assert_noop, assert_ok, ord_parameter_types, parameter_types,
|
||||
traits::{
|
||||
ConstU32, ConstU64, Contains, EqualPrivilegeOnly, GenesisBuild, OnInitialize, SortedMembers,
|
||||
ConstU32, ConstU64, Contains, EqualPrivilegeOnly, GenesisBuild, OnInitialize,
|
||||
SortedMembers, StorePreimage,
|
||||
},
|
||||
weights::Weight,
|
||||
};
|
||||
@@ -35,14 +35,12 @@ use sp_runtime::{
|
||||
traits::{BadOrigin, BlakeTwo256, IdentityLookup},
|
||||
Perbill,
|
||||
};
|
||||
|
||||
mod cancellation;
|
||||
mod decoders;
|
||||
mod delegation;
|
||||
mod external_proposing;
|
||||
mod fast_tracking;
|
||||
mod lock_voting;
|
||||
mod preimage;
|
||||
mod public_proposals;
|
||||
mod scheduling;
|
||||
mod voting;
|
||||
@@ -63,6 +61,7 @@ frame_support::construct_runtime!(
|
||||
{
|
||||
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
|
||||
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
Preimage: pallet_preimage,
|
||||
Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event<T>},
|
||||
Democracy: pallet_democracy::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
}
|
||||
@@ -78,13 +77,11 @@ impl Contains<RuntimeCall> for BaseFilter {
|
||||
|
||||
parameter_types! {
|
||||
pub BlockWeights: frame_system::limits::BlockWeights =
|
||||
frame_system::limits::BlockWeights::simple_max(
|
||||
Weight::from_ref_time(1_000_000).set_proof_size(u64::MAX),
|
||||
);
|
||||
frame_system::limits::BlockWeights::simple_max(frame_support::weights::constants::WEIGHT_PER_SECOND.set_proof_size(u64::MAX));
|
||||
}
|
||||
impl frame_system::Config for Test {
|
||||
type BaseCallFilter = BaseFilter;
|
||||
type BlockWeights = ();
|
||||
type BlockWeights = BlockWeights;
|
||||
type BlockLength = ();
|
||||
type DbWeight = ();
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
@@ -111,6 +108,16 @@ impl frame_system::Config for Test {
|
||||
parameter_types! {
|
||||
pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * BlockWeights::get().max_block;
|
||||
}
|
||||
|
||||
impl pallet_preimage::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type WeightInfo = ();
|
||||
type Currency = Balances;
|
||||
type ManagerOrigin = EnsureRoot<u64>;
|
||||
type BaseDeposit = ConstU64<0>;
|
||||
type ByteDeposit = ConstU64<0>;
|
||||
}
|
||||
|
||||
impl pallet_scheduler::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
@@ -118,11 +125,10 @@ impl pallet_scheduler::Config for Test {
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type MaximumWeight = MaximumSchedulerWeight;
|
||||
type ScheduleOrigin = EnsureRoot<u64>;
|
||||
type MaxScheduledPerBlock = ();
|
||||
type MaxScheduledPerBlock = ConstU32<100>;
|
||||
type WeightInfo = ();
|
||||
type OriginPrivilegeCmp = EqualPrivilegeOnly;
|
||||
type PreimageProvider = ();
|
||||
type NoPreimagePostponement = ();
|
||||
type Preimages = ();
|
||||
}
|
||||
|
||||
impl pallet_balances::Config for Test {
|
||||
@@ -158,7 +164,6 @@ impl SortedMembers<u64> for OneToFive {
|
||||
}
|
||||
|
||||
impl Config for Test {
|
||||
type Proposal = RuntimeCall;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Currency = pallet_balances::Pallet<Self>;
|
||||
type EnactmentPeriod = ConstU64<2>;
|
||||
@@ -167,6 +172,8 @@ impl Config for Test {
|
||||
type VoteLockingPeriod = ConstU64<3>;
|
||||
type FastTrackVotingPeriod = ConstU64<2>;
|
||||
type MinimumDeposit = ConstU64<1>;
|
||||
type MaxDeposits = ConstU32<1000>;
|
||||
type MaxBlacklisted = ConstU32<5>;
|
||||
type ExternalOrigin = EnsureSignedBy<Two, u64>;
|
||||
type ExternalMajorityOrigin = EnsureSignedBy<Three, u64>;
|
||||
type ExternalDefaultOrigin = EnsureSignedBy<One, u64>;
|
||||
@@ -176,16 +183,15 @@ impl Config for Test {
|
||||
type CancelProposalOrigin = EnsureRoot<u64>;
|
||||
type VetoOrigin = EnsureSignedBy<OneToFive, u64>;
|
||||
type CooloffPeriod = ConstU64<2>;
|
||||
type PreimageByteDeposit = PreimageByteDeposit;
|
||||
type Slash = ();
|
||||
type InstantOrigin = EnsureSignedBy<Six, u64>;
|
||||
type InstantAllowed = InstantAllowed;
|
||||
type Scheduler = Scheduler;
|
||||
type MaxVotes = ConstU32<100>;
|
||||
type OperationalPreimageOrigin = EnsureSignedBy<Six, u64>;
|
||||
type PalletsOrigin = OriginCaller;
|
||||
type WeightInfo = ();
|
||||
type MaxProposals = ConstU32<100>;
|
||||
type Preimages = Preimage;
|
||||
}
|
||||
|
||||
pub fn new_test_ext() -> sp_io::TestExternalities {
|
||||
@@ -203,12 +209,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
|
||||
ext
|
||||
}
|
||||
|
||||
/// Execute the function two times, with `true` and with `false`.
|
||||
pub fn new_test_ext_execute_with_cond(execute: impl FnOnce(bool) -> () + Clone) {
|
||||
new_test_ext().execute_with(|| (execute.clone())(false));
|
||||
new_test_ext().execute_with(|| execute(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn params_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
@@ -218,44 +218,22 @@ fn params_should_work() {
|
||||
});
|
||||
}
|
||||
|
||||
fn set_balance_proposal(value: u64) -> Vec<u8> {
|
||||
RuntimeCall::Balances(pallet_balances::Call::set_balance {
|
||||
who: 42,
|
||||
new_free: value,
|
||||
new_reserved: 0,
|
||||
})
|
||||
.encode()
|
||||
fn set_balance_proposal(value: u64) -> BoundedCallOf<Test> {
|
||||
let inner = pallet_balances::Call::set_balance { who: 42, new_free: value, new_reserved: 0 };
|
||||
let outer = RuntimeCall::Balances(inner);
|
||||
Preimage::bound(outer).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_balance_proposal_is_correctly_filtered_out() {
|
||||
for i in 0..10 {
|
||||
let call = RuntimeCall::decode(&mut &set_balance_proposal(i)[..]).unwrap();
|
||||
let call = Preimage::realize(&set_balance_proposal(i)).unwrap().0;
|
||||
assert!(!<Test as frame_system::Config>::BaseCallFilter::contains(&call));
|
||||
}
|
||||
}
|
||||
|
||||
fn set_balance_proposal_hash(value: u64) -> H256 {
|
||||
BlakeTwo256::hash(&set_balance_proposal(value)[..])
|
||||
}
|
||||
|
||||
fn set_balance_proposal_hash_and_note(value: u64) -> H256 {
|
||||
let p = set_balance_proposal(value);
|
||||
let h = BlakeTwo256::hash(&p[..]);
|
||||
match Democracy::note_preimage(RuntimeOrigin::signed(6), p) {
|
||||
Ok(_) => (),
|
||||
Err(x) if x == Error::<Test>::DuplicatePreimage.into() => (),
|
||||
Err(x) => panic!("{:?}", x),
|
||||
}
|
||||
h
|
||||
}
|
||||
|
||||
fn propose_set_balance(who: u64, value: u64, delay: u64) -> DispatchResult {
|
||||
Democracy::propose(RuntimeOrigin::signed(who), set_balance_proposal_hash(value), delay)
|
||||
}
|
||||
|
||||
fn propose_set_balance_and_note(who: u64, value: u64, delay: u64) -> DispatchResult {
|
||||
Democracy::propose(RuntimeOrigin::signed(who), set_balance_proposal_hash_and_note(value), delay)
|
||||
Democracy::propose(RuntimeOrigin::signed(who), set_balance_proposal(value), delay)
|
||||
}
|
||||
|
||||
fn next_block() {
|
||||
@@ -272,7 +250,7 @@ fn fast_forward_to(n: u64) {
|
||||
|
||||
fn begin_referendum() -> ReferendumIndex {
|
||||
System::set_block_number(0);
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 1));
|
||||
assert_ok!(propose_set_balance(1, 2, 1));
|
||||
fast_forward_to(2);
|
||||
0
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ fn cancel_referendum_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
@@ -42,37 +42,13 @@ fn cancel_referendum_should_work() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_queued_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 1));
|
||||
|
||||
// start of 2 => next referendum scheduled.
|
||||
fast_forward_to(2);
|
||||
|
||||
assert_ok!(Democracy::vote(RuntimeOrigin::signed(1), 0, aye(1)));
|
||||
|
||||
fast_forward_to(4);
|
||||
|
||||
assert!(pallet_scheduler::Agenda::<Test>::get(6)[0].is_some());
|
||||
|
||||
assert_noop!(
|
||||
Democracy::cancel_queued(RuntimeOrigin::root(), 1),
|
||||
Error::<Test>::ProposalMissing
|
||||
);
|
||||
assert_ok!(Democracy::cancel_queued(RuntimeOrigin::root(), 0));
|
||||
assert!(pallet_scheduler::Agenda::<Test>::get(6)[0].is_none());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emergency_cancel_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
2,
|
||||
);
|
||||
@@ -86,7 +62,7 @@ fn emergency_cancel_should_work() {
|
||||
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
2,
|
||||
);
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
//! The for various partial storage decoders
|
||||
|
||||
use super::*;
|
||||
use frame_support::storage::{migration, unhashed};
|
||||
use frame_support::{
|
||||
storage::{migration, unhashed},
|
||||
BoundedVec,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_decode_compact_u32_at() {
|
||||
@@ -42,7 +45,8 @@ fn test_decode_compact_u32_at() {
|
||||
fn len_of_deposit_of() {
|
||||
new_test_ext().execute_with(|| {
|
||||
for l in vec![0, 1, 200, 1000] {
|
||||
let value: (Vec<u64>, u64) = ((0..l).map(|_| Default::default()).collect(), 3u64);
|
||||
let value: (BoundedVec<u64, _>, u64) =
|
||||
((0..l).map(|_| Default::default()).collect::<Vec<_>>().try_into().unwrap(), 3u64);
|
||||
DepositOf::<Test>::insert(2, value);
|
||||
assert_eq!(Democracy::len_of_deposit_of(2), Some(l));
|
||||
}
|
||||
@@ -51,35 +55,3 @@ fn len_of_deposit_of() {
|
||||
assert_eq!(Democracy::len_of_deposit_of(2), None);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_image() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let key = Default::default();
|
||||
let missing = PreimageStatus::Missing(0);
|
||||
Preimages::<Test>::insert(key, missing);
|
||||
assert_noop!(Democracy::pre_image_data_len(key), Error::<Test>::PreimageMissing);
|
||||
assert_eq!(Democracy::check_pre_image_is_missing(key), Ok(()));
|
||||
|
||||
Preimages::<Test>::remove(key);
|
||||
assert_noop!(Democracy::pre_image_data_len(key), Error::<Test>::PreimageMissing);
|
||||
assert_noop!(Democracy::check_pre_image_is_missing(key), Error::<Test>::NotImminent);
|
||||
|
||||
for l in vec![0, 10, 100, 1000u32] {
|
||||
let available = PreimageStatus::Available {
|
||||
data: (0..l).map(|i| i as u8).collect(),
|
||||
provider: 0,
|
||||
deposit: 0,
|
||||
since: 0,
|
||||
expiry: None,
|
||||
};
|
||||
|
||||
Preimages::<Test>::insert(key, available);
|
||||
assert_eq!(Democracy::pre_image_data_len(key), Ok(l));
|
||||
assert_noop!(
|
||||
Democracy::check_pre_image_is_missing(key),
|
||||
Error::<Test>::DuplicatePreimage
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ fn single_proposal_should_work_with_delegation() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 1));
|
||||
assert_ok!(propose_set_balance(1, 2, 1));
|
||||
|
||||
fast_forward_to(2);
|
||||
|
||||
@@ -75,7 +75,7 @@ fn cyclic_delegation_should_unwind() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 1));
|
||||
assert_ok!(propose_set_balance(1, 2, 1));
|
||||
|
||||
fast_forward_to(2);
|
||||
|
||||
@@ -100,7 +100,7 @@ fn single_proposal_should_work_with_vote_and_delegation() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 1));
|
||||
assert_ok!(propose_set_balance(1, 2, 1));
|
||||
|
||||
fast_forward_to(2);
|
||||
|
||||
@@ -122,7 +122,7 @@ fn single_proposal_should_work_with_undelegation() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 1));
|
||||
assert_ok!(propose_set_balance(1, 2, 1));
|
||||
|
||||
// Delegate and undelegate vote.
|
||||
assert_ok!(Democracy::delegate(RuntimeOrigin::signed(2), 1, Conviction::None, 20));
|
||||
|
||||
@@ -23,35 +23,29 @@ use super::*;
|
||||
fn veto_external_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
assert_ok!(Democracy::external_propose(
|
||||
RuntimeOrigin::signed(2),
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
));
|
||||
assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2),));
|
||||
assert!(<NextExternal<Test>>::exists());
|
||||
|
||||
let h = set_balance_proposal_hash_and_note(2);
|
||||
let h = set_balance_proposal(2).hash();
|
||||
assert_ok!(Democracy::veto_external(RuntimeOrigin::signed(3), h));
|
||||
// cancelled.
|
||||
assert!(!<NextExternal<Test>>::exists());
|
||||
// fails - same proposal can't be resubmitted.
|
||||
assert_noop!(
|
||||
Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal_hash(2),),
|
||||
Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2),),
|
||||
Error::<Test>::ProposalBlacklisted
|
||||
);
|
||||
|
||||
fast_forward_to(1);
|
||||
// fails as we're still in cooloff period.
|
||||
assert_noop!(
|
||||
Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal_hash(2),),
|
||||
Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2),),
|
||||
Error::<Test>::ProposalBlacklisted
|
||||
);
|
||||
|
||||
fast_forward_to(2);
|
||||
// works; as we're out of the cooloff period.
|
||||
assert_ok!(Democracy::external_propose(
|
||||
RuntimeOrigin::signed(2),
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
));
|
||||
assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2),));
|
||||
assert!(<NextExternal<Test>>::exists());
|
||||
|
||||
// 3 can't veto the same thing twice.
|
||||
@@ -68,14 +62,11 @@ fn veto_external_works() {
|
||||
fast_forward_to(3);
|
||||
// same proposal fails as we're still in cooloff
|
||||
assert_noop!(
|
||||
Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal_hash(2),),
|
||||
Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2)),
|
||||
Error::<Test>::ProposalBlacklisted
|
||||
);
|
||||
// different proposal works fine.
|
||||
assert_ok!(Democracy::external_propose(
|
||||
RuntimeOrigin::signed(2),
|
||||
set_balance_proposal_hash_and_note(3),
|
||||
));
|
||||
assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(3),));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -84,22 +75,16 @@ fn external_blacklisting_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
|
||||
assert_ok!(Democracy::external_propose(
|
||||
RuntimeOrigin::signed(2),
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
));
|
||||
assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2),));
|
||||
|
||||
let hash = set_balance_proposal_hash(2);
|
||||
let hash = set_balance_proposal(2).hash();
|
||||
assert_ok!(Democracy::blacklist(RuntimeOrigin::root(), hash, None));
|
||||
|
||||
fast_forward_to(2);
|
||||
assert_noop!(Democracy::referendum_status(0), Error::<Test>::ReferendumInvalid);
|
||||
|
||||
assert_noop!(
|
||||
Democracy::external_propose(
|
||||
RuntimeOrigin::signed(2),
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
),
|
||||
Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2)),
|
||||
Error::<Test>::ProposalBlacklisted,
|
||||
);
|
||||
});
|
||||
@@ -110,15 +95,12 @@ fn external_referendum_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
assert_noop!(
|
||||
Democracy::external_propose(RuntimeOrigin::signed(1), set_balance_proposal_hash(2),),
|
||||
Democracy::external_propose(RuntimeOrigin::signed(1), set_balance_proposal(2),),
|
||||
BadOrigin,
|
||||
);
|
||||
assert_ok!(Democracy::external_propose(
|
||||
RuntimeOrigin::signed(2),
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
));
|
||||
assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2),));
|
||||
assert_noop!(
|
||||
Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal_hash(1),),
|
||||
Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(1),),
|
||||
Error::<Test>::DuplicateProposal
|
||||
);
|
||||
fast_forward_to(2);
|
||||
@@ -126,7 +108,7 @@ fn external_referendum_works() {
|
||||
Democracy::referendum_status(0),
|
||||
Ok(ReferendumStatus {
|
||||
end: 4,
|
||||
proposal_hash: set_balance_proposal_hash(2),
|
||||
proposal: set_balance_proposal(2),
|
||||
threshold: VoteThreshold::SuperMajorityApprove,
|
||||
delay: 2,
|
||||
tally: Tally { ayes: 0, nays: 0, turnout: 0 },
|
||||
@@ -140,22 +122,19 @@ fn external_majority_referendum_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
assert_noop!(
|
||||
Democracy::external_propose_majority(
|
||||
RuntimeOrigin::signed(1),
|
||||
set_balance_proposal_hash(2)
|
||||
),
|
||||
Democracy::external_propose_majority(RuntimeOrigin::signed(1), set_balance_proposal(2)),
|
||||
BadOrigin,
|
||||
);
|
||||
assert_ok!(Democracy::external_propose_majority(
|
||||
RuntimeOrigin::signed(3),
|
||||
set_balance_proposal_hash_and_note(2)
|
||||
set_balance_proposal(2)
|
||||
));
|
||||
fast_forward_to(2);
|
||||
assert_eq!(
|
||||
Democracy::referendum_status(0),
|
||||
Ok(ReferendumStatus {
|
||||
end: 4,
|
||||
proposal_hash: set_balance_proposal_hash(2),
|
||||
proposal: set_balance_proposal(2),
|
||||
threshold: VoteThreshold::SimpleMajority,
|
||||
delay: 2,
|
||||
tally: Tally { ayes: 0, nays: 0, turnout: 0 },
|
||||
@@ -169,22 +148,19 @@ fn external_default_referendum_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
assert_noop!(
|
||||
Democracy::external_propose_default(
|
||||
RuntimeOrigin::signed(3),
|
||||
set_balance_proposal_hash(2)
|
||||
),
|
||||
Democracy::external_propose_default(RuntimeOrigin::signed(3), set_balance_proposal(2)),
|
||||
BadOrigin,
|
||||
);
|
||||
assert_ok!(Democracy::external_propose_default(
|
||||
RuntimeOrigin::signed(1),
|
||||
set_balance_proposal_hash_and_note(2)
|
||||
set_balance_proposal(2)
|
||||
));
|
||||
fast_forward_to(2);
|
||||
assert_eq!(
|
||||
Democracy::referendum_status(0),
|
||||
Ok(ReferendumStatus {
|
||||
end: 4,
|
||||
proposal_hash: set_balance_proposal_hash(2),
|
||||
proposal: set_balance_proposal(2),
|
||||
threshold: VoteThreshold::SuperMajorityAgainst,
|
||||
delay: 2,
|
||||
tally: Tally { ayes: 0, nays: 0, turnout: 0 },
|
||||
@@ -197,11 +173,8 @@ fn external_default_referendum_works() {
|
||||
fn external_and_public_interleaving_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
assert_ok!(Democracy::external_propose(
|
||||
RuntimeOrigin::signed(2),
|
||||
set_balance_proposal_hash_and_note(1),
|
||||
));
|
||||
assert_ok!(propose_set_balance_and_note(6, 2, 2));
|
||||
assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(1),));
|
||||
assert_ok!(propose_set_balance(6, 2, 2));
|
||||
|
||||
fast_forward_to(2);
|
||||
|
||||
@@ -210,17 +183,14 @@ fn external_and_public_interleaving_works() {
|
||||
Democracy::referendum_status(0),
|
||||
Ok(ReferendumStatus {
|
||||
end: 4,
|
||||
proposal_hash: set_balance_proposal_hash_and_note(1),
|
||||
proposal: set_balance_proposal(1),
|
||||
threshold: VoteThreshold::SuperMajorityApprove,
|
||||
delay: 2,
|
||||
tally: Tally { ayes: 0, nays: 0, turnout: 0 },
|
||||
})
|
||||
);
|
||||
// replenish external
|
||||
assert_ok!(Democracy::external_propose(
|
||||
RuntimeOrigin::signed(2),
|
||||
set_balance_proposal_hash_and_note(3),
|
||||
));
|
||||
assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(3),));
|
||||
|
||||
fast_forward_to(4);
|
||||
|
||||
@@ -229,7 +199,7 @@ fn external_and_public_interleaving_works() {
|
||||
Democracy::referendum_status(1),
|
||||
Ok(ReferendumStatus {
|
||||
end: 6,
|
||||
proposal_hash: set_balance_proposal_hash_and_note(2),
|
||||
proposal: set_balance_proposal(2),
|
||||
threshold: VoteThreshold::SuperMajorityApprove,
|
||||
delay: 2,
|
||||
tally: Tally { ayes: 0, nays: 0, turnout: 0 },
|
||||
@@ -244,17 +214,14 @@ fn external_and_public_interleaving_works() {
|
||||
Democracy::referendum_status(2),
|
||||
Ok(ReferendumStatus {
|
||||
end: 8,
|
||||
proposal_hash: set_balance_proposal_hash_and_note(3),
|
||||
proposal: set_balance_proposal(3),
|
||||
threshold: VoteThreshold::SuperMajorityApprove,
|
||||
delay: 2,
|
||||
tally: Tally { ayes: 0, nays: 0, turnout: 0 },
|
||||
})
|
||||
);
|
||||
// replenish external
|
||||
assert_ok!(Democracy::external_propose(
|
||||
RuntimeOrigin::signed(2),
|
||||
set_balance_proposal_hash_and_note(5),
|
||||
));
|
||||
assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(5),));
|
||||
|
||||
fast_forward_to(8);
|
||||
|
||||
@@ -263,18 +230,15 @@ fn external_and_public_interleaving_works() {
|
||||
Democracy::referendum_status(3),
|
||||
Ok(ReferendumStatus {
|
||||
end: 10,
|
||||
proposal_hash: set_balance_proposal_hash_and_note(5),
|
||||
proposal: set_balance_proposal(5),
|
||||
threshold: VoteThreshold::SuperMajorityApprove,
|
||||
delay: 2,
|
||||
tally: Tally { ayes: 0, nays: 0, turnout: 0 },
|
||||
})
|
||||
);
|
||||
// replenish both
|
||||
assert_ok!(Democracy::external_propose(
|
||||
RuntimeOrigin::signed(2),
|
||||
set_balance_proposal_hash_and_note(7),
|
||||
));
|
||||
assert_ok!(propose_set_balance_and_note(6, 4, 2));
|
||||
assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(7),));
|
||||
assert_ok!(propose_set_balance(6, 4, 2));
|
||||
|
||||
fast_forward_to(10);
|
||||
|
||||
@@ -283,16 +247,16 @@ fn external_and_public_interleaving_works() {
|
||||
Democracy::referendum_status(4),
|
||||
Ok(ReferendumStatus {
|
||||
end: 12,
|
||||
proposal_hash: set_balance_proposal_hash_and_note(4),
|
||||
proposal: set_balance_proposal(4),
|
||||
threshold: VoteThreshold::SuperMajorityApprove,
|
||||
delay: 2,
|
||||
tally: Tally { ayes: 0, nays: 0, turnout: 0 },
|
||||
})
|
||||
);
|
||||
// replenish public again
|
||||
assert_ok!(propose_set_balance_and_note(6, 6, 2));
|
||||
assert_ok!(propose_set_balance(6, 6, 2));
|
||||
// cancel external
|
||||
let h = set_balance_proposal_hash_and_note(7);
|
||||
let h = set_balance_proposal(7).hash();
|
||||
assert_ok!(Democracy::veto_external(RuntimeOrigin::signed(3), h));
|
||||
|
||||
fast_forward_to(12);
|
||||
@@ -302,7 +266,7 @@ fn external_and_public_interleaving_works() {
|
||||
Democracy::referendum_status(5),
|
||||
Ok(ReferendumStatus {
|
||||
end: 14,
|
||||
proposal_hash: set_balance_proposal_hash_and_note(6),
|
||||
proposal: set_balance_proposal(6),
|
||||
threshold: VoteThreshold::SuperMajorityApprove,
|
||||
delay: 2,
|
||||
tally: Tally { ayes: 0, nays: 0, turnout: 0 },
|
||||
|
||||
@@ -23,14 +23,14 @@ use super::*;
|
||||
fn fast_track_referendum_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
let h = set_balance_proposal_hash_and_note(2);
|
||||
let h = set_balance_proposal(2).hash();
|
||||
assert_noop!(
|
||||
Democracy::fast_track(RuntimeOrigin::signed(5), h, 3, 2),
|
||||
Error::<Test>::ProposalMissing
|
||||
);
|
||||
assert_ok!(Democracy::external_propose_majority(
|
||||
RuntimeOrigin::signed(3),
|
||||
set_balance_proposal_hash_and_note(2)
|
||||
set_balance_proposal(2)
|
||||
));
|
||||
assert_noop!(Democracy::fast_track(RuntimeOrigin::signed(1), h, 3, 2), BadOrigin);
|
||||
assert_ok!(Democracy::fast_track(RuntimeOrigin::signed(5), h, 2, 0));
|
||||
@@ -38,7 +38,7 @@ fn fast_track_referendum_works() {
|
||||
Democracy::referendum_status(0),
|
||||
Ok(ReferendumStatus {
|
||||
end: 2,
|
||||
proposal_hash: set_balance_proposal_hash_and_note(2),
|
||||
proposal: set_balance_proposal(2),
|
||||
threshold: VoteThreshold::SimpleMajority,
|
||||
delay: 0,
|
||||
tally: Tally { ayes: 0, nays: 0, turnout: 0 },
|
||||
@@ -51,14 +51,14 @@ fn fast_track_referendum_works() {
|
||||
fn instant_referendum_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
let h = set_balance_proposal_hash_and_note(2);
|
||||
let h = set_balance_proposal(2).hash();
|
||||
assert_noop!(
|
||||
Democracy::fast_track(RuntimeOrigin::signed(5), h, 3, 2),
|
||||
Error::<Test>::ProposalMissing
|
||||
);
|
||||
assert_ok!(Democracy::external_propose_majority(
|
||||
RuntimeOrigin::signed(3),
|
||||
set_balance_proposal_hash_and_note(2)
|
||||
set_balance_proposal(2)
|
||||
));
|
||||
assert_noop!(Democracy::fast_track(RuntimeOrigin::signed(1), h, 3, 2), BadOrigin);
|
||||
assert_noop!(Democracy::fast_track(RuntimeOrigin::signed(5), h, 1, 0), BadOrigin);
|
||||
@@ -76,7 +76,7 @@ fn instant_referendum_works() {
|
||||
Democracy::referendum_status(0),
|
||||
Ok(ReferendumStatus {
|
||||
end: 1,
|
||||
proposal_hash: set_balance_proposal_hash_and_note(2),
|
||||
proposal: set_balance_proposal(2),
|
||||
threshold: VoteThreshold::SimpleMajority,
|
||||
delay: 0,
|
||||
tally: Tally { ayes: 0, nays: 0, turnout: 0 },
|
||||
@@ -93,7 +93,7 @@ fn instant_next_block_referendum_backed() {
|
||||
let majority_origin_id = 3;
|
||||
let instant_origin_id = 6;
|
||||
let voting_period = 1;
|
||||
let proposal_hash = set_balance_proposal_hash_and_note(2);
|
||||
let proposal = set_balance_proposal(2);
|
||||
let delay = 2; // has no effect on test
|
||||
|
||||
// init
|
||||
@@ -103,13 +103,13 @@ fn instant_next_block_referendum_backed() {
|
||||
// propose with majority origin
|
||||
assert_ok!(Democracy::external_propose_majority(
|
||||
RuntimeOrigin::signed(majority_origin_id),
|
||||
proposal_hash
|
||||
proposal.clone()
|
||||
));
|
||||
|
||||
// fast track with instant origin and voting period pointing to the next block
|
||||
assert_ok!(Democracy::fast_track(
|
||||
RuntimeOrigin::signed(instant_origin_id),
|
||||
proposal_hash,
|
||||
proposal.hash(),
|
||||
voting_period,
|
||||
delay
|
||||
));
|
||||
@@ -119,7 +119,7 @@ fn instant_next_block_referendum_backed() {
|
||||
Democracy::referendum_status(0),
|
||||
Ok(ReferendumStatus {
|
||||
end: start_block_number + voting_period,
|
||||
proposal_hash,
|
||||
proposal,
|
||||
threshold: VoteThreshold::SimpleMajority,
|
||||
delay,
|
||||
tally: Tally { ayes: 0, nays: 0, turnout: 0 },
|
||||
@@ -143,11 +143,8 @@ fn instant_next_block_referendum_backed() {
|
||||
fn fast_track_referendum_fails_when_no_simple_majority() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
let h = set_balance_proposal_hash_and_note(2);
|
||||
assert_ok!(Democracy::external_propose(
|
||||
RuntimeOrigin::signed(2),
|
||||
set_balance_proposal_hash_and_note(2)
|
||||
));
|
||||
let h = set_balance_proposal(2).hash();
|
||||
assert_ok!(Democracy::external_propose(RuntimeOrigin::signed(2), set_balance_proposal(2)));
|
||||
assert_noop!(
|
||||
Democracy::fast_track(RuntimeOrigin::signed(5), h, 3, 2),
|
||||
Error::<Test>::NotSimpleMajority
|
||||
|
||||
@@ -43,7 +43,7 @@ fn lock_voting_should_work() {
|
||||
System::set_block_number(0);
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
@@ -59,7 +59,7 @@ fn lock_voting_should_work() {
|
||||
assert_eq!(Balances::locks(i), vec![the_lock(i * 10)]);
|
||||
}
|
||||
|
||||
fast_forward_to(2);
|
||||
fast_forward_to(3);
|
||||
|
||||
// Referendum passed; 1 and 5 didn't get their way and can now reap and unlock.
|
||||
assert_ok!(Democracy::remove_vote(RuntimeOrigin::signed(1), r));
|
||||
@@ -126,13 +126,13 @@ fn no_locks_without_conviction_should_work() {
|
||||
System::set_block_number(0);
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
assert_ok!(Democracy::vote(RuntimeOrigin::signed(1), r, aye(0, 10)));
|
||||
|
||||
fast_forward_to(2);
|
||||
fast_forward_to(3);
|
||||
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
assert_ok!(Democracy::remove_other_vote(RuntimeOrigin::signed(2), 1, r));
|
||||
@@ -146,7 +146,7 @@ fn lock_voting_should_work_with_delegation() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
@@ -167,28 +167,16 @@ fn lock_voting_should_work_with_delegation() {
|
||||
|
||||
fn setup_three_referenda() -> (u32, u32, u32) {
|
||||
System::set_block_number(0);
|
||||
let r1 = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
VoteThreshold::SimpleMajority,
|
||||
0,
|
||||
);
|
||||
let r1 =
|
||||
Democracy::inject_referendum(2, set_balance_proposal(2), VoteThreshold::SimpleMajority, 0);
|
||||
assert_ok!(Democracy::vote(RuntimeOrigin::signed(5), r1, aye(4, 10)));
|
||||
|
||||
let r2 = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
VoteThreshold::SimpleMajority,
|
||||
0,
|
||||
);
|
||||
let r2 =
|
||||
Democracy::inject_referendum(2, set_balance_proposal(2), VoteThreshold::SimpleMajority, 0);
|
||||
assert_ok!(Democracy::vote(RuntimeOrigin::signed(5), r2, aye(3, 20)));
|
||||
|
||||
let r3 = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
VoteThreshold::SimpleMajority,
|
||||
0,
|
||||
);
|
||||
let r3 =
|
||||
Democracy::inject_referendum(2, set_balance_proposal(2), VoteThreshold::SimpleMajority, 0);
|
||||
assert_ok!(Democracy::vote(RuntimeOrigin::signed(5), r3, aye(2, 50)));
|
||||
|
||||
fast_forward_to(2);
|
||||
@@ -306,7 +294,7 @@ fn locks_should_persist_from_voting_to_delegation() {
|
||||
System::set_block_number(0);
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SimpleMajority,
|
||||
0,
|
||||
);
|
||||
|
||||
@@ -1,237 +0,0 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2017-2022 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.
|
||||
|
||||
//! The preimage tests.
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn missing_preimage_should_fail() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
assert_ok!(Democracy::vote(RuntimeOrigin::signed(1), r, aye(1)));
|
||||
|
||||
next_block();
|
||||
next_block();
|
||||
|
||||
assert_eq!(Balances::free_balance(42), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preimage_deposit_should_be_required_and_returned() {
|
||||
new_test_ext_execute_with_cond(|operational| {
|
||||
// fee of 100 is too much.
|
||||
PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 100);
|
||||
assert_noop!(
|
||||
if operational {
|
||||
Democracy::note_preimage_operational(RuntimeOrigin::signed(6), vec![0; 500])
|
||||
} else {
|
||||
Democracy::note_preimage(RuntimeOrigin::signed(6), vec![0; 500])
|
||||
},
|
||||
BalancesError::<Test, _>::InsufficientBalance,
|
||||
);
|
||||
// fee of 1 is reasonable.
|
||||
PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1);
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
assert_ok!(Democracy::vote(RuntimeOrigin::signed(1), r, aye(1)));
|
||||
|
||||
assert_eq!(Balances::reserved_balance(6), 12);
|
||||
|
||||
next_block();
|
||||
next_block();
|
||||
|
||||
assert_eq!(Balances::reserved_balance(6), 0);
|
||||
assert_eq!(Balances::free_balance(6), 60);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preimage_deposit_should_be_reapable_earlier_by_owner() {
|
||||
new_test_ext_execute_with_cond(|operational| {
|
||||
PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1);
|
||||
assert_ok!(if operational {
|
||||
Democracy::note_preimage_operational(RuntimeOrigin::signed(6), set_balance_proposal(2))
|
||||
} else {
|
||||
Democracy::note_preimage(RuntimeOrigin::signed(6), set_balance_proposal(2))
|
||||
});
|
||||
|
||||
assert_eq!(Balances::reserved_balance(6), 12);
|
||||
|
||||
next_block();
|
||||
assert_noop!(
|
||||
Democracy::reap_preimage(
|
||||
RuntimeOrigin::signed(6),
|
||||
set_balance_proposal_hash(2),
|
||||
u32::MAX
|
||||
),
|
||||
Error::<Test>::TooEarly
|
||||
);
|
||||
next_block();
|
||||
assert_ok!(Democracy::reap_preimage(
|
||||
RuntimeOrigin::signed(6),
|
||||
set_balance_proposal_hash(2),
|
||||
u32::MAX
|
||||
));
|
||||
|
||||
assert_eq!(Balances::free_balance(6), 60);
|
||||
assert_eq!(Balances::reserved_balance(6), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preimage_deposit_should_be_reapable() {
|
||||
new_test_ext_execute_with_cond(|operational| {
|
||||
assert_noop!(
|
||||
Democracy::reap_preimage(
|
||||
RuntimeOrigin::signed(5),
|
||||
set_balance_proposal_hash(2),
|
||||
u32::MAX
|
||||
),
|
||||
Error::<Test>::PreimageMissing
|
||||
);
|
||||
|
||||
PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1);
|
||||
assert_ok!(if operational {
|
||||
Democracy::note_preimage_operational(RuntimeOrigin::signed(6), set_balance_proposal(2))
|
||||
} else {
|
||||
Democracy::note_preimage(RuntimeOrigin::signed(6), set_balance_proposal(2))
|
||||
});
|
||||
assert_eq!(Balances::reserved_balance(6), 12);
|
||||
|
||||
next_block();
|
||||
next_block();
|
||||
next_block();
|
||||
assert_noop!(
|
||||
Democracy::reap_preimage(
|
||||
RuntimeOrigin::signed(5),
|
||||
set_balance_proposal_hash(2),
|
||||
u32::MAX
|
||||
),
|
||||
Error::<Test>::TooEarly
|
||||
);
|
||||
|
||||
next_block();
|
||||
assert_ok!(Democracy::reap_preimage(
|
||||
RuntimeOrigin::signed(5),
|
||||
set_balance_proposal_hash(2),
|
||||
u32::MAX
|
||||
));
|
||||
assert_eq!(Balances::reserved_balance(6), 0);
|
||||
assert_eq!(Balances::free_balance(6), 48);
|
||||
assert_eq!(Balances::free_balance(5), 62);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn noting_imminent_preimage_for_free_should_work() {
|
||||
new_test_ext_execute_with_cond(|operational| {
|
||||
PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1);
|
||||
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
1,
|
||||
);
|
||||
assert_ok!(Democracy::vote(RuntimeOrigin::signed(1), r, aye(1)));
|
||||
|
||||
assert_noop!(
|
||||
if operational {
|
||||
Democracy::note_imminent_preimage_operational(
|
||||
RuntimeOrigin::signed(6),
|
||||
set_balance_proposal(2),
|
||||
)
|
||||
} else {
|
||||
Democracy::note_imminent_preimage(RuntimeOrigin::signed(6), set_balance_proposal(2))
|
||||
},
|
||||
Error::<Test>::NotImminent
|
||||
);
|
||||
|
||||
next_block();
|
||||
|
||||
// Now we're in the dispatch queue it's all good.
|
||||
assert_ok!(Democracy::note_imminent_preimage(
|
||||
RuntimeOrigin::signed(6),
|
||||
set_balance_proposal(2)
|
||||
));
|
||||
|
||||
next_block();
|
||||
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reaping_imminent_preimage_should_fail() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let h = set_balance_proposal_hash_and_note(2);
|
||||
let r = Democracy::inject_referendum(3, h, VoteThreshold::SuperMajorityApprove, 1);
|
||||
assert_ok!(Democracy::vote(RuntimeOrigin::signed(1), r, aye(1)));
|
||||
next_block();
|
||||
next_block();
|
||||
assert_noop!(
|
||||
Democracy::reap_preimage(RuntimeOrigin::signed(6), h, u32::MAX),
|
||||
Error::<Test>::Imminent
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn note_imminent_preimage_can_only_be_successful_once() {
|
||||
new_test_ext().execute_with(|| {
|
||||
PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1);
|
||||
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
1,
|
||||
);
|
||||
assert_ok!(Democracy::vote(RuntimeOrigin::signed(1), r, aye(1)));
|
||||
next_block();
|
||||
|
||||
// First time works
|
||||
assert_ok!(Democracy::note_imminent_preimage(
|
||||
RuntimeOrigin::signed(6),
|
||||
set_balance_proposal(2)
|
||||
));
|
||||
|
||||
// Second time fails
|
||||
assert_noop!(
|
||||
Democracy::note_imminent_preimage(RuntimeOrigin::signed(6), set_balance_proposal(2)),
|
||||
Error::<Test>::DuplicatePreimage
|
||||
);
|
||||
|
||||
// Fails from any user
|
||||
assert_noop!(
|
||||
Democracy::note_imminent_preimage(RuntimeOrigin::signed(5), set_balance_proposal(2)),
|
||||
Error::<Test>::DuplicatePreimage
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -22,9 +22,9 @@ use super::*;
|
||||
#[test]
|
||||
fn backing_for_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 2));
|
||||
assert_ok!(propose_set_balance_and_note(1, 4, 4));
|
||||
assert_ok!(propose_set_balance_and_note(1, 3, 3));
|
||||
assert_ok!(propose_set_balance(1, 2, 2));
|
||||
assert_ok!(propose_set_balance(1, 4, 4));
|
||||
assert_ok!(propose_set_balance(1, 3, 3));
|
||||
assert_eq!(Democracy::backing_for(0), Some(2));
|
||||
assert_eq!(Democracy::backing_for(1), Some(4));
|
||||
assert_eq!(Democracy::backing_for(2), Some(3));
|
||||
@@ -34,11 +34,11 @@ fn backing_for_should_work() {
|
||||
#[test]
|
||||
fn deposit_for_proposals_should_be_taken() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 5));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(2), 0, u32::MAX));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(5), 0, u32::MAX));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(5), 0, u32::MAX));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(5), 0, u32::MAX));
|
||||
assert_ok!(propose_set_balance(1, 2, 5));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(2), 0));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(5), 0));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(5), 0));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(5), 0));
|
||||
assert_eq!(Balances::free_balance(1), 5);
|
||||
assert_eq!(Balances::free_balance(2), 15);
|
||||
assert_eq!(Balances::free_balance(5), 35);
|
||||
@@ -48,11 +48,11 @@ fn deposit_for_proposals_should_be_taken() {
|
||||
#[test]
|
||||
fn deposit_for_proposals_should_be_returned() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 5));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(2), 0, u32::MAX));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(5), 0, u32::MAX));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(5), 0, u32::MAX));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(5), 0, u32::MAX));
|
||||
assert_ok!(propose_set_balance(1, 2, 5));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(2), 0));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(5), 0));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(5), 0));
|
||||
assert_ok!(Democracy::second(RuntimeOrigin::signed(5), 0));
|
||||
fast_forward_to(3);
|
||||
assert_eq!(Balances::free_balance(1), 10);
|
||||
assert_eq!(Balances::free_balance(2), 20);
|
||||
@@ -77,30 +77,19 @@ fn poor_proposer_should_not_work() {
|
||||
#[test]
|
||||
fn poor_seconder_should_not_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(propose_set_balance_and_note(2, 2, 11));
|
||||
assert_ok!(propose_set_balance(2, 2, 11));
|
||||
assert_noop!(
|
||||
Democracy::second(RuntimeOrigin::signed(1), 0, u32::MAX),
|
||||
Democracy::second(RuntimeOrigin::signed(1), 0),
|
||||
BalancesError::<Test, _>::InsufficientBalance
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_seconds_upper_bound_should_not_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 5));
|
||||
assert_noop!(
|
||||
Democracy::second(RuntimeOrigin::signed(2), 0, 0),
|
||||
Error::<Test>::WrongUpperBound
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_proposal_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 2));
|
||||
assert_ok!(propose_set_balance_and_note(1, 4, 4));
|
||||
assert_ok!(propose_set_balance(1, 2, 2));
|
||||
assert_ok!(propose_set_balance(1, 4, 4));
|
||||
assert_noop!(Democracy::cancel_proposal(RuntimeOrigin::signed(1), 0), BadOrigin);
|
||||
assert_ok!(Democracy::cancel_proposal(RuntimeOrigin::root(), 0));
|
||||
System::assert_last_event(crate::Event::ProposalCanceled { prop_index: 0 }.into());
|
||||
@@ -113,10 +102,10 @@ fn cancel_proposal_should_work() {
|
||||
fn blacklisting_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
let hash = set_balance_proposal_hash(2);
|
||||
let hash = set_balance_proposal(2).hash();
|
||||
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 2));
|
||||
assert_ok!(propose_set_balance_and_note(1, 4, 4));
|
||||
assert_ok!(propose_set_balance(1, 2, 2));
|
||||
assert_ok!(propose_set_balance(1, 4, 4));
|
||||
|
||||
assert_noop!(Democracy::blacklist(RuntimeOrigin::signed(1), hash, None), BadOrigin);
|
||||
assert_ok!(Democracy::blacklist(RuntimeOrigin::root(), hash, None));
|
||||
@@ -124,11 +113,11 @@ fn blacklisting_should_work() {
|
||||
assert_eq!(Democracy::backing_for(0), None);
|
||||
assert_eq!(Democracy::backing_for(1), Some(4));
|
||||
|
||||
assert_noop!(propose_set_balance_and_note(1, 2, 2), Error::<Test>::ProposalBlacklisted);
|
||||
assert_noop!(propose_set_balance(1, 2, 2), Error::<Test>::ProposalBlacklisted);
|
||||
|
||||
fast_forward_to(2);
|
||||
|
||||
let hash = set_balance_proposal_hash(4);
|
||||
let hash = set_balance_proposal(4).hash();
|
||||
assert_ok!(Democracy::referendum_status(0));
|
||||
assert_ok!(Democracy::blacklist(RuntimeOrigin::root(), hash, Some(0)));
|
||||
assert_noop!(Democracy::referendum_status(0), Error::<Test>::ReferendumInvalid);
|
||||
@@ -139,9 +128,9 @@ fn blacklisting_should_work() {
|
||||
fn runners_up_should_come_after() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 2));
|
||||
assert_ok!(propose_set_balance_and_note(1, 4, 4));
|
||||
assert_ok!(propose_set_balance_and_note(1, 3, 3));
|
||||
assert_ok!(propose_set_balance(1, 2, 2));
|
||||
assert_ok!(propose_set_balance(1, 4, 4));
|
||||
assert_ok!(propose_set_balance(1, 3, 3));
|
||||
fast_forward_to(2);
|
||||
assert_ok!(Democracy::vote(RuntimeOrigin::signed(1), 0, aye(1)));
|
||||
fast_forward_to(4);
|
||||
|
||||
@@ -24,7 +24,7 @@ fn simple_passing_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
@@ -43,7 +43,7 @@ fn simple_failing_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
@@ -62,13 +62,13 @@ fn ooo_inject_referendums_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let r1 = Democracy::inject_referendum(
|
||||
3,
|
||||
set_balance_proposal_hash_and_note(3),
|
||||
set_balance_proposal(3),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
let r2 = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
@@ -77,11 +77,13 @@ fn ooo_inject_referendums_should_work() {
|
||||
assert_eq!(tally(r2), Tally { ayes: 1, nays: 0, turnout: 10 });
|
||||
|
||||
next_block();
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
|
||||
assert_ok!(Democracy::vote(RuntimeOrigin::signed(1), r1, aye(1)));
|
||||
assert_eq!(tally(r1), Tally { ayes: 1, nays: 0, turnout: 10 });
|
||||
|
||||
next_block();
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
|
||||
next_block();
|
||||
assert_eq!(Balances::free_balance(42), 3);
|
||||
});
|
||||
@@ -92,7 +94,7 @@ fn delayed_enactment_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
1,
|
||||
);
|
||||
@@ -118,19 +120,19 @@ fn lowest_unbaked_should_be_sensible() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let r1 = Democracy::inject_referendum(
|
||||
3,
|
||||
set_balance_proposal_hash_and_note(1),
|
||||
set_balance_proposal(1),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
let r2 = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
let r3 = Democracy::inject_referendum(
|
||||
10,
|
||||
set_balance_proposal_hash_and_note(3),
|
||||
set_balance_proposal(3),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
@@ -141,16 +143,19 @@ fn lowest_unbaked_should_be_sensible() {
|
||||
assert_eq!(Democracy::lowest_unbaked(), 0);
|
||||
|
||||
next_block();
|
||||
|
||||
// r2 is approved
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
// r2 ends with approval
|
||||
assert_eq!(Democracy::lowest_unbaked(), 0);
|
||||
|
||||
next_block();
|
||||
|
||||
// r1 is approved
|
||||
assert_eq!(Balances::free_balance(42), 1);
|
||||
// r1 ends with approval
|
||||
assert_eq!(Democracy::lowest_unbaked(), 3);
|
||||
assert_eq!(Democracy::lowest_unbaked(), Democracy::referendum_count());
|
||||
|
||||
// r2 is executed
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
|
||||
next_block();
|
||||
// r1 is executed
|
||||
assert_eq!(Balances::free_balance(42), 1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ fn split_vote_cancellation_should_work() {
|
||||
fn single_proposal_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::set_block_number(0);
|
||||
assert_ok!(propose_set_balance_and_note(1, 2, 1));
|
||||
assert_ok!(propose_set_balance(1, 2, 1));
|
||||
let r = 0;
|
||||
assert!(Democracy::referendum_info(r).is_none());
|
||||
|
||||
@@ -76,7 +76,7 @@ fn single_proposal_should_work() {
|
||||
Democracy::referendum_status(0),
|
||||
Ok(ReferendumStatus {
|
||||
end: 4,
|
||||
proposal_hash: set_balance_proposal_hash_and_note(2),
|
||||
proposal: set_balance_proposal(2),
|
||||
threshold: VoteThreshold::SuperMajorityApprove,
|
||||
delay: 2,
|
||||
tally: Tally { ayes: 1, nays: 0, turnout: 10 },
|
||||
@@ -106,7 +106,7 @@ fn controversial_voting_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
@@ -132,7 +132,7 @@ fn controversial_low_turnout_voting_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
@@ -156,7 +156,7 @@ fn passing_low_turnout_voting_should_work() {
|
||||
|
||||
let r = Democracy::inject_referendum(
|
||||
2,
|
||||
set_balance_proposal_hash_and_note(2),
|
||||
set_balance_proposal(2),
|
||||
VoteThreshold::SuperMajorityApprove,
|
||||
0,
|
||||
);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//! Miscellaneous additional datatypes.
|
||||
|
||||
use crate::{AccountVote, Conviction, Vote, VoteThreshold};
|
||||
use codec::{Decode, Encode};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{
|
||||
traits::{Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Saturating, Zero},
|
||||
@@ -26,7 +26,7 @@ use sp_runtime::{
|
||||
};
|
||||
|
||||
/// Info regarding an ongoing referendum.
|
||||
#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
||||
#[derive(Encode, MaxEncodedLen, Decode, Default, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
||||
pub struct Tally<Balance> {
|
||||
/// The number of aye votes, expressed in terms of post-conviction lock-vote.
|
||||
pub ayes: Balance,
|
||||
@@ -37,7 +37,9 @@ pub struct Tally<Balance> {
|
||||
}
|
||||
|
||||
/// Amount of votes and capital placed in delegation for an account.
|
||||
#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
||||
#[derive(
|
||||
Encode, MaxEncodedLen, Decode, Default, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo,
|
||||
)]
|
||||
pub struct Delegations<Balance> {
|
||||
/// The number of votes (this is post-conviction).
|
||||
pub votes: Balance,
|
||||
@@ -160,12 +162,12 @@ impl<
|
||||
}
|
||||
|
||||
/// Info regarding an ongoing referendum.
|
||||
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
||||
pub struct ReferendumStatus<BlockNumber, Hash, Balance> {
|
||||
#[derive(Encode, MaxEncodedLen, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
||||
pub struct ReferendumStatus<BlockNumber, Proposal, Balance> {
|
||||
/// When voting on this referendum will end.
|
||||
pub end: BlockNumber,
|
||||
/// The hash of the proposal being voted on.
|
||||
pub proposal_hash: Hash,
|
||||
/// The proposal being voted on.
|
||||
pub proposal: Proposal,
|
||||
/// The thresholding mechanism to determine whether it passed.
|
||||
pub threshold: VoteThreshold,
|
||||
/// The delay (in blocks) to wait after a successful referendum before deploying.
|
||||
@@ -175,23 +177,23 @@ pub struct ReferendumStatus<BlockNumber, Hash, Balance> {
|
||||
}
|
||||
|
||||
/// Info regarding a referendum, present or past.
|
||||
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
||||
pub enum ReferendumInfo<BlockNumber, Hash, Balance> {
|
||||
#[derive(Encode, MaxEncodedLen, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
||||
pub enum ReferendumInfo<BlockNumber, Proposal, Balance> {
|
||||
/// Referendum is happening, the arg is the block number at which it will end.
|
||||
Ongoing(ReferendumStatus<BlockNumber, Hash, Balance>),
|
||||
Ongoing(ReferendumStatus<BlockNumber, Proposal, Balance>),
|
||||
/// Referendum finished at `end`, and has been `approved` or rejected.
|
||||
Finished { approved: bool, end: BlockNumber },
|
||||
}
|
||||
|
||||
impl<BlockNumber, Hash, Balance: Default> ReferendumInfo<BlockNumber, Hash, Balance> {
|
||||
impl<BlockNumber, Proposal, Balance: Default> ReferendumInfo<BlockNumber, Proposal, Balance> {
|
||||
/// Create a new instance.
|
||||
pub fn new(
|
||||
end: BlockNumber,
|
||||
proposal_hash: Hash,
|
||||
proposal: Proposal,
|
||||
threshold: VoteThreshold,
|
||||
delay: BlockNumber,
|
||||
) -> Self {
|
||||
let s = ReferendumStatus { end, proposal_hash, threshold, delay, tally: Tally::default() };
|
||||
let s = ReferendumStatus { end, proposal, threshold, delay, tally: Tally::default() };
|
||||
ReferendumInfo::Ongoing(s)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,12 @@
|
||||
//! The vote datatype.
|
||||
|
||||
use crate::{Conviction, Delegations, ReferendumIndex};
|
||||
use codec::{Decode, Encode, EncodeLike, Input, Output};
|
||||
use codec::{Decode, Encode, EncodeLike, Input, MaxEncodedLen, Output};
|
||||
use frame_support::traits::Get;
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{
|
||||
traits::{Saturating, Zero},
|
||||
RuntimeDebug,
|
||||
BoundedVec, RuntimeDebug,
|
||||
};
|
||||
use sp_std::prelude::*;
|
||||
|
||||
@@ -39,6 +40,12 @@ impl Encode for Vote {
|
||||
}
|
||||
}
|
||||
|
||||
impl MaxEncodedLen for Vote {
|
||||
fn max_encoded_len() -> usize {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
impl EncodeLike for Vote {}
|
||||
|
||||
impl Decode for Vote {
|
||||
@@ -66,7 +73,7 @@ impl TypeInfo for Vote {
|
||||
}
|
||||
|
||||
/// A vote for a referendum of a particular account.
|
||||
#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo)]
|
||||
#[derive(Encode, MaxEncodedLen, Decode, Copy, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo)]
|
||||
pub enum AccountVote<Balance> {
|
||||
/// A standard vote, one-way (approve or reject) with a given amount of conviction.
|
||||
Standard { vote: Vote, balance: Balance },
|
||||
@@ -107,7 +114,18 @@ impl<Balance: Saturating> AccountVote<Balance> {
|
||||
|
||||
/// A "prior" lock, i.e. a lock for some now-forgotten reason.
|
||||
#[derive(
|
||||
Encode, Decode, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug, TypeInfo,
|
||||
Encode,
|
||||
MaxEncodedLen,
|
||||
Decode,
|
||||
Default,
|
||||
Copy,
|
||||
Clone,
|
||||
Eq,
|
||||
PartialEq,
|
||||
Ord,
|
||||
PartialOrd,
|
||||
RuntimeDebug,
|
||||
TypeInfo,
|
||||
)]
|
||||
pub struct PriorLock<BlockNumber, Balance>(BlockNumber, Balance);
|
||||
|
||||
@@ -131,13 +149,15 @@ impl<BlockNumber: Ord + Copy + Zero, Balance: Ord + Copy + Zero> PriorLock<Block
|
||||
}
|
||||
|
||||
/// An indicator for what an account is doing; it can either be delegating or voting.
|
||||
#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo)]
|
||||
pub enum Voting<Balance, AccountId, BlockNumber> {
|
||||
#[derive(Clone, Encode, Decode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)]
|
||||
#[codec(mel_bound(skip_type_params(MaxVotes)))]
|
||||
#[scale_info(skip_type_params(MaxVotes))]
|
||||
pub enum Voting<Balance, AccountId, BlockNumber, MaxVotes: Get<u32>> {
|
||||
/// The account is voting directly. `delegations` is the total amount of post-conviction voting
|
||||
/// weight that it controls from those that have delegated to it.
|
||||
Direct {
|
||||
/// The current votes of the account.
|
||||
votes: Vec<(ReferendumIndex, AccountVote<Balance>)>,
|
||||
votes: BoundedVec<(ReferendumIndex, AccountVote<Balance>), MaxVotes>,
|
||||
/// The total amount of delegations that this account has received.
|
||||
delegations: Delegations<Balance>,
|
||||
/// Any pre-existing locks from past voting/delegating activity.
|
||||
@@ -155,20 +175,24 @@ pub enum Voting<Balance, AccountId, BlockNumber> {
|
||||
},
|
||||
}
|
||||
|
||||
impl<Balance: Default, AccountId, BlockNumber: Zero> Default
|
||||
for Voting<Balance, AccountId, BlockNumber>
|
||||
impl<Balance: Default, AccountId, BlockNumber: Zero, MaxVotes: Get<u32>> Default
|
||||
for Voting<Balance, AccountId, BlockNumber, MaxVotes>
|
||||
{
|
||||
fn default() -> Self {
|
||||
Voting::Direct {
|
||||
votes: Vec::new(),
|
||||
votes: Default::default(),
|
||||
delegations: Default::default(),
|
||||
prior: PriorLock(Zero::zero(), Default::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Balance: Saturating + Ord + Zero + Copy, BlockNumber: Ord + Copy + Zero, AccountId>
|
||||
Voting<Balance, AccountId, BlockNumber>
|
||||
impl<
|
||||
Balance: Saturating + Ord + Zero + Copy,
|
||||
BlockNumber: Ord + Copy + Zero,
|
||||
AccountId,
|
||||
MaxVotes: Get<u32>,
|
||||
> Voting<Balance, AccountId, BlockNumber, MaxVotes>
|
||||
{
|
||||
pub fn rejig(&mut self, now: BlockNumber) {
|
||||
match self {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//! Voting thresholds.
|
||||
|
||||
use crate::Tally;
|
||||
use codec::{Decode, Encode};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use scale_info::TypeInfo;
|
||||
#[cfg(feature = "std")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -26,7 +26,9 @@ use sp_runtime::traits::{IntegerSquareRoot, Zero};
|
||||
use sp_std::ops::{Add, Div, Mul, Rem};
|
||||
|
||||
/// A means of determining if a vote is past pass threshold.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, sp_runtime::RuntimeDebug, TypeInfo)]
|
||||
#[derive(
|
||||
Clone, Copy, PartialEq, Eq, Encode, MaxEncodedLen, Decode, sp_runtime::RuntimeDebug, TypeInfo,
|
||||
)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
||||
pub enum VoteThreshold {
|
||||
/// A supermajority of approvals is needed to pass this vote.
|
||||
|
||||
@@ -18,22 +18,24 @@
|
||||
//! Autogenerated weights for pallet_democracy
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2022-05-23, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! DATE: 2022-10-03, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/production/substrate
|
||||
// /home/benchbot/cargo_target_dir/production/substrate
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=pallet_democracy
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --template=./.maintain/frame-weight-template.hbs
|
||||
// --heap-pages=4096
|
||||
// --pallet=pallet_democracy
|
||||
// --chain=dev
|
||||
// --output=./frame/democracy/src/weights.rs
|
||||
// --template=./.maintain/frame-weight-template.hbs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
@@ -45,27 +47,23 @@ use sp_std::marker::PhantomData;
|
||||
/// Weight functions needed for pallet_democracy.
|
||||
pub trait WeightInfo {
|
||||
fn propose() -> Weight;
|
||||
fn second(s: u32, ) -> Weight;
|
||||
fn vote_new(r: u32, ) -> Weight;
|
||||
fn vote_existing(r: u32, ) -> Weight;
|
||||
fn second() -> Weight;
|
||||
fn vote_new() -> Weight;
|
||||
fn vote_existing() -> Weight;
|
||||
fn emergency_cancel() -> Weight;
|
||||
fn blacklist(p: u32, ) -> Weight;
|
||||
fn external_propose(v: u32, ) -> Weight;
|
||||
fn blacklist() -> Weight;
|
||||
fn external_propose() -> Weight;
|
||||
fn external_propose_majority() -> Weight;
|
||||
fn external_propose_default() -> Weight;
|
||||
fn fast_track() -> Weight;
|
||||
fn veto_external(v: u32, ) -> Weight;
|
||||
fn cancel_proposal(p: u32, ) -> Weight;
|
||||
fn veto_external() -> Weight;
|
||||
fn cancel_proposal() -> Weight;
|
||||
fn cancel_referendum() -> Weight;
|
||||
fn cancel_queued(r: u32, ) -> Weight;
|
||||
fn on_initialize_base(r: u32, ) -> Weight;
|
||||
fn on_initialize_base_with_launch_period(r: u32, ) -> Weight;
|
||||
fn delegate(r: u32, ) -> Weight;
|
||||
fn undelegate(r: u32, ) -> Weight;
|
||||
fn clear_public_proposals() -> Weight;
|
||||
fn note_preimage(b: u32, ) -> Weight;
|
||||
fn note_imminent_preimage(b: u32, ) -> Weight;
|
||||
fn reap_preimage(b: u32, ) -> Weight;
|
||||
fn unlock_remove(r: u32, ) -> Weight;
|
||||
fn unlock_set(r: u32, ) -> Weight;
|
||||
fn remove_vote(r: u32, ) -> Weight;
|
||||
@@ -80,125 +78,103 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Storage: Democracy Blacklist (r:1 w:0)
|
||||
// Storage: Democracy DepositOf (r:0 w:1)
|
||||
fn propose() -> Weight {
|
||||
Weight::from_ref_time(48_328_000 as u64)
|
||||
Weight::from_ref_time(57_410_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy DepositOf (r:1 w:1)
|
||||
fn second(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(30_923_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(142_000 as u64).saturating_mul(s as u64))
|
||||
fn second() -> Weight {
|
||||
Weight::from_ref_time(49_224_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy VotingOf (r:1 w:1)
|
||||
// Storage: Balances Locks (r:1 w:1)
|
||||
fn vote_new(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(40_345_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(140_000 as u64).saturating_mul(r as u64))
|
||||
fn vote_new() -> Weight {
|
||||
Weight::from_ref_time(60_933_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy VotingOf (r:1 w:1)
|
||||
// Storage: Balances Locks (r:1 w:1)
|
||||
fn vote_existing(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(39_853_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(150_000 as u64).saturating_mul(r as u64))
|
||||
fn vote_existing() -> Weight {
|
||||
Weight::from_ref_time(60_393_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy Cancellations (r:1 w:1)
|
||||
fn emergency_cancel() -> Weight {
|
||||
Weight::from_ref_time(19_364_000 as u64)
|
||||
Weight::from_ref_time(24_588_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Democracy PublicProps (r:1 w:1)
|
||||
// Storage: Democracy DepositOf (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:1)
|
||||
// Storage: Democracy NextExternal (r:1 w:1)
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy Blacklist (r:0 w:1)
|
||||
// Storage: Democracy DepositOf (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:1)
|
||||
fn blacklist(p: u32, ) -> Weight {
|
||||
Weight::from_ref_time(57_708_000 as u64)
|
||||
// Standard Error: 4_000
|
||||
.saturating_add(Weight::from_ref_time(192_000 as u64).saturating_mul(p as u64))
|
||||
fn blacklist() -> Weight {
|
||||
Weight::from_ref_time(91_226_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(5 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(6 as u64))
|
||||
}
|
||||
// Storage: Democracy NextExternal (r:1 w:1)
|
||||
// Storage: Democracy Blacklist (r:1 w:0)
|
||||
fn external_propose(v: u32, ) -> Weight {
|
||||
Weight::from_ref_time(10_714_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(33_000 as u64).saturating_mul(v as u64))
|
||||
fn external_propose() -> Weight {
|
||||
Weight::from_ref_time(18_898_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy NextExternal (r:0 w:1)
|
||||
fn external_propose_majority() -> Weight {
|
||||
Weight::from_ref_time(3_697_000 as u64)
|
||||
Weight::from_ref_time(5_136_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy NextExternal (r:0 w:1)
|
||||
fn external_propose_default() -> Weight {
|
||||
Weight::from_ref_time(3_831_000 as u64)
|
||||
Weight::from_ref_time(5_243_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy NextExternal (r:1 w:1)
|
||||
// Storage: Democracy ReferendumCount (r:1 w:1)
|
||||
// Storage: Democracy ReferendumInfoOf (r:0 w:1)
|
||||
fn fast_track() -> Weight {
|
||||
Weight::from_ref_time(20_271_000 as u64)
|
||||
Weight::from_ref_time(24_275_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy NextExternal (r:1 w:1)
|
||||
// Storage: Democracy Blacklist (r:1 w:1)
|
||||
fn veto_external(v: u32, ) -> Weight {
|
||||
Weight::from_ref_time(21_319_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(52_000 as u64).saturating_mul(v as u64))
|
||||
fn veto_external() -> Weight {
|
||||
Weight::from_ref_time(30_988_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Democracy PublicProps (r:1 w:1)
|
||||
// Storage: Democracy DepositOf (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:1)
|
||||
fn cancel_proposal(p: u32, ) -> Weight {
|
||||
Weight::from_ref_time(43_960_000 as u64)
|
||||
// Standard Error: 2_000
|
||||
.saturating_add(Weight::from_ref_time(184_000 as u64).saturating_mul(p as u64))
|
||||
fn cancel_proposal() -> Weight {
|
||||
Weight::from_ref_time(78_515_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy ReferendumInfoOf (r:0 w:1)
|
||||
fn cancel_referendum() -> Weight {
|
||||
Weight::from_ref_time(13_475_000 as u64)
|
||||
Weight::from_ref_time(16_155_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Scheduler Lookup (r:1 w:1)
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
fn cancel_queued(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(24_320_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(560_000 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Democracy LowestUnbaked (r:1 w:1)
|
||||
// Storage: Democracy ReferendumCount (r:1 w:0)
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:0)
|
||||
// Storage: Democracy ReferendumInfoOf (r:2 w:0)
|
||||
/// The range of component `r` is `[0, 99]`.
|
||||
fn on_initialize_base(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(3_428_000 as u64)
|
||||
// Standard Error: 2_000
|
||||
.saturating_add(Weight::from_ref_time(3_171_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(7_007_000 as u64)
|
||||
// Standard Error: 2_686
|
||||
.saturating_add(Weight::from_ref_time(2_288_781 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
@@ -208,33 +184,36 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Storage: Democracy LastTabledWasExternal (r:1 w:0)
|
||||
// Storage: Democracy NextExternal (r:1 w:0)
|
||||
// Storage: Democracy PublicProps (r:1 w:0)
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:0)
|
||||
// Storage: Democracy ReferendumInfoOf (r:2 w:0)
|
||||
/// The range of component `r` is `[0, 99]`.
|
||||
fn on_initialize_base_with_launch_period(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(7_867_000 as u64)
|
||||
// Standard Error: 2_000
|
||||
.saturating_add(Weight::from_ref_time(3_177_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(9_528_000 as u64)
|
||||
// Standard Error: 2_521
|
||||
.saturating_add(Weight::from_ref_time(2_291_780 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(5 as u64))
|
||||
.saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy VotingOf (r:3 w:3)
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Balances Locks (r:1 w:1)
|
||||
// Storage: Democracy ReferendumInfoOf (r:2 w:2)
|
||||
/// The range of component `r` is `[0, 99]`.
|
||||
fn delegate(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(37_902_000 as u64)
|
||||
// Standard Error: 4_000
|
||||
.saturating_add(Weight::from_ref_time(4_335_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(46_787_000 as u64)
|
||||
// Standard Error: 2_943
|
||||
.saturating_add(Weight::from_ref_time(3_460_194 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(4 as u64))
|
||||
.saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(4 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(r as u64)))
|
||||
}
|
||||
// Storage: Democracy VotingOf (r:2 w:2)
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy ReferendumInfoOf (r:2 w:2)
|
||||
/// The range of component `r` is `[0, 99]`.
|
||||
fn undelegate(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(21_272_000 as u64)
|
||||
// Standard Error: 3_000
|
||||
.saturating_add(Weight::from_ref_time(4_351_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(29_789_000 as u64)
|
||||
// Standard Error: 2_324
|
||||
.saturating_add(Weight::from_ref_time(3_360_918 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
@@ -242,69 +221,48 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
}
|
||||
// Storage: Democracy PublicProps (r:0 w:1)
|
||||
fn clear_public_proposals() -> Weight {
|
||||
Weight::from_ref_time(4_913_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy Preimages (r:1 w:1)
|
||||
fn note_preimage(b: u32, ) -> Weight {
|
||||
Weight::from_ref_time(27_986_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(b as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy Preimages (r:1 w:1)
|
||||
fn note_imminent_preimage(b: u32, ) -> Weight {
|
||||
Weight::from_ref_time(20_058_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(b as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy Preimages (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:0)
|
||||
fn reap_preimage(b: u32, ) -> Weight {
|
||||
Weight::from_ref_time(28_619_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(1_000 as u64).saturating_mul(b as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
Weight::from_ref_time(6_519_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy VotingOf (r:1 w:1)
|
||||
// Storage: Balances Locks (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:1)
|
||||
/// The range of component `r` is `[0, 99]`.
|
||||
fn unlock_remove(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(26_619_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(56_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(28_884_000 as u64)
|
||||
// Standard Error: 2_631
|
||||
.saturating_add(Weight::from_ref_time(163_516 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(3 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy VotingOf (r:1 w:1)
|
||||
// Storage: Balances Locks (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:1)
|
||||
/// The range of component `r` is `[0, 99]`.
|
||||
fn unlock_set(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(25_373_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(142_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(33_498_000 as u64)
|
||||
// Standard Error: 622
|
||||
.saturating_add(Weight::from_ref_time(133_421 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(3 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy VotingOf (r:1 w:1)
|
||||
/// The range of component `r` is `[1, 100]`.
|
||||
fn remove_vote(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(15_961_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(115_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(18_201_000 as u64)
|
||||
// Standard Error: 1_007
|
||||
.saturating_add(Weight::from_ref_time(152_699 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy VotingOf (r:1 w:1)
|
||||
/// The range of component `r` is `[1, 100]`.
|
||||
fn remove_other_vote(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(15_992_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(113_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(18_455_000 as u64)
|
||||
// Standard Error: 951
|
||||
.saturating_add(Weight::from_ref_time(150_907 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
@@ -317,125 +275,103 @@ impl WeightInfo for () {
|
||||
// Storage: Democracy Blacklist (r:1 w:0)
|
||||
// Storage: Democracy DepositOf (r:0 w:1)
|
||||
fn propose() -> Weight {
|
||||
Weight::from_ref_time(48_328_000 as u64)
|
||||
Weight::from_ref_time(57_410_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy DepositOf (r:1 w:1)
|
||||
fn second(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(30_923_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(142_000 as u64).saturating_mul(s as u64))
|
||||
fn second() -> Weight {
|
||||
Weight::from_ref_time(49_224_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy VotingOf (r:1 w:1)
|
||||
// Storage: Balances Locks (r:1 w:1)
|
||||
fn vote_new(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(40_345_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(140_000 as u64).saturating_mul(r as u64))
|
||||
fn vote_new() -> Weight {
|
||||
Weight::from_ref_time(60_933_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy VotingOf (r:1 w:1)
|
||||
// Storage: Balances Locks (r:1 w:1)
|
||||
fn vote_existing(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(39_853_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(150_000 as u64).saturating_mul(r as u64))
|
||||
fn vote_existing() -> Weight {
|
||||
Weight::from_ref_time(60_393_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy Cancellations (r:1 w:1)
|
||||
fn emergency_cancel() -> Weight {
|
||||
Weight::from_ref_time(19_364_000 as u64)
|
||||
Weight::from_ref_time(24_588_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Democracy PublicProps (r:1 w:1)
|
||||
// Storage: Democracy DepositOf (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:1)
|
||||
// Storage: Democracy NextExternal (r:1 w:1)
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy Blacklist (r:0 w:1)
|
||||
// Storage: Democracy DepositOf (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:1)
|
||||
fn blacklist(p: u32, ) -> Weight {
|
||||
Weight::from_ref_time(57_708_000 as u64)
|
||||
// Standard Error: 4_000
|
||||
.saturating_add(Weight::from_ref_time(192_000 as u64).saturating_mul(p as u64))
|
||||
fn blacklist() -> Weight {
|
||||
Weight::from_ref_time(91_226_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(5 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(6 as u64))
|
||||
}
|
||||
// Storage: Democracy NextExternal (r:1 w:1)
|
||||
// Storage: Democracy Blacklist (r:1 w:0)
|
||||
fn external_propose(v: u32, ) -> Weight {
|
||||
Weight::from_ref_time(10_714_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(33_000 as u64).saturating_mul(v as u64))
|
||||
fn external_propose() -> Weight {
|
||||
Weight::from_ref_time(18_898_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy NextExternal (r:0 w:1)
|
||||
fn external_propose_majority() -> Weight {
|
||||
Weight::from_ref_time(3_697_000 as u64)
|
||||
Weight::from_ref_time(5_136_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy NextExternal (r:0 w:1)
|
||||
fn external_propose_default() -> Weight {
|
||||
Weight::from_ref_time(3_831_000 as u64)
|
||||
Weight::from_ref_time(5_243_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy NextExternal (r:1 w:1)
|
||||
// Storage: Democracy ReferendumCount (r:1 w:1)
|
||||
// Storage: Democracy ReferendumInfoOf (r:0 w:1)
|
||||
fn fast_track() -> Weight {
|
||||
Weight::from_ref_time(20_271_000 as u64)
|
||||
Weight::from_ref_time(24_275_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy NextExternal (r:1 w:1)
|
||||
// Storage: Democracy Blacklist (r:1 w:1)
|
||||
fn veto_external(v: u32, ) -> Weight {
|
||||
Weight::from_ref_time(21_319_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(52_000 as u64).saturating_mul(v as u64))
|
||||
fn veto_external() -> Weight {
|
||||
Weight::from_ref_time(30_988_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Democracy PublicProps (r:1 w:1)
|
||||
// Storage: Democracy DepositOf (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:1)
|
||||
fn cancel_proposal(p: u32, ) -> Weight {
|
||||
Weight::from_ref_time(43_960_000 as u64)
|
||||
// Standard Error: 2_000
|
||||
.saturating_add(Weight::from_ref_time(184_000 as u64).saturating_mul(p as u64))
|
||||
fn cancel_proposal() -> Weight {
|
||||
Weight::from_ref_time(78_515_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy ReferendumInfoOf (r:0 w:1)
|
||||
fn cancel_referendum() -> Weight {
|
||||
Weight::from_ref_time(13_475_000 as u64)
|
||||
Weight::from_ref_time(16_155_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Scheduler Lookup (r:1 w:1)
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
fn cancel_queued(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(24_320_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(560_000 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Democracy LowestUnbaked (r:1 w:1)
|
||||
// Storage: Democracy ReferendumCount (r:1 w:0)
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:0)
|
||||
// Storage: Democracy ReferendumInfoOf (r:2 w:0)
|
||||
/// The range of component `r` is `[0, 99]`.
|
||||
fn on_initialize_base(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(3_428_000 as u64)
|
||||
// Standard Error: 2_000
|
||||
.saturating_add(Weight::from_ref_time(3_171_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(7_007_000 as u64)
|
||||
// Standard Error: 2_686
|
||||
.saturating_add(Weight::from_ref_time(2_288_781 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(r as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
@@ -445,33 +381,36 @@ impl WeightInfo for () {
|
||||
// Storage: Democracy LastTabledWasExternal (r:1 w:0)
|
||||
// Storage: Democracy NextExternal (r:1 w:0)
|
||||
// Storage: Democracy PublicProps (r:1 w:0)
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:0)
|
||||
// Storage: Democracy ReferendumInfoOf (r:2 w:0)
|
||||
/// The range of component `r` is `[0, 99]`.
|
||||
fn on_initialize_base_with_launch_period(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(7_867_000 as u64)
|
||||
// Standard Error: 2_000
|
||||
.saturating_add(Weight::from_ref_time(3_177_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(9_528_000 as u64)
|
||||
// Standard Error: 2_521
|
||||
.saturating_add(Weight::from_ref_time(2_291_780 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(5 as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(r as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy VotingOf (r:3 w:3)
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Balances Locks (r:1 w:1)
|
||||
// Storage: Democracy ReferendumInfoOf (r:2 w:2)
|
||||
/// The range of component `r` is `[0, 99]`.
|
||||
fn delegate(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(37_902_000 as u64)
|
||||
// Standard Error: 4_000
|
||||
.saturating_add(Weight::from_ref_time(4_335_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(46_787_000 as u64)
|
||||
// Standard Error: 2_943
|
||||
.saturating_add(Weight::from_ref_time(3_460_194 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(4 as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(r as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(4 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(r as u64)))
|
||||
}
|
||||
// Storage: Democracy VotingOf (r:2 w:2)
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy ReferendumInfoOf (r:2 w:2)
|
||||
/// The range of component `r` is `[0, 99]`.
|
||||
fn undelegate(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(21_272_000 as u64)
|
||||
// Standard Error: 3_000
|
||||
.saturating_add(Weight::from_ref_time(4_351_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(29_789_000 as u64)
|
||||
// Standard Error: 2_324
|
||||
.saturating_add(Weight::from_ref_time(3_360_918 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(r as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
@@ -479,69 +418,48 @@ impl WeightInfo for () {
|
||||
}
|
||||
// Storage: Democracy PublicProps (r:0 w:1)
|
||||
fn clear_public_proposals() -> Weight {
|
||||
Weight::from_ref_time(4_913_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy Preimages (r:1 w:1)
|
||||
fn note_preimage(b: u32, ) -> Weight {
|
||||
Weight::from_ref_time(27_986_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(b as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy Preimages (r:1 w:1)
|
||||
fn note_imminent_preimage(b: u32, ) -> Weight {
|
||||
Weight::from_ref_time(20_058_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(b as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy Preimages (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:0)
|
||||
fn reap_preimage(b: u32, ) -> Weight {
|
||||
Weight::from_ref_time(28_619_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(1_000 as u64).saturating_mul(b as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
Weight::from_ref_time(6_519_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Democracy VotingOf (r:1 w:1)
|
||||
// Storage: Balances Locks (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:1)
|
||||
/// The range of component `r` is `[0, 99]`.
|
||||
fn unlock_remove(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(26_619_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(56_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(28_884_000 as u64)
|
||||
// Standard Error: 2_631
|
||||
.saturating_add(Weight::from_ref_time(163_516 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy VotingOf (r:1 w:1)
|
||||
// Storage: Balances Locks (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:1)
|
||||
/// The range of component `r` is `[0, 99]`.
|
||||
fn unlock_set(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(25_373_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(142_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(33_498_000 as u64)
|
||||
// Standard Error: 622
|
||||
.saturating_add(Weight::from_ref_time(133_421 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3 as u64))
|
||||
}
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy VotingOf (r:1 w:1)
|
||||
/// The range of component `r` is `[1, 100]`.
|
||||
fn remove_vote(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(15_961_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(115_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(18_201_000 as u64)
|
||||
// Standard Error: 1_007
|
||||
.saturating_add(Weight::from_ref_time(152_699 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
|
||||
// Storage: Democracy VotingOf (r:1 w:1)
|
||||
/// The range of component `r` is `[1, 100]`.
|
||||
fn remove_other_vote(r: u32, ) -> Weight {
|
||||
Weight::from_ref_time(15_992_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(113_000 as u64).saturating_mul(r as u64))
|
||||
Weight::from_ref_time(18_455_000 as u64)
|
||||
// Standard Error: 951
|
||||
.saturating_add(Weight::from_ref_time(150_907 as u64).saturating_mul(r as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ fn registration_should_work() {
|
||||
let mut three_fields = ten();
|
||||
three_fields.additional.try_push(Default::default()).unwrap();
|
||||
three_fields.additional.try_push(Default::default()).unwrap();
|
||||
assert_eq!(three_fields.additional.try_push(Default::default()), Err(()));
|
||||
assert!(three_fields.additional.try_push(Default::default()).is_err());
|
||||
assert_ok!(Identity::set_identity(RuntimeOrigin::signed(10), Box::new(ten())));
|
||||
assert_eq!(Identity::identity(10).unwrap().info, ten());
|
||||
assert_eq!(Balances::free_balance(10), 90);
|
||||
|
||||
@@ -22,6 +22,9 @@ sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/
|
||||
sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" }
|
||||
sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" }
|
||||
|
||||
# third party
|
||||
log = { version = "0.4.17", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
pallet-balances = { version = "4.0.0-dev", path = "../balances" }
|
||||
sp-core = { version = "6.0.0", path = "../../primitives/core" }
|
||||
|
||||
@@ -31,7 +31,7 @@ const SEED: u32 = 0;
|
||||
fn setup_multi<T: Config>(
|
||||
s: u32,
|
||||
z: u32,
|
||||
) -> Result<(Vec<T::AccountId>, OpaqueCall<T>), &'static str> {
|
||||
) -> Result<(Vec<T::AccountId>, Box<<T as Config>::RuntimeCall>), &'static str> {
|
||||
let mut signatories: Vec<T::AccountId> = Vec::new();
|
||||
for i in 0..s {
|
||||
let signatory = account("signatory", i, SEED);
|
||||
@@ -44,8 +44,7 @@ fn setup_multi<T: Config>(
|
||||
// Must first convert to runtime call type.
|
||||
let call: <T as Config>::RuntimeCall =
|
||||
frame_system::Call::<T>::remark { remark: vec![0; z as usize] }.into();
|
||||
let call_data = OpaqueCall::<T>::from_encoded(call.encode());
|
||||
Ok((signatories, call_data))
|
||||
Ok((signatories, Box::new(call)))
|
||||
}
|
||||
|
||||
benchmarks! {
|
||||
@@ -74,35 +73,15 @@ benchmarks! {
|
||||
// Transaction Length
|
||||
let z in 0 .. 10_000;
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_hash = call.using_encoded(blake2_256);
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: as_multi(RawOrigin::Signed(caller), s as u16, signatories, None, call, false, Weight::zero())
|
||||
}: as_multi(RawOrigin::Signed(caller), s as u16, signatories, None, call, Weight::zero())
|
||||
verify {
|
||||
assert!(Multisigs::<T>::contains_key(multi_account_id, call_hash));
|
||||
assert!(!Calls::<T>::contains_key(call_hash));
|
||||
}
|
||||
|
||||
as_multi_create_store {
|
||||
// Signatories, need at least 2 total people
|
||||
let s in 2 .. T::MaxSignatories::get() as u32;
|
||||
// Transaction Length
|
||||
let z in 0 .. 10_000;
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: as_multi(RawOrigin::Signed(caller), s as u16, signatories, None, call, true, Weight::zero())
|
||||
verify {
|
||||
assert!(Multisigs::<T>::contains_key(multi_account_id, call_hash));
|
||||
assert!(Calls::<T>::contains_key(call_hash));
|
||||
}
|
||||
|
||||
as_multi_approve {
|
||||
@@ -111,78 +90,51 @@ benchmarks! {
|
||||
// Transaction Length
|
||||
let z in 0 .. 10_000;
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_hash = call.using_encoded(blake2_256);
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let mut signatories2 = signatories.clone();
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
// before the call, get the timepoint
|
||||
let timepoint = Multisig::<T>::timepoint();
|
||||
// Create the multi, storing for worst case
|
||||
Multisig::<T>::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), true, Weight::zero())?;
|
||||
assert!(Calls::<T>::contains_key(call_hash));
|
||||
// Create the multi
|
||||
Multisig::<T>::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), Weight::zero())?;
|
||||
let caller2 = signatories2.remove(0);
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller2);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, false, Weight::zero())
|
||||
}: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, Weight::zero())
|
||||
verify {
|
||||
let multisig = Multisigs::<T>::get(multi_account_id, call_hash).ok_or("multisig not created")?;
|
||||
assert_eq!(multisig.approvals.len(), 2);
|
||||
}
|
||||
|
||||
as_multi_approve_store {
|
||||
// Signatories, need at least 3 people (so we don't complete the multisig)
|
||||
let s in 3 .. T::MaxSignatories::get() as u32;
|
||||
// Transaction Length
|
||||
let z in 0 .. 10_000;
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let mut signatories2 = signatories.clone();
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
// before the call, get the timepoint
|
||||
let timepoint = Multisig::<T>::timepoint();
|
||||
// Create the multi, not storing
|
||||
Multisig::<T>::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), false, Weight::zero())?;
|
||||
assert!(!Calls::<T>::contains_key(call_hash));
|
||||
let caller2 = signatories2.remove(0);
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller2);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, true, Weight::zero())
|
||||
verify {
|
||||
let multisig = Multisigs::<T>::get(multi_account_id, call_hash).ok_or("multisig not created")?;
|
||||
assert_eq!(multisig.approvals.len(), 2);
|
||||
assert!(Calls::<T>::contains_key(call_hash));
|
||||
}
|
||||
|
||||
as_multi_complete {
|
||||
// Signatories, need at least 2 people
|
||||
let s in 2 .. T::MaxSignatories::get() as u32;
|
||||
// Transaction Length
|
||||
let z in 0 .. 10_000;
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_hash = call.using_encoded(blake2_256);
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let mut signatories2 = signatories.clone();
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
// before the call, get the timepoint
|
||||
let timepoint = Multisig::<T>::timepoint();
|
||||
// Create the multi, storing it for worst case
|
||||
Multisig::<T>::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), true, Weight::zero())?;
|
||||
// Create the multi
|
||||
Multisig::<T>::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), Weight::zero())?;
|
||||
// Everyone except the first person approves
|
||||
for i in 1 .. s - 1 {
|
||||
let mut signatories_loop = signatories2.clone();
|
||||
let caller_loop = signatories_loop.remove(i as usize);
|
||||
let o = RawOrigin::Signed(caller_loop).into();
|
||||
Multisig::<T>::as_multi(o, s as u16, signatories_loop, Some(timepoint), call.clone(), false, Weight::zero())?;
|
||||
Multisig::<T>::as_multi(o, s as u16, signatories_loop, Some(timepoint), call.clone(), Weight::zero())?;
|
||||
}
|
||||
let caller2 = signatories2.remove(0);
|
||||
assert!(Multisigs::<T>::contains_key(&multi_account_id, call_hash));
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller2);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, false, Weight::MAX)
|
||||
}: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call, Weight::MAX)
|
||||
verify {
|
||||
assert!(!Multisigs::<T>::contains_key(&multi_account_id, call_hash));
|
||||
}
|
||||
@@ -195,7 +147,7 @@ benchmarks! {
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_hash = call.using_encoded(blake2_256);
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
@@ -214,7 +166,7 @@ benchmarks! {
|
||||
let mut signatories2 = signatories.clone();
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_hash = call.using_encoded(blake2_256);
|
||||
// before the call, get the timepoint
|
||||
let timepoint = Multisig::<T>::timepoint();
|
||||
// Create the multi
|
||||
@@ -224,7 +176,6 @@ benchmarks! {
|
||||
signatories,
|
||||
None,
|
||||
call,
|
||||
false,
|
||||
Weight::zero()
|
||||
)?;
|
||||
let caller2 = signatories2.remove(0);
|
||||
@@ -237,45 +188,6 @@ benchmarks! {
|
||||
assert_eq!(multisig.approvals.len(), 2);
|
||||
}
|
||||
|
||||
approve_as_multi_complete {
|
||||
// Signatories, need at least 2 people
|
||||
let s in 2 .. T::MaxSignatories::get() as u32;
|
||||
// Transaction Length, not a component
|
||||
let z = 10_000;
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let mut signatories2 = signatories.clone();
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
// before the call, get the timepoint
|
||||
let timepoint = Multisig::<T>::timepoint();
|
||||
// Create the multi
|
||||
Multisig::<T>::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone(), true, Weight::zero())?;
|
||||
// Everyone except the first person approves
|
||||
for i in 1 .. s - 1 {
|
||||
let mut signatories_loop = signatories2.clone();
|
||||
let caller_loop = signatories_loop.remove(i as usize);
|
||||
let o = RawOrigin::Signed(caller_loop).into();
|
||||
Multisig::<T>::as_multi(o, s as u16, signatories_loop, Some(timepoint), call.clone(), false, Weight::zero())?;
|
||||
}
|
||||
let caller2 = signatories2.remove(0);
|
||||
assert!(Multisigs::<T>::contains_key(&multi_account_id, call_hash));
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller2);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: approve_as_multi(
|
||||
RawOrigin::Signed(caller2),
|
||||
s as u16,
|
||||
signatories2,
|
||||
Some(timepoint),
|
||||
call_hash,
|
||||
Weight::MAX
|
||||
)
|
||||
verify {
|
||||
assert!(!Multisigs::<T>::contains_key(multi_account_id, call_hash));
|
||||
}
|
||||
|
||||
cancel_as_multi {
|
||||
// Signatories, need at least 2 people
|
||||
let s in 2 .. T::MaxSignatories::get() as u32;
|
||||
@@ -284,20 +196,18 @@ benchmarks! {
|
||||
let (mut signatories, call) = setup_multi::<T>(s, z)?;
|
||||
let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap());
|
||||
let caller = signatories.pop().ok_or("signatories should have len 2 or more")?;
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_hash = call.using_encoded(blake2_256);
|
||||
let timepoint = Multisig::<T>::timepoint();
|
||||
// Create the multi
|
||||
let o = RawOrigin::Signed(caller.clone()).into();
|
||||
Multisig::<T>::as_multi(o, s as u16, signatories.clone(), None, call, true, Weight::zero())?;
|
||||
Multisig::<T>::as_multi(o, s as u16, signatories.clone(), None, call, Weight::zero())?;
|
||||
assert!(Multisigs::<T>::contains_key(&multi_account_id, call_hash));
|
||||
assert!(Calls::<T>::contains_key(call_hash));
|
||||
// Whitelist caller account from further DB operations.
|
||||
let caller_key = frame_system::Account::<T>::hashed_key_for(&caller);
|
||||
frame_benchmarking::benchmarking::add_to_whitelist(caller_key.into());
|
||||
}: _(RawOrigin::Signed(caller), s as u16, signatories, timepoint, call_hash)
|
||||
verify {
|
||||
assert!(!Multisigs::<T>::contains_key(multi_account_id, call_hash));
|
||||
assert!(!Calls::<T>::contains_key(call_hash));
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(Multisig, crate::tests::new_test_ext(), crate::tests::Test);
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
mod benchmarking;
|
||||
pub mod migrations;
|
||||
mod tests;
|
||||
pub mod weights;
|
||||
|
||||
@@ -57,7 +58,7 @@ use frame_support::{
|
||||
PostDispatchInfo,
|
||||
},
|
||||
ensure,
|
||||
traits::{Currency, Get, ReservableCurrency, WrapperKeepOpaque},
|
||||
traits::{Currency, Get, ReservableCurrency},
|
||||
weights::Weight,
|
||||
RuntimeDebug,
|
||||
};
|
||||
@@ -73,6 +74,20 @@ pub use weights::WeightInfo;
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
/// The log target of this pallet.
|
||||
pub const LOG_TARGET: &'static str = "runtime::multisig";
|
||||
|
||||
// syntactic sugar for logging.
|
||||
#[macro_export]
|
||||
macro_rules! log {
|
||||
($level:tt, $patter:expr $(, $values:expr)* $(,)?) => {
|
||||
log::$level!(
|
||||
target: crate::LOG_TARGET,
|
||||
concat!("[{:?}] ✍️ ", $patter), <frame_system::Pallet<T>>::block_number() $(, $values)*
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
type BalanceOf<T> =
|
||||
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
|
||||
|
||||
@@ -100,12 +115,10 @@ pub struct Multisig<BlockNumber, Balance, AccountId> {
|
||||
approvals: Vec<AccountId>,
|
||||
}
|
||||
|
||||
type OpaqueCall<T> = WrapperKeepOpaque<<T as Config>::RuntimeCall>;
|
||||
|
||||
type CallHash = [u8; 32];
|
||||
|
||||
enum CallOrHash<T: Config> {
|
||||
Call(OpaqueCall<T>, bool),
|
||||
Call(<T as Config>::RuntimeCall),
|
||||
Hash([u8; 32]),
|
||||
}
|
||||
|
||||
@@ -152,9 +165,13 @@ pub mod pallet {
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
/// The current storage version.
|
||||
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
|
||||
|
||||
#[pallet::pallet]
|
||||
#[pallet::generate_store(pub(super) trait Store)]
|
||||
#[pallet::without_storage_info]
|
||||
#[pallet::storage_version(STORAGE_VERSION)]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
/// The set of open multisig operations.
|
||||
@@ -168,10 +185,6 @@ pub mod pallet {
|
||||
Multisig<T::BlockNumber, BalanceOf<T>, T::AccountId>,
|
||||
>;
|
||||
|
||||
#[pallet::storage]
|
||||
pub type Calls<T: Config> =
|
||||
StorageMap<_, Identity, [u8; 32], (OpaqueCall<T>, T::AccountId, BalanceOf<T>)>;
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
/// Threshold must be 2 or greater.
|
||||
@@ -343,13 +356,13 @@ pub mod pallet {
|
||||
/// taken for its lifetime of `DepositBase + threshold * DepositFactor`.
|
||||
/// -------------------------------
|
||||
/// - DB Weight:
|
||||
/// - Reads: Multisig Storage, [Caller Account], Calls (if `store_call`)
|
||||
/// - Writes: Multisig Storage, [Caller Account], Calls (if `store_call`)
|
||||
/// - Reads: Multisig Storage, [Caller Account]
|
||||
/// - Writes: Multisig Storage, [Caller Account]
|
||||
/// - Plus Call Weight
|
||||
/// # </weight>
|
||||
#[pallet::weight({
|
||||
let s = other_signatories.len() as u32;
|
||||
let z = call.encoded_len() as u32;
|
||||
let z = call.using_encoded(|d| d.len()) as u32;
|
||||
|
||||
T::WeightInfo::as_multi_create(s, z)
|
||||
.max(T::WeightInfo::as_multi_create_store(s, z))
|
||||
@@ -362,8 +375,7 @@ pub mod pallet {
|
||||
threshold: u16,
|
||||
other_signatories: Vec<T::AccountId>,
|
||||
maybe_timepoint: Option<Timepoint<T::BlockNumber>>,
|
||||
call: OpaqueCall<T>,
|
||||
store_call: bool,
|
||||
call: Box<<T as Config>::RuntimeCall>,
|
||||
max_weight: Weight,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let who = ensure_signed(origin)?;
|
||||
@@ -372,7 +384,7 @@ pub mod pallet {
|
||||
threshold,
|
||||
other_signatories,
|
||||
maybe_timepoint,
|
||||
CallOrHash::Call(call, store_call),
|
||||
CallOrHash::Call(*call),
|
||||
max_weight,
|
||||
)
|
||||
}
|
||||
@@ -462,8 +474,8 @@ pub mod pallet {
|
||||
/// - Storage: removes one item.
|
||||
/// ----------------------------------
|
||||
/// - DB Weight:
|
||||
/// - Read: Multisig Storage, [Caller Account], Refund Account, Calls
|
||||
/// - Write: Multisig Storage, [Caller Account], Refund Account, Calls
|
||||
/// - Read: Multisig Storage, [Caller Account], Refund Account
|
||||
/// - Write: Multisig Storage, [Caller Account], Refund Account
|
||||
/// # </weight>
|
||||
#[pallet::weight(T::WeightInfo::cancel_as_multi(other_signatories.len() as u32))]
|
||||
pub fn cancel_as_multi(
|
||||
@@ -489,7 +501,6 @@ pub mod pallet {
|
||||
let err_amount = T::Currency::unreserve(&m.depositor, m.deposit);
|
||||
debug_assert!(err_amount.is_zero());
|
||||
<Multisigs<T>>::remove(&id, &call_hash);
|
||||
Self::clear_call(&call_hash);
|
||||
|
||||
Self::deposit_event(Event::MultisigCancelled {
|
||||
cancelling: who,
|
||||
@@ -531,13 +542,12 @@ impl<T: Config> Pallet<T> {
|
||||
let id = Self::multi_account_id(&signatories, threshold);
|
||||
|
||||
// Threshold > 1; this means it's a multi-step operation. We extract the `call_hash`.
|
||||
let (call_hash, call_len, maybe_call, store) = match call_or_hash {
|
||||
CallOrHash::Call(call, should_store) => {
|
||||
let call_hash = blake2_256(call.encoded());
|
||||
let call_len = call.encoded_len();
|
||||
(call_hash, call_len, Some(call), should_store)
|
||||
let (call_hash, call_len, maybe_call) = match call_or_hash {
|
||||
CallOrHash::Call(call) => {
|
||||
let (call_hash, call_len) = call.using_encoded(|d| (blake2_256(d), d.len()));
|
||||
(call_hash, call_len, Some(call))
|
||||
},
|
||||
CallOrHash::Hash(h) => (h, 0, None, false),
|
||||
CallOrHash::Hash(h) => (h, 0, None),
|
||||
};
|
||||
|
||||
// Branch on whether the operation has already started or not.
|
||||
@@ -556,13 +566,7 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
|
||||
// We only bother fetching/decoding call if we know that we're ready to execute.
|
||||
let maybe_approved_call = if approvals >= threshold {
|
||||
Self::get_call(&call_hash, maybe_call.as_ref())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some((call, call_len)) = maybe_approved_call {
|
||||
if let Some(call) = maybe_call.filter(|_| approvals >= threshold) {
|
||||
// verify weight
|
||||
ensure!(
|
||||
call.get_dispatch_info().weight.all_lte(max_weight),
|
||||
@@ -572,7 +576,6 @@ impl<T: Config> Pallet<T> {
|
||||
// Clean up storage before executing call to avoid an possibility of reentrancy
|
||||
// attack.
|
||||
<Multisigs<T>>::remove(&id, call_hash);
|
||||
Self::clear_call(&call_hash);
|
||||
T::Currency::unreserve(&m.depositor, m.deposit);
|
||||
|
||||
let result = call.dispatch(RawOrigin::Signed(id.clone()).into());
|
||||
@@ -596,19 +599,6 @@ impl<T: Config> Pallet<T> {
|
||||
// We cannot dispatch the call now; either it isn't available, or it is, but we
|
||||
// don't have threshold approvals even with our signature.
|
||||
|
||||
// Store the call if desired.
|
||||
let stored = if let Some(data) = maybe_call.filter(|_| store) {
|
||||
Self::store_call_and_reserve(
|
||||
who.clone(),
|
||||
&call_hash,
|
||||
data,
|
||||
BalanceOf::<T>::zero(),
|
||||
)?;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if let Some(pos) = maybe_pos {
|
||||
// Record approval.
|
||||
m.approvals.insert(pos, who.clone());
|
||||
@@ -622,17 +612,11 @@ impl<T: Config> Pallet<T> {
|
||||
} else {
|
||||
// If we already approved and didn't store the Call, then this was useless and
|
||||
// we report an error.
|
||||
ensure!(stored, Error::<T>::AlreadyApproved);
|
||||
Err(Error::<T>::AlreadyApproved)?
|
||||
}
|
||||
|
||||
let final_weight = if stored {
|
||||
T::WeightInfo::as_multi_approve_store(
|
||||
other_signatories_len as u32,
|
||||
call_len as u32,
|
||||
)
|
||||
} else {
|
||||
T::WeightInfo::as_multi_approve(other_signatories_len as u32, call_len as u32)
|
||||
};
|
||||
let final_weight =
|
||||
T::WeightInfo::as_multi_approve(other_signatories_len as u32, call_len as u32);
|
||||
// Call is not made, so the actual weight does not include call
|
||||
Ok(Some(final_weight).into())
|
||||
}
|
||||
@@ -643,14 +627,7 @@ impl<T: Config> Pallet<T> {
|
||||
// Just start the operation by recording it in storage.
|
||||
let deposit = T::DepositBase::get() + T::DepositFactor::get() * threshold.into();
|
||||
|
||||
// Store the call if desired.
|
||||
let stored = if let Some(data) = maybe_call.filter(|_| store) {
|
||||
Self::store_call_and_reserve(who.clone(), &call_hash, data, deposit)?;
|
||||
true
|
||||
} else {
|
||||
T::Currency::reserve(&who, deposit)?;
|
||||
false
|
||||
};
|
||||
T::Currency::reserve(&who, deposit)?;
|
||||
|
||||
<Multisigs<T>>::insert(
|
||||
&id,
|
||||
@@ -664,58 +641,13 @@ impl<T: Config> Pallet<T> {
|
||||
);
|
||||
Self::deposit_event(Event::NewMultisig { approving: who, multisig: id, call_hash });
|
||||
|
||||
let final_weight = if stored {
|
||||
T::WeightInfo::as_multi_create_store(other_signatories_len as u32, call_len as u32)
|
||||
} else {
|
||||
T::WeightInfo::as_multi_create(other_signatories_len as u32, call_len as u32)
|
||||
};
|
||||
let final_weight =
|
||||
T::WeightInfo::as_multi_create(other_signatories_len as u32, call_len as u32);
|
||||
// Call is not made, so the actual weight does not include call
|
||||
Ok(Some(final_weight).into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Place a call's encoded data in storage, reserving funds as appropriate.
|
||||
///
|
||||
/// We store `data` here because storing `call` would result in needing another `.encode`.
|
||||
///
|
||||
/// Returns a `bool` indicating whether the data did end up being stored.
|
||||
fn store_call_and_reserve(
|
||||
who: T::AccountId,
|
||||
hash: &[u8; 32],
|
||||
data: OpaqueCall<T>,
|
||||
other_deposit: BalanceOf<T>,
|
||||
) -> DispatchResult {
|
||||
ensure!(!Calls::<T>::contains_key(hash), Error::<T>::AlreadyStored);
|
||||
let deposit = other_deposit +
|
||||
T::DepositBase::get() +
|
||||
T::DepositFactor::get() *
|
||||
BalanceOf::<T>::from(((data.encoded_len() + 31) / 32) as u32);
|
||||
T::Currency::reserve(&who, deposit)?;
|
||||
Calls::<T>::insert(&hash, (data, who, deposit));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Attempt to decode and return the call, provided by the user or from storage.
|
||||
fn get_call(
|
||||
hash: &[u8; 32],
|
||||
maybe_known: Option<&OpaqueCall<T>>,
|
||||
) -> Option<(<T as Config>::RuntimeCall, usize)> {
|
||||
maybe_known.map_or_else(
|
||||
|| {
|
||||
Calls::<T>::get(hash)
|
||||
.and_then(|(data, ..)| Some((data.try_decode()?, data.encoded_len())))
|
||||
},
|
||||
|data| Some((data.try_decode()?, data.encoded_len())),
|
||||
)
|
||||
}
|
||||
|
||||
/// Attempt to remove a call from storage, returning any deposit on it to the owner.
|
||||
fn clear_call(hash: &[u8; 32]) {
|
||||
if let Some((_, who, deposit)) = Calls::<T>::take(hash) {
|
||||
T::Currency::unreserve(&who, deposit);
|
||||
}
|
||||
}
|
||||
|
||||
/// The current `Timepoint`.
|
||||
pub fn timepoint() -> Timepoint<T::BlockNumber> {
|
||||
Timepoint {
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2019-2022 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.
|
||||
|
||||
// Migrations for Multisig Pallet
|
||||
|
||||
use super::*;
|
||||
use frame_support::{
|
||||
dispatch::GetStorageVersion,
|
||||
traits::{OnRuntimeUpgrade, WrapperKeepOpaque},
|
||||
Identity,
|
||||
};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use frame_support::ensure;
|
||||
|
||||
pub mod v1 {
|
||||
use super::*;
|
||||
|
||||
type OpaqueCall<T> = WrapperKeepOpaque<<T as Config>::RuntimeCall>;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
type Calls<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
Identity,
|
||||
[u8; 32],
|
||||
(OpaqueCall<T>, <T as frame_system::Config>::AccountId, BalanceOf<T>),
|
||||
>;
|
||||
|
||||
pub struct MigrateToV1<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
let onchain = Pallet::<T>::on_chain_storage_version();
|
||||
|
||||
ensure!(onchain < 1, "this migration can be deleted");
|
||||
|
||||
log!(info, "Number of calls to refund and delete: {}", Calls::<T>::iter().count());
|
||||
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let current = Pallet::<T>::current_storage_version();
|
||||
let onchain = Pallet::<T>::on_chain_storage_version();
|
||||
|
||||
if onchain > 0 {
|
||||
log!(info, "MigrateToV1 should be removed");
|
||||
return T::DbWeight::get().reads(1)
|
||||
}
|
||||
|
||||
Calls::<T>::drain().for_each(|(_call_hash, (_data, caller, deposit))| {
|
||||
T::Currency::unreserve(&caller, deposit);
|
||||
});
|
||||
|
||||
current.put::<Pallet<T>>();
|
||||
|
||||
<T as frame_system::Config>::BlockWeights::get().max_block
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
|
||||
let onchain = Pallet::<T>::on_chain_storage_version();
|
||||
ensure!(onchain < 2, "this migration needs to be removed");
|
||||
ensure!(onchain == 1, "this migration needs to be run");
|
||||
ensure!(
|
||||
Calls::<T>::iter().count() == 0,
|
||||
"there are some dangling calls that need to be destroyed and refunded"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,6 @@ use sp_runtime::{
|
||||
|
||||
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
|
||||
type Block = frame_system::mocking::MockBlock<Test>;
|
||||
type OpaqueCall = super::OpaqueCall<Test>;
|
||||
|
||||
frame_support::construct_runtime!(
|
||||
pub enum Test where
|
||||
@@ -130,8 +129,8 @@ fn now() -> Timepoint<u64> {
|
||||
Multisig::timepoint()
|
||||
}
|
||||
|
||||
fn call_transfer(dest: u64, value: u64) -> RuntimeCall {
|
||||
RuntimeCall::Balances(BalancesCall::transfer { dest, value })
|
||||
fn call_transfer(dest: u64, value: u64) -> Box<RuntimeCall> {
|
||||
Box::new(RuntimeCall::Balances(BalancesCall::transfer { dest, value }))
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -144,14 +143,12 @@ fn multisig_deposit_is_taken_and_returned() {
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 2);
|
||||
@@ -162,8 +159,7 @@ fn multisig_deposit_is_taken_and_returned() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 5);
|
||||
@@ -171,96 +167,6 @@ fn multisig_deposit_is_taken_and_returned() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multisig_deposit_is_taken_and_returned_with_call_storage() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let multi = Multisig::multi_account_id(&[1, 2, 3][..], 2);
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(1), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(2), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(3), multi, 5));
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data),
|
||||
true,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 0);
|
||||
assert_eq!(Balances::reserved_balance(1), 5);
|
||||
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(2),
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
hash,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 5);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multisig_deposit_is_taken_and_returned_with_alt_call_storage() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let multi = Multisig::multi_account_id(&[1, 2, 3][..], 3);
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(1), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(2), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(3), multi, 5));
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
3,
|
||||
vec![2, 3],
|
||||
None,
|
||||
hash,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 1);
|
||||
assert_eq!(Balances::reserved_balance(1), 4);
|
||||
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(2),
|
||||
3,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
true,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(2), 3);
|
||||
assert_eq!(Balances::reserved_balance(2), 2);
|
||||
assert_eq!(Balances::free_balance(1), 1);
|
||||
assert_eq!(Balances::reserved_balance(1), 4);
|
||||
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(3),
|
||||
3,
|
||||
vec![1, 2],
|
||||
Some(now()),
|
||||
hash,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 5);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
assert_eq!(Balances::free_balance(2), 5);
|
||||
assert_eq!(Balances::reserved_balance(2), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_multisig_returns_deposit() {
|
||||
new_test_ext().execute_with(|| {
|
||||
@@ -298,8 +204,8 @@ fn timepoint_checking_works() {
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(2), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(3), multi, 5));
|
||||
|
||||
let call = call_transfer(6, 15).encode();
|
||||
let hash = blake2_256(&call);
|
||||
let call = call_transfer(6, 15);
|
||||
let hash = blake2_256(&call.encode());
|
||||
|
||||
assert_noop!(
|
||||
Multisig::approve_as_multi(
|
||||
@@ -328,8 +234,7 @@ fn timepoint_checking_works() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(call.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::NoTimepoint,
|
||||
@@ -341,8 +246,7 @@ fn timepoint_checking_works() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(later),
|
||||
OpaqueCall::from_encoded(call),
|
||||
false,
|
||||
call,
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::WrongTimepoint,
|
||||
@@ -350,41 +254,6 @@ fn timepoint_checking_works() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multisig_2_of_3_works_with_call_storing() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let multi = Multisig::multi_account_id(&[1, 2, 3][..], 2);
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(1), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(2), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(3), multi, 5));
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data),
|
||||
true,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 0);
|
||||
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(2),
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
hash,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 15);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multisig_2_of_3_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
@@ -395,8 +264,7 @@ fn multisig_2_of_3_works() {
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
let hash = blake2_256(&call.encode());
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
@@ -412,8 +280,7 @@ fn multisig_2_of_3_works() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 15);
|
||||
@@ -430,8 +297,7 @@ fn multisig_3_of_3_works() {
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
let hash = blake2_256(&call.encode());
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
3,
|
||||
@@ -455,8 +321,7 @@ fn multisig_3_of_3_works() {
|
||||
3,
|
||||
vec![1, 2],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 15);
|
||||
@@ -492,68 +357,6 @@ fn cancel_multisig_works() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_multisig_with_call_storage_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let call = call_transfer(6, 15).encode();
|
||||
let hash = blake2_256(&call);
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
3,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(call),
|
||||
true,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 4);
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(2),
|
||||
3,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
hash,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_noop!(
|
||||
Multisig::cancel_as_multi(RuntimeOrigin::signed(2), 3, vec![1, 3], now(), hash),
|
||||
Error::<Test>::NotOwner,
|
||||
);
|
||||
assert_ok!(Multisig::cancel_as_multi(RuntimeOrigin::signed(1), 3, vec![2, 3], now(), hash),);
|
||||
assert_eq!(Balances::free_balance(1), 10);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_multisig_with_alt_call_storage_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let call = call_transfer(6, 15).encode();
|
||||
let hash = blake2_256(&call);
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
3,
|
||||
vec![2, 3],
|
||||
None,
|
||||
hash,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(1), 6);
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(2),
|
||||
3,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(call),
|
||||
true,
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(2), 8);
|
||||
assert_ok!(Multisig::cancel_as_multi(RuntimeOrigin::signed(1), 3, vec![2, 3], now(), hash));
|
||||
assert_eq!(Balances::free_balance(1), 10);
|
||||
assert_eq!(Balances::free_balance(2), 10);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multisig_2_of_3_as_multi_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
@@ -564,14 +367,12 @@ fn multisig_2_of_3_as_multi_works() {
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 0);
|
||||
@@ -581,8 +382,7 @@ fn multisig_2_of_3_as_multi_works() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 15);
|
||||
@@ -599,18 +399,15 @@ fn multisig_2_of_3_as_multi_with_many_calls_works() {
|
||||
|
||||
let call1 = call_transfer(6, 10);
|
||||
let call1_weight = call1.get_dispatch_info().weight;
|
||||
let data1 = call1.encode();
|
||||
let call2 = call_transfer(7, 5);
|
||||
let call2_weight = call2.get_dispatch_info().weight;
|
||||
let data2 = call2.encode();
|
||||
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data1.clone()),
|
||||
false,
|
||||
call1.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_ok!(Multisig::as_multi(
|
||||
@@ -618,8 +415,7 @@ fn multisig_2_of_3_as_multi_with_many_calls_works() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data2.clone()),
|
||||
false,
|
||||
call2.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_ok!(Multisig::as_multi(
|
||||
@@ -627,8 +423,7 @@ fn multisig_2_of_3_as_multi_with_many_calls_works() {
|
||||
2,
|
||||
vec![1, 2],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data1),
|
||||
false,
|
||||
call1,
|
||||
call1_weight
|
||||
));
|
||||
assert_ok!(Multisig::as_multi(
|
||||
@@ -636,8 +431,7 @@ fn multisig_2_of_3_as_multi_with_many_calls_works() {
|
||||
2,
|
||||
vec![1, 2],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data2),
|
||||
false,
|
||||
call2,
|
||||
call2_weight
|
||||
));
|
||||
|
||||
@@ -656,15 +450,13 @@ fn multisig_2_of_3_cannot_reissue_same_call() {
|
||||
|
||||
let call = call_transfer(6, 10);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
let hash = blake2_256(&call.encode());
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_ok!(Multisig::as_multi(
|
||||
@@ -672,8 +464,7 @@ fn multisig_2_of_3_cannot_reissue_same_call() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(multi), 5);
|
||||
@@ -683,8 +474,7 @@ fn multisig_2_of_3_cannot_reissue_same_call() {
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_ok!(Multisig::as_multi(
|
||||
@@ -692,8 +482,7 @@ fn multisig_2_of_3_cannot_reissue_same_call() {
|
||||
2,
|
||||
vec![1, 2],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call.clone(),
|
||||
call_weight
|
||||
));
|
||||
|
||||
@@ -714,15 +503,14 @@ fn multisig_2_of_3_cannot_reissue_same_call() {
|
||||
#[test]
|
||||
fn minimum_threshold_check_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let call = call_transfer(6, 15).encode();
|
||||
let call = call_transfer(6, 15);
|
||||
assert_noop!(
|
||||
Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
0,
|
||||
vec![2],
|
||||
None,
|
||||
OpaqueCall::from_encoded(call.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::MinimumThreshold,
|
||||
@@ -733,8 +521,7 @@ fn minimum_threshold_check_works() {
|
||||
1,
|
||||
vec![2],
|
||||
None,
|
||||
OpaqueCall::from_encoded(call.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::MinimumThreshold,
|
||||
@@ -745,15 +532,14 @@ fn minimum_threshold_check_works() {
|
||||
#[test]
|
||||
fn too_many_signatories_fails() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let call = call_transfer(6, 15).encode();
|
||||
let call = call_transfer(6, 15);
|
||||
assert_noop!(
|
||||
Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3, 4],
|
||||
None,
|
||||
OpaqueCall::from_encoded(call),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::TooManySignatories,
|
||||
@@ -815,8 +601,8 @@ fn multisig_1_of_3_works() {
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(2), multi, 5));
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(3), multi, 5));
|
||||
|
||||
let call = call_transfer(6, 15).encode();
|
||||
let hash = blake2_256(&call);
|
||||
let call = call_transfer(6, 15);
|
||||
let hash = blake2_256(&call.encode());
|
||||
assert_noop!(
|
||||
Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
@@ -834,17 +620,15 @@ fn multisig_1_of_3_works() {
|
||||
1,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(call),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::MinimumThreshold,
|
||||
);
|
||||
let boxed_call = Box::new(call_transfer(6, 15));
|
||||
assert_ok!(Multisig::as_multi_threshold_1(
|
||||
RuntimeOrigin::signed(1),
|
||||
vec![2, 3],
|
||||
boxed_call
|
||||
call_transfer(6, 15)
|
||||
));
|
||||
|
||||
assert_eq!(Balances::free_balance(6), 15);
|
||||
@@ -871,14 +655,12 @@ fn weight_check_works() {
|
||||
assert_ok!(Balances::transfer(RuntimeOrigin::signed(3), multi, 5));
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let data = call.encode();
|
||||
assert_ok!(Multisig::as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
2,
|
||||
vec![2, 3],
|
||||
None,
|
||||
OpaqueCall::from_encoded(data.clone()),
|
||||
false,
|
||||
call.clone(),
|
||||
Weight::zero()
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 0);
|
||||
@@ -889,8 +671,7 @@ fn weight_check_works() {
|
||||
2,
|
||||
vec![1, 3],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call,
|
||||
Weight::zero()
|
||||
),
|
||||
Error::<Test>::MaxWeightTooLow,
|
||||
@@ -911,8 +692,7 @@ fn multisig_handles_no_preimage_after_all_approve() {
|
||||
|
||||
let call = call_transfer(6, 15);
|
||||
let call_weight = call.get_dispatch_info().weight;
|
||||
let data = call.encode();
|
||||
let hash = blake2_256(&data);
|
||||
let hash = blake2_256(&call.encode());
|
||||
assert_ok!(Multisig::approve_as_multi(
|
||||
RuntimeOrigin::signed(1),
|
||||
3,
|
||||
@@ -944,8 +724,7 @@ fn multisig_handles_no_preimage_after_all_approve() {
|
||||
3,
|
||||
vec![1, 2],
|
||||
Some(now()),
|
||||
OpaqueCall::from_encoded(data),
|
||||
false,
|
||||
call,
|
||||
call_weight
|
||||
));
|
||||
assert_eq!(Balances::free_balance(6), 15);
|
||||
|
||||
@@ -140,7 +140,7 @@ pub mod pallet {
|
||||
let sender = ensure_signed(origin)?;
|
||||
|
||||
let bounded_name: BoundedVec<_, _> =
|
||||
name.try_into().map_err(|()| Error::<T>::TooLong)?;
|
||||
name.try_into().map_err(|_| Error::<T>::TooLong)?;
|
||||
ensure!(bounded_name.len() >= T::MinLength::get() as usize, Error::<T>::TooShort);
|
||||
|
||||
let deposit = if let Some((_, deposit)) = <NameOf<T>>::get(&sender) {
|
||||
@@ -229,7 +229,7 @@ pub mod pallet {
|
||||
T::ForceOrigin::ensure_origin(origin)?;
|
||||
|
||||
let bounded_name: BoundedVec<_, _> =
|
||||
name.try_into().map_err(|()| Error::<T>::TooLong)?;
|
||||
name.try_into().map_err(|_| Error::<T>::TooLong)?;
|
||||
let target = T::Lookup::lookup(target)?;
|
||||
let deposit = <NameOf<T>>::get(&target).map(|x| x.1).unwrap_or_else(Zero::zero);
|
||||
<NameOf<T>>::insert(&target, (bounded_name, deposit));
|
||||
|
||||
@@ -19,6 +19,7 @@ sp-core = { version = "6.0.0", default-features = false, optional = true, path =
|
||||
sp-io = { version = "6.0.0", default-features = false, path = "../../primitives/io" }
|
||||
sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" }
|
||||
sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" }
|
||||
log = { version = "0.4.17", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
pallet-balances = { version = "4.0.0-dev", path = "../balances" }
|
||||
@@ -36,10 +37,13 @@ std = [
|
||||
"frame-benchmarking?/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
"log/std",
|
||||
"scale-info/std",
|
||||
"sp-core/std",
|
||||
"sp-io/std",
|
||||
"sp-runtime/std",
|
||||
"sp-std/std",
|
||||
]
|
||||
try-runtime = ["frame-support/try-runtime"]
|
||||
try-runtime = [
|
||||
"frame-support/try-runtime",
|
||||
]
|
||||
|
||||
@@ -35,7 +35,7 @@ fn funded_account<T: Config>(name: &'static str, index: u32) -> T::AccountId {
|
||||
}
|
||||
|
||||
fn preimage_and_hash<T: Config>() -> (Vec<u8>, T::Hash) {
|
||||
sized_preimage_and_hash::<T>(T::MaxSize::get())
|
||||
sized_preimage_and_hash::<T>(MAX_SIZE)
|
||||
}
|
||||
|
||||
fn sized_preimage_and_hash<T: Config>(size: u32) -> (Vec<u8>, T::Hash) {
|
||||
@@ -48,7 +48,7 @@ fn sized_preimage_and_hash<T: Config>(size: u32) -> (Vec<u8>, T::Hash) {
|
||||
benchmarks! {
|
||||
// Expensive note - will reserve.
|
||||
note_preimage {
|
||||
let s in 0 .. T::MaxSize::get();
|
||||
let s in 0 .. MAX_SIZE;
|
||||
let caller = funded_account::<T>("caller", 0);
|
||||
whitelist_account!(caller);
|
||||
let (preimage, hash) = sized_preimage_and_hash::<T>(s);
|
||||
@@ -58,7 +58,7 @@ benchmarks! {
|
||||
}
|
||||
// Cheap note - will not reserve since it was requested.
|
||||
note_requested_preimage {
|
||||
let s in 0 .. T::MaxSize::get();
|
||||
let s in 0 .. MAX_SIZE;
|
||||
let caller = funded_account::<T>("caller", 0);
|
||||
whitelist_account!(caller);
|
||||
let (preimage, hash) = sized_preimage_and_hash::<T>(s);
|
||||
@@ -69,7 +69,7 @@ benchmarks! {
|
||||
}
|
||||
// Cheap note - will not reserve since it's the manager.
|
||||
note_no_deposit_preimage {
|
||||
let s in 0 .. T::MaxSize::get();
|
||||
let s in 0 .. MAX_SIZE;
|
||||
let (preimage, hash) = sized_preimage_and_hash::<T>(s);
|
||||
assert_ok!(Preimage::<T>::request_preimage(T::ManagerOrigin::successful_origin(), hash));
|
||||
}: note_preimage<T::RuntimeOrigin>(T::ManagerOrigin::successful_origin(), preimage)
|
||||
@@ -101,10 +101,12 @@ benchmarks! {
|
||||
let (preimage, hash) = preimage_and_hash::<T>();
|
||||
let noter = funded_account::<T>("noter", 0);
|
||||
whitelist_account!(noter);
|
||||
assert_ok!(Preimage::<T>::note_preimage(RawOrigin::Signed(noter).into(), preimage));
|
||||
assert_ok!(Preimage::<T>::note_preimage(RawOrigin::Signed(noter.clone()).into(), preimage));
|
||||
}: _<T::RuntimeOrigin>(T::ManagerOrigin::successful_origin(), hash)
|
||||
verify {
|
||||
assert_eq!(StatusFor::<T>::get(&hash), Some(RequestStatus::Requested(1)));
|
||||
let deposit = T::BaseDeposit::get() + T::ByteDeposit::get() * MAX_SIZE.into();
|
||||
let s = RequestStatus::Requested { deposit: Some((noter, deposit)), count: 1, len: Some(MAX_SIZE) };
|
||||
assert_eq!(StatusFor::<T>::get(&hash), Some(s));
|
||||
}
|
||||
// Cheap request - would unreserve the deposit but none was held.
|
||||
request_no_deposit_preimage {
|
||||
@@ -112,14 +114,16 @@ benchmarks! {
|
||||
assert_ok!(Preimage::<T>::note_preimage(T::ManagerOrigin::successful_origin(), preimage));
|
||||
}: request_preimage<T::RuntimeOrigin>(T::ManagerOrigin::successful_origin(), hash)
|
||||
verify {
|
||||
assert_eq!(StatusFor::<T>::get(&hash), Some(RequestStatus::Requested(1)));
|
||||
let s = RequestStatus::Requested { deposit: None, count: 2, len: Some(MAX_SIZE) };
|
||||
assert_eq!(StatusFor::<T>::get(&hash), Some(s));
|
||||
}
|
||||
// Cheap request - the preimage is not yet noted, so deposit to unreserve.
|
||||
request_unnoted_preimage {
|
||||
let (_, hash) = preimage_and_hash::<T>();
|
||||
}: request_preimage<T::RuntimeOrigin>(T::ManagerOrigin::successful_origin(), hash)
|
||||
verify {
|
||||
assert_eq!(StatusFor::<T>::get(&hash), Some(RequestStatus::Requested(1)));
|
||||
let s = RequestStatus::Requested { deposit: None, count: 1, len: None };
|
||||
assert_eq!(StatusFor::<T>::get(&hash), Some(s));
|
||||
}
|
||||
// Cheap request - the preimage is already requested, so just a counter bump.
|
||||
request_requested_preimage {
|
||||
@@ -127,7 +131,8 @@ benchmarks! {
|
||||
assert_ok!(Preimage::<T>::request_preimage(T::ManagerOrigin::successful_origin(), hash));
|
||||
}: request_preimage<T::RuntimeOrigin>(T::ManagerOrigin::successful_origin(), hash)
|
||||
verify {
|
||||
assert_eq!(StatusFor::<T>::get(&hash), Some(RequestStatus::Requested(2)));
|
||||
let s = RequestStatus::Requested { deposit: None, count: 2, len: None };
|
||||
assert_eq!(StatusFor::<T>::get(&hash), Some(s));
|
||||
}
|
||||
|
||||
// Expensive unrequest - last reference and it's noted, so will destroy the preimage.
|
||||
@@ -154,7 +159,8 @@ benchmarks! {
|
||||
assert_ok!(Preimage::<T>::request_preimage(T::ManagerOrigin::successful_origin(), hash));
|
||||
}: unrequest_preimage<T::RuntimeOrigin>(T::ManagerOrigin::successful_origin(), hash)
|
||||
verify {
|
||||
assert_eq!(StatusFor::<T>::get(&hash), Some(RequestStatus::Requested(1)));
|
||||
let s = RequestStatus::Requested { deposit: None, count: 1, len: None };
|
||||
assert_eq!(StatusFor::<T>::get(&hash), Some(s));
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(Preimage, crate::mock::new_test_ext(), crate::mock::Test);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benchmarking;
|
||||
pub mod migration;
|
||||
#[cfg(test)]
|
||||
mod mock;
|
||||
#[cfg(test)]
|
||||
@@ -37,15 +38,18 @@ mod tests;
|
||||
pub mod weights;
|
||||
|
||||
use sp_runtime::traits::{BadOrigin, Hash, Saturating};
|
||||
use sp_std::prelude::*;
|
||||
use sp_std::{borrow::Cow, prelude::*};
|
||||
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use frame_support::{
|
||||
dispatch::Pays,
|
||||
ensure,
|
||||
pallet_prelude::Get,
|
||||
traits::{Currency, PreimageProvider, PreimageRecipient, ReservableCurrency},
|
||||
BoundedVec,
|
||||
traits::{
|
||||
Currency, Defensive, FetchResult, Hash as PreimageHash, PreimageProvider,
|
||||
PreimageRecipient, QueryPreimage, ReservableCurrency, StorePreimage,
|
||||
},
|
||||
BoundedSlice, BoundedVec,
|
||||
};
|
||||
use scale_info::TypeInfo;
|
||||
pub use weights::WeightInfo;
|
||||
@@ -59,20 +63,27 @@ pub use pallet::*;
|
||||
#[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo, MaxEncodedLen, RuntimeDebug)]
|
||||
pub enum RequestStatus<AccountId, Balance> {
|
||||
/// The associated preimage has not yet been requested by the system. The given deposit (if
|
||||
/// some) is being held until either it becomes requested or the user retracts the primage.
|
||||
Unrequested(Option<(AccountId, Balance)>),
|
||||
/// some) is being held until either it becomes requested or the user retracts the preimage.
|
||||
Unrequested { deposit: (AccountId, Balance), len: u32 },
|
||||
/// There are a non-zero number of outstanding requests for this hash by this chain. If there
|
||||
/// is a preimage registered, then it may be removed iff this counter becomes zero.
|
||||
Requested(u32),
|
||||
/// is a preimage registered, then `len` is `Some` and it may be removed iff this counter
|
||||
/// becomes zero.
|
||||
Requested { deposit: Option<(AccountId, Balance)>, count: u32, len: Option<u32> },
|
||||
}
|
||||
|
||||
type BalanceOf<T> =
|
||||
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
|
||||
|
||||
/// Maximum size of preimage we can store is 4mb.
|
||||
const MAX_SIZE: u32 = 4 * 1024 * 1024;
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
|
||||
/// The current storage version.
|
||||
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config {
|
||||
/// The overarching event type.
|
||||
@@ -88,9 +99,6 @@ pub mod pallet {
|
||||
/// manage existing preimages.
|
||||
type ManagerOrigin: EnsureOrigin<Self::RuntimeOrigin>;
|
||||
|
||||
/// Max size allowed for a preimage.
|
||||
type MaxSize: Get<u32>;
|
||||
|
||||
/// The base deposit for placing a preimage on chain.
|
||||
type BaseDeposit: Get<BalanceOf<Self>>;
|
||||
|
||||
@@ -100,6 +108,7 @@ pub mod pallet {
|
||||
|
||||
#[pallet::pallet]
|
||||
#[pallet::generate_store(pub(super) trait Store)]
|
||||
#[pallet::storage_version(STORAGE_VERSION)]
|
||||
pub struct Pallet<T>(PhantomData<T>);
|
||||
|
||||
#[pallet::event]
|
||||
@@ -116,7 +125,7 @@ pub mod pallet {
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
/// Preimage is too large to store on-chain.
|
||||
TooLarge,
|
||||
TooBig,
|
||||
/// Preimage has already been noted on-chain.
|
||||
AlreadyNoted,
|
||||
/// The user is not authorized to perform this action.
|
||||
@@ -134,10 +143,9 @@ pub mod pallet {
|
||||
pub(super) type StatusFor<T: Config> =
|
||||
StorageMap<_, Identity, T::Hash, RequestStatus<T::AccountId, BalanceOf<T>>>;
|
||||
|
||||
/// The preimages stored by this pallet.
|
||||
#[pallet::storage]
|
||||
pub(super) type PreimageFor<T: Config> =
|
||||
StorageMap<_, Identity, T::Hash, BoundedVec<u8, T::MaxSize>>;
|
||||
StorageMap<_, Identity, (T::Hash, u32), BoundedVec<u8, ConstU32<MAX_SIZE>>>;
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
@@ -150,9 +158,7 @@ pub mod pallet {
|
||||
// We accept a signed origin which will pay a deposit, or a root origin where a deposit
|
||||
// is not taken.
|
||||
let maybe_sender = Self::ensure_signed_or_manager(origin)?;
|
||||
let bounded_vec =
|
||||
BoundedVec::<u8, T::MaxSize>::try_from(bytes).map_err(|()| Error::<T>::TooLarge)?;
|
||||
let system_requested = Self::note_bytes(bounded_vec, maybe_sender.as_ref())?;
|
||||
let (system_requested, _) = Self::note_bytes(bytes.into(), maybe_sender.as_ref())?;
|
||||
if system_requested || maybe_sender.is_none() {
|
||||
Ok(Pays::No.into())
|
||||
} else {
|
||||
@@ -161,6 +167,11 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
/// Clear an unrequested preimage from the runtime storage.
|
||||
///
|
||||
/// If `len` is provided, then it will be a much cheaper operation.
|
||||
///
|
||||
/// - `hash`: The hash of the preimage to be removed from the store.
|
||||
/// - `len`: The length of the preimage of `hash`.
|
||||
#[pallet::weight(T::WeightInfo::unnote_preimage())]
|
||||
pub fn unnote_preimage(origin: OriginFor<T>, hash: T::Hash) -> DispatchResult {
|
||||
let maybe_sender = Self::ensure_signed_or_manager(origin)?;
|
||||
@@ -203,41 +214,46 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
/// Store some preimage on chain.
|
||||
///
|
||||
/// If `maybe_depositor` is `None` then it is also requested. If `Some`, then it is not.
|
||||
///
|
||||
/// We verify that the preimage is within the bounds of what the pallet supports.
|
||||
///
|
||||
/// If the preimage was requested to be uploaded, then the user pays no deposits or tx fees.
|
||||
fn note_bytes(
|
||||
preimage: BoundedVec<u8, T::MaxSize>,
|
||||
preimage: Cow<[u8]>,
|
||||
maybe_depositor: Option<&T::AccountId>,
|
||||
) -> Result<bool, DispatchError> {
|
||||
) -> Result<(bool, T::Hash), DispatchError> {
|
||||
let hash = T::Hashing::hash(&preimage);
|
||||
ensure!(!PreimageFor::<T>::contains_key(hash), Error::<T>::AlreadyNoted);
|
||||
let len = preimage.len() as u32;
|
||||
ensure!(len <= MAX_SIZE, Error::<T>::TooBig);
|
||||
|
||||
// We take a deposit only if there is a provided depositor, and the preimage was not
|
||||
// We take a deposit only if there is a provided depositor and the preimage was not
|
||||
// previously requested. This also allows the tx to pay no fee.
|
||||
let was_requested = match (StatusFor::<T>::get(hash), maybe_depositor) {
|
||||
(Some(RequestStatus::Requested(..)), _) => true,
|
||||
(Some(RequestStatus::Unrequested(..)), _) =>
|
||||
let status = match (StatusFor::<T>::get(hash), maybe_depositor) {
|
||||
(Some(RequestStatus::Requested { count, deposit, .. }), _) =>
|
||||
RequestStatus::Requested { count, deposit, len: Some(len) },
|
||||
(Some(RequestStatus::Unrequested { .. }), Some(_)) =>
|
||||
return Err(Error::<T>::AlreadyNoted.into()),
|
||||
(None, None) => {
|
||||
StatusFor::<T>::insert(hash, RequestStatus::Unrequested(None));
|
||||
false
|
||||
},
|
||||
(Some(RequestStatus::Unrequested { len, deposit }), None) =>
|
||||
RequestStatus::Requested { deposit: Some(deposit), count: 1, len: Some(len) },
|
||||
(None, None) => RequestStatus::Requested { count: 1, len: Some(len), deposit: None },
|
||||
(None, Some(depositor)) => {
|
||||
let length = preimage.len() as u32;
|
||||
let deposit = T::BaseDeposit::get()
|
||||
.saturating_add(T::ByteDeposit::get().saturating_mul(length.into()));
|
||||
T::Currency::reserve(depositor, deposit)?;
|
||||
let status = RequestStatus::Unrequested(Some((depositor.clone(), deposit)));
|
||||
StatusFor::<T>::insert(hash, status);
|
||||
false
|
||||
RequestStatus::Unrequested { deposit: (depositor.clone(), deposit), len }
|
||||
},
|
||||
};
|
||||
let was_requested = matches!(status, RequestStatus::Requested { .. });
|
||||
StatusFor::<T>::insert(hash, status);
|
||||
|
||||
let _ = Self::insert(&hash, preimage)
|
||||
.defensive_proof("Unable to insert. Logic error in `note_bytes`?");
|
||||
|
||||
PreimageFor::<T>::insert(hash, preimage);
|
||||
Self::deposit_event(Event::Noted { hash });
|
||||
|
||||
Ok(was_requested)
|
||||
Ok((was_requested, hash))
|
||||
}
|
||||
|
||||
// This function will add a hash to the list of requested preimages.
|
||||
@@ -245,19 +261,15 @@ impl<T: Config> Pallet<T> {
|
||||
// If the preimage already exists before the request is made, the deposit for the preimage is
|
||||
// returned to the user, and removed from their management.
|
||||
fn do_request_preimage(hash: &T::Hash) {
|
||||
let count = StatusFor::<T>::get(hash).map_or(1, |x| match x {
|
||||
RequestStatus::Requested(mut count) => {
|
||||
count.saturating_inc();
|
||||
count
|
||||
},
|
||||
RequestStatus::Unrequested(None) => 1,
|
||||
RequestStatus::Unrequested(Some((owner, deposit))) => {
|
||||
// Return the deposit - the preimage now has outstanding requests.
|
||||
T::Currency::unreserve(&owner, deposit);
|
||||
1
|
||||
},
|
||||
});
|
||||
StatusFor::<T>::insert(hash, RequestStatus::Requested(count));
|
||||
let (count, len, deposit) =
|
||||
StatusFor::<T>::get(hash).map_or((1, None, None), |x| match x {
|
||||
RequestStatus::Requested { mut count, len, deposit } => {
|
||||
count.saturating_inc();
|
||||
(count, len, deposit)
|
||||
},
|
||||
RequestStatus::Unrequested { deposit, len } => (1, Some(len), Some(deposit)),
|
||||
});
|
||||
StatusFor::<T>::insert(hash, RequestStatus::Requested { count, len, deposit });
|
||||
if count == 1 {
|
||||
Self::deposit_event(Event::Requested { hash: *hash });
|
||||
}
|
||||
@@ -265,6 +277,8 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
// Clear a preimage from the storage of the chain, returning any deposit that may be reserved.
|
||||
//
|
||||
// If `len` is provided, it will be a much cheaper operation.
|
||||
//
|
||||
// If `maybe_owner` is provided, we verify that it is the correct owner before clearing the
|
||||
// data.
|
||||
fn do_unnote_preimage(
|
||||
@@ -272,51 +286,101 @@ impl<T: Config> Pallet<T> {
|
||||
maybe_check_owner: Option<T::AccountId>,
|
||||
) -> DispatchResult {
|
||||
match StatusFor::<T>::get(hash).ok_or(Error::<T>::NotNoted)? {
|
||||
RequestStatus::Unrequested(Some((owner, deposit))) => {
|
||||
RequestStatus::Requested { deposit: Some((owner, deposit)), count, len } => {
|
||||
ensure!(maybe_check_owner.map_or(true, |c| c == owner), Error::<T>::NotAuthorized);
|
||||
T::Currency::unreserve(&owner, deposit);
|
||||
StatusFor::<T>::insert(
|
||||
hash,
|
||||
RequestStatus::Requested { deposit: None, count, len },
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
RequestStatus::Unrequested(None) => {
|
||||
RequestStatus::Requested { deposit: None, .. } => {
|
||||
ensure!(maybe_check_owner.is_none(), Error::<T>::NotAuthorized);
|
||||
Self::do_unrequest_preimage(hash)
|
||||
},
|
||||
RequestStatus::Unrequested { deposit: (owner, deposit), len } => {
|
||||
ensure!(maybe_check_owner.map_or(true, |c| c == owner), Error::<T>::NotAuthorized);
|
||||
T::Currency::unreserve(&owner, deposit);
|
||||
StatusFor::<T>::remove(hash);
|
||||
|
||||
Self::remove(hash, len);
|
||||
Self::deposit_event(Event::Cleared { hash: *hash });
|
||||
Ok(())
|
||||
},
|
||||
RequestStatus::Requested(_) => return Err(Error::<T>::Requested.into()),
|
||||
}
|
||||
StatusFor::<T>::remove(hash);
|
||||
PreimageFor::<T>::remove(hash);
|
||||
Self::deposit_event(Event::Cleared { hash: *hash });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Clear a preimage request.
|
||||
fn do_unrequest_preimage(hash: &T::Hash) -> DispatchResult {
|
||||
match StatusFor::<T>::get(hash).ok_or(Error::<T>::NotRequested)? {
|
||||
RequestStatus::Requested(mut count) if count > 1 => {
|
||||
RequestStatus::Requested { mut count, len, deposit } if count > 1 => {
|
||||
count.saturating_dec();
|
||||
StatusFor::<T>::insert(hash, RequestStatus::Requested(count));
|
||||
StatusFor::<T>::insert(hash, RequestStatus::Requested { count, len, deposit });
|
||||
},
|
||||
RequestStatus::Requested(count) => {
|
||||
RequestStatus::Requested { count, len, deposit } => {
|
||||
debug_assert!(count == 1, "preimage request counter at zero?");
|
||||
PreimageFor::<T>::remove(hash);
|
||||
StatusFor::<T>::remove(hash);
|
||||
Self::deposit_event(Event::Cleared { hash: *hash });
|
||||
match (len, deposit) {
|
||||
// Preimage was never noted.
|
||||
(None, _) => StatusFor::<T>::remove(hash),
|
||||
// Preimage was noted without owner - just remove it.
|
||||
(Some(len), None) => {
|
||||
Self::remove(hash, len);
|
||||
StatusFor::<T>::remove(hash);
|
||||
Self::deposit_event(Event::Cleared { hash: *hash });
|
||||
},
|
||||
// Preimage was noted with owner - move to unrequested so they can get refund.
|
||||
(Some(len), Some(deposit)) => {
|
||||
StatusFor::<T>::insert(hash, RequestStatus::Unrequested { deposit, len });
|
||||
},
|
||||
}
|
||||
},
|
||||
RequestStatus::Unrequested(_) => return Err(Error::<T>::NotRequested.into()),
|
||||
RequestStatus::Unrequested { .. } => return Err(Error::<T>::NotRequested.into()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn insert(hash: &T::Hash, preimage: Cow<[u8]>) -> Result<(), ()> {
|
||||
BoundedSlice::<u8, ConstU32<MAX_SIZE>>::try_from(preimage.as_ref())
|
||||
.map(|s| PreimageFor::<T>::insert((hash, s.len() as u32), s))
|
||||
}
|
||||
|
||||
fn remove(hash: &T::Hash, len: u32) {
|
||||
PreimageFor::<T>::remove((hash, len))
|
||||
}
|
||||
|
||||
fn have(hash: &T::Hash) -> bool {
|
||||
Self::len(hash).is_some()
|
||||
}
|
||||
|
||||
fn len(hash: &T::Hash) -> Option<u32> {
|
||||
use RequestStatus::*;
|
||||
match StatusFor::<T>::get(hash) {
|
||||
Some(Requested { len: Some(len), .. }) | Some(Unrequested { len, .. }) => Some(len),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn fetch(hash: &T::Hash, len: Option<u32>) -> FetchResult {
|
||||
let len = len.or_else(|| Self::len(hash)).ok_or(DispatchError::Unavailable)?;
|
||||
PreimageFor::<T>::get((hash, len))
|
||||
.map(|p| p.into_inner())
|
||||
.map(Into::into)
|
||||
.ok_or(DispatchError::Unavailable)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> PreimageProvider<T::Hash> for Pallet<T> {
|
||||
fn have_preimage(hash: &T::Hash) -> bool {
|
||||
PreimageFor::<T>::contains_key(hash)
|
||||
Self::have(hash)
|
||||
}
|
||||
|
||||
fn preimage_requested(hash: &T::Hash) -> bool {
|
||||
matches!(StatusFor::<T>::get(hash), Some(RequestStatus::Requested(..)))
|
||||
matches!(StatusFor::<T>::get(hash), Some(RequestStatus::Requested { .. }))
|
||||
}
|
||||
|
||||
fn get_preimage(hash: &T::Hash) -> Option<Vec<u8>> {
|
||||
PreimageFor::<T>::get(hash).map(|preimage| preimage.to_vec())
|
||||
Self::fetch(hash, None).ok().map(Cow::into_owned)
|
||||
}
|
||||
|
||||
fn request_preimage(hash: &T::Hash) {
|
||||
@@ -330,15 +394,60 @@ impl<T: Config> PreimageProvider<T::Hash> for Pallet<T> {
|
||||
}
|
||||
|
||||
impl<T: Config> PreimageRecipient<T::Hash> for Pallet<T> {
|
||||
type MaxSize = T::MaxSize;
|
||||
type MaxSize = ConstU32<MAX_SIZE>; // 2**22
|
||||
|
||||
fn note_preimage(bytes: BoundedVec<u8, Self::MaxSize>) {
|
||||
// We don't really care if this fails, since that's only the case if someone else has
|
||||
// already noted it.
|
||||
let _ = Self::note_bytes(bytes, None);
|
||||
let _ = Self::note_bytes(bytes.into_inner().into(), None);
|
||||
}
|
||||
|
||||
fn unnote_preimage(hash: &T::Hash) {
|
||||
// Should never fail if authorization check is skipped.
|
||||
let res = Self::do_unrequest_preimage(hash);
|
||||
debug_assert!(res.is_ok(), "unnote_preimage failed - request outstanding?");
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<Hash = PreimageHash>> QueryPreimage for Pallet<T> {
|
||||
fn len(hash: &T::Hash) -> Option<u32> {
|
||||
Pallet::<T>::len(hash)
|
||||
}
|
||||
|
||||
fn fetch(hash: &T::Hash, len: Option<u32>) -> FetchResult {
|
||||
Pallet::<T>::fetch(hash, len)
|
||||
}
|
||||
|
||||
fn is_requested(hash: &T::Hash) -> bool {
|
||||
matches!(StatusFor::<T>::get(hash), Some(RequestStatus::Requested { .. }))
|
||||
}
|
||||
|
||||
fn request(hash: &T::Hash) {
|
||||
Self::do_request_preimage(hash)
|
||||
}
|
||||
|
||||
fn unrequest(hash: &T::Hash) {
|
||||
let res = Self::do_unrequest_preimage(hash);
|
||||
debug_assert!(res.is_ok(), "do_unrequest_preimage failed - counter underflow?");
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<Hash = PreimageHash>> StorePreimage for Pallet<T> {
|
||||
const MAX_LENGTH: usize = MAX_SIZE as usize;
|
||||
|
||||
fn note(bytes: Cow<[u8]>) -> Result<T::Hash, DispatchError> {
|
||||
// We don't really care if this fails, since that's only the case if someone else has
|
||||
// already noted it.
|
||||
let maybe_hash = Self::note_bytes(bytes, None).map(|(_, h)| h);
|
||||
// Map to the correct trait error.
|
||||
if maybe_hash == Err(DispatchError::from(Error::<T>::TooBig)) {
|
||||
Err(DispatchError::Exhausted)
|
||||
} else {
|
||||
maybe_hash
|
||||
}
|
||||
}
|
||||
|
||||
fn unnote(hash: &T::Hash) {
|
||||
// Should never fail if authorization check is skipped.
|
||||
let res = Self::do_unnote_preimage(hash, None);
|
||||
debug_assert!(res.is_ok(), "unnote_preimage failed - request outstanding?");
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2022 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.
|
||||
|
||||
//! Storage migrations for the preimage pallet.
|
||||
|
||||
use super::*;
|
||||
use frame_support::{
|
||||
storage_alias,
|
||||
traits::{ConstU32, OnRuntimeUpgrade},
|
||||
};
|
||||
use sp_std::collections::btree_map::BTreeMap;
|
||||
|
||||
/// The log target.
|
||||
const TARGET: &'static str = "runtime::preimage::migration::v1";
|
||||
|
||||
/// The original data layout of the preimage pallet without a specific version number.
|
||||
mod v0 {
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo, MaxEncodedLen, RuntimeDebug)]
|
||||
pub enum RequestStatus<AccountId, Balance> {
|
||||
Unrequested(Option<(AccountId, Balance)>),
|
||||
Requested(u32),
|
||||
}
|
||||
|
||||
#[storage_alias]
|
||||
pub type PreimageFor<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
Identity,
|
||||
<T as frame_system::Config>::Hash,
|
||||
BoundedVec<u8, ConstU32<MAX_SIZE>>,
|
||||
>;
|
||||
|
||||
#[storage_alias]
|
||||
pub type StatusFor<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
Identity,
|
||||
<T as frame_system::Config>::Hash,
|
||||
RequestStatus<<T as frame_system::Config>::AccountId, BalanceOf<T>>,
|
||||
>;
|
||||
|
||||
/// Returns the number of images or `None` if the storage is corrupted.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
pub fn image_count<T: Config>() -> Option<u32> {
|
||||
let images = v0::PreimageFor::<T>::iter_values().count() as u32;
|
||||
let status = v0::StatusFor::<T>::iter_values().count() as u32;
|
||||
|
||||
if images == status {
|
||||
Some(images)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod v1 {
|
||||
use super::*;
|
||||
|
||||
/// Migration for moving preimage from V0 to V1 storage.
|
||||
///
|
||||
/// Note: This needs to be run with the same hashing algorithm as before
|
||||
/// since it is not re-hashing the preimages.
|
||||
pub struct Migration<T>(sp_std::marker::PhantomData<T>);
|
||||
|
||||
impl<T: Config> OnRuntimeUpgrade for Migration<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 0, "can only upgrade from version 0");
|
||||
|
||||
let images = v0::image_count::<T>().expect("v0 storage corrupted");
|
||||
log::info!(target: TARGET, "Migrating {} images", &images);
|
||||
Ok((images as u32).encode())
|
||||
}
|
||||
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let mut weight = T::DbWeight::get().reads(1);
|
||||
if StorageVersion::get::<Pallet<T>>() != 0 {
|
||||
log::warn!(
|
||||
target: TARGET,
|
||||
"skipping MovePreimagesIntoBuckets: executed on wrong storage version.\
|
||||
Expected version 0"
|
||||
);
|
||||
return weight
|
||||
}
|
||||
|
||||
let status = v0::StatusFor::<T>::drain().collect::<Vec<_>>();
|
||||
weight.saturating_accrue(T::DbWeight::get().reads(status.len() as u64));
|
||||
|
||||
let preimages = v0::PreimageFor::<T>::drain().collect::<BTreeMap<_, _>>();
|
||||
weight.saturating_accrue(T::DbWeight::get().reads(preimages.len() as u64));
|
||||
|
||||
for (hash, status) in status.into_iter() {
|
||||
let preimage = if let Some(preimage) = preimages.get(&hash) {
|
||||
preimage
|
||||
} else {
|
||||
log::error!(target: TARGET, "preimage not found for hash {:?}", &hash);
|
||||
continue
|
||||
};
|
||||
let len = preimage.len() as u32;
|
||||
if len > MAX_SIZE {
|
||||
log::error!(
|
||||
target: TARGET,
|
||||
"preimage too large for hash {:?}, len: {}",
|
||||
&hash,
|
||||
len
|
||||
);
|
||||
continue
|
||||
}
|
||||
|
||||
let status = match status {
|
||||
v0::RequestStatus::Unrequested(deposit) => match deposit {
|
||||
Some(deposit) => RequestStatus::Unrequested { deposit, len },
|
||||
// `None` depositor becomes system-requested.
|
||||
None =>
|
||||
RequestStatus::Requested { deposit: None, count: 1, len: Some(len) },
|
||||
},
|
||||
v0::RequestStatus::Requested(count) if count == 0 => {
|
||||
log::error!(target: TARGET, "preimage has counter of zero: {:?}", hash);
|
||||
continue
|
||||
},
|
||||
v0::RequestStatus::Requested(count) =>
|
||||
RequestStatus::Requested { deposit: None, count, len: Some(len) },
|
||||
};
|
||||
log::trace!(target: TARGET, "Moving preimage {:?} with len {}", hash, len);
|
||||
|
||||
crate::StatusFor::<T>::insert(hash, status);
|
||||
crate::PreimageFor::<T>::insert(&(hash, len), preimage);
|
||||
|
||||
weight.saturating_accrue(T::DbWeight::get().writes(2));
|
||||
}
|
||||
StorageVersion::new(1).put::<Pallet<T>>();
|
||||
|
||||
weight.saturating_add(T::DbWeight::get().writes(1))
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {
|
||||
let old_images: u32 =
|
||||
Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed");
|
||||
let new_images = image_count::<T>().expect("V1 storage corrupted");
|
||||
|
||||
if new_images != old_images {
|
||||
log::error!(
|
||||
target: TARGET,
|
||||
"migrated {} images, expected {}",
|
||||
new_images,
|
||||
old_images
|
||||
);
|
||||
}
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 1, "must upgrade");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of images or `None` if the storage is corrupted.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
pub fn image_count<T: Config>() -> Option<u32> {
|
||||
// Use iter_values() to ensure that the values are decodable.
|
||||
let images = crate::PreimageFor::<T>::iter_values().count() as u32;
|
||||
let status = crate::StatusFor::<T>::iter_values().count() as u32;
|
||||
|
||||
if images == status {
|
||||
Some(images)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "try-runtime")]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::mock::{Test as T, *};
|
||||
|
||||
use frame_support::bounded_vec;
|
||||
|
||||
#[test]
|
||||
fn migration_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 0);
|
||||
// Insert some preimages into the v0 storage:
|
||||
|
||||
// Case 1: Unrequested without deposit
|
||||
let (p, h) = preimage::<T>(128);
|
||||
v0::PreimageFor::<T>::insert(h, p);
|
||||
v0::StatusFor::<T>::insert(h, v0::RequestStatus::Unrequested(None));
|
||||
// Case 2: Unrequested with deposit
|
||||
let (p, h) = preimage::<T>(1024);
|
||||
v0::PreimageFor::<T>::insert(h, p);
|
||||
v0::StatusFor::<T>::insert(h, v0::RequestStatus::Unrequested(Some((1, 1))));
|
||||
// Case 3: Requested by 0 (invalid)
|
||||
let (p, h) = preimage::<T>(8192);
|
||||
v0::PreimageFor::<T>::insert(h, p);
|
||||
v0::StatusFor::<T>::insert(h, v0::RequestStatus::Requested(0));
|
||||
// Case 4: Requested by 10
|
||||
let (p, h) = preimage::<T>(65536);
|
||||
v0::PreimageFor::<T>::insert(h, p);
|
||||
v0::StatusFor::<T>::insert(h, v0::RequestStatus::Requested(10));
|
||||
|
||||
assert_eq!(v0::image_count::<T>(), Some(4));
|
||||
assert_eq!(v1::image_count::<T>(), None, "V1 storage should be corrupted");
|
||||
|
||||
let state = v1::Migration::<T>::pre_upgrade().unwrap();
|
||||
let _w = v1::Migration::<T>::on_runtime_upgrade();
|
||||
v1::Migration::<T>::post_upgrade(state).unwrap();
|
||||
|
||||
// V0 and V1 share the same prefix, so `iter_values` still counts the same.
|
||||
assert_eq!(v0::image_count::<T>(), Some(3));
|
||||
assert_eq!(v1::image_count::<T>(), Some(3)); // One gets skipped therefore 3.
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 1);
|
||||
|
||||
// Case 1: Unrequested without deposit becomes system-requested
|
||||
let (p, h) = preimage::<T>(128);
|
||||
assert_eq!(crate::PreimageFor::<T>::get(&(h, 128)), Some(p));
|
||||
assert_eq!(
|
||||
crate::StatusFor::<T>::get(h),
|
||||
Some(RequestStatus::Requested { deposit: None, count: 1, len: Some(128) })
|
||||
);
|
||||
// Case 2: Unrequested with deposit becomes unrequested
|
||||
let (p, h) = preimage::<T>(1024);
|
||||
assert_eq!(crate::PreimageFor::<T>::get(&(h, 1024)), Some(p));
|
||||
assert_eq!(
|
||||
crate::StatusFor::<T>::get(h),
|
||||
Some(RequestStatus::Unrequested { deposit: (1, 1), len: 1024 })
|
||||
);
|
||||
// Case 3: Requested by 0 should be skipped
|
||||
let (_, h) = preimage::<T>(8192);
|
||||
assert_eq!(crate::PreimageFor::<T>::get(&(h, 8192)), None);
|
||||
assert_eq!(crate::StatusFor::<T>::get(h), None);
|
||||
// Case 4: Requested by 10 becomes requested by 10
|
||||
let (p, h) = preimage::<T>(65536);
|
||||
assert_eq!(crate::PreimageFor::<T>::get(&(h, 65536)), Some(p));
|
||||
assert_eq!(
|
||||
crate::StatusFor::<T>::get(h),
|
||||
Some(RequestStatus::Requested { deposit: None, count: 10, len: Some(65536) })
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Returns a preimage with a given size and its hash.
|
||||
fn preimage<T: Config>(
|
||||
len: usize,
|
||||
) -> (BoundedVec<u8, ConstU32<MAX_SIZE>>, <T as frame_system::Config>::Hash) {
|
||||
let p = bounded_vec![1; len];
|
||||
let h = <T as frame_system::Config>::Hashing::hash_of(&p);
|
||||
(p, h)
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,6 @@ impl Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Currency = Balances;
|
||||
type ManagerOrigin = EnsureSignedBy<One, u64>;
|
||||
type MaxSize = ConstU32<1024>;
|
||||
type BaseDeposit = ConstU64<2>;
|
||||
type ByteDeposit = ConstU64<1>;
|
||||
}
|
||||
|
||||
@@ -17,11 +17,35 @@
|
||||
|
||||
//! # Scheduler tests.
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use super::*;
|
||||
use crate::mock::*;
|
||||
|
||||
use frame_support::{assert_noop, assert_ok};
|
||||
use frame_support::{
|
||||
assert_err, assert_noop, assert_ok, assert_storage_noop, bounded_vec,
|
||||
traits::{Bounded, BoundedInline, Hash as PreimageHash},
|
||||
StorageNoopGuard,
|
||||
};
|
||||
use pallet_balances::Error as BalancesError;
|
||||
use sp_core::{blake2_256, H256};
|
||||
|
||||
/// Returns one `Inline`, `Lookup` and `Legacy` item each with different data and hash.
|
||||
pub fn make_bounded_values() -> (Bounded<Vec<u8>>, Bounded<Vec<u8>>, Bounded<Vec<u8>>) {
|
||||
let data: BoundedInline = bounded_vec![1];
|
||||
let inline = Bounded::<Vec<u8>>::Inline(data);
|
||||
|
||||
let data = vec![1, 2];
|
||||
let hash: H256 = blake2_256(&data[..]).into();
|
||||
let len = data.len() as u32;
|
||||
let lookup = Bounded::<Vec<u8>>::unrequested(hash, len);
|
||||
|
||||
let data = vec![1, 2, 3];
|
||||
let hash: H256 = blake2_256(&data[..]).into();
|
||||
let legacy = Bounded::<Vec<u8>>::Legacy { hash, dummy: Default::default() };
|
||||
|
||||
(inline, lookup, legacy)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn user_note_preimage_works() {
|
||||
@@ -56,10 +80,7 @@ fn manager_note_preimage_works() {
|
||||
assert!(Preimage::have_preimage(&h));
|
||||
assert_eq!(Preimage::get_preimage(&h), Some(vec![1]));
|
||||
|
||||
assert_noop!(
|
||||
Preimage::note_preimage(RuntimeOrigin::signed(1), vec![1]),
|
||||
Error::<Test>::AlreadyNoted
|
||||
);
|
||||
assert_ok!(Preimage::note_preimage(RuntimeOrigin::signed(1), vec![1]));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -130,14 +151,16 @@ fn requested_then_noted_preimage_cannot_be_unnoted() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Preimage::note_preimage(RuntimeOrigin::signed(1), vec![1]));
|
||||
assert_ok!(Preimage::request_preimage(RuntimeOrigin::signed(1), hashed([1])));
|
||||
assert_noop!(
|
||||
Preimage::unnote_preimage(RuntimeOrigin::signed(1), hashed([1])),
|
||||
Error::<Test>::Requested
|
||||
);
|
||||
assert_ok!(Preimage::unnote_preimage(RuntimeOrigin::signed(1), hashed([1])));
|
||||
// it's still here.
|
||||
|
||||
let h = hashed([1]);
|
||||
assert!(Preimage::have_preimage(&h));
|
||||
assert_eq!(Preimage::get_preimage(&h), Some(vec![1]));
|
||||
|
||||
// now it's gone
|
||||
assert_ok!(Preimage::unrequest_preimage(RuntimeOrigin::signed(1), hashed([1])));
|
||||
assert!(!Preimage::have_preimage(&hashed([1])));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -145,15 +168,16 @@ fn requested_then_noted_preimage_cannot_be_unnoted() {
|
||||
fn request_note_order_makes_no_difference() {
|
||||
let one_way = new_test_ext().execute_with(|| {
|
||||
assert_ok!(Preimage::request_preimage(RuntimeOrigin::signed(1), hashed([1])));
|
||||
assert_ok!(Preimage::note_preimage(RuntimeOrigin::signed(1), vec![1]));
|
||||
assert_ok!(Preimage::note_preimage(RuntimeOrigin::signed(2), vec![1]));
|
||||
(
|
||||
StatusFor::<Test>::iter().collect::<Vec<_>>(),
|
||||
PreimageFor::<Test>::iter().collect::<Vec<_>>(),
|
||||
)
|
||||
});
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Preimage::note_preimage(RuntimeOrigin::signed(1), vec![1]));
|
||||
assert_ok!(Preimage::note_preimage(RuntimeOrigin::signed(2), vec![1]));
|
||||
assert_ok!(Preimage::request_preimage(RuntimeOrigin::signed(1), hashed([1])));
|
||||
assert_ok!(Preimage::unnote_preimage(RuntimeOrigin::signed(2), hashed([1])));
|
||||
let other_way = (
|
||||
StatusFor::<Test>::iter().collect::<Vec<_>>(),
|
||||
PreimageFor::<Test>::iter().collect::<Vec<_>>(),
|
||||
@@ -189,6 +213,7 @@ fn request_user_note_order_makes_no_difference() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Preimage::note_preimage(RuntimeOrigin::signed(2), vec![1]));
|
||||
assert_ok!(Preimage::request_preimage(RuntimeOrigin::signed(1), hashed([1])));
|
||||
assert_ok!(Preimage::unnote_preimage(RuntimeOrigin::signed(2), hashed([1])));
|
||||
let other_way = (
|
||||
StatusFor::<Test>::iter().collect::<Vec<_>>(),
|
||||
PreimageFor::<Test>::iter().collect::<Vec<_>>(),
|
||||
@@ -226,8 +251,240 @@ fn user_noted_then_requested_preimage_is_refunded_once_only() {
|
||||
assert_ok!(Preimage::note_preimage(RuntimeOrigin::signed(2), vec![1]));
|
||||
assert_ok!(Preimage::request_preimage(RuntimeOrigin::signed(1), hashed([1])));
|
||||
assert_ok!(Preimage::unrequest_preimage(RuntimeOrigin::signed(1), hashed([1])));
|
||||
assert_ok!(Preimage::unnote_preimage(RuntimeOrigin::signed(2), hashed([1])));
|
||||
// Still have reserve from `vec[1; 3]`.
|
||||
assert_eq!(Balances::reserved_balance(2), 5);
|
||||
assert_eq!(Balances::free_balance(2), 95);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn noted_preimage_use_correct_map() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Add one preimage per bucket...
|
||||
for i in 0..7 {
|
||||
assert_ok!(Preimage::note_preimage(RuntimeOrigin::signed(1), vec![0; 128 << (i * 2)]));
|
||||
}
|
||||
assert_ok!(Preimage::note_preimage(RuntimeOrigin::signed(1), vec![0; MAX_SIZE as usize]));
|
||||
assert_eq!(PreimageFor::<Test>::iter().count(), 8);
|
||||
|
||||
// All are present
|
||||
assert_eq!(StatusFor::<Test>::iter().count(), 8);
|
||||
|
||||
// Now start removing them again...
|
||||
for i in 0..7 {
|
||||
assert_ok!(Preimage::unnote_preimage(
|
||||
RuntimeOrigin::signed(1),
|
||||
hashed(vec![0; 128 << (i * 2)])
|
||||
));
|
||||
}
|
||||
assert_eq!(PreimageFor::<Test>::iter().count(), 1);
|
||||
assert_ok!(Preimage::unnote_preimage(
|
||||
RuntimeOrigin::signed(1),
|
||||
hashed(vec![0; MAX_SIZE as usize])
|
||||
));
|
||||
assert_eq!(PreimageFor::<Test>::iter().count(), 0);
|
||||
|
||||
// All are gone
|
||||
assert_eq!(StatusFor::<Test>::iter().count(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
/// The `StorePreimage` and `QueryPreimage` traits work together.
|
||||
#[test]
|
||||
fn query_and_store_preimage_workflow() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let _guard = StorageNoopGuard::default();
|
||||
let data: Vec<u8> = vec![1; 512];
|
||||
let encoded = data.encode();
|
||||
|
||||
// Bound an unbound value.
|
||||
let bound = Preimage::bound(data.clone()).unwrap();
|
||||
let (len, hash) = (bound.len().unwrap(), bound.hash());
|
||||
|
||||
assert_eq!(hash, blake2_256(&encoded).into());
|
||||
assert_eq!(bound.len(), Some(len));
|
||||
assert!(bound.lookup_needed(), "Should not be Inlined");
|
||||
assert_eq!(bound.lookup_len(), Some(len));
|
||||
|
||||
// The value is requested and available.
|
||||
assert!(Preimage::is_requested(&hash));
|
||||
assert!(<Preimage as QueryPreimage>::have(&bound));
|
||||
assert_eq!(Preimage::len(&hash), Some(len));
|
||||
|
||||
// It can be fetched with length.
|
||||
assert_eq!(Preimage::fetch(&hash, Some(len)).unwrap(), encoded);
|
||||
// ... and without length.
|
||||
assert_eq!(Preimage::fetch(&hash, None).unwrap(), encoded);
|
||||
// ... but not with wrong length.
|
||||
assert_err!(Preimage::fetch(&hash, Some(0)), DispatchError::Unavailable);
|
||||
|
||||
// It can be peeked and decoded correctly.
|
||||
assert_eq!(Preimage::peek::<Vec<u8>>(&bound).unwrap(), (data.clone(), Some(len)));
|
||||
// Request it two more times.
|
||||
assert_eq!(Preimage::pick::<Vec<u8>>(hash, len), bound);
|
||||
Preimage::request(&hash);
|
||||
// It is requested thrice.
|
||||
assert!(matches!(
|
||||
StatusFor::<Test>::get(&hash).unwrap(),
|
||||
RequestStatus::Requested { count: 3, .. }
|
||||
));
|
||||
|
||||
// It can be realized and decoded correctly.
|
||||
assert_eq!(Preimage::realize::<Vec<u8>>(&bound).unwrap(), (data.clone(), Some(len)));
|
||||
assert!(matches!(
|
||||
StatusFor::<Test>::get(&hash).unwrap(),
|
||||
RequestStatus::Requested { count: 2, .. }
|
||||
));
|
||||
// Dropping should unrequest.
|
||||
Preimage::drop(&bound);
|
||||
assert!(matches!(
|
||||
StatusFor::<Test>::get(&hash).unwrap(),
|
||||
RequestStatus::Requested { count: 1, .. }
|
||||
));
|
||||
|
||||
// Is still available.
|
||||
assert!(<Preimage as QueryPreimage>::have(&bound));
|
||||
// Manually unnote it.
|
||||
Preimage::unnote(&hash);
|
||||
// Is not available anymore.
|
||||
assert!(!<Preimage as QueryPreimage>::have(&bound));
|
||||
assert_err!(Preimage::fetch(&hash, Some(len)), DispatchError::Unavailable);
|
||||
// And not requested since the traits assume permissioned origin.
|
||||
assert!(!Preimage::is_requested(&hash));
|
||||
|
||||
// No storage changes remain. Checked by `StorageNoopGuard`.
|
||||
});
|
||||
}
|
||||
|
||||
/// The request function behaves as expected.
|
||||
#[test]
|
||||
fn query_preimage_request_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let _guard = StorageNoopGuard::default();
|
||||
let data: Vec<u8> = vec![1; 10];
|
||||
let hash: PreimageHash = blake2_256(&data[..]).into();
|
||||
|
||||
// Request the preimage.
|
||||
<Preimage as QueryPreimage>::request(&hash);
|
||||
|
||||
// The preimage is requested with unknown length and cannot be fetched.
|
||||
assert!(<Preimage as QueryPreimage>::is_requested(&hash));
|
||||
assert!(<Preimage as QueryPreimage>::len(&hash).is_none());
|
||||
assert_noop!(<Preimage as QueryPreimage>::fetch(&hash, None), DispatchError::Unavailable);
|
||||
|
||||
// Request again.
|
||||
<Preimage as QueryPreimage>::request(&hash);
|
||||
// The preimage is still requested.
|
||||
assert!(<Preimage as QueryPreimage>::is_requested(&hash));
|
||||
assert!(<Preimage as QueryPreimage>::len(&hash).is_none());
|
||||
assert_noop!(<Preimage as QueryPreimage>::fetch(&hash, None), DispatchError::Unavailable);
|
||||
// But there is only one entry in the map.
|
||||
assert_eq!(StatusFor::<Test>::iter().count(), 1);
|
||||
|
||||
// Un-request the preimage.
|
||||
<Preimage as QueryPreimage>::unrequest(&hash);
|
||||
// It is still requested.
|
||||
assert!(<Preimage as QueryPreimage>::is_requested(&hash));
|
||||
// Un-request twice.
|
||||
<Preimage as QueryPreimage>::unrequest(&hash);
|
||||
// It is not requested anymore.
|
||||
assert!(!<Preimage as QueryPreimage>::is_requested(&hash));
|
||||
// And there is no entry in the map.
|
||||
assert_eq!(StatusFor::<Test>::iter().count(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
/// The `QueryPreimage` functions can be used together with `Bounded` values.
|
||||
#[test]
|
||||
fn query_preimage_hold_and_drop_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let _guard = StorageNoopGuard::default();
|
||||
let (inline, lookup, legacy) = make_bounded_values();
|
||||
|
||||
// `hold` does nothing for `Inline` values.
|
||||
assert_storage_noop!(<Preimage as QueryPreimage>::hold(&inline));
|
||||
// `hold` requests `Lookup` values.
|
||||
<Preimage as QueryPreimage>::hold(&lookup);
|
||||
assert!(<Preimage as QueryPreimage>::is_requested(&lookup.hash()));
|
||||
// `hold` requests `Legacy` values.
|
||||
<Preimage as QueryPreimage>::hold(&legacy);
|
||||
assert!(<Preimage as QueryPreimage>::is_requested(&legacy.hash()));
|
||||
|
||||
// There are two values requested in total.
|
||||
assert_eq!(StatusFor::<Test>::iter().count(), 2);
|
||||
|
||||
// Cleanup by dropping both.
|
||||
<Preimage as QueryPreimage>::drop(&lookup);
|
||||
assert!(!<Preimage as QueryPreimage>::is_requested(&lookup.hash()));
|
||||
<Preimage as QueryPreimage>::drop(&legacy);
|
||||
assert!(!<Preimage as QueryPreimage>::is_requested(&legacy.hash()));
|
||||
|
||||
// There are no values requested anymore.
|
||||
assert_eq!(StatusFor::<Test>::iter().count(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
/// The `StorePreimage` trait works as expected.
|
||||
#[test]
|
||||
fn store_preimage_basic_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let _guard = StorageNoopGuard::default();
|
||||
let data: Vec<u8> = vec![1; 512]; // Too large to inline.
|
||||
let encoded = Cow::from(data.encode());
|
||||
|
||||
// Bound the data.
|
||||
let bound = <Preimage as StorePreimage>::bound(data.clone()).unwrap();
|
||||
// The preimage can be peeked.
|
||||
assert_ok!(<Preimage as QueryPreimage>::peek(&bound));
|
||||
// Un-note the preimage.
|
||||
<Preimage as StorePreimage>::unnote(&bound.hash());
|
||||
// The preimage cannot be peeked anymore.
|
||||
assert_err!(<Preimage as QueryPreimage>::peek(&bound), DispatchError::Unavailable);
|
||||
// Noting the wrong pre-image does not make it peek-able.
|
||||
assert_ok!(<Preimage as StorePreimage>::note(Cow::Borrowed(&data)));
|
||||
assert_err!(<Preimage as QueryPreimage>::peek(&bound), DispatchError::Unavailable);
|
||||
|
||||
// Manually note the preimage makes it peek-able again.
|
||||
assert_ok!(<Preimage as StorePreimage>::note(encoded.clone()));
|
||||
// Noting again works.
|
||||
assert_ok!(<Preimage as StorePreimage>::note(encoded));
|
||||
assert_ok!(<Preimage as QueryPreimage>::peek(&bound));
|
||||
|
||||
// Cleanup.
|
||||
<Preimage as StorePreimage>::unnote(&bound.hash());
|
||||
let data_hash = blake2_256(&data);
|
||||
<Preimage as StorePreimage>::unnote(&data_hash.into());
|
||||
|
||||
// No storage changes remain. Checked by `StorageNoopGuard`.
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn store_preimage_note_too_large_errors() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Works with `MAX_LENGTH`.
|
||||
let len = <Preimage as StorePreimage>::MAX_LENGTH;
|
||||
let data = vec![0u8; len];
|
||||
assert_ok!(<Preimage as StorePreimage>::note(data.into()));
|
||||
|
||||
// Errors with `MAX_LENGTH+1`.
|
||||
let data = vec![0u8; len + 1];
|
||||
assert_err!(<Preimage as StorePreimage>::note(data.into()), DispatchError::Exhausted);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn store_preimage_bound_too_large_errors() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Using `MAX_LENGTH` number of bytes in a vector does not work
|
||||
// since SCALE prepends the length.
|
||||
let len = <Preimage as StorePreimage>::MAX_LENGTH;
|
||||
let data: Vec<u8> = vec![0; len];
|
||||
assert_err!(<Preimage as StorePreimage>::bound(data.clone()), DispatchError::Exhausted);
|
||||
|
||||
// Works with `MAX_LENGTH-4`.
|
||||
let data: Vec<u8> = vec![0; len - 4];
|
||||
assert_ok!(<Preimage as StorePreimage>::bound(data.clone()));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,22 +18,24 @@
|
||||
//! Autogenerated weights for pallet_preimage
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2022-05-23, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! DATE: 2022-10-03, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/production/substrate
|
||||
// /home/benchbot/cargo_target_dir/production/substrate
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=pallet_preimage
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --template=./.maintain/frame-weight-template.hbs
|
||||
// --heap-pages=4096
|
||||
// --pallet=pallet_preimage
|
||||
// --chain=dev
|
||||
// --output=./frame/preimage/src/weights.rs
|
||||
// --template=./.maintain/frame-weight-template.hbs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
@@ -61,88 +63,90 @@ pub trait WeightInfo {
|
||||
/// Weights for pallet_preimage using the Substrate node and recommended hardware.
|
||||
pub struct SubstrateWeight<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
/// The range of component `s` is `[0, 4194304]`.
|
||||
fn note_preimage(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(0 as u64)
|
||||
Weight::from_ref_time(32_591_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(Weight::from_ref_time(1_680 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:0)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
/// The range of component `s` is `[0, 4194304]`.
|
||||
fn note_requested_preimage(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(0 as u64)
|
||||
Weight::from_ref_time(23_350_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
.saturating_add(Weight::from_ref_time(1_681 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:0)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
/// The range of component `s` is `[0, 4194304]`.
|
||||
fn note_no_deposit_preimage(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(0 as u64)
|
||||
Weight::from_ref_time(21_436_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
.saturating_add(Weight::from_ref_time(1_680 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
fn unnote_preimage() -> Weight {
|
||||
Weight::from_ref_time(44_380_000 as u64)
|
||||
Weight::from_ref_time(44_567_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
fn unnote_no_deposit_preimage() -> Weight {
|
||||
Weight::from_ref_time(30_280_000 as u64)
|
||||
Weight::from_ref_time(30_065_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn request_preimage() -> Weight {
|
||||
Weight::from_ref_time(42_809_000 as u64)
|
||||
Weight::from_ref_time(28_470_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn request_no_deposit_preimage() -> Weight {
|
||||
Weight::from_ref_time(28_964_000 as u64)
|
||||
Weight::from_ref_time(14_601_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn request_unnoted_preimage() -> Weight {
|
||||
Weight::from_ref_time(17_555_000 as u64)
|
||||
Weight::from_ref_time(20_121_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn request_requested_preimage() -> Weight {
|
||||
Weight::from_ref_time(7_745_000 as u64)
|
||||
Weight::from_ref_time(9_440_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
fn unrequest_preimage() -> Weight {
|
||||
Weight::from_ref_time(29_758_000 as u64)
|
||||
Weight::from_ref_time(29_013_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
fn unrequest_unnoted_preimage() -> Weight {
|
||||
Weight::from_ref_time(18_360_000 as u64)
|
||||
Weight::from_ref_time(9_223_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn unrequest_multi_referenced_preimage() -> Weight {
|
||||
Weight::from_ref_time(7_439_000 as u64)
|
||||
Weight::from_ref_time(9_252_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
@@ -150,88 +154,90 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
|
||||
// For backwards compatibility and tests
|
||||
impl WeightInfo for () {
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
/// The range of component `s` is `[0, 4194304]`.
|
||||
fn note_preimage(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(0 as u64)
|
||||
Weight::from_ref_time(32_591_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(Weight::from_ref_time(1_680 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:0)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
/// The range of component `s` is `[0, 4194304]`.
|
||||
fn note_requested_preimage(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(0 as u64)
|
||||
Weight::from_ref_time(23_350_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
.saturating_add(Weight::from_ref_time(1_681 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:0)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
/// The range of component `s` is `[0, 4194304]`.
|
||||
fn note_no_deposit_preimage(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(0 as u64)
|
||||
Weight::from_ref_time(21_436_000 as u64)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
.saturating_add(Weight::from_ref_time(1_680 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
fn unnote_preimage() -> Weight {
|
||||
Weight::from_ref_time(44_380_000 as u64)
|
||||
Weight::from_ref_time(44_567_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
fn unnote_no_deposit_preimage() -> Weight {
|
||||
Weight::from_ref_time(30_280_000 as u64)
|
||||
Weight::from_ref_time(30_065_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn request_preimage() -> Weight {
|
||||
Weight::from_ref_time(42_809_000 as u64)
|
||||
Weight::from_ref_time(28_470_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn request_no_deposit_preimage() -> Weight {
|
||||
Weight::from_ref_time(28_964_000 as u64)
|
||||
Weight::from_ref_time(14_601_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn request_unnoted_preimage() -> Weight {
|
||||
Weight::from_ref_time(17_555_000 as u64)
|
||||
Weight::from_ref_time(20_121_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn request_requested_preimage() -> Weight {
|
||||
Weight::from_ref_time(7_745_000 as u64)
|
||||
Weight::from_ref_time(9_440_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
fn unrequest_preimage() -> Weight {
|
||||
Weight::from_ref_time(29_758_000 as u64)
|
||||
Weight::from_ref_time(29_013_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:0 w:1)
|
||||
fn unrequest_unnoted_preimage() -> Weight {
|
||||
Weight::from_ref_time(18_360_000 as u64)
|
||||
Weight::from_ref_time(9_223_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn unrequest_multi_referenced_preimage() -> Weight {
|
||||
Weight::from_ref_time(7_439_000 as u64)
|
||||
Weight::from_ref_time(9_252_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
|
||||
@@ -452,7 +452,7 @@ pub mod pallet {
|
||||
ensure!(!friends.is_empty(), Error::<T>::NotEnoughFriends);
|
||||
ensure!(threshold as usize <= friends.len(), Error::<T>::NotEnoughFriends);
|
||||
let bounded_friends: FriendsOf<T> =
|
||||
friends.try_into().map_err(|()| Error::<T>::MaxFriends)?;
|
||||
friends.try_into().map_err(|_| Error::<T>::MaxFriends)?;
|
||||
ensure!(Self::is_sorted_and_unique(&bounded_friends), Error::<T>::NotSorted);
|
||||
// Total deposit is base fee + number of friends * factor fee
|
||||
let friend_deposit = T::FriendDepositFactor::get()
|
||||
@@ -554,7 +554,7 @@ pub mod pallet {
|
||||
Err(pos) => active_recovery
|
||||
.friends
|
||||
.try_insert(pos, who.clone())
|
||||
.map_err(|()| Error::<T>::MaxFriends)?,
|
||||
.map_err(|_| Error::<T>::MaxFriends)?,
|
||||
}
|
||||
// Update storage with the latest details
|
||||
<ActiveRecoveries<T>>::insert(&lost, &rescuer, active_recovery);
|
||||
|
||||
@@ -24,10 +24,10 @@ use frame_benchmarking::{account, benchmarks_instance_pallet, whitelist_account}
|
||||
use frame_support::{
|
||||
assert_ok,
|
||||
dispatch::UnfilteredDispatchable,
|
||||
traits::{Currency, EnsureOrigin},
|
||||
traits::{Bounded, Currency, EnsureOrigin},
|
||||
};
|
||||
use frame_system::RawOrigin;
|
||||
use sp_runtime::traits::{Bounded, Hash};
|
||||
use sp_runtime::traits::Bounded as ArithBounded;
|
||||
|
||||
const SEED: u32 = 0;
|
||||
|
||||
@@ -42,6 +42,12 @@ fn funded_account<T: Config<I>, I: 'static>(name: &'static str, index: u32) -> T
|
||||
caller
|
||||
}
|
||||
|
||||
fn dummy_call<T: Config<I>, I: 'static>() -> Bounded<<T as Config<I>>::RuntimeCall> {
|
||||
let inner = frame_system::Call::remark { remark: vec![] };
|
||||
let call = <T as Config<I>>::RuntimeCall::from(inner);
|
||||
T::Preimages::bound(call).unwrap()
|
||||
}
|
||||
|
||||
fn create_referendum<T: Config<I>, I: 'static>() -> (T::RuntimeOrigin, ReferendumIndex) {
|
||||
let origin: T::RuntimeOrigin = T::SubmitOrigin::successful_origin();
|
||||
if let Ok(caller) = frame_system::ensure_signed(origin.clone()) {
|
||||
@@ -50,9 +56,9 @@ fn create_referendum<T: Config<I>, I: 'static>() -> (T::RuntimeOrigin, Referendu
|
||||
}
|
||||
|
||||
let proposal_origin = Box::new(RawOrigin::Root.into());
|
||||
let proposal_hash = T::Hashing::hash_of(&0);
|
||||
let proposal = dummy_call::<T, I>();
|
||||
let enactment_moment = DispatchTime::After(0u32.into());
|
||||
let call = Call::<T, I>::submit { proposal_origin, proposal_hash, enactment_moment };
|
||||
let call = crate::Call::<T, I>::submit { proposal_origin, proposal, enactment_moment };
|
||||
assert_ok!(call.dispatch_bypass_filter(origin.clone()));
|
||||
let index = ReferendumCount::<T, I>::get() - 1;
|
||||
(origin, index)
|
||||
@@ -196,7 +202,7 @@ benchmarks_instance_pallet! {
|
||||
}: _<T::RuntimeOrigin>(
|
||||
origin,
|
||||
Box::new(RawOrigin::Root.into()),
|
||||
T::Hashing::hash_of(&0),
|
||||
dummy_call::<T, I>(),
|
||||
DispatchTime::After(0u32.into())
|
||||
) verify {
|
||||
let index = ReferendumCount::<T, I>::get().checked_sub(1).unwrap();
|
||||
|
||||
@@ -69,11 +69,11 @@ use frame_support::{
|
||||
ensure,
|
||||
traits::{
|
||||
schedule::{
|
||||
v2::{Anon as ScheduleAnon, Named as ScheduleNamed},
|
||||
DispatchTime, MaybeHashed,
|
||||
v3::{Anon as ScheduleAnon, Named as ScheduleNamed},
|
||||
DispatchTime,
|
||||
},
|
||||
Currency, LockIdentifier, OnUnbalanced, OriginTrait, PollStatus, Polling,
|
||||
ReservableCurrency, VoteTally,
|
||||
Currency, LockIdentifier, OnUnbalanced, OriginTrait, PollStatus, Polling, QueryPreimage,
|
||||
ReservableCurrency, StorePreimage, VoteTally,
|
||||
},
|
||||
BoundedVec,
|
||||
};
|
||||
@@ -92,10 +92,10 @@ use self::branch::{BeginDecidingBranch, OneFewerDecidingBranch, ServiceBranch};
|
||||
pub use self::{
|
||||
pallet::*,
|
||||
types::{
|
||||
BalanceOf, CallOf, Curve, DecidingStatus, DecidingStatusOf, Deposit, InsertSorted,
|
||||
NegativeImbalanceOf, PalletsOriginOf, ReferendumIndex, ReferendumInfo, ReferendumInfoOf,
|
||||
ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, TallyOf, TrackIdOf, TrackInfo,
|
||||
TrackInfoOf, TracksInfo, VotesOf,
|
||||
BalanceOf, BoundedCallOf, CallOf, Curve, DecidingStatus, DecidingStatusOf, Deposit,
|
||||
InsertSorted, NegativeImbalanceOf, PalletsOriginOf, ReferendumIndex, ReferendumInfo,
|
||||
ReferendumInfoOf, ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, TallyOf,
|
||||
TrackIdOf, TrackInfo, TrackInfoOf, TracksInfo, VotesOf,
|
||||
},
|
||||
weights::WeightInfo,
|
||||
};
|
||||
@@ -149,23 +149,16 @@ pub mod pallet {
|
||||
// System level stuff.
|
||||
type RuntimeCall: Parameter
|
||||
+ Dispatchable<RuntimeOrigin = Self::RuntimeOrigin>
|
||||
+ From<Call<Self, I>>;
|
||||
+ From<Call<Self, I>>
|
||||
+ IsType<<Self as frame_system::Config>::RuntimeCall>
|
||||
+ From<frame_system::Call<Self>>;
|
||||
type RuntimeEvent: From<Event<Self, I>>
|
||||
+ IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
/// Weight information for extrinsics in this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
/// The Scheduler.
|
||||
type Scheduler: ScheduleAnon<
|
||||
Self::BlockNumber,
|
||||
CallOf<Self, I>,
|
||||
PalletsOriginOf<Self>,
|
||||
Hash = Self::Hash,
|
||||
> + ScheduleNamed<
|
||||
Self::BlockNumber,
|
||||
CallOf<Self, I>,
|
||||
PalletsOriginOf<Self>,
|
||||
Hash = Self::Hash,
|
||||
>;
|
||||
type Scheduler: ScheduleAnon<Self::BlockNumber, CallOf<Self, I>, PalletsOriginOf<Self>>
|
||||
+ ScheduleNamed<Self::BlockNumber, CallOf<Self, I>, PalletsOriginOf<Self>>;
|
||||
/// Currency type for this pallet.
|
||||
type Currency: ReservableCurrency<Self::AccountId>;
|
||||
// Origins and unbalances.
|
||||
@@ -221,6 +214,9 @@ pub mod pallet {
|
||||
Self::BlockNumber,
|
||||
RuntimeOrigin = <Self::RuntimeOrigin as OriginTrait>::PalletsOrigin,
|
||||
>;
|
||||
|
||||
/// The preimage provider.
|
||||
type Preimages: QueryPreimage + StorePreimage;
|
||||
}
|
||||
|
||||
/// The next free referendum index, aka the number of referenda started so far.
|
||||
@@ -259,8 +255,8 @@ pub mod pallet {
|
||||
index: ReferendumIndex,
|
||||
/// The track (and by extension proposal dispatch origin) of this referendum.
|
||||
track: TrackIdOf<T, I>,
|
||||
/// The hash of the proposal up for referendum.
|
||||
proposal_hash: T::Hash,
|
||||
/// The proposal for the referendum.
|
||||
proposal: BoundedCallOf<T, I>,
|
||||
},
|
||||
/// The decision deposit has been placed.
|
||||
DecisionDepositPlaced {
|
||||
@@ -293,8 +289,8 @@ pub mod pallet {
|
||||
index: ReferendumIndex,
|
||||
/// The track (and by extension proposal dispatch origin) of this referendum.
|
||||
track: TrackIdOf<T, I>,
|
||||
/// The hash of the proposal up for referendum.
|
||||
proposal_hash: T::Hash,
|
||||
/// The proposal for the referendum.
|
||||
proposal: BoundedCallOf<T, I>,
|
||||
/// The current tally of votes in this referendum.
|
||||
tally: T::Tally,
|
||||
},
|
||||
@@ -381,7 +377,7 @@ pub mod pallet {
|
||||
/// - `origin`: must be `SubmitOrigin` and the account must have `SubmissionDeposit` funds
|
||||
/// available.
|
||||
/// - `proposal_origin`: The origin from which the proposal should be executed.
|
||||
/// - `proposal_hash`: The hash of the proposal preimage.
|
||||
/// - `proposal`: The proposal.
|
||||
/// - `enactment_moment`: The moment that the proposal should be enacted.
|
||||
///
|
||||
/// Emits `Submitted`.
|
||||
@@ -389,7 +385,7 @@ pub mod pallet {
|
||||
pub fn submit(
|
||||
origin: OriginFor<T>,
|
||||
proposal_origin: Box<PalletsOriginOf<T>>,
|
||||
proposal_hash: T::Hash,
|
||||
proposal: BoundedCallOf<T, I>,
|
||||
enactment_moment: DispatchTime<T::BlockNumber>,
|
||||
) -> DispatchResult {
|
||||
let who = T::SubmitOrigin::ensure_origin(origin)?;
|
||||
@@ -403,11 +399,12 @@ pub mod pallet {
|
||||
r
|
||||
});
|
||||
let now = frame_system::Pallet::<T>::block_number();
|
||||
let nudge_call = Call::nudge_referendum { index };
|
||||
let nudge_call =
|
||||
T::Preimages::bound(CallOf::<T, I>::from(Call::nudge_referendum { index }))?;
|
||||
let status = ReferendumStatus {
|
||||
track,
|
||||
origin: *proposal_origin,
|
||||
proposal_hash,
|
||||
proposal: proposal.clone(),
|
||||
enactment: enactment_moment,
|
||||
submitted: now,
|
||||
submission_deposit,
|
||||
@@ -419,7 +416,7 @@ pub mod pallet {
|
||||
};
|
||||
ReferendumInfoFor::<T, I>::insert(index, ReferendumInfo::Ongoing(status));
|
||||
|
||||
Self::deposit_event(Event::<T, I>::Submitted { index, track, proposal_hash });
|
||||
Self::deposit_event(Event::<T, I>::Submitted { index, track, proposal });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -651,7 +648,8 @@ impl<T: Config<I>, I: 'static> Polling<T::Tally> for Pallet<T, I> {
|
||||
let mut status = ReferendumStatusOf::<T, I> {
|
||||
track: class,
|
||||
origin: frame_support::dispatch::RawOrigin::Root.into(),
|
||||
proposal_hash: <T::Hashing as sp_runtime::traits::Hash>::hash_of(&index),
|
||||
proposal: T::Preimages::bound(CallOf::<T, I>::from(Call::nudge_referendum { index }))
|
||||
.map_err(|_| ())?,
|
||||
enactment: DispatchTime::After(Zero::zero()),
|
||||
submitted: now,
|
||||
submission_deposit: Deposit { who: dummy_account_id, amount: Zero::zero() },
|
||||
@@ -709,18 +707,18 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
track: &TrackInfoOf<T, I>,
|
||||
desired: DispatchTime<T::BlockNumber>,
|
||||
origin: PalletsOriginOf<T>,
|
||||
call_hash: T::Hash,
|
||||
call: BoundedCallOf<T, I>,
|
||||
) {
|
||||
let now = frame_system::Pallet::<T>::block_number();
|
||||
let earliest_allowed = now.saturating_add(track.min_enactment_period);
|
||||
let desired = desired.evaluate(now);
|
||||
let ok = T::Scheduler::schedule_named(
|
||||
(ASSEMBLY_ID, "enactment", index).encode(),
|
||||
(ASSEMBLY_ID, "enactment", index).using_encoded(sp_io::hashing::blake2_256),
|
||||
DispatchTime::At(desired.max(earliest_allowed)),
|
||||
None,
|
||||
63,
|
||||
origin,
|
||||
MaybeHashed::Hash(call_hash),
|
||||
call,
|
||||
)
|
||||
.is_ok();
|
||||
debug_assert!(ok, "LOGIC ERROR: bake_referendum/schedule_named failed");
|
||||
@@ -728,7 +726,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
|
||||
/// Set an alarm to dispatch `call` at block number `when`.
|
||||
fn set_alarm(
|
||||
call: impl Into<CallOf<T, I>>,
|
||||
call: BoundedCallOf<T, I>,
|
||||
when: T::BlockNumber,
|
||||
) -> Option<(T::BlockNumber, ScheduleAddressOf<T, I>)> {
|
||||
let alarm_interval = T::AlarmInterval::get().max(One::one());
|
||||
@@ -739,7 +737,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
None,
|
||||
128u8,
|
||||
frame_system::RawOrigin::Root.into(),
|
||||
MaybeHashed::Value(call.into()),
|
||||
call,
|
||||
)
|
||||
.ok()
|
||||
.map(|x| (when, x));
|
||||
@@ -776,7 +774,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
Self::deposit_event(Event::<T, I>::DecisionStarted {
|
||||
index,
|
||||
tally: status.tally.clone(),
|
||||
proposal_hash: status.proposal_hash,
|
||||
proposal: status.proposal.clone(),
|
||||
track: status.track,
|
||||
});
|
||||
let confirming = if is_passing {
|
||||
@@ -843,12 +841,21 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
let alarm_interval = T::AlarmInterval::get().max(One::one());
|
||||
let when = (next_block + alarm_interval - One::one()) / alarm_interval * alarm_interval;
|
||||
|
||||
let call = match T::Preimages::bound(CallOf::<T, I>::from(Call::one_fewer_deciding {
|
||||
track,
|
||||
})) {
|
||||
Ok(c) => c,
|
||||
Err(_) => {
|
||||
debug_assert!(false, "Unable to create a bounded call from `one_fewer_deciding`??",);
|
||||
return
|
||||
},
|
||||
};
|
||||
let maybe_result = T::Scheduler::schedule(
|
||||
DispatchTime::At(when),
|
||||
None,
|
||||
128u8,
|
||||
frame_system::RawOrigin::Root.into(),
|
||||
MaybeHashed::Value(Call::one_fewer_deciding { track }.into()),
|
||||
call,
|
||||
);
|
||||
debug_assert!(
|
||||
maybe_result.is_ok(),
|
||||
@@ -871,7 +878,18 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
if status.alarm.as_ref().map_or(true, |&(when, _)| when != alarm) {
|
||||
// Either no alarm or one that was different
|
||||
Self::ensure_no_alarm(status);
|
||||
status.alarm = Self::set_alarm(Call::nudge_referendum { index }, alarm);
|
||||
let call =
|
||||
match T::Preimages::bound(CallOf::<T, I>::from(Call::nudge_referendum { index })) {
|
||||
Ok(c) => c,
|
||||
Err(_) => {
|
||||
debug_assert!(
|
||||
false,
|
||||
"Unable to create a bounded call from `nudge_referendum`??",
|
||||
);
|
||||
return false
|
||||
},
|
||||
};
|
||||
status.alarm = Self::set_alarm(call, alarm);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -987,14 +1005,8 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
// Passed!
|
||||
Self::ensure_no_alarm(&mut status);
|
||||
Self::note_one_fewer_deciding(status.track);
|
||||
let (desired, call_hash) = (status.enactment, status.proposal_hash);
|
||||
Self::schedule_enactment(
|
||||
index,
|
||||
track,
|
||||
desired,
|
||||
status.origin,
|
||||
call_hash,
|
||||
);
|
||||
let (desired, call) = (status.enactment, status.proposal);
|
||||
Self::schedule_enactment(index, track, desired, status.origin, call);
|
||||
Self::deposit_event(Event::<T, I>::Confirmed {
|
||||
index,
|
||||
tally: status.tally,
|
||||
|
||||
@@ -24,7 +24,7 @@ use frame_support::{
|
||||
assert_ok, ord_parameter_types, parameter_types,
|
||||
traits::{
|
||||
ConstU32, ConstU64, Contains, EqualPrivilegeOnly, OnInitialize, OriginTrait, Polling,
|
||||
PreimageRecipient, SortedMembers,
|
||||
SortedMembers,
|
||||
},
|
||||
weights::Weight,
|
||||
};
|
||||
@@ -32,7 +32,7 @@ use frame_system::{EnsureRoot, EnsureSignedBy};
|
||||
use sp_core::H256;
|
||||
use sp_runtime::{
|
||||
testing::Header,
|
||||
traits::{BlakeTwo256, Hash, IdentityLookup},
|
||||
traits::{BlakeTwo256, IdentityLookup},
|
||||
DispatchResult, Perbill,
|
||||
};
|
||||
|
||||
@@ -97,7 +97,6 @@ impl pallet_preimage::Config for Test {
|
||||
type WeightInfo = ();
|
||||
type Currency = Balances;
|
||||
type ManagerOrigin = EnsureRoot<u64>;
|
||||
type MaxSize = ConstU32<4096>;
|
||||
type BaseDeposit = ();
|
||||
type ByteDeposit = ();
|
||||
}
|
||||
@@ -111,8 +110,7 @@ impl pallet_scheduler::Config for Test {
|
||||
type MaxScheduledPerBlock = ConstU32<100>;
|
||||
type WeightInfo = ();
|
||||
type OriginPrivilegeCmp = EqualPrivilegeOnly;
|
||||
type PreimageProvider = Preimage;
|
||||
type NoPreimagePostponement = ConstU64<10>;
|
||||
type Preimages = Preimage;
|
||||
}
|
||||
impl pallet_balances::Config for Test {
|
||||
type MaxReserves = ();
|
||||
@@ -229,6 +227,7 @@ impl Config for Test {
|
||||
type UndecidingTimeout = ConstU64<20>;
|
||||
type AlarmInterval = AlarmInterval;
|
||||
type Tracks = TestTracksInfo;
|
||||
type Preimages = Preimage;
|
||||
}
|
||||
|
||||
pub fn new_test_ext() -> sp_io::TestExternalities {
|
||||
@@ -306,14 +305,13 @@ pub fn set_balance_proposal(value: u64) -> Vec<u8> {
|
||||
.encode()
|
||||
}
|
||||
|
||||
pub fn set_balance_proposal_hash(value: u64) -> H256 {
|
||||
pub fn set_balance_proposal_bounded(value: u64) -> BoundedCallOf<Test, ()> {
|
||||
let c = RuntimeCall::Balances(pallet_balances::Call::set_balance {
|
||||
who: 42,
|
||||
new_free: value,
|
||||
new_reserved: 0,
|
||||
});
|
||||
<Preimage as PreimageRecipient<_>>::note_preimage(c.encode().try_into().unwrap());
|
||||
BlakeTwo256::hash_of(&c)
|
||||
<Preimage as StorePreimage>::bound(c).unwrap()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -321,7 +319,7 @@ pub fn propose_set_balance(who: u64, value: u64, delay: u64) -> DispatchResult {
|
||||
Referenda::submit(
|
||||
RuntimeOrigin::signed(who),
|
||||
Box::new(frame_system::RawOrigin::Root.into()),
|
||||
set_balance_proposal_hash(value),
|
||||
set_balance_proposal_bounded(value),
|
||||
DispatchTime::After(delay),
|
||||
)
|
||||
}
|
||||
@@ -449,7 +447,7 @@ impl RefState {
|
||||
assert_ok!(Referenda::submit(
|
||||
RuntimeOrigin::signed(1),
|
||||
Box::new(frame_support::dispatch::RawOrigin::Root.into()),
|
||||
set_balance_proposal_hash(1),
|
||||
set_balance_proposal_bounded(1),
|
||||
DispatchTime::At(10),
|
||||
));
|
||||
assert_ok!(Referenda::place_decision_deposit(RuntimeOrigin::signed(2), 0));
|
||||
|
||||
@@ -44,7 +44,7 @@ fn basic_happy_path_works() {
|
||||
assert_ok!(Referenda::submit(
|
||||
RuntimeOrigin::signed(1),
|
||||
Box::new(RawOrigin::Root.into()),
|
||||
set_balance_proposal_hash(1),
|
||||
set_balance_proposal_bounded(1),
|
||||
DispatchTime::At(10),
|
||||
));
|
||||
assert_eq!(Balances::reserved_balance(&1), 2);
|
||||
@@ -175,7 +175,7 @@ fn queueing_works() {
|
||||
assert_ok!(Referenda::submit(
|
||||
RuntimeOrigin::signed(5),
|
||||
Box::new(RawOrigin::Root.into()),
|
||||
set_balance_proposal_hash(0),
|
||||
set_balance_proposal_bounded(0),
|
||||
DispatchTime::After(0),
|
||||
));
|
||||
assert_ok!(Referenda::place_decision_deposit(RuntimeOrigin::signed(5), 0));
|
||||
@@ -187,7 +187,7 @@ fn queueing_works() {
|
||||
assert_ok!(Referenda::submit(
|
||||
RuntimeOrigin::signed(i),
|
||||
Box::new(RawOrigin::Root.into()),
|
||||
set_balance_proposal_hash(i),
|
||||
set_balance_proposal_bounded(i),
|
||||
DispatchTime::After(0),
|
||||
));
|
||||
assert_ok!(Referenda::place_decision_deposit(RuntimeOrigin::signed(i), i as u32));
|
||||
@@ -272,7 +272,7 @@ fn auto_timeout_should_happen_with_nothing_but_submit() {
|
||||
assert_ok!(Referenda::submit(
|
||||
RuntimeOrigin::signed(1),
|
||||
Box::new(RawOrigin::Root.into()),
|
||||
set_balance_proposal_hash(1),
|
||||
set_balance_proposal_bounded(1),
|
||||
DispatchTime::At(20),
|
||||
));
|
||||
run_to(20);
|
||||
@@ -292,13 +292,13 @@ fn tracks_are_distinguished() {
|
||||
assert_ok!(Referenda::submit(
|
||||
RuntimeOrigin::signed(1),
|
||||
Box::new(RawOrigin::Root.into()),
|
||||
set_balance_proposal_hash(1),
|
||||
set_balance_proposal_bounded(1),
|
||||
DispatchTime::At(10),
|
||||
));
|
||||
assert_ok!(Referenda::submit(
|
||||
RuntimeOrigin::signed(2),
|
||||
Box::new(RawOrigin::None.into()),
|
||||
set_balance_proposal_hash(2),
|
||||
set_balance_proposal_bounded(2),
|
||||
DispatchTime::At(20),
|
||||
));
|
||||
|
||||
@@ -315,7 +315,7 @@ fn tracks_are_distinguished() {
|
||||
ReferendumInfo::Ongoing(ReferendumStatus {
|
||||
track: 0,
|
||||
origin: OriginCaller::system(RawOrigin::Root),
|
||||
proposal_hash: set_balance_proposal_hash(1),
|
||||
proposal: set_balance_proposal_bounded(1),
|
||||
enactment: DispatchTime::At(10),
|
||||
submitted: 1,
|
||||
submission_deposit: Deposit { who: 1, amount: 2 },
|
||||
@@ -331,7 +331,7 @@ fn tracks_are_distinguished() {
|
||||
ReferendumInfo::Ongoing(ReferendumStatus {
|
||||
track: 1,
|
||||
origin: OriginCaller::system(RawOrigin::None),
|
||||
proposal_hash: set_balance_proposal_hash(2),
|
||||
proposal: set_balance_proposal_bounded(2),
|
||||
enactment: DispatchTime::At(20),
|
||||
submitted: 1,
|
||||
submission_deposit: Deposit { who: 2, amount: 2 },
|
||||
@@ -350,13 +350,13 @@ fn tracks_are_distinguished() {
|
||||
#[test]
|
||||
fn submit_errors_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let h = set_balance_proposal_hash(1);
|
||||
let h = set_balance_proposal_bounded(1);
|
||||
// No track for Signed origins.
|
||||
assert_noop!(
|
||||
Referenda::submit(
|
||||
RuntimeOrigin::signed(1),
|
||||
Box::new(RawOrigin::Signed(2).into()),
|
||||
h,
|
||||
h.clone(),
|
||||
DispatchTime::At(10),
|
||||
),
|
||||
Error::<Test>::NoTrack
|
||||
@@ -381,7 +381,7 @@ fn decision_deposit_errors_work() {
|
||||
let e = Error::<Test>::NotOngoing;
|
||||
assert_noop!(Referenda::place_decision_deposit(RuntimeOrigin::signed(2), 0), e);
|
||||
|
||||
let h = set_balance_proposal_hash(1);
|
||||
let h = set_balance_proposal_bounded(1);
|
||||
assert_ok!(Referenda::submit(
|
||||
RuntimeOrigin::signed(1),
|
||||
Box::new(RawOrigin::Root.into()),
|
||||
@@ -403,7 +403,7 @@ fn refund_deposit_works() {
|
||||
let e = Error::<Test>::BadReferendum;
|
||||
assert_noop!(Referenda::refund_decision_deposit(RuntimeOrigin::signed(1), 0), e);
|
||||
|
||||
let h = set_balance_proposal_hash(1);
|
||||
let h = set_balance_proposal_bounded(1);
|
||||
assert_ok!(Referenda::submit(
|
||||
RuntimeOrigin::signed(1),
|
||||
Box::new(RawOrigin::Root.into()),
|
||||
@@ -425,7 +425,7 @@ fn refund_deposit_works() {
|
||||
#[test]
|
||||
fn cancel_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let h = set_balance_proposal_hash(1);
|
||||
let h = set_balance_proposal_bounded(1);
|
||||
assert_ok!(Referenda::submit(
|
||||
RuntimeOrigin::signed(1),
|
||||
Box::new(RawOrigin::Root.into()),
|
||||
@@ -444,7 +444,7 @@ fn cancel_works() {
|
||||
#[test]
|
||||
fn cancel_errors_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let h = set_balance_proposal_hash(1);
|
||||
let h = set_balance_proposal_bounded(1);
|
||||
assert_ok!(Referenda::submit(
|
||||
RuntimeOrigin::signed(1),
|
||||
Box::new(RawOrigin::Root.into()),
|
||||
@@ -462,7 +462,7 @@ fn cancel_errors_works() {
|
||||
#[test]
|
||||
fn kill_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let h = set_balance_proposal_hash(1);
|
||||
let h = set_balance_proposal_bounded(1);
|
||||
assert_ok!(Referenda::submit(
|
||||
RuntimeOrigin::signed(1),
|
||||
Box::new(RawOrigin::Root.into()),
|
||||
@@ -482,7 +482,7 @@ fn kill_works() {
|
||||
#[test]
|
||||
fn kill_errors_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let h = set_balance_proposal_hash(1);
|
||||
let h = set_balance_proposal_bounded(1);
|
||||
assert_ok!(Referenda::submit(
|
||||
RuntimeOrigin::signed(1),
|
||||
Box::new(RawOrigin::Root.into()),
|
||||
|
||||
@@ -19,7 +19,10 @@
|
||||
|
||||
use super::*;
|
||||
use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
|
||||
use frame_support::{traits::schedule::Anon, Parameter};
|
||||
use frame_support::{
|
||||
traits::{schedule::v3::Anon, Bounded},
|
||||
Parameter,
|
||||
};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_arithmetic::{Rounding::*, SignedRounding::*};
|
||||
use sp_runtime::{FixedI64, PerThing, RuntimeDebug};
|
||||
@@ -31,6 +34,7 @@ pub type NegativeImbalanceOf<T, I> = <<T as Config<I>>::Currency as Currency<
|
||||
<T as frame_system::Config>::AccountId,
|
||||
>>::NegativeImbalance;
|
||||
pub type CallOf<T, I> = <T as Config<I>>::RuntimeCall;
|
||||
pub type BoundedCallOf<T, I> = Bounded<<T as Config<I>>::RuntimeCall>;
|
||||
pub type VotesOf<T, I> = <T as Config<I>>::Votes;
|
||||
pub type TallyOf<T, I> = <T as Config<I>>::Tally;
|
||||
pub type PalletsOriginOf<T> =
|
||||
@@ -39,7 +43,7 @@ pub type ReferendumInfoOf<T, I> = ReferendumInfo<
|
||||
TrackIdOf<T, I>,
|
||||
PalletsOriginOf<T>,
|
||||
<T as frame_system::Config>::BlockNumber,
|
||||
<T as frame_system::Config>::Hash,
|
||||
BoundedCallOf<T, I>,
|
||||
BalanceOf<T, I>,
|
||||
TallyOf<T, I>,
|
||||
<T as frame_system::Config>::AccountId,
|
||||
@@ -49,7 +53,7 @@ pub type ReferendumStatusOf<T, I> = ReferendumStatus<
|
||||
TrackIdOf<T, I>,
|
||||
PalletsOriginOf<T>,
|
||||
<T as frame_system::Config>::BlockNumber,
|
||||
<T as frame_system::Config>::Hash,
|
||||
BoundedCallOf<T, I>,
|
||||
BalanceOf<T, I>,
|
||||
TallyOf<T, I>,
|
||||
<T as frame_system::Config>::AccountId,
|
||||
@@ -160,7 +164,7 @@ pub struct ReferendumStatus<
|
||||
TrackId: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
RuntimeOrigin: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
Moment: Parameter + Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone + EncodeLike,
|
||||
Hash: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
Call: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
Balance: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
Tally: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
AccountId: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
@@ -171,7 +175,7 @@ pub struct ReferendumStatus<
|
||||
/// The origin for this referendum.
|
||||
pub(crate) origin: RuntimeOrigin,
|
||||
/// The hash of the proposal up for referendum.
|
||||
pub(crate) proposal_hash: Hash,
|
||||
pub(crate) proposal: Call,
|
||||
/// The time the proposal should be scheduled for enactment.
|
||||
pub(crate) enactment: DispatchTime<Moment>,
|
||||
/// The time of submission. Once `UndecidingTimeout` passes, it may be closed by anyone if it
|
||||
@@ -197,7 +201,7 @@ pub enum ReferendumInfo<
|
||||
TrackId: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
RuntimeOrigin: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
Moment: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone + EncodeLike,
|
||||
Hash: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
Call: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
Balance: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
Tally: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
AccountId: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
@@ -209,7 +213,7 @@ pub enum ReferendumInfo<
|
||||
TrackId,
|
||||
RuntimeOrigin,
|
||||
Moment,
|
||||
Hash,
|
||||
Call,
|
||||
Balance,
|
||||
Tally,
|
||||
AccountId,
|
||||
@@ -232,12 +236,12 @@ impl<
|
||||
TrackId: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
RuntimeOrigin: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
Moment: Parameter + Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone + EncodeLike,
|
||||
Hash: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
Call: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
Balance: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
Tally: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
AccountId: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
ScheduleAddress: Eq + PartialEq + Debug + Encode + Decode + TypeInfo + Clone,
|
||||
> ReferendumInfo<TrackId, RuntimeOrigin, Moment, Hash, Balance, Tally, AccountId, ScheduleAddress>
|
||||
> ReferendumInfo<TrackId, RuntimeOrigin, Moment, Call, Balance, Tally, AccountId, ScheduleAddress>
|
||||
{
|
||||
/// Take the Decision Deposit from `self`, if there is one. Returns an `Err` if `self` is not
|
||||
/// in a valid state for the Decision Deposit to be refunded.
|
||||
|
||||
@@ -18,201 +18,219 @@
|
||||
//! Scheduler pallet benchmarking.
|
||||
|
||||
use super::*;
|
||||
use frame_benchmarking::benchmarks;
|
||||
use frame_benchmarking::{account, benchmarks};
|
||||
use frame_support::{
|
||||
ensure,
|
||||
traits::{OnInitialize, PreimageProvider, PreimageRecipient},
|
||||
traits::{schedule::Priority, BoundedInline},
|
||||
};
|
||||
use sp_runtime::traits::Hash;
|
||||
use frame_system::RawOrigin;
|
||||
use sp_std::{prelude::*, vec};
|
||||
|
||||
use crate::Pallet as Scheduler;
|
||||
use frame_system::Pallet as System;
|
||||
use frame_system::Call as SystemCall;
|
||||
|
||||
const SEED: u32 = 0;
|
||||
|
||||
const BLOCK_NUMBER: u32 = 2;
|
||||
|
||||
type SystemOrigin<T> = <T as frame_system::Config>::RuntimeOrigin;
|
||||
|
||||
/// Add `n` named items to the schedule.
|
||||
/// Add `n` items to the schedule.
|
||||
///
|
||||
/// For `resolved`:
|
||||
/// - `
|
||||
/// - `None`: aborted (hash without preimage)
|
||||
/// - `Some(true)`: hash resolves into call if possible, plain call otherwise
|
||||
/// - `Some(false)`: plain call
|
||||
fn fill_schedule<T: Config>(
|
||||
when: T::BlockNumber,
|
||||
n: u32,
|
||||
periodic: bool,
|
||||
named: bool,
|
||||
resolved: Option<bool>,
|
||||
) -> Result<(), &'static str> {
|
||||
fn fill_schedule<T: Config>(when: T::BlockNumber, n: u32) -> Result<(), &'static str> {
|
||||
let t = DispatchTime::At(when);
|
||||
let origin: <T as Config>::PalletsOrigin = frame_system::RawOrigin::Root.into();
|
||||
for i in 0..n {
|
||||
// Named schedule is strictly heavier than anonymous
|
||||
let (call, hash) = call_and_hash::<T>(i);
|
||||
let call_or_hash = match resolved {
|
||||
Some(true) => {
|
||||
T::PreimageProvider::note_preimage(call.encode().try_into().unwrap());
|
||||
if T::PreimageProvider::have_preimage(&hash) {
|
||||
CallOrHashOf::<T>::Hash(hash)
|
||||
} else {
|
||||
call.into()
|
||||
}
|
||||
},
|
||||
Some(false) => call.into(),
|
||||
None => CallOrHashOf::<T>::Hash(hash),
|
||||
};
|
||||
let period = match periodic {
|
||||
true => Some(((i + 100).into(), 100)),
|
||||
false => None,
|
||||
};
|
||||
let t = DispatchTime::At(when);
|
||||
let origin = frame_system::RawOrigin::Root.into();
|
||||
if named {
|
||||
Scheduler::<T>::do_schedule_named(i.encode(), t, period, 0, origin, call_or_hash)?;
|
||||
} else {
|
||||
Scheduler::<T>::do_schedule(t, period, 0, origin, call_or_hash)?;
|
||||
}
|
||||
let call = make_call::<T>(None);
|
||||
let period = Some(((i + 100).into(), 100));
|
||||
let name = u32_to_name(i);
|
||||
Scheduler::<T>::do_schedule_named(name, t, period, 0, origin.clone(), call)?;
|
||||
}
|
||||
ensure!(Agenda::<T>::get(when).len() == n as usize, "didn't fill schedule");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn call_and_hash<T: Config>(i: u32) -> (<T as Config>::RuntimeCall, T::Hash) {
|
||||
// Essentially a no-op call.
|
||||
let call: <T as Config>::RuntimeCall = frame_system::Call::remark { remark: i.encode() }.into();
|
||||
let hash = T::Hashing::hash_of(&call);
|
||||
(call, hash)
|
||||
fn u32_to_name(i: u32) -> TaskName {
|
||||
i.using_encoded(blake2_256)
|
||||
}
|
||||
|
||||
fn make_task<T: Config>(
|
||||
periodic: bool,
|
||||
named: bool,
|
||||
signed: bool,
|
||||
maybe_lookup_len: Option<u32>,
|
||||
priority: Priority,
|
||||
) -> ScheduledOf<T> {
|
||||
let call = make_call::<T>(maybe_lookup_len);
|
||||
let maybe_periodic = match periodic {
|
||||
true => Some((100u32.into(), 100)),
|
||||
false => None,
|
||||
};
|
||||
let maybe_id = match named {
|
||||
true => Some(u32_to_name(0)),
|
||||
false => None,
|
||||
};
|
||||
let origin = make_origin::<T>(signed);
|
||||
Scheduled { maybe_id, priority, call, maybe_periodic, origin, _phantom: PhantomData }
|
||||
}
|
||||
|
||||
fn bounded<T: Config>(len: u32) -> Option<Bounded<<T as Config>::RuntimeCall>> {
|
||||
let call =
|
||||
<<T as Config>::RuntimeCall>::from(SystemCall::remark { remark: vec![0; len as usize] });
|
||||
T::Preimages::bound(call).ok()
|
||||
}
|
||||
|
||||
fn make_call<T: Config>(maybe_lookup_len: Option<u32>) -> Bounded<<T as Config>::RuntimeCall> {
|
||||
let bound = BoundedInline::bound() as u32;
|
||||
let mut len = match maybe_lookup_len {
|
||||
Some(len) => len.min(T::Preimages::MAX_LENGTH as u32 - 2).max(bound) - 3,
|
||||
None => bound.saturating_sub(4),
|
||||
};
|
||||
|
||||
loop {
|
||||
let c = match bounded::<T>(len) {
|
||||
Some(x) => x,
|
||||
None => {
|
||||
len -= 1;
|
||||
continue
|
||||
},
|
||||
};
|
||||
if c.lookup_needed() == maybe_lookup_len.is_some() {
|
||||
break c
|
||||
}
|
||||
if maybe_lookup_len.is_some() {
|
||||
len += 1;
|
||||
} else {
|
||||
if len > 0 {
|
||||
len -= 1;
|
||||
} else {
|
||||
break c
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_origin<T: Config>(signed: bool) -> <T as Config>::PalletsOrigin {
|
||||
match signed {
|
||||
true => frame_system::RawOrigin::Signed(account("origin", 0, SEED)).into(),
|
||||
false => frame_system::RawOrigin::Root.into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn dummy_counter() -> WeightCounter {
|
||||
WeightCounter { used: Weight::zero(), limit: Weight::MAX }
|
||||
}
|
||||
|
||||
benchmarks! {
|
||||
on_initialize_periodic_named_resolved {
|
||||
let s in 1 .. T::MaxScheduledPerBlock::get();
|
||||
let when = BLOCK_NUMBER.into();
|
||||
fill_schedule::<T>(when, s, true, true, Some(true))?;
|
||||
}: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }
|
||||
verify {
|
||||
assert_eq!(System::<T>::event_count(), s * 2);
|
||||
for i in 0..s {
|
||||
assert_eq!(Agenda::<T>::get(when + (i + 100).into()).len(), 1 as usize);
|
||||
}
|
||||
// `service_agendas` when no work is done.
|
||||
service_agendas_base {
|
||||
let now = T::BlockNumber::from(BLOCK_NUMBER);
|
||||
IncompleteSince::<T>::put(now - One::one());
|
||||
}: {
|
||||
Scheduler::<T>::service_agendas(&mut dummy_counter(), now, 0);
|
||||
} verify {
|
||||
assert_eq!(IncompleteSince::<T>::get(), Some(now - One::one()));
|
||||
}
|
||||
|
||||
on_initialize_named_resolved {
|
||||
let s in 1 .. T::MaxScheduledPerBlock::get();
|
||||
let when = BLOCK_NUMBER.into();
|
||||
fill_schedule::<T>(when, s, false, true, Some(true))?;
|
||||
}: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }
|
||||
verify {
|
||||
assert_eq!(System::<T>::event_count(), s * 2);
|
||||
assert!(Agenda::<T>::iter().count() == 0);
|
||||
// `service_agenda` when no work is done.
|
||||
service_agenda_base {
|
||||
let now = BLOCK_NUMBER.into();
|
||||
let s in 0 .. T::MaxScheduledPerBlock::get();
|
||||
fill_schedule::<T>(now, s)?;
|
||||
let mut executed = 0;
|
||||
}: {
|
||||
Scheduler::<T>::service_agenda(&mut dummy_counter(), &mut executed, now, now, 0);
|
||||
} verify {
|
||||
assert_eq!(executed, 0);
|
||||
}
|
||||
|
||||
on_initialize_periodic_resolved {
|
||||
let s in 1 .. T::MaxScheduledPerBlock::get();
|
||||
let when = BLOCK_NUMBER.into();
|
||||
fill_schedule::<T>(when, s, true, false, Some(true))?;
|
||||
}: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }
|
||||
verify {
|
||||
assert_eq!(System::<T>::event_count(), s * 2);
|
||||
for i in 0..s {
|
||||
assert_eq!(Agenda::<T>::get(when + (i + 100).into()).len(), 1 as usize);
|
||||
}
|
||||
// `service_task` when the task is a non-periodic, non-named, non-fetched call which is not
|
||||
// dispatched (e.g. due to being overweight).
|
||||
service_task_base {
|
||||
let now = BLOCK_NUMBER.into();
|
||||
let task = make_task::<T>(false, false, false, None, 0);
|
||||
// prevent any tasks from actually being executed as we only want the surrounding weight.
|
||||
let mut counter = WeightCounter { used: Weight::zero(), limit: Weight::zero() };
|
||||
}: {
|
||||
let result = Scheduler::<T>::service_task(&mut counter, now, now, 0, true, task);
|
||||
} verify {
|
||||
//assert_eq!(result, Ok(()));
|
||||
}
|
||||
|
||||
on_initialize_resolved {
|
||||
let s in 1 .. T::MaxScheduledPerBlock::get();
|
||||
let when = BLOCK_NUMBER.into();
|
||||
fill_schedule::<T>(when, s, false, false, Some(true))?;
|
||||
}: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }
|
||||
verify {
|
||||
assert_eq!(System::<T>::event_count(), s * 2);
|
||||
assert!(Agenda::<T>::iter().count() == 0);
|
||||
// `service_task` when the task is a non-periodic, non-named, fetched call (with a known
|
||||
// preimage length) and which is not dispatched (e.g. due to being overweight).
|
||||
service_task_fetched {
|
||||
let s in (BoundedInline::bound() as u32) .. (T::Preimages::MAX_LENGTH as u32);
|
||||
let now = BLOCK_NUMBER.into();
|
||||
let task = make_task::<T>(false, false, false, Some(s), 0);
|
||||
// prevent any tasks from actually being executed as we only want the surrounding weight.
|
||||
let mut counter = WeightCounter { used: Weight::zero(), limit: Weight::zero() };
|
||||
}: {
|
||||
let result = Scheduler::<T>::service_task(&mut counter, now, now, 0, true, task);
|
||||
} verify {
|
||||
}
|
||||
|
||||
on_initialize_named_aborted {
|
||||
let s in 1 .. T::MaxScheduledPerBlock::get();
|
||||
let when = BLOCK_NUMBER.into();
|
||||
fill_schedule::<T>(when, s, false, true, None)?;
|
||||
}: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }
|
||||
verify {
|
||||
assert_eq!(System::<T>::event_count(), 0);
|
||||
if let Some(delay) = T::NoPreimagePostponement::get() {
|
||||
assert_eq!(Agenda::<T>::get(when + delay).len(), s as usize);
|
||||
} else {
|
||||
assert!(Agenda::<T>::iter().count() == 0);
|
||||
}
|
||||
// `service_task` when the task is a non-periodic, named, non-fetched call which is not
|
||||
// dispatched (e.g. due to being overweight).
|
||||
service_task_named {
|
||||
let now = BLOCK_NUMBER.into();
|
||||
let task = make_task::<T>(false, true, false, None, 0);
|
||||
// prevent any tasks from actually being executed as we only want the surrounding weight.
|
||||
let mut counter = WeightCounter { used: Weight::zero(), limit: Weight::zero() };
|
||||
}: {
|
||||
let result = Scheduler::<T>::service_task(&mut counter, now, now, 0, true, task);
|
||||
} verify {
|
||||
}
|
||||
|
||||
on_initialize_aborted {
|
||||
let s in 1 .. T::MaxScheduledPerBlock::get();
|
||||
let when = BLOCK_NUMBER.into();
|
||||
fill_schedule::<T>(when, s, false, false, None)?;
|
||||
}: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }
|
||||
verify {
|
||||
assert_eq!(System::<T>::event_count(), 0);
|
||||
if let Some(delay) = T::NoPreimagePostponement::get() {
|
||||
assert_eq!(Agenda::<T>::get(when + delay).len(), s as usize);
|
||||
} else {
|
||||
assert!(Agenda::<T>::iter().count() == 0);
|
||||
}
|
||||
// `service_task` when the task is a periodic, non-named, non-fetched call which is not
|
||||
// dispatched (e.g. due to being overweight).
|
||||
service_task_periodic {
|
||||
let now = BLOCK_NUMBER.into();
|
||||
let task = make_task::<T>(true, false, false, None, 0);
|
||||
// prevent any tasks from actually being executed as we only want the surrounding weight.
|
||||
let mut counter = WeightCounter { used: Weight::zero(), limit: Weight::zero() };
|
||||
}: {
|
||||
let result = Scheduler::<T>::service_task(&mut counter, now, now, 0, true, task);
|
||||
} verify {
|
||||
}
|
||||
|
||||
on_initialize_periodic_named {
|
||||
let s in 1 .. T::MaxScheduledPerBlock::get();
|
||||
let when = BLOCK_NUMBER.into();
|
||||
fill_schedule::<T>(when, s, true, true, Some(false))?;
|
||||
}: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }
|
||||
// `execute_dispatch` when the origin is `Signed`, not counting the dispatable's weight.
|
||||
execute_dispatch_signed {
|
||||
let mut counter = WeightCounter { used: Weight::zero(), limit: Weight::MAX };
|
||||
let origin = make_origin::<T>(true);
|
||||
let call = T::Preimages::realize(&make_call::<T>(None)).unwrap().0;
|
||||
}: {
|
||||
assert!(Scheduler::<T>::execute_dispatch(&mut counter, origin, call).is_ok());
|
||||
}
|
||||
verify {
|
||||
assert_eq!(System::<T>::event_count(), s);
|
||||
for i in 0..s {
|
||||
assert_eq!(Agenda::<T>::get(when + (i + 100).into()).len(), 1 as usize);
|
||||
}
|
||||
}
|
||||
|
||||
on_initialize_periodic {
|
||||
let s in 1 .. T::MaxScheduledPerBlock::get();
|
||||
let when = BLOCK_NUMBER.into();
|
||||
fill_schedule::<T>(when, s, true, false, Some(false))?;
|
||||
}: { Scheduler::<T>::on_initialize(when); }
|
||||
verify {
|
||||
assert_eq!(System::<T>::event_count(), s);
|
||||
for i in 0..s {
|
||||
assert_eq!(Agenda::<T>::get(when + (i + 100).into()).len(), 1 as usize);
|
||||
}
|
||||
// `execute_dispatch` when the origin is not `Signed`, not counting the dispatable's weight.
|
||||
execute_dispatch_unsigned {
|
||||
let mut counter = WeightCounter { used: Weight::zero(), limit: Weight::MAX };
|
||||
let origin = make_origin::<T>(false);
|
||||
let call = T::Preimages::realize(&make_call::<T>(None)).unwrap().0;
|
||||
}: {
|
||||
assert!(Scheduler::<T>::execute_dispatch(&mut counter, origin, call).is_ok());
|
||||
}
|
||||
|
||||
on_initialize_named {
|
||||
let s in 1 .. T::MaxScheduledPerBlock::get();
|
||||
let when = BLOCK_NUMBER.into();
|
||||
fill_schedule::<T>(when, s, false, true, Some(false))?;
|
||||
}: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }
|
||||
verify {
|
||||
assert_eq!(System::<T>::event_count(), s);
|
||||
assert!(Agenda::<T>::iter().count() == 0);
|
||||
}
|
||||
|
||||
on_initialize {
|
||||
let s in 1 .. T::MaxScheduledPerBlock::get();
|
||||
let when = BLOCK_NUMBER.into();
|
||||
fill_schedule::<T>(when, s, false, false, Some(false))?;
|
||||
}: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }
|
||||
verify {
|
||||
assert_eq!(System::<T>::event_count(), s);
|
||||
assert!(Agenda::<T>::iter().count() == 0);
|
||||
}
|
||||
|
||||
schedule {
|
||||
let s in 0 .. T::MaxScheduledPerBlock::get();
|
||||
let s in 0 .. (T::MaxScheduledPerBlock::get() - 1);
|
||||
let when = BLOCK_NUMBER.into();
|
||||
let periodic = Some((T::BlockNumber::one(), 100));
|
||||
let priority = 0;
|
||||
// Essentially a no-op call.
|
||||
let inner_call = frame_system::Call::set_storage { items: vec![] }.into();
|
||||
let call = Box::new(CallOrHashOf::<T>::Value(inner_call));
|
||||
let call = Box::new(SystemCall::set_storage { items: vec![] }.into());
|
||||
|
||||
fill_schedule::<T>(when, s, true, true, Some(false))?;
|
||||
let schedule_origin = T::ScheduleOrigin::successful_origin();
|
||||
}: _<SystemOrigin<T>>(schedule_origin, when, periodic, priority, call)
|
||||
fill_schedule::<T>(when, s)?;
|
||||
}: _(RawOrigin::Root, when, periodic, priority, call)
|
||||
verify {
|
||||
ensure!(
|
||||
Agenda::<T>::get(when).len() == (s + 1) as usize,
|
||||
@@ -224,13 +242,13 @@ benchmarks! {
|
||||
let s in 1 .. T::MaxScheduledPerBlock::get();
|
||||
let when = BLOCK_NUMBER.into();
|
||||
|
||||
fill_schedule::<T>(when, s, true, true, Some(false))?;
|
||||
fill_schedule::<T>(when, s)?;
|
||||
assert_eq!(Agenda::<T>::get(when).len(), s as usize);
|
||||
let schedule_origin = T::ScheduleOrigin::successful_origin();
|
||||
}: _<SystemOrigin<T>>(schedule_origin, when, 0)
|
||||
verify {
|
||||
ensure!(
|
||||
Lookup::<T>::get(0.encode()).is_none(),
|
||||
Lookup::<T>::get(u32_to_name(0)).is_none(),
|
||||
"didn't remove from lookup"
|
||||
);
|
||||
// Removed schedule is NONE
|
||||
@@ -241,18 +259,16 @@ benchmarks! {
|
||||
}
|
||||
|
||||
schedule_named {
|
||||
let s in 0 .. T::MaxScheduledPerBlock::get();
|
||||
let id = s.encode();
|
||||
let s in 0 .. (T::MaxScheduledPerBlock::get() - 1);
|
||||
let id = u32_to_name(s);
|
||||
let when = BLOCK_NUMBER.into();
|
||||
let periodic = Some((T::BlockNumber::one(), 100));
|
||||
let priority = 0;
|
||||
// Essentially a no-op call.
|
||||
let inner_call = frame_system::Call::set_storage { items: vec![] }.into();
|
||||
let call = Box::new(CallOrHashOf::<T>::Value(inner_call));
|
||||
let call = Box::new(SystemCall::set_storage { items: vec![] }.into());
|
||||
|
||||
fill_schedule::<T>(when, s, true, true, Some(false))?;
|
||||
let schedule_origin = T::ScheduleOrigin::successful_origin();
|
||||
}: _<SystemOrigin<T>>(schedule_origin, id, when, periodic, priority, call)
|
||||
fill_schedule::<T>(when, s)?;
|
||||
}: _(RawOrigin::Root, id, when, periodic, priority, call)
|
||||
verify {
|
||||
ensure!(
|
||||
Agenda::<T>::get(when).len() == (s + 1) as usize,
|
||||
@@ -264,12 +280,11 @@ benchmarks! {
|
||||
let s in 1 .. T::MaxScheduledPerBlock::get();
|
||||
let when = BLOCK_NUMBER.into();
|
||||
|
||||
fill_schedule::<T>(when, s, true, true, Some(false))?;
|
||||
let schedule_origin = T::ScheduleOrigin::successful_origin();
|
||||
}: _<SystemOrigin<T>>(schedule_origin, 0.encode())
|
||||
fill_schedule::<T>(when, s)?;
|
||||
}: _(RawOrigin::Root, u32_to_name(0))
|
||||
verify {
|
||||
ensure!(
|
||||
Lookup::<T>::get(0.encode()).is_none(),
|
||||
Lookup::<T>::get(u32_to_name(0)).is_none(),
|
||||
"didn't remove from lookup"
|
||||
);
|
||||
// Removed schedule is NONE
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,402 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2017-2022 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.
|
||||
|
||||
//! Migrations for the scheduler pallet.
|
||||
|
||||
use super::*;
|
||||
use frame_support::traits::OnRuntimeUpgrade;
|
||||
|
||||
/// The log target.
|
||||
const TARGET: &'static str = "runtime::scheduler::migration";
|
||||
|
||||
pub mod v1 {
|
||||
use super::*;
|
||||
use frame_support::pallet_prelude::*;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type Agenda<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
Twox64Concat,
|
||||
<T as frame_system::Config>::BlockNumber,
|
||||
Vec<
|
||||
Option<
|
||||
ScheduledV1<<T as Config>::RuntimeCall, <T as frame_system::Config>::BlockNumber>,
|
||||
>,
|
||||
>,
|
||||
ValueQuery,
|
||||
>;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type Lookup<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
Twox64Concat,
|
||||
Vec<u8>,
|
||||
TaskAddress<<T as frame_system::Config>::BlockNumber>,
|
||||
>;
|
||||
}
|
||||
|
||||
pub mod v2 {
|
||||
use super::*;
|
||||
use frame_support::pallet_prelude::*;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type Agenda<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
Twox64Concat,
|
||||
<T as frame_system::Config>::BlockNumber,
|
||||
Vec<Option<ScheduledV2Of<T>>>,
|
||||
ValueQuery,
|
||||
>;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type Lookup<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
Twox64Concat,
|
||||
Vec<u8>,
|
||||
TaskAddress<<T as frame_system::Config>::BlockNumber>,
|
||||
>;
|
||||
}
|
||||
|
||||
pub mod v3 {
|
||||
use super::*;
|
||||
use frame_support::pallet_prelude::*;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type Agenda<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
Twox64Concat,
|
||||
<T as frame_system::Config>::BlockNumber,
|
||||
Vec<Option<ScheduledV3Of<T>>>,
|
||||
ValueQuery,
|
||||
>;
|
||||
|
||||
#[frame_support::storage_alias]
|
||||
pub(crate) type Lookup<T: Config> = StorageMap<
|
||||
Pallet<T>,
|
||||
Twox64Concat,
|
||||
Vec<u8>,
|
||||
TaskAddress<<T as frame_system::Config>::BlockNumber>,
|
||||
>;
|
||||
|
||||
/// Migrate the scheduler pallet from V3 to V4.
|
||||
pub struct MigrateToV4<T>(sp_std::marker::PhantomData<T>);
|
||||
|
||||
impl<T: Config<Hash = PreimageHash>> OnRuntimeUpgrade for MigrateToV4<T> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 3, "Can only upgrade from version 3");
|
||||
|
||||
let agendas = Agenda::<T>::iter_keys().count() as u32;
|
||||
let decodable_agendas = Agenda::<T>::iter_values().count() as u32;
|
||||
if agendas != decodable_agendas {
|
||||
// This is not necessarily an error, but can happen when there are Calls
|
||||
// in an Agenda that are not valid anymore with the new runtime.
|
||||
log::error!(
|
||||
target: TARGET,
|
||||
"Can only decode {} of {} agendas - others will be dropped",
|
||||
decodable_agendas,
|
||||
agendas
|
||||
);
|
||||
}
|
||||
log::info!(target: TARGET, "Trying to migrate {} agendas...", decodable_agendas);
|
||||
|
||||
// Check that no agenda overflows `MaxScheduledPerBlock`.
|
||||
let max_scheduled_per_block = T::MaxScheduledPerBlock::get() as usize;
|
||||
for (block_number, agenda) in Agenda::<T>::iter() {
|
||||
if agenda.iter().cloned().filter_map(|s| s).count() > max_scheduled_per_block {
|
||||
log::error!(
|
||||
target: TARGET,
|
||||
"Would truncate agenda of block {:?} from {} items to {} items.",
|
||||
block_number,
|
||||
agenda.len(),
|
||||
max_scheduled_per_block,
|
||||
);
|
||||
return Err("Agenda would overflow `MaxScheduledPerBlock`.")
|
||||
}
|
||||
}
|
||||
// Check that bounding the calls will not overflow `MAX_LENGTH`.
|
||||
let max_length = T::Preimages::MAX_LENGTH as usize;
|
||||
for (block_number, agenda) in Agenda::<T>::iter() {
|
||||
for schedule in agenda.iter().cloned().filter_map(|s| s) {
|
||||
match schedule.call {
|
||||
frame_support::traits::schedule::MaybeHashed::Value(call) => {
|
||||
let l = call.using_encoded(|c| c.len());
|
||||
if l > max_length {
|
||||
log::error!(
|
||||
target: TARGET,
|
||||
"Call in agenda of block {:?} is too large: {} byte",
|
||||
block_number,
|
||||
l,
|
||||
);
|
||||
return Err("Call is too large.")
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok((decodable_agendas as u32).encode())
|
||||
}
|
||||
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let version = StorageVersion::get::<Pallet<T>>();
|
||||
if version != 3 {
|
||||
log::warn!(
|
||||
target: TARGET,
|
||||
"skipping v3 to v4 migration: executed on wrong storage version.\
|
||||
Expected version 3, found {:?}",
|
||||
version,
|
||||
);
|
||||
return T::DbWeight::get().reads(1)
|
||||
}
|
||||
|
||||
crate::Pallet::<T>::migrate_v3_to_v4()
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {
|
||||
assert_eq!(StorageVersion::get::<Pallet<T>>(), 4, "Must upgrade");
|
||||
|
||||
// Check that everything decoded fine.
|
||||
for k in crate::Agenda::<T>::iter_keys() {
|
||||
assert!(crate::Agenda::<T>::try_get(k).is_ok(), "Cannot decode V4 Agenda");
|
||||
}
|
||||
|
||||
let old_agendas: u32 =
|
||||
Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed");
|
||||
let new_agendas = crate::Agenda::<T>::iter_keys().count() as u32;
|
||||
if old_agendas != new_agendas {
|
||||
// This is not necessarily an error, but can happen when there are Calls
|
||||
// in an Agenda that are not valid anymore in the new runtime.
|
||||
log::error!(
|
||||
target: TARGET,
|
||||
"Did not migrate all Agendas. Previous {}, Now {}",
|
||||
old_agendas,
|
||||
new_agendas,
|
||||
);
|
||||
} else {
|
||||
log::info!(target: TARGET, "Migrated {} agendas.", new_agendas);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "try-runtime")]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::mock::*;
|
||||
use frame_support::Hashable;
|
||||
use sp_std::borrow::Cow;
|
||||
use substrate_test_utils::assert_eq_uvec;
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn migration_v3_to_v4_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Assume that we are at V3.
|
||||
StorageVersion::new(3).put::<Scheduler>();
|
||||
|
||||
// Call that will be bounded to a `Lookup`.
|
||||
let large_call =
|
||||
RuntimeCall::System(frame_system::Call::remark { remark: vec![0; 1024] });
|
||||
// Call that can be inlined.
|
||||
let small_call =
|
||||
RuntimeCall::System(frame_system::Call::remark { remark: vec![0; 10] });
|
||||
// Call that is already hashed and can will be converted to `Legacy`.
|
||||
let hashed_call =
|
||||
RuntimeCall::System(frame_system::Call::remark { remark: vec![0; 2048] });
|
||||
let bound_hashed_call = Preimage::bound(hashed_call.clone()).unwrap();
|
||||
assert!(bound_hashed_call.lookup_needed());
|
||||
// A Call by hash that will fail to decode becomes `None`.
|
||||
let trash_data = vec![255u8; 1024];
|
||||
let undecodable_hash = Preimage::note(Cow::Borrowed(&trash_data)).unwrap();
|
||||
|
||||
for i in 0..2u64 {
|
||||
let k = i.twox_64_concat();
|
||||
let old = vec![
|
||||
Some(ScheduledV3Of::<Test> {
|
||||
maybe_id: None,
|
||||
priority: i as u8 + 10,
|
||||
call: small_call.clone().into(),
|
||||
maybe_periodic: None, // 1
|
||||
origin: root(),
|
||||
_phantom: PhantomData::<u64>::default(),
|
||||
}),
|
||||
None,
|
||||
Some(ScheduledV3Of::<Test> {
|
||||
maybe_id: Some(vec![i as u8; 32]),
|
||||
priority: 123,
|
||||
call: large_call.clone().into(),
|
||||
maybe_periodic: Some((4u64, 20)),
|
||||
origin: signed(i),
|
||||
_phantom: PhantomData::<u64>::default(),
|
||||
}),
|
||||
Some(ScheduledV3Of::<Test> {
|
||||
maybe_id: Some(vec![255 - i as u8; 320]),
|
||||
priority: 123,
|
||||
call: MaybeHashed::Hash(bound_hashed_call.hash()),
|
||||
maybe_periodic: Some((8u64, 10)),
|
||||
origin: signed(i),
|
||||
_phantom: PhantomData::<u64>::default(),
|
||||
}),
|
||||
Some(ScheduledV3Of::<Test> {
|
||||
maybe_id: Some(vec![i as u8; 320]),
|
||||
priority: 123,
|
||||
call: MaybeHashed::Hash(undecodable_hash.clone()),
|
||||
maybe_periodic: Some((4u64, 20)),
|
||||
origin: root(),
|
||||
_phantom: PhantomData::<u64>::default(),
|
||||
}),
|
||||
];
|
||||
frame_support::migration::put_storage_value(b"Scheduler", b"Agenda", &k, old);
|
||||
}
|
||||
|
||||
let state = v3::MigrateToV4::<Test>::pre_upgrade().unwrap();
|
||||
let _w = v3::MigrateToV4::<Test>::on_runtime_upgrade();
|
||||
v3::MigrateToV4::<Test>::post_upgrade(state).unwrap();
|
||||
|
||||
let mut x = Agenda::<Test>::iter().map(|x| (x.0, x.1.into_inner())).collect::<Vec<_>>();
|
||||
x.sort_by_key(|x| x.0);
|
||||
|
||||
let bound_large_call = Preimage::bound(large_call).unwrap();
|
||||
assert!(bound_large_call.lookup_needed());
|
||||
let bound_small_call = Preimage::bound(small_call).unwrap();
|
||||
assert!(!bound_small_call.lookup_needed());
|
||||
|
||||
let expected = vec![
|
||||
(
|
||||
0,
|
||||
vec![
|
||||
Some(ScheduledOf::<Test> {
|
||||
maybe_id: None,
|
||||
priority: 10,
|
||||
call: bound_small_call.clone(),
|
||||
maybe_periodic: None,
|
||||
origin: root(),
|
||||
_phantom: PhantomData::<u64>::default(),
|
||||
}),
|
||||
None,
|
||||
Some(ScheduledOf::<Test> {
|
||||
maybe_id: Some(blake2_256(&[0u8; 32])),
|
||||
priority: 123,
|
||||
call: bound_large_call.clone(),
|
||||
maybe_periodic: Some((4u64, 20)),
|
||||
origin: signed(0),
|
||||
_phantom: PhantomData::<u64>::default(),
|
||||
}),
|
||||
Some(ScheduledOf::<Test> {
|
||||
maybe_id: Some(blake2_256(&[255u8; 320])),
|
||||
priority: 123,
|
||||
call: Bounded::from_legacy_hash(bound_hashed_call.hash()),
|
||||
maybe_periodic: Some((8u64, 10)),
|
||||
origin: signed(0),
|
||||
_phantom: PhantomData::<u64>::default(),
|
||||
}),
|
||||
None,
|
||||
],
|
||||
),
|
||||
(
|
||||
1,
|
||||
vec![
|
||||
Some(ScheduledOf::<Test> {
|
||||
maybe_id: None,
|
||||
priority: 11,
|
||||
call: bound_small_call.clone(),
|
||||
maybe_periodic: None,
|
||||
origin: root(),
|
||||
_phantom: PhantomData::<u64>::default(),
|
||||
}),
|
||||
None,
|
||||
Some(ScheduledOf::<Test> {
|
||||
maybe_id: Some(blake2_256(&[1u8; 32])),
|
||||
priority: 123,
|
||||
call: bound_large_call.clone(),
|
||||
maybe_periodic: Some((4u64, 20)),
|
||||
origin: signed(1),
|
||||
_phantom: PhantomData::<u64>::default(),
|
||||
}),
|
||||
Some(ScheduledOf::<Test> {
|
||||
maybe_id: Some(blake2_256(&[254u8; 320])),
|
||||
priority: 123,
|
||||
call: Bounded::from_legacy_hash(bound_hashed_call.hash()),
|
||||
maybe_periodic: Some((8u64, 10)),
|
||||
origin: signed(1),
|
||||
_phantom: PhantomData::<u64>::default(),
|
||||
}),
|
||||
None,
|
||||
],
|
||||
),
|
||||
];
|
||||
for (outer, (i, j)) in x.iter().zip(expected.iter()).enumerate() {
|
||||
assert_eq!(i.0, j.0);
|
||||
for (inner, (x, y)) in i.1.iter().zip(j.1.iter()).enumerate() {
|
||||
assert_eq!(x, y, "at index: outer {} inner {}", outer, inner);
|
||||
}
|
||||
}
|
||||
assert_eq_uvec!(x, expected);
|
||||
|
||||
assert_eq!(StorageVersion::get::<Scheduler>(), 4);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn migration_v3_to_v4_too_large_calls_are_ignored() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Assume that we are at V3.
|
||||
StorageVersion::new(3).put::<Scheduler>();
|
||||
|
||||
let too_large_call = RuntimeCall::System(frame_system::Call::remark {
|
||||
remark: vec![0; <Test as Config>::Preimages::MAX_LENGTH + 1],
|
||||
});
|
||||
|
||||
let i = 0u64;
|
||||
let k = i.twox_64_concat();
|
||||
let old = vec![Some(ScheduledV3Of::<Test> {
|
||||
maybe_id: None,
|
||||
priority: 1,
|
||||
call: too_large_call.clone().into(),
|
||||
maybe_periodic: None,
|
||||
origin: root(),
|
||||
_phantom: PhantomData::<u64>::default(),
|
||||
})];
|
||||
frame_support::migration::put_storage_value(b"Scheduler", b"Agenda", &k, old);
|
||||
|
||||
// The pre_upgrade hook fails:
|
||||
let err = v3::MigrateToV4::<Test>::pre_upgrade().unwrap_err();
|
||||
assert!(err.contains("Call is too large"));
|
||||
// But the migration itself works:
|
||||
let _w = v3::MigrateToV4::<Test>::on_runtime_upgrade();
|
||||
|
||||
let mut x = Agenda::<Test>::iter().map(|x| (x.0, x.1.into_inner())).collect::<Vec<_>>();
|
||||
x.sort_by_key(|x| x.0);
|
||||
// The call becomes `None`.
|
||||
let expected = vec![(0, vec![None])];
|
||||
assert_eq_uvec!(x, expected);
|
||||
|
||||
assert_eq!(StorageVersion::get::<Scheduler>(), 4);
|
||||
});
|
||||
}
|
||||
|
||||
fn signed(i: u64) -> OriginCaller {
|
||||
system::RawOrigin::Signed(i).into()
|
||||
}
|
||||
}
|
||||
@@ -124,7 +124,7 @@ parameter_types! {
|
||||
}
|
||||
impl system::Config for Test {
|
||||
type BaseCallFilter = BaseFilter;
|
||||
type BlockWeights = ();
|
||||
type BlockWeights = BlockWeights;
|
||||
type BlockLength = ();
|
||||
type DbWeight = RocksDbWeight;
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
@@ -151,10 +151,6 @@ impl system::Config for Test {
|
||||
impl logger::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
}
|
||||
parameter_types! {
|
||||
pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * BlockWeights::get().max_block;
|
||||
pub const NoPreimagePostponement: Option<u64> = Some(2);
|
||||
}
|
||||
ord_parameter_types! {
|
||||
pub const One: u64 = 1;
|
||||
}
|
||||
@@ -164,11 +160,54 @@ impl pallet_preimage::Config for Test {
|
||||
type WeightInfo = ();
|
||||
type Currency = ();
|
||||
type ManagerOrigin = EnsureRoot<u64>;
|
||||
type MaxSize = ConstU32<1024>;
|
||||
type BaseDeposit = ();
|
||||
type ByteDeposit = ();
|
||||
}
|
||||
|
||||
pub struct TestWeightInfo;
|
||||
impl WeightInfo for TestWeightInfo {
|
||||
fn service_agendas_base() -> Weight {
|
||||
Weight::from_ref_time(0b0000_0001)
|
||||
}
|
||||
fn service_agenda_base(i: u32) -> Weight {
|
||||
Weight::from_ref_time((i << 8) as u64 + 0b0000_0010)
|
||||
}
|
||||
fn service_task_base() -> Weight {
|
||||
Weight::from_ref_time(0b0000_0100)
|
||||
}
|
||||
fn service_task_periodic() -> Weight {
|
||||
Weight::from_ref_time(0b0000_1100)
|
||||
}
|
||||
fn service_task_named() -> Weight {
|
||||
Weight::from_ref_time(0b0001_0100)
|
||||
}
|
||||
fn service_task_fetched(s: u32) -> Weight {
|
||||
Weight::from_ref_time((s << 8) as u64 + 0b0010_0100)
|
||||
}
|
||||
fn execute_dispatch_signed() -> Weight {
|
||||
Weight::from_ref_time(0b0100_0000)
|
||||
}
|
||||
fn execute_dispatch_unsigned() -> Weight {
|
||||
Weight::from_ref_time(0b1000_0000)
|
||||
}
|
||||
fn schedule(_s: u32) -> Weight {
|
||||
Weight::from_ref_time(50)
|
||||
}
|
||||
fn cancel(_s: u32) -> Weight {
|
||||
Weight::from_ref_time(50)
|
||||
}
|
||||
fn schedule_named(_s: u32) -> Weight {
|
||||
Weight::from_ref_time(50)
|
||||
}
|
||||
fn cancel_named(_s: u32) -> Weight {
|
||||
Weight::from_ref_time(50)
|
||||
}
|
||||
}
|
||||
parameter_types! {
|
||||
pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) *
|
||||
BlockWeights::get().max_block;
|
||||
}
|
||||
|
||||
impl Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
@@ -177,10 +216,9 @@ impl Config for Test {
|
||||
type MaximumWeight = MaximumSchedulerWeight;
|
||||
type ScheduleOrigin = EitherOfDiverse<EnsureRoot<u64>, EnsureSignedBy<One, u64>>;
|
||||
type MaxScheduledPerBlock = ConstU32<10>;
|
||||
type WeightInfo = ();
|
||||
type WeightInfo = TestWeightInfo;
|
||||
type OriginPrivilegeCmp = EqualPrivilegeOnly;
|
||||
type PreimageProvider = Preimage;
|
||||
type NoPreimagePostponement = NoPreimagePostponement;
|
||||
type Preimages = Preimage;
|
||||
}
|
||||
|
||||
pub type LoggerCall = logger::Call<Test>;
|
||||
|
||||
+1093
-387
File diff suppressed because it is too large
Load Diff
@@ -18,22 +18,24 @@
|
||||
//! Autogenerated weights for pallet_scheduler
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2022-05-23, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! DATE: 2022-10-03, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// ./target/production/substrate
|
||||
// /home/benchbot/cargo_target_dir/production/substrate
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=pallet_scheduler
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --template=./.maintain/frame-weight-template.hbs
|
||||
// --heap-pages=4096
|
||||
// --pallet=pallet_scheduler
|
||||
// --chain=dev
|
||||
// --output=./frame/scheduler/src/weights.rs
|
||||
// --template=./.maintain/frame-weight-template.hbs
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
@@ -44,16 +46,14 @@ use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions needed for pallet_scheduler.
|
||||
pub trait WeightInfo {
|
||||
fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight;
|
||||
fn on_initialize_named_resolved(s: u32, ) -> Weight;
|
||||
fn on_initialize_periodic_resolved(s: u32, ) -> Weight;
|
||||
fn on_initialize_resolved(s: u32, ) -> Weight;
|
||||
fn on_initialize_named_aborted(s: u32, ) -> Weight;
|
||||
fn on_initialize_aborted(s: u32, ) -> Weight;
|
||||
fn on_initialize_periodic_named(s: u32, ) -> Weight;
|
||||
fn on_initialize_periodic(s: u32, ) -> Weight;
|
||||
fn on_initialize_named(s: u32, ) -> Weight;
|
||||
fn on_initialize(s: u32, ) -> Weight;
|
||||
fn service_agendas_base() -> Weight;
|
||||
fn service_agenda_base(s: u32, ) -> Weight;
|
||||
fn service_task_base() -> Weight;
|
||||
fn service_task_fetched(s: u32, ) -> Weight;
|
||||
fn service_task_named() -> Weight;
|
||||
fn service_task_periodic() -> Weight;
|
||||
fn execute_dispatch_signed() -> Weight;
|
||||
fn execute_dispatch_unsigned() -> Weight;
|
||||
fn schedule(s: u32, ) -> Weight;
|
||||
fn cancel(s: u32, ) -> Weight;
|
||||
fn schedule_named(s: u32, ) -> Weight;
|
||||
@@ -63,149 +63,84 @@ pub trait WeightInfo {
|
||||
/// Weights for pallet_scheduler using the Substrate node and recommended hardware.
|
||||
pub struct SubstrateWeight<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Storage: Scheduler Agenda (r:2 w:2)
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Scheduler Lookup (r:0 w:1)
|
||||
fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(9_994_000 as u64)
|
||||
// Standard Error: 20_000
|
||||
.saturating_add(Weight::from_ref_time(19_843_000 as u64).saturating_mul(s as u64))
|
||||
// Storage: Scheduler IncompleteSince (r:1 w:1)
|
||||
fn service_agendas_base() -> Weight {
|
||||
Weight::from_ref_time(4_992_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes((4 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
/// The range of component `s` is `[0, 512]`.
|
||||
fn service_agenda_base(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(4_320_000 as u64)
|
||||
// Standard Error: 619
|
||||
.saturating_add(Weight::from_ref_time(336_713 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
fn service_task_base() -> Weight {
|
||||
Weight::from_ref_time(10_864_000 as u64)
|
||||
}
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Scheduler Lookup (r:0 w:1)
|
||||
fn on_initialize_named_resolved(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(10_318_000 as u64)
|
||||
// Standard Error: 17_000
|
||||
.saturating_add(Weight::from_ref_time(15_451_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:2 w:2)
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn on_initialize_periodic_resolved(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(11_675_000 as u64)
|
||||
// Standard Error: 17_000
|
||||
.saturating_add(Weight::from_ref_time(17_019_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn on_initialize_resolved(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(11_934_000 as u64)
|
||||
// Standard Error: 11_000
|
||||
.saturating_add(Weight::from_ref_time(14_134_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:2 w:2)
|
||||
// Storage: Preimage PreimageFor (r:1 w:0)
|
||||
// Storage: Scheduler Lookup (r:0 w:1)
|
||||
fn on_initialize_named_aborted(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(7_279_000 as u64)
|
||||
// Standard Error: 5_000
|
||||
.saturating_add(Weight::from_ref_time(5_388_000 as u64).saturating_mul(s as u64))
|
||||
/// The range of component `s` is `[128, 4194304]`.
|
||||
fn service_task_fetched(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(24_586_000 as u64)
|
||||
// Standard Error: 1
|
||||
.saturating_add(Weight::from_ref_time(1_138 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:2 w:2)
|
||||
// Storage: Preimage PreimageFor (r:1 w:0)
|
||||
fn on_initialize_aborted(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(8_619_000 as u64)
|
||||
// Standard Error: 4_000
|
||||
.saturating_add(Weight::from_ref_time(2_969_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:2 w:2)
|
||||
// Storage: Scheduler Lookup (r:0 w:1)
|
||||
fn on_initialize_periodic_named(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(16_129_000 as u64)
|
||||
// Standard Error: 7_000
|
||||
.saturating_add(Weight::from_ref_time(9_772_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(s as u64)))
|
||||
fn service_task_named() -> Weight {
|
||||
Weight::from_ref_time(13_127_000 as u64)
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:2 w:2)
|
||||
fn on_initialize_periodic(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(15_785_000 as u64)
|
||||
// Standard Error: 5_000
|
||||
.saturating_add(Weight::from_ref_time(7_208_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
// Storage: Scheduler Lookup (r:0 w:1)
|
||||
fn on_initialize_named(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(15_778_000 as u64)
|
||||
// Standard Error: 3_000
|
||||
.saturating_add(Weight::from_ref_time(5_597_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
fn on_initialize(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(15_912_000 as u64)
|
||||
// Standard Error: 5_000
|
||||
.saturating_add(Weight::from_ref_time(4_530_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
fn service_task_periodic() -> Weight {
|
||||
Weight::from_ref_time(11_053_000 as u64)
|
||||
}
|
||||
fn execute_dispatch_signed() -> Weight {
|
||||
Weight::from_ref_time(4_158_000 as u64)
|
||||
}
|
||||
fn execute_dispatch_unsigned() -> Weight {
|
||||
Weight::from_ref_time(4_104_000 as u64)
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
/// The range of component `s` is `[0, 511]`.
|
||||
fn schedule(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(18_013_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(87_000 as u64).saturating_mul(s as u64))
|
||||
Weight::from_ref_time(20_074_000 as u64)
|
||||
// Standard Error: 765
|
||||
.saturating_add(Weight::from_ref_time(343_285 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
// Storage: Scheduler Lookup (r:0 w:1)
|
||||
/// The range of component `s` is `[1, 512]`.
|
||||
fn cancel(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(18_131_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(595_000 as u64).saturating_mul(s as u64))
|
||||
Weight::from_ref_time(21_509_000 as u64)
|
||||
// Standard Error: 708
|
||||
.saturating_add(Weight::from_ref_time(323_013 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Scheduler Lookup (r:1 w:1)
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
/// The range of component `s` is `[0, 511]`.
|
||||
fn schedule_named(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(21_230_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(98_000 as u64).saturating_mul(s as u64))
|
||||
Weight::from_ref_time(22_427_000 as u64)
|
||||
// Standard Error: 850
|
||||
.saturating_add(Weight::from_ref_time(357_265 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Scheduler Lookup (r:1 w:1)
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
/// The range of component `s` is `[1, 512]`.
|
||||
fn cancel_named(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(20_139_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(595_000 as u64).saturating_mul(s as u64))
|
||||
Weight::from_ref_time(22_875_000 as u64)
|
||||
// Standard Error: 693
|
||||
.saturating_add(Weight::from_ref_time(336_643 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as u64))
|
||||
}
|
||||
@@ -213,149 +148,84 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
|
||||
// For backwards compatibility and tests
|
||||
impl WeightInfo for () {
|
||||
// Storage: Scheduler Agenda (r:2 w:2)
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Scheduler Lookup (r:0 w:1)
|
||||
fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(9_994_000 as u64)
|
||||
// Standard Error: 20_000
|
||||
.saturating_add(Weight::from_ref_time(19_843_000 as u64).saturating_mul(s as u64))
|
||||
// Storage: Scheduler IncompleteSince (r:1 w:1)
|
||||
fn service_agendas_base() -> Weight {
|
||||
Weight::from_ref_time(4_992_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((3 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes((4 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
/// The range of component `s` is `[0, 512]`.
|
||||
fn service_agenda_base(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(4_320_000 as u64)
|
||||
// Standard Error: 619
|
||||
.saturating_add(Weight::from_ref_time(336_713 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
fn service_task_base() -> Weight {
|
||||
Weight::from_ref_time(10_864_000 as u64)
|
||||
}
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
// Storage: Scheduler Lookup (r:0 w:1)
|
||||
fn on_initialize_named_resolved(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(10_318_000 as u64)
|
||||
// Standard Error: 17_000
|
||||
.saturating_add(Weight::from_ref_time(15_451_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((2 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes((3 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:2 w:2)
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn on_initialize_periodic_resolved(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(11_675_000 as u64)
|
||||
// Standard Error: 17_000
|
||||
.saturating_add(Weight::from_ref_time(17_019_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((3 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes((3 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
// Storage: Preimage PreimageFor (r:1 w:1)
|
||||
// Storage: Preimage StatusFor (r:1 w:1)
|
||||
fn on_initialize_resolved(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(11_934_000 as u64)
|
||||
// Standard Error: 11_000
|
||||
.saturating_add(Weight::from_ref_time(14_134_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((2 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes((2 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:2 w:2)
|
||||
// Storage: Preimage PreimageFor (r:1 w:0)
|
||||
// Storage: Scheduler Lookup (r:0 w:1)
|
||||
fn on_initialize_named_aborted(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(7_279_000 as u64)
|
||||
// Standard Error: 5_000
|
||||
.saturating_add(Weight::from_ref_time(5_388_000 as u64).saturating_mul(s as u64))
|
||||
/// The range of component `s` is `[128, 4194304]`.
|
||||
fn service_task_fetched(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(24_586_000 as u64)
|
||||
// Standard Error: 1
|
||||
.saturating_add(Weight::from_ref_time(1_138 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:2 w:2)
|
||||
// Storage: Preimage PreimageFor (r:1 w:0)
|
||||
fn on_initialize_aborted(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(8_619_000 as u64)
|
||||
// Standard Error: 4_000
|
||||
.saturating_add(Weight::from_ref_time(2_969_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:2 w:2)
|
||||
// Storage: Scheduler Lookup (r:0 w:1)
|
||||
fn on_initialize_periodic_named(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(16_129_000 as u64)
|
||||
// Standard Error: 7_000
|
||||
.saturating_add(Weight::from_ref_time(9_772_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(s as u64)))
|
||||
fn service_task_named() -> Weight {
|
||||
Weight::from_ref_time(13_127_000 as u64)
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes((2 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:2 w:2)
|
||||
fn on_initialize_periodic(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(15_785_000 as u64)
|
||||
// Standard Error: 5_000
|
||||
.saturating_add(Weight::from_ref_time(7_208_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(s as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
// Storage: Scheduler Lookup (r:0 w:1)
|
||||
fn on_initialize_named(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(15_778_000 as u64)
|
||||
// Standard Error: 3_000
|
||||
.saturating_add(Weight::from_ref_time(5_597_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(s as u64)))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
fn on_initialize(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(15_912_000 as u64)
|
||||
// Standard Error: 5_000
|
||||
.saturating_add(Weight::from_ref_time(4_530_000 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
fn service_task_periodic() -> Weight {
|
||||
Weight::from_ref_time(11_053_000 as u64)
|
||||
}
|
||||
fn execute_dispatch_signed() -> Weight {
|
||||
Weight::from_ref_time(4_158_000 as u64)
|
||||
}
|
||||
fn execute_dispatch_unsigned() -> Weight {
|
||||
Weight::from_ref_time(4_104_000 as u64)
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
/// The range of component `s` is `[0, 511]`.
|
||||
fn schedule(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(18_013_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(87_000 as u64).saturating_mul(s as u64))
|
||||
Weight::from_ref_time(20_074_000 as u64)
|
||||
// Standard Error: 765
|
||||
.saturating_add(Weight::from_ref_time(343_285 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as u64))
|
||||
}
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
// Storage: Scheduler Lookup (r:0 w:1)
|
||||
/// The range of component `s` is `[1, 512]`.
|
||||
fn cancel(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(18_131_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(595_000 as u64).saturating_mul(s as u64))
|
||||
Weight::from_ref_time(21_509_000 as u64)
|
||||
// Standard Error: 708
|
||||
.saturating_add(Weight::from_ref_time(323_013 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Scheduler Lookup (r:1 w:1)
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
/// The range of component `s` is `[0, 511]`.
|
||||
fn schedule_named(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(21_230_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(98_000 as u64).saturating_mul(s as u64))
|
||||
Weight::from_ref_time(22_427_000 as u64)
|
||||
// Standard Error: 850
|
||||
.saturating_add(Weight::from_ref_time(357_265 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
// Storage: Scheduler Lookup (r:1 w:1)
|
||||
// Storage: Scheduler Agenda (r:1 w:1)
|
||||
/// The range of component `s` is `[1, 512]`.
|
||||
fn cancel_named(s: u32, ) -> Weight {
|
||||
Weight::from_ref_time(20_139_000 as u64)
|
||||
// Standard Error: 1_000
|
||||
.saturating_add(Weight::from_ref_time(595_000 as u64).saturating_mul(s as u64))
|
||||
Weight::from_ref_time(22_875_000 as u64)
|
||||
// Standard Error: 693
|
||||
.saturating_add(Weight::from_ref_time(336_643 as u64).saturating_mul(s as u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as u64))
|
||||
}
|
||||
|
||||
@@ -169,6 +169,10 @@ pub fn expand_outer_origin(
|
||||
&self.caller
|
||||
}
|
||||
|
||||
fn into_caller(self) -> Self::PalletsOrigin {
|
||||
self.caller
|
||||
}
|
||||
|
||||
fn try_with_caller<R>(
|
||||
mut self,
|
||||
f: impl FnOnce(Self::PalletsOrigin) -> Result<R, Self::PalletsOrigin>,
|
||||
@@ -190,13 +194,6 @@ pub fn expand_outer_origin(
|
||||
fn signed(by: Self::AccountId) -> Self {
|
||||
#system_path::RawOrigin::Signed(by).into()
|
||||
}
|
||||
|
||||
fn as_signed(self) -> Option<Self::AccountId> {
|
||||
match self.caller {
|
||||
OriginCaller::system(#system_path::RawOrigin::Signed(by)) => Some(by),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
@@ -215,7 +212,6 @@ pub fn expand_outer_origin(
|
||||
// For backwards compatibility and ease of accessing these functions.
|
||||
#[allow(dead_code)]
|
||||
impl RuntimeOrigin {
|
||||
|
||||
#[doc = #doc_string_none_origin]
|
||||
pub fn none() -> Self {
|
||||
<RuntimeOrigin as #scrate::traits::OriginTrait>::none()
|
||||
@@ -238,6 +234,21 @@ pub fn expand_outer_origin(
|
||||
}
|
||||
}
|
||||
|
||||
impl #scrate::traits::CallerTrait<<#runtime as #system_path::Config>::AccountId> for OriginCaller {
|
||||
fn into_system(self) -> Option<#system_path::RawOrigin<<#runtime as #system_path::Config>::AccountId>> {
|
||||
match self {
|
||||
OriginCaller::system(x) => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn as_system_ref(&self) -> Option<&#system_path::RawOrigin<<#runtime as #system_path::Config>::AccountId>> {
|
||||
match &self {
|
||||
OriginCaller::system(o) => Some(o),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<OriginCaller> for #system_path::Origin<#runtime> {
|
||||
type Error = OriginCaller;
|
||||
fn try_from(x: OriginCaller)
|
||||
|
||||
@@ -3181,8 +3181,8 @@ mod tests {
|
||||
dispatch::{DispatchClass, DispatchInfo, Pays},
|
||||
metadata::*,
|
||||
traits::{
|
||||
CrateVersion, Get, GetCallName, IntegrityTest, OnFinalize, OnIdle, OnInitialize,
|
||||
OnRuntimeUpgrade, PalletInfo,
|
||||
CallerTrait, CrateVersion, Get, GetCallName, IntegrityTest, OnFinalize, OnIdle,
|
||||
OnInitialize, OnRuntimeUpgrade, PalletInfo,
|
||||
},
|
||||
};
|
||||
use sp_weights::RuntimeDbWeight;
|
||||
@@ -3300,6 +3300,16 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
impl CallerTrait<<TraitImpl as system::Config>::AccountId> for OuterOrigin {
|
||||
fn into_system(self) -> Option<RawOrigin<<TraitImpl as system::Config>::AccountId>> {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
|
||||
fn as_system_ref(&self) -> Option<&RawOrigin<<TraitImpl as system::Config>::AccountId>> {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::traits::OriginTrait for OuterOrigin {
|
||||
type Call = <TraitImpl as system::Config>::RuntimeCall;
|
||||
type PalletsOrigin = OuterOrigin;
|
||||
@@ -3325,6 +3335,10 @@ mod tests {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
|
||||
fn into_caller(self) -> Self::PalletsOrigin {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
|
||||
fn try_with_caller<R>(
|
||||
self,
|
||||
_f: impl FnOnce(Self::PalletsOrigin) -> Result<R, Self::PalletsOrigin>,
|
||||
@@ -3344,6 +3358,9 @@ mod tests {
|
||||
fn as_signed(self) -> Option<Self::AccountId> {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
fn as_system_ref(&self) -> Option<&RawOrigin<Self::AccountId>> {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
}
|
||||
|
||||
impl system::Config for TraitImpl {
|
||||
|
||||
@@ -58,10 +58,11 @@ pub use misc::{
|
||||
Backing, ConstBool, ConstI128, ConstI16, ConstI32, ConstI64, ConstI8, ConstU128, ConstU16,
|
||||
ConstU32, ConstU64, ConstU8, DefensiveSaturating, EnsureInherentsAreFirst, EqualPrivilegeOnly,
|
||||
EstimateCallFee, ExecuteBlock, ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime,
|
||||
IsSubType, IsType, Len, OffchainWorker, OnKilledAccount, OnNewAccount, PreimageProvider,
|
||||
PreimageRecipient, PrivilegeCmp, SameOrOther, Time, TryCollect, TryDrop, TypedGet, UnixTime,
|
||||
WrapperKeepOpaque, WrapperOpaque,
|
||||
IsSubType, IsType, Len, OffchainWorker, OnKilledAccount, OnNewAccount, PrivilegeCmp,
|
||||
SameOrOther, Time, TryCollect, TryDrop, TypedGet, UnixTime, WrapperKeepOpaque, WrapperOpaque,
|
||||
};
|
||||
#[allow(deprecated)]
|
||||
pub use misc::{PreimageProvider, PreimageRecipient};
|
||||
#[doc(hidden)]
|
||||
pub use misc::{DEFENSIVE_OP_INTERNAL_ERROR, DEFENSIVE_OP_PUBLIC_ERROR};
|
||||
|
||||
@@ -96,8 +97,9 @@ mod dispatch;
|
||||
#[allow(deprecated)]
|
||||
pub use dispatch::EnsureOneOf;
|
||||
pub use dispatch::{
|
||||
AsEnsureOriginWithArg, EitherOf, EitherOfDiverse, EnsureOrigin, EnsureOriginWithArg,
|
||||
MapSuccess, NeverEnsureOrigin, OriginTrait, TryMapSuccess, UnfilteredDispatchable,
|
||||
AsEnsureOriginWithArg, CallerTrait, EitherOf, EitherOfDiverse, EnsureOrigin,
|
||||
EnsureOriginWithArg, MapSuccess, NeverEnsureOrigin, OriginTrait, TryMapSuccess,
|
||||
UnfilteredDispatchable,
|
||||
};
|
||||
|
||||
mod voting;
|
||||
@@ -106,6 +108,9 @@ pub use voting::{
|
||||
U128CurrencyToVote, VoteTally,
|
||||
};
|
||||
|
||||
mod preimages;
|
||||
pub use preimages::{Bounded, BoundedInline, FetchResult, Hash, QueryPreimage, StorePreimage};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
mod try_runtime;
|
||||
#[cfg(feature = "try-runtime")]
|
||||
|
||||
@@ -236,17 +236,25 @@ pub trait UnfilteredDispatchable {
|
||||
fn dispatch_bypass_filter(self, origin: Self::RuntimeOrigin) -> DispatchResultWithPostInfo;
|
||||
}
|
||||
|
||||
/// The trait implemented by the overarching enumeration of the different pallets' origins.
|
||||
/// Unlike `OriginTrait` impls, this does not include any kind of dispatch/call filter. Also, this
|
||||
/// trait is more flexible in terms of how it can be used: it is a `Parameter` and `Member`, so it
|
||||
/// can be used as dispatchable parameters as well as in storage items.
|
||||
pub trait CallerTrait<AccountId>: Parameter + Member + From<RawOrigin<AccountId>> {
|
||||
/// Extract the signer from the message if it is a `Signed` origin.
|
||||
fn into_system(self) -> Option<RawOrigin<AccountId>>;
|
||||
|
||||
/// Extract a reference to the system-level `RawOrigin` if it is that.
|
||||
fn as_system_ref(&self) -> Option<&RawOrigin<AccountId>>;
|
||||
}
|
||||
|
||||
/// Methods available on `frame_system::Config::RuntimeOrigin`.
|
||||
pub trait OriginTrait: Sized {
|
||||
/// Runtime call type, as in `frame_system::Config::Call`
|
||||
type Call;
|
||||
|
||||
/// The caller origin, overarching type of all pallets origins.
|
||||
type PalletsOrigin: Parameter
|
||||
+ Member
|
||||
+ Into<Self>
|
||||
+ From<RawOrigin<Self::AccountId>>
|
||||
+ MaxEncodedLen;
|
||||
type PalletsOrigin: Into<Self> + CallerTrait<Self::AccountId> + MaxEncodedLen;
|
||||
|
||||
/// The AccountId used across the system.
|
||||
type AccountId;
|
||||
@@ -266,9 +274,12 @@ pub trait OriginTrait: Sized {
|
||||
/// For root origin caller, the filters are bypassed and true is returned.
|
||||
fn filter_call(&self, call: &Self::Call) -> bool;
|
||||
|
||||
/// Get the caller.
|
||||
/// Get a reference to the caller (`CallerTrait` impl).
|
||||
fn caller(&self) -> &Self::PalletsOrigin;
|
||||
|
||||
/// Consume `self` and return the caller.
|
||||
fn into_caller(self) -> Self::PalletsOrigin;
|
||||
|
||||
/// Do something with the caller, consuming self but returning it if the caller was unused.
|
||||
fn try_with_caller<R>(
|
||||
self,
|
||||
@@ -285,7 +296,20 @@ pub trait OriginTrait: Sized {
|
||||
fn signed(by: Self::AccountId) -> Self;
|
||||
|
||||
/// Extract the signer from the message if it is a `Signed` origin.
|
||||
fn as_signed(self) -> Option<Self::AccountId>;
|
||||
fn as_signed(self) -> Option<Self::AccountId> {
|
||||
self.into_caller().into_system().and_then(|s| {
|
||||
if let RawOrigin::Signed(who) = s {
|
||||
Some(who)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Extract a reference to the sytsem origin, if that's what the caller is.
|
||||
fn as_system_ref(&self) -> Option<&RawOrigin<Self::AccountId>> {
|
||||
self.caller().as_system_ref()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -932,7 +932,7 @@ pub trait PreimageRecipient<Hash>: PreimageProvider<Hash> {
|
||||
/// Maximum size of a preimage.
|
||||
type MaxSize: Get<u32>;
|
||||
|
||||
/// Store the bytes of a preimage on chain.
|
||||
/// Store the bytes of a preimage on chain infallible due to the bounded type.
|
||||
fn note_preimage(bytes: crate::BoundedVec<u8, Self::MaxSize>);
|
||||
|
||||
/// Clear a previously noted preimage. This is infallible and should be treated more like a
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2019-2022 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.
|
||||
|
||||
//! Stuff for dealing with 32-byte hashed preimages.
|
||||
|
||||
use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
|
||||
use sp_core::{RuntimeDebug, H256};
|
||||
use sp_io::hashing::blake2_256;
|
||||
use sp_runtime::{traits::ConstU32, DispatchError};
|
||||
use sp_std::borrow::Cow;
|
||||
|
||||
pub type Hash = H256;
|
||||
pub type BoundedInline = crate::BoundedVec<u8, ConstU32<128>>;
|
||||
|
||||
#[derive(
|
||||
Encode, Decode, MaxEncodedLen, Clone, Eq, PartialEq, scale_info::TypeInfo, RuntimeDebug,
|
||||
)]
|
||||
#[codec(mel_bound())]
|
||||
pub enum Bounded<T> {
|
||||
/// A Blake2 256 hash with no preimage length. We
|
||||
/// do not support creation of this except for transitioning from legacy state.
|
||||
/// In the future we will make this a pure `Dummy` item storing only the final `dummy` field.
|
||||
Legacy { hash: Hash, dummy: sp_std::marker::PhantomData<T> },
|
||||
/// A an bounded `Call`. Its encoding must be at most 128 bytes.
|
||||
Inline(BoundedInline),
|
||||
/// A Blake2-256 hash of the call together with an upper limit for its size.
|
||||
Lookup { hash: Hash, len: u32 },
|
||||
}
|
||||
|
||||
impl<T> Bounded<T> {
|
||||
/// Casts the wrapped type into something that encodes alike.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use frame_support::traits::Bounded;
|
||||
///
|
||||
/// // Transmute from `String` to `&str`.
|
||||
/// let x: Bounded<String> = Bounded::Inline(Default::default());
|
||||
/// let _: Bounded<&str> = x.transmute();
|
||||
/// ```
|
||||
pub fn transmute<S: Encode>(self) -> Bounded<S>
|
||||
where
|
||||
T: Encode + EncodeLike<S>,
|
||||
{
|
||||
use Bounded::*;
|
||||
match self {
|
||||
Legacy { hash, .. } => Legacy { hash, dummy: sp_std::marker::PhantomData },
|
||||
Inline(x) => Inline(x),
|
||||
Lookup { hash, len } => Lookup { hash, len },
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the hash of the preimage.
|
||||
///
|
||||
/// The hash is re-calculated every time if the preimage is inlined.
|
||||
pub fn hash(&self) -> H256 {
|
||||
use Bounded::*;
|
||||
match self {
|
||||
Legacy { hash, .. } => *hash,
|
||||
Inline(x) => blake2_256(x.as_ref()).into(),
|
||||
Lookup { hash, .. } => *hash,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The maximum we expect a single legacy hash lookup to be.
|
||||
const MAX_LEGACY_LEN: u32 = 1_000_000;
|
||||
|
||||
impl<T> Bounded<T> {
|
||||
/// Returns the length of the preimage or `None` if the length is unknown.
|
||||
pub fn len(&self) -> Option<u32> {
|
||||
match self {
|
||||
Self::Legacy { .. } => None,
|
||||
Self::Inline(i) => Some(i.len() as u32),
|
||||
Self::Lookup { len, .. } => Some(*len),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the image will require a lookup to be peeked.
|
||||
pub fn lookup_needed(&self) -> bool {
|
||||
match self {
|
||||
Self::Inline(..) => false,
|
||||
Self::Legacy { .. } | Self::Lookup { .. } => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// The maximum length of the lookup that is needed to peek `Self`.
|
||||
pub fn lookup_len(&self) -> Option<u32> {
|
||||
match self {
|
||||
Self::Inline(..) => None,
|
||||
Self::Legacy { .. } => Some(MAX_LEGACY_LEN),
|
||||
Self::Lookup { len, .. } => Some(*len),
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a `Lookup` bounded item.
|
||||
pub fn unrequested(hash: Hash, len: u32) -> Self {
|
||||
Self::Lookup { hash, len }
|
||||
}
|
||||
|
||||
/// Constructs a `Legacy` bounded item.
|
||||
#[deprecated = "This API is only for transitioning to Scheduler v3 API"]
|
||||
pub fn from_legacy_hash(hash: impl Into<Hash>) -> Self {
|
||||
Self::Legacy { hash: hash.into(), dummy: sp_std::marker::PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
pub type FetchResult = Result<Cow<'static, [u8]>, DispatchError>;
|
||||
|
||||
/// A interface for looking up preimages from their hash on chain.
|
||||
pub trait QueryPreimage {
|
||||
/// Returns whether a preimage exists for a given hash and if so its length.
|
||||
fn len(hash: &Hash) -> Option<u32>;
|
||||
|
||||
/// Returns the preimage for a given hash. If given, `len` must be the size of the preimage.
|
||||
fn fetch(hash: &Hash, len: Option<u32>) -> FetchResult;
|
||||
|
||||
/// Returns whether a preimage request exists for a given hash.
|
||||
fn is_requested(hash: &Hash) -> bool;
|
||||
|
||||
/// Request that someone report a preimage. Providers use this to optimise the economics for
|
||||
/// preimage reporting.
|
||||
fn request(hash: &Hash);
|
||||
|
||||
/// Cancel a previous preimage request.
|
||||
fn unrequest(hash: &Hash);
|
||||
|
||||
/// Request that the data required for decoding the given `bounded` value is made available.
|
||||
fn hold<T>(bounded: &Bounded<T>) {
|
||||
use Bounded::*;
|
||||
match bounded {
|
||||
Inline(..) => {},
|
||||
Legacy { hash, .. } | Lookup { hash, .. } => Self::request(hash),
|
||||
}
|
||||
}
|
||||
|
||||
/// No longer request that the data required for decoding the given `bounded` value is made
|
||||
/// available.
|
||||
fn drop<T>(bounded: &Bounded<T>) {
|
||||
use Bounded::*;
|
||||
match bounded {
|
||||
Inline(..) => {},
|
||||
Legacy { hash, .. } | Lookup { hash, .. } => Self::unrequest(hash),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check to see if all data required for the given `bounded` value is available for its
|
||||
/// decoding.
|
||||
fn have<T>(bounded: &Bounded<T>) -> bool {
|
||||
use Bounded::*;
|
||||
match bounded {
|
||||
Inline(..) => true,
|
||||
Legacy { hash, .. } | Lookup { hash, .. } => Self::len(hash).is_some(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a `Bounded` instance based on the `hash` and `len` of the encoded value. This may not
|
||||
/// be `peek`-able or `realize`-able.
|
||||
fn pick<T>(hash: Hash, len: u32) -> Bounded<T> {
|
||||
Self::request(&hash);
|
||||
Bounded::Lookup { hash, len }
|
||||
}
|
||||
|
||||
/// Convert the given `bounded` instance back into its original instance, also returning the
|
||||
/// exact size of its encoded form if it needed to be looked-up from a stored preimage).
|
||||
///
|
||||
/// NOTE: This does not remove any data needed for realization. If you will no longer use the
|
||||
/// `bounded`, call `realize` instead or call `drop` afterwards.
|
||||
fn peek<T: Decode>(bounded: &Bounded<T>) -> Result<(T, Option<u32>), DispatchError> {
|
||||
use Bounded::*;
|
||||
match bounded {
|
||||
Inline(data) => T::decode(&mut &data[..]).ok().map(|x| (x, None)),
|
||||
Lookup { hash, len } => {
|
||||
let data = Self::fetch(hash, Some(*len))?;
|
||||
T::decode(&mut &data[..]).ok().map(|x| (x, Some(data.len() as u32)))
|
||||
},
|
||||
Legacy { hash, .. } => {
|
||||
let data = Self::fetch(hash, None)?;
|
||||
T::decode(&mut &data[..]).ok().map(|x| (x, Some(data.len() as u32)))
|
||||
},
|
||||
}
|
||||
.ok_or(DispatchError::Corruption)
|
||||
}
|
||||
|
||||
/// Convert the given `bounded` value back into its original instance. If successful,
|
||||
/// `drop` any data backing it. This will not break the realisability of independently
|
||||
/// created instances of `Bounded` which happen to have identical data.
|
||||
fn realize<T: Decode>(bounded: &Bounded<T>) -> Result<(T, Option<u32>), DispatchError> {
|
||||
let r = Self::peek(bounded)?;
|
||||
Self::drop(bounded);
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
/// A interface for managing preimages to hashes on chain.
|
||||
///
|
||||
/// Note that this API does not assume any underlying user is calling, and thus
|
||||
/// does not handle any preimage ownership or fees. Other system level logic that
|
||||
/// uses this API should implement that on their own side.
|
||||
pub trait StorePreimage: QueryPreimage {
|
||||
/// The maximum length of preimage we can store.
|
||||
///
|
||||
/// This is the maximum length of the *encoded* value that can be passed to `bound`.
|
||||
const MAX_LENGTH: usize;
|
||||
|
||||
/// Request and attempt to store the bytes of a preimage on chain.
|
||||
///
|
||||
/// May return `DispatchError::Exhausted` if the preimage is just too big.
|
||||
fn note(bytes: Cow<[u8]>) -> Result<Hash, DispatchError>;
|
||||
|
||||
/// Attempt to clear a previously noted preimage. Exactly the same as `unrequest` but is
|
||||
/// provided for symmetry.
|
||||
fn unnote(hash: &Hash) {
|
||||
Self::unrequest(hash)
|
||||
}
|
||||
|
||||
/// Convert an otherwise unbounded or large value into a type ready for placing in storage. The
|
||||
/// result is a type whose `MaxEncodedLen` is 131 bytes.
|
||||
///
|
||||
/// NOTE: Once this API is used, you should use either `drop` or `realize`.
|
||||
fn bound<T: Encode>(t: T) -> Result<Bounded<T>, DispatchError> {
|
||||
let data = t.encode();
|
||||
let len = data.len() as u32;
|
||||
Ok(match BoundedInline::try_from(data) {
|
||||
Ok(bounded) => Bounded::Inline(bounded),
|
||||
Err(unbounded) => Bounded::Lookup { hash: Self::note(unbounded.into())?, len },
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl QueryPreimage for () {
|
||||
fn len(_: &Hash) -> Option<u32> {
|
||||
None
|
||||
}
|
||||
fn fetch(_: &Hash, _: Option<u32>) -> FetchResult {
|
||||
Err(DispatchError::Unavailable)
|
||||
}
|
||||
fn is_requested(_: &Hash) -> bool {
|
||||
false
|
||||
}
|
||||
fn request(_: &Hash) {}
|
||||
fn unrequest(_: &Hash) {}
|
||||
}
|
||||
|
||||
impl StorePreimage for () {
|
||||
const MAX_LENGTH: usize = 0;
|
||||
fn note(_: Cow<[u8]>) -> Result<Hash, DispatchError> {
|
||||
Err(DispatchError::Exhausted)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{bounded_vec, BoundedVec};
|
||||
|
||||
#[test]
|
||||
fn bounded_size_is_correct() {
|
||||
assert_eq!(<Bounded<Vec<u8>> as MaxEncodedLen>::max_encoded_len(), 131);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bounded_basic_works() {
|
||||
let data: BoundedVec<u8, _> = bounded_vec![b'a', b'b', b'c'];
|
||||
let len = data.len() as u32;
|
||||
let hash = blake2_256(&data).into();
|
||||
|
||||
// Inline works
|
||||
{
|
||||
let bound: Bounded<Vec<u8>> = Bounded::Inline(data.clone());
|
||||
assert_eq!(bound.hash(), hash);
|
||||
assert_eq!(bound.len(), Some(len));
|
||||
assert!(!bound.lookup_needed());
|
||||
assert_eq!(bound.lookup_len(), None);
|
||||
}
|
||||
// Legacy works
|
||||
{
|
||||
let bound: Bounded<Vec<u8>> = Bounded::Legacy { hash, dummy: Default::default() };
|
||||
assert_eq!(bound.hash(), hash);
|
||||
assert_eq!(bound.len(), None);
|
||||
assert!(bound.lookup_needed());
|
||||
assert_eq!(bound.lookup_len(), Some(1_000_000));
|
||||
}
|
||||
// Lookup works
|
||||
{
|
||||
let bound: Bounded<Vec<u8>> = Bounded::Lookup { hash, len: data.len() as u32 };
|
||||
assert_eq!(bound.hash(), hash);
|
||||
assert_eq!(bound.len(), Some(len));
|
||||
assert!(bound.lookup_needed());
|
||||
assert_eq!(bound.lookup_len(), Some(len));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bounded_transmuting_works() {
|
||||
let data: BoundedVec<u8, _> = bounded_vec![b'a', b'b', b'c'];
|
||||
|
||||
// Transmute a `String` into a `&str`.
|
||||
let x: Bounded<String> = Bounded::Inline(data.clone());
|
||||
let y: Bounded<&str> = x.transmute();
|
||||
assert_eq!(y, Bounded::Inline(data));
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
//! Traits and associated utilities for scheduling dispatchables in FRAME.
|
||||
|
||||
#[allow(deprecated)]
|
||||
use super::PreimageProvider;
|
||||
use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{traits::Saturating, DispatchError, RuntimeDebug};
|
||||
@@ -128,6 +130,7 @@ impl<T: Decode, H> MaybeHashed<T, H> {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: deprecate
|
||||
pub mod v1 {
|
||||
use super::*;
|
||||
|
||||
@@ -283,6 +286,7 @@ pub mod v1 {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: deprecate
|
||||
pub mod v2 {
|
||||
use super::*;
|
||||
|
||||
@@ -375,6 +379,97 @@ pub mod v2 {
|
||||
}
|
||||
}
|
||||
|
||||
pub use v1::*;
|
||||
pub mod v3 {
|
||||
use super::*;
|
||||
use crate::traits::Bounded;
|
||||
|
||||
use super::PreimageProvider;
|
||||
/// A type that can be used as a scheduler.
|
||||
pub trait Anon<BlockNumber, Call, Origin> {
|
||||
/// An address which can be used for removing a scheduled task.
|
||||
type Address: Codec + MaxEncodedLen + Clone + Eq + EncodeLike + Debug + TypeInfo;
|
||||
|
||||
/// Schedule a dispatch to happen at the beginning of some block in the future.
|
||||
///
|
||||
/// This is not named.
|
||||
fn schedule(
|
||||
when: DispatchTime<BlockNumber>,
|
||||
maybe_periodic: Option<Period<BlockNumber>>,
|
||||
priority: Priority,
|
||||
origin: Origin,
|
||||
call: Bounded<Call>,
|
||||
) -> Result<Self::Address, DispatchError>;
|
||||
|
||||
/// Cancel a scheduled task. If periodic, then it will cancel all further instances of that,
|
||||
/// also.
|
||||
///
|
||||
/// Will return an `Unavailable` error if the `address` is invalid.
|
||||
///
|
||||
/// NOTE: This guaranteed to work only *before* the point that it is due to be executed.
|
||||
/// If it ends up being delayed beyond the point of execution, then it cannot be cancelled.
|
||||
///
|
||||
/// NOTE2: This will not work to cancel periodic tasks after their initial execution. For
|
||||
/// that, you must name the task explicitly using the `Named` trait.
|
||||
fn cancel(address: Self::Address) -> Result<(), DispatchError>;
|
||||
|
||||
/// Reschedule a task. For one-off tasks, this dispatch is guaranteed to succeed
|
||||
/// only if it is executed *before* the currently scheduled block. For periodic tasks,
|
||||
/// this dispatch is guaranteed to succeed only before the *initial* execution; for
|
||||
/// others, use `reschedule_named`.
|
||||
///
|
||||
/// Will return an `Unavailable` error if the `address` is invalid.
|
||||
fn reschedule(
|
||||
address: Self::Address,
|
||||
when: DispatchTime<BlockNumber>,
|
||||
) -> Result<Self::Address, DispatchError>;
|
||||
|
||||
/// Return the next dispatch time for a given task.
|
||||
///
|
||||
/// Will return an `Unavailable` error if the `address` is invalid.
|
||||
fn next_dispatch_time(address: Self::Address) -> Result<BlockNumber, DispatchError>;
|
||||
}
|
||||
|
||||
pub type TaskName = [u8; 32];
|
||||
|
||||
/// A type that can be used as a scheduler.
|
||||
pub trait Named<BlockNumber, Call, Origin> {
|
||||
/// An address which can be used for removing a scheduled task.
|
||||
type Address: Codec + MaxEncodedLen + Clone + Eq + EncodeLike + sp_std::fmt::Debug;
|
||||
|
||||
/// Schedule a dispatch to happen at the beginning of some block in the future.
|
||||
///
|
||||
/// - `id`: The identity of the task. This must be unique and will return an error if not.
|
||||
fn schedule_named(
|
||||
id: TaskName,
|
||||
when: DispatchTime<BlockNumber>,
|
||||
maybe_periodic: Option<Period<BlockNumber>>,
|
||||
priority: Priority,
|
||||
origin: Origin,
|
||||
call: Bounded<Call>,
|
||||
) -> Result<Self::Address, DispatchError>;
|
||||
|
||||
/// Cancel a scheduled, named task. If periodic, then it will cancel all further instances
|
||||
/// of that, also.
|
||||
///
|
||||
/// Will return an `Unavailable` error if the `id` is invalid.
|
||||
///
|
||||
/// NOTE: This guaranteed to work only *before* the point that it is due to be executed.
|
||||
/// If it ends up being delayed beyond the point of execution, then it cannot be cancelled.
|
||||
fn cancel_named(id: TaskName) -> Result<(), DispatchError>;
|
||||
|
||||
/// Reschedule a task. For one-off tasks, this dispatch is guaranteed to succeed
|
||||
/// only if it is executed *before* the currently scheduled block.
|
||||
///
|
||||
/// Will return an `Unavailable` error if the `id` is invalid.
|
||||
fn reschedule_named(
|
||||
id: TaskName,
|
||||
when: DispatchTime<BlockNumber>,
|
||||
) -> Result<Self::Address, DispatchError>;
|
||||
|
||||
/// Return the next dispatch time for a given task.
|
||||
///
|
||||
/// Will return an `Unavailable` error if the `id` is invalid.
|
||||
fn next_dispatch_time(id: TaskName) -> Result<BlockNumber, DispatchError>;
|
||||
}
|
||||
}
|
||||
|
||||
pub use v1::*;
|
||||
|
||||
+3
-3
@@ -28,7 +28,7 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
|
||||
<&[(T,)] as EncodeLike<BinaryHeap<LikeT>>>
|
||||
<&[(T,)] as EncodeLike<LinkedList<LikeT>>>
|
||||
<&[T] as EncodeLike<Vec<U>>>
|
||||
and 279 others
|
||||
and 280 others
|
||||
= note: required because of the requirements on the impl of `FullEncode` for `Bar`
|
||||
= note: required because of the requirements on the impl of `FullCodec` for `Bar`
|
||||
= note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
|
||||
@@ -69,7 +69,7 @@ error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied
|
||||
(A, B, C, D)
|
||||
(A, B, C, D, E)
|
||||
(A, B, C, D, E, F)
|
||||
and 160 others
|
||||
and 161 others
|
||||
= note: required because of the requirements on the impl of `StaticTypeInfo` for `Bar`
|
||||
= note: required because of the requirements on the impl of `StorageEntryMetadataBuilder` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
|
||||
|
||||
@@ -103,7 +103,7 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
|
||||
<&[(T,)] as EncodeLike<BinaryHeap<LikeT>>>
|
||||
<&[(T,)] as EncodeLike<LinkedList<LikeT>>>
|
||||
<&[T] as EncodeLike<Vec<U>>>
|
||||
and 279 others
|
||||
and 280 others
|
||||
= note: required because of the requirements on the impl of `FullEncode` for `Bar`
|
||||
= note: required because of the requirements on the impl of `FullCodec` for `Bar`
|
||||
= note: required because of the requirements on the impl of `StorageEntryMetadataBuilder` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
|
||||
|
||||
+3
-3
@@ -28,7 +28,7 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
|
||||
<&[(T,)] as EncodeLike<BinaryHeap<LikeT>>>
|
||||
<&[(T,)] as EncodeLike<LinkedList<LikeT>>>
|
||||
<&[T] as EncodeLike<Vec<U>>>
|
||||
and 279 others
|
||||
and 280 others
|
||||
= note: required because of the requirements on the impl of `FullEncode` for `Bar`
|
||||
= note: required because of the requirements on the impl of `FullCodec` for `Bar`
|
||||
= note: required because of the requirements on the impl of `PartialStorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
|
||||
@@ -69,7 +69,7 @@ error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied
|
||||
(A, B, C, D)
|
||||
(A, B, C, D, E)
|
||||
(A, B, C, D, E, F)
|
||||
and 160 others
|
||||
and 161 others
|
||||
= note: required because of the requirements on the impl of `StaticTypeInfo` for `Bar`
|
||||
= note: required because of the requirements on the impl of `StorageEntryMetadataBuilder` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
|
||||
|
||||
@@ -103,7 +103,7 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied
|
||||
<&[(T,)] as EncodeLike<BinaryHeap<LikeT>>>
|
||||
<&[(T,)] as EncodeLike<LinkedList<LikeT>>>
|
||||
<&[T] as EncodeLike<Vec<U>>>
|
||||
and 279 others
|
||||
and 280 others
|
||||
= note: required because of the requirements on the impl of `FullEncode` for `Bar`
|
||||
= note: required because of the requirements on the impl of `FullCodec` for `Bar`
|
||||
= note: required because of the requirements on the impl of `StorageEntryMetadataBuilder` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
|
||||
|
||||
@@ -13,5 +13,5 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied
|
||||
(TupleElement0, TupleElement1, TupleElement2, TupleElement3, TupleElement4, TupleElement5)
|
||||
(TupleElement0, TupleElement1, TupleElement2, TupleElement3, TupleElement4, TupleElement5, TupleElement6)
|
||||
(TupleElement0, TupleElement1, TupleElement2, TupleElement3, TupleElement4, TupleElement5, TupleElement6, TupleElement7)
|
||||
and 77 others
|
||||
and 78 others
|
||||
= note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo<T>, Bar>`
|
||||
|
||||
@@ -13,6 +13,6 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied
|
||||
(TupleElement0, TupleElement1, TupleElement2, TupleElement3, TupleElement4, TupleElement5)
|
||||
(TupleElement0, TupleElement1, TupleElement2, TupleElement3, TupleElement4, TupleElement5, TupleElement6)
|
||||
(TupleElement0, TupleElement1, TupleElement2, TupleElement3, TupleElement4, TupleElement5, TupleElement6, TupleElement7)
|
||||
and 77 others
|
||||
and 78 others
|
||||
= note: required because of the requirements on the impl of `KeyGeneratorMaxEncodedLen` for `Key<frame_support::Twox64Concat, Bar>`
|
||||
= note: required because of the requirements on the impl of `StorageInfoTrait` for `frame_support::pallet_prelude::StorageNMap<_GeneratedPrefixForStorageFoo<T>, Key<frame_support::Twox64Concat, Bar>, u32>`
|
||||
|
||||
@@ -222,7 +222,10 @@ pub mod pallet {
|
||||
+ OriginTrait<Call = Self::RuntimeCall>;
|
||||
|
||||
/// The aggregated `RuntimeCall` type.
|
||||
type RuntimeCall: Dispatchable + Debug;
|
||||
type RuntimeCall: Parameter
|
||||
+ Dispatchable<RuntimeOrigin = Self::RuntimeOrigin>
|
||||
+ Debug
|
||||
+ From<Call<Self>>;
|
||||
|
||||
/// Account index (aka nonce) type. This stores the number of previous transactions
|
||||
/// associated with a sender account.
|
||||
|
||||
@@ -96,7 +96,6 @@ impl pallet_preimage::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Currency = Balances;
|
||||
type ManagerOrigin = EnsureRoot<Self::AccountId>;
|
||||
type MaxSize = ConstU32<{ 4096 * 1024 }>; // PreimageMaxSize Taken from Polkadot as reference.
|
||||
type BaseDeposit = ConstU64<1>;
|
||||
type ByteDeposit = ConstU64<1>;
|
||||
type WeightInfo = ();
|
||||
|
||||
@@ -276,6 +276,14 @@ impl<'a, T, S> sp_std::iter::IntoIterator for BoundedSlice<'a, T, S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, S: Get<u32>> BoundedSlice<'a, T, S> {
|
||||
/// Create an instance from the first elements of the given slice (or all of it if it is smaller
|
||||
/// than the length bound).
|
||||
pub fn truncate_from(s: &'a [T]) -> Self {
|
||||
Self(&s[0..(s.len().min(S::get() as usize))], PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Decode, S: Get<u32>> Decode for BoundedVec<T, S> {
|
||||
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
|
||||
let inner = Vec::<T>::decode(input)?;
|
||||
@@ -620,12 +628,12 @@ impl<T, S: Get<u32>> BoundedVec<T, S> {
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `index > len`.
|
||||
pub fn try_insert(&mut self, index: usize, element: T) -> Result<(), ()> {
|
||||
pub fn try_insert(&mut self, index: usize, element: T) -> Result<(), T> {
|
||||
if self.len() < Self::bound() {
|
||||
self.0.insert(index, element);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
Err(element)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,12 +643,12 @@ impl<T, S: Get<u32>> BoundedVec<T, S> {
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the new capacity exceeds isize::MAX bytes.
|
||||
pub fn try_push(&mut self, element: T) -> Result<(), ()> {
|
||||
pub fn try_push(&mut self, element: T) -> Result<(), T> {
|
||||
if self.len() < Self::bound() {
|
||||
self.0.push(element);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
Err(element)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -673,13 +681,13 @@ where
|
||||
}
|
||||
|
||||
impl<T, S: Get<u32>> TryFrom<Vec<T>> for BoundedVec<T, S> {
|
||||
type Error = ();
|
||||
type Error = Vec<T>;
|
||||
fn try_from(t: Vec<T>) -> Result<Self, Self::Error> {
|
||||
if t.len() <= Self::bound() {
|
||||
// explicit check just above
|
||||
Ok(Self::unchecked_from(t))
|
||||
} else {
|
||||
Err(())
|
||||
Err(t)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -886,6 +894,16 @@ pub mod test {
|
||||
use super::*;
|
||||
use crate::{bounded_vec, ConstU32};
|
||||
|
||||
#[test]
|
||||
fn slice_truncate_from_works() {
|
||||
let bounded = BoundedSlice::<u32, ConstU32<4>>::truncate_from(&[1, 2, 3, 4, 5]);
|
||||
assert_eq!(bounded.deref(), &[1, 2, 3, 4]);
|
||||
let bounded = BoundedSlice::<u32, ConstU32<4>>::truncate_from(&[1, 2, 3, 4]);
|
||||
assert_eq!(bounded.deref(), &[1, 2, 3, 4]);
|
||||
let bounded = BoundedSlice::<u32, ConstU32<4>>::truncate_from(&[1, 2, 3]);
|
||||
assert_eq!(bounded.deref(), &[1, 2, 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slide_works() {
|
||||
let mut b: BoundedVec<u32, ConstU32<6>> = bounded_vec![0, 1, 2, 3, 4, 5];
|
||||
|
||||
@@ -547,6 +547,12 @@ pub enum DispatchError {
|
||||
/// The number of transactional layers has been reached, or we are not in a transactional
|
||||
/// layer.
|
||||
Transactional(TransactionalError),
|
||||
/// Resources exhausted, e.g. attempt to read/write data which is too large to manipulate.
|
||||
Exhausted,
|
||||
/// The state is corrupt; this is generally not going to fix itself.
|
||||
Corruption,
|
||||
/// Some resource (e.g. a preimage) is unavailable right now. This might fix itself later.
|
||||
Unavailable,
|
||||
}
|
||||
|
||||
/// Result of a `Dispatchable` which contains the `DispatchResult` and additional information about
|
||||
@@ -671,18 +677,21 @@ impl From<&'static str> for DispatchError {
|
||||
|
||||
impl From<DispatchError> for &'static str {
|
||||
fn from(err: DispatchError) -> &'static str {
|
||||
use DispatchError::*;
|
||||
match err {
|
||||
DispatchError::Other(msg) => msg,
|
||||
DispatchError::CannotLookup => "Cannot lookup",
|
||||
DispatchError::BadOrigin => "Bad origin",
|
||||
DispatchError::Module(ModuleError { message, .. }) =>
|
||||
message.unwrap_or("Unknown module error"),
|
||||
DispatchError::ConsumerRemaining => "Consumer remaining",
|
||||
DispatchError::NoProviders => "No providers",
|
||||
DispatchError::TooManyConsumers => "Too many consumers",
|
||||
DispatchError::Token(e) => e.into(),
|
||||
DispatchError::Arithmetic(e) => e.into(),
|
||||
DispatchError::Transactional(e) => e.into(),
|
||||
Other(msg) => msg,
|
||||
CannotLookup => "Cannot lookup",
|
||||
BadOrigin => "Bad origin",
|
||||
Module(ModuleError { message, .. }) => message.unwrap_or("Unknown module error"),
|
||||
ConsumerRemaining => "Consumer remaining",
|
||||
NoProviders => "No providers",
|
||||
TooManyConsumers => "Too many consumers",
|
||||
Token(e) => e.into(),
|
||||
Arithmetic(e) => e.into(),
|
||||
Transactional(e) => e.into(),
|
||||
Exhausted => "Resources exhausted",
|
||||
Corruption => "State corrupt",
|
||||
Unavailable => "Resource unavailable",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -698,33 +707,37 @@ where
|
||||
|
||||
impl traits::Printable for DispatchError {
|
||||
fn print(&self) {
|
||||
use DispatchError::*;
|
||||
"DispatchError".print();
|
||||
match self {
|
||||
Self::Other(err) => err.print(),
|
||||
Self::CannotLookup => "Cannot lookup".print(),
|
||||
Self::BadOrigin => "Bad origin".print(),
|
||||
Self::Module(ModuleError { index, error, message }) => {
|
||||
Other(err) => err.print(),
|
||||
CannotLookup => "Cannot lookup".print(),
|
||||
BadOrigin => "Bad origin".print(),
|
||||
Module(ModuleError { index, error, message }) => {
|
||||
index.print();
|
||||
error.print();
|
||||
if let Some(msg) = message {
|
||||
msg.print();
|
||||
}
|
||||
},
|
||||
Self::ConsumerRemaining => "Consumer remaining".print(),
|
||||
Self::NoProviders => "No providers".print(),
|
||||
Self::TooManyConsumers => "Too many consumers".print(),
|
||||
Self::Token(e) => {
|
||||
ConsumerRemaining => "Consumer remaining".print(),
|
||||
NoProviders => "No providers".print(),
|
||||
TooManyConsumers => "Too many consumers".print(),
|
||||
Token(e) => {
|
||||
"Token error: ".print();
|
||||
<&'static str>::from(*e).print();
|
||||
},
|
||||
Self::Arithmetic(e) => {
|
||||
Arithmetic(e) => {
|
||||
"Arithmetic error: ".print();
|
||||
<&'static str>::from(*e).print();
|
||||
},
|
||||
Self::Transactional(e) => {
|
||||
Transactional(e) => {
|
||||
"Transactional error: ".print();
|
||||
<&'static str>::from(*e).print();
|
||||
},
|
||||
Exhausted => "Resources exhausted".print(),
|
||||
Corruption => "State corrupt".print(),
|
||||
Unavailable => "Resource unavailable".print(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +37,9 @@ use trie_db::{Trie, TrieMut};
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use frame_support::{
|
||||
dispatch::RawOrigin,
|
||||
parameter_types,
|
||||
traits::{ConstU32, ConstU64, CrateVersion, KeyOwnerProofSystem},
|
||||
traits::{CallerTrait, ConstU32, ConstU64, CrateVersion, KeyOwnerProofSystem},
|
||||
weights::{RuntimeDbWeight, Weight},
|
||||
};
|
||||
use frame_system::limits::{BlockLength, BlockWeights};
|
||||
@@ -119,7 +120,7 @@ pub fn native_version() -> NativeVersion {
|
||||
}
|
||||
|
||||
/// Calls in transactions.
|
||||
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)]
|
||||
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
|
||||
pub struct Transfer {
|
||||
pub from: AccountId,
|
||||
pub to: AccountId,
|
||||
@@ -150,7 +151,7 @@ impl Transfer {
|
||||
}
|
||||
|
||||
/// Extrinsic for test-runtime.
|
||||
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)]
|
||||
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
|
||||
pub enum Extrinsic {
|
||||
AuthoritiesChange(Vec<AuthorityId>),
|
||||
Transfer {
|
||||
@@ -446,11 +447,22 @@ impl GetRuntimeBlockType for Runtime {
|
||||
#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)]
|
||||
pub struct RuntimeOrigin;
|
||||
|
||||
impl From<frame_system::Origin<Runtime>> for RuntimeOrigin {
|
||||
fn from(_o: frame_system::Origin<Runtime>) -> Self {
|
||||
impl From<RawOrigin<<Runtime as frame_system::Config>::AccountId>> for RuntimeOrigin {
|
||||
fn from(_: RawOrigin<<Runtime as frame_system::Config>::AccountId>) -> Self {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
}
|
||||
|
||||
impl CallerTrait<<Runtime as frame_system::Config>::AccountId> for RuntimeOrigin {
|
||||
fn into_system(self) -> Option<RawOrigin<<Runtime as frame_system::Config>::AccountId>> {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
|
||||
fn as_system_ref(&self) -> Option<&RawOrigin<<Runtime as frame_system::Config>::AccountId>> {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RuntimeOrigin> for Result<frame_system::Origin<Runtime>, RuntimeOrigin> {
|
||||
fn from(_origin: RuntimeOrigin) -> Result<frame_system::Origin<Runtime>, RuntimeOrigin> {
|
||||
unimplemented!("Not required in tests!")
|
||||
@@ -482,6 +494,10 @@ impl frame_support::traits::OriginTrait for RuntimeOrigin {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
|
||||
fn into_caller(self) -> Self::PalletsOrigin {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
|
||||
fn try_with_caller<R>(
|
||||
self,
|
||||
_f: impl FnOnce(Self::PalletsOrigin) -> Result<R, Self::PalletsOrigin>,
|
||||
@@ -501,6 +517,9 @@ impl frame_support::traits::OriginTrait for RuntimeOrigin {
|
||||
fn as_signed(self) -> Option<Self::AccountId> {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
fn as_system_ref(&self) -> Option<&RawOrigin<Self::AccountId>> {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
|
||||
@@ -583,6 +602,12 @@ parameter_types! {
|
||||
BlockWeights::with_sensible_defaults(Weight::from_ref_time(4 * 1024 * 1024), Perbill::from_percent(75));
|
||||
}
|
||||
|
||||
impl From<frame_system::Call<Runtime>> for Extrinsic {
|
||||
fn from(_: frame_system::Call<Runtime>) -> Self {
|
||||
unimplemented!("Not required in tests!")
|
||||
}
|
||||
}
|
||||
|
||||
impl frame_system::Config for Runtime {
|
||||
type BaseCallFilter = frame_support::traits::Everything;
|
||||
type BlockWeights = RuntimeBlockWeights;
|
||||
|
||||
Reference in New Issue
Block a user