Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EIP-7251: Update correlation penalty computation #3882

Merged
merged 2 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion specs/electra/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
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
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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


Expand Down