2019-03-20 14:22:47 +00:00
|
|
|
from copy import deepcopy
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
import build.phase0.spec as spec
|
|
|
|
|
|
|
|
from build.phase0.spec import (
|
|
|
|
get_active_validator_indices,
|
|
|
|
get_current_epoch,
|
|
|
|
process_voluntary_exit,
|
|
|
|
)
|
|
|
|
from tests.phase0.helpers import (
|
|
|
|
build_voluntary_exit,
|
2019-03-25 16:37:34 +00:00
|
|
|
pubkey_to_privkey,
|
2019-03-20 14:22:47 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# mark entire file as 'voluntary_exits'
|
|
|
|
pytestmark = pytest.mark.voluntary_exits
|
|
|
|
|
|
|
|
|
2019-03-25 16:37:34 +00:00
|
|
|
def test_success(state):
|
2019-03-20 14:22:47 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
#
|
|
|
|
# build voluntary exit
|
|
|
|
#
|
|
|
|
current_epoch = get_current_epoch(pre_state)
|
|
|
|
validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
|
2019-03-25 16:37:34 +00:00
|
|
|
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]
|
2019-03-20 14:22:47 +00:00
|
|
|
|
|
|
|
voluntary_exit = build_voluntary_exit(
|
|
|
|
pre_state,
|
|
|
|
current_epoch,
|
|
|
|
validator_index,
|
|
|
|
privkey,
|
|
|
|
)
|
|
|
|
|
|
|
|
post_state = deepcopy(pre_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
|
|
|
|
|
|
|
|
return pre_state, voluntary_exit, post_state
|
|
|
|
|
|
|
|
|
2019-03-25 16:37:34 +00:00
|
|
|
def test_validator_not_active(state):
|
2019-03-20 14:22:47 +00:00
|
|
|
pre_state = deepcopy(state)
|
|
|
|
current_epoch = get_current_epoch(pre_state)
|
|
|
|
validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
|
2019-03-25 16:37:34 +00:00
|
|
|
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]
|
2019-03-20 14:22:47 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# setup pre_state
|
|
|
|
#
|
|
|
|
pre_state.validator_registry[validator_index].activation_epoch = spec.FAR_FUTURE_EPOCH
|
|
|
|
|
|
|
|
#
|
|
|
|
# build and test 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
|
|
|
|
|
|
|
|
|
2019-03-25 16:37:34 +00:00
|
|
|
def test_validator_already_exited(state):
|
2019-03-20 14:22:47 +00:00
|
|
|
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]
|
2019-03-25 16:37:34 +00:00
|
|
|
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]
|
2019-03-20 14:22:47 +00:00
|
|
|
|
|
|
|
# but validator already has exited
|
|
|
|
pre_state.validator_registry[validator_index].exit_epoch = current_epoch + 2
|
|
|
|
|
|
|
|
#
|
|
|
|
# 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
|
|
|
|
|
|
|
|
|
2019-03-25 16:37:34 +00:00
|
|
|
def test_validator_already_initiated_exit(state):
|
2019-03-20 14:22:47 +00:00
|
|
|
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]
|
2019-03-25 16:37:34 +00:00
|
|
|
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]
|
2019-03-20 14:22:47 +00:00
|
|
|
|
|
|
|
# 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
|
|
|
|
|
|
|
|
|
2019-03-25 16:37:34 +00:00
|
|
|
def test_validator_not_active_long_enough(state):
|
2019-03-20 14:22:47 +00:00
|
|
|
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]
|
2019-03-25 16:37:34 +00:00
|
|
|
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]
|
2019-03-20 14:22:47 +00:00
|
|
|
|
|
|
|
# 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,
|
|
|
|
)
|
|
|
|
|
|
|
|
assert (
|
|
|
|
current_epoch - pre_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
|