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

Slashing: differentiating between stake bonded at the time of infraction and since the time of infraction #1440

Closed
cwgoes opened this issue Jun 28, 2018 · 11 comments

Comments

@cwgoes
Copy link
Contributor

cwgoes commented Jun 28, 2018

The semantics of slashing should be that voting power which contributed to an infraction is punished proportionally to the infraction's severity, and that voting power which did not contribute is not punished. This means we need to be able to reconstruct the changes in contributing stake to a validator up to an unbonding period in the past.

Redelegations and unbonding delegations give us sufficient information to identify and punish delegators who have since redelegated or unbonded, but we do not presently differentiate between stake which was delegated at the time of the infraction and still delegated at the time of discovery and stake which was delegated between the time of infraction and the time of discovery. The latter stake did not contribute to the infraction and per these desired semantics should not be slashable.

We could differentiate between these two categories of stake, with our current store model, by simply iterating over the delegations to a validator which is slashed, finding all the stake delegated since the infraction, and subtracting that stake from the validator's "slashable stake" (and adjusting the delegator's percentage of the validator's shares) - however, this is O(n) in the total number of delegations to the validator. Other possible approaches include keeping a time-sorted index of delegations, adding a secondary data structure for this purpose which can be deleted after an unbonding period, or just making the stake delegated since the infraction slashable anyways.

@rigelrozanski
Copy link
Contributor

Redelegations and unbonding delegations give us sufficient information to identify and punish delegators who have since redelegated or unbonded, but we do not presently differentiate between stake which was delegated at the time of the infraction and still delegated at the time of discovery and stake which was delegated between the time of infraction and the time of discovery. The latter stake did not contribute to the infraction and per these desired semantics should not be slashable.

Is this basically referring to "don't slash a delegator who just joined you and didn't contribute voting power to your nasty nasty move in a previous block" - right now it doesn't really matter if you just joined a validator or not - if you join and then that validator get's slashed your going to get the short end of the stick and (arguably maybe unfairly) get slashed

Yeah I mean it's arguable whether it's unfair behaviour or not - it's the same kind of problem of the other issue - if we allow for this kind of slashing to persist it would be considered slashing-by-association - which I don't think is the worst thing in the world

Maybe even we just want to keep this to keep the code base simpler and have less avenues for being spammed (spamvenues 😄)


but yeah basically if we kept an additional queue of delegations for the first unbonding period for which you have bonded to somebody then we could parse this information out and prevent this instance of slashing-by-association

@cwgoes
Copy link
Contributor Author

cwgoes commented Jun 29, 2018

Is this basically referring to "don't slash a delegator who just joined you and didn't contribute voting power to your nasty nasty move in a previous block" - right now it doesn't really matter if you just joined a validator or not - if you join and then that validator get's slashed your going to get the short end of the stick and (arguably maybe unfairly) get slashed

Yes, that's the behaviour at the moment. I don't know how likely it is to arise in practice, but it's a bit concerning because it can set up perverse incentives. It's not just that stake which delegated since an infraction also gets slashed - it's (maybe more concerningly) that stake which contributed to the infraction is slashed less if other stake delegates before the infraction is discovered.

For example, let's say users A and B are delegating 10 stake to validators 1 and 2 (who have no other delegators in this simple example). Validators 1 and 2 both commit equally slashable infractions (slash fraction 1/2) at time α, which are not discovered until time β. In between α and β, A convinces C to also delegate 10 stake to validator 1, while B does nothing.

At time β, both infractions are discovered, and validators 1 and 2 are each slashed by 5 stake (half of 10). Now, share and validator distributions are as follows:

Validator 1 has 15 stake (10 delegated from A + 10 delegated from C - 5 slashed)
Validator 2 has 5 stake (10 delegated from B - 5 slashed)

A and C each own 50% shares in validator 1, while B owns 100% shares in validator 2 - giving A an equivalent 7.5 stake and B an equivalent 5 stake. A and B committed equal severity offenses at the same time, but since A managed to convince C to delegate to A's validator before the offense was discovered, A has halved his punishment.

