Merge pull request #3227 from ethereum/more-capella-tests
More capella tests
This commit is contained in:
commit
26d233aec5
|
@ -147,12 +147,14 @@ def test_success_one_partial_withdrawal(spec, state):
|
|||
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_max_per_slot(spec, state):
|
||||
def test_success_mixed_fully_and_partial_withdrawable(spec, state):
|
||||
num_full_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 2
|
||||
num_partial_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD - num_full_withdrawals
|
||||
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals(
|
||||
spec, state,
|
||||
num_full_withdrawals=num_full_withdrawals, num_partial_withdrawals=num_partial_withdrawals)
|
||||
num_full_withdrawals=num_full_withdrawals,
|
||||
num_partial_withdrawals=num_partial_withdrawals,
|
||||
)
|
||||
|
||||
next_slot(spec, state)
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
|
|
|
@ -1,22 +1,34 @@
|
|||
from eth2spec.test.helpers.constants import MINIMAL
|
||||
from eth2spec.test.context import (
|
||||
with_capella_and_later, spec_state_test
|
||||
with_capella_and_later,
|
||||
spec_state_test,
|
||||
with_presets,
|
||||
)
|
||||
from eth2spec.test.helpers.keys import pubkeys
|
||||
from eth2spec.test.helpers.state import (
|
||||
next_epoch_via_block,
|
||||
state_transition_and_sign_block,
|
||||
transition_to,
|
||||
transition_to_slot_via_block,
|
||||
next_slot,
|
||||
)
|
||||
from eth2spec.test.helpers.block import (
|
||||
build_empty_block_for_next_slot,
|
||||
build_empty_block,
|
||||
)
|
||||
from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change
|
||||
from eth2spec.test.helpers.state import (
|
||||
next_slot,
|
||||
from eth2spec.test.helpers.attestations import (
|
||||
next_epoch_with_attestations,
|
||||
)
|
||||
from eth2spec.test.helpers.withdrawals import (
|
||||
set_eth1_withdrawal_credential_with_balance,
|
||||
set_validator_fully_withdrawable,
|
||||
set_validator_partially_withdrawable,
|
||||
prepare_expected_withdrawals,
|
||||
)
|
||||
from eth2spec.test.helpers.deposits import (
|
||||
prepare_state_and_deposit,
|
||||
)
|
||||
from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits
|
||||
|
||||
|
||||
|
@ -255,3 +267,154 @@ def test_invalid_withdrawal_fail_second_block_payload_isnt_compatible(spec, stat
|
|||
|
||||
yield 'blocks', [signed_block_2]
|
||||
yield 'post', None
|
||||
|
||||
|
||||
#
|
||||
# Mix top-ups and withdrawals
|
||||
#
|
||||
|
||||
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_top_up_and_partial_withdrawable_validator(spec, state):
|
||||
next_withdrawal_validator_index = 0
|
||||
validator_index = next_withdrawal_validator_index + 1
|
||||
|
||||
set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, spec.MAX_EFFECTIVE_BALANCE)
|
||||
validator = state.validators[validator_index]
|
||||
balance = state.balances[validator_index]
|
||||
assert not spec.is_partially_withdrawable_validator(validator, balance)
|
||||
|
||||
# Make a top-up balance to validator
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||
|
||||
yield 'pre', state
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
block.body.deposits.append(deposit)
|
||||
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
|
||||
yield 'blocks', [signed_block]
|
||||
yield 'post', state
|
||||
|
||||
# Since withdrawals happen before deposits, it becomes partially withdrawable after state transition.
|
||||
validator = state.validators[validator_index]
|
||||
balance = state.balances[validator_index]
|
||||
assert spec.is_partially_withdrawable_validator(validator, balance)
|
||||
|
||||
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_top_up_to_fully_withdrawn_validator(spec, state):
|
||||
"""
|
||||
Similar to `teste_process_deposit::test_success_top_up_to_withdrawn_validator` test.
|
||||
"""
|
||||
next_withdrawal_validator_index = 0
|
||||
validator_index = next_withdrawal_validator_index + 1
|
||||
|
||||
# Fully withdraw validator
|
||||
set_validator_fully_withdrawable(spec, state, validator_index)
|
||||
assert state.balances[validator_index] > 0
|
||||
next_epoch_via_block(spec, state)
|
||||
assert state.balances[validator_index] == 0
|
||||
assert state.validators[validator_index].effective_balance > 0
|
||||
next_epoch_via_block(spec, state)
|
||||
assert state.validators[validator_index].effective_balance == 0
|
||||
|
||||
# Make a top-up deposit to validator
|
||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||
|
||||
yield 'pre', state
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
block.body.deposits.append(deposit)
|
||||
|
||||
signed_block_1 = state_transition_and_sign_block(spec, state, block)
|
||||
|
||||
assert spec.is_fully_withdrawable_validator(
|
||||
state.validators[validator_index],
|
||||
state.balances[validator_index],
|
||||
spec.get_current_epoch(state)
|
||||
)
|
||||
|
||||
# Apply an empty block
|
||||
signed_block_2 = transition_to_slot_via_block(spec, state, state.slot + 1)
|
||||
|
||||
# With mainnet preset, it holds
|
||||
if len(state.validators) <= spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP:
|
||||
assert not spec.is_fully_withdrawable_validator(
|
||||
state.validators[validator_index],
|
||||
state.balances[validator_index],
|
||||
spec.get_current_epoch(state)
|
||||
)
|
||||
|
||||
yield 'blocks', [signed_block_1, signed_block_2]
|
||||
yield 'post', state
|
||||
|
||||
|
||||
def _insert_validator(spec, state, balance):
|
||||
effective_balance = balance if balance < spec.MAX_EFFECTIVE_BALANCE else spec.MAX_EFFECTIVE_BALANCE
|
||||
validator_index = len(state.validators)
|
||||
validator = spec.Validator(
|
||||
pubkey=pubkeys[validator_index],
|
||||
withdrawal_credentials=spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + b'\x00' * 11 + b'\x56' * 20,
|
||||
activation_eligibility_epoch=1,
|
||||
activation_epoch=2,
|
||||
exit_epoch=spec.FAR_FUTURE_EPOCH,
|
||||
withdrawable_epoch=spec.FAR_FUTURE_EPOCH,
|
||||
effective_balance=effective_balance,
|
||||
)
|
||||
state.validators.append(validator)
|
||||
state.balances.append(balance)
|
||||
state.previous_epoch_participation.append(spec.ParticipationFlags(0b0000_0000))
|
||||
state.current_epoch_participation.append(spec.ParticipationFlags(0b0000_0000))
|
||||
state.inactivity_scores.append(0)
|
||||
|
||||
return validator_index
|
||||
|
||||
|
||||
def _run_activate_and_partial_withdrawal(spec, state, initial_balance):
|
||||
validator_index = _insert_validator(spec, state, balance=initial_balance)
|
||||
|
||||
# To make it eligibile activation
|
||||
transition_to(spec, state, spec.compute_start_slot_at_epoch(2) - 1)
|
||||
assert not spec.is_active_validator(state.validators[validator_index], spec.get_current_epoch(state))
|
||||
|
||||
yield 'pre', state
|
||||
|
||||
blocks = []
|
||||
# To activate
|
||||
signed_block = transition_to_slot_via_block(spec, state, state.slot + 1)
|
||||
blocks.append(signed_block)
|
||||
|
||||
assert spec.is_active_validator(state.validators[validator_index], spec.get_current_epoch(state))
|
||||
|
||||
if initial_balance > spec.MAX_EFFECTIVE_BALANCE:
|
||||
assert spec.is_partially_withdrawable_validator(
|
||||
state.validators[validator_index], state.balances[validator_index])
|
||||
else:
|
||||
assert not spec.is_partially_withdrawable_validator(
|
||||
state.validators[validator_index], state.balances[validator_index])
|
||||
|
||||
_, new_blocks, state = next_epoch_with_attestations(spec, state, True, True)
|
||||
blocks += new_blocks
|
||||
|
||||
yield 'blocks', blocks
|
||||
yield 'post', state
|
||||
|
||||
|
||||
@with_capella_and_later
|
||||
@with_presets([MINIMAL], reason="too many validators with mainnet config")
|
||||
@spec_state_test
|
||||
def test_activate_and_partial_withdrawal_max_effective_balance(spec, state):
|
||||
yield from _run_activate_and_partial_withdrawal(spec, state, initial_balance=spec.MAX_EFFECTIVE_BALANCE)
|
||||
|
||||
|
||||
@with_capella_and_later
|
||||
@with_presets([MINIMAL], reason="too many validators with mainnet config")
|
||||
@spec_state_test
|
||||
def test_activate_and_partial_withdrawal_overdeposit(spec, state):
|
||||
yield from _run_activate_and_partial_withdrawal(spec, state, initial_balance=spec.MAX_EFFECTIVE_BALANCE + 10000000)
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
from eth2spec.test.context import (
|
||||
ForkMeta,
|
||||
always_bls,
|
||||
with_fork_metas,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import (
|
||||
AFTER_DENEB_PRE_POST_FORKS,
|
||||
)
|
||||
from eth2spec.test.helpers.fork_transition import (
|
||||
OperationType,
|
||||
run_transition_with_operation,
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# BLSToExecutionChange
|
||||
#
|
||||
|
||||
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2)
|
||||
for pre, post in AFTER_DENEB_PRE_POST_FORKS])
|
||||
@always_bls
|
||||
def test_transition_with_btec_right_after_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||
"""
|
||||
Create a BLS_TO_EXECUTION_CHANGE right *after* the transition
|
||||
"""
|
||||
yield from run_transition_with_operation(
|
||||
state,
|
||||
fork_epoch,
|
||||
spec,
|
||||
post_spec,
|
||||
pre_tag,
|
||||
post_tag,
|
||||
operation_type=OperationType.BLS_TO_EXECUTION_CHANGE,
|
||||
operation_at_slot=fork_epoch * spec.SLOTS_PER_EPOCH,
|
||||
)
|
||||
|
||||
|
||||
@with_fork_metas([ForkMeta(pre_fork_name=pre, post_fork_name=post, fork_epoch=2)
|
||||
for pre, post in AFTER_DENEB_PRE_POST_FORKS])
|
||||
@always_bls
|
||||
def test_transition_with_btec_right_before_fork(state, fork_epoch, spec, post_spec, pre_tag, post_tag):
|
||||
"""
|
||||
Create a BLS_TO_EXECUTION_CHANGE right *before* the transition
|
||||
"""
|
||||
yield from run_transition_with_operation(
|
||||
state,
|
||||
fork_epoch,
|
||||
spec,
|
||||
post_spec,
|
||||
pre_tag,
|
||||
post_tag,
|
||||
operation_type=OperationType.BLS_TO_EXECUTION_CHANGE,
|
||||
operation_at_slot=fork_epoch * spec.SLOTS_PER_EPOCH - 1,
|
||||
)
|
|
@ -37,6 +37,12 @@ ALL_FORK_UPGRADES = {
|
|||
ALL_PRE_POST_FORKS = ALL_FORK_UPGRADES.items()
|
||||
AFTER_BELLATRIX_UPGRADES = {key: value for key, value in ALL_FORK_UPGRADES.items() if key != PHASE0}
|
||||
AFTER_BELLATRIX_PRE_POST_FORKS = AFTER_BELLATRIX_UPGRADES.items()
|
||||
AFTER_CAPELLA_UPGRADES = {key: value for key, value in ALL_FORK_UPGRADES.items()
|
||||
if key not in [PHASE0, ALTAIR]}
|
||||
AFTER_CAPELLA_PRE_POST_FORKS = AFTER_CAPELLA_UPGRADES.items()
|
||||
AFTER_DENEB_UPGRADES = {key: value for key, value in ALL_FORK_UPGRADES.items()
|
||||
if key not in [PHASE0, ALTAIR, BELLATRIX]}
|
||||
AFTER_DENEB_PRE_POST_FORKS = AFTER_DENEB_UPGRADES.items()
|
||||
|
||||
#
|
||||
# Config
|
||||
|
|
|
@ -9,6 +9,7 @@ from eth2spec.test.helpers.block import (
|
|||
build_empty_block,
|
||||
sign_block,
|
||||
)
|
||||
from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change
|
||||
from eth2spec.test.helpers.constants import (
|
||||
ALTAIR,
|
||||
BELLATRIX,
|
||||
|
@ -36,6 +37,7 @@ class OperationType(Enum):
|
|||
ATTESTER_SLASHING = auto()
|
||||
DEPOSIT = auto()
|
||||
VOLUNTARY_EXIT = auto()
|
||||
BLS_TO_EXECUTION_CHANGE = auto()
|
||||
|
||||
|
||||
def _set_operations_by_dict(block, operation_dict):
|
||||
|
@ -267,6 +269,10 @@ def run_transition_with_operation(state,
|
|||
selected_validator_index = 0
|
||||
signed_exits = prepare_signed_exits(spec, state, [selected_validator_index])
|
||||
operation_dict = {'voluntary_exits': signed_exits}
|
||||
elif operation_type == OperationType.BLS_TO_EXECUTION_CHANGE:
|
||||
selected_validator_index = 0
|
||||
bls_to_execution_changes = [get_signed_address_change(spec, state, selected_validator_index)]
|
||||
operation_dict = {'bls_to_execution_changes': bls_to_execution_changes}
|
||||
|
||||
def _check_state():
|
||||
if operation_type == OperationType.PROPOSER_SLASHING:
|
||||
|
@ -288,6 +294,9 @@ def run_transition_with_operation(state,
|
|||
elif operation_type == OperationType.VOLUNTARY_EXIT:
|
||||
validator = state.validators[selected_validator_index]
|
||||
assert validator.exit_epoch < post_spec.FAR_FUTURE_EPOCH
|
||||
elif operation_type == OperationType.BLS_TO_EXECUTION_CHANGE:
|
||||
validator = state.validators[selected_validator_index]
|
||||
assert validator.withdrawal_credentials[:1] == spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
||||
|
||||
yield "pre", state
|
||||
|
||||
|
|
|
@ -38,8 +38,9 @@ def transition_to_slot_via_block(spec, state, slot):
|
|||
Transition to ``slot`` via an empty block transition
|
||||
"""
|
||||
assert state.slot < slot
|
||||
apply_empty_block(spec, state, slot)
|
||||
signed_block = apply_empty_block(spec, state, slot)
|
||||
assert state.slot == slot
|
||||
return signed_block
|
||||
|
||||
|
||||
def transition_to_valid_shard_slot(spec, state):
|
||||
|
|
|
@ -16,6 +16,9 @@ from eth2spec.test.altair.transition import (
|
|||
test_slashing as test_altair_slashing,
|
||||
test_operations as test_altair_operations,
|
||||
)
|
||||
from eth2spec.test.eip4844.transition import (
|
||||
test_operations as test_eip4844_operations,
|
||||
)
|
||||
|
||||
|
||||
def create_provider(tests_src, preset_name: str, pre_fork_name: str, post_fork_name: str) -> gen_typing.TestProvider:
|
||||
|
@ -37,14 +40,14 @@ def create_provider(tests_src, preset_name: str, pre_fork_name: str, post_fork_n
|
|||
|
||||
|
||||
if __name__ == "__main__":
|
||||
altair_tests = (
|
||||
all_tests = (
|
||||
test_altair_transition,
|
||||
test_altair_activations_and_exits,
|
||||
test_altair_leaking,
|
||||
test_altair_slashing,
|
||||
test_altair_operations,
|
||||
test_eip4844_operations,
|
||||
)
|
||||
all_tests = altair_tests
|
||||
for transition_test_module in all_tests:
|
||||
for pre_fork, post_fork in ALL_PRE_POST_FORKS:
|
||||
gen_runner.run_generator("transition", [
|
||||
|
|
Loading…
Reference in New Issue