Skip to content

Commit c037be6

Browse files
authored
Staking Payout Creates Controller (#6496)
* payout creates controller * update benchmarks * oops * fix session benchmarks * Update weights * fix line width
1 parent b0467de commit c037be6

File tree

4 files changed

+79
-6
lines changed

4 files changed

+79
-6
lines changed

src/benchmarking.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ fn add_slashing_spans<T: Trait>(who: &T::AccountId, spans: u32) {
4747

4848
// This function generates one validator being nominated by n nominators, and returns the validator
4949
// stash account. It also starts an era and creates pending payouts.
50-
pub fn create_validator_with_nominators<T: Trait>(n: u32, upper_bound: u32) -> Result<T::AccountId, &'static str> {
50+
pub fn create_validator_with_nominators<T: Trait>(
51+
n: u32,
52+
upper_bound: u32,
53+
dead: bool,
54+
) -> Result<T::AccountId, &'static str> {
5155
let mut points_total = 0;
5256
let mut points_individual = Vec::new();
5357

@@ -65,7 +69,11 @@ pub fn create_validator_with_nominators<T: Trait>(n: u32, upper_bound: u32) -> R
6569

6670
// Give the validator n nominators, but keep total users in the system the same.
6771
for i in 0 .. upper_bound {
68-
let (_n_stash, n_controller) = create_stash_controller::<T>(u32::max_value() - i, 100)?;
72+
let (_n_stash, n_controller) = if !dead {
73+
create_stash_controller::<T>(u32::max_value() - i, 100)?
74+
} else {
75+
create_stash_and_dead_controller::<T>(u32::max_value() - i, 100)?
76+
};
6977
if i < n {
7078
Staking::<T>::nominate(RawOrigin::Signed(n_controller.clone()).into(), vec![stash_lookup.clone()])?;
7179
}
@@ -271,7 +279,8 @@ benchmarks! {
271279

272280
payout_stakers {
273281
let n in 1 .. T::MaxNominatorRewardedPerValidator::get() as u32;
274-
let validator = create_validator_with_nominators::<T>(n, T::MaxNominatorRewardedPerValidator::get() as u32)?;
282+
let validator = create_validator_with_nominators::<T>(n, T::MaxNominatorRewardedPerValidator::get() as u32, true)?;
283+
275284
let current_era = CurrentEra::get().unwrap();
276285
let caller = account("caller", 0, SEED);
277286
let balance_before = T::Currency::free_balance(&validator);
@@ -282,6 +291,20 @@ benchmarks! {
282291
assert!(balance_before < balance_after);
283292
}
284293

294+
payout_stakers_alive_controller {
295+
let n in 1 .. T::MaxNominatorRewardedPerValidator::get() as u32;
296+
let validator = create_validator_with_nominators::<T>(n, T::MaxNominatorRewardedPerValidator::get() as u32, false)?;
297+
298+
let current_era = CurrentEra::get().unwrap();
299+
let caller = account("caller", 0, SEED);
300+
let balance_before = T::Currency::free_balance(&validator);
301+
}: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era)
302+
verify {
303+
// Validator has been paid!
304+
let balance_after = T::Currency::free_balance(&validator);
305+
assert!(balance_before < balance_after);
306+
}
307+
285308
rebond {
286309
let l in 1 .. MAX_UNLOCKING_CHUNKS as u32;
287310
let (_, controller) = create_stash_controller::<T>(u, 100)?;
@@ -630,6 +653,7 @@ mod tests {
630653
let validator_stash = create_validator_with_nominators::<Test>(
631654
n,
632655
<Test as Trait>::MaxNominatorRewardedPerValidator::get() as u32,
656+
false,
633657
).unwrap();
634658

635659
let current_era = CurrentEra::get().unwrap();
@@ -650,6 +674,7 @@ mod tests {
650674
let validator_stash = create_validator_with_nominators::<Test>(
651675
n,
652676
<Test as Trait>::MaxNominatorRewardedPerValidator::get() as u32,
677+
false,
653678
).unwrap();
654679

655680
// Add 20 slashing spans
@@ -710,6 +735,7 @@ mod tests {
710735
assert_ok!(test_benchmark_force_unstake::<Test>());
711736
assert_ok!(test_benchmark_cancel_deferred_slash::<Test>());
712737
assert_ok!(test_benchmark_payout_stakers::<Test>());
738+
assert_ok!(test_benchmark_payout_stakers_alive_controller::<Test>());
713739
assert_ok!(test_benchmark_rebond::<Test>());
714740
assert_ok!(test_benchmark_set_history_depth::<Test>());
715741
assert_ok!(test_benchmark_reap_stash::<Test>());

src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,15 +1978,17 @@ decl_module! {
19781978
/// - Contains a limited number of reads and writes.
19791979
/// -----------
19801980
/// N is the Number of payouts for the validator (including the validator)
1981-
/// Base Weight: 110 + 54.2 * N µs (Median Slopes)
1981+
/// Base Weight:
1982+
/// - Reward Destination Staked: 110 + 54.2 * N µs (Median Slopes)
1983+
/// - Reward Destination Controller (Creating): 120 + 41.95 * N µs (Median Slopes)
19821984
/// DB Weight:
19831985
/// - Read: EraElectionStatus, CurrentEra, HistoryDepth, ErasValidatorReward,
19841986
/// ErasStakersClipped, ErasRewardPoints, ErasValidatorPrefs (8 items)
19851987
/// - Read Each: Bonded, Ledger, Payee, Locks, System Account (5 items)
19861988
/// - Write Each: System Account, Locks, Ledger (3 items)
19871989
/// # </weight>
19881990
#[weight =
1989-
110 * WEIGHT_PER_MICROS
1991+
120 * WEIGHT_PER_MICROS
19901992
+ 54 * WEIGHT_PER_MICROS * Weight::from(T::MaxNominatorRewardedPerValidator::get())
19911993
+ T::DbWeight::get().reads(7)
19921994
+ T::DbWeight::get().reads(5) * Weight::from(T::MaxNominatorRewardedPerValidator::get() + 1)
@@ -2395,7 +2397,7 @@ impl<T: Trait> Module<T> {
23952397
match dest {
23962398
RewardDestination::Controller => Self::bonded(stash)
23972399
.and_then(|controller|
2398-
T::Currency::deposit_into_existing(&controller, amount).ok()
2400+
Some(T::Currency::deposit_creating(&controller, amount))
23992401
),
24002402
RewardDestination::Stash =>
24012403
T::Currency::deposit_into_existing(stash, amount).ok(),

src/testing_utils.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,21 @@ pub fn create_stash_controller<T: Trait>(n: u32, balance_factor: u32)
5151
return Ok((stash, controller))
5252
}
5353

54+
/// Create a stash and controller pair, where the controller is dead, and payouts go to controller.
55+
/// This is used to test worst case payout scenarios.
56+
pub fn create_stash_and_dead_controller<T: Trait>(n: u32, balance_factor: u32)
57+
-> Result<(T::AccountId, T::AccountId), &'static str>
58+
{
59+
let stash = create_funded_user::<T>("stash", n, balance_factor);
60+
// controller has no funds
61+
let controller = create_funded_user::<T>("controller", n, 0);
62+
let controller_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(controller.clone());
63+
let reward_destination = RewardDestination::Controller;
64+
let amount = T::Currency::minimum_balance() * (balance_factor / 10).max(1).into();
65+
Staking::<T>::bond(RawOrigin::Signed(stash.clone()).into(), controller_lookup, amount, reward_destination)?;
66+
return Ok((stash, controller))
67+
}
68+
5469
/// create `max` validators.
5570
pub fn create_validators<T: Trait>(
5671
max: u32,

src/tests.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4501,3 +4501,33 @@ fn on_initialize_weight_is_correct() {
45014501
assert_eq!(final_weight, Staking::on_initialize(System::block_number()));
45024502
});
45034503
}
4504+
4505+
4506+
#[test]
4507+
fn payout_creates_controller() {
4508+
// Here we will test validator can set `max_nominators_payout` and it works.
4509+
// We also test that `payout_extra_nominators` works.
4510+
ExtBuilder::default().has_stakers(false).build_and_execute(|| {
4511+
let balance = 1000;
4512+
// Create three validators:
4513+
bond_validator(11, 10, balance); // Default(64)
4514+
4515+
// Create a stash/controller pair
4516+
bond_nominator(1234, 1337, 100, vec![11]);
4517+
4518+
// kill controller
4519+
assert_ok!(Balances::transfer(Origin::signed(1337), 1234, 100));
4520+
assert_eq!(Balances::free_balance(1337), 0);
4521+
4522+
mock::start_era(1);
4523+
Staking::reward_by_ids(vec![(11, 1)]);
4524+
// Compute total payout now for whole duration as other parameter won't change
4525+
let total_payout_0 = current_total_payout_for_duration(3 * 1000);
4526+
assert!(total_payout_0 > 100); // Test is meaningful if reward something
4527+
mock::start_era(2);
4528+
assert_ok!(Staking::payout_stakers(Origin::signed(1337), 11, 1));
4529+
4530+
// Controller is created
4531+
assert!(Balances::free_balance(1337) > 0);
4532+
})
4533+
}

0 commit comments

Comments
 (0)