Merge pull request #3882 from mkalinin/correlation-penalty-fix
EIP-7251: Update correlation penalty computation
This commit is contained in:
commit
6c3868c872
|
@ -71,6 +71,7 @@
|
|||
- [Epoch processing](#epoch-processing)
|
||||
- [Modified `process_epoch`](#modified-process_epoch)
|
||||
- [Modified `process_registry_updates`](#modified-process_registry_updates)
|
||||
- [Modified `process_slashings`](#modified-process_slashings)
|
||||
- [New `process_pending_balance_deposits`](#new-process_pending_balance_deposits)
|
||||
- [New `process_pending_consolidations`](#new-process_pending_consolidations)
|
||||
- [Modified `process_effective_balance_updates`](#modified-process_effective_balance_updates)
|
||||
|
@ -813,7 +814,7 @@ def process_epoch(state: BeaconState) -> None:
|
|||
process_inactivity_updates(state)
|
||||
process_rewards_and_penalties(state)
|
||||
process_registry_updates(state) # [Modified in Electra:EIP7251]
|
||||
process_slashings(state)
|
||||
process_slashings(state) # [Modified in Electra:EIP7251]
|
||||
process_eth1_data_reset(state)
|
||||
process_pending_balance_deposits(state) # [New in Electra:EIP7251]
|
||||
process_pending_consolidations(state) # [New in Electra:EIP7251]
|
||||
|
@ -850,6 +851,28 @@ def process_registry_updates(state: BeaconState) -> None:
|
|||
validator.activation_epoch = activation_epoch
|
||||
```
|
||||
|
||||
#### Modified `process_slashings`
|
||||
|
||||
*Note*: The function `process_slashings` is modified to use a new algorithm to compute correlation penalty.
|
||||
|
||||
```python
|
||||
def process_slashings(state: BeaconState) -> None:
|
||||
epoch = get_current_epoch(state)
|
||||
total_balance = get_total_active_balance(state)
|
||||
adjusted_total_slashing_balance = min(
|
||||
sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX,
|
||||
total_balance
|
||||
)
|
||||
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:
|
||||
effective_balance_increments = validator.effective_balance // increment
|
||||
# [Modified in Electra:EIP7251]
|
||||
penalty = penalty_per_effective_balance_increment * effective_balance_increments
|
||||
decrease_balance(state, ValidatorIndex(index), penalty)
|
||||
```
|
||||
|
||||
#### New `process_pending_balance_deposits`
|
||||
|
||||
```python
|
||||
|
|
|
@ -3,7 +3,11 @@ from eth2spec.test.context import spec_state_test, with_all_phases
|
|||
from eth2spec.test.helpers.epoch_processing import (
|
||||
run_epoch_processing_with, run_epoch_processing_to
|
||||
)
|
||||
from eth2spec.test.helpers.forks import is_post_altair, is_post_bellatrix
|
||||
from eth2spec.test.helpers.forks import (
|
||||
is_post_altair,
|
||||
is_post_bellatrix,
|
||||
is_post_electra,
|
||||
)
|
||||
from eth2spec.test.helpers.random import randomize_state
|
||||
from eth2spec.test.helpers.state import has_active_balance_differential
|
||||
from eth2spec.test.helpers.voluntary_exits import get_unslashed_exited_validators
|
||||
|
@ -40,6 +44,18 @@ def get_slashing_multiplier(spec):
|
|||
return spec.PROPORTIONAL_SLASHING_MULTIPLIER
|
||||
|
||||
|
||||
def _compute_expected_correlation_penalty(spec, effective_balance, total_slashed_balance, total_balance):
|
||||
if is_post_electra(spec):
|
||||
return ((get_slashing_multiplier(spec) * total_slashed_balance)
|
||||
// (total_balance // spec.EFFECTIVE_BALANCE_INCREMENT)
|
||||
* (effective_balance // spec.EFFECTIVE_BALANCE_INCREMENT))
|
||||
else:
|
||||
return (effective_balance // spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
* (get_slashing_multiplier(spec) * total_slashed_balance)
|
||||
// total_balance
|
||||
* spec.EFFECTIVE_BALANCE_INCREMENT)
|
||||
|
||||
|
||||
def _setup_process_slashings_test(spec, state, not_slashable_set=set()):
|
||||
# Slashed count to ensure that enough validators are slashed to induce maximum penalties
|
||||
slashed_count = min(
|
||||
|
@ -99,7 +115,8 @@ def test_minimal_penalty(spec, state):
|
|||
#
|
||||
|
||||
# Just the bare minimum for this one validator
|
||||
state.balances[0] = state.validators[0].effective_balance = spec.config.EJECTION_BALANCE
|
||||
state.balances[0] = state.validators[0].effective_balance = (
|
||||
spec.config.EJECTION_BALANCE + spec.EFFECTIVE_BALANCE_INCREMENT)
|
||||
# All the other validators get the maximum.
|
||||
for i in range(1, len(state.validators)):
|
||||
state.validators[i].effective_balance = state.balances[i] = spec.MAX_EFFECTIVE_BALANCE
|
||||
|
@ -119,15 +136,10 @@ def test_minimal_penalty(spec, state):
|
|||
spec.process_slashings(state)
|
||||
yield 'post', state
|
||||
|
||||
expected_penalty = (
|
||||
state.validators[0].effective_balance // spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
* (get_slashing_multiplier(spec) * total_penalties)
|
||||
// total_balance
|
||||
* spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
)
|
||||
expected_penalty = _compute_expected_correlation_penalty(
|
||||
spec, state.validators[0].effective_balance, total_penalties, total_balance)
|
||||
|
||||
assert expected_penalty == 0
|
||||
assert state.balances[0] == pre_slash_balances[0]
|
||||
assert state.balances[0] == pre_slash_balances[0] - expected_penalty
|
||||
|
||||
|
||||
@with_all_phases
|
||||
|
@ -181,12 +193,8 @@ def test_scaled_penalties(spec, state):
|
|||
|
||||
for i in slashed_indices:
|
||||
v = state.validators[i]
|
||||
expected_penalty = (
|
||||
v.effective_balance // spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
* (get_slashing_multiplier(spec) * total_penalties)
|
||||
// (total_balance)
|
||||
* spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
)
|
||||
expected_penalty = _compute_expected_correlation_penalty(
|
||||
spec, v.effective_balance, total_penalties, total_balance)
|
||||
assert state.balances[i] == pre_slash_balances[i] - expected_penalty
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue