Add basic tests
This commit is contained in:
parent
b8e77c5486
commit
34693f2db6
|
@ -9,12 +9,13 @@ from eth2spec.bellatrix import mainnet as spec_bellatrix_mainnet, minimal as spe
|
|||
from eth2spec.capella import mainnet as spec_capella_mainnet, minimal as spec_capella_minimal
|
||||
from eth2spec.deneb import mainnet as spec_deneb_mainnet, minimal as spec_deneb_minimal
|
||||
from eth2spec.eip6110 import mainnet as spec_eip6110_mainnet, minimal as spec_eip6110_minimal
|
||||
from eth2spec.eip7002 import mainnet as spec_eip7002_mainnet, minimal as spec_eip7002_minimal
|
||||
from eth2spec.utils import bls
|
||||
|
||||
from .exceptions import SkippedTest
|
||||
from .helpers.constants import (
|
||||
PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB,
|
||||
EIP6110,
|
||||
EIP6110, EIP7002,
|
||||
MINIMAL, MAINNET,
|
||||
ALL_PHASES,
|
||||
ALL_FORK_UPGRADES,
|
||||
|
@ -82,6 +83,7 @@ spec_targets: Dict[PresetBaseName, Dict[SpecForkName, Spec]] = {
|
|||
CAPELLA: spec_capella_minimal,
|
||||
DENEB: spec_deneb_minimal,
|
||||
EIP6110: spec_eip6110_minimal,
|
||||
EIP7002: spec_eip7002_minimal,
|
||||
},
|
||||
MAINNET: {
|
||||
PHASE0: spec_phase0_mainnet,
|
||||
|
@ -90,6 +92,7 @@ spec_targets: Dict[PresetBaseName, Dict[SpecForkName, Spec]] = {
|
|||
CAPELLA: spec_capella_mainnet,
|
||||
DENEB: spec_deneb_mainnet,
|
||||
EIP6110: spec_eip6110_mainnet,
|
||||
EIP7002: spec_eip7002_mainnet,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -433,6 +436,7 @@ with_bellatrix_and_later = with_all_phases_from(BELLATRIX)
|
|||
with_capella_and_later = with_all_phases_from(CAPELLA)
|
||||
with_deneb_and_later = with_all_phases_from(DENEB)
|
||||
with_eip6110_and_later = with_all_phases_from(EIP6110)
|
||||
with_eip7002_and_later = with_all_phases_from(EIP7002)
|
||||
|
||||
|
||||
def _get_preset_targets(kw):
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
from eth2spec.test.context import spec_state_test, with_eip7002_and_later
|
||||
from eth2spec.test.helpers.execution_layer_exits import run_execution_layer_exit_processing
|
||||
from eth2spec.test.helpers.withdrawals import set_eth1_withdrawal_credential_with_balance
|
||||
|
||||
|
||||
@with_eip7002_and_later
|
||||
@spec_state_test
|
||||
def test_basic_exit(spec, 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]
|
||||
address = b'\x22' * 20
|
||||
set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, address=address)
|
||||
execution_layer_exit = spec.ExecutionLayerExit(
|
||||
source_address=address,
|
||||
validator_index=validator_index,
|
||||
)
|
||||
|
||||
yield from run_execution_layer_exit_processing(spec, state, execution_layer_exit)
|
||||
|
||||
|
||||
@with_eip7002_and_later
|
||||
@spec_state_test
|
||||
def test_incorrect_source_address(spec, 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]
|
||||
address = b'\x22' * 20
|
||||
incorrect_address = b'\x33' * 20
|
||||
set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, address=address)
|
||||
execution_layer_exit = spec.ExecutionLayerExit(
|
||||
source_address=incorrect_address,
|
||||
validator_index=validator_index,
|
||||
)
|
||||
|
||||
yield from run_execution_layer_exit_processing(spec, state, execution_layer_exit, success=False)
|
|
@ -0,0 +1,46 @@
|
|||
from eth2spec.test.helpers.block import (
|
||||
build_empty_block_for_next_slot
|
||||
)
|
||||
from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
with_eip7002_and_later,
|
||||
)
|
||||
from eth2spec.test.helpers.execution_payload import (
|
||||
compute_el_block_hash,
|
||||
)
|
||||
from eth2spec.test.helpers.state import (
|
||||
state_transition_and_sign_block
|
||||
)
|
||||
from eth2spec.test.helpers.withdrawals import (
|
||||
set_eth1_withdrawal_credential_with_balance,
|
||||
)
|
||||
|
||||
|
||||
@with_eip7002_and_later
|
||||
@spec_state_test
|
||||
def test_basic_exit(spec, 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]
|
||||
address = b'\x22' * 20
|
||||
set_eth1_withdrawal_credential_with_balance(spec, state, validator_index, address=address)
|
||||
execution_layer_exit = spec.ExecutionLayerExit(
|
||||
source_address=address,
|
||||
validator_index=validator_index,
|
||||
)
|
||||
|
||||
yield 'pre', state
|
||||
|
||||
assert state.validators[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
block.body.execution_payload.exits = [execution_layer_exit]
|
||||
block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload)
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
|
||||
yield 'blocks', [signed_block]
|
||||
yield 'post', state
|
||||
|
||||
assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
|
@ -16,6 +16,7 @@ SHARDING = SpecForkName('sharding')
|
|||
CUSTODY_GAME = SpecForkName('custody_game')
|
||||
DAS = SpecForkName('das')
|
||||
EIP6110 = SpecForkName('eip6110')
|
||||
EIP7002 = SpecForkName('eip7002')
|
||||
|
||||
# The forks that pytest can run with.
|
||||
ALL_PHASES = (
|
||||
|
@ -23,6 +24,7 @@ ALL_PHASES = (
|
|||
PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB,
|
||||
# Experimental patches
|
||||
EIP6110,
|
||||
EIP7002,
|
||||
)
|
||||
# The forks that output to the test vectors.
|
||||
TESTGEN_FORKS = (PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110)
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
from eth2spec.test.context import expect_assertion_error
|
||||
|
||||
|
||||
#
|
||||
# Run processing
|
||||
#
|
||||
|
||||
|
||||
def run_execution_layer_exit_processing(spec, state, execution_layer_exit, valid=True, success=True):
|
||||
"""
|
||||
Run ``process_execution_layer_exit``, yielding:
|
||||
- pre-state ('pre')
|
||||
- execution_layer_exit ('execution_layer_exit')
|
||||
- post-state ('post').
|
||||
If ``valid == False``, run expecting ``AssertionError``
|
||||
"""
|
||||
validator_index = execution_layer_exit.validator_index
|
||||
|
||||
yield 'pre', state
|
||||
yield 'execution_layer_exit', execution_layer_exit
|
||||
|
||||
if not valid:
|
||||
expect_assertion_error(lambda: spec.process_execution_layer_exit(state, execution_layer_exit))
|
||||
yield 'post', None
|
||||
return
|
||||
|
||||
pre_exit_epoch = state.validators[validator_index].exit_epoch
|
||||
|
||||
spec.process_execution_layer_exit(state, execution_layer_exit)
|
||||
|
||||
yield 'post', state
|
||||
|
||||
if success:
|
||||
assert pre_exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||
assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||
else:
|
||||
assert state.validators[validator_index].exit_epoch == pre_exit_epoch
|
|
@ -8,6 +8,7 @@ from eth2spec.test.helpers.forks import (
|
|||
is_post_capella,
|
||||
is_post_deneb,
|
||||
is_post_eip6110,
|
||||
is_post_eip7002,
|
||||
)
|
||||
|
||||
|
||||
|
@ -34,6 +35,8 @@ def get_execution_payload_header(spec, execution_payload):
|
|||
payload_header.excess_data_gas = execution_payload.excess_data_gas
|
||||
if is_post_eip6110(spec):
|
||||
payload_header.deposit_receipts_root = spec.hash_tree_root(execution_payload.deposit_receipts)
|
||||
if is_post_eip7002(spec):
|
||||
payload_header.exits_root = spec.hash_tree_root(execution_payload.exits)
|
||||
return payload_header
|
||||
|
||||
|
||||
|
@ -55,7 +58,8 @@ def compute_el_header_block_hash(spec,
|
|||
payload_header,
|
||||
transactions_trie_root,
|
||||
withdrawals_trie_root=None,
|
||||
deposit_receipts_trie_root=None):
|
||||
deposit_receipts_trie_root=None,
|
||||
exits_trie_root=None):
|
||||
"""
|
||||
Computes the RLP execution block hash described by an `ExecutionPayloadHeader`.
|
||||
"""
|
||||
|
@ -103,6 +107,9 @@ def compute_el_header_block_hash(spec,
|
|||
# deposit_receipts_root
|
||||
assert deposit_receipts_trie_root is not None
|
||||
execution_payload_header_rlp.append((Binary(32, 32), deposit_receipts_trie_root))
|
||||
if is_post_eip7002(spec):
|
||||
# exits_trie_root
|
||||
execution_payload_header_rlp.append((Binary(32, 32), exits_trie_root))
|
||||
|
||||
sedes = List([schema for schema, _ in execution_payload_header_rlp])
|
||||
values = [value for _, value in execution_payload_header_rlp]
|
||||
|
@ -112,7 +119,7 @@ def compute_el_header_block_hash(spec,
|
|||
|
||||
|
||||
# https://eips.ethereum.org/EIPS/eip-4895
|
||||
def get_withdrawal_rlp(spec, withdrawal):
|
||||
def get_withdrawal_rlp(withdrawal):
|
||||
withdrawal_rlp = [
|
||||
# index
|
||||
(big_endian_int, withdrawal.index),
|
||||
|
@ -129,6 +136,20 @@ def get_withdrawal_rlp(spec, withdrawal):
|
|||
return encode(values, sedes)
|
||||
|
||||
|
||||
# https://eips.ethereum.org/EIPS/eip-7002
|
||||
def get_exit_rlp(exit):
|
||||
exit_rlp = [
|
||||
# source_address
|
||||
(Binary(20, 20), exit.source_address),
|
||||
# validator_index
|
||||
(big_endian_int, exit.validator_index),
|
||||
]
|
||||
|
||||
sedes = List([schema for schema, _ in exit_rlp])
|
||||
values = [value for _, value in exit_rlp]
|
||||
return encode(values, sedes)
|
||||
|
||||
|
||||
def get_deposit_receipt_rlp(spec, deposit_receipt):
|
||||
deposit_receipt_rlp = [
|
||||
# pubkey
|
||||
|
@ -153,13 +174,17 @@ def compute_el_block_hash(spec, payload):
|
|||
|
||||
withdrawals_trie_root = None
|
||||
deposit_receipts_trie_root = None
|
||||
exits_trie_root = None
|
||||
|
||||
if is_post_capella(spec):
|
||||
withdrawals_encoded = [get_withdrawal_rlp(spec, withdrawal) for withdrawal in payload.withdrawals]
|
||||
withdrawals_encoded = [get_withdrawal_rlp(withdrawal) for withdrawal in payload.withdrawals]
|
||||
withdrawals_trie_root = compute_trie_root_from_indexed_data(withdrawals_encoded)
|
||||
if is_post_eip6110(spec):
|
||||
deposit_receipts_encoded = [get_deposit_receipt_rlp(spec, receipt) for receipt in payload.deposit_receipts]
|
||||
deposit_receipts_trie_root = compute_trie_root_from_indexed_data(deposit_receipts_encoded)
|
||||
if is_post_eip7002(spec):
|
||||
exits_encoded = [get_exit_rlp(exit) for exit in payload.exits]
|
||||
exits_trie_root = compute_trie_root_from_indexed_data(exits_encoded)
|
||||
|
||||
payload_header = get_execution_payload_header(spec, payload)
|
||||
|
||||
|
@ -169,6 +194,7 @@ def compute_el_block_hash(spec, payload):
|
|||
transactions_trie_root,
|
||||
withdrawals_trie_root,
|
||||
deposit_receipts_trie_root,
|
||||
exits_trie_root,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
from .constants import (
|
||||
PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB,
|
||||
EIP6110,
|
||||
EIP6110, EIP7002,
|
||||
)
|
||||
|
||||
|
||||
def is_post_fork(a, b):
|
||||
if a == EIP7002:
|
||||
return b in [PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP7002]
|
||||
if a == EIP6110:
|
||||
return b in [PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110]
|
||||
if a == DENEB:
|
||||
|
@ -38,3 +40,7 @@ def is_post_deneb(spec):
|
|||
|
||||
def is_post_eip6110(spec):
|
||||
return is_post_fork(spec.fork, EIP6110)
|
||||
|
||||
|
||||
def is_post_eip7002(spec):
|
||||
return is_post_fork(spec.fork, EIP7002)
|
||||
|
|
|
@ -5,7 +5,7 @@ from eth2spec.test.helpers.execution_payload import (
|
|||
compute_el_header_block_hash,
|
||||
)
|
||||
from eth2spec.test.helpers.forks import (
|
||||
is_post_altair, is_post_bellatrix, is_post_capella, is_post_eip6110,
|
||||
is_post_altair, is_post_bellatrix, is_post_capella, is_post_eip6110, is_post_eip7002,
|
||||
)
|
||||
from eth2spec.test.helpers.keys import pubkeys
|
||||
|
||||
|
@ -49,11 +49,14 @@ def get_sample_genesis_execution_payload_header(spec,
|
|||
transactions_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
||||
withdrawals_trie_root = None
|
||||
deposit_receipts_trie_root = None
|
||||
exits_trie_root = None
|
||||
|
||||
if is_post_capella(spec):
|
||||
withdrawals_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
||||
if is_post_eip6110(spec):
|
||||
deposit_receipts_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
||||
if is_post_eip7002(spec):
|
||||
exits_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
||||
|
||||
payload_header.block_hash = compute_el_header_block_hash(
|
||||
spec,
|
||||
|
@ -61,6 +64,7 @@ def get_sample_genesis_execution_payload_header(spec,
|
|||
transactions_trie_root,
|
||||
withdrawals_trie_root,
|
||||
deposit_receipts_trie_root,
|
||||
exits_trie_root,
|
||||
)
|
||||
return payload_header
|
||||
|
||||
|
|
|
@ -20,9 +20,14 @@ def set_validator_fully_withdrawable(spec, state, index, withdrawable_epoch=None
|
|||
assert spec.is_fully_withdrawable_validator(validator, state.balances[index], withdrawable_epoch)
|
||||
|
||||
|
||||
def set_eth1_withdrawal_credential_with_balance(spec, state, index, balance):
|
||||
def set_eth1_withdrawal_credential_with_balance(spec, state, index, balance=None, address=None):
|
||||
if balance is None:
|
||||
balance = spec.MAX_EFFECTIVE_BALANCE
|
||||
if address is None:
|
||||
address = b'\x11' * 20
|
||||
|
||||
validator = state.validators[index]
|
||||
validator.withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + validator.withdrawal_credentials[1:]
|
||||
validator.withdrawal_credentials = spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + b'\x00' * 11 + address
|
||||
validator.effective_balance = min(balance, spec.MAX_EFFECTIVE_BALANCE)
|
||||
state.balances[index] = balance
|
||||
|
||||
|
|
Loading…
Reference in New Issue