Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

staking: avoid proportional slashing leak dust into chunks that should not be slashed #12058

Merged
merged 11 commits into from
Sep 6, 2022

Conversation

NingLin-P
Copy link
Contributor

@NingLin-P NingLin-P commented Aug 17, 2022

Attempt to fix #11810

This PR replaces the slash ratio with the remaining ratio, since calculations are rounded down, the slash_from_target calculated from the remaining ratio will be a bit more than the expected proportion instead of less, thus fixing the issue. This PR also comes with a little refactoring.

polkadot address: 1CWyso9Zw46QdR54sTvKJXTUdmZznYZa2aJfNHdG6xQ6L71

Signed-off-by: linning <linningde25@gmail.com>
Signed-off-by: linning <linningde25@gmail.com>
@NingLin-P
Copy link
Contributor Author

@kianenigma PTAL

@paritytech-cicd-pr
Copy link

The CI pipeline was cancelled due to failure one of the required jobs.
The job name - test-linux-stable
The job logs - https://gitlab.parity.io/parity/mirrors/substrate/-/jobs/1752357

Signed-off-by: linning <linningde25@gmail.com>
Signed-off-by: linning <linningde25@gmail.com>
@kianenigma kianenigma added A0-please_review Pull request needs code review. B0-silent Changes should not be mentioned in any release notes C1-low PR touches the given topic and has a low impact on builders. D5-nicetohaveaudit ⚠️ PR contains trivial changes to logic that should be properly reviewed. labels Aug 18, 2022
// zero otherwise. In both cases, we slash first `self.active`, and then
// `slash_chunks_priority`.
let (remaining_ratio, slash_chunks_priority) = {
let mut affected_balance = BalanceOf::<T>::zero();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite agree with the changes here, like let mut first_chunk = None; and assigning to it in the loop. This is actually not Rust-idiomatic at all, and the previous if let Some(_) = iterator {} else {} is more preferred.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought using a single loop to get first_index and affected_balance was more efficient (less iteration) and cleaner (less if else branch), but indeed hand code the functionality that the Iterator API already provided is not Rust-idiomatic.

@@ -611,21 +621,19 @@ impl<T: Config> StakingLedger<T> {
slash_era,
self,
slash_chunks_priority,
maybe_proportional,
Perquintill::one() - remaining_ratio,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be safe math. Or, yet again, I want to complain that the refactor is more of step backwards, since Option is the prefect type to show a maybe_it_is_proportional, instead of some value being 0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intention was to unify both cases (proportional or not) under a ratio, proportional or not just a matter of different ratio, but since it is important to get clear of these cases this indeed may not be a good idea

Copy link
Contributor

@kianenigma kianenigma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right direction and we can fix this, but please:

  1. The refactors are a bit opinionated, let's keep this PR limited only to fixing the rounding down (unless if you want to try a different approach at refactoring the code)
  2. As a simpler approach, please use the same logic as before, but use Rounding::Up when multiplying the Prequintill.

The combination of these two should make the diff of this PR very small, which makes it way easier to merge, since it is a very sensitive code. Thanks!

@NingLin-P
Copy link
Contributor Author

Thanks for the hint @kianenigma !

As a simpler approach, please use the same logic as before, but use Rounding::Up when multiplying the Prequintill.

I found there may have two places need to change to Rounding::Up:

let ratio = Perquintill::from_rational(slash_amount, affected_balance);

ratio * (*target)

the first place may have more impact to the result, it can changing to Perquintill::from_rational_with_rounding but which return a Result I'm not quite sure the proper way to handle the error here. The second place can easily changing to ratio.mul_ceil(*target) though.

@kianenigma
Copy link
Contributor

You should do what normal from_rational is doing:

Self::from_rational_with_rounding(p, q, Rounding::Down).unwrap_or_else(|_| Self::one())

Signed-off-by: linning <linningde25@gmail.com>
Signed-off-by: linning <linningde25@gmail.com>
@paritytech-cicd-pr
Copy link

The CI pipeline was cancelled due to failure one of the required jobs.
The job name - cargo-check-benches
The job logs - https://gitlab.parity.io/parity/mirrors/substrate/-/jobs/1757628

@paritytech-cicd-pr
Copy link

The CI pipeline was cancelled due to failure one of the required jobs.
The job name - cargo-check-benches
The job logs - https://gitlab.parity.io/parity/mirrors/substrate/-/jobs/1757627

Signed-off-by: linning <linningde25@gmail.com>
@@ -5233,26 +5233,12 @@ fn proportional_ledger_slash_works() {
ledger.active = unit;
ledger.total = unit * 4 + value;
// When
assert_eq!(ledger.slash(slash, 0, 0), slash - 43);
assert_eq!(ledger.slash(slash, 0, 2), slash);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add this test case and make sure it is reasonable as well: bdd1399

Ideally, existing tests should not be changed at all.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why you changed this test?

Copy link
Contributor Author

@NingLin-P NingLin-P Aug 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh sorry, I thought the original case was subject to the round down problem and changed it to meet the case not affected chunk should not be slashed (like bdd1399), should not changing it and add a new case instead.

Signed-off-by: linning <linningde25@gmail.com>
@kianenigma kianenigma added D9-needsaudit 👮 PR contains changes to fund-managing logic that should be properly reviewed and externally audited and removed D5-nicetohaveaudit ⚠️ PR contains trivial changes to logic that should be properly reviewed. labels Aug 28, 2022
Copy link
Contributor

@kianenigma kianenigma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, except the small question about tests.

Signed-off-by: linning <linningde25@gmail.com>

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Copy link
Contributor

@ruseinov ruseinov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems good!

Signed-off-by: linning <linningde25@gmail.com>

Co-authored-by: Roman Useinov <roman.useinov@gmail.com>
@kianenigma
Copy link
Contributor

bot rebase

@paritytech-processbot
Copy link

Rebased

@kianenigma
Copy link
Contributor

bot merge

@paritytech-processbot paritytech-processbot bot merged commit dcfaa41 into paritytech:master Sep 6, 2022
@jakoblell jakoblell added D1-audited 👍 PR contains changes to fund-managing logic that has been properly reviewed and externally audited and removed D9-needsaudit 👮 PR contains changes to fund-managing logic that should be properly reviewed and externally audited labels Sep 8, 2022
ark0f pushed a commit to gear-tech/substrate that referenced this pull request Feb 27, 2023
…d not be slashed (paritytech#12058)

* replace slash ratio with remaining ratio

Signed-off-by: linning <linningde25@gmail.com>

* little refactor

Signed-off-by: linning <linningde25@gmail.com>

* fix test

Signed-off-by: linning <linningde25@gmail.com>

* fix typo

Signed-off-by: linning <linningde25@gmail.com>

* revert refactor

Signed-off-by: linning <linningde25@gmail.com>

* rounding up instead of remaining ratio

Signed-off-by: linning <linningde25@gmail.com>

* address comment

Signed-off-by: linning <linningde25@gmail.com>

* Update frame/nomination-pools/test-staking/src/lib.rs

Signed-off-by: linning <linningde25@gmail.com>

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Update frame/nomination-pools/test-staking/src/lib.rs

Signed-off-by: linning <linningde25@gmail.com>

Co-authored-by: Roman Useinov <roman.useinov@gmail.com>

Signed-off-by: linning <linningde25@gmail.com>
Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Roman Useinov <roman.useinov@gmail.com>
Co-authored-by: parity-processbot <>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A0-please_review Pull request needs code review. B0-silent Changes should not be mentioned in any release notes C1-low PR touches the given topic and has a low impact on builders. D1-audited 👍 PR contains changes to fund-managing logic that has been properly reviewed and externally audited
Projects
Status: Done
Status: Done
Development

Successfully merging this pull request may close these issues.

Rewrite proportional slashing to to not leak dust into chunks that should not be slashed.
5 participants