From cf42fd4828e36ad368fd31b88cda809bd83e91b9 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Thu, 16 Jul 2020 16:34:21 +0800 Subject: [PATCH 1/6] Rename `PHASE_1_GENESIS_SLOT` to `PHASE_1_FORK_SLOT` and set it to `Slot(0)` for testing. --- configs/README.md | 2 +- configs/mainnet/phase1.yaml | 2 +- configs/minimal/phase1.yaml | 4 +- specs/phase1/beacon-chain.md | 27 ++++++++------ specs/phase1/phase1-fork.md | 8 ++-- specs/phase1/shard-fork-choice.md | 2 +- specs/phase1/validator.md | 3 ++ tests/core/pyspec/eth2spec/test/context.py | 3 -- .../test/fork_choice/test_on_shard_head.py | 12 +++--- .../eth2spec/test/helpers/attestations.py | 28 ++++++++------ .../pyspec/eth2spec/test/helpers/state.py | 6 +-- .../test_process_chunk_challenge.py | 20 +++++++--- .../test_process_custody_slashing.py | 1 + .../test_process_shard_transition.py | 2 +- .../test_process_challenge_deadlines.py | 5 ++- .../test_process_custody_final_updates.py | 12 ++++-- .../test/phase1/sanity/test_blocks.py | 12 +++--- .../test/phase1/sanity/test_shard_blocks.py | 37 +++++++++++++------ 18 files changed, 112 insertions(+), 74 deletions(-) diff --git a/configs/README.md b/configs/README.md index be3c60e6f2..353cd35dbc 100644 --- a/configs/README.md +++ b/configs/README.md @@ -15,7 +15,7 @@ Over time, the need to sync an older state may be deprecated. In this case, the prefix on the new constant may be removed, and the old constant will keep a special name before completely being removed. A previous iteration of forking made use of "timelines", but this collides with the definitions used in the spec (constants for special forking slots, etc.), and was not integrated sufficiently in any of the spec tools or implementations. -Instead, the config essentially doubles as fork definition now, e.g. changing the value for `PHASE_1_GENESIS_SLOT` changes the fork. +Instead, the config essentially doubles as fork definition now, e.g. changing the value for `PHASE_1_FORK_SLOT` changes the fork. Another reason to prefer forking through constants is the ability to program a forking moment based on context, instead of being limited to a static slot number. diff --git a/configs/mainnet/phase1.yaml b/configs/mainnet/phase1.yaml index 8c08009576..a9c7f89cc4 100644 --- a/configs/mainnet/phase1.yaml +++ b/configs/mainnet/phase1.yaml @@ -5,7 +5,7 @@ # --------------------------------------------------------------- PHASE_1_FORK_VERSION: 0x01000000 # [STUB] -PHASE_1_GENESIS_SLOT: 32 +PHASE_1_FORK_SLOT: 0 INITIAL_ACTIVE_SHARDS: 64 diff --git a/configs/minimal/phase1.yaml b/configs/minimal/phase1.yaml index 7fbc7e5a30..09e288900e 100644 --- a/configs/minimal/phase1.yaml +++ b/configs/minimal/phase1.yaml @@ -5,8 +5,8 @@ # --------------------------------------------------------------- # [customized] for testnet distinction PHASE_1_FORK_VERSION: 0x01000001 -# [customized] for testing -PHASE_1_GENESIS_SLOT: 8 +# [STUB] +PHASE_1_FORK_SLOT: 0 # [customized] reduced for testing INITIAL_ACTIVE_SHARDS: 2 diff --git a/specs/phase1/beacon-chain.md b/specs/phase1/beacon-chain.md index e7ad5913a8..16a0ea4cbc 100644 --- a/specs/phase1/beacon-chain.md +++ b/specs/phase1/beacon-chain.md @@ -760,20 +760,23 @@ def validate_attestation(state: BeaconState, attestation: Attestation) -> None: committee = get_beacon_committee(state, data.slot, data.index) assert len(attestation.aggregation_bits) == len(committee) - if attestation.data.target.epoch == get_current_epoch(state): - assert attestation.data.source == state.current_justified_checkpoint + if data.target.epoch == get_current_epoch(state): + assert data.source == state.current_justified_checkpoint else: - assert attestation.data.source == state.previous_justified_checkpoint + assert data.source == state.previous_justified_checkpoint # Type 1: on-time attestations - if is_on_time_attestation(state, attestation.data): + if is_on_time_attestation(state, data): # Correct parent block root assert data.beacon_block_root == get_block_root_at_slot(state, compute_previous_slot(state.slot)) # Correct shard number - shard = compute_shard_from_committee_index(state, attestation.data.index, attestation.data.slot) - assert attestation.data.shard == shard - # On-time attestations should have a non-empty shard transition root - assert attestation.data.shard_transition_root != hash_tree_root(ShardTransition()) + shard = compute_shard_from_committee_index(state, data.index, data.slot) + assert data.shard == shard + if data.slot == PHASE_1_FORK_SLOT: + assert data.shard_transition_root == hash_tree_root(ShardTransition()) + else: + # On-time attestations should have a non-empty shard transition root + assert data.shard_transition_root != hash_tree_root(ShardTransition()) # Type 2: no shard transition else: # Ensure delayed attestation @@ -811,7 +814,7 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: ```python def apply_shard_transition(state: BeaconState, shard: Shard, transition: ShardTransition) -> None: # TODO: only need to check it once when phase 1 starts - assert state.slot > PHASE_1_GENESIS_SLOT + assert state.slot > PHASE_1_FORK_SLOT # Correct data root count offset_slots = get_offset_slots(state, shard) @@ -976,8 +979,10 @@ def verify_empty_shard_transition(state: BeaconState, shard_transitions: Sequenc def process_shard_transitions(state: BeaconState, shard_transitions: Sequence[ShardTransition], attestations: Sequence[Attestation]) -> None: - # Process crosslinks - process_crosslinks(state, shard_transitions, attestations) + if compute_previous_slot(state.slot) != PHASE_1_FORK_SLOT: + # Process crosslinks + process_crosslinks(state, shard_transitions, attestations) + # Verify the empty proposal shard states assert verify_empty_shard_transition(state, shard_transitions) ``` diff --git a/specs/phase1/phase1-fork.md b/specs/phase1/phase1-fork.md index e83e9ef4a3..e3949aca8a 100644 --- a/specs/phase1/phase1-fork.md +++ b/specs/phase1/phase1-fork.md @@ -35,18 +35,18 @@ Warning: this configuration is not definitive. | Name | Value | | - | - | | `PHASE_1_FORK_VERSION` | `Version('0x01000000')` | -| `PHASE_1_GENESIS_SLOT` | `2**5` **TBD** | +| `PHASE_1_FORK_SLOT` | `Slot(0)` **TBD** | | `INITIAL_ACTIVE_SHARDS` | `2**6` (= 64) | ## Fork to Phase 1 ### Fork trigger -TBD. Social consensus, along with state conditions such as epoch boundary, finality, deposits, active validator count, etc. may be part of the decision process to trigger the fork. For now we assume the condition will be triggered at slot `PHASE_1_GENESIS_SLOT`, where `PHASE_1_GENESIS_SLOT % SLOTS_PER_EPOCH == 0`. +TBD. Social consensus, along with state conditions such as epoch boundary, finality, deposits, active validator count, etc. may be part of the decision process to trigger the fork. For now we assume the condition will be triggered at slot `PHASE_1_FORK_SLOT`, where `PHASE_1_FORK_SLOT % SLOTS_PER_EPOCH == 0`. ### Upgrading the state -After `process_slots` of Phase 0 finishes, if `state.slot == PHASE_1_GENESIS_SLOT`, an irregular state change is made to upgrade to Phase 1. +After `process_slots` of Phase 0 finishes, if `state.slot == PHASE_1_FORK_SLOT`, an irregular state change is made to upgrade to Phase 1. ```python def upgrade_to_phase1(pre: phase0.BeaconState) -> BeaconState: @@ -102,7 +102,7 @@ def upgrade_to_phase1(pre: phase0.BeaconState) -> BeaconState: current_epoch_start_shard=Shard(0), shard_states=List[ShardState, MAX_SHARDS]( ShardState( - slot=pre.slot, + slot=compute_previous_slot(pre.slot), gasprice=MIN_GASPRICE, latest_block_root=Root(), ) for i in range(INITIAL_ACTIVE_SHARDS) diff --git a/specs/phase1/shard-fork-choice.md b/specs/phase1/shard-fork-choice.md index 8416009d73..bdc6ab8f49 100644 --- a/specs/phase1/shard-fork-choice.md +++ b/specs/phase1/shard-fork-choice.md @@ -48,7 +48,7 @@ def get_forkchoice_shard_store(anchor_state: BeaconState, shard: Shard) -> Shard shard=shard, signed_blocks={ anchor_state.shard_states[shard].latest_block_root: SignedShardBlock( - message=ShardBlock(slot=anchor_state.slot, shard=shard) + message=ShardBlock(slot=compute_previous_slot(anchor_state.slot), shard=shard) ) }, block_states={anchor_state.shard_states[shard].latest_block_root: anchor_state.copy().shard_states[shard]}, diff --git a/specs/phase1/validator.md b/specs/phase1/validator.md index b89b90c8a7..7f5313554b 100644 --- a/specs/phase1/validator.md +++ b/specs/phase1/validator.md @@ -310,6 +310,9 @@ def get_shard_transition_fields( def get_shard_transition(beacon_state: BeaconState, shard: Shard, shard_blocks: Sequence[SignedShardBlock]) -> ShardTransition: + if beacon_state.slot == PHASE_1_FORK_SLOT: + return ShardTransition() + offset_slots = compute_offset_slots( get_latest_slot_for_shard(beacon_state, shard), Slot(beacon_state.slot + 1), diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index 0d953cf241..68696ea0a4 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -63,9 +63,6 @@ def _prepare_state(balances_fn: Callable[[Any], Sequence[int]], threshold_fn: Ca # TODO: instead of upgrading a test phase0 genesis state we can also write a phase1 state helper. # Decide based on performance/consistency results later. state = phases[PHASE1].upgrade_to_phase1(state) - # Shard state slot must lag behind BeaconState slot by at least 1 - # Will handle this more elegantly with fork mechanics - spec.process_slots(state, state.slot + 1) return state diff --git a/tests/core/pyspec/eth2spec/test/fork_choice/test_on_shard_head.py b/tests/core/pyspec/eth2spec/test/fork_choice/test_on_shard_head.py index a87a859171..f38f1aef16 100644 --- a/tests/core/pyspec/eth2spec/test/fork_choice/test_on_shard_head.py +++ b/tests/core/pyspec/eth2spec/test/fork_choice/test_on_shard_head.py @@ -8,7 +8,10 @@ get_committee_index_of_shard, ) from eth2spec.test.helpers.fork_choice import add_block_to_store, get_anchor_root -from eth2spec.test.helpers.state import state_transition_and_sign_block +from eth2spec.test.helpers.state import ( + state_transition_and_sign_block, + transition_to_valid_shard_slot, +) from eth2spec.test.helpers.block import build_empty_block @@ -102,21 +105,18 @@ def apply_shard_and_beacon(spec, state, store, shard_store, shard_blocks_buffer) @spec_state_test @never_bls # Set to never_bls for testing `check_pending_shard_blocks` def test_basic(spec, state): - spec.PHASE_1_GENESIS_SLOT = 0 # NOTE: mock genesis slot here - state = spec.upgrade_to_phase1(state) - shard = spec.Shard(1) + transition_to_valid_shard_slot(spec, state) # Initialization store = spec.get_forkchoice_store(state) anchor_root = get_anchor_root(spec, state) assert spec.get_head(store) == anchor_root + shard = spec.Shard(1) shard_store = spec.get_forkchoice_shard_store(state, shard) shard_head_root = spec.get_shard_head(store, shard_store) assert shard_head_root == state.shard_states[shard].latest_block_root - assert shard_store.block_states[shard_head_root].slot == 1 assert shard_store.block_states[shard_head_root] == state.shard_states[shard] - # For mainnet config, it's possible that only one committee of `shard` per epoch. # we set this counter to test more rounds. shard_committee_counter = 2 diff --git a/tests/core/pyspec/eth2spec/test/helpers/attestations.py b/tests/core/pyspec/eth2spec/test/helpers/attestations.py index 3445f9ff64..fa6a90059d 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/attestations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/attestations.py @@ -69,7 +69,7 @@ def build_attestation_data(spec, state, slot, index, shard=None, shard_transitio source_epoch = state.current_justified_checkpoint.epoch source_root = state.current_justified_checkpoint.root - attestation_data = spec.AttestationData( + data = spec.AttestationData( slot=slot, index=index, beacon_block_root=block_root, @@ -79,23 +79,27 @@ def build_attestation_data(spec, state, slot, index, shard=None, shard_transitio if spec.fork == PHASE1: if shard is None: - shard = spec.compute_shard_from_committee_index(state, attestation_data.index, attestation_data.slot) - attestation_data.shard = shard + shard = spec.compute_shard_from_committee_index(state, data.index, data.slot) + data.shard = shard if shard_transition is not None: last_offset_index = len(shard_transition.shard_data_roots) - 1 - attestation_data.shard_head_root = shard_transition.shard_states[last_offset_index].latest_block_root - attestation_data.shard_transition_root = shard_transition.hash_tree_root() + data.shard_head_root = shard_transition.shard_states[last_offset_index].latest_block_root + data.shard_transition_root = shard_transition.hash_tree_root() else: if on_time: - shard_transition = spec.get_shard_transition(state, shard, shard_blocks=[]) - last_offset_index = len(shard_transition.shard_data_roots) - 1 - attestation_data.shard_head_root = shard_transition.shard_states[last_offset_index].latest_block_root - attestation_data.shard_transition_root = shard_transition.hash_tree_root() + if data.slot == spec.PHASE_1_FORK_SLOT: + data.shard_head_root = spec.Root() + data.shard_transition_root = spec.ShardTransition().hash_tree_root() + else: + shard_transition = spec.get_shard_transition(state, shard, shard_blocks=[]) + last_offset_index = len(shard_transition.shard_data_roots) - 1 + data.shard_head_root = shard_transition.shard_states[last_offset_index].latest_block_root + data.shard_transition_root = shard_transition.hash_tree_root() else: - attestation_data.shard_head_root = state.shard_states[shard].latest_block_root - attestation_data.shard_transition_root = spec.Root() - return attestation_data + data.shard_head_root = state.shard_states[shard].latest_block_root + data.shard_transition_root = spec.Root() + return data def get_valid_on_time_attestation(spec, state, slot=None, index=None, shard_transition=None, signed=False): diff --git a/tests/core/pyspec/eth2spec/test/helpers/state.py b/tests/core/pyspec/eth2spec/test/helpers/state.py index c70a47742f..f53d8f7116 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/state.py +++ b/tests/core/pyspec/eth2spec/test/helpers/state.py @@ -42,12 +42,10 @@ def transition_to_slot_via_block(spec, state, 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 slot `spec.PHASE_1_FORK_SLOT + 1` and fork at `spec.PHASE_1_FORK_SLOT`. """ - transition_to(spec, state, spec.PHASE_1_GENESIS_SLOT) - state = spec.upgrade_to_phase1(state) # `upgrade_to_phase1` is a pure function + transition_to(spec, state, spec.PHASE_1_FORK_SLOT) next_slot(spec, state) - return state def next_epoch(spec, state): diff --git a/tests/core/pyspec/eth2spec/test/phase1/block_processing/test_process_chunk_challenge.py b/tests/core/pyspec/eth2spec/test/phase1/block_processing/test_process_chunk_challenge.py index 4ef1d667a2..395bcc2fdb 100644 --- a/tests/core/pyspec/eth2spec/test/phase1/block_processing/test_process_chunk_challenge.py +++ b/tests/core/pyspec/eth2spec/test/phase1/block_processing/test_process_chunk_challenge.py @@ -6,7 +6,7 @@ from eth2spec.test.helpers.attestations import ( get_valid_on_time_attestation, ) -from eth2spec.test.helpers.state import transition_to +from eth2spec.test.helpers.state import transition_to, transition_to_valid_shard_slot from eth2spec.test.context import ( PHASE0, with_all_phases_except, @@ -68,7 +68,8 @@ def run_custody_chunk_response_processing(spec, state, custody_response, valid=T @with_all_phases_except([PHASE0]) @spec_state_test def test_challenge_appended(spec, state): - transition_to(spec, state, state.slot + 1) + transition_to_valid_shard_slot(spec, state) + transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) @@ -89,7 +90,8 @@ def test_challenge_appended(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_challenge_empty_element_replaced(spec, state): - transition_to(spec, state, state.slot + 1) + transition_to_valid_shard_slot(spec, state) + transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) @@ -112,7 +114,8 @@ def test_challenge_empty_element_replaced(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_duplicate_challenge(spec, state): - transition_to(spec, state, state.slot + 1) + transition_to_valid_shard_slot(spec, state) + transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) @@ -135,7 +138,8 @@ def test_duplicate_challenge(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_second_challenge(spec, state): - transition_to(spec, state, state.slot + 1) + transition_to_valid_shard_slot(spec, state) + transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) @@ -160,6 +164,7 @@ def test_second_challenge(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_multiple_epochs_custody(spec, state): + transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 3) shard = 0 @@ -182,6 +187,7 @@ def test_multiple_epochs_custody(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_many_epochs_custody(spec, state): + transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 20) shard = 0 @@ -204,6 +210,7 @@ def test_many_epochs_custody(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_off_chain_attestation(spec, state): + transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH) shard = 0 @@ -222,6 +229,7 @@ def test_off_chain_attestation(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_custody_response(spec, state): + transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH) shard = 0 @@ -251,6 +259,7 @@ def test_custody_response(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_custody_response_multiple_epochs(spec, state): + transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 3) shard = 0 @@ -280,6 +289,7 @@ def test_custody_response_multiple_epochs(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_custody_response_many_epochs(spec, state): + transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 20) shard = 0 diff --git a/tests/core/pyspec/eth2spec/test/phase1/block_processing/test_process_custody_slashing.py b/tests/core/pyspec/eth2spec/test/phase1/block_processing/test_process_custody_slashing.py index 07cd769961..23a60cd220 100644 --- a/tests/core/pyspec/eth2spec/test/phase1/block_processing/test_process_custody_slashing.py +++ b/tests/core/pyspec/eth2spec/test/phase1/block_processing/test_process_custody_slashing.py @@ -63,6 +63,7 @@ def run_standard_custody_slashing_test(spec, slashing_message_data=None, correct=True, valid=True): + transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 if shard_lateness is None: shard_lateness = spec.SLOTS_PER_EPOCH transition_to(spec, state, state.slot + shard_lateness) diff --git a/tests/core/pyspec/eth2spec/test/phase1/block_processing/test_process_shard_transition.py b/tests/core/pyspec/eth2spec/test/phase1/block_processing/test_process_shard_transition.py index 8668316863..2bb569eac2 100644 --- a/tests/core/pyspec/eth2spec/test/phase1/block_processing/test_process_shard_transition.py +++ b/tests/core/pyspec/eth2spec/test/phase1/block_processing/test_process_shard_transition.py @@ -22,7 +22,7 @@ def get_initial_env(spec, state, target_len_offset_slot): - state = transition_to_valid_shard_slot(spec, state) + transition_to_valid_shard_slot(spec, state) committee_index = spec.CommitteeIndex(0) target_shard_slot = state.slot + target_len_offset_slot - 1 shard = spec.compute_shard_from_committee_index(state, committee_index, target_shard_slot) diff --git a/tests/core/pyspec/eth2spec/test/phase1/epoch_processing/test_process_challenge_deadlines.py b/tests/core/pyspec/eth2spec/test/phase1/epoch_processing/test_process_challenge_deadlines.py index 675b0d8da6..828ace91cd 100644 --- a/tests/core/pyspec/eth2spec/test/phase1/epoch_processing/test_process_challenge_deadlines.py +++ b/tests/core/pyspec/eth2spec/test/phase1/epoch_processing/test_process_challenge_deadlines.py @@ -5,7 +5,7 @@ from eth2spec.test.helpers.attestations import ( get_valid_on_time_attestation, ) -from eth2spec.test.helpers.state import transition_to +from eth2spec.test.helpers.state import transition_to, transition_to_valid_shard_slot from eth2spec.test.context import ( PHASE0, with_all_phases_except, @@ -26,7 +26,8 @@ def run_process_challenge_deadlines(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_validator_slashed_after_chunk_challenge(spec, state): - transition_to(spec, state, state.slot + 1) + transition_to_valid_shard_slot(spec, state) + transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) diff --git a/tests/core/pyspec/eth2spec/test/phase1/epoch_processing/test_process_custody_final_updates.py b/tests/core/pyspec/eth2spec/test/phase1/epoch_processing/test_process_custody_final_updates.py index 93fea19cf2..0541411da0 100644 --- a/tests/core/pyspec/eth2spec/test/phase1/epoch_processing/test_process_custody_final_updates.py +++ b/tests/core/pyspec/eth2spec/test/phase1/epoch_processing/test_process_custody_final_updates.py @@ -10,7 +10,7 @@ from eth2spec.test.helpers.attestations import ( get_valid_on_time_attestation, ) -from eth2spec.test.helpers.state import next_epoch_via_block, transition_to +from eth2spec.test.helpers.state import next_epoch_via_block, transition_to, transition_to_valid_shard_slot from eth2spec.test.context import ( with_all_phases_except, spec_state_test, @@ -32,6 +32,8 @@ def run_process_custody_final_updates(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_validator_withdrawal_delay(spec, state): + transition_to_valid_shard_slot(spec, state) + transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 spec.initiate_validator_exit(state, 0) assert state.validators[0].withdrawable_epoch < spec.FAR_FUTURE_EPOCH @@ -43,6 +45,8 @@ def test_validator_withdrawal_delay(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_validator_withdrawal_reenable_after_custody_reveal(spec, state): + transition_to_valid_shard_slot(spec, state) + transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 spec.initiate_validator_exit(state, 0) assert state.validators[0].withdrawable_epoch < spec.FAR_FUTURE_EPOCH @@ -66,7 +70,8 @@ def test_validator_withdrawal_reenable_after_custody_reveal(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_validator_withdrawal_suspend_after_chunk_challenge(spec, state): - transition_to(spec, state, state.slot + 1) + transition_to_valid_shard_slot(spec, state) + transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) @@ -114,7 +119,8 @@ def test_validator_withdrawal_suspend_after_chunk_challenge(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_validator_withdrawal_resume_after_chunk_challenge_response(spec, state): - transition_to(spec, state, state.slot + 1) + transition_to_valid_shard_slot(spec, state) + transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) diff --git a/tests/core/pyspec/eth2spec/test/phase1/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/phase1/sanity/test_blocks.py index f69cd47935..5fe3394db0 100644 --- a/tests/core/pyspec/eth2spec/test/phase1/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/phase1/sanity/test_blocks.py @@ -105,7 +105,7 @@ def test_process_beacon_block_with_normal_shard_transition(spec, state): # skip return - state = transition_to_valid_shard_slot(spec, state) + transition_to_valid_shard_slot(spec, state) target_len_offset_slot = 1 committee_index = spec.CommitteeIndex(0) @@ -123,7 +123,7 @@ def test_process_beacon_block_with_empty_proposal_transition(spec, state): # skip return - state = transition_to_valid_shard_slot(spec, state) + transition_to_valid_shard_slot(spec, state) target_len_offset_slot = 1 committee_index = spec.CommitteeIndex(0) @@ -146,7 +146,7 @@ def test_with_shard_transition_with_custody_challenge_and_response(spec, state): # skip return - state = transition_to_valid_shard_slot(spec, state) + transition_to_valid_shard_slot(spec, state) # build shard block shard = 0 @@ -179,7 +179,7 @@ def test_with_shard_transition_with_custody_challenge_and_response(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_custody_key_reveal(spec, state): - state = transition_to_valid_shard_slot(spec, state) + transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + spec.EPOCHS_PER_CUSTODY_PERIOD * spec.SLOTS_PER_EPOCH) block = build_empty_block(spec, state, slot=state.slot + 1) @@ -192,7 +192,7 @@ def test_custody_key_reveal(spec, state): @with_all_phases_except([PHASE0]) @spec_state_test def test_early_derived_secret_reveal(spec, state): - state = transition_to_valid_shard_slot(spec, state) + transition_to_valid_shard_slot(spec, state) block = build_empty_block(spec, state, slot=state.slot + 1) early_derived_secret_reveal = get_valid_early_derived_secret_reveal(spec, state) block.body.early_derived_secret_reveals = [early_derived_secret_reveal] @@ -208,7 +208,7 @@ def test_custody_slashing(spec, state): # skip return - state = transition_to_valid_shard_slot(spec, state) + transition_to_valid_shard_slot(spec, state) # Build shard block shard = 0 diff --git a/tests/core/pyspec/eth2spec/test/phase1/sanity/test_shard_blocks.py b/tests/core/pyspec/eth2spec/test/phase1/sanity/test_shard_blocks.py index 041b882abf..440d0dd8d8 100644 --- a/tests/core/pyspec/eth2spec/test/phase1/sanity/test_shard_blocks.py +++ b/tests/core/pyspec/eth2spec/test/phase1/sanity/test_shard_blocks.py @@ -51,10 +51,12 @@ def test_valid_shard_block(spec, state): # skip return - beacon_state = transition_to_valid_shard_slot(spec, state) + beacon_state = state.copy() + transition_to_valid_shard_slot(spec, beacon_state) + shard = 0 shard_state = beacon_state.shard_states[shard] - signed_shard_block = build_shard_block(spec, beacon_state, shard, slot=beacon_state.slot, signed=True) + signed_shard_block = build_shard_block(spec, state, shard, slot=beacon_state.slot, signed=True) yield from run_shard_blocks(spec, shard_state, signed_shard_block, beacon_state) @@ -71,7 +73,9 @@ def test_invalid_shard_parent_root(spec, state): # skip return - beacon_state = transition_to_valid_shard_slot(spec, state) + beacon_state = state.copy() + transition_to_valid_shard_slot(spec, beacon_state) + shard = 0 shard_state = beacon_state.shard_states[shard] signed_shard_block = build_shard_block(spec, beacon_state, shard, slot=beacon_state.slot, signed=True) @@ -88,7 +92,8 @@ def test_invalid_beacon_parent_root(spec, state): # skip return - beacon_state = transition_to_valid_shard_slot(spec, state) + beacon_state = state.copy() + transition_to_valid_shard_slot(spec, beacon_state) shard = 0 shard_state = beacon_state.shard_states[shard] signed_shard_block = build_shard_block(spec, beacon_state, shard, slot=beacon_state.slot, signed=True) @@ -105,7 +110,8 @@ def test_invalid_slot(spec, state): # skip return - beacon_state = transition_to_valid_shard_slot(spec, state) + beacon_state = state.copy() + transition_to_valid_shard_slot(spec, beacon_state) shard = 0 shard_state = beacon_state.shard_states[shard] signed_shard_block = build_shard_block(spec, beacon_state, shard, slot=beacon_state.slot, signed=True) @@ -123,7 +129,8 @@ def test_invalid_proposer_index(spec, state): # skip return - beacon_state = transition_to_valid_shard_slot(spec, state) + beacon_state = state.copy() + transition_to_valid_shard_slot(spec, beacon_state) shard = 0 shard_state = beacon_state.shard_states[shard] signed_shard_block = build_shard_block(spec, beacon_state, shard, slot=beacon_state.slot, signed=True) @@ -147,7 +154,8 @@ def test_out_of_bound_offset(spec, state): # skip return - beacon_state = transition_to_valid_shard_slot(spec, state) + beacon_state = state.copy() + transition_to_valid_shard_slot(spec, beacon_state) shard = 0 slot = ( beacon_state.shard_states[shard].slot @@ -170,7 +178,8 @@ def test_invalid_offset(spec, state): # skip return - beacon_state = transition_to_valid_shard_slot(spec, state) + beacon_state = state.copy() + transition_to_valid_shard_slot(spec, beacon_state) # 4 is not in `SHARD_BLOCK_OFFSETS` shard = 0 slot = beacon_state.shard_states[shard].slot + 4 @@ -191,7 +200,8 @@ def test_empty_block_body(spec, state): # skip return - beacon_state = transition_to_valid_shard_slot(spec, state) + beacon_state = state.copy() + transition_to_valid_shard_slot(spec, beacon_state) shard = 0 shard_state = beacon_state.shard_states[shard] signed_shard_block = build_shard_block(spec, beacon_state, shard, slot=beacon_state.slot, body=b'', signed=True) @@ -212,7 +222,8 @@ def test_invalid_signature(spec, state): # skip return - beacon_state = transition_to_valid_shard_slot(spec, state) + beacon_state = state.copy() + transition_to_valid_shard_slot(spec, beacon_state) shard = 0 shard_state = beacon_state.shard_states[shard] signed_shard_block = build_shard_block(spec, beacon_state, shard, slot=beacon_state.slot, signed=False) @@ -233,7 +244,8 @@ def test_max_offset(spec, state): # skip return - beacon_state = transition_to_valid_shard_slot(spec, state) + beacon_state = state.copy() + transition_to_valid_shard_slot(spec, beacon_state) shard = 0 slot = beacon_state.shard_states[shard].slot + spec.SHARD_BLOCK_OFFSETS[spec.MAX_SHARD_BLOCKS_PER_ATTESTATION - 1] transition_to(spec, beacon_state, slot) @@ -253,7 +265,8 @@ def test_pending_shard_parent_block(spec, state): return # Block N - beacon_state = transition_to_valid_shard_slot(spec, state) + beacon_state = state.copy() + transition_to_valid_shard_slot(spec, beacon_state) shard = 0 shard_state = beacon_state.shard_states[shard] signed_shard_block_1 = build_shard_block(spec, beacon_state, shard, slot=beacon_state.slot, signed=True) From 8fb96f18608b4827a72495e7fba33b20d5ce92b7 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Fri, 17 Jul 2020 00:10:04 +0800 Subject: [PATCH 2/6] Enable more phase 0 tests to be compatible with phase 1 --- .../test_process_attester_slashing.py | 33 +++++++++---------- .../test_process_rewards_and_penalties.py | 7 ++-- .../test/phase0/sanity/test_blocks.py | 10 +++--- .../pyspec/eth2spec/test/test_finality.py | 4 +-- 4 files changed, 26 insertions(+), 28 deletions(-) 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 192e0390d1..5f26ba5f78 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 @@ -1,6 +1,5 @@ from eth2spec.test.context import ( - PHASE0, - spec_state_test, expect_assertion_error, always_bls, with_all_phases, with_phases + spec_state_test, expect_assertion_error, always_bls, with_all_phases ) from eth2spec.test.helpers.attestations import sign_indexed_attestation from eth2spec.test.helpers.attester_slashings import get_valid_attester_slashing, \ @@ -197,7 +196,7 @@ def test_participants_already_slashed(spec, state): # Some of the following tests are phase0 only: phase 1 lists participants with bitfields instead of index list. -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @always_bls def test_att1_high_index(spec, state): @@ -210,7 +209,7 @@ def test_att1_high_index(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @always_bls def test_att2_high_index(spec, state): @@ -223,7 +222,7 @@ def test_att2_high_index(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @always_bls def test_att1_empty_indices(spec, state): @@ -235,7 +234,7 @@ def test_att1_empty_indices(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @always_bls def test_att2_empty_indices(spec, state): @@ -247,7 +246,7 @@ def test_att2_empty_indices(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @always_bls def test_all_empty_indices(spec, state): @@ -262,7 +261,7 @@ def test_all_empty_indices(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @always_bls def test_att1_bad_extra_index(spec, state): @@ -278,7 +277,7 @@ def test_att1_bad_extra_index(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @always_bls def test_att1_bad_replaced_index(spec, state): @@ -294,7 +293,7 @@ def test_att1_bad_replaced_index(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @always_bls def test_att2_bad_extra_index(spec, state): @@ -310,7 +309,7 @@ def test_att2_bad_extra_index(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @always_bls def test_att2_bad_replaced_index(spec, state): @@ -326,7 +325,7 @@ def test_att2_bad_replaced_index(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @always_bls def test_att1_duplicate_index_normal_signed(spec, state): @@ -346,7 +345,7 @@ def test_att1_duplicate_index_normal_signed(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @always_bls def test_att2_duplicate_index_normal_signed(spec, state): @@ -366,7 +365,7 @@ def test_att2_duplicate_index_normal_signed(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @always_bls def test_att1_duplicate_index_double_signed(spec, state): @@ -381,7 +380,7 @@ def test_att1_duplicate_index_double_signed(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @always_bls def test_att2_duplicate_index_double_signed(spec, state): @@ -396,7 +395,7 @@ def test_att2_duplicate_index_double_signed(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test def test_unsorted_att_1(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) @@ -409,7 +408,7 @@ def test_unsorted_att_1(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test def test_unsorted_att_2(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=False) diff --git a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_rewards_and_penalties.py b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_rewards_and_penalties.py index 72bdd3e92a..0137ddca42 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_rewards_and_penalties.py +++ b/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_rewards_and_penalties.py @@ -1,7 +1,6 @@ from eth2spec.test.context import ( - PHASE0, spec_state_test, spec_test, - with_all_phases, with_phases, single_phase, + with_all_phases, single_phase, with_custom_state, zero_activation_threshold, misc_balances, low_single_balance, @@ -25,7 +24,7 @@ def run_process_rewards_and_penalties(spec, state): yield from run_epoch_processing_with(spec, state, 'process_rewards_and_penalties') -@with_phases([PHASE0]) +@with_all_phases @spec_state_test def test_genesis_epoch_no_attestations_no_penalties(spec, state): pre_state = state.copy() @@ -38,7 +37,7 @@ def test_genesis_epoch_no_attestations_no_penalties(spec, state): assert state.balances[index] == pre_state.balances[index] -@with_phases([PHASE0]) +@with_all_phases @spec_state_test def test_genesis_epoch_full_attestations_no_rewards(spec, state): attestations = [] 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 c3b1dceed8..6dffcdaba1 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py @@ -484,7 +484,7 @@ def test_duplicate_attester_slashing(spec, state): # All AttesterSlashing tests should be adopted for Phase 1 but helper support is not yet there -@with_phases([PHASE0]) +@with_all_phases @spec_state_test def test_multiple_attester_slashings_no_overlap(spec, state): # Skip test if config cannot handle multiple AttesterSlashings per block @@ -525,7 +525,7 @@ def test_multiple_attester_slashings_no_overlap(spec, state): check_attester_slashing_effect(spec, pre_state, state, full_indices) -@with_phases([PHASE0]) +@with_all_phases @spec_state_test def test_multiple_attester_slashings_partial_overlap(spec, state): # Skip test if config cannot handle multiple AttesterSlashings per block @@ -740,7 +740,7 @@ def create_signed_exit(index): # exceeding the minimal-config randao mixes memory size. # Applies to all voluntary-exit sanity block tests. -@with_phases([PHASE0]) +@with_all_phases @spec_state_test def test_voluntary_exit(spec, state): validator_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -768,7 +768,7 @@ def test_voluntary_exit(spec, state): assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH -@with_phases([PHASE0]) +@with_all_phases @spec_state_test def test_double_validator_exit_same_block(spec, state): validator_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -789,7 +789,7 @@ def test_double_validator_exit_same_block(spec, state): yield 'post', None -@with_phases([PHASE0]) +@with_all_phases @spec_state_test def test_multiple_different_validator_exits_same_block(spec, state): validator_indices = [ diff --git a/tests/core/pyspec/eth2spec/test/test_finality.py b/tests/core/pyspec/eth2spec/test/test_finality.py index adbadcdf2c..106c7ab02a 100644 --- a/tests/core/pyspec/eth2spec/test/test_finality.py +++ b/tests/core/pyspec/eth2spec/test/test_finality.py @@ -1,4 +1,4 @@ -from eth2spec.test.context import PHASE0, spec_state_test, never_bls, with_all_phases, with_phases +from eth2spec.test.context import spec_state_test, never_bls, with_all_phases from eth2spec.test.helpers.state import next_epoch_via_block from eth2spec.test.helpers.attestations import next_epoch_with_attestations @@ -28,7 +28,7 @@ def check_finality(spec, assert state.finalized_checkpoint == prev_state.finalized_checkpoint -@with_phases([PHASE0]) +@with_all_phases @spec_state_test @never_bls def test_finality_no_updates_at_genesis(spec, state): From 0b81c967fa1bd0adedcb4f1e367eb4a6bc73165c Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Fri, 17 Jul 2020 00:18:44 +0800 Subject: [PATCH 3/6] Add notes --- specs/phase1/beacon-chain.md | 2 ++ specs/phase1/validator.md | 1 + tests/core/pyspec/eth2spec/test/helpers/attestations.py | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/specs/phase1/beacon-chain.md b/specs/phase1/beacon-chain.md index 16a0ea4cbc..759687a2f1 100644 --- a/specs/phase1/beacon-chain.md +++ b/specs/phase1/beacon-chain.md @@ -772,6 +772,7 @@ def validate_attestation(state: BeaconState, attestation: Attestation) -> None: # Correct shard number shard = compute_shard_from_committee_index(state, data.index, data.slot) assert data.shard == shard + # NOTE: We currently set `PHASE_1_FORK_SLOT` to `GENESIS_SLOT` for test vectors. if data.slot == PHASE_1_FORK_SLOT: assert data.shard_transition_root == hash_tree_root(ShardTransition()) else: @@ -979,6 +980,7 @@ def verify_empty_shard_transition(state: BeaconState, shard_transitions: Sequenc def process_shard_transitions(state: BeaconState, shard_transitions: Sequence[ShardTransition], attestations: Sequence[Attestation]) -> None: + # NOTE: We currently set `PHASE_1_FORK_SLOT` to `GENESIS_SLOT` for test vectors. if compute_previous_slot(state.slot) != PHASE_1_FORK_SLOT: # Process crosslinks process_crosslinks(state, shard_transitions, attestations) diff --git a/specs/phase1/validator.md b/specs/phase1/validator.md index 7f5313554b..7e9cddd060 100644 --- a/specs/phase1/validator.md +++ b/specs/phase1/validator.md @@ -310,6 +310,7 @@ def get_shard_transition_fields( def get_shard_transition(beacon_state: BeaconState, shard: Shard, shard_blocks: Sequence[SignedShardBlock]) -> ShardTransition: + # NOTE: We currently set `PHASE_1_FORK_SLOT` to `GENESIS_SLOT` for test vectors. if beacon_state.slot == PHASE_1_FORK_SLOT: return ShardTransition() diff --git a/tests/core/pyspec/eth2spec/test/helpers/attestations.py b/tests/core/pyspec/eth2spec/test/helpers/attestations.py index fa6a90059d..ae90fc808e 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/attestations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/attestations.py @@ -88,7 +88,7 @@ def build_attestation_data(spec, state, slot, index, shard=None, shard_transitio data.shard_transition_root = shard_transition.hash_tree_root() else: if on_time: - if data.slot == spec.PHASE_1_FORK_SLOT: + if data.slot == spec.GENESIS_SLOT: data.shard_head_root = spec.Root() data.shard_transition_root = spec.ShardTransition().hash_tree_root() else: From 74aa027e38f4822274ff65a07e2588e1409356ad Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Mon, 20 Jul 2020 16:37:43 +0800 Subject: [PATCH 4/6] Apply suggestions from @mkalinin Co-authored-by: Mikhail Kalinin --- specs/phase1/beacon-chain.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specs/phase1/beacon-chain.md b/specs/phase1/beacon-chain.md index 759687a2f1..4fe0316f33 100644 --- a/specs/phase1/beacon-chain.md +++ b/specs/phase1/beacon-chain.md @@ -773,11 +773,11 @@ def validate_attestation(state: BeaconState, attestation: Attestation) -> None: shard = compute_shard_from_committee_index(state, data.index, data.slot) assert data.shard == shard # NOTE: We currently set `PHASE_1_FORK_SLOT` to `GENESIS_SLOT` for test vectors. - if data.slot == PHASE_1_FORK_SLOT: - assert data.shard_transition_root == hash_tree_root(ShardTransition()) - else: + if data.slot > PHASE_1_FORK_SLOT: # On-time attestations should have a non-empty shard transition root assert data.shard_transition_root != hash_tree_root(ShardTransition()) + else: + assert data.shard_transition_root == hash_tree_root(ShardTransition()) # Type 2: no shard transition else: # Ensure delayed attestation @@ -981,7 +981,7 @@ def process_shard_transitions(state: BeaconState, shard_transitions: Sequence[ShardTransition], attestations: Sequence[Attestation]) -> None: # NOTE: We currently set `PHASE_1_FORK_SLOT` to `GENESIS_SLOT` for test vectors. - if compute_previous_slot(state.slot) != PHASE_1_FORK_SLOT: + if compute_previous_slot(state.slot) > PHASE_1_FORK_SLOT: # Process crosslinks process_crosslinks(state, shard_transitions, attestations) From c981fc4411392de1bd31430fd937b21328a8d674 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Mon, 20 Jul 2020 16:47:21 +0800 Subject: [PATCH 5/6] Apply mkalinin's suggestion --- specs/phase1/beacon-chain.md | 4 ++-- specs/phase1/validator.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/phase1/beacon-chain.md b/specs/phase1/beacon-chain.md index 4fe0316f33..a98487fba1 100644 --- a/specs/phase1/beacon-chain.md +++ b/specs/phase1/beacon-chain.md @@ -773,7 +773,7 @@ def validate_attestation(state: BeaconState, attestation: Attestation) -> None: shard = compute_shard_from_committee_index(state, data.index, data.slot) assert data.shard == shard # NOTE: We currently set `PHASE_1_FORK_SLOT` to `GENESIS_SLOT` for test vectors. - if data.slot > PHASE_1_FORK_SLOT: + if data.slot > GENESIS_SLOT: # On-time attestations should have a non-empty shard transition root assert data.shard_transition_root != hash_tree_root(ShardTransition()) else: @@ -981,7 +981,7 @@ def process_shard_transitions(state: BeaconState, shard_transitions: Sequence[ShardTransition], attestations: Sequence[Attestation]) -> None: # NOTE: We currently set `PHASE_1_FORK_SLOT` to `GENESIS_SLOT` for test vectors. - if compute_previous_slot(state.slot) > PHASE_1_FORK_SLOT: + if compute_previous_slot(state.slot) > GENESIS_SLOT: # Process crosslinks process_crosslinks(state, shard_transitions, attestations) diff --git a/specs/phase1/validator.md b/specs/phase1/validator.md index 7e9cddd060..4eadec495e 100644 --- a/specs/phase1/validator.md +++ b/specs/phase1/validator.md @@ -311,7 +311,7 @@ def get_shard_transition(beacon_state: BeaconState, shard: Shard, shard_blocks: Sequence[SignedShardBlock]) -> ShardTransition: # NOTE: We currently set `PHASE_1_FORK_SLOT` to `GENESIS_SLOT` for test vectors. - if beacon_state.slot == PHASE_1_FORK_SLOT: + if beacon_state.slot == GENESIS_SLOT: return ShardTransition() offset_slots = compute_offset_slots( From cd8bb3d85a011225ea78043cf6f47d86ebff2358 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Wed, 22 Jul 2020 23:39:18 +0800 Subject: [PATCH 6/6] Update v-guide: Shard head root --- specs/phase1/validator.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/phase1/validator.md b/specs/phase1/validator.md index 4eadec495e..7f38c6043d 100644 --- a/specs/phase1/validator.md +++ b/specs/phase1/validator.md @@ -31,7 +31,7 @@ - [`FullAttestation`](#fullattestation) - [Timing](#timing) - [Attestation data](#attestation-data) - - [Head shard root](#head-shard-root) + - [Shard head root](#shard-head-root) - [Shard transition](#shard-transition) - [Construct attestation](#construct-attestation) - [Attestation Aggregation](#attestation-aggregation) @@ -267,9 +267,9 @@ A validator should create and broadcast the `attestation` to the associated atte *Note*: We assume that the fork choice only follows branches with valid `offset_slots` with respect to the most recent beacon state shard transition for the queried shard. -##### Head shard root +##### Shard head root -Set `attestation_data.shard_head_root = hash_tree_root(shard_head_block)`. +If `attestation_data.slot == GENESIS_SLOT`, set `attestation_data.shard_head_root = Root()`. Otherwise, set `attestation_data.shard_head_root = hash_tree_root(shard_head_block)`. ##### Shard transition