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

Consider removing/simplifying SlashingSpans and SpanSlash from staking pallet #2650

Open
tdimitrov opened this issue Dec 7, 2023 · 5 comments

Comments

@tdimitrov
Copy link
Contributor

Currently SlashingSpans and SpanSlash are used only for keeping track if a validator needs to be chilled on an offence or not. Furthermore SpanSlash keeps track of slash and reward amount via SpanRecord but this values are never used. Also after #1962 is merged offenders no longer will be chilled in favour of disabling them.

Consider if slashing spans are used for a case I am missing or they can be completely removed.

cc @gpestana

@Overkillus
Copy link
Contributor

Archived PR introducing that logic: paritytech/substrate#3846

Archived PR links to a now removed paper explaining the design, but pretty sure that's the paper in question: https://github.com/w3f/research/blob/master/docs/Polkadot/security/slashing/npos.md


After my initial reading it seems like the system changes so drastically since its inception that the slashing span logic is mostly redundant. Nevertheless they present some properties which could still prove useful to maintain for our new strategy.

Main point of interest is if this assumption/goal still holds:

We demand that slashing never exceeds nominators' exposure because doing so creates an incentive to break up stash keys. We avoid encouraging such Sibel-ish behavior in Polkadot because doing so makes Polkadot less fair and harms our information about nominator behavior.

Above is the problem of overslashing right? Just to make sure I understand with an example:
a nominator has his nominated stake split into 2 portions for 2 different validators. If one of the validators gets slashed we want to slash only the part assigned to that validator and not the whole stake of the nominator. Is my understanding of the problem correct?

There seems to be some focus on the past era slashing which somewhat complicates maintaining the above property as we can slash someone during era e and then find some more offences in e+1 which would warrant extra slashes. Those slashes if applied cumulatively with the ones from e could easily exceed the base nominators' exposure. Although since all of our slashes are deferred by 27 eras (unbonding period) then can't we simply adjust the actual slash amounts that will be applied once we are sure everything in this era is finalized? Might me missing some crucial detail so call me out.

@burdges

@burdges
Copy link

burdges commented Dec 12, 2023

We could go through the document piece by piece and descide what still feels relevant. It'd be useful to reconstruct whatever recently looked useful for parachains too, but maybe that's why deferred slashing kept coming up. Anyways..

Yes, we do not want slashes to exceed exposure for several reasons, including (*) below. We've agreed on deferred slashing, yes? If so, yes we could simplify things by using deffered slashing I guess. How exactly?

We'd have spome deffered slashing queue, nominators are eligable for fast unstaking only if not in the queue, and fast unstaking still need some time like 24 hours, so all slashes should appear in the queue almost a full unbonding period before being applied.

All slashed account have a slashing log which contains the amount, validator, and slashing time. After the unbonding period aka 27 days, we process an individual slash maybe like this:

  • remove any expired slashing log entries older than 27 days,
  • compute the maximum m logged slashes caused by the same validator,
  • compute the slashed value like s = exposure * proportion,
  • add the slash to the log using the value s.
  • if positive, deduct s-m from the balance,

We'd discussed 100% slashed of course, but this document predates parachains, so it focuses upon equivocation offenses in babe and grandpa. In particular, approvals breaks this statement "only minimal concerns about multiple miss-behaviours from the same validator in one era", so soundness slashes could handle some max differently, but being 100% makes this unimportant.

(*) We do like when information about who control what DOTs surfaces through the slashing system. We could've the opposite perspective ala zk staking, but we do have whales so that's quite a big trade off. We've another concern here about overworking NPoS too, meaning it sucks if you can protect yourself by making NPoS slower.

@Overkillus
Copy link
Contributor

we've agreed on deferred slashing, yes?

Yes. The only point of contention was BEEFY but we did not handle that case (yet). It's a separate issue. All other offences will be deferred based on the un-bonding period IIRC.


Not sure I follow the design so let me reiterate some items:

