Terra's slashing module inherits from the Cosmos SDK's slashing module. This document is a stub and mainly covers important Terra-specific notes on how it is used.
The slashing module enables Terra to disincentivize any attributable action by a protocol-recognized actor with value at stake by penalizing them. The penalty is called slashing. Terra mainly uses the Staking module to slash a validator who violates their responsibilities. This module manages lower-level penalties at the Tendermint consensus level, such as double-signing.
This section was taken from the official Cosmos SDK docs, and placed here for your convenience to understand the slashing module's parameters.
At the beginning of each block, the slashing module checks for evidence of infractions or downtime of validators, double-signing, and other low-level consensus penalties.
Tendermint blocks can include evidence, which indicates that a validator committed malicious
behaviour. The relevant information is forwarded to the application as ABCI Evidence
in abci.RequestBeginBlock so that the validator an be punished.
For some Evidence submitted in block to be valid, it must satisfy:
where Evidence.Timestamp is the timestamp in the block at height
Evidence.Height, and block.Timestamp is the current block timestamp.
If valid evidence is included in a block, the validator's stake is reduced by
some penalty (SlashFractionDoubleSign for equivocation) of what their stake was
when the infraction occurred instead of when the evidence was discovered. We
want to follow the stake, i.e. the stake which contributed to the infraction
should be slashed, even if it has since been redelegated or has started unbonding.
The unbondings and redelegations from the slashed validator are looped through, and the amount of stake that has moved is tracked:
slashAmountUnbondings :=0
slashAmountRedelegations :=0
unbondings :=getUnbondings(validator.Address)
for unbond in unbondings {
if was not bonded before evidence.Height or started unbonding before unbonding period ago {
continue
}
burn := unbond.InitialTokens * SLASH_PROPORTION
slashAmountUnbondings += burn
unbond.Tokens =max(0, unbond.Tokens - burn)
}
// only care if source gets slashed because we're already bonded to destination
// so if destination validator gets slashed the delegation just has same shares
This process ensures that offending validators are punished with the same amount whether they act as a single validator with X stake or as N validators with a collective X stake. The amount slashed for all double-signature infractions committed within a single slashing period is capped. For more information, see tombstone caps.
At the beginning of each block, the ValidatorSigningInfo for each
validator is updated and whether they've crossed below the liveness threshold over a
sliding window is checked. This sliding window is defined by SignedBlocksWindow, and the
index in this window is determined by IndexOffset found in the validator's
ValidatorSigningInfo. For each block processed, the IndexOffset is incremented
regardless of whether the validator signed. After the index is determined, the
MissedBlocksBitArray and MissedBlocksCounter are updated accordingly.
Finally, to determine whether a validator crosses below the liveness threshold,
the maximum number of blocks missed, maxMissed, which is
SignedBlocksWindow - (MinSignedPerWindow * SignedBlocksWindow), and the minimum
height at which liveness can be determined, minHeight, are fetched. If the current block is
greater than minHeight and the validator's MissedBlocksCounter is greater than
maxMissed, they are slashed by SlashFractionDowntime, jailed
for DowntimeJailDuration, and have the following values reset:
MissedBlocksBitArray, MissedBlocksCounter, and IndexOffset.