Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
ea30833
make pool roles optional
kianenigma May 13, 2022
00e8c87
undo lock file changes?
kianenigma May 13, 2022
fa5e95a
add migration
kianenigma May 13, 2022
f2df79e
add the ability for pools to chill themselves
kianenigma May 14, 2022
56cf997
boilerplate of tests
kianenigma May 14, 2022
508bc0a
new system works, tests need fixing
kianenigma May 15, 2022
f83944a
somewhat stable, but I think I found another bug as well
kianenigma May 15, 2022
ac48c37
Fix it all
kianenigma May 16, 2022
cbeb9fb
Master.into()
kianenigma May 16, 2022
031040f
Add more more sophisticated test + capture one more bug.
kianenigma May 16, 2022
efc7b4f
Update frame/staking/src/lib.rs
kianenigma May 16, 2022
60d42f1
reduce the diff a little bit
kianenigma May 17, 2022
02aa7d4
add some test for the slashing bug
kianenigma May 19, 2022
90db26e
cleanup
kianenigma May 19, 2022
5bf6d9c
Merge branch 'kiz-pool-chill' of github.com:paritytech/substrate into…
kianenigma May 19, 2022
1d8c940
Master.into()
kianenigma May 19, 2022
2ec4857
Merge branch 'master' of github.com:paritytech/substrate into kiz-poo…
kianenigma May 20, 2022
a51e408
fix lock file?
kianenigma May 20, 2022
28c8852
Fix
kianenigma May 20, 2022
c9413a2
fmt
kianenigma May 20, 2022
433476d
Merge branch 'master' of github.com:paritytech/substrate into kiz-poo…
kianenigma May 23, 2022
c34b655
Update frame/nomination-pools/src/lib.rs
kianenigma May 23, 2022
d0d75a1
Update frame/nomination-pools/src/lib.rs
kianenigma May 23, 2022
a6afb06
Update frame/nomination-pools/src/lib.rs
kianenigma May 23, 2022
a3a43e7
Update frame/nomination-pools/src/mock.rs
kianenigma May 23, 2022
4b7b0c7
Fix build
kianenigma May 23, 2022
3f66688
Merge branch 'kiz-pool-chill' of github.com:paritytech/substrate into…
kianenigma May 23, 2022
640ec31
fix some fishy tests..
kianenigma May 23, 2022
398ddfe
add one last integrity check for MinCreateBond
kianenigma May 24, 2022
d5dc697
remove bad assertion -- needs to be dealt with later
kianenigma May 24, 2022
05fb517
Merge branch 'master' of github.com:paritytech/substrate into kiz-poo…
kianenigma May 24, 2022
f4dbd0a
nits
shawntabrizi May 25, 2022
0a79c80
Master.into()
kianenigma Jun 8, 2022
78c0310
Merge branch 'kiz-pool-chill' of github.com:paritytech/substrate into…
kianenigma Jun 9, 2022
0fb1125
fix tests and add benchmarks for chill
kianenigma Jun 9, 2022
12773bb
remove stuff
kianenigma Jun 9, 2022
ca475df
fix benchmarks
kianenigma Jun 10, 2022
44a2722
Merge branch 'master' of https://github.com/paritytech/substrate into…
Jun 10, 2022
f027faf
cargo run --quiet --profile=production --features=runtime-benchmarks…
Jun 10, 2022
33b581c
Master.into()
kianenigma Jun 11, 2022
c77613f
Merge branch 'kiz-pool-chill' of github.com:paritytech/substrate into…
kianenigma Jun 11, 2022
d69af2c
remove defensive
kianenigma Jun 11, 2022
d318197
Merge branch 'master' of github.com:paritytech/substrate into kiz-poo…
kianenigma Jun 13, 2022
486a0e9
first working version
kianenigma Jun 13, 2022
9b2113f
Master.into()
kianenigma Jun 14, 2022
36cb484
bring back all tests
kianenigma Jun 14, 2022
723574b
ALL new tests work now
kianenigma Jun 14, 2022
624abe9
Merge branch 'master' of github.com:paritytech/substrate into kiz-fix…
kianenigma Jun 14, 2022
82287b0
cleanup
kianenigma Jun 14, 2022
e403fb1
make sure benchmarks and all work
kianenigma Jun 15, 2022
4cad93a
Merge branch 'master' of https://github.com/paritytech/substrate into…
Jun 15, 2022
221369b
cargo run --quiet --profile=production --features=runtime-benchmarks…
Jun 15, 2022
696a55e
round of self-review, make arithmetic safe
kianenigma Jun 15, 2022
0689b58
Merge branch 'kiz-fix-reward-pools-2' of github.com:paritytech/substr…
kianenigma Jun 15, 2022
bcb413c
fix warn
kianenigma Jun 15, 2022
bce40f7
add migration code
kianenigma Jun 16, 2022
8fc25ac
Merge branch 'master' of github.com:paritytech/substrate into kiz-fix…
kianenigma Jun 16, 2022
fc3ad18
Fix doc
kianenigma Jun 17, 2022
03107f3
Merge branches 'kiz-fix-reward-pools-2' and 'master' of github.com:pa…
kianenigma Jun 21, 2022
9f875a9
add precision notes
kianenigma Jun 21, 2022
0513284
make arithmetic fallible
kianenigma Jun 21, 2022
1c43f09
fix node runtime
kianenigma Jun 21, 2022
ef56db6
a lot of precision tests and notes and stuff
kianenigma Jun 22, 2022
3da2364
document MaxPOintsToBalance better
kianenigma Jun 22, 2022
ed5083f
Merge branch 'master' of github.com:paritytech/substrate into kiz-fix…
kianenigma Jun 23, 2022
3690489
:round of self-review
kianenigma Jun 23, 2022
62d35c8
fmt
kianenigma Jun 23, 2022
1c840b2
fix some comments
kianenigma Jun 23, 2022
7d9d403
Merge branch 'master' of github.com:paritytech/substrate into kiz-fix…
kianenigma Jun 26, 2022
78b79f2
Master.into()
kianenigma Jul 1, 2022
a8ccd71
Fix proportional slashing logic
kianenigma Jul 5, 2022
60b7641
Update frame/nomination-pools/src/tests.rs
kianenigma Jul 6, 2022
a2082cd
Update frame/nomination-pools/src/tests.rs
kianenigma Jul 6, 2022
ecb7890
Update frame/nomination-pools/src/lib.rs
kianenigma Jul 6, 2022
7e56e1a
track poinst in migration
kianenigma Jul 6, 2022
80b31c0
Merge branch 'kiz-fix-reward-pools-2' of github.com:paritytech/substr…
kianenigma Jul 6, 2022
579da37
fix
kianenigma Jul 6, 2022
51c1608
fmt
kianenigma Jul 6, 2022
3779081
fix migration
kianenigma Jul 6, 2022
9171a13
remove event read
kianenigma Jul 6, 2022
b9ab747
Apply suggestions from code review
kianenigma Jul 7, 2022
d4f45e7
Update frame/staking/src/lib.rs
kianenigma Jul 9, 2022
ca47b05
Update frame/nomination-pools/src/lib.rs
kianenigma Jul 9, 2022
f3e10a9
Update frame/nomination-pools/src/lib.rs
kianenigma Jul 9, 2022
463ddfd
Merge branch 'master' of github.com:paritytech/substrate into kiz-fix…
kianenigma Jul 10, 2022
51873c7
Merge branch 'kiz-fix-reward-pools-2' of github.com:paritytech/substr…
kianenigma Jul 10, 2022
c205ac3
update
kianenigma Jul 10, 2022
69d1f9c
fmt
kianenigma Jul 10, 2022
3efe9f5
fmt
kianenigma Jul 10, 2022
84a2639
add one last test
kianenigma Jul 10, 2022
e7673f8
fmt
kianenigma Jul 12, 2022
ed2c225
Merge branch 'master' of github.com:paritytech/substrate into kiz-fix…
kianenigma Jul 12, 2022
de9886d
merged
kianenigma Jul 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix proportional slashing logic
  • Loading branch information
