diff --git a/presets/mainnet/capella.yaml b/presets/mainnet/capella.yaml index 62306c8dc..913c2956b 100644 --- a/presets/mainnet/capella.yaml +++ b/presets/mainnet/capella.yaml @@ -10,3 +10,8 @@ MAX_BLS_TO_EXECUTION_CHANGES: 16 # --------------------------------------------------------------- # 2**4 (= 16) withdrawals MAX_WITHDRAWALS_PER_PAYLOAD: 16 + +# Withdrawals processing +# --------------------------------------------------------------- +# 2**14 (= 16384) validators +MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: 16384 diff --git a/presets/mainnet/eip4844.yaml b/presets/mainnet/eip4844.yaml index c40908fde..3866e82ff 100644 --- a/presets/mainnet/eip4844.yaml +++ b/presets/mainnet/eip4844.yaml @@ -4,5 +4,5 @@ # --------------------------------------------------------------- # `uint64(4096)` FIELD_ELEMENTS_PER_BLOB: 4096 -# `uint64(2**4)` (= 16) -MAX_BLOBS_PER_BLOCK: 16 +# `uint64(2**2)` (= 4) +MAX_BLOBS_PER_BLOCK: 4 diff --git a/presets/minimal/capella.yaml b/presets/minimal/capella.yaml index 1ac8a806c..d27253de8 100644 --- a/presets/minimal/capella.yaml +++ b/presets/minimal/capella.yaml @@ -10,3 +10,8 @@ MAX_BLS_TO_EXECUTION_CHANGES: 16 # --------------------------------------------------------------- # [customized] 2**2 (= 4) MAX_WITHDRAWALS_PER_PAYLOAD: 4 + +# Withdrawals processing +# --------------------------------------------------------------- +# [customized] 2**4 (= 16) validators +MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: 16 diff --git a/presets/minimal/eip4844.yaml b/presets/minimal/eip4844.yaml index fbb676819..dacacf5b8 100644 --- a/presets/minimal/eip4844.yaml +++ b/presets/minimal/eip4844.yaml @@ -4,5 +4,5 @@ # --------------------------------------------------------------- # [customized] FIELD_ELEMENTS_PER_BLOB: 4 -# `uint64(2**4)` (= 16) -MAX_BLOBS_PER_BLOCK: 16 +# `uint64(2**2)` (= 4) +MAX_BLOBS_PER_BLOCK: 4 diff --git a/setup.py b/setup.py index 432a41fe4..be8be6d90 100644 --- a/setup.py +++ b/setup.py @@ -1173,6 +1173,7 @@ setup( "py_ecc==6.0.0", "milagro_bls_binding==1.9.0", "remerkleable==0.1.25", + "trie==2.0.2", RUAMEL_YAML_VERSION, "lru-dict==1.1.8", MARKO_VERSION, diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index 79ab8d022..fe71a5ff8 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -523,6 +523,7 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None: if bls.Verify(pubkey, signing_root, deposit.data.signature): state.validators.append(get_validator_from_deposit(deposit)) state.balances.append(amount) + # [New in Altair] state.previous_epoch_participation.append(ParticipationFlags(0b0000_0000)) state.current_epoch_participation.append(ParticipationFlags(0b0000_0000)) state.inactivity_scores.append(uint64(0)) diff --git a/specs/capella/beacon-chain.md b/specs/capella/beacon-chain.md index 90a64925f..20f4a5dd4 100644 --- a/specs/capella/beacon-chain.md +++ b/specs/capella/beacon-chain.md @@ -8,11 +8,11 @@ - [Introduction](#introduction) - [Custom types](#custom-types) -- [Constants](#constants) - [Domain types](#domain-types) - [Preset](#preset) - [Max operations per block](#max-operations-per-block) - [Execution](#execution) + - [Withdrawals processing](#withdrawals-processing) - [Containers](#containers) - [New containers](#new-containers) - [`Withdrawal`](#withdrawal) @@ -58,8 +58,6 @@ We define the following Python custom types for type hinting and readability: | - | - | - | | `WithdrawalIndex` | `uint64` | an index of a `Withdrawal` | -## Constants - ### Domain types | Name | Value | @@ -80,6 +78,12 @@ We define the following Python custom types for type hinting and readability: | - | - | - | | `MAX_WITHDRAWALS_PER_PAYLOAD` | `uint64(2**4)` (= 16) | Maximum amount of withdrawals allowed in each payload | +### Withdrawals processing + +| Name | Value | +| - | - | +| `MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP` | `16384` (= 2**14 ) | + ## Containers ### New containers @@ -288,7 +292,8 @@ def get_expected_withdrawals(state: BeaconState) -> Sequence[Withdrawal]: withdrawal_index = state.next_withdrawal_index validator_index = state.next_withdrawal_validator_index withdrawals: List[Withdrawal] = [] - for _ in range(len(state.validators)): + bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) + for _ in range(bound): validator = state.validators[validator_index] balance = state.balances[validator_index] if is_fully_withdrawable_validator(validator, balance, epoch): @@ -312,7 +317,7 @@ def get_expected_withdrawals(state: BeaconState) -> Sequence[Withdrawal]: validator_index = ValidatorIndex((validator_index + 1) % len(state.validators)) return withdrawals ``` - + #### New `process_withdrawals` ```python @@ -323,10 +328,21 @@ def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None: for expected_withdrawal, withdrawal in zip(expected_withdrawals, payload.withdrawals): assert withdrawal == expected_withdrawal decrease_balance(state, withdrawal.validator_index, withdrawal.amount) - if len(expected_withdrawals) > 0: + + # Update the next withdrawal index if this block contained withdrawals + if len(expected_withdrawals) != 0: latest_withdrawal = expected_withdrawals[-1] state.next_withdrawal_index = WithdrawalIndex(latest_withdrawal.index + 1) - next_validator_index = ValidatorIndex((latest_withdrawal.validator_index + 1) % len(state.validators)) + + # Update the next validator index to start the next withdrawal sweep + if len(expected_withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD: + # Next sweep starts after the latest withdrawal's validator index + next_validator_index = ValidatorIndex((expected_withdrawals[-1].validator_index + 1) % len(state.validators)) + state.next_withdrawal_validator_index = next_validator_index + else: + # Advance sweep by the max length of the sweep if there was not a full set of withdrawals + next_index = state.next_withdrawal_validator_index + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP + next_validator_index = ValidatorIndex(next_index % len(state.validators)) state.next_withdrawal_validator_index = next_validator_index ``` diff --git a/specs/eip4844/beacon-chain.md b/specs/eip4844/beacon-chain.md index 63a6cd987..ac148ac68 100644 --- a/specs/eip4844/beacon-chain.md +++ b/specs/eip4844/beacon-chain.md @@ -63,7 +63,7 @@ This upgrade adds blobs to the beacon chain as part of EIP-4844. This is an exte | Name | Value | | - | - | -| `MAX_BLOBS_PER_BLOCK` | `uint64(2**4)` (= 16) | +| `MAX_BLOBS_PER_BLOCK` | `uint64(2**2)` (= 4) | ## Configuration @@ -168,8 +168,7 @@ The implementation of `is_data_available` is meant to change with later sharding Initially, it requires every verifying actor to retrieve the matching `BlobsSidecar`, and validate the sidecar with `validate_blobs_sidecar`. -Without the sidecar the block may be processed further optimistically, -but MUST NOT be considered valid until a valid `BlobsSidecar` has been downloaded. +The block MUST NOT be considered valid until a valid `BlobsSidecar` has been downloaded. ```python def is_data_available(slot: Slot, beacon_block_root: Root, blob_kzg_commitments: Sequence[KZGCommitment]) -> bool: @@ -242,7 +241,7 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None: process_sync_aggregate(state, block.body.sync_aggregate) process_blob_kzg_commitments(state, block.body) # [New in EIP-4844] - # New in EIP-4844, note: Can sync optimistically without this condition, see note on `is_data_available` + # New in EIP-4844 assert is_data_available(block.slot, hash_tree_root(block), block.body.blob_kzg_commitments) ``` diff --git a/specs/eip4844/p2p-interface.md b/specs/eip4844/p2p-interface.md index f031b3723..a8318bcc7 100644 --- a/specs/eip4844/p2p-interface.md +++ b/specs/eip4844/p2p-interface.md @@ -230,7 +230,7 @@ Clients MUST keep a record of signed blobs sidecars seen on the epoch range where `current_epoch` is defined by the current wall-clock time, and clients MUST support serving requests of blocks on this range. -Peers that are unable to reply to block requests within the `MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS` +Peers that are unable to reply to blobs sidecars requests within the `MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS` epoch range SHOULD respond with error code `3: ResourceUnavailable`. Such peers that are unable to successfully reply to this range of requests MAY get descored or disconnected at any time. diff --git a/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_deposit.py b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_deposit.py new file mode 100644 index 000000000..25c276726 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_deposit.py @@ -0,0 +1,41 @@ +from eth2spec.test.context import ( + spec_state_test, + always_bls, + with_phases, + with_altair_and_later, +) +from eth2spec.test.helpers.constants import ( + ALTAIR, +) + + +from eth2spec.test.helpers.deposits import ( + run_deposit_processing_with_specific_fork_version, +) + + +@with_phases([ALTAIR]) +@spec_state_test +@always_bls +def test_effective_deposit_with_previous_fork_version(spec, state): + assert state.fork.previous_version != state.fork.current_version + + # It's only effective in Altair because the default `fork_version` of `compute_domain` is `GENESIS_FORK_VERSION`. + # Therefore it's just a normal `DepositMessage`. + yield from run_deposit_processing_with_specific_fork_version( + spec, + state, + fork_version=state.fork.previous_version, + ) + + +@with_altair_and_later +@spec_state_test +@always_bls +def test_ineffective_deposit_with_current_fork_version(spec, state): + yield from run_deposit_processing_with_specific_fork_version( + spec, + state, + fork_version=state.fork.current_version, + effective=False, + ) diff --git a/tests/core/pyspec/eth2spec/test/altair/epoch_processing/test_process_sync_committee_updates.py b/tests/core/pyspec/eth2spec/test/altair/epoch_processing/test_process_sync_committee_updates.py index 4b0cb70d5..9e8444b54 100644 --- a/tests/core/pyspec/eth2spec/test/altair/epoch_processing/test_process_sync_committee_updates.py +++ b/tests/core/pyspec/eth2spec/test/altair/epoch_processing/test_process_sync_committee_updates.py @@ -110,7 +110,7 @@ def test_sync_committees_progress_misc_balances_not_genesis(spec, state): @spec_state_test @always_bls @with_presets([MINIMAL], reason="too slow") -def test_sync_committees_no_progress_not_boundary(spec, state): +def test_sync_committees_no_progress_not_at_period_boundary(spec, state): assert spec.get_current_epoch(state) == spec.GENESIS_EPOCH slot_not_at_period_boundary = state.slot + spec.SLOTS_PER_EPOCH transition_to(spec, state, slot_not_at_period_boundary) diff --git a/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks.py index a3299c170..0c2f1c755 100644 --- a/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/altair/sanity/test_blocks.py @@ -51,40 +51,40 @@ def run_sync_committee_sanity_test(spec, state, fraction_full=1.0, rng=Random(45 @with_altair_and_later @spec_state_test -def test_full_sync_committee_committee(spec, state): +def test_sync_committee_committee__full(spec, state): next_epoch(spec, state) yield from run_sync_committee_sanity_test(spec, state, fraction_full=1.0) @with_altair_and_later @spec_state_test -def test_half_sync_committee_committee(spec, state): +def test_sync_committee_committee__half(spec, state): next_epoch(spec, state) yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.5, rng=Random(1212)) @with_altair_and_later @spec_state_test -def test_empty_sync_committee_committee(spec, state): +def test_sync_committee_committee__empty(spec, state): next_epoch(spec, state) yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.0) @with_altair_and_later @spec_state_test -def test_full_sync_committee_committee_genesis(spec, state): +def test_sync_committee_committee_genesis__full(spec, state): yield from run_sync_committee_sanity_test(spec, state, fraction_full=1.0) @with_altair_and_later @spec_state_test -def test_half_sync_committee_committee_genesis(spec, state): +def test_sync_committee_committee_genesis__half(spec, state): yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.5, rng=Random(2323)) @with_altair_and_later @spec_state_test -def test_empty_sync_committee_committee_genesis(spec, state): +def test_sync_committee_committee_genesis__empty(spec, state): yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.0) diff --git a/tests/core/pyspec/eth2spec/test/altair/unittests/test_config_override.py b/tests/core/pyspec/eth2spec/test/altair/unittests/test_config_override.py index ed6f63868..6824439bf 100644 --- a/tests/core/pyspec/eth2spec/test/altair/unittests/test_config_override.py +++ b/tests/core/pyspec/eth2spec/test/altair/unittests/test_config_override.py @@ -8,10 +8,11 @@ from eth2spec.test.context import ( with_phases, with_state, ) -from eth2spec.test.helpers.constants import ALTAIR, BELLATRIX -from eth2spec.test.helpers.forks import ( - is_post_capella, is_post_eip4844, +from eth2spec.test.helpers.constants import ( + PHASE0, ALTAIR, BELLATRIX, + ALL_PHASES, ) +from eth2spec.test.helpers.forks import is_post_fork @with_phases([ALTAIR]) @@ -34,32 +35,31 @@ def test_config_override(spec, state): @with_all_phases @spec_state_test_with_matching_config def test_config_override_matching_fork_epochs(spec, state): - if state.fork.current_version == spec.config.GENESIS_FORK_VERSION: - return + # Fork schedule must be consistent with state fork + epoch = spec.get_current_epoch(state) + if is_post_fork(spec.fork, ALTAIR): + assert state.fork.current_version == spec.compute_fork_version(epoch) + else: + assert state.fork.current_version == spec.config.GENESIS_FORK_VERSION - assert spec.config.ALTAIR_FORK_EPOCH == spec.GENESIS_EPOCH - if state.fork.current_version == spec.config.ALTAIR_FORK_VERSION: - return + # Identify state fork + state_fork = None + for fork in [fork for fork in ALL_PHASES if is_post_fork(spec.fork, fork)]: + if fork == PHASE0: + fork_version_field = 'GENESIS_FORK_VERSION' + else: + fork_version_field = fork.upper() + '_FORK_VERSION' + if state.fork.current_version == getattr(spec.config, fork_version_field): + state_fork = fork + break + assert state_fork is not None - assert spec.config.BELLATRIX_FORK_EPOCH == spec.GENESIS_EPOCH - if state.fork.current_version == spec.config.BELLATRIX_FORK_VERSION: - return - - if is_post_capella(spec): - assert spec.config.CAPELLA_FORK_EPOCH == spec.GENESIS_EPOCH - if state.fork.current_version == spec.config.CAPELLA_FORK_VERSION: - return - - if is_post_eip4844(spec): - assert spec.config.EIP4844_FORK_EPOCH == spec.GENESIS_EPOCH - if state.fork.current_version == spec.config.EIP4844_FORK_VERSION: - return - - assert spec.config.SHARDING_FORK_EPOCH == spec.GENESIS_EPOCH - if state.fork.current_version == spec.config.SHARDING_FORK_VERSION: - return - - assert False # Fork is missing + # Check that all prior forks have already been triggered + for fork in [fork for fork in ALL_PHASES if is_post_fork(state_fork, fork)]: + if fork == PHASE0: + continue + fork_epoch_field = fork.upper() + '_FORK_EPOCH' + assert getattr(spec.config, fork_epoch_field) <= epoch @with_phases(phases=[ALTAIR], other_phases=[BELLATRIX]) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_deposit.py b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_deposit.py index b111fd9ff..c88463b7a 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_deposit.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_deposit.py @@ -4,55 +4,23 @@ from eth2spec.test.context import ( with_bellatrix_and_later, ) from eth2spec.test.helpers.deposits import ( - deposit_from_context, - run_deposit_processing, + run_deposit_processing_with_specific_fork_version, ) -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_ineffective(spec, state): +def test_ineffective_deposit_with_previous_fork_version(spec, state): + # Since deposits are valid across forks, the domain is always set with `GENESIS_FORK_VERSION`. + # It's an ineffective deposit because it fails at BLS sig verification. + # NOTE: it was effective in Altair. assert state.fork.previous_version != state.fork.current_version - yield from _run_deposit_processing_with_specific_fork_version( + yield from run_deposit_processing_with_specific_fork_version( spec, state, fork_version=state.fork.previous_version, - valid=True, effective=False, ) @@ -60,26 +28,11 @@ def test_deposit_with_previous_fork_version__valid_ineffective(spec, state): @with_bellatrix_and_later @spec_state_test @always_bls -def test_deposit_with_genesis_fork_version__valid_effective(spec, state): +def test_effective_deposit_with_genesis_fork_version(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( + 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, ) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py index 2819b2a24..3ec58b31e 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py @@ -3,6 +3,7 @@ from random import Random from eth2spec.test.helpers.execution_payload import ( build_empty_execution_payload, build_randomized_execution_payload, + compute_el_block_hash, get_execution_payload_header, build_state_with_incomplete_transition, build_state_with_complete_transition, @@ -104,14 +105,14 @@ def run_bad_execution_test(spec, state): @with_bellatrix_and_later @spec_state_test -def test_bad_execution_first_payload(spec, state): +def test_invalid_bad_execution_first_payload(spec, state): state = build_state_with_incomplete_transition(spec, state) yield from run_bad_execution_test(spec, state) @with_bellatrix_and_later @spec_state_test -def test_bad_execution_regular_payload(spec, state): +def test_invalid_bad_execution_regular_payload(spec, state): state = build_state_with_complete_transition(spec, state) yield from run_bad_execution_test(spec, state) @@ -124,18 +125,20 @@ def test_bad_parent_hash_first_payload(spec, state): execution_payload = build_empty_execution_payload(spec, state) execution_payload.parent_hash = b'\x55' * 32 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) - yield from run_execution_payload_processing(spec, state, execution_payload, valid=True) + yield from run_execution_payload_processing(spec, state, execution_payload) @with_bellatrix_and_later @spec_state_test -def test_bad_parent_hash_regular_payload(spec, state): +def test_invalid_bad_parent_hash_regular_payload(spec, state): state = build_state_with_complete_transition(spec, state) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.parent_hash = spec.Hash32() + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_execution_payload_processing(spec, state, execution_payload, valid=False) @@ -145,20 +148,21 @@ def run_bad_prev_randao_test(spec, state): execution_payload = build_empty_execution_payload(spec, state) execution_payload.prev_randao = b'\x42' * 32 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_execution_payload_processing(spec, state, execution_payload, valid=False) @with_bellatrix_and_later @spec_state_test -def test_bad_prev_randao_first_payload(spec, state): +def test_invalid_bad_prev_randao_first_payload(spec, state): state = build_state_with_incomplete_transition(spec, state) yield from run_bad_prev_randao_test(spec, state) @with_bellatrix_and_later @spec_state_test -def test_bad_pre_randao_regular_payload(spec, state): +def test_invalid_bad_pre_randao_regular_payload(spec, state): state = build_state_with_complete_transition(spec, state) yield from run_bad_prev_randao_test(spec, state) @@ -170,20 +174,21 @@ def run_bad_everything_test(spec, state): execution_payload.parent_hash = spec.Hash32() execution_payload.prev_randao = spec.Bytes32() execution_payload.timestamp = 0 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_execution_payload_processing(spec, state, execution_payload, valid=False) @with_bellatrix_and_later @spec_state_test -def test_bad_everything_first_payload(spec, state): +def test_invalid_bad_everything_first_payload(spec, state): state = build_state_with_incomplete_transition(spec, state) yield from run_bad_everything_test(spec, state) @with_bellatrix_and_later @spec_state_test -def test_bad_everything_regular_payload(spec, state): +def test_invalid_bad_everything_regular_payload(spec, state): state = build_state_with_complete_transition(spec, state) yield from run_bad_everything_test(spec, state) @@ -198,34 +203,35 @@ def run_bad_timestamp_test(spec, state, is_future): else: timestamp = execution_payload.timestamp - 1 execution_payload.timestamp = timestamp + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_execution_payload_processing(spec, state, execution_payload, valid=False) @with_bellatrix_and_later @spec_state_test -def test_future_timestamp_first_payload(spec, state): +def test_invalid_future_timestamp_first_payload(spec, state): state = build_state_with_incomplete_transition(spec, state) yield from run_bad_timestamp_test(spec, state, is_future=True) @with_bellatrix_and_later @spec_state_test -def test_future_timestamp_regular_payload(spec, state): +def test_invalid_future_timestamp_regular_payload(spec, state): state = build_state_with_complete_transition(spec, state) yield from run_bad_timestamp_test(spec, state, is_future=True) @with_bellatrix_and_later @spec_state_test -def test_past_timestamp_first_payload(spec, state): +def test_invalid_past_timestamp_first_payload(spec, state): state = build_state_with_incomplete_transition(spec, state) yield from run_bad_timestamp_test(spec, state, is_future=False) @with_bellatrix_and_later @spec_state_test -def test_past_timestamp_regular_payload(spec, state): +def test_invalid_past_timestamp_regular_payload(spec, state): state = build_state_with_complete_transition(spec, state) yield from run_bad_timestamp_test(spec, state, is_future=False) @@ -235,6 +241,7 @@ def run_non_empty_extra_data_test(spec, state): execution_payload = build_empty_execution_payload(spec, state) execution_payload.extra_data = b'\x45' * 12 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_execution_payload_processing(spec, state, execution_payload) assert state.latest_execution_payload_header.extra_data == execution_payload.extra_data @@ -263,6 +270,7 @@ def run_non_empty_transactions_test(spec, state): spec.Transaction(b'\x99' * 128) for _ in range(num_transactions) ] + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_execution_payload_processing(spec, state, execution_payload) assert state.latest_execution_payload_header.transactions_root == execution_payload.transactions.hash_tree_root() @@ -288,6 +296,7 @@ def run_zero_length_transaction_test(spec, state): execution_payload = build_empty_execution_payload(spec, state) execution_payload.transactions = [spec.Transaction(b'')] assert len(execution_payload.transactions[0]) == 0 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_execution_payload_processing(spec, state, execution_payload) assert state.latest_execution_payload_header.transactions_root == execution_payload.transactions.hash_tree_root() @@ -320,27 +329,27 @@ def run_randomized_non_validated_execution_fields_test(spec, state, execution_va @with_bellatrix_and_later @spec_state_test -def test_randomized_non_validated_execution_fields_first_payload__valid(spec, state): +def test_randomized_non_validated_execution_fields_first_payload__execution_valid(spec, state): state = build_state_with_incomplete_transition(spec, state) yield from run_randomized_non_validated_execution_fields_test(spec, state) @with_bellatrix_and_later @spec_state_test -def test_randomized_non_validated_execution_fields_regular_payload__valid(spec, state): +def test_randomized_non_validated_execution_fields_regular_payload__execution_valid(spec, state): state = build_state_with_complete_transition(spec, state) yield from run_randomized_non_validated_execution_fields_test(spec, state) @with_bellatrix_and_later @spec_state_test -def test_randomized_non_validated_execution_fields_first_payload__invalid(spec, state): +def test_invalid_randomized_non_validated_execution_fields_first_payload__execution_invalid(spec, state): state = build_state_with_incomplete_transition(spec, state) yield from run_randomized_non_validated_execution_fields_test(spec, state, execution_valid=False) @with_bellatrix_and_later @spec_state_test -def test_randomized_non_validated_execution_fields_regular_payload__invalid(spec, state): +def test_invalid_randomized_non_validated_execution_fields_regular_payload__execution_invalid(spec, state): state = build_state_with_complete_transition(spec, state) yield from run_randomized_non_validated_execution_fields_test(spec, state, execution_valid=False) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_voluntary_exit.py b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_voluntary_exit.py index 257247b16..f4fcaac68 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_voluntary_exit.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_voluntary_exit.py @@ -18,7 +18,7 @@ def _run_voluntary_exit_processing_test( state, fork_version, is_before_fork_epoch, - valid): + valid=True): # create a fork next_epoch(spec, state) state.fork.epoch = spec.get_current_epoch(state) @@ -50,7 +50,7 @@ def _run_voluntary_exit_processing_test( @with_bellatrix_and_later @spec_state_test @always_bls -def test_voluntary_exit_with_current_fork_version_is_before_fork_epoch__invalid(spec, state): +def test_invalid_voluntary_exit_with_current_fork_version_is_before_fork_epoch(spec, state): yield from _run_voluntary_exit_processing_test( spec, state, @@ -63,20 +63,19 @@ def test_voluntary_exit_with_current_fork_version_is_before_fork_epoch__invalid( @with_bellatrix_and_later @spec_state_test @always_bls -def test_voluntary_exit_with_current_fork_version_not_is_before_fork_epoch__valid(spec, state): +def test_voluntary_exit_with_current_fork_version_not_is_before_fork_epoch(spec, state): yield from _run_voluntary_exit_processing_test( spec, state, fork_version=state.fork.current_version, is_before_fork_epoch=False, - valid=True, ) @with_bellatrix_and_later @spec_state_test @always_bls -def test_voluntary_exit_with_previous_fork_version_is_before_fork_epoch__valid(spec, state): +def test_voluntary_exit_with_previous_fork_version_is_before_fork_epoch(spec, state): assert state.fork.previous_version != state.fork.current_version yield from _run_voluntary_exit_processing_test( @@ -84,14 +83,13 @@ def test_voluntary_exit_with_previous_fork_version_is_before_fork_epoch__valid(s state, fork_version=state.fork.previous_version, is_before_fork_epoch=True, - valid=True, ) @with_bellatrix_and_later @spec_state_test @always_bls -def test_voluntary_exit_with_previous_fork_version_not_is_before_fork_epoch__invalid(spec, state): +def test_invalid_voluntary_exit_with_previous_fork_version_not_is_before_fork_epoch(spec, state): assert state.fork.previous_version != state.fork.current_version yield from _run_voluntary_exit_processing_test( @@ -106,7 +104,7 @@ def test_voluntary_exit_with_previous_fork_version_not_is_before_fork_epoch__inv @with_bellatrix_and_later @spec_state_test @always_bls -def test_voluntary_exit_with_genesis_fork_version_is_before_fork_epoch__invalid(spec, state): +def test_invalid_voluntary_exit_with_genesis_fork_version_is_before_fork_epoch(spec, state): assert spec.config.GENESIS_FORK_VERSION not in (state.fork.previous_version, state.fork.current_version) yield from _run_voluntary_exit_processing_test( @@ -121,7 +119,7 @@ def test_voluntary_exit_with_genesis_fork_version_is_before_fork_epoch__invalid( @with_bellatrix_and_later @spec_state_test @always_bls -def test_voluntary_exit_with_genesis_fork_version_not_is_before_fork_epoch__invalid(spec, state): +def test_invalid_voluntary_exit_with_genesis_fork_version_not_is_before_fork_epoch(spec, state): assert spec.config.GENESIS_FORK_VERSION not in (state.fork.previous_version, state.fork.current_version) yield from _run_voluntary_exit_processing_test( diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/fork_choice/test_on_merge_block.py b/tests/core/pyspec/eth2spec/test/bellatrix/fork_choice/test_on_merge_block.py index 3a935c061..86071c225 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/fork_choice/test_on_merge_block.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/fork_choice/test_on_merge_block.py @@ -4,6 +4,9 @@ from eth2spec.test.context import spec_state_test, with_phases, BELLATRIX from eth2spec.test.helpers.block import ( build_empty_block_for_next_slot, ) +from eth2spec.test.helpers.execution_payload import ( + compute_el_block_hash, +) from eth2spec.test.helpers.fork_choice import ( get_genesis_forkchoice_store_and_block, on_tick_and_append_step, @@ -72,6 +75,7 @@ def test_all_valid(spec, state): def run_func(): block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_block.block_hash + 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 from tick_and_add_block(spec, store, signed_block, test_steps, merge_block=True) # valid @@ -103,6 +107,7 @@ def test_block_lookup_failed(spec, state): def run_func(): block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_block.block_hash + 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 from tick_and_add_block(spec, store, signed_block, test_steps, valid=False, merge_block=True, block_not_found=True) @@ -136,6 +141,7 @@ def test_too_early_for_merge(spec, state): def run_func(): block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_block.block_hash + 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 from tick_and_add_block(spec, store, signed_block, test_steps, valid=False, merge_block=True) @@ -168,6 +174,7 @@ def test_too_late_for_merge(spec, state): def run_func(): block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_block.block_hash + 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 from tick_and_add_block(spec, store, signed_block, test_steps, valid=False, merge_block=True) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/sync/test_optimistic.py b/tests/core/pyspec/eth2spec/test/bellatrix/sync/test_optimistic.py index c849ccbd8..974719f92 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/sync/test_optimistic.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/sync/test_optimistic.py @@ -8,6 +8,9 @@ from eth2spec.test.helpers.attestations import ( from eth2spec.test.helpers.block import ( build_empty_block_for_next_slot, ) +from eth2spec.test.helpers.execution_payload import ( + compute_el_block_hash, +) from eth2spec.test.helpers.fork_choice import ( get_genesis_forkchoice_store_and_block, on_tick_and_append_step, @@ -33,6 +36,7 @@ def test_from_syncing_to_invalid(spec, state): fc_store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state) op_store = get_optimistic_store(spec, state, anchor_block) mega_store = MegaStore(spec, fc_store, op_store) + block_hashes = {} yield 'anchor_state', state yield 'anchor_block', anchor_block @@ -46,7 +50,7 @@ def test_from_syncing_to_invalid(spec, state): # Block 0 block_0 = build_empty_block_for_next_slot(spec, state) - block_0.body.execution_payload.block_hash = spec.hash(bytes('block_0', 'UTF-8')) + block_hashes['block_0'] = block_0.body.execution_payload.block_hash signed_block = state_transition_and_sign_block(spec, state, block_0) yield from add_optimistic_block(spec, mega_store, signed_block, test_steps, status=PayloadStatusV1Status.VALID) assert spec.get_head(mega_store.fc_store) == mega_store.opt_store.head_block_root @@ -57,10 +61,11 @@ def test_from_syncing_to_invalid(spec, state): signed_blocks_a = [] for i in range(3): block = build_empty_block_for_next_slot(spec, state) - block.body.execution_payload.block_hash = spec.hash(bytes(f'chain_a_{i}', 'UTF-8')) block.body.execution_payload.parent_hash = ( - spec.hash(bytes(f'chain_a_{i - 1}', 'UTF-8')) if i != 0 else block_0.body.execution_payload.block_hash + block_hashes[f'chain_a_{i - 1}'] if i != 0 else block_hashes['block_0'] ) + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) + block_hashes[f'chain_a_{i}'] = block.body.execution_payload.block_hash signed_block = state_transition_and_sign_block(spec, state, block) yield from add_optimistic_block(spec, mega_store, signed_block, test_steps, status=PayloadStatusV1Status.VALID) @@ -72,10 +77,12 @@ def test_from_syncing_to_invalid(spec, state): state = state_0.copy() for i in range(3): block = build_empty_block_for_next_slot(spec, state) - block.body.execution_payload.block_hash = spec.hash(bytes(f'chain_b_{i}', 'UTF-8')) block.body.execution_payload.parent_hash = ( - spec.hash(bytes(f'chain_b_{i - 1}', 'UTF-8')) if i != 0 else block_0.body.execution_payload.block_hash + block_hashes[f'chain_b_{i - 1}'] if i != 0 else block_hashes['block_0'] ) + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) + block_hashes[f'chain_b_{i}'] = block.body.execution_payload.block_hash + signed_block = state_transition_with_full_block(spec, state, True, True, block=block) signed_blocks_b.append(signed_block.copy()) yield from add_optimistic_block(spec, mega_store, signed_block, test_steps, @@ -84,8 +91,10 @@ def test_from_syncing_to_invalid(spec, state): # Now add block 4 to chain `b` with INVALID block = build_empty_block_for_next_slot(spec, state) - block.body.execution_payload.block_hash = spec.hash(bytes('chain_b_3', 'UTF-8')) block.body.execution_payload.parent_hash = signed_blocks_b[-1].message.body.execution_payload.block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) + block_hashes['chain_b_3'] = block.body.execution_payload.block_hash + signed_block = state_transition_and_sign_block(spec, state, block) payload_status = PayloadStatusV1( status=PayloadStatusV1Status.INVALID, diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/unittests/test_validate_merge_block.py b/tests/core/pyspec/eth2spec/test/bellatrix/unittests/test_validate_merge_block.py index 141ad5a27..df9792a43 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/unittests/test_validate_merge_block.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/unittests/test_validate_merge_block.py @@ -3,6 +3,9 @@ from eth2spec.utils.ssz.ssz_typing import uint256, Bytes32 from eth2spec.test.helpers.block import ( build_empty_block_for_next_slot, ) +from eth2spec.test.helpers.execution_payload import ( + compute_el_block_hash, +) from eth2spec.test.helpers.pow_block import ( prepare_random_pow_chain, ) @@ -57,6 +60,7 @@ def test_validate_merge_block_success(spec, state): pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) run_validate_merge_block(spec, pow_chain, block) @@ -77,6 +81,7 @@ def test_validate_merge_block_fail_parent_block_lookup(spec, state): pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) run_validate_merge_block(spec, pow_chain, block, valid=False) @@ -88,6 +93,7 @@ def test_validate_merge_block_fail_after_terminal(spec, state): pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY + uint256(1) block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) run_validate_merge_block(spec, pow_chain, block, valid=False) @@ -104,6 +110,7 @@ def test_validate_merge_block_tbh_override_success(spec, state): pow_chain.head().block_hash = TERMINAL_BLOCK_HASH block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) run_validate_merge_block(spec, pow_chain, block) @@ -119,6 +126,7 @@ def test_validate_merge_block_fail_parent_hash_is_not_tbh(spec, state): pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) run_validate_merge_block(spec, pow_chain, block, valid=False) @@ -135,6 +143,7 @@ def test_validate_merge_block_terminal_block_hash_fail_activation_not_reached(sp pow_chain.head().block_hash = TERMINAL_BLOCK_HASH block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) run_validate_merge_block(spec, pow_chain, block, valid=False) @@ -150,4 +159,5 @@ def test_validate_merge_block_fail_activation_not_reached_parent_hash_is_not_tbh pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) run_validate_merge_block(spec, pow_chain, block, valid=False) diff --git a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_bls_to_execution_change.py b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_bls_to_execution_change.py index 79d79fa6e..6a1ba5b36 100644 --- a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_bls_to_execution_change.py +++ b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_bls_to_execution_change.py @@ -131,7 +131,7 @@ def test_success_withdrawable(spec, state): @with_phases([CAPELLA]) @spec_state_test -def test_fail_val_index_out_of_range(spec, state): +def test_invalid_val_index_out_of_range(spec, state): # Create for one validator beyond the validator list length signed_address_change = get_signed_address_change(spec, state, validator_index=len(state.validators)) @@ -140,7 +140,7 @@ def test_fail_val_index_out_of_range(spec, state): @with_phases([CAPELLA]) @spec_state_test -def test_fail_already_0x01(spec, state): +def test_invalid_already_0x01(spec, state): # Create for one validator beyond the validator list length validator_index = len(state.validators) // 2 validator = state.validators[validator_index] @@ -152,7 +152,7 @@ def test_fail_already_0x01(spec, state): @with_phases([CAPELLA]) @spec_state_test -def test_fail_incorrect_from_bls_pubkey(spec, state): +def test_invalid_incorrect_from_bls_pubkey(spec, state): # Create for one validator beyond the validator list length validator_index = 2 signed_address_change = get_signed_address_change( @@ -167,7 +167,7 @@ def test_fail_incorrect_from_bls_pubkey(spec, state): @with_phases([CAPELLA]) @spec_state_test @always_bls -def test_fail_bad_signature(spec, state): +def test_invalid_bad_signature(spec, state): signed_address_change = get_signed_address_change(spec, state) # Mutate signature signed_address_change.signature = spec.BLSSignature(b'\x42' * 96) diff --git a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py index da3ddcb4d..fa3806d2c 100644 --- a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py @@ -6,9 +6,10 @@ from eth2spec.test.context import ( with_presets, with_phases, ) -from eth2spec.test.helpers.constants import MINIMAL, CAPELLA +from eth2spec.test.helpers.constants import MAINNET, MINIMAL, CAPELLA from eth2spec.test.helpers.execution_payload import ( build_empty_execution_payload, + compute_el_block_hash, ) from eth2spec.test.helpers.random import ( randomize_state, @@ -33,8 +34,13 @@ def verify_post_state(state, spec, expected_withdrawals, expected_withdrawals_validator_indices = [withdrawal.validator_index for withdrawal in expected_withdrawals] assert state.next_withdrawal_index == expected_withdrawals[-1].index + 1 - next_withdrawal_validator_index = (expected_withdrawals_validator_indices[-1] + 1) % len(state.validators) - assert state.next_withdrawal_validator_index == next_withdrawal_validator_index + + if len(expected_withdrawals) == spec.MAX_WITHDRAWALS_PER_PAYLOAD: + # NOTE: ideally we would also check in the case with + # fewer than maximum withdrawals but that requires the pre-state info + next_withdrawal_validator_index = (expected_withdrawals_validator_indices[-1] + 1) % len(state.validators) + assert state.next_withdrawal_validator_index == next_withdrawal_validator_index + for index in fully_withdrawable_indices: if index in expected_withdrawals_validator_indices: assert state.balances[index] == 0 @@ -75,9 +81,13 @@ def run_withdrawals_processing(spec, state, execution_payload, num_expected_with yield 'post', state if len(expected_withdrawals) == 0: - assert state == pre_state - elif len(expected_withdrawals) < spec.MAX_WITHDRAWALS_PER_PAYLOAD: - assert len(spec.get_expected_withdrawals(state)) == 0 + next_withdrawal_validator_index = ( + pre_state.next_withdrawal_validator_index + spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP + ) + assert state.next_withdrawal_validator_index == next_withdrawal_validator_index % len(state.validators) + elif len(expected_withdrawals) <= spec.MAX_WITHDRAWALS_PER_PAYLOAD: + bound = min(spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP, spec.MAX_WITHDRAWALS_PER_PAYLOAD) + assert len(spec.get_expected_withdrawals(state)) <= bound elif len(expected_withdrawals) > spec.MAX_WITHDRAWALS_PER_PAYLOAD: raise ValueError('len(expected_withdrawals) should not be greater than MAX_WITHDRAWALS_PER_PAYLOAD') @@ -154,10 +164,14 @@ def test_success_max_per_slot(spec, state): @with_phases([CAPELLA]) +@with_presets([MAINNET], reason="too few validators with minimal config") @spec_state_test -def test_success_all_fully_withdrawable(spec, state): +def test_success_all_fully_withdrawable_in_one_sweep(spec, state): + assert len(state.validators) <= spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP + + withdrawal_count = len(state.validators) fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals( - spec, state, num_full_withdrawals=len(state.validators)) + spec, state, num_full_withdrawals=withdrawal_count) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) @@ -169,10 +183,52 @@ def test_success_all_fully_withdrawable(spec, state): @with_phases([CAPELLA]) +@with_presets([MINIMAL], reason="too many validators with mainnet config") +@spec_state_test +def test_success_all_fully_withdrawable(spec, state): + assert len(state.validators) > spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP + + withdrawal_count = spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP + fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals( + spec, state, num_full_withdrawals=withdrawal_count) + + next_slot(spec, state) + execution_payload = build_empty_execution_payload(spec, state) + + yield from run_withdrawals_processing( + spec, state, execution_payload, + fully_withdrawable_indices=fully_withdrawable_indices, + partial_withdrawals_indices=partial_withdrawals_indices) + + +@with_phases([CAPELLA]) +@with_presets([MAINNET], reason="too few validators with minimal config") +@spec_state_test +def test_success_all_partially_withdrawable_in_one_sweep(spec, state): + assert len(state.validators) <= spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP + + withdrawal_count = len(state.validators) + fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals( + spec, state, num_partial_withdrawals=withdrawal_count) + + next_slot(spec, state) + execution_payload = build_empty_execution_payload(spec, state) + + yield from run_withdrawals_processing( + spec, state, execution_payload, + fully_withdrawable_indices=fully_withdrawable_indices, + partial_withdrawals_indices=partial_withdrawals_indices) + + +@with_phases([CAPELLA]) +@with_presets([MINIMAL], reason="too many validators with mainnet config") @spec_state_test def test_success_all_partially_withdrawable(spec, state): + assert len(state.validators) > spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP + + withdrawal_count = spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals( - spec, state, num_partial_withdrawals=len(state.validators)) + spec, state, num_partial_withdrawals=withdrawal_count) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) @@ -189,7 +245,7 @@ def test_success_all_partially_withdrawable(spec, state): @with_phases([CAPELLA]) @spec_state_test -def test_fail_non_withdrawable_non_empty_withdrawals(spec, state): +def test_invalid_non_withdrawable_non_empty_withdrawals(spec, state): next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) withdrawal = spec.Withdrawal( @@ -199,115 +255,125 @@ def test_fail_non_withdrawable_non_empty_withdrawals(spec, state): amount=420, ) execution_payload.withdrawals.append(withdrawal) + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_one_expected_full_withdrawal_and_none_in_withdrawals(spec, state): +def test_invalid_one_expected_full_withdrawal_and_none_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, num_full_withdrawals=1) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals = [] + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_one_expected_partial_withdrawal_and_none_in_withdrawals(spec, state): +def test_invalid_one_expected_partial_withdrawal_and_none_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, num_partial_withdrawals=1) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals = [] + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_one_expected_full_withdrawal_and_duplicate_in_withdrawals(spec, state): +def test_invalid_one_expected_full_withdrawal_and_duplicate_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, num_full_withdrawals=2) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals.append(execution_payload.withdrawals[0].copy()) + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_two_expected_partial_withdrawal_and_duplicate_in_withdrawals(spec, state): +def test_invalid_two_expected_partial_withdrawal_and_duplicate_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, num_partial_withdrawals=2) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals.append(execution_payload.withdrawals[0].copy()) + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_max_per_slot_full_withdrawals_and_one_less_in_withdrawals(spec, state): +def test_invalid_max_per_slot_full_withdrawals_and_one_less_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals = execution_payload.withdrawals[:-1] + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_max_per_slot_partial_withdrawals_and_one_less_in_withdrawals(spec, state): +def test_invalid_max_per_slot_partial_withdrawals_and_one_less_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals = execution_payload.withdrawals[:-1] + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_a_lot_fully_withdrawable_too_few_in_withdrawals(spec, state): +def test_invalid_a_lot_fully_withdrawable_too_few_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals = execution_payload.withdrawals[:-1] + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_a_lot_partially_withdrawable_too_few_in_withdrawals(spec, state): +def test_invalid_a_lot_partially_withdrawable_too_few_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals = execution_payload.withdrawals[:-1] + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_a_lot_mixed_withdrawable_in_queue_too_few_in_withdrawals(spec, state): - prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4, - num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) +def test_invalid_a_lot_mixed_withdrawable_in_queue_too_few_in_withdrawals(spec, state): + prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD, + num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals = execution_payload.withdrawals[:-1] + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @@ -318,67 +384,72 @@ def test_fail_a_lot_mixed_withdrawable_in_queue_too_few_in_withdrawals(spec, sta @with_phases([CAPELLA]) @spec_state_test -def test_fail_incorrect_withdrawal_index(spec, state): +def test_invalid_incorrect_withdrawal_index(spec, state): prepare_expected_withdrawals(spec, state, num_full_withdrawals=1) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals[0].index += 1 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_incorrect_address_full(spec, state): +def test_invalid_incorrect_address_full(spec, state): prepare_expected_withdrawals(spec, state, num_full_withdrawals=1) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals[0].address = b'\xff' * 20 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_incorrect_address_partial(spec, state): +def test_invalid_incorrect_address_partial(spec, state): prepare_expected_withdrawals(spec, state, num_partial_withdrawals=1) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals[0].address = b'\xff' * 20 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_incorrect_amount_full(spec, state): +def test_invalid_incorrect_amount_full(spec, state): prepare_expected_withdrawals(spec, state, num_full_withdrawals=1) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals[0].amount += 1 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_incorrect_amount_partial(spec, state): +def test_invalid_incorrect_amount_partial(spec, state): prepare_expected_withdrawals(spec, state, num_full_withdrawals=1) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals[0].amount += 1 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_one_of_many_incorrectly_full(spec, state): +def test_invalid_one_of_many_incorrectly_full(spec, state): prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) next_slot(spec, state) @@ -390,13 +461,14 @@ def test_fail_one_of_many_incorrectly_full(spec, state): withdrawal.index += 1 withdrawal.address = b'\x99' * 20 withdrawal.amount += 4000000 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_one_of_many_incorrectly_partial(spec, state): +def test_invalid_one_of_many_incorrectly_partial(spec, state): prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) next_slot(spec, state) @@ -408,13 +480,14 @@ def test_fail_one_of_many_incorrectly_partial(spec, state): withdrawal.index += 1 withdrawal.address = b'\x99' * 20 withdrawal.amount += 4000000 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_many_incorrectly_full(spec, state): +def test_invalid_many_incorrectly_full(spec, state): prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) next_slot(spec, state) @@ -426,13 +499,14 @@ def test_fail_many_incorrectly_full(spec, state): withdrawal.address = i.to_bytes(20, 'big') else: withdrawal.amount += 1 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @with_phases([CAPELLA]) @spec_state_test -def test_fail_many_incorrectly_partial(spec, state): +def test_invalid_many_incorrectly_partial(spec, state): prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) next_slot(spec, state) @@ -444,6 +518,7 @@ def test_fail_many_incorrectly_partial(spec, state): withdrawal.address = i.to_bytes(20, 'big') else: withdrawal.amount += 1 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) @@ -624,7 +699,7 @@ def test_success_excess_balance_but_no_max_effective_balance(spec, state): @with_phases([CAPELLA]) @spec_state_test def test_success_one_partial_withdrawable_not_yet_active(spec, state): - validator_index = len(state.validators) // 2 + validator_index = min(len(state.validators) // 2, spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP - 1) state.validators[validator_index].activation_epoch += 4 set_validator_partially_withdrawable(spec, state, validator_index) @@ -638,7 +713,7 @@ def test_success_one_partial_withdrawable_not_yet_active(spec, state): @with_phases([CAPELLA]) @spec_state_test def test_success_one_partial_withdrawable_in_exit_queue(spec, state): - validator_index = len(state.validators) // 2 + validator_index = min(len(state.validators) // 2, spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP - 1) state.validators[validator_index].exit_epoch = spec.get_current_epoch(state) + 1 set_validator_partially_withdrawable(spec, state, validator_index) @@ -653,7 +728,7 @@ def test_success_one_partial_withdrawable_in_exit_queue(spec, state): @with_phases([CAPELLA]) @spec_state_test def test_success_one_partial_withdrawable_exited(spec, state): - validator_index = len(state.validators) // 2 + validator_index = min(len(state.validators) // 2, spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP - 1) state.validators[validator_index].exit_epoch = spec.get_current_epoch(state) set_validator_partially_withdrawable(spec, state, validator_index) @@ -667,7 +742,7 @@ def test_success_one_partial_withdrawable_exited(spec, state): @with_phases([CAPELLA]) @spec_state_test def test_success_one_partial_withdrawable_active_and_slashed(spec, state): - validator_index = len(state.validators) // 2 + validator_index = min(len(state.validators) // 2, spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP - 1) state.validators[validator_index].slashed = True set_validator_partially_withdrawable(spec, state, validator_index) @@ -681,7 +756,7 @@ def test_success_one_partial_withdrawable_active_and_slashed(spec, state): @with_phases([CAPELLA]) @spec_state_test def test_success_one_partial_withdrawable_exited_and_slashed(spec, state): - validator_index = len(state.validators) // 2 + validator_index = min(len(state.validators) // 2, spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP - 1) state.validators[validator_index].slashed = True state.validators[validator_index].exit_epoch = spec.get_current_epoch(state) set_validator_partially_withdrawable(spec, state, validator_index) diff --git a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py index 229d8ecc5..1df046c9d 100644 --- a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py @@ -194,8 +194,8 @@ def test_many_partial_withdrawals_in_epoch_transition(spec, state): def _perform_valid_withdrawal(spec, state): fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals( - spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4, - num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4) + spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 2, + num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 2) next_slot(spec, state) pre_next_withdrawal_index = state.next_withdrawal_index @@ -240,7 +240,7 @@ def test_withdrawal_success_two_blocks(spec, state): @with_phases([CAPELLA]) @spec_state_test -def test_withdrawal_fail_second_block_payload_isnt_compatible(spec, state): +def test_invalid_withdrawal_fail_second_block_payload_isnt_compatible(spec, state): _perform_valid_withdrawal(spec, state) # Block 2 diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index 39b889901..8401b973e 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -12,7 +12,7 @@ from eth2spec.utils import bls from .exceptions import SkippedTest from .helpers.constants import ( - PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844, SHARDING, + PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844, MINIMAL, MAINNET, ALL_PHASES, ALL_FORK_UPGRADES, @@ -259,6 +259,12 @@ def dump_skipping_message(reason: str) -> None: raise SkippedTest(message) +def description(case_description: str): + def entry(fn): + return with_meta_tags({'description': case_description})(fn) + return entry + + def spec_test(fn): # Bls switch must be wrapped by vector_test, # to fully go through the yielded bls switch data, before setting back the BLS setting. @@ -268,7 +274,7 @@ def spec_test(fn): return vector_test()(bls_switch(fn)) -# shorthand for decorating @spectest() @with_state @single_phase +# shorthand for decorating @spec_test @with_state @single_phase def spec_state_test(fn): return spec_test(with_state(single_phase(fn))) @@ -292,31 +298,16 @@ def _check_current_version(spec, state, version_name): def config_fork_epoch_overrides(spec, state): - overrides = {} if state.fork.current_version == spec.config.GENESIS_FORK_VERSION: - pass - elif _check_current_version(spec, state, ALTAIR): - overrides['ALTAIR_FORK_EPOCH'] = spec.GENESIS_EPOCH - elif _check_current_version(spec, state, BELLATRIX): - overrides['ALTAIR_FORK_EPOCH'] = spec.GENESIS_EPOCH - overrides['BELLATRIX_FORK_EPOCH'] = spec.GENESIS_EPOCH - elif _check_current_version(spec, state, CAPELLA): - overrides['ALTAIR_FORK_EPOCH'] = spec.GENESIS_EPOCH - overrides['BELLATRIX_FORK_EPOCH'] = spec.GENESIS_EPOCH - overrides['CAPELLA_FORK_EPOCH'] = spec.GENESIS_EPOCH - elif _check_current_version(spec, state, EIP4844): - overrides['ALTAIR_FORK_EPOCH'] = spec.GENESIS_EPOCH - overrides['BELLATRIX_FORK_EPOCH'] = spec.GENESIS_EPOCH - overrides['CAPELLA_FORK_EPOCH'] = spec.GENESIS_EPOCH - overrides['EIP4844_FORK_EPOCH'] = spec.GENESIS_EPOCH - elif _check_current_version(spec, state, SHARDING): - overrides['ALTAIR_FORK_EPOCH'] = spec.GENESIS_EPOCH - overrides['BELLATRIX_FORK_EPOCH'] = spec.GENESIS_EPOCH - overrides['CAPELLA_FORK_EPOCH'] = spec.GENESIS_EPOCH - overrides['SHARDING_FORK_EPOCH'] = spec.GENESIS_EPOCH - else: - assert False # Fork is missing - return overrides + return {} + + for fork in ALL_PHASES: + if fork != PHASE0 and _check_current_version(spec, state, fork): + overrides = {} + for f in ALL_PHASES: + if f != PHASE0 and is_post_fork(fork, f): + overrides[f.upper() + '_FORK_EPOCH'] = spec.GENESIS_EPOCH + return overrides def with_matching_spec_config(emitted_fork=None): diff --git a/tests/core/pyspec/eth2spec/test/eip4844/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/eip4844/sanity/test_blocks.py index f08a7fda9..0aeafe052 100644 --- a/tests/core/pyspec/eth2spec/test/eip4844/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/eip4844/sanity/test_blocks.py @@ -8,6 +8,9 @@ from eth2spec.test.context import ( spec_state_test, with_eip4844_and_later, ) +from eth2spec.test.helpers.execution_payload import ( + compute_el_block_hash, +) from eth2spec.test.helpers.sharding import ( get_sample_opaque_tx, ) @@ -22,6 +25,7 @@ def test_one_blob(spec, state): opaque_tx, _, blob_kzg_commitments = get_sample_opaque_tx(spec) block.body.blob_kzg_commitments = blob_kzg_commitments block.body.execution_payload.transactions = [opaque_tx] + 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] @@ -30,13 +34,14 @@ def test_one_blob(spec, state): @with_eip4844_and_later @spec_state_test -def test_multiple_blobs(spec, state): +def test_max_blobs(spec, state): yield 'pre', state block = build_empty_block_for_next_slot(spec, state) - opaque_tx, _, blob_kzg_commitments = get_sample_opaque_tx(spec, blob_count=5) + opaque_tx, _, blob_kzg_commitments = get_sample_opaque_tx(spec, blob_count=spec.MAX_BLOBS_PER_BLOCK) block.body.blob_kzg_commitments = blob_kzg_commitments block.body.execution_payload.transactions = [opaque_tx] + 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] diff --git a/tests/core/pyspec/eth2spec/test/eip4844/unittests/validator/test_validator.py b/tests/core/pyspec/eth2spec/test/eip4844/unittests/validator/test_validator.py index d9e3877c3..dbea9f784 100644 --- a/tests/core/pyspec/eth2spec/test/eip4844/unittests/validator/test_validator.py +++ b/tests/core/pyspec/eth2spec/test/eip4844/unittests/validator/test_validator.py @@ -8,6 +8,9 @@ from eth2spec.test.context import ( spec_state_test, with_eip4844_and_later, ) +from eth2spec.test.helpers.execution_payload import ( + compute_el_block_hash, +) from eth2spec.test.helpers.sharding import ( get_sample_opaque_tx, ) @@ -18,6 +21,7 @@ def _run_validate_blobs_sidecar_test(spec, state, blob_count): opaque_tx, blobs, blob_kzg_commitments = get_sample_opaque_tx(spec, blob_count=blob_count) block.body.blob_kzg_commitments = blob_kzg_commitments block.body.execution_payload.transactions = [opaque_tx] + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) state_transition_and_sign_block(spec, state, block) blobs_sidecar = spec.get_blobs_sidecar(block, blobs) @@ -45,5 +49,5 @@ def test_validate_blobs_sidecar_two_blobs(spec, state): @with_eip4844_and_later @spec_state_test -def test_validate_blobs_sidecar_ten_blobs(spec, state): - _run_validate_blobs_sidecar_test(spec, state, blob_count=10) +def test_validate_blobs_sidecar_max_blobs(spec, state): + _run_validate_blobs_sidecar_test(spec, state, blob_count=spec.MAX_BLOBS_PER_BLOCK) diff --git a/tests/core/pyspec/eth2spec/test/helpers/deposits.py b/tests/core/pyspec/eth2spec/test/helpers/deposits.py index f8ab75e85..cfff9c5ef 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/deposits.py +++ b/tests/core/pyspec/eth2spec/test/helpers/deposits.py @@ -208,25 +208,50 @@ def run_deposit_processing(spec, state, deposit, validator_index, valid=True, ef if not effective or not bls.KeyValidate(deposit.data.pubkey): assert len(state.validators) == pre_validator_count assert len(state.balances) == pre_validator_count - if validator_index < pre_validator_count: + if is_top_up: assert get_balance(state, validator_index) == pre_balance else: - if validator_index < pre_validator_count: - # top-up + if is_top_up: + # Top-ups do not change effective balance + assert state.validators[validator_index].effective_balance == pre_effective_balance 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 - - if is_top_up: - # Top-ups do not change effective balance - assert state.validators[validator_index].effective_balance == pre_effective_balance - else: effective_balance = min(spec.MAX_EFFECTIVE_BALANCE, deposit.data.amount) effective_balance -= effective_balance % spec.EFFECTIVE_BALANCE_INCREMENT assert state.validators[validator_index].effective_balance == effective_balance + assert get_balance(state, validator_index) == pre_balance + deposit.data.amount + assert state.eth1_deposit_index == state.eth1_data.deposit_count + + +def run_deposit_processing_with_specific_fork_version( + spec, + state, + fork_version, + valid=True, + effective=True): + 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) diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 5ed1472db..1f478ccc6 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -1,68 +1,10 @@ +from eth_hash.auto import keccak +from trie import HexaryTrie +from rlp import encode +from rlp.sedes import big_endian_int, Binary, List + from eth2spec.debug.random_value import get_random_bytes_list -from eth2spec.test.helpers.forks import is_post_capella - - -def build_empty_execution_payload(spec, state, randao_mix=None): - """ - Assuming a pre-state of the same slot, build a valid ExecutionPayload without any transactions. - """ - latest = state.latest_execution_payload_header - timestamp = spec.compute_timestamp_at_slot(state, state.slot) - empty_txs = spec.List[spec.Transaction, spec.MAX_TRANSACTIONS_PER_PAYLOAD]() - - if randao_mix is None: - randao_mix = spec.get_randao_mix(state, spec.get_current_epoch(state)) - - payload = spec.ExecutionPayload( - parent_hash=latest.block_hash, - fee_recipient=spec.ExecutionAddress(), - state_root=latest.state_root, # no changes to the state - receipts_root=b"no receipts here" + b"\x00" * 16, # TODO: root of empty MPT may be better. - logs_bloom=spec.ByteVector[spec.BYTES_PER_LOGS_BLOOM](), # TODO: zeroed logs bloom for empty logs ok? - block_number=latest.block_number + 1, - prev_randao=randao_mix, - gas_limit=latest.gas_limit, # retain same limit - gas_used=0, # empty block, 0 gas - timestamp=timestamp, - extra_data=spec.ByteList[spec.MAX_EXTRA_DATA_BYTES](), - base_fee_per_gas=latest.base_fee_per_gas, # retain same base_fee - block_hash=spec.Hash32(), - transactions=empty_txs, - ) - if is_post_capella(spec): - payload.withdrawals = spec.get_expected_withdrawals(state) - - # TODO: real RLP + block hash logic would be nice, requires RLP and keccak256 dependency however. - payload.block_hash = spec.Hash32(spec.hash(payload.hash_tree_root() + b"FAKE RLP HASH")) - - return payload - - -def build_randomized_execution_payload(spec, state, rng): - execution_payload = build_empty_execution_payload(spec, state) - execution_payload.fee_recipient = spec.ExecutionAddress(get_random_bytes_list(rng, 20)) - execution_payload.state_root = spec.Bytes32(get_random_bytes_list(rng, 32)) - execution_payload.receipts_root = spec.Bytes32(get_random_bytes_list(rng, 32)) - execution_payload.logs_bloom = spec.ByteVector[spec.BYTES_PER_LOGS_BLOOM]( - get_random_bytes_list(rng, spec.BYTES_PER_LOGS_BLOOM) - ) - execution_payload.block_number = rng.randint(0, 10e10) - execution_payload.gas_limit = rng.randint(0, 10e10) - execution_payload.gas_used = rng.randint(0, 10e10) - extra_data_length = rng.randint(0, spec.MAX_EXTRA_DATA_BYTES) - execution_payload.extra_data = spec.ByteList[spec.MAX_EXTRA_DATA_BYTES]( - get_random_bytes_list(rng, extra_data_length) - ) - execution_payload.base_fee_per_gas = rng.randint(0, 2**256 - 1) - execution_payload.block_hash = spec.Hash32(get_random_bytes_list(rng, 32)) - - num_transactions = rng.randint(0, 100) - execution_payload.transactions = [ - spec.Transaction(get_random_bytes_list(rng, rng.randint(0, 1000))) - for _ in range(num_transactions) - ] - - return execution_payload +from eth2spec.test.helpers.forks import is_post_capella, is_post_eip4844 def get_execution_payload_header(spec, execution_payload): @@ -87,6 +29,174 @@ def get_execution_payload_header(spec, execution_payload): return payload_header +# https://eips.ethereum.org/EIPS/eip-2718 +def compute_trie_root_from_indexed_data(data): + """ + Computes the root hash of `patriciaTrie(rlp(Index) => Data)` for a data array. + """ + t = HexaryTrie(db={}) + for i, obj in enumerate(data): + k = encode(i, big_endian_int) + t.set(k, obj) + return t.root_hash + + +# https://eips.ethereum.org/EIPS/eip-4895 +# https://eips.ethereum.org/EIPS/eip-4844 +def compute_el_header_block_hash(spec, + payload_header, + transactions_trie_root, + withdrawals_trie_root=None): + """ + Computes the RLP execution block hash described by an `ExecutionPayloadHeader`. + """ + execution_payload_header_rlp = [ + # parent_hash + (Binary(32, 32), payload_header.parent_hash), + # ommers_hash + (Binary(32, 32), bytes.fromhex("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")), + # coinbase + (Binary(20, 20), payload_header.fee_recipient), + # state_root + (Binary(32, 32), payload_header.state_root), + # txs_root + (Binary(32, 32), transactions_trie_root), + # receipts_root + (Binary(32, 32), payload_header.receipts_root), + # logs_bloom + (Binary(256, 256), payload_header.logs_bloom), + # difficulty + (big_endian_int, 0), + # number + (big_endian_int, payload_header.block_number), + # gas_limit + (big_endian_int, payload_header.gas_limit), + # gas_used + (big_endian_int, payload_header.gas_used), + # timestamp + (big_endian_int, payload_header.timestamp), + # extradata + (Binary(0, 32), payload_header.extra_data), + # prev_randao + (Binary(32, 32), payload_header.prev_randao), + # nonce + (Binary(8, 8), bytes.fromhex("0000000000000000")), + # base_fee_per_gas + (big_endian_int, payload_header.base_fee_per_gas), + ] + if is_post_capella(spec): + # withdrawals_root + execution_payload_header_rlp.append((Binary(32, 32), withdrawals_trie_root)) + if is_post_eip4844(spec): + # excess_data_gas + execution_payload_header_rlp.append((big_endian_int, payload_header.excess_data_gas)) + + sedes = List([schema for schema, _ in execution_payload_header_rlp]) + values = [value for _, value in execution_payload_header_rlp] + encoded = encode(values, sedes) + + return spec.Hash32(keccak(encoded)) + + +# https://eips.ethereum.org/EIPS/eip-4895 +def get_withdrawal_rlp(spec, withdrawal): + withdrawal_rlp = [ + # index + (big_endian_int, withdrawal.index), + # validator_index + (big_endian_int, withdrawal.validator_index), + # address + (Binary(20, 20), withdrawal.address), + # amount + (big_endian_int, spec.uint256(withdrawal.amount) * (10**9)), + ] + + sedes = List([schema for schema, _ in withdrawal_rlp]) + values = [value for _, value in withdrawal_rlp] + return encode(values, sedes) + + +def compute_el_block_hash(spec, payload): + transactions_trie_root = compute_trie_root_from_indexed_data(payload.transactions) + + if is_post_capella(spec): + withdrawals_encoded = [get_withdrawal_rlp(spec, withdrawal) for withdrawal in payload.withdrawals] + withdrawals_trie_root = compute_trie_root_from_indexed_data(withdrawals_encoded) + else: + withdrawals_trie_root = None + + payload_header = get_execution_payload_header(spec, payload) + + return compute_el_header_block_hash( + spec, + payload_header, + transactions_trie_root, + withdrawals_trie_root, + ) + + +def build_empty_execution_payload(spec, state, randao_mix=None): + """ + Assuming a pre-state of the same slot, build a valid ExecutionPayload without any transactions. + """ + latest = state.latest_execution_payload_header + timestamp = spec.compute_timestamp_at_slot(state, state.slot) + empty_txs = spec.List[spec.Transaction, spec.MAX_TRANSACTIONS_PER_PAYLOAD]() + + if randao_mix is None: + randao_mix = spec.get_randao_mix(state, spec.get_current_epoch(state)) + + payload = spec.ExecutionPayload( + parent_hash=latest.block_hash, + fee_recipient=spec.ExecutionAddress(), + state_root=latest.state_root, # no changes to the state + receipts_root=spec.Bytes32(bytes.fromhex("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")), + logs_bloom=spec.ByteVector[spec.BYTES_PER_LOGS_BLOOM](), # TODO: zeroed logs bloom for empty logs ok? + block_number=latest.block_number + 1, + prev_randao=randao_mix, + gas_limit=latest.gas_limit, # retain same limit + gas_used=0, # empty block, 0 gas + timestamp=timestamp, + extra_data=spec.ByteList[spec.MAX_EXTRA_DATA_BYTES](), + base_fee_per_gas=latest.base_fee_per_gas, # retain same base_fee + transactions=empty_txs, + ) + if is_post_capella(spec): + payload.withdrawals = spec.get_expected_withdrawals(state) + + payload.block_hash = compute_el_block_hash(spec, payload) + + return payload + + +def build_randomized_execution_payload(spec, state, rng): + execution_payload = build_empty_execution_payload(spec, state) + execution_payload.fee_recipient = spec.ExecutionAddress(get_random_bytes_list(rng, 20)) + execution_payload.state_root = spec.Bytes32(get_random_bytes_list(rng, 32)) + execution_payload.receipts_root = spec.Bytes32(get_random_bytes_list(rng, 32)) + execution_payload.logs_bloom = spec.ByteVector[spec.BYTES_PER_LOGS_BLOOM]( + get_random_bytes_list(rng, spec.BYTES_PER_LOGS_BLOOM) + ) + execution_payload.block_number = rng.randint(0, 10e10) + execution_payload.gas_limit = rng.randint(0, 10e10) + execution_payload.gas_used = rng.randint(0, 10e10) + extra_data_length = rng.randint(0, spec.MAX_EXTRA_DATA_BYTES) + execution_payload.extra_data = spec.ByteList[spec.MAX_EXTRA_DATA_BYTES]( + get_random_bytes_list(rng, extra_data_length) + ) + execution_payload.base_fee_per_gas = rng.randint(0, 2**256 - 1) + + num_transactions = rng.randint(0, 100) + execution_payload.transactions = [ + spec.Transaction(get_random_bytes_list(rng, rng.randint(0, 1000))) + for _ in range(num_transactions) + ] + + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) + + return execution_payload + + def build_state_with_incomplete_transition(spec, state): state = build_state_with_execution_payload_header(spec, state, spec.ExecutionPayloadHeader()) assert not spec.is_merge_transition_complete(state) diff --git a/tests/core/pyspec/eth2spec/test/helpers/genesis.py b/tests/core/pyspec/eth2spec/test/helpers/genesis.py index d758936e9..de2dd2647 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/genesis.py +++ b/tests/core/pyspec/eth2spec/test/helpers/genesis.py @@ -1,8 +1,11 @@ from eth2spec.test.helpers.constants import ( ALTAIR, BELLATRIX, CAPELLA, EIP4844, ) +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_altair, is_post_bellatrix, is_post_capella, ) from eth2spec.test.helpers.keys import pubkeys @@ -29,7 +32,7 @@ def get_sample_genesis_execution_payload_header(spec, eth1_block_hash=None): if eth1_block_hash is None: eth1_block_hash = b'\x55' * 32 - return spec.ExecutionPayloadHeader( + payload_header = spec.ExecutionPayloadHeader( parent_hash=b'\x30' * 32, fee_recipient=b'\x42' * 20, state_root=b'\x20' * 32, @@ -43,6 +46,21 @@ def get_sample_genesis_execution_payload_header(spec, transactions_root=spec.Root(b'\x56' * 32), ) + transactions_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + + if is_post_capella(spec): + withdrawals_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + else: + withdrawals_trie_root = None + + payload_header.block_hash = compute_el_header_block_hash( + spec, + payload_header, + transactions_trie_root, + withdrawals_trie_root, + ) + return payload_header + def create_genesis_state(spec, validator_balances, activation_threshold): deposit_root = b'\x42' * 32 diff --git a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py index a55ac36ef..aebe49f26 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py @@ -36,9 +36,10 @@ def set_validator_partially_withdrawable(spec, state, index, excess_balance=1000 def prepare_expected_withdrawals(spec, state, num_full_withdrawals=0, num_partial_withdrawals=0, rng=random.Random(5566)): - assert num_full_withdrawals + num_partial_withdrawals <= len(state.validators) - all_validator_indices = list(range(len(state.validators))) - sampled_indices = rng.sample(all_validator_indices, num_full_withdrawals + num_partial_withdrawals) + bound = min(len(state.validators), spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) + assert num_full_withdrawals + num_partial_withdrawals <= bound + eligible_validator_indices = list(range(bound)) + sampled_indices = rng.sample(eligible_validator_indices, num_full_withdrawals + num_partial_withdrawals) fully_withdrawable_indices = rng.sample(sampled_indices, num_full_withdrawals) partial_withdrawals_indices = list(set(sampled_indices).difference(set(fully_withdrawable_indices))) diff --git a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_attestation.py b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_attestation.py index 8d9e67998..7595ce9cb 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_attestation.py +++ b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_attestation.py @@ -23,7 +23,7 @@ from eth2spec.utils.ssz.ssz_typing import Bitlist @with_all_phases @spec_state_test -def test_success(spec, state): +def test_one_basic_attestation(spec, state): attestation = get_valid_attestation(spec, state, signed=True) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -34,7 +34,7 @@ def test_success(spec, state): @spec_test @with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE) @single_phase -def test_success_multi_proposer_index_iterations(spec, state): +def test_multi_proposer_index_iterations(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2) attestation = get_valid_attestation(spec, state, signed=True) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -44,7 +44,7 @@ def test_success_multi_proposer_index_iterations(spec, state): @with_all_phases @spec_state_test -def test_success_previous_epoch(spec, state): +def test_previous_epoch(spec, state): attestation = get_valid_attestation(spec, state, signed=True) next_epoch_via_block(spec, state) @@ -58,55 +58,55 @@ def test_invalid_attestation_signature(spec, state): attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test @always_bls -def test_empty_participants_zeroes_sig(spec, state): +def test_invalid_empty_participants_zeroes_sig(spec, state): attestation = get_valid_attestation(spec, state, filter_participant_set=lambda comm: []) # 0 participants attestation.signature = spec.BLSSignature(b'\x00' * 96) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test @always_bls -def test_empty_participants_seemingly_valid_sig(spec, state): +def test_invalid_empty_participants_seemingly_valid_sig(spec, state): attestation = get_valid_attestation(spec, state, filter_participant_set=lambda comm: []) # 0 participants # Special BLS value, valid for zero pubkeys on some (but not all) BLS implementations. attestation.signature = spec.BLSSignature(b'\xc0' + b'\x00' * 95) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test -def test_before_inclusion_delay(spec, state): +def test_invalid_before_inclusion_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=True) # do not increment slot to allow for inclusion delay - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test -def test_after_epoch_slots(spec, state): +def test_invalid_after_epoch_slots(spec, state): attestation = get_valid_attestation(spec, state, signed=True) # increment past latest inclusion slot transition_to_slot_via_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH + 1) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test -def test_old_source_epoch(spec, state): +def test_invalid_old_source_epoch(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH * 5) state.finalized_checkpoint.epoch = 2 state.previous_justified_checkpoint.epoch = 3 @@ -121,19 +121,19 @@ def test_old_source_epoch(spec, state): sign_attestation(spec, state, attestation) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test @always_bls -def test_wrong_index_for_committee_signature(spec, state): +def test_invalid_wrong_index_for_committee_signature(spec, state): attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) attestation.data.index += 1 - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) def reduce_state_committee_count_from_max(spec, state): @@ -148,7 +148,7 @@ def reduce_state_committee_count_from_max(spec, state): @with_all_phases @spec_state_test @never_bls -def test_wrong_index_for_slot_0(spec, state): +def test_invalid_wrong_index_for_slot_0(spec, state): reduce_state_committee_count_from_max(spec, state) attestation = get_valid_attestation(spec, state) @@ -157,13 +157,13 @@ def test_wrong_index_for_slot_0(spec, state): # Invalid index: current committees per slot is less than the max attestation.data.index = spec.MAX_COMMITTEES_PER_SLOT - 1 - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test @never_bls -def test_wrong_index_for_slot_1(spec, state): +def test_invalid_wrong_index_for_slot_1(spec, state): reduce_state_committee_count_from_max(spec, state) current_epoch = spec.get_current_epoch(state) @@ -175,7 +175,7 @@ def test_wrong_index_for_slot_1(spec, state): # Invalid index: off by one attestation.data.index = committee_count - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @@ -188,12 +188,12 @@ def test_invalid_index(spec, state): # Invalid index: off by one (with respect to valid range) on purpose attestation.data.index = spec.MAX_COMMITTEES_PER_SLOT - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test -def test_mismatched_target_and_slot(spec, state): +def test_invalid_mismatched_target_and_slot(spec, state): next_epoch_via_block(spec, state) next_epoch_via_block(spec, state) @@ -202,24 +202,24 @@ def test_mismatched_target_and_slot(spec, state): sign_attestation(spec, state, attestation) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test -def test_old_target_epoch(spec, state): +def test_invalid_old_target_epoch(spec, state): assert spec.MIN_ATTESTATION_INCLUSION_DELAY < spec.SLOTS_PER_EPOCH * 2 attestation = get_valid_attestation(spec, state, signed=True) next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2) # target epoch will be too old to handle - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test -def test_future_target_epoch(spec, state): +def test_invalid_future_target_epoch(spec, state): assert spec.MIN_ATTESTATION_INCLUSION_DELAY < spec.SLOTS_PER_EPOCH * 2 attestation = get_valid_attestation(spec, state) @@ -236,12 +236,12 @@ def test_future_target_epoch(spec, state): next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test -def test_new_source_epoch(spec, state): +def test_invalid_new_source_epoch(spec, state): attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -249,12 +249,12 @@ def test_new_source_epoch(spec, state): sign_attestation(spec, state, attestation) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test -def test_source_root_is_target_root(spec, state): +def test_invalid_source_root_is_target_root(spec, state): attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -262,7 +262,7 @@ def test_source_root_is_target_root(spec, state): sign_attestation(spec, state, attestation) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @@ -289,7 +289,7 @@ def test_invalid_current_source_root(spec, state): sign_attestation(spec, state, attestation) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @@ -315,12 +315,12 @@ def test_invalid_previous_source_root(spec, state): sign_attestation(spec, state, attestation) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test -def test_bad_source_root(spec, state): +def test_invalid_bad_source_root(spec, state): attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -328,24 +328,24 @@ def test_bad_source_root(spec, state): sign_attestation(spec, state, attestation) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test -def test_too_many_aggregation_bits(spec, state): +def test_invalid_too_many_aggregation_bits(spec, state): attestation = get_valid_attestation(spec, state, signed=True) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) # one too many bits attestation.aggregation_bits.append(0b0) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) @with_all_phases @spec_state_test -def test_too_few_aggregation_bits(spec, state): +def test_invalid_too_few_aggregation_bits(spec, state): attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -357,7 +357,7 @@ def test_too_few_aggregation_bits(spec, state): # one too few bits attestation.aggregation_bits = attestation.aggregation_bits[:-1] - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) # @@ -366,7 +366,7 @@ def test_too_few_aggregation_bits(spec, state): @with_all_phases @spec_state_test -def test_correct_min_inclusion_delay(spec, state): +def test_correct_attestation_included_at_min_inclusion_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=True) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -375,7 +375,7 @@ def test_correct_min_inclusion_delay(spec, state): @with_all_phases @spec_state_test -def test_correct_sqrt_epoch_delay(spec, state): +def test_correct_attestation_included_at_sqrt_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=True) next_slots(spec, state, spec.integer_squareroot(spec.SLOTS_PER_EPOCH)) @@ -384,7 +384,7 @@ def test_correct_sqrt_epoch_delay(spec, state): @with_all_phases @spec_state_test -def test_correct_epoch_delay(spec, state): +def test_correct_attestation_included_at_one_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=True) next_slots(spec, state, spec.SLOTS_PER_EPOCH) @@ -393,13 +393,13 @@ def test_correct_epoch_delay(spec, state): @with_all_phases @spec_state_test -def test_correct_after_epoch_delay(spec, state): +def test_invalid_correct_attestation_included_after_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=True) # increment past latest inclusion slot next_slots(spec, state, spec.SLOTS_PER_EPOCH + 1) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) # @@ -408,7 +408,7 @@ def test_correct_after_epoch_delay(spec, state): @with_all_phases @spec_state_test -def test_incorrect_head_min_inclusion_delay(spec, state): +def test_incorrect_head_included_at_min_inclusion_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -420,7 +420,7 @@ def test_incorrect_head_min_inclusion_delay(spec, state): @with_all_phases @spec_state_test -def test_incorrect_head_sqrt_epoch_delay(spec, state): +def test_incorrect_head_included_at_sqrt_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) next_slots(spec, state, spec.integer_squareroot(spec.SLOTS_PER_EPOCH)) @@ -432,7 +432,7 @@ def test_incorrect_head_sqrt_epoch_delay(spec, state): @with_all_phases @spec_state_test -def test_incorrect_head_epoch_delay(spec, state): +def test_incorrect_head_included_at_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) next_slots(spec, state, spec.SLOTS_PER_EPOCH) @@ -444,7 +444,7 @@ def test_incorrect_head_epoch_delay(spec, state): @with_all_phases @spec_state_test -def test_incorrect_head_after_epoch_delay(spec, state): +def test_invalid_incorrect_head_included_after_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) # increment past latest inclusion slot @@ -453,7 +453,7 @@ def test_incorrect_head_after_epoch_delay(spec, state): attestation.data.beacon_block_root = b'\x42' * 32 sign_attestation(spec, state, attestation) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) # @@ -475,7 +475,7 @@ def test_incorrect_head_and_target_min_inclusion_delay(spec, state): @with_all_phases @spec_state_test -def test_incorrect_head_and_target_sqrt_epoch_delay(spec, state): +def test_incorrect_head_and_target_included_at_sqrt_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) next_slots(spec, state, spec.integer_squareroot(spec.SLOTS_PER_EPOCH)) @@ -488,7 +488,7 @@ def test_incorrect_head_and_target_sqrt_epoch_delay(spec, state): @with_all_phases @spec_state_test -def test_incorrect_head_and_target_epoch_delay(spec, state): +def test_incorrect_head_and_target_included_at_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) next_slots(spec, state, spec.SLOTS_PER_EPOCH) @@ -501,7 +501,7 @@ def test_incorrect_head_and_target_epoch_delay(spec, state): @with_all_phases @spec_state_test -def test_incorrect_head_and_target_after_epoch_delay(spec, state): +def test_invalid_incorrect_head_and_target_included_after_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) # increment past latest inclusion slot next_slots(spec, state, spec.SLOTS_PER_EPOCH + 1) @@ -510,7 +510,7 @@ def test_incorrect_head_and_target_after_epoch_delay(spec, state): attestation.data.target.root = b'\x42' * 32 sign_attestation(spec, state, attestation) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) # @@ -519,7 +519,7 @@ def test_incorrect_head_and_target_after_epoch_delay(spec, state): @with_all_phases @spec_state_test -def test_incorrect_target_min_inclusion_delay(spec, state): +def test_incorrect_target_included_at_min_inclusion_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -531,7 +531,7 @@ def test_incorrect_target_min_inclusion_delay(spec, state): @with_all_phases @spec_state_test -def test_incorrect_target_sqrt_epoch_delay(spec, state): +def test_incorrect_target_included_at_sqrt_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) next_slots(spec, state, spec.integer_squareroot(spec.SLOTS_PER_EPOCH)) @@ -543,7 +543,7 @@ def test_incorrect_target_sqrt_epoch_delay(spec, state): @with_all_phases @spec_state_test -def test_incorrect_target_epoch_delay(spec, state): +def test_incorrect_target_included_at_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) next_slots(spec, state, spec.SLOTS_PER_EPOCH) @@ -555,7 +555,7 @@ def test_incorrect_target_epoch_delay(spec, state): @with_all_phases @spec_state_test -def test_incorrect_target_after_epoch_delay(spec, state): +def test_invalid_incorrect_target_included_after_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) # increment past latest inclusion slot next_slots(spec, state, spec.SLOTS_PER_EPOCH + 1) @@ -563,4 +563,4 @@ def test_incorrect_target_after_epoch_delay(spec, state): attestation.data.target.root = b'\x42' * 32 sign_attestation(spec, state, attestation) - yield from run_attestation_processing(spec, state, attestation, False) + yield from run_attestation_processing(spec, state, attestation, valid=False) diff --git a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_attester_slashing.py b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_attester_slashing.py index 13d64e03b..e63554677 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_attester_slashing.py +++ b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_attester_slashing.py @@ -91,7 +91,7 @@ def run_attester_slashing_processing(spec, state, attester_slashing, valid=True) @with_all_phases @spec_state_test -def test_success_double(spec, state): +def test_basic_double(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) yield from run_attester_slashing_processing(spec, state, attester_slashing) @@ -99,7 +99,7 @@ def test_success_double(spec, state): @with_all_phases @spec_state_test -def test_success_surround(spec, state): +def test_basic_surround(spec, state): next_epoch_via_block(spec, state) state.current_justified_checkpoint.epoch += 1 @@ -119,7 +119,7 @@ def test_success_surround(spec, state): @with_all_phases @spec_state_test @always_bls -def test_success_already_exited_recent(spec, state): +def test_already_exited_recent(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) slashed_indices = get_indexed_attestation_participants(spec, attester_slashing.attestation_1) for index in slashed_indices: @@ -131,7 +131,7 @@ def test_success_already_exited_recent(spec, state): @with_all_phases @spec_state_test @always_bls -def test_success_proposer_index_slashed(spec, state): +def test_proposer_index_slashed(spec, state): # Transition past genesis slot because generally doesn't have a proposer next_epoch_via_block(spec, state) @@ -147,7 +147,7 @@ def test_success_proposer_index_slashed(spec, state): @with_all_phases @spec_state_test -def test_success_attestation_from_future(spec, state): +def test_attestation_from_future(spec, state): # Transition state to future to enable generation of a "future" attestation future_state = state.copy() next_epoch_via_block(spec, future_state) @@ -165,7 +165,7 @@ def test_success_attestation_from_future(spec, state): @with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE) @spec_test @single_phase -def test_success_low_balances(spec, state): +def test_low_balances(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) yield from run_attester_slashing_processing(spec, state, attester_slashing) @@ -175,7 +175,7 @@ def test_success_low_balances(spec, state): @with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE) @spec_test @single_phase -def test_success_misc_balances(spec, state): +def test_misc_balances(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) yield from run_attester_slashing_processing(spec, state, attester_slashing) @@ -185,7 +185,7 @@ def test_success_misc_balances(spec, state): @with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE) @spec_test @single_phase -def test_success_with_effective_balance_disparity(spec, state): +def test_with_effective_balance_disparity(spec, state): # Jitter balances to be different from effective balances rng = Random(12345) for i in range(len(state.balances)): @@ -200,7 +200,7 @@ def test_success_with_effective_balance_disparity(spec, state): @with_all_phases @spec_state_test @always_bls -def test_success_already_exited_long_ago(spec, state): +def test_already_exited_long_ago(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) slashed_indices = get_indexed_attestation_participants(spec, attester_slashing.attestation_1) for index in slashed_indices: @@ -213,30 +213,30 @@ def test_success_already_exited_long_ago(spec, state): @with_all_phases @spec_state_test @always_bls -def test_invalid_sig_1(spec, state): +def test_invalid_incorrect_sig_1(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_invalid_sig_2(spec, state): +def test_invalid_incorrect_sig_2(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=False) - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_invalid_sig_1_and_2(spec, state): +def test_invalid_incorrect_sig_1_and_2(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=False) - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test -def test_same_data(spec, state): +def test_invalid_same_data(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) indexed_att_1 = attester_slashing.attestation_1 @@ -244,12 +244,12 @@ def test_same_data(spec, state): indexed_att_1.data = att_2_data sign_indexed_attestation(spec, state, attester_slashing.attestation_1) - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test -def test_no_double_or_surround(spec, state): +def test_invalid_no_double_or_surround(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) att_1_data = get_attestation_1_data(spec, attester_slashing) @@ -257,12 +257,12 @@ def test_no_double_or_surround(spec, state): sign_indexed_attestation(spec, state, attester_slashing.attestation_1) - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test -def test_participants_already_slashed(spec, state): +def test_invalid_participants_already_slashed(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) # set all indices to slashed @@ -270,63 +270,63 @@ def test_participants_already_slashed(spec, state): for index in validator_indices: state.validators[index].slashed = True - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_att1_high_index(spec, state): +def test_invalid_att1_high_index(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) indices = get_indexed_attestation_participants(spec, attester_slashing.attestation_1) indices.append(spec.ValidatorIndex(len(state.validators))) # off by 1 attester_slashing.attestation_1.attesting_indices = indices - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_att2_high_index(spec, state): +def test_invalid_att2_high_index(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) indices = get_indexed_attestation_participants(spec, attester_slashing.attestation_2) indices.append(spec.ValidatorIndex(len(state.validators))) # off by 1 attester_slashing.attestation_2.attesting_indices = indices - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_att1_empty_indices(spec, state): +def test_invalid_att1_empty_indices(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) attester_slashing.attestation_1.attesting_indices = [] attester_slashing.attestation_1.signature = spec.bls.G2_POINT_AT_INFINITY - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_att2_empty_indices(spec, state): +def test_invalid_att2_empty_indices(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=False) attester_slashing.attestation_2.attesting_indices = [] attester_slashing.attestation_2.signature = spec.bls.G2_POINT_AT_INFINITY - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_all_empty_indices(spec, state): +def test_invalid_all_empty_indices(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=False) attester_slashing.attestation_1.attesting_indices = [] @@ -335,13 +335,13 @@ def test_all_empty_indices(spec, state): attester_slashing.attestation_2.attesting_indices = [] attester_slashing.attestation_2.signature = spec.bls.G2_POINT_AT_INFINITY - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_att1_bad_extra_index(spec, state): +def test_invalid_att1_bad_extra_index(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) indices = get_indexed_attestation_participants(spec, attester_slashing.attestation_1) @@ -351,13 +351,13 @@ def test_att1_bad_extra_index(spec, state): # Do not sign the modified attestation (it's ok to slash if attester signed, not if they did not), # see if the bad extra index is spotted, and slashing is aborted. - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_att1_bad_replaced_index(spec, state): +def test_invalid_att1_bad_replaced_index(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) indices = attester_slashing.attestation_1.attesting_indices @@ -367,13 +367,13 @@ def test_att1_bad_replaced_index(spec, state): # Do not sign the modified attestation (it's ok to slash if attester signed, not if they did not), # see if the bad replaced index is spotted, and slashing is aborted. - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_att2_bad_extra_index(spec, state): +def test_invalid_att2_bad_extra_index(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) indices = attester_slashing.attestation_2.attesting_indices @@ -383,13 +383,13 @@ def test_att2_bad_extra_index(spec, state): # Do not sign the modified attestation (it's ok to slash if attester signed, not if they did not), # see if the bad extra index is spotted, and slashing is aborted. - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_att2_bad_replaced_index(spec, state): +def test_invalid_att2_bad_replaced_index(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) indices = attester_slashing.attestation_2.attesting_indices @@ -399,13 +399,13 @@ def test_att2_bad_replaced_index(spec, state): # Do not sign the modified attestation (it's ok to slash if attester signed, not if they did not), # see if the bad replaced index is spotted, and slashing is aborted. - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_att1_duplicate_index_normal_signed(spec, state): +def test_invalid_att1_duplicate_index_normal_signed(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) indices = list(attester_slashing.attestation_1.attesting_indices) @@ -419,13 +419,13 @@ def test_att1_duplicate_index_normal_signed(spec, state): attester_slashing.attestation_1.attesting_indices = sorted(indices) # it will just appear normal, unless the double index is spotted - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_att2_duplicate_index_normal_signed(spec, state): +def test_invalid_att2_duplicate_index_normal_signed(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=False) indices = list(attester_slashing.attestation_2.attesting_indices) @@ -439,13 +439,13 @@ def test_att2_duplicate_index_normal_signed(spec, state): attester_slashing.attestation_2.attesting_indices = sorted(indices) # it will just appear normal, unless the double index is spotted - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_att1_duplicate_index_double_signed(spec, state): +def test_invalid_att1_duplicate_index_double_signed(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) indices = list(attester_slashing.attestation_1.attesting_indices) @@ -454,13 +454,13 @@ def test_att1_duplicate_index_double_signed(spec, state): attester_slashing.attestation_1.attesting_indices = sorted(indices) sign_indexed_attestation(spec, state, attester_slashing.attestation_1) # will have one attester signing it double - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_att2_duplicate_index_double_signed(spec, state): +def test_invalid_att2_duplicate_index_double_signed(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=False) indices = list(attester_slashing.attestation_2.attesting_indices) @@ -469,12 +469,12 @@ def test_att2_duplicate_index_double_signed(spec, state): attester_slashing.attestation_2.attesting_indices = sorted(indices) sign_indexed_attestation(spec, state, attester_slashing.attestation_2) # will have one attester signing it double - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test -def test_unsorted_att_1(spec, state): +def test_invalid_unsorted_att_1(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) indices = attester_slashing.attestation_1.attesting_indices @@ -482,12 +482,12 @@ def test_unsorted_att_1(spec, state): indices[1], indices[2] = indices[2], indices[1] # unsort second and third index sign_indexed_attestation(spec, state, attester_slashing.attestation_1) - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) @with_all_phases @spec_state_test -def test_unsorted_att_2(spec, state): +def test_invalid_unsorted_att_2(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=False) indices = attester_slashing.attestation_2.attesting_indices @@ -495,4 +495,4 @@ def test_unsorted_att_2(spec, state): indices[1], indices[2] = indices[2], indices[1] # unsort second and third index sign_indexed_attestation(spec, state, attester_slashing.attestation_2) - yield from run_attester_slashing_processing(spec, state, attester_slashing, False) + yield from run_attester_slashing_processing(spec, state, attester_slashing, valid=False) diff --git a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py index b57090568..5188d8f91 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py +++ b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py @@ -34,7 +34,7 @@ def run_block_header_processing(spec, state, block, prepare_state=True, valid=Tr @with_all_phases @spec_state_test -def test_success_block_header(spec, state): +def test_basic_block_header(spec, state): block = build_empty_block_for_next_slot(spec, state) yield from run_block_header_processing(spec, state, block) @@ -87,7 +87,7 @@ def test_invalid_multiple_blocks_single_slot(spec, state): @with_all_phases @spec_state_test -def test_proposer_slashed(spec, state): +def test_invalid_proposer_slashed(spec, state): # use stub state to get proposer index of next slot stub_state = deepcopy(state) next_slot(spec, stub_state) diff --git a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_deposit.py b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_deposit.py index 20d8d7d74..bcfcedd92 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_deposit.py +++ b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_deposit.py @@ -1,13 +1,12 @@ from eth2spec.test.context import spec_state_test, always_bls, with_all_phases from eth2spec.test.helpers.deposits import ( build_deposit, - deposit_from_context, prepare_state_and_deposit, run_deposit_processing, + run_deposit_processing_with_specific_fork_version, sign_deposit_data, ) from eth2spec.test.helpers.keys import privkeys, pubkeys -from eth2spec.utils import bls @with_all_phases @@ -92,56 +91,29 @@ def test_new_deposit_non_versioned_withdrawal_credentials(spec, state): @with_all_phases @spec_state_test @always_bls -def test_invalid_sig_other_version(spec, state): - 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:] - - # Go through the effort of manually signing, not something normally done. This sig domain will be invalid. - deposit_message = spec.DepositMessage(pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, amount=amount) - domain = spec.compute_domain(domain_type=spec.DOMAIN_DEPOSIT, fork_version=spec.Version('0xaabbccdd')) - 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=True, effective=False) - - -@with_all_phases -@spec_state_test -@always_bls -def test_valid_sig_but_forked_state(spec, state): +def test_correct_sig_but_forked_state(spec, state): validator_index = len(state.validators) amount = spec.MAX_EFFECTIVE_BALANCE # deposits will always be valid, regardless of the current fork state.fork.current_version = spec.Version('0x1234abcd') deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True) - yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=True) + yield from run_deposit_processing(spec, state, deposit, validator_index) @with_all_phases @spec_state_test @always_bls -def test_invalid_sig_new_deposit(spec, state): +def test_incorrect_sig_new_deposit(spec, state): # fresh deposit = next validator index = validator appended to registry validator_index = len(state.validators) amount = spec.MAX_EFFECTIVE_BALANCE deposit = prepare_state_and_deposit(spec, state, validator_index, amount) - yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=False) + yield from run_deposit_processing(spec, state, deposit, validator_index, effective=False) @with_all_phases @spec_state_test -def test_success_top_up__max_effective_balance(spec, state): +def test_top_up__max_effective_balance(spec, state): validator_index = 0 amount = spec.MAX_EFFECTIVE_BALANCE // 4 deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True) @@ -157,7 +129,7 @@ def test_success_top_up__max_effective_balance(spec, state): @with_all_phases @spec_state_test -def test_success_top_up__less_effective_balance(spec, state): +def test_top_up__less_effective_balance(spec, state): validator_index = 0 amount = spec.MAX_EFFECTIVE_BALANCE // 4 deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True) @@ -176,7 +148,7 @@ def test_success_top_up__less_effective_balance(spec, state): @with_all_phases @spec_state_test -def test_success_top_up__zero_balance(spec, state): +def test_top_up__zero_balance(spec, state): validator_index = 0 amount = spec.MAX_EFFECTIVE_BALANCE // 4 deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True) @@ -196,18 +168,18 @@ def test_success_top_up__zero_balance(spec, state): @with_all_phases @spec_state_test @always_bls -def test_invalid_sig_top_up(spec, state): +def test_incorrect_sig_top_up(spec, state): validator_index = 0 amount = spec.MAX_EFFECTIVE_BALANCE // 4 deposit = prepare_state_and_deposit(spec, state, validator_index, amount) # invalid signatures, in top-ups, are allowed! - yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=True) + yield from run_deposit_processing(spec, state, deposit, validator_index) @with_all_phases @spec_state_test -def test_invalid_withdrawal_credentials_top_up(spec, state): +def test_incorrect_withdrawal_credentials_top_up(spec, state): validator_index = 0 amount = spec.MAX_EFFECTIVE_BALANCE // 4 withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(b"junk")[1:] @@ -220,12 +192,12 @@ def test_invalid_withdrawal_credentials_top_up(spec, state): ) # inconsistent withdrawal credentials, in top-ups, are allowed! - yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=True) + yield from run_deposit_processing(spec, state, deposit, validator_index) @with_all_phases @spec_state_test -def test_wrong_deposit_for_deposit_count(spec, state): +def test_invalid_wrong_deposit_for_deposit_count(spec, state): deposit_data_leaves = [spec.DepositData() for _ in range(len(state.validators))] # build root for deposit_1 @@ -266,7 +238,7 @@ def test_wrong_deposit_for_deposit_count(spec, state): @with_all_phases @spec_state_test -def test_bad_merkle_proof(spec, state): +def test_invalid_bad_merkle_proof(spec, state): validator_index = len(state.validators) amount = spec.MAX_EFFECTIVE_BALANCE deposit = prepare_state_and_deposit(spec, state, validator_index, amount) @@ -307,3 +279,15 @@ def test_key_validate_invalid_decompression(spec, state): deposit = prepare_state_and_deposit(spec, state, validator_index, amount, pubkey=pubkey, signed=True) yield from run_deposit_processing(spec, state, deposit, validator_index) + + +@with_all_phases +@spec_state_test +@always_bls +def test_ineffective_deposit_with_bad_fork_version(spec, state): + yield from run_deposit_processing_with_specific_fork_version( + spec, + state, + fork_version=spec.Version('0xAaBbCcDd'), + effective=False, + ) diff --git a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_proposer_slashing.py b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_proposer_slashing.py index 6ca87adae..42c94b6f5 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_proposer_slashing.py +++ b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_proposer_slashing.py @@ -34,7 +34,7 @@ def run_proposer_slashing_processing(spec, state, proposer_slashing, valid=True) @with_all_phases @spec_state_test -def test_success(spec, state): +def test_basic(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) yield from run_proposer_slashing_processing(spec, state, proposer_slashing) @@ -42,7 +42,7 @@ def test_success(spec, state): @with_all_phases @spec_state_test -def test_success_slashed_and_proposer_index_the_same(spec, state): +def test_slashed_and_proposer_index_the_same(spec, state): # Get proposer for next slot block = build_empty_block_for_next_slot(spec, state) proposer_index = block.proposer_index @@ -57,7 +57,7 @@ def test_success_slashed_and_proposer_index_the_same(spec, state): @with_all_phases @spec_state_test -def test_success_block_header_from_future(spec, state): +def test_block_header_from_future(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, slot=state.slot + 5, signed_1=True, signed_2=True) yield from run_proposer_slashing_processing(spec, state, proposer_slashing) @@ -66,31 +66,31 @@ def test_success_block_header_from_future(spec, state): @with_all_phases @spec_state_test @always_bls -def test_invalid_sig_1(spec, state): +def test_invalid_incorrect_sig_1(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=False, signed_2=True) - yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) + yield from run_proposer_slashing_processing(spec, state, proposer_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_invalid_sig_2(spec, state): +def test_invalid_incorrect_sig_2(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=False) - yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) + yield from run_proposer_slashing_processing(spec, state, proposer_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_invalid_sig_1_and_2(spec, state): +def test_invalid_incorrect_sig_1_and_2(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=False, signed_2=False) - yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) + yield from run_proposer_slashing_processing(spec, state, proposer_slashing, valid=False) @with_all_phases @spec_state_test @always_bls -def test_invalid_sig_1_and_2_swap(spec, state): +def test_invalid_incorrect_sig_1_and_2_swap(spec, state): # Get valid signatures for the slashings proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) @@ -98,18 +98,18 @@ def test_invalid_sig_1_and_2_swap(spec, state): signature_1 = proposer_slashing.signed_header_1.signature proposer_slashing.signed_header_1.signature = proposer_slashing.signed_header_2.signature proposer_slashing.signed_header_2.signature = signature_1 - yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) + yield from run_proposer_slashing_processing(spec, state, proposer_slashing, valid=False) @with_all_phases @spec_state_test -def test_invalid_proposer_index(spec, state): +def test_invalid_incorrect_proposer_index(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) # Index just too high (by 1) proposer_slashing.signed_header_1.message.proposer_index = len(state.validators) proposer_slashing.signed_header_2.message.proposer_index = len(state.validators) - yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) + yield from run_proposer_slashing_processing(spec, state, proposer_slashing, valid=False) @with_all_phases @@ -125,12 +125,12 @@ def test_invalid_different_proposer_indices(spec, state): header_2.proposer_index = active_indices[0] proposer_slashing.signed_header_2 = sign_block_header(spec, state, header_2, privkeys[header_2.proposer_index]) - yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) + yield from run_proposer_slashing_processing(spec, state, proposer_slashing, valid=False) @with_all_phases @spec_state_test -def test_epochs_are_different(spec, state): +def test_invalid_slots_of_different_epochs(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=False) # set slots to be in different epochs @@ -139,23 +139,23 @@ def test_epochs_are_different(spec, state): header_2.slot += spec.SLOTS_PER_EPOCH proposer_slashing.signed_header_2 = sign_block_header(spec, state, header_2, privkeys[proposer_index]) - yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) + yield from run_proposer_slashing_processing(spec, state, proposer_slashing, valid=False) @with_all_phases @spec_state_test -def test_headers_are_same_sigs_are_same(spec, state): +def test_invalid_headers_are_same_sigs_are_same(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=False) # set headers to be the same proposer_slashing.signed_header_2 = proposer_slashing.signed_header_1.copy() - yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) + yield from run_proposer_slashing_processing(spec, state, proposer_slashing, valid=False) @with_all_phases @spec_state_test -def test_headers_are_same_sigs_are_different(spec, state): +def test_invalid_headers_are_same_sigs_are_different(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=False) # set headers to be the same @@ -165,36 +165,36 @@ def test_headers_are_same_sigs_are_different(spec, state): assert proposer_slashing.signed_header_1.signature != proposer_slashing.signed_header_2.signature - yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) + yield from run_proposer_slashing_processing(spec, state, proposer_slashing, valid=False) @with_all_phases @spec_state_test -def test_proposer_is_not_activated(spec, state): +def test_invalid_proposer_is_not_activated(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) # set proposer to be not active yet proposer_index = proposer_slashing.signed_header_1.message.proposer_index state.validators[proposer_index].activation_epoch = spec.get_current_epoch(state) + 1 - yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) + yield from run_proposer_slashing_processing(spec, state, proposer_slashing, valid=False) @with_all_phases @spec_state_test -def test_proposer_is_slashed(spec, state): +def test_invalid_proposer_is_slashed(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) # set proposer to slashed proposer_index = proposer_slashing.signed_header_1.message.proposer_index state.validators[proposer_index].slashed = True - yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) + yield from run_proposer_slashing_processing(spec, state, proposer_slashing, valid=False) @with_all_phases @spec_state_test -def test_proposer_is_withdrawn(spec, state): +def test_invalid_proposer_is_withdrawn(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) # move 1 epoch into future, to allow for past withdrawable epoch @@ -204,4 +204,4 @@ def test_proposer_is_withdrawn(spec, state): proposer_index = proposer_slashing.signed_header_1.message.proposer_index state.validators[proposer_index].withdrawable_epoch = current_epoch - 1 - yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) + yield from run_proposer_slashing_processing(spec, state, proposer_slashing, valid=False) diff --git a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_voluntary_exit.py b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_voluntary_exit.py index 73602f14c..4a7286d52 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_voluntary_exit.py +++ b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_voluntary_exit.py @@ -14,7 +14,7 @@ from eth2spec.test.helpers.voluntary_exits import ( @with_all_phases @spec_state_test -def test_success(spec, state): +def test_basic(spec, state): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH @@ -33,7 +33,7 @@ def test_success(spec, state): @with_all_phases @spec_state_test @always_bls -def test_invalid_signature(spec, state): +def test_invalid_incorrect_signature(spec, state): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH @@ -46,7 +46,7 @@ def test_invalid_signature(spec, state): ) signed_voluntary_exit = sign_voluntary_exit(spec, state, voluntary_exit, 12345) - yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, False) + yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=False) def run_test_success_exit_queue(spec, state): @@ -134,7 +134,7 @@ def test_default_exit_epoch_subsequent_exit(spec, state): @with_all_phases @spec_state_test -def test_validator_exit_in_future(spec, state): +def test_invalid_validator_exit_in_future(spec, state): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH @@ -148,12 +148,12 @@ def test_validator_exit_in_future(spec, state): ) signed_voluntary_exit = sign_voluntary_exit(spec, state, voluntary_exit, privkey) - yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, False) + yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=False) @with_all_phases @spec_state_test -def test_validator_invalid_validator_index(spec, state): +def test_invalid_validator_incorrect_validator_index(spec, state): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH @@ -167,12 +167,12 @@ def test_validator_invalid_validator_index(spec, state): ) signed_voluntary_exit = sign_voluntary_exit(spec, state, voluntary_exit, privkey) - yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, False) + yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=False) @with_all_phases @spec_state_test -def test_validator_not_active(spec, state): +def test_invalid_validator_not_active(spec, state): 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] @@ -182,12 +182,12 @@ def test_validator_not_active(spec, state): signed_voluntary_exit = sign_voluntary_exit( spec, state, spec.VoluntaryExit(epoch=current_epoch, validator_index=validator_index), privkey) - yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, False) + yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=False) @with_all_phases @spec_state_test -def test_validator_already_exited(spec, state): +def test_invalid_validator_already_exited(spec, state): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow validator able to exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH @@ -201,12 +201,12 @@ def test_validator_already_exited(spec, state): signed_voluntary_exit = sign_voluntary_exit( spec, state, spec.VoluntaryExit(epoch=current_epoch, validator_index=validator_index), privkey) - yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, False) + yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=False) @with_all_phases @spec_state_test -def test_validator_not_active_long_enough(spec, state): +def test_invalid_validator_not_active_long_enough(spec, state): 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] @@ -219,4 +219,4 @@ def test_validator_not_active_long_enough(spec, state): spec.config.SHARD_COMMITTEE_PERIOD ) - yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, False) + yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=False) diff --git a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py index aecc96077..d245b8fcf 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py +++ b/tests/core/pyspec/eth2spec/test/phase0/genesis/test_validity.py @@ -47,20 +47,20 @@ def run_is_valid_genesis_state(spec, state, valid=True): @spec_test @single_phase @with_presets([MINIMAL], reason="too slow") -def test_is_valid_genesis_state_true(spec): +def test_full_genesis_deposits(spec): if is_post_altair(spec): yield 'description', 'meta', get_post_altair_description(spec) state = create_valid_beacon_state(spec) - yield from run_is_valid_genesis_state(spec, state, valid=True) + yield from run_is_valid_genesis_state(spec, state) @with_all_phases @spec_test @single_phase @with_presets([MINIMAL], reason="too slow") -def test_is_valid_genesis_state_false_invalid_timestamp(spec): +def test_invalid_invalid_timestamp(spec): if is_post_altair(spec): yield 'description', 'meta', get_post_altair_description(spec) @@ -74,21 +74,21 @@ def test_is_valid_genesis_state_false_invalid_timestamp(spec): @spec_test @single_phase @with_presets([MINIMAL], reason="too slow") -def test_is_valid_genesis_state_true_more_balance(spec): +def test_extra_balance(spec): if is_post_altair(spec): yield 'description', 'meta', get_post_altair_description(spec) state = create_valid_beacon_state(spec) state.validators[0].effective_balance = spec.MAX_EFFECTIVE_BALANCE + 1 - yield from run_is_valid_genesis_state(spec, state, valid=True) + yield from run_is_valid_genesis_state(spec, state) @with_all_phases @spec_test @single_phase @with_presets([MINIMAL], reason="too slow") -def test_is_valid_genesis_state_true_one_more_validator(spec): +def test_one_more_validator(spec): if is_post_altair(spec): yield 'description', 'meta', get_post_altair_description(spec) @@ -104,14 +104,14 @@ def test_is_valid_genesis_state_true_one_more_validator(spec): eth1_timestamp = spec.config.MIN_GENESIS_TIME state = spec.initialize_beacon_state_from_eth1(eth1_block_hash, eth1_timestamp, deposits) - yield from run_is_valid_genesis_state(spec, state, valid=True) + yield from run_is_valid_genesis_state(spec, state) @with_all_phases @spec_test @single_phase @with_presets([MINIMAL], reason="too slow") -def test_is_valid_genesis_state_false_not_enough_validator(spec): +def test_invalid_not_enough_validator_count(spec): if is_post_altair(spec): yield 'description', 'meta', get_post_altair_description(spec) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py index 0e19e65b7..1e9dd2d48 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py @@ -43,7 +43,7 @@ from eth2spec.test.context import ( @with_all_phases @spec_state_test -def test_prev_slot_block_transition(spec, state): +def test_invalid_prev_slot_block_transition(spec, state): # Go to clean slot spec.process_slots(state, state.slot + 1) # Make a block for it @@ -64,7 +64,7 @@ def test_prev_slot_block_transition(spec, state): @with_all_phases @spec_state_test -def test_same_slot_block_transition(spec, state): +def test_invalid_same_slot_block_transition(spec, state): # Same slot on top of pre-state, but move out of slot 0 first. spec.process_slots(state, state.slot + 1) @@ -161,7 +161,7 @@ def process_and_sign_block_without_header_validations(spec, state, block): @with_phases([PHASE0]) @spec_state_test -def test_proposal_for_genesis_slot(spec, state): +def test_invalid_proposal_for_genesis_slot(spec, state): assert state.slot == spec.GENESIS_SLOT yield 'pre', state @@ -184,7 +184,7 @@ def test_proposal_for_genesis_slot(spec, state): @with_all_phases @spec_state_test -def test_parent_from_same_slot(spec, state): +def test_invalid_parent_from_same_slot(spec, state): yield 'pre', state parent_block = build_empty_block_for_next_slot(spec, state) @@ -211,7 +211,7 @@ def test_parent_from_same_slot(spec, state): @with_all_phases @spec_state_test -def test_invalid_state_root(spec, state): +def test_invalid_incorrect_state_root(spec, state): yield 'pre', state block = build_empty_block_for_next_slot(spec, state) @@ -227,7 +227,7 @@ def test_invalid_state_root(spec, state): @with_all_phases @spec_state_test @always_bls -def test_zero_block_sig(spec, state): +def test_invalid_all_zeroed_sig(spec, state): yield 'pre', state block = build_empty_block_for_next_slot(spec, state) @@ -241,7 +241,7 @@ def test_zero_block_sig(spec, state): @with_all_phases @spec_state_test @always_bls -def test_invalid_block_sig(spec, state): +def test_invalid_incorrect_block_sig(spec, state): yield 'pre', state block = build_empty_block_for_next_slot(spec, state) @@ -260,7 +260,7 @@ def test_invalid_block_sig(spec, state): @with_all_phases @spec_state_test @always_bls -def test_invalid_proposer_index_sig_from_expected_proposer(spec, state): +def test_invalid_incorrect_proposer_index_sig_from_expected_proposer(spec, state): yield 'pre', state block = build_empty_block_for_next_slot(spec, state) @@ -282,7 +282,7 @@ def test_invalid_proposer_index_sig_from_expected_proposer(spec, state): @with_all_phases @spec_state_test @always_bls -def test_invalid_proposer_index_sig_from_proposer_index(spec, state): +def test_invalid_incorrect_proposer_index_sig_from_proposer_index(spec, state): yield 'pre', state block = build_empty_block_for_next_slot(spec, state) @@ -707,7 +707,7 @@ def test_high_proposer_index(spec, state): @with_all_phases @spec_state_test -def test_expected_deposit_in_block(spec, state): +def test_invalid_only_increase_deposit_count(spec, state): # Make the state expect a deposit, then don't provide it. state.eth1_data.deposit_count += 1 yield 'pre', state diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_slots.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_slots.py index 198ada6b9..3fa57f0f1 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_slots.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_slots.py @@ -1,5 +1,8 @@ from eth2spec.test.helpers.state import get_state_root -from eth2spec.test.context import spec_state_test, with_all_phases +from eth2spec.test.context import ( + spec_state_test, + with_all_phases, +) @with_all_phases diff --git a/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py index 37fbdc417..4d2ec124d 100644 --- a/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py +++ b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py @@ -7,6 +7,9 @@ import warnings from random import Random from typing import Callable +from eth2spec.test.helpers.execution_payload import ( + compute_el_block_hash, +) from eth2spec.test.helpers.multi_operations import ( build_random_block_from_state_for_next_slot, get_random_bls_to_execution_changes, @@ -234,6 +237,7 @@ def random_block_eip4844(spec, state, signed_blocks, scenario_state, rng=Random( # TODO: more commitments. blob_kzg_commitments: List[KZGCommitment, MAX_BLOBS_PER_BLOCK] opaque_tx, _, blob_kzg_commitments = get_sample_opaque_tx(spec, blob_count=1) block.body.execution_payload.transactions = [opaque_tx] + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) block.body.blob_kzg_commitments = blob_kzg_commitments return block diff --git a/tests/generators/operations/main.py b/tests/generators/operations/main.py index bb879a647..4c073ebe4 100644 --- a/tests/generators/operations/main.py +++ b/tests/generators/operations/main.py @@ -11,10 +11,15 @@ if __name__ == "__main__": 'proposer_slashing', 'voluntary_exit', ]} - _new_altair_mods = {'sync_aggregate': [ - 'eth2spec.test.altair.block_processing.sync_aggregate.test_process_' + key - for key in ['sync_aggregate', 'sync_aggregate_random'] - ]} + _new_altair_mods = { + **{'sync_aggregate': [ + 'eth2spec.test.altair.block_processing.sync_aggregate.test_process_' + key + for key in ['sync_aggregate', 'sync_aggregate_random'] + ]}, + **{key: 'eth2spec.test.altair.block_processing.test_process_' + key for key in [ + 'deposit', + ]} + } altair_mods = combine_mods(_new_altair_mods, phase_0_mods) _new_bellatrix_mods = {key: 'eth2spec.test.bellatrix.block_processing.test_process_' + key for key in [