Skip to content

Commit

Permalink
Merge pull request #850 from ethereum/vbuterin-patch-13
Browse files Browse the repository at this point in the history
Withdrawal queue -> exit queue
  • Loading branch information
djrtwo committed Apr 14, 2019
2 parents be86f96 + 3394368 commit 7840d29
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 305 deletions.
248 changes: 86 additions & 162 deletions specs/core/0_beacon-chain.md

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions tests/phase0/block_processing/test_process_attestation.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
state_transition,
)
from build.phase0.spec import (
ZERO_HASH,
get_current_epoch,
process_attestation,
slot_to_epoch,
Expand Down Expand Up @@ -102,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)

Expand All @@ -113,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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion tests/phase0/block_processing/test_process_block_header.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions tests/phase0/block_processing/test_process_deposit.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
)


# mark entire file as 'voluntary_exits'
pytestmark = pytest.mark.voluntary_exits
# mark entire file as 'deposits'
pytestmark = pytest.mark.deposits


def test_success(state):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
180 changes: 84 additions & 96 deletions tests/phase0/block_processing/test_voluntary_exit.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from build.phase0.spec import (
get_active_validator_indices,
get_churn_limit,
get_current_epoch,
process_voluntary_exit,
)
Expand All @@ -18,158 +19,145 @@
pytestmark = pytest.mark.voluntary_exits


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)

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):
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
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]
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]

voluntary_exit = build_voluntary_exit(
pre_state,
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

pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit)
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]

#
# setup pre_state
#
pre_state.validator_registry[validator_index].activation_epoch = spec.FAR_FUTURE_EPOCH

#
# build and test voluntary 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(
pre_state,
state,
current_epoch,
validator_index,
privkey,
)

with pytest.raises(AssertionError):
process_voluntary_exit(pre_state, voluntary_exit)
pre_state, post_state = run_voluntary_exit_processing(post_state, voluntary_exit)

return pre_state, voluntary_exit, None
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_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

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]
def test_validator_not_active(state):
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].activation_epoch = spec.FAR_FUTURE_EPOCH

#
# build voluntary exit
# 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_initiated_exit(state):
pre_state = deepcopy(state)
#
# setup pre_state
#
def test_validator_already_exited(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 initiated exit
pre_state.validator_registry[validator_index].initiated_exit = True
# but validator already has exited
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
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]

# but validator already has initiated exit
pre_state.validator_registry[validator_index].initiated_exit = True
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]

#
# 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
13 changes: 2 additions & 11 deletions tests/phase0/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
get_attestation_participants,
get_block_root,
get_crosslink_committee_for_attestation,
get_crosslink_committees_at_slot,
get_current_epoch,
get_domain,
get_empty_block,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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),
Expand Down
Loading

0 comments on commit 7840d29

Please sign in to comment.