From ff0e525ecc7579db692267e8c47ed8fdf855d4a0 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Fri, 28 Oct 2022 22:14:25 +0200 Subject: [PATCH 01/11] Pass blocks to LC data creation functions Future light client protocol extensions may include data from the block in addition to data from the state, e.g., `ExecutionPayloadHeader`. To prepare for this, also pass the block to the corresponding functions. In practice, blocks access is easier than historic state access, meaning there are no practical limitations due to this change. --- specs/altair/light-client/full-node.md | 21 +++- specs/altair/light-client/p2p-interface.md | 2 +- .../test/altair/light_client/test_sync.py | 64 ++++++---- .../light_client/test_update_ranking.py | 116 +++++++++--------- 4 files changed, 113 insertions(+), 90 deletions(-) diff --git a/specs/altair/light-client/full-node.md b/specs/altair/light-client/full-node.md index e3f4d7a3e..53ba4dc82 100644 --- a/specs/altair/light-client/full-node.md +++ b/specs/altair/light-client/full-node.md @@ -40,10 +40,19 @@ Full nodes are expected to derive light client data from historic blocks and sta ### `create_light_client_bootstrap` +To form a `LightClientBootstrap`, the following objects are needed: +- `state`: the post state of any post-Altair block +- `block`: the corresponding block + ```python -def create_light_client_bootstrap(state: BeaconState) -> LightClientBootstrap: +def create_light_client_bootstrap(state: BeaconState, + block: SignedBeaconBlock) -> LightClientBootstrap: assert compute_epoch_at_slot(state.slot) >= ALTAIR_FORK_EPOCH + assert state.slot == state.latest_block_header.slot + header = state.latest_block_header.copy() + header.state_root = hash_tree_root(state) + assert hash_tree_root(header) == hash_tree_root(block.message) return LightClientBootstrap( header=BeaconBlockHeader( @@ -54,7 +63,7 @@ def create_light_client_bootstrap(state: BeaconState) -> LightClientBootstrap: body_root=state.latest_block_header.body_root, ), current_sync_committee=state.current_sync_committee, - current_sync_committee_branch=compute_merkle_proof_for_state(state, CURRENT_SYNC_COMMITTEE_INDEX) + current_sync_committee_branch=compute_merkle_proof_for_state(state, CURRENT_SYNC_COMMITTEE_INDEX), ) ``` @@ -69,13 +78,15 @@ Blocks are considered to be epoch boundary blocks if their block root can occur To form a `LightClientUpdate`, the following historical states and blocks are needed: - `state`: the post state of any block with a post-Altair parent block - `block`: the corresponding block -- `attested_state`: the post state of the block referred to by `block.parent_root` +- `attested_state`: the post state of `attested_block` +- `attested_block`: the block referred to by `block.parent_root` - `finalized_block`: the block referred to by `attested_state.finalized_checkpoint.root`, if locally available (may be unavailable, e.g., when using checkpoint sync, or if it was pruned locally) ```python def create_light_client_update(state: BeaconState, block: SignedBeaconBlock, attested_state: BeaconState, + attested_block: SignedBeaconBlock, finalized_block: Optional[SignedBeaconBlock]) -> LightClientUpdate: assert compute_epoch_at_slot(attested_state.slot) >= ALTAIR_FORK_EPOCH assert sum(block.message.body.sync_aggregate.sync_committee_bits) >= MIN_SYNC_COMMITTEE_PARTICIPANTS @@ -89,8 +100,8 @@ def create_light_client_update(state: BeaconState, assert attested_state.slot == attested_state.latest_block_header.slot attested_header = attested_state.latest_block_header.copy() attested_header.state_root = hash_tree_root(attested_state) - assert hash_tree_root(attested_header) == block.message.parent_root - update_attested_period = compute_sync_committee_period_at_slot(attested_header.slot) + assert hash_tree_root(attested_header) == hash_tree_root(attested_block.message) == block.message.parent_root + update_attested_period = compute_sync_committee_period_at_slot(attested_block.message.slot) # `next_sync_committee` is only useful if the message is signed by the current sync committee if update_attested_period == update_signature_period: diff --git a/specs/altair/light-client/p2p-interface.md b/specs/altair/light-client/p2p-interface.md index 5c2b27b22..51b4759ba 100644 --- a/specs/altair/light-client/p2p-interface.md +++ b/specs/altair/light-client/p2p-interface.md @@ -116,7 +116,7 @@ Requests the `LightClientBootstrap` structure corresponding to a given post-Alta The request MUST be encoded as an SSZ-field. -Peers SHOULD provide results as defined in [`create_light_client_bootstrap`](./full-node.md#create_light_client_bootstrap). To fulfill a request, the requested block's post state needs to be known. +Peers SHOULD provide results as defined in [`create_light_client_bootstrap`](./full-node.md#create_light_client_bootstrap). To fulfill a request, the requested block and its post state need to be known. When a `LightClientBootstrap` instance cannot be produced for a given block root, peers SHOULD respond with error code `3: ResourceUnavailable`. diff --git a/tests/core/pyspec/eth2spec/test/altair/light_client/test_sync.py b/tests/core/pyspec/eth2spec/test/altair/light_client/test_sync.py index 4621a2772..1364c4bf1 100644 --- a/tests/core/pyspec/eth2spec/test/altair/light_client/test_sync.py +++ b/tests/core/pyspec/eth2spec/test/altair/light_client/test_sync.py @@ -35,7 +35,7 @@ def setup_test(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2 - 1) trusted_block = state_transition_with_full_block(spec, state, True, True) trusted_block_root = trusted_block.message.hash_tree_root() - bootstrap = spec.create_light_client_bootstrap(state) + bootstrap = spec.create_light_client_bootstrap(state, trusted_block) yield "trusted_block_root", "meta", "0x" + trusted_block_root.hex() yield "bootstrap", bootstrap test.store = spec.initialize_light_client_store(trusted_block_root, bootstrap) @@ -85,9 +85,9 @@ def emit_force_update(test, spec, state): }) -def emit_update(test, spec, state, block, attested_state, finalized_block, with_next_sync_committee=True): - update = spec.create_light_client_update(state, block, attested_state, finalized_block) - if not with_next_sync_committee: +def emit_update(test, spec, state, block, attested_state, attested_block, finalized_block, with_next=True): + update = spec.create_light_client_update(state, block, attested_state, attested_block, finalized_block) + if not with_next: update.next_sync_committee = spec.SyncCommittee() update.next_sync_committee_branch = \ [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))] @@ -135,11 +135,12 @@ def test_light_client_sync(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH - 1) finalized_block = state_transition_with_full_block(spec, state, True, True) finalized_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - yield from emit_update(test, spec, state, block, attested_state, finalized_block) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None @@ -160,11 +161,12 @@ def test_light_client_sync(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH - 1) finalized_block = state_transition_with_full_block(spec, state, True, True) finalized_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - yield from emit_update(test, spec, state, block, attested_state, finalized_block) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None @@ -184,12 +186,13 @@ def test_light_client_sync(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH - 2) finalized_block = state_transition_with_full_block(spec, state, True, True) finalized_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() transition_to(spec, state, compute_start_slot_at_next_sync_committee_period(spec, state)) sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - yield from emit_update(test, spec, state, block, attested_state, finalized_block) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None @@ -206,10 +209,11 @@ def test_light_client_sync(spec, state): # sync committee # period boundary # ``` + attested_block = block.copy() attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - update = yield from emit_update(test, spec, state, block, attested_state, finalized_block=None) + update = yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block=None) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update == update @@ -226,11 +230,12 @@ def test_light_client_sync(spec, state): # sync committee # period boundary # ``` + attested_block = block.copy() attested_state = state.copy() store_state = attested_state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - update = yield from emit_update(test, spec, state, block, attested_state, finalized_block) + update = yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update == update @@ -247,6 +252,7 @@ def test_light_client_sync(spec, state): # sync committee `--- store.finalized_header # period boundary # ``` + attested_block = block.copy() attested_state = state.copy() next_slots(spec, state, spec.UPDATE_TIMEOUT - 1) yield from emit_force_update(test, spec, state) @@ -268,7 +274,7 @@ def test_light_client_sync(spec, state): # ``` sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - update = yield from emit_update(test, spec, state, block, attested_state, finalized_block=None) + update = yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block=None) assert test.store.finalized_header.slot == store_state.slot assert test.store.next_sync_committee == store_state.next_sync_committee assert test.store.best_valid_update == update @@ -285,10 +291,11 @@ def test_light_client_sync(spec, state): # sync committee sync committee # period boundary period boundary # ``` + attested_block = block.copy() attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - update = yield from emit_update(test, spec, state, block, attested_state, finalized_block) + update = yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == store_state.slot assert test.store.next_sync_committee == store_state.next_sync_committee assert test.store.best_valid_update == update @@ -314,11 +321,12 @@ def test_light_client_sync(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH - 1) finalized_block = state_transition_with_full_block(spec, state, True, True) finalized_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - yield from emit_update(test, spec, state, block, attested_state, finalized_block) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None @@ -336,7 +344,8 @@ def test_supply_sync_committee_from_past_update(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2 - 1) finalized_block = state_transition_with_full_block(spec, state, True, True) finalized_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) @@ -347,7 +356,7 @@ def test_supply_sync_committee_from_past_update(spec, state): assert not spec.is_next_sync_committee_known(test.store) # Apply `LightClientUpdate` from the past, populating `store.next_sync_committee` - yield from emit_update(test, spec, past_state, block, attested_state, finalized_block) + yield from emit_update(test, spec, past_state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None @@ -368,11 +377,12 @@ def test_advance_finality_without_sync_committee(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH - 1) finalized_block = state_transition_with_full_block(spec, state, True, True) finalized_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - yield from emit_update(test, spec, state, block, attested_state, finalized_block) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None @@ -386,11 +396,12 @@ def test_advance_finality_without_sync_committee(spec, state): _, _, state = next_slots_with_attestations(spec, state, spec.SLOTS_PER_EPOCH - 1, True, True) justified_block = state_transition_with_full_block(spec, state, True, True) justified_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - yield from emit_update(test, spec, state, block, attested_state, finalized_block, with_next_sync_committee=False) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block, with_next=False) assert test.store.finalized_header.slot == finalized_state.slot assert not spec.is_next_sync_committee_known(test.store) assert test.store.best_valid_update is None @@ -400,27 +411,28 @@ def test_advance_finality_without_sync_committee(spec, state): past_state = finalized_state finalized_block = justified_block finalized_state = justified_state - _, _, state = next_slots_with_attestations(spec, state, spec.SLOTS_PER_EPOCH - 1, True, True) + _, _, state = next_slots_with_attestations(spec, state, spec.SLOTS_PER_EPOCH - 2, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) # Apply `LightClientUpdate` without `finalized_header` nor `next_sync_committee` - update = yield from emit_update(test, spec, state, block, attested_state, None, with_next_sync_committee=False) + update = yield from emit_update(test, spec, state, block, attested_state, attested_block, None, with_next=False) assert test.store.finalized_header.slot == past_state.slot assert not spec.is_next_sync_committee_known(test.store) assert test.store.best_valid_update == update assert test.store.optimistic_header.slot == attested_state.slot # Apply `LightClientUpdate` with `finalized_header` but no `next_sync_committee` - yield from emit_update(test, spec, state, block, attested_state, finalized_block, with_next_sync_committee=False) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block, with_next=False) assert test.store.finalized_header.slot == finalized_state.slot assert not spec.is_next_sync_committee_known(test.store) assert test.store.best_valid_update is None assert test.store.optimistic_header.slot == attested_state.slot # Apply full `LightClientUpdate`, supplying `next_sync_committee` - yield from emit_update(test, spec, state, block, attested_state, finalized_block) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None diff --git a/tests/core/pyspec/eth2spec/test/altair/light_client/test_update_ranking.py b/tests/core/pyspec/eth2spec/test/altair/light_client/test_update_ranking.py index ae5d5296a..23ad79584 100644 --- a/tests/core/pyspec/eth2spec/test/altair/light_client/test_update_ranking.py +++ b/tests/core/pyspec/eth2spec/test/altair/light_client/test_update_ranking.py @@ -18,13 +18,13 @@ from eth2spec.test.helpers.state import ( from math import floor -def create_update(spec, test, with_next_sync_committee, with_finality, participation_rate): +def create_update(spec, test, with_next, with_finality, participation_rate): attested_state, attested_block, finalized_block = test num_participants = floor(spec.SYNC_COMMITTEE_SIZE * participation_rate) attested_header = signed_block_to_header(spec, attested_block) - if with_next_sync_committee: + if with_next: next_sync_committee = attested_state.next_sync_committee next_sync_committee_branch = spec.compute_merkle_proof_for_state(attested_state, spec.NEXT_SYNC_COMMITTEE_INDEX) else: @@ -84,76 +84,76 @@ def test_update_ranking(spec, state): # Create updates (in descending order of quality) updates = [ # Updates with sync committee finality - create_update(spec, fin, with_next_sync_committee=1, with_finality=1, participation_rate=1.0), - create_update(spec, lat, with_next_sync_committee=1, with_finality=1, participation_rate=1.0), - create_update(spec, fin, with_next_sync_committee=1, with_finality=1, participation_rate=0.8), - create_update(spec, lat, with_next_sync_committee=1, with_finality=1, participation_rate=0.8), + create_update(spec, fin, with_next=1, with_finality=1, participation_rate=1.0), + create_update(spec, lat, with_next=1, with_finality=1, participation_rate=1.0), + create_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.8), + create_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.8), # Updates without sync committee finality - create_update(spec, att, with_next_sync_committee=1, with_finality=1, participation_rate=1.0), - create_update(spec, att, with_next_sync_committee=1, with_finality=1, participation_rate=0.8), + create_update(spec, att, with_next=1, with_finality=1, participation_rate=1.0), + create_update(spec, att, with_next=1, with_finality=1, participation_rate=0.8), # Updates without indication of any finality - create_update(spec, att, with_next_sync_committee=1, with_finality=0, participation_rate=1.0), - create_update(spec, fin, with_next_sync_committee=1, with_finality=0, participation_rate=1.0), - create_update(spec, lat, with_next_sync_committee=1, with_finality=0, participation_rate=1.0), - create_update(spec, att, with_next_sync_committee=1, with_finality=0, participation_rate=0.8), - create_update(spec, fin, with_next_sync_committee=1, with_finality=0, participation_rate=0.8), - create_update(spec, lat, with_next_sync_committee=1, with_finality=0, participation_rate=0.8), + create_update(spec, att, with_next=1, with_finality=0, participation_rate=1.0), + create_update(spec, fin, with_next=1, with_finality=0, participation_rate=1.0), + create_update(spec, lat, with_next=1, with_finality=0, participation_rate=1.0), + create_update(spec, att, with_next=1, with_finality=0, participation_rate=0.8), + create_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.8), + create_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.8), # Updates with sync committee finality but no `next_sync_committee` - create_update(spec, sig, with_next_sync_committee=0, with_finality=1, participation_rate=1.0), - create_update(spec, fin, with_next_sync_committee=0, with_finality=1, participation_rate=1.0), - create_update(spec, lat, with_next_sync_committee=0, with_finality=1, participation_rate=1.0), - create_update(spec, sig, with_next_sync_committee=0, with_finality=1, participation_rate=0.8), - create_update(spec, fin, with_next_sync_committee=0, with_finality=1, participation_rate=0.8), - create_update(spec, lat, with_next_sync_committee=0, with_finality=1, participation_rate=0.8), + create_update(spec, sig, with_next=0, with_finality=1, participation_rate=1.0), + create_update(spec, fin, with_next=0, with_finality=1, participation_rate=1.0), + create_update(spec, lat, with_next=0, with_finality=1, participation_rate=1.0), + create_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.8), + create_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.8), + create_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.8), # Updates without sync committee finality and also no `next_sync_committee` - create_update(spec, att, with_next_sync_committee=0, with_finality=1, participation_rate=1.0), - create_update(spec, att, with_next_sync_committee=0, with_finality=1, participation_rate=0.8), + create_update(spec, att, with_next=0, with_finality=1, participation_rate=1.0), + create_update(spec, att, with_next=0, with_finality=1, participation_rate=0.8), # Updates without indication of any finality nor `next_sync_committee` - create_update(spec, sig, with_next_sync_committee=0, with_finality=0, participation_rate=1.0), - create_update(spec, att, with_next_sync_committee=0, with_finality=0, participation_rate=1.0), - create_update(spec, fin, with_next_sync_committee=0, with_finality=0, participation_rate=1.0), - create_update(spec, lat, with_next_sync_committee=0, with_finality=0, participation_rate=1.0), - create_update(spec, sig, with_next_sync_committee=0, with_finality=0, participation_rate=0.8), - create_update(spec, att, with_next_sync_committee=0, with_finality=0, participation_rate=0.8), - create_update(spec, fin, with_next_sync_committee=0, with_finality=0, participation_rate=0.8), - create_update(spec, lat, with_next_sync_committee=0, with_finality=0, participation_rate=0.8), + create_update(spec, sig, with_next=0, with_finality=0, participation_rate=1.0), + create_update(spec, att, with_next=0, with_finality=0, participation_rate=1.0), + create_update(spec, fin, with_next=0, with_finality=0, participation_rate=1.0), + create_update(spec, lat, with_next=0, with_finality=0, participation_rate=1.0), + create_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.8), + create_update(spec, att, with_next=0, with_finality=0, participation_rate=0.8), + create_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.8), + create_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.8), # Updates with low sync committee participation - create_update(spec, fin, with_next_sync_committee=1, with_finality=1, participation_rate=0.4), - create_update(spec, lat, with_next_sync_committee=1, with_finality=1, participation_rate=0.4), - create_update(spec, att, with_next_sync_committee=1, with_finality=1, participation_rate=0.4), - create_update(spec, att, with_next_sync_committee=1, with_finality=0, participation_rate=0.4), - create_update(spec, fin, with_next_sync_committee=1, with_finality=0, participation_rate=0.4), - create_update(spec, lat, with_next_sync_committee=1, with_finality=0, participation_rate=0.4), - create_update(spec, sig, with_next_sync_committee=0, with_finality=1, participation_rate=0.4), - create_update(spec, fin, with_next_sync_committee=0, with_finality=1, participation_rate=0.4), - create_update(spec, lat, with_next_sync_committee=0, with_finality=1, participation_rate=0.4), - create_update(spec, att, with_next_sync_committee=0, with_finality=1, participation_rate=0.4), - create_update(spec, sig, with_next_sync_committee=0, with_finality=0, participation_rate=0.4), - create_update(spec, att, with_next_sync_committee=0, with_finality=0, participation_rate=0.4), - create_update(spec, fin, with_next_sync_committee=0, with_finality=0, participation_rate=0.4), - create_update(spec, lat, with_next_sync_committee=0, with_finality=0, participation_rate=0.4), + create_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.4), + create_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.4), + create_update(spec, att, with_next=1, with_finality=1, participation_rate=0.4), + create_update(spec, att, with_next=1, with_finality=0, participation_rate=0.4), + create_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.4), + create_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.4), + create_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.4), + create_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.4), + create_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.4), + create_update(spec, att, with_next=0, with_finality=1, participation_rate=0.4), + create_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.4), + create_update(spec, att, with_next=0, with_finality=0, participation_rate=0.4), + create_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.4), + create_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.4), # Updates with very low sync committee participation - create_update(spec, fin, with_next_sync_committee=1, with_finality=1, participation_rate=0.2), - create_update(spec, lat, with_next_sync_committee=1, with_finality=1, participation_rate=0.2), - create_update(spec, att, with_next_sync_committee=1, with_finality=1, participation_rate=0.2), - create_update(spec, att, with_next_sync_committee=1, with_finality=0, participation_rate=0.2), - create_update(spec, fin, with_next_sync_committee=1, with_finality=0, participation_rate=0.2), - create_update(spec, lat, with_next_sync_committee=1, with_finality=0, participation_rate=0.2), - create_update(spec, sig, with_next_sync_committee=0, with_finality=1, participation_rate=0.2), - create_update(spec, fin, with_next_sync_committee=0, with_finality=1, participation_rate=0.2), - create_update(spec, lat, with_next_sync_committee=0, with_finality=1, participation_rate=0.2), - create_update(spec, att, with_next_sync_committee=0, with_finality=1, participation_rate=0.2), - create_update(spec, sig, with_next_sync_committee=0, with_finality=0, participation_rate=0.2), - create_update(spec, att, with_next_sync_committee=0, with_finality=0, participation_rate=0.2), - create_update(spec, fin, with_next_sync_committee=0, with_finality=0, participation_rate=0.2), - create_update(spec, lat, with_next_sync_committee=0, with_finality=0, participation_rate=0.2), + create_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.2), + create_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.2), + create_update(spec, att, with_next=1, with_finality=1, participation_rate=0.2), + create_update(spec, att, with_next=1, with_finality=0, participation_rate=0.2), + create_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.2), + create_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.2), + create_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.2), + create_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.2), + create_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.2), + create_update(spec, att, with_next=0, with_finality=1, participation_rate=0.2), + create_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.2), + create_update(spec, att, with_next=0, with_finality=0, participation_rate=0.2), + create_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.2), + create_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.2), ] yield "updates", updates From 3624742ff5d068019b2f0e2cfa7b014a2bd969fe Mon Sep 17 00:00:00 2001 From: terence tsao Date: Tue, 22 Nov 2022 09:07:48 -0800 Subject: [PATCH 02/11] Remove is_data_available --- specs/eip4844/beacon-chain.md | 25 ------------------ specs/eip4844/p2p-interface.md | 47 ++++++++++++---------------------- 2 files changed, 17 insertions(+), 55 deletions(-) diff --git a/specs/eip4844/beacon-chain.md b/specs/eip4844/beacon-chain.md index 600793a3f..94aa665a6 100644 --- a/specs/eip4844/beacon-chain.md +++ b/specs/eip4844/beacon-chain.md @@ -23,7 +23,6 @@ - [Helper functions](#helper-functions) - [Misc](#misc) - [`validate_blobs_sidecar`](#validate_blobs_sidecar) - - [`is_data_available`](#is_data_available) - [`kzg_commitment_to_versioned_hash`](#kzg_commitment_to_versioned_hash) - [`tx_peek_blob_versioned_hashes`](#tx_peek_blob_versioned_hashes) - [`verify_kzg_commitments_against_transactions`](#verify_kzg_commitments_against_transactions) @@ -162,27 +161,6 @@ def validate_blobs_sidecar(slot: Slot, assert verify_aggregate_kzg_proof(blobs, expected_kzg_commitments, kzg_aggregated_proof) ``` -#### `is_data_available` - -The implementation of `is_data_available` is meant to change with later sharding upgrades. -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. - -```python -def is_data_available(slot: Slot, beacon_block_root: Root, blob_kzg_commitments: Sequence[KZGCommitment]) -> bool: - # `retrieve_blobs_sidecar` is implementation dependent, raises an exception if not available. - sidecar = retrieve_blobs_sidecar(slot, beacon_block_root) - if sidecar == "TEST": - return True # For testing; remove once we have a way to inject `BlobsSidecar` into tests - validate_blobs_sidecar(slot, beacon_block_root, blob_kzg_commitments, sidecar) - - return True -``` - - #### `kzg_commitment_to_versioned_hash` ```python @@ -238,9 +216,6 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None: process_operations(state, block.body) 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` - assert is_data_available(block.slot, hash_tree_root(block), block.body.blob_kzg_commitments) ``` #### Execution payload diff --git a/specs/eip4844/p2p-interface.md b/specs/eip4844/p2p-interface.md index f031b3723..bbd18e34c 100644 --- a/specs/eip4844/p2p-interface.md +++ b/specs/eip4844/p2p-interface.md @@ -10,24 +10,22 @@ The specification of these changes continues in the same format as the network s - - [Configuration](#configuration) - - [Containers](#containers) - - [`BlobsSidecar`](#blobssidecar) - - [`SignedBeaconBlockAndBlobsSidecar`](#signedbeaconblockandblobssidecar) - - [The gossip domain: gossipsub](#the-gossip-domain-gossipsub) - - [Topics and messages](#topics-and-messages) - - [Global topics](#global-topics) - - [`beacon_block`](#beacon_block) - - [`beacon_block_and_blobs_sidecar`](#beacon_block_and_blobs_sidecar) - - [Transitioning the gossip](#transitioning-the-gossip) - - [The Req/Resp domain](#the-reqresp-domain) - - [Messages](#messages) - - [BeaconBlocksByRange v2](#beaconblocksbyrange-v2) - - [BeaconBlocksByRoot v2](#beaconblocksbyroot-v2) - - [BeaconBlockAndBlobsSidecarByRoot v1](#beaconblockandblobssidecarbyroot-v1) - - [BlobsSidecarsByRange v1](#blobssidecarsbyrange-v1) -- [Design decision rationale](#design-decision-rationale) - - [Why are blobs relayed as a sidecar, separate from beacon blocks?](#why-are-blobs-relayed-as-a-sidecar-separate-from-beacon-blocks) +- [Configuration](#configuration) +- [Containers](#containers) + - [`BlobsSidecar`](#blobssidecar) + - [`SignedBeaconBlockAndBlobsSidecar`](#signedbeaconblockandblobssidecar) +- [The gossip domain: gossipsub](#the-gossip-domain-gossipsub) + - [Topics and messages](#topics-and-messages) + - [Global topics](#global-topics) + - [`beacon_block`](#beacon_block) + - [`beacon_block_and_blobs_sidecar`](#beacon_block_and_blobs_sidecar) + - [Transitioning the gossip](#transitioning-the-gossip) +- [The Req/Resp domain](#the-reqresp-domain) + - [Messages](#messages) + - [BeaconBlocksByRange v2](#beaconblocksbyrange-v2) + - [BeaconBlocksByRoot v2](#beaconblocksbyroot-v2) + - [BeaconBlockAndBlobsSidecarByRoot v1](#beaconblockandblobssidecarbyroot-v1) + - [BlobsSidecarsByRange v1](#blobssidecarsbyrange-v1) @@ -259,15 +257,4 @@ Of note, blocks from slots before the finalization MUST lead to the finalized bl Clients MUST respond with blobs sidecars that are consistent from a single chain within the context of the request. After the initial blobs sidecar, clients MAY stop in the process of responding -if their fork choice changes the view of the chain in the context of the request. - -# Design decision rationale - -## Why are blobs relayed as a sidecar, separate from beacon blocks? - -This "sidecar" design provides forward compatibility for further data increases by black-boxing `is_data_available()`: -with full sharding `is_data_available()` can be replaced by data-availability-sampling (DAS) -thus avoiding all blobs being downloaded by all beacon nodes on the network. - -Such sharding design may introduce an updated `BlobsSidecar` to identify the shard, -but does not affect the `BeaconBlock` structure. +if their fork choice changes the view of the chain in the context of the request. \ No newline at end of file From 339b78883911a90ef92ff48114685a496f508591 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Mon, 28 Nov 2022 19:46:02 -0800 Subject: [PATCH 03/11] Revert previous changes. Remove optimistic wording --- specs/eip4844/beacon-chain.md | 24 +++++++++++++++++ specs/eip4844/p2p-interface.md | 47 ++++++++++++++++++++++------------ 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/specs/eip4844/beacon-chain.md b/specs/eip4844/beacon-chain.md index 94aa665a6..37c6e71e5 100644 --- a/specs/eip4844/beacon-chain.md +++ b/specs/eip4844/beacon-chain.md @@ -23,6 +23,7 @@ - [Helper functions](#helper-functions) - [Misc](#misc) - [`validate_blobs_sidecar`](#validate_blobs_sidecar) + - [`is_data_available`](#is_data_available) - [`kzg_commitment_to_versioned_hash`](#kzg_commitment_to_versioned_hash) - [`tx_peek_blob_versioned_hashes`](#tx_peek_blob_versioned_hashes) - [`verify_kzg_commitments_against_transactions`](#verify_kzg_commitments_against_transactions) @@ -161,6 +162,26 @@ def validate_blobs_sidecar(slot: Slot, assert verify_aggregate_kzg_proof(blobs, expected_kzg_commitments, kzg_aggregated_proof) ``` +#### `is_data_available` + +The implementation of `is_data_available` is meant to change with later sharding upgrades. +Initially, it requires every verifying actor to retrieve the matching `BlobsSidecar`, +and validate the sidecar with `validate_blobs_sidecar`. + +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: + # `retrieve_blobs_sidecar` is implementation dependent, raises an exception if not available. + sidecar = retrieve_blobs_sidecar(slot, beacon_block_root) + if sidecar == "TEST": + return True # For testing; remove once we have a way to inject `BlobsSidecar` into tests + validate_blobs_sidecar(slot, beacon_block_root, blob_kzg_commitments, sidecar) + + return True +``` + + #### `kzg_commitment_to_versioned_hash` ```python @@ -216,6 +237,9 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None: process_operations(state, block.body) process_sync_aggregate(state, block.body.sync_aggregate) process_blob_kzg_commitments(state, block.body) # [New in EIP-4844] + + # New in EIP-4844 + assert is_data_available(block.slot, hash_tree_root(block), block.body.blob_kzg_commitments) ``` #### Execution payload diff --git a/specs/eip4844/p2p-interface.md b/specs/eip4844/p2p-interface.md index bbd18e34c..f031b3723 100644 --- a/specs/eip4844/p2p-interface.md +++ b/specs/eip4844/p2p-interface.md @@ -10,22 +10,24 @@ The specification of these changes continues in the same format as the network s -- [Configuration](#configuration) -- [Containers](#containers) - - [`BlobsSidecar`](#blobssidecar) - - [`SignedBeaconBlockAndBlobsSidecar`](#signedbeaconblockandblobssidecar) -- [The gossip domain: gossipsub](#the-gossip-domain-gossipsub) - - [Topics and messages](#topics-and-messages) - - [Global topics](#global-topics) - - [`beacon_block`](#beacon_block) - - [`beacon_block_and_blobs_sidecar`](#beacon_block_and_blobs_sidecar) - - [Transitioning the gossip](#transitioning-the-gossip) -- [The Req/Resp domain](#the-reqresp-domain) - - [Messages](#messages) - - [BeaconBlocksByRange v2](#beaconblocksbyrange-v2) - - [BeaconBlocksByRoot v2](#beaconblocksbyroot-v2) - - [BeaconBlockAndBlobsSidecarByRoot v1](#beaconblockandblobssidecarbyroot-v1) - - [BlobsSidecarsByRange v1](#blobssidecarsbyrange-v1) + - [Configuration](#configuration) + - [Containers](#containers) + - [`BlobsSidecar`](#blobssidecar) + - [`SignedBeaconBlockAndBlobsSidecar`](#signedbeaconblockandblobssidecar) + - [The gossip domain: gossipsub](#the-gossip-domain-gossipsub) + - [Topics and messages](#topics-and-messages) + - [Global topics](#global-topics) + - [`beacon_block`](#beacon_block) + - [`beacon_block_and_blobs_sidecar`](#beacon_block_and_blobs_sidecar) + - [Transitioning the gossip](#transitioning-the-gossip) + - [The Req/Resp domain](#the-reqresp-domain) + - [Messages](#messages) + - [BeaconBlocksByRange v2](#beaconblocksbyrange-v2) + - [BeaconBlocksByRoot v2](#beaconblocksbyroot-v2) + - [BeaconBlockAndBlobsSidecarByRoot v1](#beaconblockandblobssidecarbyroot-v1) + - [BlobsSidecarsByRange v1](#blobssidecarsbyrange-v1) +- [Design decision rationale](#design-decision-rationale) + - [Why are blobs relayed as a sidecar, separate from beacon blocks?](#why-are-blobs-relayed-as-a-sidecar-separate-from-beacon-blocks) @@ -257,4 +259,15 @@ Of note, blocks from slots before the finalization MUST lead to the finalized bl Clients MUST respond with blobs sidecars that are consistent from a single chain within the context of the request. After the initial blobs sidecar, clients MAY stop in the process of responding -if their fork choice changes the view of the chain in the context of the request. \ No newline at end of file +if their fork choice changes the view of the chain in the context of the request. + +# Design decision rationale + +## Why are blobs relayed as a sidecar, separate from beacon blocks? + +This "sidecar" design provides forward compatibility for further data increases by black-boxing `is_data_available()`: +with full sharding `is_data_available()` can be replaced by data-availability-sampling (DAS) +thus avoiding all blobs being downloaded by all beacon nodes on the network. + +Such sharding design may introduce an updated `BlobsSidecar` to identify the shard, +but does not affect the `BeaconBlock` structure. From 5b0bfe7eb63e164658d5ae656266ebd330343b5f Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 30 Nov 2022 13:57:19 -0800 Subject: [PATCH 04/11] EIP4844: Update `MAX_BLOBS_PER_BLOCK` to 4 --- presets/mainnet/eip4844.yaml | 4 ++-- presets/minimal/eip4844.yaml | 4 ++-- specs/eip4844/beacon-chain.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) 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/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/specs/eip4844/beacon-chain.md b/specs/eip4844/beacon-chain.md index 600793a3f..3f1dc3ca0 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 From 0dda0b263366a73bae95cd304b7923c8ac2abdc3 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Thu, 1 Dec 2022 23:37:16 +0800 Subject: [PATCH 05/11] Fix tests --- tests/core/pyspec/eth2spec/test/eip4844/sanity/test_blocks.py | 4 ++-- .../test/eip4844/unittests/validator/test_validator.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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..c83eb38ef 100644 --- a/tests/core/pyspec/eth2spec/test/eip4844/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/eip4844/sanity/test_blocks.py @@ -30,11 +30,11 @@ 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] signed_block = state_transition_and_sign_block(spec, state, 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..bd9f40a6e 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 @@ -45,5 +45,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) From 37e504e78457733e4ee5c737e23b6623ba8459fc Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 11 Nov 2022 10:47:53 -0700 Subject: [PATCH 06/11] bound the maximum number of validators considered for withdrawals per sweep --- presets/mainnet/capella.yaml | 5 ++ presets/minimal/capella.yaml | 5 ++ specs/capella/beacon-chain.md | 30 +++++-- .../test_process_withdrawals.py | 83 +++++++++++++++---- .../test/capella/sanity/test_blocks.py | 4 +- .../eth2spec/test/helpers/withdrawals.py | 7 +- 6 files changed, 107 insertions(+), 27 deletions(-) diff --git a/presets/mainnet/capella.yaml b/presets/mainnet/capella.yaml index 62306c8dc..bd80f6beb 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**10 (= 1024) validators +MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: 1024 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/specs/capella/beacon-chain.md b/specs/capella/beacon-chain.md index 90a64925f..779d97a04 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` | `1024` (= 2**10 ) | + ## 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/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..dc913e5d7 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,7 +6,7 @@ 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, ) @@ -33,8 +33,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 +80,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 +163,32 @@ 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_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=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_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=len(state.validators)) + spec, state, num_full_withdrawals=withdrawal_count) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) @@ -169,10 +200,32 @@ def test_success_all_fully_withdrawable(spec, state): @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) @@ -302,8 +355,8 @@ def test_fail_a_lot_partially_withdrawable_too_few_in_withdrawals(spec, state): @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) + 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) @@ -624,7 +677,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 +691,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 +706,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 +720,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 +734,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..91adc1de3 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 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))) From a8449fa4aa3e0c358a874452594096f52c376089 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Mon, 12 Dec 2022 15:36:51 +0200 Subject: [PATCH 07/11] Fix typo in BlobsSidecarsByRange v1 --- specs/eip4844/p2p-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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. From 478b437b053450eccf36ab51d1649973c09936d8 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 12 Dec 2022 08:25:31 -0700 Subject: [PATCH 08/11] lint --- .../test/capella/block_processing/test_process_withdrawals.py | 2 ++ 1 file changed, 2 insertions(+) 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 dc913e5d7..8292e66ce 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 @@ -180,6 +180,7 @@ def test_success_all_fully_withdrawable_in_one_sweep(spec, state): 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 @@ -217,6 +218,7 @@ def test_success_all_partially_withdrawable_in_one_sweep(spec, state): 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 From a06275765650fe61a1e3eaf83d92429485557360 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 12 Dec 2022 09:25:40 -0700 Subject: [PATCH 09/11] update mainnet preset value for sweep size --- presets/mainnet/capella.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/presets/mainnet/capella.yaml b/presets/mainnet/capella.yaml index bd80f6beb..913c2956b 100644 --- a/presets/mainnet/capella.yaml +++ b/presets/mainnet/capella.yaml @@ -13,5 +13,5 @@ MAX_WITHDRAWALS_PER_PAYLOAD: 16 # Withdrawals processing # --------------------------------------------------------------- -# 2**10 (= 1024) validators -MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: 1024 +# 2**14 (= 16384) validators +MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: 16384 From 1f943f0d64a4330d9435564a9374e72b1413aa3e Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Mon, 12 Dec 2022 14:22:58 -0700 Subject: [PATCH 10/11] Update specs/capella/beacon-chain.md --- specs/capella/beacon-chain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/capella/beacon-chain.md b/specs/capella/beacon-chain.md index 779d97a04..20f4a5dd4 100644 --- a/specs/capella/beacon-chain.md +++ b/specs/capella/beacon-chain.md @@ -82,7 +82,7 @@ We define the following Python custom types for type hinting and readability: | Name | Value | | - | - | -| `MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP` | `1024` (= 2**10 ) | +| `MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP` | `16384` (= 2**14 ) | ## Containers From da3f5af919be4abb5a6db5a80b235deb8b4b5cba Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Tue, 13 Dec 2022 15:13:44 +0800 Subject: [PATCH 11/11] Test case naming clean up (#3143) * Add @description decorator * Unify test case naming style * more clean ups * Altair tests cleanup * Clean up Altair and Bellatrix `process_deposit` tests * Clean up Bellatrix tests * Clean up Capella tests * PR feedback from @ralexstokes * Add comments on the deposit fork version tests * Remove `test_incorrect_sig_other_version` since it is duplicate to `test_ineffective_deposit_with_bad_fork_version` * Add `test_ineffective_deposit_with_current_fork_version` --- specs/altair/beacon-chain.md | 1 + .../block_processing/test_process_deposit.py | 41 +++++++ .../test_process_sync_committee_updates.py | 2 +- .../test/altair/sanity/test_blocks.py | 12 +- .../block_processing/test_process_deposit.py | 63 ++-------- .../test_process_execution_payload.py | 32 ++--- .../test_process_voluntary_exit.py | 16 ++- .../test_process_bls_to_execution_change.py | 8 +- .../test_process_withdrawals.py | 38 +++--- .../test/capella/sanity/test_blocks.py | 2 +- tests/core/pyspec/eth2spec/test/context.py | 8 +- .../pyspec/eth2spec/test/helpers/deposits.py | 43 +++++-- .../test_process_attestation.py | 116 +++++++++--------- .../test_process_attester_slashing.py | 102 +++++++-------- .../test_process_block_header.py | 4 +- .../block_processing/test_process_deposit.py | 68 ++++------ .../test_process_proposer_slashing.py | 52 ++++---- .../test_process_voluntary_exit.py | 26 ++-- .../test/phase0/genesis/test_validity.py | 16 +-- .../test/phase0/sanity/test_blocks.py | 20 +-- .../eth2spec/test/phase0/sanity/test_slots.py | 5 +- tests/generators/operations/main.py | 13 +- 22 files changed, 352 insertions(+), 336 deletions(-) create mode 100644 tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_deposit.py 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/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/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..6d254f174 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 @@ -104,14 +104,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) @@ -125,12 +125,12 @@ def test_bad_parent_hash_first_payload(spec, state): execution_payload = build_empty_execution_payload(spec, state) execution_payload.parent_hash = b'\x55' * 32 - 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) @@ -151,14 +151,14 @@ def run_bad_prev_randao_test(spec, state): @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) @@ -176,14 +176,14 @@ def run_bad_everything_test(spec, state): @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) @@ -204,28 +204,28 @@ def run_bad_timestamp_test(spec, state, is_future): @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) @@ -320,27 +320,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/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 8292e66ce..ad3911080 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 @@ -244,7 +244,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( @@ -260,7 +260,7 @@ def test_fail_non_withdrawable_non_empty_withdrawals(spec, state): @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) @@ -272,7 +272,7 @@ def test_fail_one_expected_full_withdrawal_and_none_in_withdrawals(spec, state): @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) @@ -284,7 +284,7 @@ def test_fail_one_expected_partial_withdrawal_and_none_in_withdrawals(spec, stat @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) @@ -296,7 +296,7 @@ def test_fail_one_expected_full_withdrawal_and_duplicate_in_withdrawals(spec, st @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) @@ -308,7 +308,7 @@ def test_fail_two_expected_partial_withdrawal_and_duplicate_in_withdrawals(spec, @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) @@ -320,7 +320,7 @@ def test_fail_max_per_slot_full_withdrawals_and_one_less_in_withdrawals(spec, st @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) @@ -332,7 +332,7 @@ def test_fail_max_per_slot_partial_withdrawals_and_one_less_in_withdrawals(spec, @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) @@ -344,7 +344,7 @@ def test_fail_a_lot_fully_withdrawable_too_few_in_withdrawals(spec, state): @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) @@ -356,7 +356,7 @@ def test_fail_a_lot_partially_withdrawable_too_few_in_withdrawals(spec, state): @with_phases([CAPELLA]) @spec_state_test -def test_fail_a_lot_mixed_withdrawable_in_queue_too_few_in_withdrawals(spec, state): +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) @@ -373,7 +373,7 @@ 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) @@ -385,7 +385,7 @@ def test_fail_incorrect_withdrawal_index(spec, state): @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) @@ -397,7 +397,7 @@ def test_fail_incorrect_address_full(spec, state): @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) @@ -409,7 +409,7 @@ def test_fail_incorrect_address_partial(spec, state): @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) @@ -421,7 +421,7 @@ def test_fail_incorrect_amount_full(spec, state): @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) @@ -433,7 +433,7 @@ def test_fail_incorrect_amount_partial(spec, state): @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) @@ -451,7 +451,7 @@ def test_fail_one_of_many_incorrectly_full(spec, state): @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) @@ -469,7 +469,7 @@ def test_fail_one_of_many_incorrectly_partial(spec, state): @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) @@ -487,7 +487,7 @@ def test_fail_many_incorrectly_full(spec, state): @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) 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 91adc1de3..1df046c9d 100644 --- a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py @@ -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 94910fa47..c0e7c2b5f 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -258,6 +258,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. @@ -267,7 +273,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))) 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/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/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 [