diff --git a/substrate/frame/conviction-voting/src/types.rs b/substrate/frame/conviction-voting/src/types.rs index 8f4f3697e976617a8f537a44a2a04d276004bd69..d6051dff6256904cddd9be5b39ef97c0e9c2d07f 100644 --- a/substrate/frame/conviction-voting/src/types.rs +++ b/substrate/frame/conviction-voting/src/types.rs @@ -93,6 +93,9 @@ impl< let ayes = approval.mul_ceil(support); Self { ayes, nays: support - ayes, support, dummy: PhantomData } } + + #[cfg(feature = "runtime-benchmarks")] + fn setup(_: Class, _: Perbill) {} } impl< diff --git a/substrate/frame/ranked-collective/src/lib.rs b/substrate/frame/ranked-collective/src/lib.rs index 7ea43a9017445d506f2ffc9711f0f217650659a5..79910c259a7cdfe159b1afb68bf0759d861e7dc2 100644 --- a/substrate/frame/ranked-collective/src/lib.rs +++ b/substrate/frame/ranked-collective/src/lib.rs @@ -85,16 +85,16 @@ pub type Votes = u32; Decode, MaxEncodedLen, )] -#[scale_info(skip_type_params(M))] +#[scale_info(skip_type_params(T, I, M))] #[codec(mel_bound())] -pub struct Tally<M: GetMaxVoters> { +pub struct Tally<T, I, M: GetMaxVoters> { bare_ayes: MemberIndex, ayes: Votes, nays: Votes, - dummy: PhantomData<M>, + dummy: PhantomData<(T, I, M)>, } -impl<M: GetMaxVoters> Tally<M> { +impl<T: Config<I>, I: 'static, M: GetMaxVoters> Tally<T, I, M> { pub fn from_parts(bare_ayes: MemberIndex, ayes: Votes, nays: Votes) -> Self { Tally { bare_ayes, ayes, nays, dummy: PhantomData } } @@ -107,10 +107,10 @@ impl<M: GetMaxVoters> Tally<M> { // All functions of VoteTally now include the class as a param. -pub type TallyOf<T, I = ()> = Tally<Pallet<T, I>>; +pub type TallyOf<T, I = ()> = Tally<T, I, Pallet<T, I>>; pub type PollIndexOf<T, I = ()> = <<T as Config<I>>::Polls as Polling<TallyOf<T, I>>>::Index; -impl<M: GetMaxVoters> VoteTally<Votes, Rank> for Tally<M> { +impl<T: Config<I>, I: 'static, M: GetMaxVoters> VoteTally<Votes, Rank> for Tally<T, I, M> { fn new(_: Rank) -> Self { Self { bare_ayes: 0, ayes: 0, nays: 0, dummy: PhantomData } } @@ -143,6 +143,20 @@ impl<M: GetMaxVoters> VoteTally<Votes, Rank> for Tally<M> { let nays = ((ayes as u64) * 1_000_000_000u64 / approval.deconstruct() as u64) as u32 - ayes; Self { bare_ayes: ayes, ayes, nays, dummy: PhantomData } } + + #[cfg(feature = "runtime-benchmarks")] + fn setup(class: Rank, granularity: Perbill) { + if M::get_max_voters(class) == 0 { + let max_voters = granularity.saturating_reciprocal_mul(1u32); + for i in 0..max_voters { + let who: T::AccountId = + frame_benchmarking::account("ranked_collective_benchmarking", i, 0); + crate::Pallet::<T, I>::do_add_member_to_rank(who, class) + .expect("could not add members for benchmarks"); + } + assert_eq!(M::get_max_voters(class), max_voters); + } + } } /// Record needed for every member. @@ -241,6 +255,19 @@ impl<T: Config<I>, I: 'static, const MIN_RANK: u16> EnsureOrigin<T::Origin> let who = IndexToId::<T, I>::get(MIN_RANK, 0).ok_or(())?; Ok(frame_system::RawOrigin::Signed(who).into()) } + + #[cfg(feature = "runtime-benchmarks")] + fn successful_origin() -> T::Origin { + match Self::try_successful_origin() { + Ok(o) => o, + Err(()) => { + let who: T::AccountId = frame_benchmarking::whitelisted_caller(); + crate::Pallet::<T, I>::do_add_member_to_rank(who.clone(), MIN_RANK) + .expect("failed to add ranked member"); + frame_system::RawOrigin::Signed(who).into() + }, + } + } } /// Guard to ensure that the given origin is a member of the collective. The account ID of the @@ -264,6 +291,19 @@ impl<T: Config<I>, I: 'static, const MIN_RANK: u16> EnsureOrigin<T::Origin> let who = IndexToId::<T, I>::get(MIN_RANK, 0).ok_or(())?; Ok(frame_system::RawOrigin::Signed(who).into()) } + + #[cfg(feature = "runtime-benchmarks")] + fn successful_origin() -> T::Origin { + match Self::try_successful_origin() { + Ok(o) => o, + Err(()) => { + let who: T::AccountId = frame_benchmarking::whitelisted_caller(); + crate::Pallet::<T, I>::do_add_member_to_rank(who.clone(), MIN_RANK) + .expect("failed to add ranked member"); + frame_system::RawOrigin::Signed(who).into() + }, + } + } } /// Guard to ensure that the given origin is a member of the collective. The pair of including both @@ -287,6 +327,19 @@ impl<T: Config<I>, I: 'static, const MIN_RANK: u16> EnsureOrigin<T::Origin> let who = IndexToId::<T, I>::get(MIN_RANK, 0).ok_or(())?; Ok(frame_system::RawOrigin::Signed(who).into()) } + + #[cfg(feature = "runtime-benchmarks")] + fn successful_origin() -> T::Origin { + match Self::try_successful_origin() { + Ok(o) => o, + Err(()) => { + let who: T::AccountId = frame_benchmarking::whitelisted_caller(); + crate::Pallet::<T, I>::do_add_member_to_rank(who.clone(), MIN_RANK) + .expect("failed to add ranked member"); + frame_system::RawOrigin::Signed(who).into() + }, + } + } } #[frame_support::pallet] @@ -415,17 +468,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::add_member())] pub fn add_member(origin: OriginFor<T>, who: T::AccountId) -> DispatchResult { let _ = T::PromoteOrigin::ensure_origin(origin)?; - ensure!(!Members::<T, I>::contains_key(&who), Error::<T, I>::AlreadyMember); - let index = MemberCount::<T, I>::get(0); - let count = index.checked_add(1).ok_or(Overflow)?; - - Members::<T, I>::insert(&who, MemberRecord { rank: 0 }); - IdToIndex::<T, I>::insert(0, &who, index); - IndexToId::<T, I>::insert(0, index, &who); - MemberCount::<T, I>::insert(0, count); - Self::deposit_event(Event::MemberAdded { who }); - - Ok(()) + Self::do_add_member(who) } /// Increment the rank of an existing member by one. @@ -437,17 +480,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::promote_member(0))] pub fn promote_member(origin: OriginFor<T>, who: T::AccountId) -> DispatchResult { let max_rank = T::PromoteOrigin::ensure_origin(origin)?; - let record = Self::ensure_member(&who)?; - let rank = record.rank.checked_add(1).ok_or(Overflow)?; - ensure!(max_rank >= rank, Error::<T, I>::NoPermission); - let index = MemberCount::<T, I>::get(rank); - MemberCount::<T, I>::insert(rank, index.checked_add(1).ok_or(Overflow)?); - IdToIndex::<T, I>::insert(rank, &who, index); - IndexToId::<T, I>::insert(rank, index, &who); - Members::<T, I>::insert(&who, MemberRecord { rank }); - Self::deposit_event(Event::RankChanged { who, rank }); - - Ok(()) + Self::do_promote_member(who, Some(max_rank)) } /// Decrement the rank of an existing member by one. If the member is already at rank zero, @@ -626,5 +659,53 @@ pub mod pallet { MemberCount::<T, I>::mutate(rank, |r| r.saturating_dec()); Ok(()) } + + /// Adds a member into the ranked collective at level 0. + /// + /// No origin checks are executed. + pub fn do_add_member(who: T::AccountId) -> DispatchResult { + ensure!(!Members::<T, I>::contains_key(&who), Error::<T, I>::AlreadyMember); + let index = MemberCount::<T, I>::get(0); + let count = index.checked_add(1).ok_or(Overflow)?; + + Members::<T, I>::insert(&who, MemberRecord { rank: 0 }); + IdToIndex::<T, I>::insert(0, &who, index); + IndexToId::<T, I>::insert(0, index, &who); + MemberCount::<T, I>::insert(0, count); + Self::deposit_event(Event::MemberAdded { who }); + Ok(()) + } + + /// Promotes a member in the ranked collective into the next role. + /// + /// A `maybe_max_rank` may be provided to check that the member does not get promoted beyond + /// a certain rank. Is `None` is provided, then the rank will be incremented without checks. + pub fn do_promote_member( + who: T::AccountId, + maybe_max_rank: Option<Rank>, + ) -> DispatchResult { + let record = Self::ensure_member(&who)?; + let rank = record.rank.checked_add(1).ok_or(Overflow)?; + if let Some(max_rank) = maybe_max_rank { + ensure!(max_rank >= rank, Error::<T, I>::NoPermission); + } + let index = MemberCount::<T, I>::get(rank); + MemberCount::<T, I>::insert(rank, index.checked_add(1).ok_or(Overflow)?); + IdToIndex::<T, I>::insert(rank, &who, index); + IndexToId::<T, I>::insert(rank, index, &who); + Members::<T, I>::insert(&who, MemberRecord { rank }); + Self::deposit_event(Event::RankChanged { who, rank }); + Ok(()) + } + + /// Add a member to the rank collective, and continue to promote them until a certain rank + /// is reached. + pub fn do_add_member_to_rank(who: T::AccountId, rank: Rank) -> DispatchResult { + Self::do_add_member(who.clone())?; + for _ in 0..rank { + Self::do_promote_member(who.clone(), None)?; + } + Ok(()) + } } } diff --git a/substrate/frame/ranked-collective/src/tests.rs b/substrate/frame/ranked-collective/src/tests.rs index 4344a1be730fb7001f4b31ed7f771175e5f51fe2..530388d83f3c454c096621246534c6c18a967781 100644 --- a/substrate/frame/ranked-collective/src/tests.rs +++ b/substrate/frame/ranked-collective/src/tests.rs @@ -455,3 +455,20 @@ fn ensure_ranked_works() { assert_eq!(Rank4::try_origin(Origin::signed(3)).unwrap_err().as_signed().unwrap(), 3); }); } + +#[test] +fn do_add_member_to_rank_works() { + new_test_ext().execute_with(|| { + let max_rank = 9u16; + assert_ok!(Club::do_add_member_to_rank(69, max_rank / 2)); + assert_ok!(Club::do_add_member_to_rank(1337, max_rank)); + for i in 0..=max_rank { + if i <= max_rank / 2 { + assert_eq!(member_count(i), 2); + } else { + assert_eq!(member_count(i), 1); + } + } + assert_eq!(member_count(max_rank + 1), 0); + }) +} diff --git a/substrate/frame/referenda/src/benchmarking.rs b/substrate/frame/referenda/src/benchmarking.rs index b9c64a61f510d890ea5e4cb77b7a1c0275919aaf..4a64a9aa03b77a2a21c822bdb139f95843a7642b 100644 --- a/substrate/frame/referenda/src/benchmarking.rs +++ b/substrate/frame/referenda/src/benchmarking.rs @@ -23,6 +23,7 @@ use assert_matches::assert_matches; use frame_benchmarking::{account, benchmarks_instance_pallet, whitelist_account}; use frame_support::{ assert_ok, + dispatch::UnfilteredDispatchable, traits::{Currency, EnsureOrigin}, }; use frame_system::RawOrigin; @@ -41,17 +42,20 @@ fn funded_account<T: Config<I>, I: 'static>(name: &'static str, index: u32) -> T caller } -fn create_referendum<T: Config<I>, I: 'static>() -> (T::AccountId, ReferendumIndex) { - let caller = funded_account::<T, I>("caller", 0); - whitelist_account!(caller); - assert_ok!(Referenda::<T, I>::submit( - RawOrigin::Signed(caller.clone()).into(), - Box::new(RawOrigin::Root.into()), - T::Hashing::hash_of(&0), - DispatchTime::After(0u32.into()) - )); +fn create_referendum<T: Config<I>, I: 'static>() -> (T::Origin, ReferendumIndex) { + let origin: T::Origin = T::SubmitOrigin::successful_origin(); + if let Ok(caller) = frame_system::ensure_signed(origin.clone()) { + T::Currency::make_free_balance_be(&caller, BalanceOf::<T, I>::max_value()); + whitelist_account!(caller); + } + + let proposal_origin = Box::new(RawOrigin::Root.into()); + let proposal_hash = T::Hashing::hash_of(&0); + let enactment_moment = DispatchTime::After(0u32.into()); + let call = Call::<T, I>::submit { proposal_origin, proposal_hash, enactment_moment }; + assert_ok!(call.dispatch_bypass_filter(origin.clone())); let index = ReferendumCount::<T, I>::get() - 1; - (caller, index) + (origin, index) } fn place_deposit<T: Config<I>, I: 'static>(index: ReferendumIndex) { @@ -72,7 +76,7 @@ fn fill_queue<T: Config<I>, I: 'static>( // First, create enough other referendums to fill the track. let mut others = vec![]; for _ in 0..info::<T, I>(index).max_deciding { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); others.push(index); } @@ -80,7 +84,7 @@ fn fill_queue<T: Config<I>, I: 'static>( // We will also need enough referenda which are queued and passing, we want `MaxQueued - 1` // in order to force the maximum amount of work to insert ours into the queue. for _ in spaces..T::MaxQueued::get() { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); make_passing_after::<T, I>(index, Perbill::from_percent(pass_after)); others.push(index); @@ -113,6 +117,7 @@ fn make_passing_after<T: Config<I>, I: 'static>(index: ReferendumIndex, period_p .saturating_add(Perbill::from_percent(1)); Referenda::<T, I>::access_poll(index, |status| { if let PollStatus::Ongoing(tally, class) = status { + T::Tally::setup(class, Perbill::from_rational(1u32, 1000u32)); *tally = T::Tally::from_requirements(support, approval, class); } }); @@ -121,6 +126,7 @@ fn make_passing_after<T: Config<I>, I: 'static>(index: ReferendumIndex, period_p fn make_passing<T: Config<I>, I: 'static>(index: ReferendumIndex) { Referenda::<T, I>::access_poll(index, |status| { if let PollStatus::Ongoing(tally, class) = status { + T::Tally::setup(class, Perbill::from_rational(1u32, 1000u32)); *tally = T::Tally::unanimity(class); } }); @@ -129,6 +135,7 @@ fn make_passing<T: Config<I>, I: 'static>(index: ReferendumIndex) { fn make_failing<T: Config<I>, I: 'static>(index: ReferendumIndex) { Referenda::<T, I>::access_poll(index, |status| { if let PollStatus::Ongoing(tally, class) = status { + T::Tally::setup(class, Perbill::from_rational(1u32, 1000u32)); *tally = T::Tally::rejection(class); } }); @@ -181,10 +188,13 @@ fn is_not_confirming<T: Config<I>, I: 'static>(index: ReferendumIndex) -> bool { benchmarks_instance_pallet! { submit { - let caller = funded_account::<T, I>("caller", 0); - whitelist_account!(caller); - }: _( - RawOrigin::Signed(caller), + let origin: T::Origin = T::SubmitOrigin::successful_origin(); + if let Ok(caller) = frame_system::ensure_signed(origin.clone()) { + T::Currency::make_free_balance_be(&caller, BalanceOf::<T, I>::max_value()); + whitelist_account!(caller); + } + }: _<T::Origin>( + origin, Box::new(RawOrigin::Root.into()), T::Hashing::hash_of(&0), DispatchTime::After(0u32.into()) @@ -194,60 +204,62 @@ benchmarks_instance_pallet! { } place_decision_deposit_preparing { - let (caller, index) = create_referendum::<T, I>(); - }: place_decision_deposit(RawOrigin::Signed(caller), index) + let (origin, index) = create_referendum::<T, I>(); + }: place_decision_deposit<T::Origin>(origin, index) verify { assert!(Referenda::<T, I>::ensure_ongoing(index).unwrap().decision_deposit.is_some()); } place_decision_deposit_queued { - let (caller, index) = create_referendum::<T, I>(); + let (origin, index) = create_referendum::<T, I>(); fill_queue::<T, I>(index, 1, 90); - }: place_decision_deposit(RawOrigin::Signed(caller), index) + }: place_decision_deposit<T::Origin>(origin, index) verify { let track = Referenda::<T, I>::ensure_ongoing(index).unwrap().track; assert_eq!(TrackQueue::<T, I>::get(&track).len() as u32, T::MaxQueued::get()); - assert_eq!(TrackQueue::<T, I>::get(&track)[0], (index, 0u32.into())); + assert!(TrackQueue::<T, I>::get(&track).contains(&(index, 0u32.into()))); } place_decision_deposit_not_queued { - let (caller, index) = create_referendum::<T, I>(); + let (origin, index) = create_referendum::<T, I>(); fill_queue::<T, I>(index, 0, 90); - }: place_decision_deposit(RawOrigin::Signed(caller), index) - verify { let track = Referenda::<T, I>::ensure_ongoing(index).unwrap().track; assert_eq!(TrackQueue::<T, I>::get(&track).len() as u32, T::MaxQueued::get()); assert!(TrackQueue::<T, I>::get(&track).into_iter().all(|(i, _)| i != index)); + }: place_decision_deposit<T::Origin>(origin, index) + verify { + assert_eq!(TrackQueue::<T, I>::get(&track).len() as u32, T::MaxQueued::get()); + assert!(TrackQueue::<T, I>::get(&track).into_iter().all(|(i, _)| i != index)); } place_decision_deposit_passing { - let (caller, index) = create_referendum::<T, I>(); + let (origin, index) = create_referendum::<T, I>(); skip_prepare_period::<T, I>(index); make_passing::<T, I>(index); - }: place_decision_deposit(RawOrigin::Signed(caller), index) + }: place_decision_deposit<T::Origin>(origin, index) verify { assert!(is_confirming::<T, I>(index)); } place_decision_deposit_failing { - let (caller, index) = create_referendum::<T, I>(); + let (origin, index) = create_referendum::<T, I>(); skip_prepare_period::<T, I>(index); - }: place_decision_deposit(RawOrigin::Signed(caller), index) + }: place_decision_deposit<T::Origin>(origin, index) verify { assert!(is_not_confirming::<T, I>(index)); } refund_decision_deposit { - let (caller, index) = create_referendum::<T, I>(); + let (origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); assert_ok!(Referenda::<T, I>::cancel(T::CancelOrigin::successful_origin(), index)); - }: _(RawOrigin::Signed(caller), index) + }: _<T::Origin>(origin, index) verify { assert_matches!(ReferendumInfoFor::<T, I>::get(index), Some(ReferendumInfo::Cancelled(_, _, None))); } cancel { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); }: _<T::Origin>(T::CancelOrigin::successful_origin(), index) verify { @@ -255,7 +267,7 @@ benchmarks_instance_pallet! { } kill { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); }: _<T::Origin>(T::KillOrigin::successful_origin(), index) verify { @@ -263,7 +275,7 @@ benchmarks_instance_pallet! { } one_fewer_deciding_queue_empty { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); skip_prepare_period::<T, I>(index); nudge::<T, I>(index); @@ -276,7 +288,7 @@ benchmarks_instance_pallet! { } one_fewer_deciding_failing { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); // No spaces free in the queue. let queued = fill_queue::<T, I>(index, 0, 90); let track = Referenda::<T, I>::ensure_ongoing(index).unwrap().track; @@ -295,7 +307,7 @@ benchmarks_instance_pallet! { } one_fewer_deciding_passing { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); // No spaces free in the queue. let queued = fill_queue::<T, I>(index, 0, 0); let track = Referenda::<T, I>::ensure_ongoing(index).unwrap().track; @@ -306,16 +318,16 @@ benchmarks_instance_pallet! { verify { assert_eq!(DecidingCount::<T, I>::get(&track), deciding_count); assert_eq!(TrackQueue::<T, I>::get(&track).len() as u32, T::MaxQueued::get() - 1); - assert!(queued.into_iter().skip(1).all(|i| Referenda::<T, I>::ensure_ongoing(i) + assert!(queued.into_iter().skip(1).filter(|i| Referenda::<T, I>::ensure_ongoing(*i) .unwrap() .deciding - .map_or(true, |d| d.confirming.is_some()) - )); + .map_or(false, |d| d.confirming.is_some()) + ).count() == 1); } nudge_referendum_requeued_insertion { // First create our referendum and place the deposit. It will be failing. - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); fill_queue::<T, I>(index, 0, 90); @@ -336,7 +348,7 @@ benchmarks_instance_pallet! { nudge_referendum_requeued_slide { // First create our referendum and place the deposit. It will be failing. - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); fill_queue::<T, I>(index, 1, 90); @@ -362,7 +374,7 @@ benchmarks_instance_pallet! { // insertion at the beginning. // First create our referendum and place the deposit. It will be failing. - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); fill_queue::<T, I>(index, 1, 0); @@ -379,7 +391,7 @@ benchmarks_instance_pallet! { nudge_referendum_not_queued { // First create our referendum and place the deposit. It will be failing. - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); fill_queue::<T, I>(index, 0, 0); @@ -395,7 +407,7 @@ benchmarks_instance_pallet! { } nudge_referendum_no_deposit { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); skip_prepare_period::<T, I>(index); }: nudge_referendum(RawOrigin::Root, index) verify { @@ -404,7 +416,7 @@ benchmarks_instance_pallet! { } nudge_referendum_preparing { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); }: nudge_referendum(RawOrigin::Root, index) verify { @@ -413,7 +425,7 @@ benchmarks_instance_pallet! { } nudge_referendum_timed_out { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); skip_timeout_period::<T, I>(index); }: nudge_referendum(RawOrigin::Root, index) verify { @@ -422,7 +434,7 @@ benchmarks_instance_pallet! { } nudge_referendum_begin_deciding_failing { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); skip_prepare_period::<T, I>(index); }: nudge_referendum(RawOrigin::Root, index) @@ -431,7 +443,7 @@ benchmarks_instance_pallet! { } nudge_referendum_begin_deciding_passing { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); make_passing::<T, I>(index); skip_prepare_period::<T, I>(index); @@ -441,7 +453,7 @@ benchmarks_instance_pallet! { } nudge_referendum_begin_confirming { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); skip_prepare_period::<T, I>(index); nudge::<T, I>(index); @@ -453,7 +465,7 @@ benchmarks_instance_pallet! { } nudge_referendum_end_confirming { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); skip_prepare_period::<T, I>(index); make_passing::<T, I>(index); @@ -466,7 +478,7 @@ benchmarks_instance_pallet! { } nudge_referendum_continue_not_confirming { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); skip_prepare_period::<T, I>(index); nudge::<T, I>(index); @@ -480,7 +492,7 @@ benchmarks_instance_pallet! { } nudge_referendum_continue_confirming { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); make_passing::<T, I>(index); skip_prepare_period::<T, I>(index); @@ -493,7 +505,7 @@ benchmarks_instance_pallet! { } nudge_referendum_approved { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); skip_prepare_period::<T, I>(index); make_passing::<T, I>(index); @@ -506,7 +518,7 @@ benchmarks_instance_pallet! { } nudge_referendum_rejected { - let (_caller, index) = create_referendum::<T, I>(); + let (_origin, index) = create_referendum::<T, I>(); place_deposit::<T, I>(index); skip_prepare_period::<T, I>(index); make_failing::<T, I>(index); diff --git a/substrate/frame/referenda/src/mock.rs b/substrate/frame/referenda/src/mock.rs index 1a24911603990e309969405c6a7292e1c8c62999..dbe22cd562349f113ea9f302a5b09ff6dd5d8c71 100644 --- a/substrate/frame/referenda/src/mock.rs +++ b/substrate/frame/referenda/src/mock.rs @@ -289,6 +289,9 @@ impl<Class> VoteTally<u32, Class> for Tally { let nays = ((ayes as u64) * 1_000_000_000u64 / approval.deconstruct() as u64) as u32 - ayes; Self { ayes, nays } } + + #[cfg(feature = "runtime-benchmarks")] + fn setup(_: Class, _: Perbill) {} } pub fn set_balance_proposal(value: u64) -> Vec<u8> { diff --git a/substrate/frame/support/src/traits/voting.rs b/substrate/frame/support/src/traits/voting.rs index b5e7d27073895660b0f70eae167640b41676528c..49ae3163d0cd1413ac876676203d13828aebdd02 100644 --- a/substrate/frame/support/src/traits/voting.rs +++ b/substrate/frame/support/src/traits/voting.rs @@ -106,6 +106,19 @@ pub trait VoteTally<Votes, Class> { fn rejection(class: Class) -> Self; #[cfg(feature = "runtime-benchmarks")] fn from_requirements(support: Perbill, approval: Perbill, class: Class) -> Self; + #[cfg(feature = "runtime-benchmarks")] + /// A function that should be called before any use of the `runtime-benchmarks` gated functions + /// of the `VoteTally` trait. + /// + /// Should be used to set up any needed state in a Pallet which implements `VoteTally` so that + /// benchmarks that execute will complete successfully. `class` can be used to set up a + /// particular class of voters, and `granularity` is used to determine the weight of one vote + /// relative to total unanimity. + /// + /// For example, in the case where there are a number of unique voters, and each voter has equal + /// voting weight, a granularity of `Perbill::from_rational(1, 1000)` should create `1_000` + /// users. + fn setup(class: Class, granularity: Perbill); } pub enum PollStatus<Tally, Moment, Class> { None,