mirror of
https://github.com/ethereum/consensus-specs.git
synced 2026-02-02 23:34:58 -05:00
Merge branch 'dev' into proto-merge-test-gen
This commit is contained in:
@@ -101,7 +101,7 @@ def test_bad_source_root(state):
|
||||
attestation = get_valid_attestation(state)
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
attestation.data.source_root = b'\x42'*32
|
||||
attestation.data.source_root = b'\x42' * 32
|
||||
|
||||
pre_state, post_state = run_attestation_processing(state, attestation, False)
|
||||
|
||||
@@ -112,7 +112,7 @@ def test_non_zero_crosslink_data_root(state):
|
||||
attestation = get_valid_attestation(state)
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
attestation.data.crosslink_data_root = b'\x42'*32
|
||||
attestation.data.crosslink_data_root = b'\x42' * 32
|
||||
|
||||
pre_state, post_state = run_attestation_processing(state, attestation, False)
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ def run_attester_slashing_processing(state, attester_slashing, valid=True):
|
||||
|
||||
slashed_index = attester_slashing.attestation_1.custody_bit_0_indices[0]
|
||||
slashed_validator = post_state.validator_registry[slashed_index]
|
||||
assert not slashed_validator.initiated_exit
|
||||
assert slashed_validator.slashed
|
||||
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
||||
|
||||
@@ -54,7 +54,7 @@ def test_invalid_slot(state):
|
||||
|
||||
def test_invalid_previous_block_root(state):
|
||||
block = build_empty_block_for_next_slot(state)
|
||||
block.previous_block_root = b'\12'*32 # invalid prev root
|
||||
block.previous_block_root = b'\12' * 32 # invalid prev root
|
||||
|
||||
pre_state, post_state = run_block_header_processing(state, block, valid=False)
|
||||
return pre_state, block, None
|
||||
|
||||
@@ -15,8 +15,8 @@ from phase0.helpers import (
|
||||
)
|
||||
|
||||
|
||||
# mark entire file as 'voluntary_exits'
|
||||
pytestmark = pytest.mark.voluntary_exits
|
||||
# mark entire file as 'deposits'
|
||||
pytestmark = pytest.mark.deposits
|
||||
|
||||
|
||||
def test_success(state):
|
||||
|
||||
@@ -30,7 +30,6 @@ def run_proposer_slashing_processing(state, proposer_slashing, valid=True):
|
||||
process_proposer_slashing(post_state, proposer_slashing)
|
||||
|
||||
slashed_validator = post_state.validator_registry[proposer_slashing.proposer_index]
|
||||
assert not slashed_validator.initiated_exit
|
||||
assert slashed_validator.slashed
|
||||
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
||||
|
||||
@@ -5,6 +5,7 @@ import eth2spec.phase0.spec as spec
|
||||
|
||||
from eth2spec.phase0.spec import (
|
||||
get_active_validator_indices,
|
||||
get_churn_limit,
|
||||
get_current_epoch,
|
||||
process_voluntary_exit,
|
||||
)
|
||||
@@ -18,158 +19,145 @@ from phase0.helpers import (
|
||||
pytestmark = pytest.mark.voluntary_exits
|
||||
|
||||
|
||||
def test_success(state):
|
||||
pre_state = deepcopy(state)
|
||||
#
|
||||
# setup pre_state
|
||||
#
|
||||
# move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
|
||||
pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
def run_voluntary_exit_processing(state, voluntary_exit, valid=True):
|
||||
"""
|
||||
Run ``process_voluntary_exit`` returning the pre and post state.
|
||||
If ``valid == False``, run expecting ``AssertionError``
|
||||
"""
|
||||
post_state = deepcopy(state)
|
||||
|
||||
#
|
||||
# build voluntary exit
|
||||
#
|
||||
current_epoch = get_current_epoch(pre_state)
|
||||
validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]
|
||||
if not valid:
|
||||
with pytest.raises(AssertionError):
|
||||
process_voluntary_exit(post_state, voluntary_exit)
|
||||
return state, None
|
||||
|
||||
process_voluntary_exit(post_state, voluntary_exit)
|
||||
|
||||
validator_index = voluntary_exit.validator_index
|
||||
assert state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||
assert post_state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||
|
||||
return state, post_state
|
||||
|
||||
|
||||
def test_success(state):
|
||||
# move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = get_current_epoch(state)
|
||||
validator_index = get_active_validator_indices(state, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
||||
|
||||
voluntary_exit = build_voluntary_exit(
|
||||
pre_state,
|
||||
state,
|
||||
current_epoch,
|
||||
validator_index,
|
||||
privkey,
|
||||
)
|
||||
|
||||
post_state = deepcopy(pre_state)
|
||||
pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit)
|
||||
return pre_state, voluntary_exit, post_state
|
||||
|
||||
#
|
||||
# test valid exit
|
||||
#
|
||||
process_voluntary_exit(post_state, voluntary_exit)
|
||||
|
||||
assert not pre_state.validator_registry[validator_index].initiated_exit
|
||||
assert post_state.validator_registry[validator_index].initiated_exit
|
||||
def test_success_exit_queue(state):
|
||||
# move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = get_current_epoch(state)
|
||||
|
||||
# exit `MAX_EXITS_PER_EPOCH`
|
||||
initial_indices = get_active_validator_indices(state, current_epoch)[:get_churn_limit(state)]
|
||||
post_state = state
|
||||
for index in initial_indices:
|
||||
privkey = pubkey_to_privkey[state.validator_registry[index].pubkey]
|
||||
voluntary_exit = build_voluntary_exit(
|
||||
state,
|
||||
current_epoch,
|
||||
index,
|
||||
privkey,
|
||||
)
|
||||
|
||||
pre_state, post_state = run_voluntary_exit_processing(post_state, voluntary_exit)
|
||||
|
||||
# exit an additional validator
|
||||
validator_index = get_active_validator_indices(state, current_epoch)[-1]
|
||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
||||
voluntary_exit = build_voluntary_exit(
|
||||
state,
|
||||
current_epoch,
|
||||
validator_index,
|
||||
privkey,
|
||||
)
|
||||
|
||||
pre_state, post_state = run_voluntary_exit_processing(post_state, voluntary_exit)
|
||||
|
||||
assert (
|
||||
post_state.validator_registry[validator_index].exit_epoch ==
|
||||
post_state.validator_registry[initial_indices[0]].exit_epoch + 1
|
||||
)
|
||||
|
||||
return pre_state, voluntary_exit, post_state
|
||||
|
||||
|
||||
def test_validator_not_active(state):
|
||||
pre_state = deepcopy(state)
|
||||
current_epoch = get_current_epoch(pre_state)
|
||||
validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]
|
||||
current_epoch = get_current_epoch(state)
|
||||
validator_index = get_active_validator_indices(state, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
||||
|
||||
#
|
||||
# setup pre_state
|
||||
#
|
||||
pre_state.validator_registry[validator_index].activation_epoch = spec.FAR_FUTURE_EPOCH
|
||||
state.validator_registry[validator_index].activation_epoch = spec.FAR_FUTURE_EPOCH
|
||||
|
||||
#
|
||||
# build and test voluntary exit
|
||||
#
|
||||
voluntary_exit = build_voluntary_exit(
|
||||
pre_state,
|
||||
state,
|
||||
current_epoch,
|
||||
validator_index,
|
||||
privkey,
|
||||
)
|
||||
|
||||
with pytest.raises(AssertionError):
|
||||
process_voluntary_exit(pre_state, voluntary_exit)
|
||||
|
||||
return pre_state, voluntary_exit, None
|
||||
pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit, False)
|
||||
return pre_state, voluntary_exit, post_state
|
||||
|
||||
|
||||
def test_validator_already_exited(state):
|
||||
pre_state = deepcopy(state)
|
||||
#
|
||||
# setup pre_state
|
||||
#
|
||||
# move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow validator able to exit
|
||||
pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = get_current_epoch(pre_state)
|
||||
validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]
|
||||
current_epoch = get_current_epoch(state)
|
||||
validator_index = get_active_validator_indices(state, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
||||
|
||||
# but validator already has exited
|
||||
pre_state.validator_registry[validator_index].exit_epoch = current_epoch + 2
|
||||
state.validator_registry[validator_index].exit_epoch = current_epoch + 2
|
||||
|
||||
#
|
||||
# build voluntary exit
|
||||
#
|
||||
voluntary_exit = build_voluntary_exit(
|
||||
pre_state,
|
||||
state,
|
||||
current_epoch,
|
||||
validator_index,
|
||||
privkey,
|
||||
)
|
||||
|
||||
with pytest.raises(AssertionError):
|
||||
process_voluntary_exit(pre_state, voluntary_exit)
|
||||
|
||||
return pre_state, voluntary_exit, None
|
||||
|
||||
|
||||
def test_validator_already_initiated_exit(state):
|
||||
pre_state = deepcopy(state)
|
||||
#
|
||||
# setup pre_state
|
||||
#
|
||||
# move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow validator able to exit
|
||||
pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = get_current_epoch(pre_state)
|
||||
validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]
|
||||
|
||||
# but validator already has initiated exit
|
||||
pre_state.validator_registry[validator_index].initiated_exit = True
|
||||
|
||||
#
|
||||
# build voluntary exit
|
||||
#
|
||||
voluntary_exit = build_voluntary_exit(
|
||||
pre_state,
|
||||
current_epoch,
|
||||
validator_index,
|
||||
privkey,
|
||||
)
|
||||
|
||||
with pytest.raises(AssertionError):
|
||||
process_voluntary_exit(pre_state, voluntary_exit)
|
||||
|
||||
return pre_state, voluntary_exit, None
|
||||
pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit, False)
|
||||
return pre_state, voluntary_exit, post_state
|
||||
|
||||
|
||||
def test_validator_not_active_long_enough(state):
|
||||
pre_state = deepcopy(state)
|
||||
#
|
||||
# setup pre_state
|
||||
#
|
||||
current_epoch = get_current_epoch(pre_state)
|
||||
validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]
|
||||
current_epoch = get_current_epoch(state)
|
||||
validator_index = get_active_validator_indices(state, current_epoch)[0]
|
||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
||||
|
||||
# but validator already has initiated exit
|
||||
pre_state.validator_registry[validator_index].initiated_exit = True
|
||||
|
||||
#
|
||||
# build voluntary exit
|
||||
#
|
||||
voluntary_exit = build_voluntary_exit(
|
||||
pre_state,
|
||||
state,
|
||||
current_epoch,
|
||||
validator_index,
|
||||
privkey,
|
||||
)
|
||||
|
||||
assert (
|
||||
current_epoch - pre_state.validator_registry[validator_index].activation_epoch <
|
||||
current_epoch - state.validator_registry[validator_index].activation_epoch <
|
||||
spec.PERSISTENT_COMMITTEE_PERIOD
|
||||
)
|
||||
|
||||
with pytest.raises(AssertionError):
|
||||
process_voluntary_exit(pre_state, voluntary_exit)
|
||||
|
||||
return pre_state, voluntary_exit, None
|
||||
pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit, False)
|
||||
return pre_state, voluntary_exit, post_state
|
||||
|
||||
@@ -25,7 +25,6 @@ from eth2spec.phase0.spec import (
|
||||
get_attestation_participants,
|
||||
get_block_root,
|
||||
get_crosslink_committee_for_attestation,
|
||||
get_crosslink_committees_at_slot,
|
||||
get_current_epoch,
|
||||
get_domain,
|
||||
get_empty_block,
|
||||
@@ -96,14 +95,6 @@ def create_genesis_state(num_validators, deposit_data_leaves=None):
|
||||
)
|
||||
|
||||
|
||||
def force_registry_change_at_next_epoch(state):
|
||||
# artificially trigger registry update at next epoch transition
|
||||
state.finalized_epoch = get_current_epoch(state) - 1
|
||||
for crosslink in state.latest_crosslinks:
|
||||
crosslink.epoch = state.finalized_epoch
|
||||
state.validator_registry_update_epoch = state.finalized_epoch - 1
|
||||
|
||||
|
||||
def build_empty_block_for_next_slot(state):
|
||||
empty_block = get_empty_block()
|
||||
empty_block.slot = state.slot + 1
|
||||
@@ -208,7 +199,7 @@ def build_deposit(state,
|
||||
|
||||
def get_valid_proposer_slashing(state):
|
||||
current_epoch = get_current_epoch(state)
|
||||
validator_index = get_active_validator_indices(state.validator_registry, current_epoch)[-1]
|
||||
validator_index = get_active_validator_indices(state, current_epoch)[-1]
|
||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
||||
slot = state.slot
|
||||
|
||||
@@ -249,7 +240,7 @@ def get_valid_proposer_slashing(state):
|
||||
def get_valid_attester_slashing(state):
|
||||
attestation_1 = get_valid_attestation(state)
|
||||
attestation_2 = deepcopy(attestation_1)
|
||||
attestation_2.data.target_root = b'\x01'*32
|
||||
attestation_2.data.target_root = b'\x01' * 32
|
||||
|
||||
return AttesterSlashing(
|
||||
attestation_1=convert_to_indexed(state, attestation_1),
|
||||
|
||||
@@ -39,7 +39,6 @@ from eth2spec.utils.merkle_minimal import (
|
||||
from .helpers import (
|
||||
build_deposit_data,
|
||||
build_empty_block_for_next_slot,
|
||||
force_registry_change_at_next_epoch,
|
||||
get_valid_attestation,
|
||||
get_valid_attester_slashing,
|
||||
get_valid_proposer_slashing,
|
||||
@@ -128,11 +127,9 @@ def test_proposer_slashing(state):
|
||||
block.body.proposer_slashings.append(proposer_slashing)
|
||||
state_transition(test_state, block)
|
||||
|
||||
assert not state.validator_registry[validator_index].initiated_exit
|
||||
assert not state.validator_registry[validator_index].slashed
|
||||
|
||||
slashed_validator = test_state.validator_registry[validator_index]
|
||||
assert not slashed_validator.initiated_exit
|
||||
assert slashed_validator.slashed
|
||||
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
||||
@@ -154,11 +151,9 @@ def test_attester_slashing(state):
|
||||
block.body.attester_slashings.append(attester_slashing)
|
||||
state_transition(test_state, block)
|
||||
|
||||
assert not state.validator_registry[validator_index].initiated_exit
|
||||
assert not state.validator_registry[validator_index].slashed
|
||||
|
||||
slashed_validator = test_state.validator_registry[validator_index]
|
||||
assert not slashed_validator.initiated_exit
|
||||
assert slashed_validator.slashed
|
||||
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
||||
@@ -283,14 +278,12 @@ def test_attestation(state):
|
||||
def test_voluntary_exit(state):
|
||||
pre_state = deepcopy(state)
|
||||
validator_index = get_active_validator_indices(
|
||||
pre_state.validator_registry,
|
||||
pre_state,
|
||||
get_current_epoch(pre_state)
|
||||
)[-1]
|
||||
|
||||
# move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
|
||||
pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
# artificially trigger registry update at next epoch transition
|
||||
force_registry_change_at_next_epoch(pre_state)
|
||||
|
||||
post_state = deepcopy(pre_state)
|
||||
|
||||
@@ -316,9 +309,7 @@ def test_voluntary_exit(state):
|
||||
initiate_exit_block.body.voluntary_exits.append(voluntary_exit)
|
||||
state_transition(post_state, initiate_exit_block)
|
||||
|
||||
assert not pre_state.validator_registry[validator_index].initiated_exit
|
||||
assert post_state.validator_registry[validator_index].initiated_exit
|
||||
assert post_state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||
assert post_state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||
|
||||
#
|
||||
# Process within epoch transition
|
||||
@@ -335,7 +326,7 @@ def test_voluntary_exit(state):
|
||||
def test_no_exit_churn_too_long_since_change(state):
|
||||
pre_state = deepcopy(state)
|
||||
validator_index = get_active_validator_indices(
|
||||
pre_state.validator_registry,
|
||||
pre_state,
|
||||
get_current_epoch(pre_state)
|
||||
)[-1]
|
||||
|
||||
@@ -344,14 +335,6 @@ def test_no_exit_churn_too_long_since_change(state):
|
||||
#
|
||||
# move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
|
||||
pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
# artificially trigger registry update at next epoch transition
|
||||
force_registry_change_at_next_epoch(pre_state)
|
||||
# make epochs since registry update greater than LATEST_SLASHED_EXIT_LENGTH
|
||||
pre_state.validator_registry_update_epoch = (
|
||||
get_current_epoch(pre_state) - spec.LATEST_SLASHED_EXIT_LENGTH
|
||||
)
|
||||
# set validator to have previously initiated exit
|
||||
pre_state.validator_registry[validator_index].initiated_exit = True
|
||||
|
||||
post_state = deepcopy(pre_state)
|
||||
|
||||
@@ -362,7 +345,6 @@ def test_no_exit_churn_too_long_since_change(state):
|
||||
block.slot += spec.SLOTS_PER_EPOCH
|
||||
state_transition(post_state, block)
|
||||
|
||||
assert post_state.validator_registry_update_epoch == get_current_epoch(post_state) - 1
|
||||
assert post_state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||
|
||||
return pre_state, [block], post_state
|
||||
@@ -371,8 +353,8 @@ def test_no_exit_churn_too_long_since_change(state):
|
||||
def test_transfer(state):
|
||||
pre_state = deepcopy(state)
|
||||
current_epoch = get_current_epoch(pre_state)
|
||||
sender_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[-1]
|
||||
recipient_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
|
||||
sender_index = get_active_validator_indices(pre_state, current_epoch)[-1]
|
||||
recipient_index = get_active_validator_indices(pre_state, current_epoch)[0]
|
||||
transfer_pubkey = pubkeys[-1]
|
||||
transfer_privkey = privkeys[-1]
|
||||
amount = get_balance(pre_state, sender_index)
|
||||
@@ -419,11 +401,11 @@ def test_transfer(state):
|
||||
return pre_state, [block], post_state
|
||||
|
||||
|
||||
def test_ejection(state):
|
||||
def test_balance_driven_status_transitions(state):
|
||||
pre_state = deepcopy(state)
|
||||
|
||||
current_epoch = get_current_epoch(pre_state)
|
||||
validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[-1]
|
||||
validator_index = get_active_validator_indices(pre_state, current_epoch)[-1]
|
||||
|
||||
assert pre_state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||
|
||||
@@ -438,7 +420,7 @@ def test_ejection(state):
|
||||
block.slot += spec.SLOTS_PER_EPOCH
|
||||
state_transition(post_state, block)
|
||||
|
||||
assert post_state.validator_registry[validator_index].initiated_exit == True
|
||||
assert post_state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||
|
||||
return pre_state, [block], post_state
|
||||
|
||||
|
||||
Reference in New Issue
Block a user