Skip to content
Merged
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
53 changes: 52 additions & 1 deletion tests/core/pyspec/eth2spec/test/phase0/sanity/test_slots.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
from eth2spec.test.helpers.forks import (
is_post_capella,
)
from eth2spec.test.helpers.state import get_state_root
from eth2spec.test.context import (
spec_state_test,
with_all_phases,
)
from eth2spec.test.helpers.state import (
get_state_root,
next_epoch,
next_slot,
transition_to
)


@with_all_phases
Expand Down Expand Up @@ -87,3 +92,49 @@ def test_historical_accumulator(spec, state):
assert len(state.historical_summaries) == len(pre_historical_summaries) + 1
else:
assert len(state.historical_roots) == len(pre_historical_roots) + 1


@with_all_phases
@spec_state_test
def test_balance_change_affects_proposer(spec, state):
# Brute-force an instance where a validator's balance change prevents it from proposing.
# We must brute-force this because sometimes the balance change doesn't make a difference.
# Give this approach 100 attempts to find such a case.
for _ in range(100):
original_state = state.copy()

# Get the proposer of the first slot in the next epoch
next_epoch_state = state.copy()
next_epoch(spec, next_epoch_state)
proposer_next_epoch = spec.get_beacon_proposer_index(next_epoch_state)

# Reduce the validator's balance, making it less likely to propose
# The validator's effective balance will be updated during epoch processing
spec.decrease_balance(state, proposer_next_epoch, 10 * spec.EFFECTIVE_BALANCE_INCREMENT)

# Check if the proposer changed as a result of the balance change
tmp_state = state.copy()
next_epoch(spec, tmp_state)
if proposer_next_epoch != spec.get_beacon_proposer_index(tmp_state):
# Use this state
break
else:
# Try another state
state = original_state.copy()
next_epoch(spec, state)

# Transition to the last slot of the current epoch
slot = state.slot + spec.SLOTS_PER_EPOCH - (state.slot % spec.SLOTS_PER_EPOCH) - 1
transition_to(spec, state, slot)

yield 'pre', state
yield 'slots', 1

# Transition to the next epoch
next_slot(spec, state)

yield 'post', state

# Verify that the proposer changed because of the balance change
proposer_next_epoch_after_change = spec.get_beacon_proposer_index(state)
assert proposer_next_epoch != proposer_next_epoch_after_change