mirror of
https://github.com/status-im/eth2.0-specs.git
synced 2025-02-02 22:03:37 +00:00
Add basic activation churn limit tests
This commit is contained in:
parent
298a6304de
commit
417b95c3e6
@ -151,4 +151,4 @@ WHISK_EPOCHS_PER_SHUFFLING_PHASE: 256
|
||||
WHISK_PROPOSER_SELECTION_GAP: 2
|
||||
|
||||
# EIP7668
|
||||
MAX_PER_EPOCH_INBOUND_CHURN_LIMIT: 12
|
||||
MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 12
|
||||
|
@ -85,8 +85,8 @@ INACTIVITY_SCORE_BIAS: 4
|
||||
INACTIVITY_SCORE_RECOVERY_RATE: 16
|
||||
# 2**4 * 10**9 (= 16,000,000,000) Gwei
|
||||
EJECTION_BALANCE: 16000000000
|
||||
# 2**2 (= 4)
|
||||
MIN_PER_EPOCH_CHURN_LIMIT: 4
|
||||
# [customized]
|
||||
MIN_PER_EPOCH_CHURN_LIMIT: 2
|
||||
# [customized] scale queue churn at much lower validator counts for testing
|
||||
CHURN_LIMIT_QUOTIENT: 32
|
||||
|
||||
@ -150,4 +150,5 @@ WHISK_EPOCHS_PER_SHUFFLING_PHASE: 4
|
||||
WHISK_PROPOSER_SELECTION_GAP: 1
|
||||
|
||||
# EIP7668
|
||||
MAX_PER_EPOCH_INBOUND_CHURN_LIMIT: 12
|
||||
# [customized]
|
||||
MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 4
|
||||
|
@ -44,7 +44,7 @@ def get_validator_activation_churn_limit(state: BeaconState) -> uint64:
|
||||
"""
|
||||
Return the validator activation churn limit for the current epoch.
|
||||
"""
|
||||
return min(MAX_PER_EPOCH_INBOUND_CHURN_LIMIT, get_validator_churn_limit(state))
|
||||
return min(MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT, get_validator_churn_limit(state))
|
||||
```
|
||||
|
||||
## Beacon chain state transition function
|
||||
|
@ -165,14 +165,34 @@ def default_balances(spec: Spec):
|
||||
return [spec.MAX_EFFECTIVE_BALANCE] * num_validators
|
||||
|
||||
|
||||
def scaled_churn_balances(spec: Spec):
|
||||
def scaled_churn_balances_min_churn_limit(spec: Spec):
|
||||
"""
|
||||
Helper method to create enough validators to scale the churn limit.
|
||||
(This is *firmly* over the churn limit -- thus the +2 instead of just +1)
|
||||
See the second argument of ``max`` in ``get_validator_churn_limit``.
|
||||
Usage: `@with_custom_state(balances_fn=scaled_churn_balances, ...)`
|
||||
Usage: `@with_custom_state(balances_fn=scaled_churn_balances_min_churn_limit, ...)`
|
||||
"""
|
||||
num_validators = spec.config.CHURN_LIMIT_QUOTIENT * (2 + spec.config.MIN_PER_EPOCH_CHURN_LIMIT)
|
||||
num_validators = spec.config.CHURN_LIMIT_QUOTIENT * (spec.config.MIN_PER_EPOCH_CHURN_LIMIT + 2)
|
||||
return [spec.MAX_EFFECTIVE_BALANCE] * num_validators
|
||||
|
||||
|
||||
def scaled_churn_balances_equal_inbound_churn_limit(spec: Spec):
|
||||
"""
|
||||
Helper method to create enough validators to scale the churn limit.
|
||||
(This is *firmly* over the churn limit -- thus the +2 instead of just +1)
|
||||
Usage: `@with_custom_state(balances_fn=scaled_churn_balances_exceed_inbound_churn_limit, ...)`
|
||||
"""
|
||||
num_validators = spec.config.CHURN_LIMIT_QUOTIENT * (spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT)
|
||||
return [spec.MAX_EFFECTIVE_BALANCE] * num_validators
|
||||
|
||||
|
||||
def scaled_churn_balances_exceed_inbound_churn_limit(spec: Spec):
|
||||
"""
|
||||
Helper method to create enough validators to scale the churn limit.
|
||||
(This is *firmly* over the churn limit -- thus the +2 instead of just +1)
|
||||
Usage: `@with_custom_state(balances_fn=scaled_churn_balances_exceed_inbound_churn_limit, ...)`
|
||||
"""
|
||||
num_validators = spec.config.CHURN_LIMIT_QUOTIENT * (spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT + 2)
|
||||
return [spec.MAX_EFFECTIVE_BALANCE] * num_validators
|
||||
|
||||
|
||||
@ -548,6 +568,7 @@ with_capella_and_later = with_all_phases_from(CAPELLA)
|
||||
with_deneb_and_later = with_all_phases_from(DENEB)
|
||||
with_eip6110_and_later = with_all_phases_from(EIP6110)
|
||||
with_eip7002_and_later = with_all_phases_from(EIP7002)
|
||||
with_eip7668_and_later = with_all_phases_from(EIP7668)
|
||||
|
||||
|
||||
class quoted_str(str):
|
||||
|
0
tests/core/pyspec/eth2spec/test/eip7668/__init__.py
Normal file
0
tests/core/pyspec/eth2spec/test/eip7668/__init__.py
Normal file
@ -0,0 +1,86 @@
|
||||
from eth2spec.test.helpers.keys import pubkeys
|
||||
from eth2spec.test.helpers.constants import MINIMAL
|
||||
from eth2spec.test.context import (
|
||||
with_eip7668_and_later,
|
||||
spec_test,
|
||||
spec_state_test,
|
||||
single_phase,
|
||||
with_custom_state,
|
||||
with_presets,
|
||||
scaled_churn_balances_exceed_inbound_churn_limit,
|
||||
scaled_churn_balances_equal_inbound_churn_limit,
|
||||
)
|
||||
from eth2spec.test.helpers.epoch_processing import run_epoch_processing_with
|
||||
|
||||
|
||||
def run_process_registry_updates(spec, state):
|
||||
yield from run_epoch_processing_with(spec, state, 'process_registry_updates')
|
||||
|
||||
|
||||
def run_test_inbound_churn_limit(spec, state):
|
||||
mock_activations = 1
|
||||
|
||||
for i in range(mock_activations):
|
||||
index = len(state.validators) + i
|
||||
validator = spec.Validator(
|
||||
pubkey=pubkeys[index],
|
||||
withdrawal_credentials=spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + b'\x00' * 11 + b'\x56' * 20,
|
||||
activation_eligibility_epoch=0,
|
||||
activation_epoch=spec.FAR_FUTURE_EPOCH,
|
||||
exit_epoch=spec.FAR_FUTURE_EPOCH,
|
||||
withdrawable_epoch=spec.FAR_FUTURE_EPOCH,
|
||||
effective_balance=spec.MAX_EFFECTIVE_BALANCE,
|
||||
)
|
||||
state.validators.append(validator)
|
||||
state.balances.append(spec.MAX_EFFECTIVE_BALANCE)
|
||||
state.previous_epoch_participation.append(spec.ParticipationFlags(0b0000_0000))
|
||||
state.current_epoch_participation.append(spec.ParticipationFlags(0b0000_0000))
|
||||
state.inactivity_scores.append(0)
|
||||
state.validators[index].activation_epoch = spec.FAR_FUTURE_EPOCH
|
||||
|
||||
churn_limit_0 = spec.get_validator_activation_churn_limit(state)
|
||||
|
||||
yield from run_process_registry_updates(spec, state)
|
||||
|
||||
# Half should churn in first run of registry update
|
||||
for i in range(mock_activations):
|
||||
if i < churn_limit_0:
|
||||
assert state.validators[i].activation_epoch < spec.FAR_FUTURE_EPOCH
|
||||
else:
|
||||
assert state.validators[i].activation_epoch == spec.FAR_FUTURE_EPOCH
|
||||
|
||||
|
||||
@with_eip7668_and_later
|
||||
@with_presets([MINIMAL],
|
||||
reason="mainnet config leads to larger validator set than limit of public/private keys pre-generated")
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=scaled_churn_balances_exceed_inbound_churn_limit,
|
||||
threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@single_phase
|
||||
def test_inbound_churn_limit__greater_than_inbound_limit(spec, state):
|
||||
assert spec.get_validator_activation_churn_limit(state) == spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT
|
||||
assert spec.get_validator_churn_limit(state) > spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT
|
||||
yield from run_test_inbound_churn_limit(spec, state)
|
||||
|
||||
|
||||
@with_eip7668_and_later
|
||||
@with_presets([MINIMAL],
|
||||
reason="mainnet config leads to larger validator set than limit of public/private keys pre-generated")
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=scaled_churn_balances_equal_inbound_churn_limit,
|
||||
threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@single_phase
|
||||
def test_inbound_churn_limit__equal_to_inbound_limit(spec, state):
|
||||
assert spec.get_validator_activation_churn_limit(state) == spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT
|
||||
assert spec.get_validator_churn_limit(state) == spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT
|
||||
yield from run_test_inbound_churn_limit(spec, state)
|
||||
|
||||
|
||||
@with_eip7668_and_later
|
||||
@with_presets([MINIMAL],
|
||||
reason="mainnet config leads to larger validator set than limit of public/private keys pre-generated")
|
||||
@spec_state_test
|
||||
def test_inbound_churn_limit__less_than_inbound_limit(spec, state):
|
||||
assert spec.get_validator_activation_churn_limit(state) < spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT
|
||||
assert spec.get_validator_churn_limit(state) < spec.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT
|
||||
yield from run_test_inbound_churn_limit(spec, state)
|
@ -46,3 +46,7 @@ def is_post_eip6110(spec):
|
||||
|
||||
def is_post_eip7002(spec):
|
||||
return is_post_fork(spec.fork, EIP7002)
|
||||
|
||||
|
||||
def is_post_eip7668(spec):
|
||||
return is_post_fork(spec.fork, EIP7668)
|
||||
|
@ -5,7 +5,7 @@ from eth2spec.test.context import (
|
||||
spec_test, spec_state_test,
|
||||
with_all_phases, single_phase,
|
||||
with_custom_state, with_presets,
|
||||
scaled_churn_balances,
|
||||
scaled_churn_balances_min_churn_limit,
|
||||
)
|
||||
from eth2spec.test.helpers.epoch_processing import run_epoch_processing_with
|
||||
|
||||
@ -164,7 +164,8 @@ def test_activation_queue_efficiency_min(spec, state):
|
||||
@with_presets([MINIMAL],
|
||||
reason="mainnet config leads to larger validator set than limit of public/private keys pre-generated")
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=scaled_churn_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=scaled_churn_balances_min_churn_limit,
|
||||
threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@single_phase
|
||||
def test_activation_queue_efficiency_scaled(spec, state):
|
||||
assert spec.get_validator_churn_limit(state) > spec.config.MIN_PER_EPOCH_CHURN_LIMIT
|
||||
@ -227,7 +228,8 @@ def test_ejection_past_churn_limit_min(spec, state):
|
||||
@with_presets([MINIMAL],
|
||||
reason="mainnet config leads to larger validator set than limit of public/private keys pre-generated")
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=scaled_churn_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=scaled_churn_balances_min_churn_limit,
|
||||
threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@single_phase
|
||||
def test_ejection_past_churn_limit_scaled(spec, state):
|
||||
assert spec.get_validator_churn_limit(state) > spec.config.MIN_PER_EPOCH_CHURN_LIMIT
|
||||
@ -324,7 +326,8 @@ def test_activation_queue_activation_and_ejection__exceed_churn_limit(spec, stat
|
||||
@with_presets([MINIMAL],
|
||||
reason="mainnet config leads to larger validator set than limit of public/private keys pre-generated")
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=scaled_churn_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=scaled_churn_balances_min_churn_limit,
|
||||
threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@single_phase
|
||||
def test_activation_queue_activation_and_ejection__scaled_churn_limit(spec, state):
|
||||
churn_limit = spec.get_validator_churn_limit(state)
|
||||
@ -336,7 +339,8 @@ def test_activation_queue_activation_and_ejection__scaled_churn_limit(spec, stat
|
||||
@with_presets([MINIMAL],
|
||||
reason="mainnet config leads to larger validator set than limit of public/private keys pre-generated")
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=scaled_churn_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=scaled_churn_balances_min_churn_limit,
|
||||
threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@single_phase
|
||||
def test_activation_queue_activation_and_ejection__exceed_scaled_churn_limit(spec, state):
|
||||
churn_limit = spec.get_validator_churn_limit(state)
|
||||
|
Loading…
x
Reference in New Issue
Block a user