kianenigma committed Jul 5, 2022
commit a8ccd71e3a8704ca90a08150f12e052ff1ca7aa3
267 changes: 265 additions & 2 deletions frame/nomination-pools/test-staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ mod mock;
use frame_support::{assert_noop, assert_ok, bounded_btree_map, traits::Currency};
use mock::*;
use pallet_nomination_pools::{
Error as PoolsError, Event as PoolsEvent, LastPoolId, PoolMember, PoolMembers, PoolState,
BondedPools, Error as PoolsError, Event as PoolsEvent, LastPoolId, PoolMember, PoolMembers,
PoolState,
};
use pallet_staking::{CurrentEra, Event as StakingEvent, Payee, RewardDestination};
use sp_runtime::traits::Zero;
Expand Down Expand Up @@ -274,7 +275,7 @@ fn pool_slash_e2e() {
30,
&mut Default::default(),
&mut Default::default(),
1, // slash era 1, affects chunks at era 5 onwards.
2, // slash era 2, affects chunks at era 5 onwards.
);

assert_eq!(staking_events_since_last_call(), vec![StakingEvent::Slashed(POOL1_BONDED, 30)]);
Expand Down Expand Up @@ -372,3 +373,265 @@ fn pool_slash_e2e() {
);
});
}

#[test]
fn pool_slash_proportional() {
// a typical example where 3 pool members unbond in era 99, 100, and 101, and a slash that
// happened in era 100 should only affect the latter two.
new_test_ext().execute_with(|| {
ExistentialDeposit::set(1);
BondingDuration::set(28);
assert_eq!(Balances::minimum_balance(), 1);
assert_eq!(Staking::current_era(), None);

// create the pool, we know this has id 1.
assert_ok!(Pools::create(Origin::signed(10), 40, 10, 10, 10));
assert_eq!(LastPoolId::<T>::get(), 1);

assert_eq!(staking_events_since_last_call(), vec![StakingEvent::Bonded(POOL1_BONDED, 40)]);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Created { depositor: 10, pool_id: 1 },
PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 40, joined: true },
]
);

