diff --git a/beacon-chain/core/epoch/precompute/slashing.go b/beacon-chain/core/epoch/precompute/slashing.go index 4faf703d1e3..dba22bbf210 100644 --- a/beacon-chain/core/epoch/precompute/slashing.go +++ b/beacon-chain/core/epoch/precompute/slashing.go @@ -1,6 +1,8 @@ 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" @@ -23,6 +25,25 @@ func ProcessSlashingsPrecompute(state *stateTrie.BeaconState, pBal *Balance) err 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 diff --git a/beacon-chain/core/epoch/precompute/slashing_test.go b/beacon-chain/core/epoch/precompute/slashing_test.go index dfef9a97ec7..4b435eb96bd 100644 --- a/beacon-chain/core/epoch/precompute/slashing_test.go +++ b/beacon-chain/core/epoch/precompute/slashing_test.go @@ -13,7 +13,7 @@ import ( "github.com/prysmaticlabs/prysm/shared/testutil/require" ) -func TestProcessSlashingsPrecompute_NotSlashed(t *testing.T) { +func TestProcessSlashingsPrecompute_NotSlashedWithSlashedTrue(t *testing.T) { s, err := beaconstate.InitializeFromProto(&pb.BeaconState{ Slot: 0, Validators: []*ethpb.Validator{{Slashed: true}}, @@ -28,6 +28,21 @@ func TestProcessSlashingsPrecompute_NotSlashed(t *testing.T) { assert.Equal(t, wanted, s.Balances()[0], "Unexpected slashed balance") } +func TestProcessSlashingsPrecompute_NotSlashedWithSlashedFalse(t *testing.T) { + s, err := beaconstate.InitializeFromProto(&pb.BeaconState{ + Slot: 0, + Validators: []*ethpb.Validator{{}}, + Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance}, + Slashings: []uint64{0, 1e9}, + }) + require.NoError(t, err) + pBal := &precompute.Balance{ActiveCurrentEpoch: params.BeaconConfig().MaxEffectiveBalance} + require.NoError(t, precompute.ProcessSlashingsPrecompute(s, pBal)) + + wanted := params.BeaconConfig().MaxEffectiveBalance + assert.Equal(t, wanted, s.Balances()[0], "Unexpected slashed balance") +} + func TestProcessSlashingsPrecompute_SlashedLess(t *testing.T) { tests := []struct { state *pb.BeaconState