We have a slashes/offences queue. Things are added to the queue chronologically so we also consume them in that order. Each item is processed 27 days after it is added. Queue holds the unprocessed offences.

There is a slashing log which contains your slashes which are cleared 27 days after being added.

Example:

Mostly for my own sanity in understanding it.

Example NPoS solution state:

nominator 1 --nominates--> val1 (with 100 tokens)
nominator 1 --nominates--> val2 (with 50 tokens)
nominator 2 --nominates--> val2 (with 50 tokens)

Example log state (nom1 perspective):

20d;    10 tokens;  val1
22d;    5 tokens;   val1
23d;    2 tokens;   val2

we have two values of m:

  • m1 for val1 is 10
  • m2 for val2 is 2

Example queue state:

[
   (27d, 100%, val2),
   (15d,   10%, val1)
]

when (27d, 100%, val2), reaches it's maturity at 27 days old we process the offence by calculating the slash value for all of val1 nominators:

  • nom1: slash = 50 * 100%
  • nom2: slash = 50 * 100%

We update the slash log (nom1 perspective):

0d;      50 tokens;   val1
20d;    10 tokens;   val1
22d;    5 tokens;     val1
23d;    2 tokens;     val2

We compute slash - m where m is the corresponding max for the appropriate validator. In case of the newly added slash corresponding m is m1 = 10. 50 - 10 > 0 so we deduct 50 - 10 = 40 from balance because hopefully the other 10 was already deduced before (5 and then another 5).

Questions

Do we even need slow 28 days un-bond at this point?

Honest people if queue is empty can simply fast unstake. Slashed users can submit their slow un-bond sure but it will execute only after 27 days. If they did it a few days after their offence it will execute a few days after they are penalised. At this point they could've waited for the fast-unstake after the queue is emptied and the slash is applied. Never using 28 days un-bond is literally optimal in every single scenario.

TLDR

Apply slashes 27 days after depositing them.
Slash only up to a max offence from the last 27 days.

@burdges
Copy link

burdges commented Dec 13, 2023

Not sure I follow the design so let me reiterate some items:

It's overly complex anyways, and tracking validator-nominator pairs suck. It also ignores one important detail.

All equivocation slashes determine their maximum slash level by correlation. Individually grandpa or babe equivocations matter little, so we slash maybe 0% but if many happen together then this precentage rises, until 100% in grandpa maybe.

Instead of simple maximums, we slash half of the incoming slash minus the total slashed in the slash log. We could avoid tracking validator-nominator pairs too I think:

A validator v havhase a slashing log L = {(p,t)} which contains the precentage and time. After the unbonding period aka 27 days, we process an individual slash maybe like this:

  • remove any expired slashing log entries older than 2*27 days,
  • compute the logged precentage slashed t like for each p in L { t += min(p-t,0) / 2 }
  • add the current slash s to the log
  • deduce min(s-t,0) * exposure from each nominator balance

In this, we largely ignore that multiple validators nominate the same validator. If V first gets A slashed, and then gets B slashed later, then B benefits dramatically from A being slashed first. Although unfortunate, I'm not sure this matters so much.

We coul do some similar computation on the the nominator side instead I guess, which afaik fixes this but causes other concerns, not sure the best options right now.

@Overkillus
Copy link
Contributor

Overkillus commented Dec 15, 2023

TODOs:

  • Verify how we use slashing spans as of now (only chilling?)
  • Check what logic we use to calculate max slashes and what timeframe/period is used for them as of now
  • Are we actually safe from overslashing in the current implementation?
  • Find concrete examples of when overslashing could occur so it's easier to design around them
  • Finalize new slashing design that slashes only max and protects from overslashing

@Overkillus Overkillus moved this from In Progress to Backlog in parachains team board Apr 11, 2024
@Overkillus Overkillus changed the title Consider removing SlashingSpans and SpanSlash from staking pallet Consider removing/simplifying SlashingSpans and SpanSlash from staking pallet Jun 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Backlog
Development

No branches or pull requests

3 participants