github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evidence/spec/06_begin_block.md (about)

     1  <!--
     2  order: 6
     3  -->
     4  
     5  # BeginBlock
     6  
     7  ## Evidence Handling
     8  
     9  Tendermint blocks can include
    10  [Evidence](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/blockchain.md#evidence),
    11  which indicates that a validator committed malicious behavior. The relevant information is
    12  forwarded to the application as ABCI Evidence in `abci.RequestBeginBlock` so that
    13  the validator an be accordingly punished.
    14  
    15  ### Equivocation
    16  
    17  Currently, the evidence module only handles evidence of type `Equivocation` which is derived from
    18  Tendermint's `ABCIEvidenceTypeDuplicateVote` during `BeginBlock`.
    19  
    20  For some `Equivocation` submitted in `block` to be valid, it must satisfy:
    21  
    22  `Evidence.Timestamp >= block.Timestamp - MaxEvidenceAge`
    23  
    24  Where `Evidence.Timestamp` is the timestamp in the block at height `Evidence.Height` and
    25  `block.Timestamp` is the current block timestamp.
    26  
    27  If valid `Equivocation` evidence is included in a block, the validator's stake is
    28  reduced (slashed) by `SlashFractionDoubleSign`, which is defined by the `x/slashing` module,
    29  of what their stake was when the infraction occurred (rather than when the evidence was discovered).
    30  We want to "follow the stake", i.e. the stake which contributed to the infraction
    31  should be slashed, even if it has since been redelegated or started unbonding.
    32  
    33  In addition, the validator is permanently jailed and tombstoned making it impossible for that
    34  validator to ever re-enter the validator set.
    35  
    36  The `Equivocation` evidence is handled as follows:
    37  
    38  ```go
    39  func (k Keeper) HandleDoubleSign(ctx Context, evidence Equivocation) {
    40    consAddr := evidence.GetConsensusAddress()
    41    infractionHeight := evidence.GetHeight()
    42  
    43    // calculate the age of the evidence
    44    blockTime := ctx.BlockHeader().Time
    45    age := blockTime.Sub(evidence.GetTime())
    46  
    47    // reject evidence we cannot handle
    48    if _, err := k.slashingKeeper.GetPubkey(ctx, consAddr.Bytes()); err != nil {
    49      return
    50    }
    51  
    52    // reject evidence if it is too old
    53    if age > k.MaxEvidenceAge(ctx) {
    54      return
    55    }
    56  
    57    // reject evidence if the validator is already unbonded
    58    validator := k.stakingKeeper.ValidatorByConsAddr(ctx, consAddr)
    59    if validator == nil || validator.IsUnbonded() {
    60      return
    61    }
    62  
    63    // verify the validator has signing info in order to be slashed and tombstoned
    64    if ok := k.slashingKeeper.HasValidatorSigningInfo(ctx, consAddr); !ok {
    65      panic(...)
    66    }
    67  
    68    // reject evidence if the validator is already tombstoned
    69    if k.slashingKeeper.IsTombstoned(ctx, consAddr) {
    70      return
    71    }
    72  
    73    // We need to retrieve the stake distribution which signed the block, so we
    74    // subtract ValidatorUpdateDelay from the evidence height.
    75    // Note, that this *can* result in a negative "distributionHeight", up to
    76    // -ValidatorUpdateDelay, i.e. at the end of the
    77    // pre-genesis block (none) = at the beginning of the genesis block.
    78    // That's fine since this is just used to filter unbonding delegations & redelegations.
    79    distributionHeight := infractionHeight - sdk.ValidatorUpdateDelay
    80  
    81    // Slash validator. The `power` is the int64 power of the validator as provided
    82    // to/by Tendermint. This value is validator.Tokens as sent to Tendermint via
    83    // ABCI, and now received as evidence. The fraction is passed in to separately
    84    // to slash unbonding and rebonding delegations.
    85    k.slashingKeeper.Slash(ctx, consAddr, evidence.GetValidatorPower(), distributionHeight)
    86  
    87    // Jail the validator if not already jailed. This will begin unbonding the
    88    // validator if not already unbonding (tombstoned).
    89    if !validator.IsJailed() {
    90      k.slashingKeeper.Jail(ctx, consAddr)
    91    }
    92  
    93    k.slashingKeeper.JailUntil(ctx, consAddr, types.DoubleSignJailEndTime)
    94    k.slashingKeeper.Tombstone(ctx, consAddr)
    95  }
    96  ```
    97  
    98  Note, the slashing, jailing, and tombstoning calls are delegated through the `x/slashing` module
    99  which emit informative events and finally delegate calls to the `x/staking` module. Documentation
   100  on slashing and jailing can be found in the [x/staking spec](/.././cosmos-sdk/x/staking/spec/02_state_transitions.md)