From dc42ba4a96aeffeb330bf0cb2051ea472a2aaa85 Mon Sep 17 00:00:00 2001 From: girazoki Date: Wed, 18 Oct 2023 12:17:28 +0200 Subject: [PATCH] events for inflation rewards and benchmark for rewards --- pallets/inflation-rewards/src/lib.rs | 53 ++++++++++++++++++----- pallets/invulnerables/src/benchmarking.rs | 45 ++++++++++++++++--- pallets/invulnerables/src/lib.rs | 25 ++++++++--- pallets/invulnerables/src/mock.rs | 2 + pallets/invulnerables/src/weights.rs | 33 ++++++++++++++ pallets/pooled-staking/src/pools.rs | 6 +-- primitives/traits/src/lib.rs | 6 +++ runtime/dancebox/src/lib.rs | 3 ++ 8 files changed, 146 insertions(+), 27 deletions(-) diff --git a/pallets/inflation-rewards/src/lib.rs b/pallets/inflation-rewards/src/lib.rs index 89352bd65..f197ce75e 100644 --- a/pallets/inflation-rewards/src/lib.rs +++ b/pallets/inflation-rewards/src/lib.rs @@ -117,7 +117,6 @@ pub mod pallet { // Let the runtime handle the non-staking part T::OnUnbalanced::on_unbalanced(not_distributed_rewards.merge(total_reminder)); - // Reward orchestrator chain author weight += Self::reward_orchestrator_author(); weight @@ -126,6 +125,9 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { + /// Overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type Currency: Inspect + Balanced; type ContainerChains: GetCurrentContainerChains; @@ -152,6 +154,22 @@ pub mod pallet { type RewardsPortion: Get; } + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Rewarding orchestrator author + RewardedOrchestrator { + account_id: T::AccountId, + balance: BalanceOf, + }, + /// Rewarding container author + RewardedContainer { + account_id: T::AccountId, + para_id: ParaId, + balance: BalanceOf, + }, + } + /// Container chains to reward per block #[pallet::storage] #[pallet::getter(fn container_chains_to_reward)] @@ -175,7 +193,7 @@ pub mod pallet { if let Some(chains_to_reward) = ChainsToReward::::get() { total_weight += T::DbWeight::get().reads(1); match T::StakingRewardsDistributor::distribute_rewards( - orchestrator_author, + orchestrator_author.clone(), T::Currency::withdraw( &T::PendingRewardsAccount::get(), chains_to_reward.rewards_per_chain, @@ -185,14 +203,19 @@ pub mod pallet { ) .unwrap_or(CreditOf::::zero()), ) { - Ok(frame_support::dispatch::PostDispatchInfo { - actual_weight: Some(weight), - .. - }) => total_weight += weight, + Ok(frame_support::dispatch::PostDispatchInfo { actual_weight, .. }) => { + Self::deposit_event(Event::RewardedOrchestrator { + account_id: orchestrator_author, + balance: chains_to_reward.rewards_per_chain, + }); + + if let Some(weight) = actual_weight { + total_weight += weight + } + } Err(e) => { log::debug!("Fail to distribute rewards: {:?}", e) } - _ => {} } } else { panic!("ChainsToReward not filled"); @@ -207,6 +230,7 @@ pub mod pallet { // There will be no additional check other than checking if we have already // rewarded this author for **in this tanssi block** // Any additional check should be done in the calling function +// TODO: consider passing a vector here impl AuthorNotingHook for Pallet { fn on_container_author_noted( author: &T::AccountId, @@ -230,14 +254,19 @@ impl AuthorNotingHook for Pallet { ) .unwrap_or(CreditOf::::zero()), ) { - Ok(frame_support::dispatch::PostDispatchInfo { - actual_weight: Some(weight), - .. - }) => total_weight += weight, + Ok(frame_support::dispatch::PostDispatchInfo { actual_weight, .. }) => { + Self::deposit_event(Event::RewardedContainer { + account_id: author.clone(), + balance: container_chains_to_reward.rewards_per_chain, + para_id, + }); + if let Some(weight) = actual_weight { + total_weight += weight + } + } Err(e) => { log::debug!("Fail to distribute rewards: {:?}", e) } - _ => {} } // we remove the para id from container-chains to reward // this makes sure we dont reward it twice in the same block diff --git a/pallets/invulnerables/src/benchmarking.rs b/pallets/invulnerables/src/benchmarking.rs index f1535df69..a238f9e91 100644 --- a/pallets/invulnerables/src/benchmarking.rs +++ b/pallets/invulnerables/src/benchmarking.rs @@ -22,17 +22,18 @@ use super::*; #[allow(unused)] use crate::Pallet as InvulnerablesPallet; +use sp_runtime::traits::AtLeast32BitUnsigned; use { frame_benchmarking::{account, impl_benchmark_test_suite, v2::*, BenchmarkError}, frame_support::{ pallet_prelude::*, - traits::{Currency, EnsureOrigin, Get}, + traits::{tokens::fungible::Balanced, Currency, EnsureOrigin, Get}, }, frame_system::{EventRecord, RawOrigin}, pallet_session::{self as session, SessionManager}, sp_std::prelude::*, + tp_traits::DistributeRewards, }; - const SEED: u32 = 0; fn assert_last_event(generic_event: ::RuntimeEvent) { @@ -94,7 +95,18 @@ fn invulnerables< invulnerables.into_iter().map(|(who, _)| who).collect() } -#[benchmarks(where T: session::Config + pallet_balances::Config)] +pub type BalanceOf = + <::Currency as frame_support::traits::fungible::Inspect< + ::AccountId, + >>::Balance; + +pub(crate) fn currency_issue( + amount: BalanceOf, +) -> crate::CreditOf { + <::Currency as Balanced>::issue(amount) +} + +#[benchmarks(where T: session::Config + pallet_balances::Config, BalanceOf: AtLeast32BitUnsigned)] mod benchmarks { use super::*; @@ -106,16 +118,14 @@ mod benchmarks { T::UpdateOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let new_invulnerables = invulnerables::(b); - let mut sorted_new_invulnerables = new_invulnerables.clone(); - sorted_new_invulnerables.sort(); #[extrinsic_call] - _(origin as T::RuntimeOrigin, new_invulnerables); + _(origin as T::RuntimeOrigin, new_invulnerables.clone()); // assert that it comes out sorted assert_last_event::( Event::NewInvulnerables { - invulnerables: sorted_new_invulnerables, + invulnerables: new_invulnerables, } .into(), ); @@ -196,6 +206,27 @@ mod benchmarks { Ok(()) } + #[benchmark] + fn reward_invulnerable( + b: Linear<{ 1 }, { T::MaxInvulnerables::get() }>, + ) -> Result<(), BenchmarkError> where { + let mut invulnerables = invulnerables::(b); + invulnerables.sort(); + let invulnerables: frame_support::BoundedVec<_, T::MaxInvulnerables> = + frame_support::BoundedVec::try_from(invulnerables).unwrap(); + >::put(invulnerables); + let to_reward = >::get().first().unwrap().clone(); + // Create new supply for rewards + let new_supply = currency_issue::(1000u32.into()); + #[block] + { + let _ = InvulnerableRewardDistribution::::distribute_rewards( + to_reward, new_supply, + ); + } + + Ok(()) + } impl_benchmark_test_suite!( InvulnerablesPallet, crate::mock::new_test_ext(), diff --git a/pallets/invulnerables/src/lib.rs b/pallets/invulnerables/src/lib.rs index 8d61574b4..7f74e2601 100644 --- a/pallets/invulnerables/src/lib.rs +++ b/pallets/invulnerables/src/lib.rs @@ -41,6 +41,8 @@ pub mod weights; #[frame_support::pallet] pub mod pallet { pub use crate::weights::WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + use frame_support::traits::Currency; use { frame_support::{ dispatch::DispatchResultWithPostInfo, @@ -92,6 +94,10 @@ pub mod pallet { /// The weight information of this pallet. type WeightInfo: WeightInfo; + + #[cfg(feature = "runtime-benchmarks")] + type Currency: Currency + + frame_support::traits::fungible::Balanced; } #[pallet::pallet] @@ -290,6 +296,9 @@ pub struct InvulnerableRewardDistribution( PhantomData<(Runtime, Currency, Fallback)>, ); +use frame_support::pallet_prelude::Weight; +use sp_runtime::traits::Get; + type CreditOf = frame_support::traits::fungible::Credit<::AccountId, Currency>; pub type AccountIdOf = ::AccountId; @@ -306,12 +315,18 @@ where rewarded: AccountIdOf, amount: CreditOf, ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo { + let mut total_weight = Weight::zero(); + // weight to read invulnerables + total_weight += Runtime::DbWeight::get().reads(1); if !Invulnerables::::get().contains(&rewarded) { - return Fallback::distribute_rewards(rewarded, amount); + let post_info = Fallback::distribute_rewards(rewarded, amount)?; + if let Some(weight) = post_info.actual_weight { + total_weight += weight; + } + } else { + Currency::resolve(&rewarded, amount).map_err(|_| TokenError::NotExpendable)?; + total_weight += Runtime::WeightInfo::reward_invulnerable() } - - Currency::resolve(&rewarded, amount).map_err(|_| TokenError::NotExpendable)?; - - Ok(().into()) + Ok(Some(total_weight).into()) } } diff --git a/pallets/invulnerables/src/mock.rs b/pallets/invulnerables/src/mock.rs index eba0d9f79..73bd16ff8 100644 --- a/pallets/invulnerables/src/mock.rs +++ b/pallets/invulnerables/src/mock.rs @@ -114,6 +114,8 @@ impl Config for Test { type CollatorIdOf = IdentityCollator; type CollatorRegistration = IsRegistered; type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type Currency = Balances; } sp_runtime::impl_opaque_keys! { diff --git a/pallets/invulnerables/src/weights.rs b/pallets/invulnerables/src/weights.rs index b5f59b518..367d83f0a 100644 --- a/pallets/invulnerables/src/weights.rs +++ b/pallets/invulnerables/src/weights.rs @@ -54,6 +54,7 @@ pub trait WeightInfo { fn add_invulnerable(_b: u32) -> Weight; fn remove_invulnerable(_b: u32) -> Weight; fn new_session(_b: u32) -> Weight; + fn reward_invulnerable() -> Weight; } /// Weight functions for `pallet_invulnerables`. @@ -120,6 +121,22 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } + + /// Storage: `Invulnerables::Invulnerables` (r:1 w:0) + /// Proof: `Invulnerables::Invulnerables` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `b` is `[1, 100]`. + fn reward_invulnerable() -> Weight { + // Proof Size summary in bytes: + // Measured: `218 + b * (33 ±0)` + // Estimated: `4687` + // Minimum execution time: 51_037_000 picoseconds. + Weight::from_parts(68_315_971, 4687) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + } // For backwards compatibility and tests @@ -187,4 +204,20 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(1)) } + /// Storage: `Invulnerables::Invulnerables` (r:1 w:0) + /// Proof: `Invulnerables::Invulnerables` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `b` is `[1, 100]`. + fn reward_invulnerable() -> Weight { + // Proof Size summary in bytes: + // Measured: `218 + b * (33 ±0)` + // Estimated: `4687` + // Minimum execution time: 51_037_000 picoseconds. + Weight::from_parts(68_315_971, 4687) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + + } diff --git a/pallets/pooled-staking/src/pools.rs b/pallets/pooled-staking/src/pools.rs index cef3fa8cd..3eb37e6b8 100644 --- a/pallets/pooled-staking/src/pools.rs +++ b/pallets/pooled-staking/src/pools.rs @@ -16,8 +16,8 @@ use { crate::{ - candidate::Candidates, Candidate, Config, CreditOf, Delegator, Error, Event, Pallet, Pools, - PoolsKey, Shares, Stake, + candidate::Candidates, weights::WeightInfo, Candidate, Config, CreditOf, Delegator, Error, + Event, Pallet, Pools, PoolsKey, Shares, Stake, }, core::marker::PhantomData, frame_support::{ @@ -472,7 +472,7 @@ pub fn distribute_rewards( T::Currency::resolve(&T::StakingAccount::get(), other_rewards) .map_err(|_| DispatchError::NoProviders)?; - Ok(().into()) + Ok(Some(T::WeightInfo::distribute_rewards()).into()) } fn distribute_rewards_inner( diff --git a/primitives/traits/src/lib.rs b/primitives/traits/src/lib.rs index 8a9b1501f..00272f7da 100644 --- a/primitives/traits/src/lib.rs +++ b/primitives/traits/src/lib.rs @@ -53,6 +53,12 @@ pub trait DistributeRewards { fn distribute_rewards(rewarded: AccountId, amount: Imbalance) -> DispatchResultWithPostInfo; } +impl DistributeRewards for () { + fn distribute_rewards(_rewarded: AccountId, _amount: Imbalance) -> DispatchResultWithPostInfo { + Ok(().into()) + } +} + /// Get the current list of container chains parachain ids. pub trait GetCurrentContainerChains { type MaxContainerChains: Get; diff --git a/runtime/dancebox/src/lib.rs b/runtime/dancebox/src/lib.rs index 7fa13d454..d5a29be0a 100644 --- a/runtime/dancebox/src/lib.rs +++ b/runtime/dancebox/src/lib.rs @@ -586,6 +586,8 @@ impl pallet_invulnerables::Config for Runtime { type CollatorIdOf = pallet_invulnerables::IdentityCollator; type CollatorRegistration = Session; type WeightInfo = pallet_invulnerables::weights::SubstrateWeight; + #[cfg(feature = "runtime-benchmarks")] + type Currency = Balances; } parameter_types! { @@ -1004,6 +1006,7 @@ impl frame_support::traits::OnUnbalanced> for OnUnba } impl pallet_inflation_rewards::Config for Runtime { + type RuntimeEvent = RuntimeEvent; type Currency = Balances; type ContainerChains = Registrar; type GetSelfChainBlockAuthor = GetSelfChainBlockAuthor;