Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use new benchmark for staking rewards #2461

Merged
merged 12 commits into from
Aug 30, 2023
112 changes: 111 additions & 1 deletion pallets/parachain-staking/src/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1618,6 +1618,116 @@ benchmarks! {
verify {
}

pay_one_collator_reward_best {
// x controls number of delegations
let x in 0..(
T::MaxTopDelegationsPerCandidate::get()
+ T::MaxBottomDelegationsPerCandidate::get() - 1
);
// y controls the number of auto-compounding delegations
let y in 0..(
T::MaxTopDelegationsPerCandidate::get()
+ T::MaxBottomDelegationsPerCandidate::get() - 1
);
// z is the number of scheduled requests per collator
let z in 0..(
T::MaxTopDelegationsPerCandidate::get()
+ T::MaxBottomDelegationsPerCandidate::get() - 1
);

use crate::{
DelayedPayout, DelayedPayouts, AtStake, CollatorSnapshot, BondWithAutoCompound, Points,
AwardedPts,
};

let mut seed = Seed::new();
let prime_candidate = create_account::<T>(
"collator",
seed.take(),
AccountBalance::MinCandidateStake,
AccountAction::JoinCandidates{ amount: Amount::All, candidate_count: 1u32 },
)?;

let mut delegations = Vec::new();
let mut col_del_count = 0u32;
let initial_delegator_balance = T::MinDelegation::get() + 100u32.into();
for i in 0..x {
let auto_compound = if i < y { Percent::from_percent(100) } else { Percent::from_percent(0) };
let delegator = create_account::<T>(
"delegator",
seed.take(),
AccountBalance::Value(initial_delegator_balance),
AccountAction::Delegate{
collator: prime_candidate.clone(),
amount: Amount::All,
auto_compound,
collator_delegation_count: col_del_count,
collator_auto_compound_delegation_count: col_del_count,
},
)?;
col_del_count += 1u32;
if i < z {
Pallet::<T>::schedule_delegator_bond_less(
RawOrigin::Signed(delegator.clone()).into(),
prime_candidate.clone(),
5u32.into(),
)?;
}

delegations.push(BondWithAutoCompound {
owner: delegator.clone(),
amount: initial_delegator_balance,
auto_compound,
});
}

let total_staked = min_candidate_stk::<T>()
+ (Into::<BalanceOf<T>>::into(x) * initial_delegator_balance);
let round_for_payout = 5;
<DelayedPayouts<T>>::insert(&round_for_payout, DelayedPayout {
round_issuance: 1000u32.into(),
total_staking_reward: total_staked,
collator_commission: Perbill::from_rational(1u32, 100u32),
});

<AtStake<T>>::insert(round_for_payout, &prime_candidate, CollatorSnapshot {
bond: 1_000u32.into(),
delegations: delegations.clone(),
total: 1_000_000u32.into(),
});

<Points<T>>::insert(round_for_payout, 100);
<AwardedPts<T>>::insert(round_for_payout, &prime_candidate, 20);

}: {
for BondWithAutoCompound {
owner,
amount,
auto_compound,
} in &delegations
{
<Pallet<T>>::mint_and_compound(
100u32.into(),
auto_compound.clone(),
prime_candidate.clone(),
owner.clone(),
);
}
}
verify {
for BondWithAutoCompound {
owner,
amount,
auto_compound,
} in &delegations
{
assert!(
T::Currency::free_balance(&owner) > initial_delegator_balance,
"delegator should have been paid in pay_one_collator_reward"
);
}
}

pay_one_collator_reward {
// y controls number of delegations, its maximum per collator is the max top delegations
let y in 0..<<T as Config>::MaxTopDelegationsPerCandidate as Get<u32>>::get();
Expand All @@ -1643,7 +1753,7 @@ benchmarks! {
)?;
total_staked += initial_stake_amount;

// generate funded collator accounts
// generate funded delegator accounts
let mut delegators: Vec<T::AccountId> = Vec::new();
for i in 0..y {
let seed = USER_SEED + i;
Expand Down
47 changes: 23 additions & 24 deletions pallets/parachain-staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1764,7 +1764,6 @@ pub mod pallet {

let collator_fee = payout_info.collator_commission;
let collator_issuance = collator_fee * payout_info.round_issuance;

if let Some((collator, state)) =
<AtStake<T>>::iter_prefix(paid_for_round).drain().next()
{
Expand All @@ -1787,6 +1786,9 @@ pub mod pallet {
let mut amt_due = total_paid;

let num_delegators = state.delegations.len();
let mut num_paid_delegations = 0u32;
let mut num_auto_compounding = 0u32;
let num_scheduled_requests = <DelegationScheduledRequests<T>>::get(&collator).len();
if state.delegations.is_empty() {
// solo collator with no delegators
extra_weight = extra_weight
Expand Down Expand Up @@ -1828,16 +1830,25 @@ pub mod pallet {
let percent = Perbill::from_rational(amount, state.total);
let due = percent * amt_due;
if !due.is_zero() {
extra_weight = extra_weight.saturating_add(Self::mint_and_compound(
nbaztec marked this conversation as resolved.
Show resolved Hide resolved
num_auto_compounding += if auto_compound.is_zero() { 0 } else { 1 };
num_paid_delegations += 1u32;
Self::mint_and_compound(
due,
auto_compound.clone(),
collator.clone(),
owner.clone(),
));
);
}
}
}

extra_weight =
extra_weight.saturating_add(T::WeightInfo::pay_one_collator_reward_best(
num_paid_delegations,
num_auto_compounding,
num_scheduled_requests as u32,
));

(
RewardPayment::Paid,
T::WeightInfo::pay_one_collator_reward(num_delegators as u32)
Expand Down Expand Up @@ -2092,8 +2103,7 @@ pub mod pallet {
compound_percent: Percent,
candidate: T::AccountId,
delegator: T::AccountId,
) -> Weight {
let mut weight = T::WeightInfo::mint_collator_reward();
) {
if let Ok(amount_transferred) =
T::Currency::deposit_into_existing(&delegator, amt.clone())
{
Expand All @@ -2104,29 +2114,20 @@ pub mod pallet {

let compound_amount = compound_percent.mul_ceil(amount_transferred.peek());
if compound_amount.is_zero() {
return weight;
return;
}

match Self::delegation_bond_more_without_event(
if let Err(err) = Self::delegation_bond_more_without_event(
delegator.clone(),
candidate.clone(),
compound_amount.clone(),
) {
Err(err) => {
log::debug!(
"skipped compounding staking reward towards candidate '{:?}' for delegator '{:?}': {:?}",
candidate,
delegator,
err
);
return weight.saturating_add(T::WeightInfo::delegator_bond_more(
T::MaxTopDelegationsPerCandidate::get()
+ T::MaxBottomDelegationsPerCandidate::get(),
));
}
Ok((_, weight_consumed)) => {
weight = weight.saturating_add(weight_consumed);
}
log::debug!(
"skipped compounding staking reward towards candidate '{:?}' for delegator '{:?}': {:?}",
candidate,
delegator,
err
);
};

Pallet::<T>::deposit_event(Event::Compounded {
Expand All @@ -2135,8 +2136,6 @@ pub mod pallet {
amount: compound_amount.clone(),
});
};

weight
}
}

Expand Down
83 changes: 83 additions & 0 deletions pallets/parachain-staking/src/weights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ pub trait WeightInfo {
fn prepare_staking_payouts() -> Weight;
fn get_rewardable_delegators(y: u32, ) -> Weight;
fn select_top_candidates(x: u32, y: u32, ) -> Weight;
fn pay_one_collator_reward_best(x: u32, y: u32, z: u32, ) -> Weight;
fn pay_one_collator_reward(y: u32, ) -> Weight;
fn base_on_initialize() -> Weight;
fn set_auto_compound(x: u32, y: u32, ) -> Weight;
Expand Down Expand Up @@ -691,6 +692,47 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
.saturating_add(Weight::from_parts(0, 3975).saturating_mul(x.into()))
.saturating_add(Weight::from_parts(0, 639).saturating_mul(y.into()))
}
/// Storage: System Account (r:349 w:349)
/// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen)
/// Storage: ParachainStaking DelegatorState (r:349 w:349)
/// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured)
/// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0)
/// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured)
/// Storage: Balances Locks (r:349 w:349)
/// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen)
/// Storage: Balances Freezes (r:349 w:0)
/// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen)
/// Storage: ParachainStaking CandidateInfo (r:1 w:1)
/// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured)
/// Storage: ParachainStaking TopDelegations (r:1 w:1)
/// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured)
/// Storage: ParachainStaking CandidatePool (r:1 w:1)
/// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: ParachainStaking Total (r:1 w:1)
/// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: ParachainStaking BottomDelegations (r:1 w:1)
/// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured)
/// The range of component `x` is `[0, 349]`.
/// The range of component `y` is `[0, 349]`.
/// The range of component `z` is `[0, 349]`.
fn pay_one_collator_reward_best(x: u32, y: u32, z: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `0 + x * (395 ±0) + y * (156 ±0) + z * (41 ±0)`
// Estimated: `125723 + x * (2591 ±1) + y * (2234 ±1) + z * (28 ±0)`
// Minimum execution time: 405_000 picoseconds.
Weight::from_parts(417_000, 125723)
// Standard Error: 820_303
.saturating_add(Weight::from_parts(79_076_895, 0).saturating_mul(x.into()))
// Standard Error: 820_303
.saturating_add(Weight::from_parts(46_332_465, 0).saturating_mul(y.into()))
.saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(x.into())))
.saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(y.into())))
.saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(x.into())))
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(y.into())))
.saturating_add(Weight::from_parts(0, 2591).saturating_mul(x.into()))
.saturating_add(Weight::from_parts(0, 2234).saturating_mul(y.into()))
.saturating_add(Weight::from_parts(0, 28).saturating_mul(z.into()))
}
/// Storage: ParachainStaking DelayedPayouts (r:1 w:0)
/// Proof Skipped: ParachainStaking DelayedPayouts (max_values: None, max_size: None, mode: Measured)
/// Storage: ParachainStaking Points (r:1 w:0)
Expand Down Expand Up @@ -1432,6 +1474,47 @@ impl WeightInfo for () {
.saturating_add(Weight::from_parts(0, 3975).saturating_mul(x.into()))
.saturating_add(Weight::from_parts(0, 639).saturating_mul(y.into()))
}
/// Storage: System Account (r:349 w:349)
/// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen)
/// Storage: ParachainStaking DelegatorState (r:349 w:349)
/// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured)
/// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0)
/// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured)
/// Storage: Balances Locks (r:349 w:349)
/// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen)
/// Storage: Balances Freezes (r:349 w:0)
/// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen)
/// Storage: ParachainStaking CandidateInfo (r:1 w:1)
/// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured)
/// Storage: ParachainStaking TopDelegations (r:1 w:1)
/// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured)
/// Storage: ParachainStaking CandidatePool (r:1 w:1)
/// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: ParachainStaking Total (r:1 w:1)
/// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: ParachainStaking BottomDelegations (r:1 w:1)
/// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured)
/// The range of component `x` is `[0, 349]`.
/// The range of component `y` is `[0, 349]`.
/// The range of component `z` is `[0, 349]`.
fn pay_one_collator_reward_best(x: u32, y: u32, z: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `0 + x * (395 ±0) + y * (156 ±0) + z * (41 ±0)`
// Estimated: `125723 + x * (2591 ±1) + y * (2234 ±1) + z * (28 ±0)`
// Minimum execution time: 405_000 picoseconds.
Weight::from_parts(417_000, 125723)
// Standard Error: 820_303
.saturating_add(Weight::from_parts(79_076_895, 0).saturating_mul(x.into()))
// Standard Error: 820_303
.saturating_add(Weight::from_parts(46_332_465, 0).saturating_mul(y.into()))
.saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(x.into())))
.saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(y.into())))
.saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(x.into())))
.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(y.into())))
.saturating_add(Weight::from_parts(0, 2591).saturating_mul(x.into()))
.saturating_add(Weight::from_parts(0, 2234).saturating_mul(y.into()))
.saturating_add(Weight::from_parts(0, 28).saturating_mul(z.into()))
}
/// Storage: ParachainStaking DelayedPayouts (r:1 w:0)
/// Proof Skipped: ParachainStaking DelayedPayouts (max_values: None, max_size: None, mode: Measured)
/// Storage: ParachainStaking Points (r:1 w:0)
Expand Down
42 changes: 42 additions & 0 deletions runtime/common/src/weights/pallet_parachain_staking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,48 @@ impl<T: frame_system::Config> pallet_parachain_staking::WeightInfo for WeightInf
.saturating_add(Weight::from_parts(0, 3975).saturating_mul(x.into()))
.saturating_add(Weight::from_parts(0, 639).saturating_mul(y.into()))
}
/// Storage: System Account (r:349 w:349)
/// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen)
/// Storage: ParachainStaking DelegatorState (r:349 w:349)
/// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured)
/// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0)
/// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured)
/// Storage: Balances Locks (r:349 w:349)
/// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen)
/// Storage: Balances Freezes (r:349 w:0)
/// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen)
/// Storage: ParachainStaking CandidateInfo (r:1 w:1)
/// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured)
/// Storage: ParachainStaking TopDelegations (r:1 w:1)
/// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured)
/// Storage: ParachainStaking CandidatePool (r:1 w:1)
/// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: ParachainStaking Total (r:1 w:1)
/// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: ParachainStaking BottomDelegations (r:1 w:1)
/// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured)
/// The range of component `x` is `[0, 349]`.
/// The range of component `y` is `[0, 349]`.
/// The range of component `z` is `[0, 349]`.
fn pay_one_collator_reward_best(x: u32, y: u32, z: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `0 + x * (395 ±0) + y * (156 ±0) + z * (41 ±0)`
// Estimated: `125723 + x * (2591 ±1) + y * (2234 ±1) + z * (28 ±0)`
// Minimum execution time: 94_000 picoseconds.
Weight::from_parts(110_000, 0)
.saturating_add(Weight::from_parts(0, 125723))
// Standard Error: 599_355
.saturating_add(Weight::from_parts(38_179_886, 0).saturating_mul(x.into()))
// Standard Error: 599_355
.saturating_add(Weight::from_parts(20_585_164, 0).saturating_mul(y.into()))
.saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(x.into())))
.saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(y.into())))
.saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(x.into())))
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(y.into())))
.saturating_add(Weight::from_parts(0, 2591).saturating_mul(x.into()))
.saturating_add(Weight::from_parts(0, 2234).saturating_mul(y.into()))
.saturating_add(Weight::from_parts(0, 28).saturating_mul(z.into()))
}
/// Storage: ParachainStaking DelayedPayouts (r:1 w:0)
/// Proof Skipped: ParachainStaking DelayedPayouts (max_values: None, max_size: None, mode: Measured)
/// Storage: ParachainStaking Points (r:1 w:0)
Expand Down
Loading