cosmos-sdk/docs/spec/slashing/state-machine.md
2018-08-13 17:52:58 +02:00

3.3 KiB

Transaction & State Machine Interaction Overview

Transactions

In this section we describe the processing of transactions for the slashing module.

TxUnjail

If a validator was automatically unbonded due to downtime and wishes to come back online & possibly rejoin the bonded set, it must send TxUnjail:

type TxUnjail struct {
    ValidatorAddr sdk.AccAddress
}

handleMsgUnjail(tx TxUnjail)

    validator := getValidator(tx.ValidatorAddr)
    if validator == nil
      fail with "No validator found"

    if !validator.Jailed
      fail with "Validator not jailed, cannot unjail"

    info := getValidatorSigningInfo(operator)
    if BlockHeader.Time.Before(info.JailedUntil)
      fail with "Validator still jailed, cannot unjail until period has expired"

    // Update the start height so the validator won't be immediately unbonded again
    info.StartHeight = BlockHeight
    setValidatorSigningInfo(info)

    validator.Jailed = false
    setValidator(validator)

    return

If the validater has enough stake to be in the top hundred, they will be automatically rebonded, and all delegators still delegated to the validator will be rebonded and begin to again collect provisions and rewards.

Interactions

In this section we describe the "hooks" - slashing module code that runs when other events happen.

Validator Bonded

Upon successful bonding of a validator (a given validator changing from "unbonded" state to "bonded" state, which may happen on delegation, on unjailing, etc), we create a new SlashingPeriod structure for the now-bonded validator, wich StartHeight of the current block, EndHeight of 0 (sentinel value for not-yet-ended), and SlashedSoFar of 0:

onValidatorBonded(address sdk.ValAddress)

  slashingPeriod := SlashingPeriod{
      ValidatorAddr : address,
      StartHeight   : CurrentHeight,
      EndHeight     : 0,    
      SlashedSoFar  : 0,
  }
  setSlashingPeriod(slashingPeriod)
  
  return

Validator Unbonded

When a validator is unbonded, we update the in-progress SlashingPeriod with the current block as the EndHeight:

onValidatorUnbonded(address sdk.ValAddress)

  slashingPeriod = getSlashingPeriod(address, CurrentHeight)
  slashingPeriod.EndHeight = CurrentHeight
  setSlashingPeriod(slashingPeriod)

  return

Validator Slashed

When a validator is slashed, we look up the appropriate SlashingPeriod based on the validator address and the time of infraction, cap the fraction slashed as max(SlashFraction, SlashedSoFar) (which may be 0), and update the SlashingPeriod with the increased SlashedSoFar:

beforeValidatorSlashed(address sdk.ValAddress, fraction sdk.Rat, infractionHeight int64)
  
  slashingPeriod = getSlashingPeriod(address, infractionHeight)
  totalToSlash = max(slashingPeriod.SlashedSoFar, fraction)
  slashingPeriod.SlashedSoFar = totalToSlash
  setSlashingPeriod(slashingPeriod)

  remainderToSlash = slashingPeriod.SlashedSoFar - totalToSlash
  fraction = remainderToSlash

  continue with slashing

State Cleanup

Once no evidence for a given slashing period can possibly be valid (the end time plus the unbonding period is less than the current time), old slashing periods should be cleaned up. This will be implemented post-launch.