Add invalid fork version tests
This commit is contained in:
parent
d133dae471
commit
b3ef9b2b3e
|
@ -0,0 +1,85 @@
|
||||||
|
from eth2spec.test.context import (
|
||||||
|
spec_state_test,
|
||||||
|
always_bls,
|
||||||
|
with_bellatrix_and_later,
|
||||||
|
)
|
||||||
|
from eth2spec.test.helpers.deposits import (
|
||||||
|
deposit_from_context,
|
||||||
|
run_deposit_processing,
|
||||||
|
)
|
||||||
|
from eth2spec.test.helpers.keys import (
|
||||||
|
privkeys,
|
||||||
|
pubkeys,
|
||||||
|
)
|
||||||
|
from eth2spec.utils import bls
|
||||||
|
|
||||||
|
|
||||||
|
def _run_deposit_processing_with_specific_fork_version(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
fork_version,
|
||||||
|
valid,
|
||||||
|
effective):
|
||||||
|
validator_index = len(state.validators)
|
||||||
|
amount = spec.MAX_EFFECTIVE_BALANCE
|
||||||
|
|
||||||
|
pubkey = pubkeys[validator_index]
|
||||||
|
privkey = privkeys[validator_index]
|
||||||
|
withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(pubkey)[1:]
|
||||||
|
|
||||||
|
deposit_message = spec.DepositMessage(pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, amount=amount)
|
||||||
|
domain = spec.compute_domain(domain_type=spec.DOMAIN_DEPOSIT, fork_version=fork_version)
|
||||||
|
deposit_data = spec.DepositData(
|
||||||
|
pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, amount=amount,
|
||||||
|
signature=bls.Sign(privkey, spec.compute_signing_root(deposit_message, domain))
|
||||||
|
)
|
||||||
|
deposit, root, _ = deposit_from_context(spec, [deposit_data], 0)
|
||||||
|
|
||||||
|
state.eth1_deposit_index = 0
|
||||||
|
state.eth1_data.deposit_root = root
|
||||||
|
state.eth1_data.deposit_count = 1
|
||||||
|
|
||||||
|
yield from run_deposit_processing(spec, state, deposit, validator_index, valid=valid, effective=effective)
|
||||||
|
|
||||||
|
|
||||||
|
@with_bellatrix_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_deposit_with_previous_fork_version__valid_effective(spec, state):
|
||||||
|
assert state.fork.previous_version != state.fork.current_version
|
||||||
|
|
||||||
|
yield from _run_deposit_processing_with_specific_fork_version(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
fork_version=state.fork.previous_version,
|
||||||
|
valid=True,
|
||||||
|
effective=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@with_bellatrix_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_deposit_with_genesis_fork_version__valid_ineffective(spec, state):
|
||||||
|
assert spec.config.GENESIS_FORK_VERSION not in (state.fork.previous_version, state.fork.current_version)
|
||||||
|
|
||||||
|
yield from _run_deposit_processing_with_specific_fork_version(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
fork_version=spec.config.GENESIS_FORK_VERSION,
|
||||||
|
valid=True,
|
||||||
|
effective=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@with_bellatrix_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_deposit_with_bad_fork_version__valid_ineffective(spec, state):
|
||||||
|
yield from _run_deposit_processing_with_specific_fork_version(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
fork_version=spec.Version('0xAaBbCcDd'),
|
||||||
|
valid=True,
|
||||||
|
effective=False,
|
||||||
|
)
|
|
@ -0,0 +1,71 @@
|
||||||
|
from eth2spec.test.context import (
|
||||||
|
spec_state_test,
|
||||||
|
always_bls,
|
||||||
|
with_bellatrix_and_later,
|
||||||
|
)
|
||||||
|
from eth2spec.test.helpers.keys import pubkey_to_privkey
|
||||||
|
from eth2spec.test.helpers.state import (
|
||||||
|
next_epoch,
|
||||||
|
)
|
||||||
|
from eth2spec.test.helpers.voluntary_exits import (
|
||||||
|
run_voluntary_exit_processing,
|
||||||
|
sign_voluntary_exit,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _run_voluntary_exit_processing_with_specific_fork_version(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
fork_version,
|
||||||
|
valid):
|
||||||
|
next_epoch(spec, state)
|
||||||
|
state.fork.epoch = spec.get_current_epoch(state)
|
||||||
|
|
||||||
|
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||||
|
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||||
|
|
||||||
|
current_epoch = spec.get_current_epoch(state)
|
||||||
|
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||||
|
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||||
|
|
||||||
|
voluntary_exit = spec.VoluntaryExit(
|
||||||
|
epoch=0,
|
||||||
|
validator_index=validator_index,
|
||||||
|
)
|
||||||
|
signed_voluntary_exit = sign_voluntary_exit(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
voluntary_exit,
|
||||||
|
privkey,
|
||||||
|
fork_version=fork_version,
|
||||||
|
)
|
||||||
|
|
||||||
|
yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=valid)
|
||||||
|
|
||||||
|
|
||||||
|
@with_bellatrix_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_voluntary_exit_with_previous_fork_version__valid(spec, state):
|
||||||
|
assert state.fork.previous_version != state.fork.current_version
|
||||||
|
|
||||||
|
yield from _run_voluntary_exit_processing_with_specific_fork_version(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
fork_version=state.fork.previous_version,
|
||||||
|
valid=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@with_bellatrix_and_later
|
||||||
|
@spec_state_test
|
||||||
|
@always_bls
|
||||||
|
def test_voluntary_exit_with_genesis_fork_version__invalid(spec, state):
|
||||||
|
assert spec.config.GENESIS_FORK_VERSION not in (state.fork.previous_version, state.fork.current_version)
|
||||||
|
|
||||||
|
yield from _run_voluntary_exit_processing_with_specific_fork_version(
|
||||||
|
spec,
|
||||||
|
state,
|
||||||
|
fork_version=spec.config.GENESIS_FORK_VERSION,
|
||||||
|
valid=False,
|
||||||
|
)
|
|
@ -1,7 +1,11 @@
|
||||||
from random import Random
|
from random import Random
|
||||||
|
|
||||||
from eth2spec.test.context import is_post_altair
|
from eth2spec.test.context import (
|
||||||
|
is_post_altair,
|
||||||
|
expect_assertion_error,
|
||||||
|
)
|
||||||
from eth2spec.test.helpers.keys import pubkeys, privkeys
|
from eth2spec.test.helpers.keys import pubkeys, privkeys
|
||||||
|
from eth2spec.test.helpers.state import get_balance
|
||||||
from eth2spec.utils import bls
|
from eth2spec.utils import bls
|
||||||
from eth2spec.utils.merkle_minimal import calc_merkle_tree_from_leaves, get_merkle_proof
|
from eth2spec.utils.merkle_minimal import calc_merkle_tree_from_leaves, get_merkle_proof
|
||||||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
||||||
|
@ -160,3 +164,57 @@ def prepare_state_and_deposit(spec, state, validator_index, amount, withdrawal_c
|
||||||
state.eth1_data.deposit_root = root
|
state.eth1_data.deposit_root = root
|
||||||
state.eth1_data.deposit_count = len(deposit_data_list)
|
state.eth1_data.deposit_count = len(deposit_data_list)
|
||||||
return deposit
|
return deposit
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Run processing
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
def run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=True):
|
||||||
|
"""
|
||||||
|
Run ``process_deposit``, yielding:
|
||||||
|
- pre-state ('pre')
|
||||||
|
- deposit ('deposit')
|
||||||
|
- post-state ('post').
|
||||||
|
If ``valid == False``, run expecting ``AssertionError``
|
||||||
|
"""
|
||||||
|
pre_validator_count = len(state.validators)
|
||||||
|
pre_balance = 0
|
||||||
|
if validator_index < pre_validator_count:
|
||||||
|
pre_balance = get_balance(state, validator_index)
|
||||||
|
|
||||||
|
yield 'pre', state
|
||||||
|
yield 'deposit', deposit
|
||||||
|
|
||||||
|
if not valid:
|
||||||
|
expect_assertion_error(lambda: spec.process_deposit(state, deposit))
|
||||||
|
yield 'post', None
|
||||||
|
return
|
||||||
|
|
||||||
|
spec.process_deposit(state, deposit)
|
||||||
|
|
||||||
|
yield 'post', state
|
||||||
|
|
||||||
|
if not effective:
|
||||||
|
assert len(state.validators) == pre_validator_count
|
||||||
|
assert len(state.balances) == pre_validator_count
|
||||||
|
if validator_index < pre_validator_count:
|
||||||
|
assert get_balance(state, validator_index) == pre_balance
|
||||||
|
else:
|
||||||
|
if validator_index < pre_validator_count:
|
||||||
|
# top-up
|
||||||
|
assert len(state.validators) == pre_validator_count
|
||||||
|
assert len(state.balances) == pre_validator_count
|
||||||
|
else:
|
||||||
|
# new validator
|
||||||
|
assert len(state.validators) == pre_validator_count + 1
|
||||||
|
assert len(state.balances) == pre_validator_count + 1
|
||||||
|
assert get_balance(state, validator_index) == pre_balance + deposit.data.amount
|
||||||
|
|
||||||
|
effective = min(spec.MAX_EFFECTIVE_BALANCE,
|
||||||
|
pre_balance + deposit.data.amount)
|
||||||
|
effective -= effective % spec.EFFECTIVE_BALANCE_INCREMENT
|
||||||
|
assert state.validators[validator_index].effective_balance == effective
|
||||||
|
|
||||||
|
assert state.eth1_deposit_index == state.eth1_data.deposit_count
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
from random import Random
|
from random import Random
|
||||||
from eth2spec.utils import bls
|
from eth2spec.utils import bls
|
||||||
|
from eth2spec.test.context import expect_assertion_error
|
||||||
from eth2spec.test.helpers.keys import privkeys
|
from eth2spec.test.helpers.keys import privkeys
|
||||||
|
|
||||||
|
|
||||||
def prepare_signed_exits(spec, state, indices):
|
def prepare_signed_exits(spec, state, indices, fork_version=None):
|
||||||
domain = spec.get_domain(state, spec.DOMAIN_VOLUNTARY_EXIT)
|
if fork_version is None:
|
||||||
|
domain = spec.get_domain(state, spec.DOMAIN_VOLUNTARY_EXIT)
|
||||||
|
else:
|
||||||
|
domain = spec.compute_domain(spec.DOMAIN_VOLUNTARY_EXIT, fork_version, state.genesis_validators_root)
|
||||||
|
|
||||||
def create_signed_exit(index):
|
def create_signed_exit(index):
|
||||||
exit = spec.VoluntaryExit(
|
exit = spec.VoluntaryExit(
|
||||||
|
@ -17,8 +21,12 @@ def prepare_signed_exits(spec, state, indices):
|
||||||
return [create_signed_exit(index) for index in indices]
|
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, fork_version=None):
|
||||||
domain = spec.get_domain(state, spec.DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
|
if fork_version is None:
|
||||||
|
domain = spec.get_domain(state, spec.DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
|
||||||
|
else:
|
||||||
|
domain = spec.compute_domain(spec.DOMAIN_VOLUNTARY_EXIT, fork_version, state.genesis_validators_root)
|
||||||
|
|
||||||
signing_root = spec.compute_signing_root(voluntary_exit, domain)
|
signing_root = spec.compute_signing_root(voluntary_exit, domain)
|
||||||
return spec.SignedVoluntaryExit(
|
return spec.SignedVoluntaryExit(
|
||||||
message=voluntary_exit,
|
message=voluntary_exit,
|
||||||
|
@ -49,3 +57,36 @@ def exit_validators(spec, state, validator_count, rng=None):
|
||||||
for index in indices:
|
for index in indices:
|
||||||
spec.initiate_validator_exit(state, index)
|
spec.initiate_validator_exit(state, index)
|
||||||
return indices
|
return indices
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Run processing
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
def run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=True):
|
||||||
|
"""
|
||||||
|
Run ``process_voluntary_exit``, yielding:
|
||||||
|
- pre-state ('pre')
|
||||||
|
- voluntary_exit ('voluntary_exit')
|
||||||
|
- post-state ('post').
|
||||||
|
If ``valid == False``, run expecting ``AssertionError``
|
||||||
|
"""
|
||||||
|
validator_index = signed_voluntary_exit.message.validator_index
|
||||||
|
|
||||||
|
yield 'pre', state
|
||||||
|
yield 'voluntary_exit', signed_voluntary_exit
|
||||||
|
|
||||||
|
if not valid:
|
||||||
|
expect_assertion_error(lambda: spec.process_voluntary_exit(state, signed_voluntary_exit))
|
||||||
|
yield 'post', None
|
||||||
|
return
|
||||||
|
|
||||||
|
pre_exit_epoch = state.validators[validator_index].exit_epoch
|
||||||
|
|
||||||
|
spec.process_voluntary_exit(state, signed_voluntary_exit)
|
||||||
|
|
||||||
|
yield 'post', state
|
||||||
|
|
||||||
|
assert pre_exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||||
|
assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
|
|
|
@ -1,63 +1,15 @@
|
||||||
from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases
|
from eth2spec.test.context import spec_state_test, always_bls, with_all_phases
|
||||||
from eth2spec.test.helpers.deposits import (
|
from eth2spec.test.helpers.deposits import (
|
||||||
build_deposit,
|
build_deposit,
|
||||||
|
deposit_from_context,
|
||||||
prepare_state_and_deposit,
|
prepare_state_and_deposit,
|
||||||
|
run_deposit_processing,
|
||||||
sign_deposit_data,
|
sign_deposit_data,
|
||||||
deposit_from_context)
|
)
|
||||||
from eth2spec.test.helpers.state import get_balance
|
|
||||||
from eth2spec.test.helpers.keys import privkeys, pubkeys
|
from eth2spec.test.helpers.keys import privkeys, pubkeys
|
||||||
from eth2spec.utils import bls
|
from eth2spec.utils import bls
|
||||||
|
|
||||||
|
|
||||||
def run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=True):
|
|
||||||
"""
|
|
||||||
Run ``process_deposit``, yielding:
|
|
||||||
- pre-state ('pre')
|
|
||||||
- deposit ('deposit')
|
|
||||||
- post-state ('post').
|
|
||||||
If ``valid == False``, run expecting ``AssertionError``
|
|
||||||
"""
|
|
||||||
pre_validator_count = len(state.validators)
|
|
||||||
pre_balance = 0
|
|
||||||
if validator_index < pre_validator_count:
|
|
||||||
pre_balance = get_balance(state, validator_index)
|
|
||||||
|
|
||||||
yield 'pre', state
|
|
||||||
yield 'deposit', deposit
|
|
||||||
|
|
||||||
if not valid:
|
|
||||||
expect_assertion_error(lambda: spec.process_deposit(state, deposit))
|
|
||||||
yield 'post', None
|
|
||||||
return
|
|
||||||
|
|
||||||
spec.process_deposit(state, deposit)
|
|
||||||
|
|
||||||
yield 'post', state
|
|
||||||
|
|
||||||
if not effective:
|
|
||||||
assert len(state.validators) == pre_validator_count
|
|
||||||
assert len(state.balances) == pre_validator_count
|
|
||||||
if validator_index < pre_validator_count:
|
|
||||||
assert get_balance(state, validator_index) == pre_balance
|
|
||||||
else:
|
|
||||||
if validator_index < pre_validator_count:
|
|
||||||
# top-up
|
|
||||||
assert len(state.validators) == pre_validator_count
|
|
||||||
assert len(state.balances) == pre_validator_count
|
|
||||||
else:
|
|
||||||
# new validator
|
|
||||||
assert len(state.validators) == pre_validator_count + 1
|
|
||||||
assert len(state.balances) == pre_validator_count + 1
|
|
||||||
assert get_balance(state, validator_index) == pre_balance + deposit.data.amount
|
|
||||||
|
|
||||||
effective = min(spec.MAX_EFFECTIVE_BALANCE,
|
|
||||||
pre_balance + deposit.data.amount)
|
|
||||||
effective -= effective % spec.EFFECTIVE_BALANCE_INCREMENT
|
|
||||||
assert state.validators[validator_index].effective_balance == effective
|
|
||||||
|
|
||||||
assert state.eth1_deposit_index == state.eth1_data.deposit_count
|
|
||||||
|
|
||||||
|
|
||||||
@with_all_phases
|
@with_all_phases
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_new_deposit_under_max(spec, state):
|
def test_new_deposit_under_max(spec, state):
|
||||||
|
|
|
@ -1,40 +1,15 @@
|
||||||
from eth2spec.test.helpers.constants import MINIMAL
|
from eth2spec.test.helpers.constants import MINIMAL
|
||||||
from eth2spec.test.context import (
|
from eth2spec.test.context import (
|
||||||
spec_state_test, expect_assertion_error,
|
spec_state_test,
|
||||||
always_bls, with_all_phases, with_presets,
|
always_bls, with_all_phases, with_presets,
|
||||||
spec_test, single_phase,
|
spec_test, single_phase,
|
||||||
with_custom_state, scaled_churn_balances,
|
with_custom_state, scaled_churn_balances,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.keys import pubkey_to_privkey
|
from eth2spec.test.helpers.keys import pubkey_to_privkey
|
||||||
from eth2spec.test.helpers.voluntary_exits import sign_voluntary_exit
|
from eth2spec.test.helpers.voluntary_exits import (
|
||||||
|
run_voluntary_exit_processing,
|
||||||
|
sign_voluntary_exit,
|
||||||
def run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=True):
|
)
|
||||||
"""
|
|
||||||
Run ``process_voluntary_exit``, yielding:
|
|
||||||
- pre-state ('pre')
|
|
||||||
- voluntary_exit ('voluntary_exit')
|
|
||||||
- post-state ('post').
|
|
||||||
If ``valid == False``, run expecting ``AssertionError``
|
|
||||||
"""
|
|
||||||
validator_index = signed_voluntary_exit.message.validator_index
|
|
||||||
|
|
||||||
yield 'pre', state
|
|
||||||
yield 'voluntary_exit', signed_voluntary_exit
|
|
||||||
|
|
||||||
if not valid:
|
|
||||||
expect_assertion_error(lambda: spec.process_voluntary_exit(state, signed_voluntary_exit))
|
|
||||||
yield 'post', None
|
|
||||||
return
|
|
||||||
|
|
||||||
pre_exit_epoch = state.validators[validator_index].exit_epoch
|
|
||||||
|
|
||||||
spec.process_voluntary_exit(state, signed_voluntary_exit)
|
|
||||||
|
|
||||||
yield 'post', state
|
|
||||||
|
|
||||||
assert pre_exit_epoch == spec.FAR_FUTURE_EPOCH
|
|
||||||
assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
|
||||||
|
|
||||||
|
|
||||||
@with_all_phases
|
@with_all_phases
|
||||||
|
|
Loading…
Reference in New Issue