{"action":"opened","issue":{"url":"https://api.github.com/repos/cosmos/cosmos-sdk/issues/1896","repository_url":"https://api.github.com/repos/cosmos/cosmos-sdk","labels_url":"https://api.github.com/repos/cosmos/cosmos-sdk/issues/1896/labels{/name}","comments_url":"https://api.github.com/repos/cosmos/cosmos-sdk/issues/1896/comments","events_url":"https://api.github.com/repos/cosmos/cosmos-sdk/issues/1896/events","html_url":"https://github.com/cosmos/cosmos-sdk/issues/1896","id":346316020,"node_id":"MDU6SXNzdWUzNDYzMTYwMjA=","number":1896,"title":"Slashing spec changes: capped slashing-per-period","user":{"login":"cwgoes","id":24760279,"node_id":"MDQ6VXNlcjI0NzYwMjc5","avatar_url":"https://avatars2.githubusercontent.com/u/24760279?v=4","gravatar_id":"","url":"https://api.github.com/users/cwgoes","html_url":"https://github.com/cwgoes","followers_url":"https://api.github.com/users/cwgoes/followers","following_url":"https://api.github.com/users/cwgoes/following{/other_user}","gists_url":"https://api.github.com/users/cwgoes/gists{/gist_id}","starred_url":"https://api.github.com/users/cwgoes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cwgoes/subscriptions","organizations_url":"https://api.github.com/users/cwgoes/orgs","repos_url":"https://api.github.com/users/cwgoes/repos","events_url":"https://api.github.com/users/cwgoes/events{/privacy}","received_events_url":"https://api.github.com/users/cwgoes/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-07-31T18:56:42Z","updated_at":"2018-07-31T18:56:42Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"As discussed in the slashing design meeting, introduce the concept of a \"slashing period\":\r\n\r\n**Slashing period**:\r\n\r\nA slashing period is a start and end time associated with a particular validator, within which only the \"worst infraction counts\": the total amount of slashing for infractions committed within the period (and discovered whenever) is capped at the penalty for the worst offense.\r\n\r\nThis period starts when a validator is first bonded and ends when a validator is slashed & revoked for double-signing (but does *not* end if they are slashed & revoked for just missing blocks). When the validator voluntarily unrevokes themselves (and possibly changes signing keys), they reset the period.\r\n\r\n**Implementation sketch**:\r\n1. Create a `SlashingPeriod` structure:\r\n```golang\r\ntype SlashingPeriod struct {\r\n  ValidatorAddr sdk.AccAddress\r\n  StartTime uint64\r\n  EndTime uint64\r\n  FractionSlashedSoFar sdk.Rat\r\n}\r\n```\r\n\r\n1. When a validator is first bonded, create a new `SlashingPeriod` structure for the validator, with the `StartTime` of the current block, a sentinel `EndTime` of `0`, and `FractionSlashedSoFar` of `0`.\r\n\r\n1. When `stakeKeeper.Slash()` is called, lookup the appropriate `SlashingPeriod` based on the time-of-infraction, cap the fraction slashed at `MaxFractionSlashedPerPeriod - FractionSlashedSoFar`, possibly `0` (where `MaxFractionSlashedPerPeriod` is a configuration parameter), and update the `SlashingPeriod` struct with the increased `FractionSlashedSoFar`.\r\n    1. Additionally, if the validator is unbonded as part of this slash, set `EndTime` of the current `SlashingPeriod` to the current block time.\r\n\r\n1. When a validator is unrevoked, look up its newest `SlashingPeriod`. If that `SlashingPeriod` has already ended (`EndTime` is nonzero), create a new `SlashingPeriod` as in (1).\r\n\r\n1. Somehow cleanup old `SlashingPeriod` structures once no evidence could possibly be valid (depends on a resolution https://github.com/cosmos/cosmos-sdk/issues/1378 among others)\r\n\r\n**Concerns**:\r\n\r\n1. Safety\r\n    1. No disincentive for committing more protocol faults (at past heights) after you've already committed the worst offense (and it has been discovered). I guess it's unclear how much this matters in practice - if we slash a lot for just one double-sign, that may be enough of a disincentive - hard to predict.\r\n1. Implementation\r\n    1. Slashing is capped fractionally per period, but the amount of total bonded stake associated with the validator can change (by an unbounded amount) over that period. For example, with `MaxFractionSlashedPerPeriod = 0.5`, if a validator is initially slashed at `0.4` near the start of a period when they have `100` steak bonded, then later slashed at `0.4` when they have `1000` steak bonded, the total amount slashed is just `40 + 100 = 140` (since the latter slash is capped at `0.1`) - whereas if they had `1000` steak bonded initially, the total amount slashed would have been `500`. One possible way to avoid this problem is to track a `MaxStakeBonded` in the `SlashingPeriod` (which must be updated every time the validator's power changes), and instead cap the total slashing amount (in tokens) within a period by `MaxStakeBonded * MaxFractionSlashedPerPeriod`.\r\n    1. May create unusual incentives for delegators - if you see that a validator can only be slashed by `X` amount more, it's now less risky to delegate to. This is not an issue if all the slashing events which change the `SlashingPeriod` also revoke the validator.\r\n    1. Some (minor) state bloat from old `SlashingPeriod`s"}}
{"actor":{"display_login":"cwgoes"}}