mirror of
https://github.com/status-im/eth2.0-specs.git
synced 2025-02-17 21:16:52 +00:00
add note about how slashings and exits can interact. add test
This commit is contained in:
parent
032a93335c
commit
c17a95a175
@ -358,6 +358,10 @@ The `proof` for each deposit must be constructed against the deposit root contai
|
|||||||
|
|
||||||
Up to `MAX_VOLUNTARY_EXITS`, [`VoluntaryExit`](./beacon-chain.md#voluntaryexit) objects can be included in the `block`. The exits must satisfy the verification conditions found in [exits processing](./beacon-chain.md#voluntary-exits).
|
Up to `MAX_VOLUNTARY_EXITS`, [`VoluntaryExit`](./beacon-chain.md#voluntaryexit) objects can be included in the `block`. The exits must satisfy the verification conditions found in [exits processing](./beacon-chain.md#voluntary-exits).
|
||||||
|
|
||||||
|
*Note*: If a slashing for a validator is included in the same block as a
|
||||||
|
voluntary exit, the voluntary exit will fail and cause the block to be invalid
|
||||||
|
due to the slashing being processed first. Implementers must take heed of this
|
||||||
|
operation interaction when packing blocks.
|
||||||
|
|
||||||
#### Packaging into a `SignedBeaconBlock`
|
#### Packaging into a `SignedBeaconBlock`
|
||||||
|
|
||||||
|
@ -1,4 +1,19 @@
|
|||||||
from eth2spec.utils import bls
|
from eth2spec.utils import bls
|
||||||
|
from eth2spec.test.helpers.keys import privkeys
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_signed_exits(spec, state, indices):
|
||||||
|
domain = spec.get_domain(state, spec.DOMAIN_VOLUNTARY_EXIT)
|
||||||
|
|
||||||
|
def create_signed_exit(index):
|
||||||
|
exit = spec.VoluntaryExit(
|
||||||
|
epoch=spec.get_current_epoch(state),
|
||||||
|
validator_index=index,
|
||||||
|
)
|
||||||
|
signing_root = spec.compute_signing_root(exit, domain)
|
||||||
|
return spec.SignedVoluntaryExit(message=exit, signature=bls.Sign(privkeys[index], signing_root))
|
||||||
|
|
||||||
|
return [create_signed_exit(index) for index in indices]
|
||||||
|
|
||||||
|
|
||||||
def sign_voluntary_exit(spec, state, voluntary_exit, privkey):
|
def sign_voluntary_exit(spec, state, voluntary_exit, privkey):
|
||||||
|
@ -9,7 +9,7 @@ from eth2spec.test.helpers.block import (
|
|||||||
sign_block,
|
sign_block,
|
||||||
transition_unsigned_block,
|
transition_unsigned_block,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.keys import privkeys, pubkeys
|
from eth2spec.test.helpers.keys import pubkeys
|
||||||
from eth2spec.test.helpers.attester_slashings import (
|
from eth2spec.test.helpers.attester_slashings import (
|
||||||
get_valid_attester_slashing_by_indices,
|
get_valid_attester_slashing_by_indices,
|
||||||
get_valid_attester_slashing,
|
get_valid_attester_slashing,
|
||||||
@ -18,6 +18,7 @@ from eth2spec.test.helpers.attester_slashings import (
|
|||||||
from eth2spec.test.helpers.proposer_slashings import get_valid_proposer_slashing, check_proposer_slashing_effect
|
from eth2spec.test.helpers.proposer_slashings import get_valid_proposer_slashing, check_proposer_slashing_effect
|
||||||
from eth2spec.test.helpers.attestations import get_valid_attestation
|
from eth2spec.test.helpers.attestations import get_valid_attestation
|
||||||
from eth2spec.test.helpers.deposits import prepare_state_and_deposit
|
from eth2spec.test.helpers.deposits import prepare_state_and_deposit
|
||||||
|
from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits
|
||||||
from eth2spec.test.helpers.shard_transitions import get_shard_transition_of_committee
|
from eth2spec.test.helpers.shard_transitions import get_shard_transition_of_committee
|
||||||
|
|
||||||
from eth2spec.test.context import (
|
from eth2spec.test.context import (
|
||||||
@ -794,20 +795,6 @@ def test_attestation(spec, state):
|
|||||||
assert spec.hash_tree_root(state.previous_epoch_attestations) == pre_current_attestations_root
|
assert spec.hash_tree_root(state.previous_epoch_attestations) == pre_current_attestations_root
|
||||||
|
|
||||||
|
|
||||||
def prepare_signed_exits(spec, state, indices):
|
|
||||||
domain = spec.get_domain(state, spec.DOMAIN_VOLUNTARY_EXIT)
|
|
||||||
|
|
||||||
def create_signed_exit(index):
|
|
||||||
exit = spec.VoluntaryExit(
|
|
||||||
epoch=spec.get_current_epoch(state),
|
|
||||||
validator_index=index,
|
|
||||||
)
|
|
||||||
signing_root = spec.compute_signing_root(exit, domain)
|
|
||||||
return spec.SignedVoluntaryExit(message=exit, signature=bls.Sign(privkeys[index], signing_root))
|
|
||||||
|
|
||||||
return [create_signed_exit(index) for index in indices]
|
|
||||||
|
|
||||||
|
|
||||||
# In phase1 a committee is computed for SHARD_COMMITTEE_PERIOD slots ago,
|
# In phase1 a committee is computed for SHARD_COMMITTEE_PERIOD slots ago,
|
||||||
# exceeding the minimal-config randao mixes memory size.
|
# exceeding the minimal-config randao mixes memory size.
|
||||||
# Applies to all voluntary-exit sanity block tests.
|
# Applies to all voluntary-exit sanity block tests.
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
from eth2spec.test.helpers.state import (
|
||||||
|
state_transition_and_sign_block,
|
||||||
|
)
|
||||||
|
from eth2spec.test.helpers.block import (
|
||||||
|
build_empty_block_for_next_slot,
|
||||||
|
)
|
||||||
|
from eth2spec.test.helpers.proposer_slashings import get_valid_proposer_slashing
|
||||||
|
from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits
|
||||||
|
|
||||||
|
from eth2spec.test.context import (
|
||||||
|
spec_state_test,
|
||||||
|
with_all_phases,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run_slash_and_exit(spec, state, slash_index, exit_index, valid=True):
|
||||||
|
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||||
|
state.slot += spec.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||||
|
|
||||||
|
yield 'pre', state
|
||||||
|
|
||||||
|
block = build_empty_block_for_next_slot(spec, state)
|
||||||
|
|
||||||
|
proposer_slashing = get_valid_proposer_slashing(
|
||||||
|
spec, state, slashed_index=slash_index, signed_1=True, signed_2=True)
|
||||||
|
signed_exit = prepare_signed_exits(spec, state, [exit_index])[0]
|
||||||
|
|
||||||
|
block.body.proposer_slashings.append(proposer_slashing)
|
||||||
|
block.body.voluntary_exits.append(signed_exit)
|
||||||
|
|
||||||
|
signed_block = state_transition_and_sign_block(spec, state, block, expect_fail=(not valid))
|
||||||
|
|
||||||
|
yield 'blocks', [signed_block]
|
||||||
|
|
||||||
|
if valid:
|
||||||
|
yield 'post', state
|
||||||
|
else:
|
||||||
|
yield 'post', None
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_slash_and_exit_same_index(spec, state):
|
||||||
|
validator_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1]
|
||||||
|
run_slash_and_exit(spec, state, validator_index, validator_index, valid=False)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_slash_and_exit_diff_index(spec, state):
|
||||||
|
slash_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1]
|
||||||
|
exit_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-2]
|
||||||
|
run_slash_and_exit(spec, state, slash_index, exit_index)
|
Loading…
x
Reference in New Issue
Block a user