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
|
@with_capella_and_later
|
||||||
@spec_state_test
|
@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_full_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 2
|
||||||
num_partial_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD - num_full_withdrawals
|
num_partial_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD - num_full_withdrawals
|
||||||
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals(
|
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals(
|
||||||
spec, state,
|
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)
|
next_slot(spec, state)
|
||||||
execution_payload = build_empty_execution_payload(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 (
|
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 (
|
from eth2spec.test.helpers.state import (
|
||||||
|
next_epoch_via_block,
|
||||||
state_transition_and_sign_block,
|
state_transition_and_sign_block,
|
||||||
|
transition_to,
|
||||||
|
transition_to_slot_via_block,
|
||||||
|
next_slot,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.block import (
|
from eth2spec.test.helpers.block import (
|
||||||
build_empty_block_for_next_slot,
|
build_empty_block_for_next_slot,
|
||||||
build_empty_block,
|
build_empty_block,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change
|
from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change
|
||||||
from eth2spec.test.helpers.state import (
|
from eth2spec.test.helpers.attestations import (
|
||||||
next_slot,
|
next_epoch_with_attestations,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.withdrawals import (
|
from eth2spec.test.helpers.withdrawals import (
|
||||||
|
set_eth1_withdrawal_credential_with_balance,
|
||||||
set_validator_fully_withdrawable,
|
set_validator_fully_withdrawable,
|
||||||
set_validator_partially_withdrawable,
|
set_validator_partially_withdrawable,
|
||||||
prepare_expected_withdrawals,
|
prepare_expected_withdrawals,
|
||||||
)
|
)
|
||||||
|
from eth2spec.test.helpers.deposits import (
|
||||||
|
prepare_state_and_deposit,
|
||||||
|
)
|
||||||
from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits
|
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 'blocks', [signed_block_2]
|
||||||
yield 'post', None
|
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()
|
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_UPGRADES = {key: value for key, value in ALL_FORK_UPGRADES.items() if key != PHASE0}
|
||||||
AFTER_BELLATRIX_PRE_POST_FORKS = AFTER_BELLATRIX_UPGRADES.items()
|
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
|
# Config
|
||||||
|
|
|
@ -9,6 +9,7 @@ from eth2spec.test.helpers.block import (
|
||||||
build_empty_block,
|
build_empty_block,
|
||||||
sign_block,
|
sign_block,
|
||||||
)
|
)
|
||||||
|
from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change
|
||||||
from eth2spec.test.helpers.constants import (
|
from eth2spec.test.helpers.constants import (
|
||||||
ALTAIR,
|
ALTAIR,
|
||||||
BELLATRIX,
|
BELLATRIX,
|
||||||
|
@ -36,6 +37,7 @@ class OperationType(Enum):
|
||||||
ATTESTER_SLASHING = auto()
|
ATTESTER_SLASHING = auto()
|
||||||
DEPOSIT = auto()
|
DEPOSIT = auto()
|
||||||
VOLUNTARY_EXIT = auto()
|
VOLUNTARY_EXIT = auto()
|
||||||
|
BLS_TO_EXECUTION_CHANGE = auto()
|
||||||
|
|
||||||
|
|
||||||
def _set_operations_by_dict(block, operation_dict):
|
def _set_operations_by_dict(block, operation_dict):
|
||||||
|
@ -267,6 +269,10 @@ def run_transition_with_operation(state,
|
||||||
selected_validator_index = 0
|
selected_validator_index = 0
|
||||||
signed_exits = prepare_signed_exits(spec, state, [selected_validator_index])
|
signed_exits = prepare_signed_exits(spec, state, [selected_validator_index])
|
||||||
operation_dict = {'voluntary_exits': signed_exits}
|
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():
|
def _check_state():
|
||||||
if operation_type == OperationType.PROPOSER_SLASHING:
|
if operation_type == OperationType.PROPOSER_SLASHING:
|
||||||
|
@ -288,6 +294,9 @@ def run_transition_with_operation(state,
|
||||||
elif operation_type == OperationType.VOLUNTARY_EXIT:
|
elif operation_type == OperationType.VOLUNTARY_EXIT:
|
||||||
validator = state.validators[selected_validator_index]
|
validator = state.validators[selected_validator_index]
|
||||||
assert validator.exit_epoch < post_spec.FAR_FUTURE_EPOCH
|
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
|
yield "pre", state
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,9 @@ def transition_to_slot_via_block(spec, state, slot):
|
||||||
Transition to ``slot`` via an empty block transition
|
Transition to ``slot`` via an empty block transition
|
||||||
"""
|
"""
|
||||||
assert state.slot < slot
|
assert state.slot < slot
|
||||||
apply_empty_block(spec, state, slot)
|
signed_block = apply_empty_block(spec, state, slot)
|
||||||
assert state.slot == slot
|
assert state.slot == slot
|
||||||
|
return signed_block
|
||||||
|
|
||||||
|
|
||||||
def transition_to_valid_shard_slot(spec, state):
|
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_slashing as test_altair_slashing,
|
||||||
test_operations as test_altair_operations,
|
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:
|
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__":
|
if __name__ == "__main__":
|
||||||
altair_tests = (
|
all_tests = (
|
||||||
test_altair_transition,
|
test_altair_transition,
|
||||||
test_altair_activations_and_exits,
|
test_altair_activations_and_exits,
|
||||||
test_altair_leaking,
|
test_altair_leaking,
|
||||||
test_altair_slashing,
|
test_altair_slashing,
|
||||||
test_altair_operations,
|
test_altair_operations,
|
||||||
|
test_eip4844_operations,
|
||||||
)
|
)
|
||||||
all_tests = altair_tests
|
|
||||||
for transition_test_module in all_tests:
|
for transition_test_module in all_tests:
|
||||||
for pre_fork, post_fork in ALL_PRE_POST_FORKS:
|
for pre_fork, post_fork in ALL_PRE_POST_FORKS:
|
||||||
gen_runner.run_generator("transition", [
|
gen_runner.run_generator("transition", [
|
||||||
|
|
Loading…
Reference in New Issue