// have two members join
let bond = 20;
assert_ok!(Pools::join(Origin::signed(20), bond, 1));
assert_ok!(Pools::join(Origin::signed(21), bond, 1));
assert_ok!(Pools::join(Origin::signed(22), bond, 1));

assert_eq!(
staking_events_since_last_call(),
vec![
StakingEvent::Bonded(POOL1_BONDED, bond),
StakingEvent::Bonded(POOL1_BONDED, bond),
StakingEvent::Bonded(POOL1_BONDED, bond),
]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: bond, joined: true },
PoolsEvent::Bonded { member: 21, pool_id: 1, bonded: bond, joined: true },
PoolsEvent::Bonded { member: 22, pool_id: 1, bonded: bond, joined: true },
]
);

// now let's progress a lot.
CurrentEra::<T>::set(Some(99));

// and unbond
assert_ok!(Pools::unbond(Origin::signed(20), 20, bond));

assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Unbonded(POOL1_BONDED, bond),]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Unbonded { member: 20, pool_id: 1, balance: bond, points: bond }]
);

CurrentEra::<T>::set(Some(100));
assert_ok!(Pools::unbond(Origin::signed(21), 21, bond));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Unbonded(POOL1_BONDED, bond),]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Unbonded { member: 21, pool_id: 1, balance: bond, points: bond }]
);

CurrentEra::<T>::set(Some(101));
assert_ok!(Pools::unbond(Origin::signed(22), 22, bond));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Unbonded(POOL1_BONDED, bond),]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Unbonded { member: 22, pool_id: 1, balance: bond, points: bond }]
);

// Apply a slash that happened in era 100. This is typically applied with a delay.
// Of the total 100, 50 is slashed.
assert_eq!(BondedPools::<T>::get(1).unwrap().points, 40);
pallet_staking::slashing::do_slash::<Runtime>(
&POOL1_BONDED,
50,
&mut Default::default(),
&mut Default::default(),
100,
);

assert_eq!(staking_events_since_last_call(), vec![StakingEvent::Slashed(POOL1_BONDED, 50)]);
assert_eq!(
pool_events_since_last_call(),
vec![
// This last pool got slashed only the leftover dust. Otherwise in principle, this
// chunk/pool should have not been affected.
// TODO: We might improve this in a future PR
PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 127, balance: 19 },
// This pool got slashed 12.5, which rounded down to 12.
PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 128, balance: 8 },
// This pool got slashed 12.5, which rounded down to 12.
PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 129, balance: 8 },
// Bonded pool got slashed for 25, remaining 15 in it.
PoolsEvent::PoolSlashed { pool_id: 1, balance: 15 }
]
);
});
}

#[test]
fn pool_slash_non_proportional_only_bonded_pool() {
// A typical example where a pool member unbonds in era 99, and he can get away with a slash tha
// happened in era 99, as long as the pool has enough active bond to cover the slash. If
// everything else in the slashing/staking system works, this should always be the case.
// Nonetheless, `ledger.slash` has been written such that it will slash greedily from any chunk
// if it runs out of chunks that it thinks should be affected by the slash.
new_test_ext().execute_with(|| {
ExistentialDeposit::set(1);
BondingDuration::set(28);
assert_eq!(Balances::minimum_balance(), 1);
assert_eq!(Staking::current_era(), None);

// create the pool, we know this has id 1.
assert_ok!(Pools::create(Origin::signed(10), 40, 10, 10, 10));
assert_eq!(staking_events_since_last_call(), vec![StakingEvent::Bonded(POOL1_BONDED, 40)]);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Created { depositor: 10, pool_id: 1 },
PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 40, joined: true },
]
);

// have two members join
let bond = 20;
assert_ok!(Pools::join(Origin::signed(20), bond, 1));
assert_eq!(
staking_events_since_last_call(),
vec![
StakingEvent::Bonded(POOL1_BONDED, bond)
]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: bond, joined: true }
]
);

// progress and unbond.
CurrentEra::<T>::set(Some(99));
assert_ok!(Pools::unbond(Origin::signed(20), 20, bond));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Unbonded(POOL1_BONDED, bond)]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Unbonded { member: 20, pool_id: 1, balance: bond, points: bond }]
);

// slash for 30. This will be deducted only from the bonded pool.
CurrentEra::<T>::set(Some(100));
assert_eq!(BondedPools::<T>::get(1).unwrap().points, 40);
pallet_staking::slashing::do_slash::<Runtime>(
&POOL1_BONDED,
30,
&mut Default::default(),
&mut Default::default(),
100,
);

assert_eq!(staking_events_since_last_call(), vec![StakingEvent::Slashed(POOL1_BONDED, 30)]);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::PoolSlashed { pool_id: 1, balance: 10 }
]
);
});
}

#[test]
fn pool_slash_non_proportional_bonded_pool_and_chunks() {
// An uncommon example where even though some funds are unlocked such that they should not be
// affected by a slash, we still slash out of them. This should not happen at all. If a
// nomination has unbonded, from the next era onwards, their exposure will drop, so if an era
// happens in that era, then their share of that slash should naturally be less, such that only
// their active ledger stake is enough to compensate it.
new_test_ext().execute_with(|| {
ExistentialDeposit::set(1);
BondingDuration::set(28);
assert_eq!(Balances::minimum_balance(), 1);
assert_eq!(Staking::current_era(), None);

// create the pool, we know this has id 1.
assert_ok!(Pools::create(Origin::signed(10), 40, 10, 10, 10));
assert_eq!(staking_events_since_last_call(), vec![StakingEvent::Bonded(POOL1_BONDED, 40)]);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Created { depositor: 10, pool_id: 1 },
PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 40, joined: true },
]
);

// have two members join
let bond = 20;
assert_ok!(Pools::join(Origin::signed(20), bond, 1));
assert_eq!(
staking_events_since_last_call(),
vec![
StakingEvent::Bonded(POOL1_BONDED, bond)
]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: bond, joined: true }
]
);

// progress and unbond.
CurrentEra::<T>::set(Some(99));
assert_ok!(Pools::unbond(Origin::signed(20), 20, bond));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Unbonded(POOL1_BONDED, bond)]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Unbonded { member: 20, pool_id: 1, balance: bond, points: bond }]
);

// slash 50. This will be deducted only from the bonded pool and one of the unbonding pools.
CurrentEra::<T>::set(Some(100));
assert_eq!(BondedPools::<T>::get(1).unwrap().points, 40);
pallet_staking::slashing::do_slash::<Runtime>(
&POOL1_BONDED,
50,
&mut Default::default(),
&mut Default::default(),
100,
);

assert_eq!(staking_events_since_last_call(), vec![StakingEvent::Slashed(POOL1_BONDED, 50)]);
assert_eq!(
pool_events_since_last_call(),
vec![
// out of 20, 10 was taken.
PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 127, balance: 10 },
// out of 40, all was taken.
PoolsEvent::PoolSlashed { pool_id: 1, balance: 0 }
]
);
});
}
7 changes: 5 additions & 2 deletions frame/nomination-pools/test-staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type AccountIndex = u32;
type BlockNumber = u64;
type Balance = u128;

pub(crate) type T = Runtime;

pub(crate) const POOL1_BONDED: AccountId = 20318131474730217858575332831085u128;
pub(crate) const POOL1_REWARD: AccountId = 20397359637244482196168876781421u128;

Expand Down Expand Up @@ -199,13 +201,14 @@ frame_support::construct_runtime!(
);

pub fn new_test_ext() -> sp_io::TestExternalities {
sp_tracing::try_init_simple();
let mut storage = frame_system::GenesisConfig::default().build_storage::<Runtime>().unwrap();
let _ = pallet_nomination_pools::GenesisConfig::<Runtime> {
min_join_bond: 2,
min_create_bond: 2,
max_pools: Some(3),
max_members_per_pool: Some(3),
max_members: Some(3 * 3),
max_members_per_pool: Some(5),
max_members: Some(3 * 5),
}
.assimilate_storage(&mut storage)
.unwrap();
Expand Down
Loading