diff --git a/CHANGELOG.md b/CHANGELOG.md index f71d58c6ff6e..c4463e28efb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -101,6 +101,7 @@ Updating to this release is recommended at your convenience. - Updated Sepolia bootnodes. - Make committee aware packing the default by deprecating `--enable-committee-aware-packing`. - Moved `ConvertKzgCommitmentToVersionedHash` to the `primitives` package. +- Updated correlation penalty for EIP-7251. ### Deprecated - `--disable-grpc-gateway` flag is deprecated due to grpc gateway removal. diff --git a/beacon-chain/core/epoch/epoch_processing.go b/beacon-chain/core/epoch/epoch_processing.go index e1adcc390237..19464abaa91d 100644 --- a/beacon-chain/core/epoch/epoch_processing.go +++ b/beacon-chain/core/epoch/epoch_processing.go @@ -147,11 +147,17 @@ func ProcessRegistryUpdates(ctx context.Context, st state.BeaconState) (state.Be // epoch = get_current_epoch(state) // total_balance = get_total_active_balance(state) // adjusted_total_slashing_balance = min(sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER, total_balance) +// if state.version == electra: +// increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from total balance to avoid uint64 overflow +// penalty_per_effective_balance_increment = adjusted_total_slashing_balance // (total_balance // increment) // for index, validator in enumerate(state.validators): // if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch: // increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow // penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance // penalty = penalty_numerator // total_balance * increment +// if state.version == electra: +// effective_balance_increments = validator.effective_balance // increment +// penalty = penalty_per_effective_balance_increment * effective_balance_increments // decrease_balance(state, ValidatorIndex(index), penalty) func ProcessSlashings(st state.BeaconState, slashingMultiplier uint64) (state.BeaconState, error) { currentEpoch := time.CurrentEpoch(st) @@ -177,13 +183,26 @@ func ProcessSlashings(st state.BeaconState, slashingMultiplier uint64) (state.Be // below equally. increment := params.BeaconConfig().EffectiveBalanceIncrement minSlashing := math.Min(totalSlashing*slashingMultiplier, totalBalance) + + // Modified in Electra:EIP7251 + var penaltyPerEffectiveBalanceIncrement uint64 + if st.Version() >= version.Electra { + penaltyPerEffectiveBalanceIncrement = minSlashing / (totalBalance / increment) + } + bals := st.Balances() changed := false err = st.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error { correctEpoch := (currentEpoch + exitLength/2) == val.WithdrawableEpoch() if val.Slashed() && correctEpoch { - penaltyNumerator := val.EffectiveBalance() / increment * minSlashing - penalty := penaltyNumerator / totalBalance * increment + var penalty uint64 + if st.Version() >= version.Electra { + effectiveBalanceIncrements := val.EffectiveBalance() / increment + penalty = penaltyPerEffectiveBalanceIncrement * effectiveBalanceIncrements + } else { + penaltyNumerator := val.EffectiveBalance() / increment * minSlashing + penalty = penaltyNumerator / totalBalance * increment + } bals[idx] = helpers.DecreaseBalanceWithVal(bals[idx], penalty) changed = true } diff --git a/beacon-chain/core/epoch/epoch_processing_test.go b/beacon-chain/core/epoch/epoch_processing_test.go index caeee1a1b25d..f9bb3b594923 100644 --- a/beacon-chain/core/epoch/epoch_processing_test.go +++ b/beacon-chain/core/epoch/epoch_processing_test.go @@ -448,3 +448,75 @@ func TestProcessHistoricalDataUpdate(t *testing.T) { }) } } + +func TestProcessSlashings_SlashedElectra(t *testing.T) { + tests := []struct { + state *ethpb.BeaconStateElectra + want uint64 + }{ + { + state: ðpb.BeaconStateElectra{ + Validators: []*ethpb.Validator{ + {Slashed: true, + WithdrawableEpoch: params.BeaconConfig().EpochsPerSlashingsVector / 2, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}, + {ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}}, + Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance}, + Slashings: []uint64{0, 1e9}, + }, + want: uint64(29000000000), + }, + { + state: ðpb.BeaconStateElectra{ + Validators: []*ethpb.Validator{ + {Slashed: true, + WithdrawableEpoch: params.BeaconConfig().EpochsPerSlashingsVector / 2, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}, + {ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}, + {ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}, + }, + Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance}, + Slashings: []uint64{0, 1e9}, + }, + want: uint64(30500000000), + }, + { + state: ðpb.BeaconStateElectra{ + Validators: []*ethpb.Validator{ + {Slashed: true, + WithdrawableEpoch: params.BeaconConfig().EpochsPerSlashingsVector / 2, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra}, + {ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra}, + {ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra}, + }, + Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance * 10, params.BeaconConfig().MaxEffectiveBalance * 20}, + Slashings: []uint64{0, 2 * 1e9}, + }, + want: uint64(317000001536), + }, + { + state: ðpb.BeaconStateElectra{ + Validators: []*ethpb.Validator{ + {Slashed: true, + WithdrawableEpoch: params.BeaconConfig().EpochsPerSlashingsVector / 2, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra - params.BeaconConfig().EffectiveBalanceIncrement}, + {ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra - params.BeaconConfig().EffectiveBalanceIncrement}}, + Balances: []uint64{params.BeaconConfig().MaxEffectiveBalanceElectra - params.BeaconConfig().EffectiveBalanceIncrement, params.BeaconConfig().MaxEffectiveBalanceElectra - params.BeaconConfig().EffectiveBalanceIncrement}, + Slashings: []uint64{0, 1e9}, + }, + want: uint64(2044000000727), + }, + } + + for i, tt := range tests { + t.Run(fmt.Sprint(i), func(t *testing.T) { + original := proto.Clone(tt.state) + s, err := state_native.InitializeFromProtoElectra(tt.state) + require.NoError(t, err) + helpers.ClearCache() + newState, err := epoch.ProcessSlashings(s, params.BeaconConfig().ProportionalSlashingMultiplierBellatrix) + require.NoError(t, err) + assert.Equal(t, tt.want, newState.Balances()[0], "ProcessSlashings({%v}) = newState; newState.Balances[0] = %d", original, newState.Balances()[0]) + }) + } +} diff --git a/testing/spectest/mainnet/electra/epoch_processing/slashings_test.go b/testing/spectest/mainnet/electra/epoch_processing/slashings_test.go index 22ebd4911e35..f5d3d2f7b95a 100644 --- a/testing/spectest/mainnet/electra/epoch_processing/slashings_test.go +++ b/testing/spectest/mainnet/electra/epoch_processing/slashings_test.go @@ -7,6 +7,5 @@ import ( ) func TestMainnet_Electra_EpochProcessing_Slashings(t *testing.T) { - t.Skip("slashing processing missing") epoch_processing.RunSlashingsTests(t, "mainnet") } diff --git a/testing/spectest/minimal/electra/epoch_processing/slashings_test.go b/testing/spectest/minimal/electra/epoch_processing/slashings_test.go index 4e46fb557cdb..2271afdf262a 100644 --- a/testing/spectest/minimal/electra/epoch_processing/slashings_test.go +++ b/testing/spectest/minimal/electra/epoch_processing/slashings_test.go @@ -7,6 +7,5 @@ import ( ) func TestMinimal_Electra_EpochProcessing_Slashings(t *testing.T) { - t.Skip("slashing processing missing") epoch_processing.RunSlashingsTests(t, "minimal") }