From 977cd73379e383cb4f1b08d342f0d790ab513915 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Sat, 2 May 2020 01:57:34 +0800 Subject: [PATCH] Refactor the tests --- .../eth2spec/test/helpers/shard_block.py | 33 ++-- .../pyspec/eth2spec/test/helpers/state.py | 10 ++ .../test_process_crosslink.py | 47 +++--- .../test/phase_1/sanity/test_blocks.py | 154 +++++++----------- 4 files changed, 106 insertions(+), 138 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/shard_block.py b/tests/core/pyspec/eth2spec/test/helpers/shard_block.py index 922f4d748..ef65d2427 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/shard_block.py +++ b/tests/core/pyspec/eth2spec/test/helpers/shard_block.py @@ -1,6 +1,6 @@ from eth2spec.test.helpers.attestations import get_valid_on_time_attestation from eth2spec.test.helpers.block import get_state_and_beacon_parent_root_at_slot -from eth2spec.test.helpers.state import next_slots +from eth2spec.test.helpers.state import transition_to from eth2spec.test.helpers.keys import privkeys from eth2spec.utils import bls from eth2spec.utils.bls import only_with_bls @@ -51,18 +51,17 @@ def build_shard_block(spec, return signed_block -def build_shard_transitions_till_slot(spec, state, shards, shard_blocks, target_len_offset_slot): - state = state.copy() - next_slots(spec, state, target_len_offset_slot) +def build_shard_transitions_till_slot(spec, state, shard_blocks, on_time_slot): + temp_state = state.copy() + transition_to(spec, temp_state, on_time_slot) shard_transitions = [spec.ShardTransition()] * spec.MAX_SHARDS - for shard in shards: - offset_slots = spec.get_offset_slots(state, shard) + for shard, blocks in shard_blocks.items(): + offset_slots = spec.get_offset_slots(temp_state, shard) len_offset_slots = len(offset_slots) - assert len_offset_slots == target_len_offset_slot - shard_blocks_of_shard = shard_blocks[shard] - shard_transition = spec.get_shard_transition(state, shard, shard_blocks_of_shard) - if len(shard_blocks_of_shard) > 0: - shard_block_root = shard_blocks_of_shard[-1].message.hash_tree_root() + assert len_offset_slots == on_time_slot - state.shard_states[shard].slot - 1 + shard_transition = spec.get_shard_transition(temp_state, shard, blocks) + if len(blocks) > 0: + shard_block_root = blocks[-1].message.hash_tree_root() assert shard_transition.shard_states[len_offset_slots - 1].latest_block_root == shard_block_root assert shard_transition.shard_states[len_offset_slots - 1].slot == offset_slots[-1] shard_transitions[shard] = shard_transition @@ -70,19 +69,17 @@ def build_shard_transitions_till_slot(spec, state, shards, shard_blocks, target_ return shard_transitions -def build_attestation_with_shard_transition(spec, state, slot, index, target_len_offset_slot, shard_transition=None): - state = state.copy() - next_slots(spec, state, target_len_offset_slot) +def build_attestation_with_shard_transition(spec, state, index, on_time_slot, shard_transition=None): + temp_state = state.copy() + transition_to(spec, temp_state, on_time_slot - 1) attestation = get_valid_on_time_attestation( spec, - state, - slot=slot, + temp_state, index=index, shard_transition=shard_transition, signed=True, ) - assert attestation.data.slot == slot + assert attestation.data.slot == temp_state.slot if shard_transition is not None: - assert target_len_offset_slot == len(shard_transition.shard_states) assert attestation.data.shard_transition_root == shard_transition.hash_tree_root() return attestation diff --git a/tests/core/pyspec/eth2spec/test/helpers/state.py b/tests/core/pyspec/eth2spec/test/helpers/state.py index 46a7ce2b5..f08f22602 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/state.py +++ b/tests/core/pyspec/eth2spec/test/helpers/state.py @@ -30,6 +30,16 @@ def transition_to(spec, state, slot): assert state.slot == slot +def transition_to_valid_shard_slot(spec, state): + """ + Transition to slot `spec.PHASE_1_GENESIS_SLOT + 1` and fork at `spec.PHASE_1_GENESIS_SLOT`. + """ + transition_to(spec, state, spec.PHASE_1_GENESIS_SLOT) + state = spec.upgrade_to_phase1(state) # `upgrade_to_phase1` is a pure function + next_slot(spec, state) + return state + + def next_epoch(spec, state): """ Transition to the start slot of the next epoch diff --git a/tests/core/pyspec/eth2spec/test/phase_1/block_processing/test_process_crosslink.py b/tests/core/pyspec/eth2spec/test/phase_1/block_processing/test_process_crosslink.py index 912770da8..1f066b344 100644 --- a/tests/core/pyspec/eth2spec/test/phase_1/block_processing/test_process_crosslink.py +++ b/tests/core/pyspec/eth2spec/test/phase_1/block_processing/test_process_crosslink.py @@ -10,69 +10,64 @@ from eth2spec.test.helpers.shard_block import ( build_shard_block, build_shard_transitions_till_slot, ) -from eth2spec.test.helpers.state import next_epoch, next_slot, transition_to +from eth2spec.test.helpers.state import transition_to, transition_to_valid_shard_slot -def run_basic_crosslink_tests(spec, state, target_len_offset_slot): - next_epoch(spec, state) - next_epoch(spec, state) - state = spec.upgrade_to_phase1(state) - next_slot(spec, state) - +def run_basic_crosslink_tests(spec, state, target_len_offset_slot, valid=True): + state = transition_to_valid_shard_slot(spec, state) # At the beginning, let `x = state.slot`, `state.shard_states[shard].slot == x - 1` slot_x = state.slot committee_index = spec.CommitteeIndex(0) shard = spec.compute_shard_from_committee_index(state, committee_index, state.slot) assert state.shard_states[shard].slot == slot_x - 1 - # Create SignedShardBlock at slot `shard_state.slot + 1` -> x + # Create SignedShardBlock body = b'\x56' * spec.MAX_SHARD_BLOCK_SIZE shard_block = build_shard_block(spec, state, shard, body=body, signed=True) shard_blocks = [shard_block] - - # Attester creates `attestation` at slot x - # Use temporary next state to get ShardTransition of shard block + # Create a shard_transitions that would be included at beacon block `state.slot + target_len_offset_slot` shard_transitions = build_shard_transitions_till_slot( spec, state, - shards=[shard, ], shard_blocks={shard: shard_blocks}, - target_len_offset_slot=target_len_offset_slot, + on_time_slot=state.slot + target_len_offset_slot, ) shard_transition = shard_transitions[shard] + # Create an attestation that would be included at beacon block `state.slot + target_len_offset_slot` attestation = build_attestation_with_shard_transition( spec, state, - slot=slot_x + target_len_offset_slot - 1, index=committee_index, - target_len_offset_slot=target_len_offset_slot, + on_time_slot=state.slot + target_len_offset_slot, shard_transition=shard_transition, ) pre_gasprice = state.shard_states[shard].gasprice - transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) + transition_to(spec, state, state.slot + target_len_offset_slot) pre_shard_state = state.shard_states[shard] - yield from run_crosslinks_processing(spec, state, shard_transitions, [attestation]) - # After state transition, - assert state.slot == slot_x + target_len_offset_slot - shard_state = state.shard_states[shard] - assert shard_state != pre_shard_state - assert shard_state == shard_transition.shard_states[len(shard_transition.shard_states) - 1] + yield from run_crosslinks_processing(spec, state, shard_transitions, [attestation], valid=valid) - if target_len_offset_slot == 1: - assert shard_state.gasprice > pre_gasprice + if valid: + # After state transition, + assert state.slot == slot_x + target_len_offset_slot + shard_state = state.shard_states[shard] + assert shard_state != pre_shard_state + assert shard_state == shard_transition.shard_states[len(shard_transition.shard_states) - 1] + + if target_len_offset_slot == 1: + assert shard_state.gasprice > pre_gasprice @with_all_phases_except([PHASE0]) @spec_state_test @always_bls def test_basic_crosslinks(spec, state): - run_basic_crosslink_tests(spec, state, target_len_offset_slot=1) + yield from run_basic_crosslink_tests(spec, state, target_len_offset_slot=1, valid=True) @with_all_phases_except([PHASE0]) @spec_state_test @always_bls def test_multiple_offset_slots(spec, state): - run_basic_crosslink_tests(spec, state, target_len_offset_slot=3) + yield from run_basic_crosslink_tests(spec, state, target_len_offset_slot=3, valid=True) diff --git a/tests/core/pyspec/eth2spec/test/phase_1/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/phase_1/sanity/test_blocks.py index 168915d02..60af35d45 100644 --- a/tests/core/pyspec/eth2spec/test/phase_1/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/phase_1/sanity/test_blocks.py @@ -1,3 +1,5 @@ +from typing import Dict, Sequence + from eth2spec.test.context import ( PHASE0, with_all_phases_except, @@ -10,69 +12,74 @@ from eth2spec.test.helpers.shard_block import ( build_shard_block, build_shard_transitions_till_slot, ) -from eth2spec.test.helpers.state import next_epoch, next_slot, state_transition_and_sign_block +from eth2spec.test.helpers.state import state_transition_and_sign_block, transition_to_valid_shard_slot + + +def run_beacon_block_with_shard_blocks(spec, state, shard_blocks, target_len_offset_slot, committee_index, valid=True): + shard_transitions = build_shard_transitions_till_slot( + spec, state, shard_blocks, on_time_slot=state.slot + target_len_offset_slot + ) + attestations = [ + build_attestation_with_shard_transition( + spec, + state, + on_time_slot=state.slot + target_len_offset_slot, + index=committee_index, + shard_transition=shard_transitions[shard], + ) + for shard in shard_blocks.keys() + ] + + # Propose beacon block at slot `x + 1` + beacon_block = build_empty_block(spec, state, slot=state.slot + target_len_offset_slot) + beacon_block.body.attestations = attestations + beacon_block.body.shard_transitions = shard_transitions + + pre_shard_states = state.shard_states.copy() + yield 'pre', state.copy() + yield 'block', beacon_block + state_transition_and_sign_block(spec, state, beacon_block) + if valid: + yield 'post', state + else: + yield 'post', None + return + + for shard in range(spec.get_active_shard_count(state)): + post_shard_state = state.shard_states[shard] + if shard in shard_blocks: + # Shard state has been changed to state_transition result + assert post_shard_state == shard_transitions[shard].shard_states[ + len(shard_transitions[shard].shard_states) - 1 + ] + assert beacon_block.slot == shard_transitions[shard].shard_states[0].slot + target_len_offset_slot + assert post_shard_state.slot == state.slot - 1 + if len(shard_blocks[shard]) == 0: + # `latest_block_root` is the same + assert post_shard_state.latest_block_root == pre_shard_states[shard].latest_block_root @with_all_phases_except([PHASE0]) @spec_state_test @always_bls def test_process_beacon_block_with_normal_shard_transition(spec, state): - next_epoch(spec, state) - next_epoch(spec, state) - state = spec.upgrade_to_phase1(state) - next_slot(spec, state) + state = transition_to_valid_shard_slot(spec, state) target_len_offset_slot = 1 - - # At the beginning, let `x = state.slot`, `state.shard_states[shard].slot == x - 1` - slot_x = state.slot committee_index = spec.CommitteeIndex(0) shard = spec.compute_shard_from_committee_index(state, committee_index, state.slot) - assert state.shard_states[shard].slot == slot_x - 1 + assert state.shard_states[shard].slot == state.slot - 1 - # Create SignedShardBlock at slot `shard_state.slot + 1` -> x - body = b'\x56' * spec.MAX_SHARD_BLOCK_SIZE - shard_block = build_shard_block(spec, state, shard, body=body, signed=True) - shard_blocks = [shard_block] - - # Attester creates `attestation` at slot x - # Use temporary next state to get ShardTransition of shard block - shard_transitions = build_shard_transitions_till_slot( - spec, - state, - shards=[shard, ], - shard_blocks={shard: shard_blocks}, - target_len_offset_slot=target_len_offset_slot, - ) - shard_transition = shard_transitions[shard] - attestation = build_attestation_with_shard_transition( - spec, - state, - slot=slot_x + target_len_offset_slot - 1, - index=committee_index, - target_len_offset_slot=target_len_offset_slot, - shard_transition=shard_transition, - ) pre_gasprice = state.shard_states[shard].gasprice - # Propose beacon block at slot `x + 1` - pre_shard_state = state.shard_states[shard] - beacon_block_1 = build_empty_block(spec, state, slot=slot_x + target_len_offset_slot) - beacon_block_1.body.attestations = [attestation] - beacon_block_1.body.shard_transitions = shard_transitions - assert ( - beacon_block_1.slot == slot_x + target_len_offset_slot - == shard_transition.shard_states[0].slot + target_len_offset_slot - ) - state_transition_and_sign_block(spec, state, beacon_block_1) + # Create SignedShardBlock at slot `shard_state.slot + 1` + body = b'\x56' * spec.MAX_SHARD_BLOCK_SIZE + shard_block = build_shard_block(spec, state, shard, body=body, signed=True) + shard_blocks: Dict[spec.Shard, Sequence[spec.SignedShardBlock]] = {shard: [shard_block]} + + yield from run_beacon_block_with_shard_blocks(spec, state, shard_blocks, target_len_offset_slot, committee_index) - # After state transition - assert state.slot == slot_x + target_len_offset_slot shard_state = state.shard_states[shard] - # latest_block_root has changed - assert shard_state.latest_block_root == shard_block.message.hash_tree_root() - assert shard_state != pre_shard_state - assert shard_state == shard_transition.shard_states[len(shard_transition.shard_states) - 1] if target_len_offset_slot == 1 and len(shard_blocks) > 0: assert shard_state.gasprice > pre_gasprice @@ -82,60 +89,19 @@ def test_process_beacon_block_with_normal_shard_transition(spec, state): @spec_state_test @always_bls def test_process_beacon_block_with_empty_proposal_transition(spec, state): - next_epoch(spec, state) - next_epoch(spec, state) - state = spec.upgrade_to_phase1(state) - next_slot(spec, state) + state = transition_to_valid_shard_slot(spec, state) target_len_offset_slot = 1 - - # At the beginning, let `x = state.slot`, `state.shard_states[shard].slot == x - 1` - slot_x = state.slot committee_index = spec.CommitteeIndex(0) shard = spec.compute_shard_from_committee_index(state, committee_index, state.slot) - assert state.shard_states[shard].slot == slot_x - 1 + assert state.shard_states[shard].slot == state.slot - 1 # No new shard block - shard_blocks = [] + shard_blocks = {} - # Attester creates `attestation` at slot x - # Use temporary next state to get ShardTransition of shard block - shard_transitions = build_shard_transitions_till_slot( - spec, - state, - shards=[shard, ], - shard_blocks={shard: shard_blocks}, - target_len_offset_slot=target_len_offset_slot, - ) - shard_transition = shard_transitions[shard] - attestation = build_attestation_with_shard_transition( - spec, - state, - slot=slot_x + target_len_offset_slot - 1, - index=committee_index, - target_len_offset_slot=target_len_offset_slot, - shard_transition=shard_transition, - ) pre_gasprice = state.shard_states[shard].gasprice - # Propose beacon block at slot `x + 1` - pre_shard_state = state.shard_states[shard] - beacon_block_1 = build_empty_block(spec, state, slot=slot_x + target_len_offset_slot) - beacon_block_1.body.attestations = [attestation] - beacon_block_1.body.shard_transitions = shard_transitions - assert ( - beacon_block_1.slot == slot_x + target_len_offset_slot - == shard_transition.shard_states[0].slot + target_len_offset_slot - ) - state_transition_and_sign_block(spec, state, beacon_block_1) - - # After state transition - assert state.slot == slot_x + target_len_offset_slot - shard_state = state.shard_states[shard] - # latest_block_root hasn't changed - assert shard_state.latest_block_root == pre_shard_state.latest_block_root - assert shard_state != pre_shard_state - assert shard_state == shard_transition.shard_states[len(shard_transition.shard_states) - 1] + yield from run_beacon_block_with_shard_blocks(spec, state, shard_blocks, target_len_offset_slot, committee_index) if target_len_offset_slot == 1 and len(shard_blocks) > 0: - assert shard_state.gasprice > pre_gasprice + assert state.shard_states[shard].gasprice > pre_gasprice