package precompute import ( "errors" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/shared/mathutil" "github.com/prysmaticlabs/prysm/shared/params" ) // ProcessSlashingsPrecompute processes the slashed validators during epoch processing. // This is an optimized version by passing in precomputed total epoch balances. func ProcessSlashingsPrecompute(state *stateTrie.BeaconState, pBal *Balance) error { currentEpoch := helpers.CurrentEpoch(state) exitLength := params.BeaconConfig().EpochsPerSlashingsVector // Compute the sum of state slashings slashings := state.Slashings() totalSlashing := uint64(0) for _, slashing := range slashings { totalSlashing += slashing } minSlashing := mathutil.Min(totalSlashing*params.BeaconConfig().ProportionalSlashingMultiplier, pBal.ActiveCurrentEpoch) epochToWithdraw := currentEpoch + exitLength/2 vs := state.ValidatorsReadOnly() var hasSlashing bool // Iterate through validator list in state, stop until a validator satisfies slashing condition of current epoch. for _, v := range vs { if v == nil { return errors.New("nil validator in state") } correctEpoch := epochToWithdraw == v.WithdrawableEpoch() if v.Slashed() && correctEpoch { hasSlashing = true break } } // Exit early if there's no meaningful slashing to process. if !hasSlashing { return nil } increment := params.BeaconConfig().EffectiveBalanceIncrement validatorFunc := func(idx int, val *ethpb.Validator) (bool, error) { correctEpoch := epochToWithdraw == val.WithdrawableEpoch if val.Slashed && correctEpoch { penaltyNumerator := val.EffectiveBalance / increment * minSlashing penalty := penaltyNumerator / pBal.ActiveCurrentEpoch * increment if err := helpers.DecreaseBalance(state, uint64(idx), penalty); err != nil { return false, err } return true, nil } return false, nil } return state.ApplyToEveryValidator(validatorFunc) }