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

Validator Re-Enabling #5724

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open

Validator Re-Enabling #5724

wants to merge 31 commits into from

Conversation

Overkillus
Copy link
Contributor

@Overkillus Overkillus commented Sep 16, 2024

Aims to implement Stage 3 of Validator Disbling as outlined here: #4359

Features:

  • New Disabling Strategy (Staking level)
  • Re-enabling logic (Session level)
  • More generic disabling decision output
  • New Disabling Events

Testing & Security:

  • Unit tests
  • Mock tests
  • Try-runtime checks
  • Try-runtime tested on westend snap
  • Try-runtime CI tests
  • Re-enabling Zombienet Test
  • SRLabs Audit

Closes #4745
Closes #2418

@Overkillus Overkillus added I1-security The node fails to follow expected, security-sensitive, behaviour. T8-polkadot This PR/Issue is related to/affects the Polkadot network. labels Sep 16, 2024
@Overkillus Overkillus self-assigned this Sep 16, 2024
Copy link
Contributor

@tdimitrov tdimitrov left a comment

Choose a reason for hiding this comment

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

I had a quick pass by focusing mainly on the approach. It looks good, nice work @Overkillus!

I've left some thoughts about a corner case with the re-enabling.

// Find the smallest offender to re-enable that is not higher than offender_slash_severity
if let Some((smallest_idx, _)) = currently_disabled
.iter()
.filter(|(_, perbill)| *perbill <= offender_slash_severity)
Copy link
Contributor

Choose a reason for hiding this comment

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

Just to clarify - even if there is no offender with a smaller offence we will re-enable the first guy with an offence equal to the new offender. Which is a good thing.

However I think we are biased here towards disabling the validator with the smallest index, which is wrong. If there are multiple elements with the same min value min_by_key returns the first one. If I am not mistaken DisabledValidators are sorted by key (here) so this way we will always reenable the guy with the smallest index.

It's a corner case but it would be nice to handle it if it is not too complicated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are definitely right. I simply don't think this is anything to worry about. This will only kick in and matter only when we have offender of the same level of severity. Slashes will be dispensed and the newest offender will be disabled. From our perspective as long as lowest severity is re-enabled this is the lowest possible risk.

We will mention it to SRLabs on audit and see what the think. We can remedy as you mentioned with a random selection for a given severity level instead of arbitrary.

substrate/frame/staking/src/slashing.rs Outdated Show resolved Hide resolved
substrate/frame/staking/src/slashing.rs Outdated Show resolved Hide resolved
@Overkillus Overkillus changed the title Validator Re-Enabling (master PR) Validator Re-Enabling Sep 24, 2024
@Overkillus Overkillus marked this pull request as ready for review September 30, 2024 09:33
@Overkillus Overkillus requested a review from a team as a code owner September 30, 2024 09:33
@tdimitrov tdimitrov self-requested a review October 1, 2024 11:32
@paritytech-cicd-pr
Copy link

The CI pipeline was cancelled due to failure one of the required jobs.
Job name: test-linux-stable 2/3
Logs: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7472972

@Overkillus Overkillus requested a review from ordian October 2, 2024 12:01
Copy link
Member

@ordian ordian left a comment

Choose a reason for hiding this comment

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

Looks good overall, but spotted some things that need to be fixed

prdoc/pr_5724.prdoc Outdated Show resolved Hide resolved
substrate/frame/staking/src/lib.rs Outdated Show resolved Hide resolved
@@ -727,7 +727,7 @@ pub mod pallet {
/// offended using binary search.
#[pallet::storage]
#[pallet::unbounded]
pub type DisabledValidators<T: Config> = StorageValue<_, Vec<u32>, ValueQuery>;
pub type DisabledValidators<T: Config> = StorageValue<_, Vec<(u32, Perbill)>, ValueQuery>;
Copy link
Member

Choose a reason for hiding this comment

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

I think we should create a separate type OffenceSeverity that implements Ord and at the moment is only a wrapper around PerBill, but could be changed in the future to compare two severities with equal slash in the different way.

Copy link
Member

Choose a reason for hiding this comment

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

Also, we need to account for #64 here by changing the runtime API like

// Use the right storage depending on version to ensure #64 doesn't cause issues with this
// migration.
let min_relay_parent_number = if shared::Pallet::<T>::on_chain_storage_version() ==
StorageVersion::new(0)

substrate/frame/staking/src/migrations.rs Show resolved Hide resolved
// Offender is already disabled, update severity if the new one is higher
Ok(index) => {
let (_, old_severity) = &mut disabled[index];
if params.slash > *old_severity {
Copy link
Member

Choose a reason for hiding this comment

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

is this a cumulitive slash or only the one coming from the latest offence? are we relying on the fact that we only slash for the max in the era and do not accumulate slashes here? all implicit assumptions would need to be documented

// Remove the validator from `DisabledValidators` and re-enable it.
if let Ok(index) = disabled.binary_search_by_key(&reenable_idx, |(index, _)| *index) {
disabled.remove(index);
// Propagate re-enablement to session level
Copy link
Member

Choose a reason for hiding this comment

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

i got confused by having the same storage name DisabledValidators in slashing and in session. maybe we could rename the one in staking to DisabledValidatorsWithSeverity or something like that

Overkillus and others added 2 commits October 15, 2024 10:13
Co-authored-by: ordian <write@reusable.software>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I1-security The node fails to follow expected, security-sensitive, behaviour. T8-polkadot This PR/Issue is related to/affects the Polkadot network.
Projects
Status: Backlog
4 participants