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

No chilling of validators #1962

Closed
eskimor opened this issue Oct 20, 2023 · 13 comments · Fixed by #2226
Closed

No chilling of validators #1962

eskimor opened this issue Oct 20, 2023 · 13 comments · Fixed by #2226
Assignees

Comments

@eskimor
Copy link
Member

eskimor commented Oct 20, 2023

Validators should always be up for re-election even if they were slashed. This is necessary so any consensus issues will never lead to malicious actors increasing their share on active validators.

@eskimor eskimor converted this from a draft issue Oct 20, 2023
@eskimor
Copy link
Member Author

eskimor commented Nov 8, 2023

@paritytech/staking-core @gpestana any concerns?

@eskimor
Copy link
Member Author

eskimor commented Nov 9, 2023

Alternatively: Disabling without slashing (not even 0%)? @ordian

@eskimor
Copy link
Member Author

eskimor commented Nov 22, 2023

@tdimitrov can we disable without slashing? Or please ping @gpestana on this one, thanks!

@tdimitrov
Copy link
Contributor

@tdimitrov can we disable without slashing? Or please ping @gpestana on this one, thanks!

Yes. With the new disabling strategy we disable each offender no matter if it was slashed or not.

@gpestana
Copy link
Contributor

In the current logic, slashed validators are "chilled" and their intention for validating is dropped. However, the validator can still re-validate its intention to become a validator right away. Is this the expected behaviour?

Recently we even changed the logic so that the nominations of slashed/chilled validators are not dropped. This means that once the chilled validator re-validates its intention to become a validator, its nominations remain the same as pre-slash.

Is this the intended behaviour described by this issue?

@eskimor
Copy link
Member Author

eskimor commented Nov 23, 2023

Yes. With the new disabling strategy we disable each offender no matter if it was slashed or not.

And do we also do that? So for voting invalid on valid - we disable but don't slash (not even 0%) and thus we get no chilling?

Is this the intended behavior described by this issue?

Not quite. It is fine if we can disable, without slashing (and thus no chilling). We are worried about the particular case that a determinism issue is abused to get honest validators disabled. We fixed all the concerns we had with disabling, but if those validators would not get re-elected we would still have the original problem just delayed: An attacker can increase its share of validators, by kicking out honest validators from the set (abusing some nondeterminism) and then run an attack.

@gpestana
Copy link
Contributor

This is necessary so any consensus issues will never lead to malicious actors increasing their share on active validators.

Could you elaborate? Are you mentioning the case where offence have been reported on non-faulty validators for some reason?

@eskimor
Copy link
Member Author

eskimor commented Nov 23, 2023

Yes. This obviously should not happen, but it is super hard (impossible) to guarantee this from never happening. With #742 in place, we will have removed one important source, but I would sleep better if nondeterminism could never cause security issues (only liveness).

@ordian
Copy link
Member

ordian commented Nov 23, 2023

So for voting invalid on valid - we disable but don't slash (not even 0%) and thus we get no chilling?

currently we don't disable (no offence is submitted)

@eskimor
Copy link
Member Author

eskimor commented Nov 23, 2023

@ordian just mentioned that he is 80% sure that there is no chilling on 0% slashes. If that is true, then this is good enough and we can close this ticket. Consequences of doing non 0% slashes should be documented in the guide though.

@ordian
Copy link
Member

ordian commented Nov 23, 2023

if params.slash * params.exposure.total == Zero::zero() {
// kick out the validator even if they won't be slashed,
// as long as the misbehavior is from their most recent slashing span.
kick_out_if_recent::<T>(params);

This doesn't seem to indicate that I was correct. Especially given that the

let mut spans = fetch_spans::<T>(
seems to be inserting the span
crate::SlashingSpans::<T>::insert(stash, &spans);

@tdimitrov
Copy link
Contributor

And also here:

add_offending_validator::<T>(params.stash);

I don't know how chilling is related to slashing, but in the current implementation we disable based on enum DisableStrategy (attached to the offence). In the new one - we disable unconditionally.

@tdimitrov
Copy link
Contributor

Me and @gpestana decided not to touch slashing spans with this issue and only remove validator chilling on offence.

Removing slashing spans is tracked in #2650

@tdimitrov tdimitrov moved this from Backlog to In Progress in parachains team board Dec 7, 2023
@Overkillus Overkillus linked a pull request Dec 11, 2023 that will close this issue
@Overkillus Overkillus moved this from In Progress to Review in progress in parachains team board Dec 11, 2023
bkchr pushed a commit that referenced this issue Apr 10, 2024
* Bump substrate/polkadot/cumulus

* sp_finality_grandpa - >sp_consensus_grandpa

* sp_beefy -> sp_consensus_beefy

* pallet_randomness_collective_flip -> pallet_insecure_randomness_collective_flip

* fix

* Cumulus parachain stuff

* Cumulus parachain stuff one more

* Millau/Rialto runtimes

* Removed pallet_insecure_randomness_collective_flip

* Millau node

* Removed session historial

* TMP: just try disable all fetches

* Docs in gitlab.yml
github-merge-queue bot pushed a commit that referenced this issue Apr 26, 2024
Closes #1966,
#1963 and
#1962.

Disabling strategy specification
[here](#2955). (Updated
13/02/2024)

Implements:
* validator disabling for a whole era instead of just a session
* no more than 1/3 of the validators in the active set are disabled
Removes:
* `DisableStrategy` enum - now each validator committing an offence is
disabled.
* New era is not forced if too many validators are disabled.

Before this PR not all offenders were disabled. A decision was made
based on [`enum
DisableStrategy`](https://github.com/paritytech/polkadot-sdk/blob/bbb6631641f9adba30c0ee6f4d11023a424dd362/substrate/primitives/staking/src/offence.rs#L54).
Some offenders were disabled for a whole era, some just for a session,
some were not disabled at all.

This PR changes the disabling behaviour. Now a validator committing an
offense is disabled immediately till the end of the current era.

Some implementation notes:
* `OffendingValidators` in pallet session keeps all offenders (this is
not changed). However its type is changed from `Vec<(u32, bool)>` to
`Vec<u32>`. The reason is simple - each offender is getting disabled so
the bool doesn't make sense anymore.
* When a validator is disabled it is first added to
`OffendingValidators` and then to `DisabledValidators`. This is done in
[`add_offending_validator`](https://github.com/paritytech/polkadot-sdk/blob/bbb6631641f9adba30c0ee6f4d11023a424dd362/substrate/frame/staking/src/slashing.rs#L325)
from staking pallet.
* In
[`rotate_session`](https://github.com/paritytech/polkadot-sdk/blob/bdbe98297032e21a553bf191c530690b1d591405/substrate/frame/session/src/lib.rs#L623)
the `end_session` also calls
[`end_era`](https://github.com/paritytech/polkadot-sdk/blob/bbb6631641f9adba30c0ee6f4d11023a424dd362/substrate/frame/staking/src/pallet/impls.rs#L490)
when an era ends. In this case `OffendingValidators` are cleared
**(1)**.
* Then in
[`rotate_session`](https://github.com/paritytech/polkadot-sdk/blob/bdbe98297032e21a553bf191c530690b1d591405/substrate/frame/session/src/lib.rs#L623)
`DisabledValidators` are cleared **(2)**
* And finally (still in `rotate_session`) a call to
[`start_session`](https://github.com/paritytech/polkadot-sdk/blob/bbb6631641f9adba30c0ee6f4d11023a424dd362/substrate/frame/staking/src/pallet/impls.rs#L430)
repopulates the disabled validators **(3)**.
* The reason for this complication is that session pallet knows nothing
abut eras. To overcome this on each new session the disabled list is
repopulated (points 2 and 3). Staking pallet knows when a new era starts
so with point 1 it ensures that the offenders list is cleared.

---------

Co-authored-by: ordian <[email protected]>
Co-authored-by: ordian <[email protected]>
Co-authored-by: Maciej <[email protected]>
Co-authored-by: Gonçalo Pestana <[email protected]>
Co-authored-by: Kian Paimani <[email protected]>
Co-authored-by: command-bot <>
Co-authored-by: Ankan <[email protected]>
@github-project-automation github-project-automation bot moved this from Review in progress to Completed in parachains team board Apr 26, 2024
Morganamilo pushed a commit that referenced this issue May 2, 2024
Closes #1966,
#1963 and
#1962.

Disabling strategy specification
[here](#2955). (Updated
13/02/2024)

Implements:
* validator disabling for a whole era instead of just a session
* no more than 1/3 of the validators in the active set are disabled
Removes:
* `DisableStrategy` enum - now each validator committing an offence is
disabled.
* New era is not forced if too many validators are disabled.

Before this PR not all offenders were disabled. A decision was made
based on [`enum
DisableStrategy`](https://github.com/paritytech/polkadot-sdk/blob/bbb6631641f9adba30c0ee6f4d11023a424dd362/substrate/primitives/staking/src/offence.rs#L54).
Some offenders were disabled for a whole era, some just for a session,
some were not disabled at all.

This PR changes the disabling behaviour. Now a validator committing an
offense is disabled immediately till the end of the current era.

Some implementation notes:
* `OffendingValidators` in pallet session keeps all offenders (this is
not changed). However its type is changed from `Vec<(u32, bool)>` to
`Vec<u32>`. The reason is simple - each offender is getting disabled so
the bool doesn't make sense anymore.
* When a validator is disabled it is first added to
`OffendingValidators` and then to `DisabledValidators`. This is done in
[`add_offending_validator`](https://github.com/paritytech/polkadot-sdk/blob/bbb6631641f9adba30c0ee6f4d11023a424dd362/substrate/frame/staking/src/slashing.rs#L325)
from staking pallet.
* In
[`rotate_session`](https://github.com/paritytech/polkadot-sdk/blob/bdbe98297032e21a553bf191c530690b1d591405/substrate/frame/session/src/lib.rs#L623)
the `end_session` also calls
[`end_era`](https://github.com/paritytech/polkadot-sdk/blob/bbb6631641f9adba30c0ee6f4d11023a424dd362/substrate/frame/staking/src/pallet/impls.rs#L490)
when an era ends. In this case `OffendingValidators` are cleared
**(1)**.
* Then in
[`rotate_session`](https://github.com/paritytech/polkadot-sdk/blob/bdbe98297032e21a553bf191c530690b1d591405/substrate/frame/session/src/lib.rs#L623)
`DisabledValidators` are cleared **(2)**
* And finally (still in `rotate_session`) a call to
[`start_session`](https://github.com/paritytech/polkadot-sdk/blob/bbb6631641f9adba30c0ee6f4d11023a424dd362/substrate/frame/staking/src/pallet/impls.rs#L430)
repopulates the disabled validators **(3)**.
* The reason for this complication is that session pallet knows nothing
abut eras. To overcome this on each new session the disabled list is
repopulated (points 2 and 3). Staking pallet knows when a new era starts
so with point 1 it ensures that the offenders list is cleared.

---------

Co-authored-by: ordian <[email protected]>
Co-authored-by: ordian <[email protected]>
Co-authored-by: Maciej <[email protected]>
Co-authored-by: Gonçalo Pestana <[email protected]>
Co-authored-by: Kian Paimani <[email protected]>
Co-authored-by: command-bot <>
Co-authored-by: Ankan <[email protected]>
TarekkMA pushed a commit to moonbeam-foundation/polkadot-sdk that referenced this issue Aug 2, 2024
Closes paritytech#1966,
paritytech#1963 and
paritytech#1962.

Disabling strategy specification
[here](paritytech#2955). (Updated
13/02/2024)

Implements:
* validator disabling for a whole era instead of just a session
* no more than 1/3 of the validators in the active set are disabled
Removes:
* `DisableStrategy` enum - now each validator committing an offence is
disabled.
* New era is not forced if too many validators are disabled.

Before this PR not all offenders were disabled. A decision was made
based on [`enum
DisableStrategy`](https://github.com/paritytech/polkadot-sdk/blob/bbb6631641f9adba30c0ee6f4d11023a424dd362/substrate/primitives/staking/src/offence.rs#L54).
Some offenders were disabled for a whole era, some just for a session,
some were not disabled at all.

This PR changes the disabling behaviour. Now a validator committing an
offense is disabled immediately till the end of the current era.

Some implementation notes:
* `OffendingValidators` in pallet session keeps all offenders (this is
not changed). However its type is changed from `Vec<(u32, bool)>` to
`Vec<u32>`. The reason is simple - each offender is getting disabled so
the bool doesn't make sense anymore.
* When a validator is disabled it is first added to
`OffendingValidators` and then to `DisabledValidators`. This is done in
[`add_offending_validator`](https://github.com/paritytech/polkadot-sdk/blob/bbb6631641f9adba30c0ee6f4d11023a424dd362/substrate/frame/staking/src/slashing.rs#L325)
from staking pallet.
* In
[`rotate_session`](https://github.com/paritytech/polkadot-sdk/blob/bdbe98297032e21a553bf191c530690b1d591405/substrate/frame/session/src/lib.rs#L623)
the `end_session` also calls
[`end_era`](https://github.com/paritytech/polkadot-sdk/blob/bbb6631641f9adba30c0ee6f4d11023a424dd362/substrate/frame/staking/src/pallet/impls.rs#L490)
when an era ends. In this case `OffendingValidators` are cleared
**(1)**.
* Then in
[`rotate_session`](https://github.com/paritytech/polkadot-sdk/blob/bdbe98297032e21a553bf191c530690b1d591405/substrate/frame/session/src/lib.rs#L623)
`DisabledValidators` are cleared **(2)**
* And finally (still in `rotate_session`) a call to
[`start_session`](https://github.com/paritytech/polkadot-sdk/blob/bbb6631641f9adba30c0ee6f4d11023a424dd362/substrate/frame/staking/src/pallet/impls.rs#L430)
repopulates the disabled validators **(3)**.
* The reason for this complication is that session pallet knows nothing
abut eras. To overcome this on each new session the disabled list is
repopulated (points 2 and 3). Staking pallet knows when a new era starts
so with point 1 it ensures that the offenders list is cleared.

---------

Co-authored-by: ordian <[email protected]>
Co-authored-by: ordian <[email protected]>
Co-authored-by: Maciej <[email protected]>
Co-authored-by: Gonçalo Pestana <[email protected]>
Co-authored-by: Kian Paimani <[email protected]>
Co-authored-by: command-bot <>
Co-authored-by: Ankan <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Completed
Development

Successfully merging a pull request may close this issue.

4 participants