More generally, this means that if I am delegating to a validator and I believe it likely (for whatever reason) that my validator has committed an infraction, it's in my immediate best interest not to unbond (for if I did my stake would be slashable at the usual infraction rate), but rather to convince other delegators to delegate to my validator, so that I will be slashed less, effectively, at which point the infraction is discovered and published to the chain.

@cwgoes
Copy link
Contributor Author

cwgoes commented Jun 29, 2018

Another interesting attack: I start up a "fake" validator, with a small self-bond. I immediately commit an infraction or many infractions with high severity (several double-signs, for example) but do not publish them to the chain. I then spend the next unbonding period (or possibly much longer depending on the resolution of #1378) convincing delegators to delegate to me (maybe a particular delegator whose stake I want to burn). Once I have convinced this stake to delegate to me, I publish the infraction evidence and burn all delegated stake (an amount which may be arbitrarily more than my self-bond, the only stake which actually contributed to the infraction).

@ValarDragon
Copy link
Contributor

ValarDragon commented Jun 29, 2018

I definitely agree with you're points @cwgoes, and think this should be addressed.

I don't think this should be solved via an additional store / putting more things into a current store. I think instead that we should ensure that all full nodes contain all blocks within the last unbonding period handily accessible. Then when its been determined that there should be a slash, they query the store at the block which the double sign was on, and slash accordingly (time of infraction). I think this method makes it more clear as to what is going on. (Though has the downside of having to load one of the state trees, shouldn't be too bad though if we assume validators are running on ssd's)

@cwgoes
Copy link
Contributor Author

cwgoes commented Jun 29, 2018

I don't think this should be solved via an additional store. I think instead that we should ensure that all full nodes contain all blocks within the last unbonding period handily accessible. Then when its been determined that there should be a slash, they query the store at the block which the double sign was on, and slash accordingly (time of infraction).

We don't need to keep a full state archive for the unbonding period, just an archive of the staking store.

@rigelrozanski
Copy link
Contributor

(maybe more concerningly) that stake which contributed to the infraction is slashed less if other stake delegates before the infraction is discovered.

yeah if we were to leave this form of slashing in here we'd want to increase the amount of slashing to make sure that the original tokens contributing to the bad behaviour had an equal amount slashed independent of the discovery date. -> aka we just slash more than usual the later it's discovered -> however this now has new funky cryptoeconomic implications :( so yeah sounds like a good idea to do create "fair" slashing - aka don't screw the new delegators.

Let's do this 👍

cwgoes added a commit that referenced this issue Jun 30, 2018
Implement semifinal Gaia slashing spec (#1263), less #1348, #1378, and #1440 which are TBD.
adrianbrink pushed a commit that referenced this issue Jul 2, 2018
Implement semifinal Gaia slashing spec (#1263), less #1348, #1378, and #1440 which are TBD.
@cwgoes cwgoes self-assigned this Jul 25, 2018
@rigelrozanski
Copy link
Contributor

NOTE - slashing with different proportions of the current stake breaks a design constraint the distribution spec. This needs to be addressed (I think it probably is possible) if we update to this unproportional slashing as proposed

@cwgoes
Copy link
Contributor Author

cwgoes commented Aug 17, 2018

Tabled to post-launch by slashing design meeting.

@jaekwon
Copy link
Contributor

jaekwon commented Aug 17, 2018

I don't think we need to do this post-launch either, but lets have another discussion if needed? Delegators are responsible for ensuring that validators didn't commit a prior infraction, but I think that's minor compared to their existing responsibility of ensuring future security... and leaving as is appears to keep the logic simpler.

@rigelrozanski
Copy link
Contributor

we could compile a list of delegator responsibilities - that's the only action item I can think of for this. Let's close?

@cwgoes
Copy link
Contributor Author

cwgoes commented Aug 22, 2018

We could compile a list of delegator responsibilities - that's the only action item I can think of for this. Let's close?

I'm still not convinced that our implementation is ideal, but I agree that this ranks pretty low on the list of potential PoS problems. Closing in favor of #1678.

@cwgoes cwgoes closed this as completed Aug 22, 2018
@cwgoes cwgoes mentioned this issue Dec 18, 2018
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants