diff --git a/specs/phase1/beacon-chain.md b/specs/phase1/beacon-chain.md index 6e8700e2f..8c7af6c4f 100644 --- a/specs/phase1/beacon-chain.md +++ b/specs/phase1/beacon-chain.md @@ -54,7 +54,6 @@ - [`get_shard_proposer_index`](#get_shard_proposer_index) - [`get_committee_count_delta`](#get_committee_count_delta) - [`get_start_shard`](#get_start_shard) - - [`get_shard`](#get_shard) - [`get_latest_slot_for_shard`](#get_latest_slot_for_shard) - [`get_offset_slots`](#get_offset_slots) - [Predicates](#predicates) @@ -167,6 +166,8 @@ class AttestationData(Container): # FFG vote source: Checkpoint target: Checkpoint + # Shard vote + shard: Shard # Current-slot shard block root shard_head_root: Root # Shard transition root @@ -621,16 +622,6 @@ def get_start_shard(state: BeaconState, slot: Slot) -> Shard: ) ``` -#### `get_shard` - -```python -def get_shard(state: BeaconState, attestation: Attestation) -> Shard: - """ - Return the shard that the given ``attestation`` is attesting. - """ - return compute_shard_from_committee_index(state, attestation.data.index, attestation.data.slot) -``` - #### `get_latest_slot_for_shard` ```python @@ -775,6 +766,9 @@ def validate_attestation(state: BeaconState, attestation: Attestation) -> None: if is_on_time_attestation(state, attestation): # 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 # Type 2: no shard transition else: # Ensure delayed attestation @@ -879,7 +873,6 @@ def process_crosslink_for_shard(state: BeaconState, on_time_attestation_slot = compute_previous_slot(state.slot) committee = get_beacon_committee(state, on_time_attestation_slot, committee_index) online_indices = get_online_validator_indices(state) - shard = compute_shard_from_committee_index(state, committee_index, on_time_attestation_slot) # Loop over all shard transition roots shard_transition_roots = set([a.data.shard_transition_root for a in attestations]) @@ -905,7 +898,7 @@ def process_crosslink_for_shard(state: BeaconState, assert shard_transition_root == hash_tree_root(shard_transition) # Apply transition - apply_shard_transition(state, shard, shard_transition) + apply_shard_transition(state, attestation.data.shard, shard_transition) # Apply proposer reward and cost beacon_proposer_index = get_beacon_proposer_index(state) estimated_attester_reward = sum([get_base_reward(state, attester) for attester in transition_participants]) @@ -913,11 +906,11 @@ def process_crosslink_for_shard(state: BeaconState, increase_balance(state, beacon_proposer_index, proposer_reward) states_slots_lengths = zip( shard_transition.shard_states, - get_offset_slots(state, shard), + get_offset_slots(state, attestation.data.shard), shard_transition.shard_block_lengths ) for shard_state, slot, length in states_slots_lengths: - proposer_index = get_shard_proposer_index(state, slot, shard) + proposer_index = get_shard_proposer_index(state, slot, attestation.data.shard) decrease_balance(state, proposer_index, shard_state.gasprice * length) # Return winning transition root @@ -938,12 +931,15 @@ def process_crosslinks(state: BeaconState, committee_count = get_committee_count_at_slot(state, on_time_attestation_slot) for committee_index in map(CommitteeIndex, range(committee_count)): # All attestations in the block for this committee/shard and current slot + shard = compute_shard_from_committee_index(state, committee_index, on_time_attestation_slot) + # Since the attestations are validated, all `shard_attestations` satisfy `attestation.data.shard == shard` shard_attestations = [ attestation for attestation in attestations if is_on_time_attestation(state, attestation) and attestation.data.index == committee_index ] - shard = compute_shard_from_committee_index(state, committee_index, on_time_attestation_slot) - winning_root = process_crosslink_for_shard(state, committee_index, shard_transitions[shard], shard_attestations) + winning_root = process_crosslink_for_shard( + state, committee_index, shard_transitions[shard], shard_attestations + ) if winning_root != Root(): # Mark relevant pending attestations as creating a successful crosslink for pending_attestation in state.current_epoch_attestations: diff --git a/specs/phase1/fork-choice.md b/specs/phase1/fork-choice.md index f92640ebb..41787cfd0 100644 --- a/specs/phase1/fork-choice.md +++ b/specs/phase1/fork-choice.md @@ -39,7 +39,8 @@ class LatestMessage(object): def update_latest_messages(store: Store, attesting_indices: Sequence[ValidatorIndex], attestation: Attestation) -> None: target = attestation.data.target beacon_block_root = attestation.data.beacon_block_root - shard = get_shard(store.block_states[beacon_block_root], attestation) + # TODO: separate shard chain vote + shard = attestation.data.shard for i in attesting_indices: if i not in store.latest_messages or target.epoch > store.latest_messages[i].epoch: store.latest_messages[i] = LatestMessage( diff --git a/specs/phase1/shard-transition.md b/specs/phase1/shard-transition.md index 083064225..50694ce68 100644 --- a/specs/phase1/shard-transition.md +++ b/specs/phase1/shard-transition.md @@ -124,8 +124,7 @@ def is_valid_fraud_proof(beacon_state: BeaconState, # 2. Check if the shard state transition result is wrong between # `transition.shard_states[offset_index - 1]` to `transition.shard_states[offset_index]`. if offset_index == 0: - shard = get_shard(beacon_state, attestation) - shard_states = beacon_parent_block.body.shard_transitions[shard].shard_states + shard_states = beacon_parent_block.body.shard_transitions[attestation.data.shard].shard_states shard_state = shard_states[len(shard_states) - 1] else: shard_state = transition.shard_states[offset_index - 1] # Not doing the actual state updates here. diff --git a/tests/core/pyspec/eth2spec/test/fork_choice/test_on_attestation.py b/tests/core/pyspec/eth2spec/test/fork_choice/test_on_attestation.py index 2c50544d8..c1a5b2b33 100644 --- a/tests/core/pyspec/eth2spec/test/fork_choice/test_on_attestation.py +++ b/tests/core/pyspec/eth2spec/test/fork_choice/test_on_attestation.py @@ -26,7 +26,7 @@ def run_on_attestation(spec, state, store, attestation, valid=True): latest_message = spec.LatestMessage( epoch=attestation.data.target.epoch, root=attestation.data.beacon_block_root, - shard=spec.get_shard(state, attestation), + shard=attestation.data.shard, shard_root=attestation.data.shard_head_root, ) 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 24eeaedbe..c84f073b2 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 @@ -82,7 +82,7 @@ def apply_shard_and_beacon(spec, state, store, shard_store, shard_blocks_buffer) shard_transition=shard_transition, signed=False, ) - assert spec.get_shard(state, attestation) == shard + assert attestation.data.shard == shard beacon_block.body.attestations = [attestation] beacon_block.body.shard_transitions = shard_transitions diff --git a/tests/core/pyspec/eth2spec/test/helpers/attestations.py b/tests/core/pyspec/eth2spec/test/helpers/attestations.py index 23eba34da..52f2ca157 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/attestations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/attestations.py @@ -46,7 +46,7 @@ def run_attestation_processing(spec, state, attestation, valid=True): yield 'post', state -def build_attestation_data(spec, state, slot, index, shard_transition=None, on_time=True): +def build_attestation_data(spec, state, slot, index, shard=None, shard_transition=None, on_time=True): assert state.slot >= slot if slot == state.slot: @@ -78,13 +78,15 @@ def build_attestation_data(spec, state, slot, index, shard_transition=None, on_t ) 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 + if shard_transition is not None: lastest_shard_data_root_index = len(shard_transition.shard_data_roots) - 1 attestation_data.shard_head_root = shard_transition.shard_data_roots[lastest_shard_data_root_index] attestation_data.shard_transition_root = shard_transition.hash_tree_root() else: - # No shard transition -> no shard block - shard = spec.get_shard(state, spec.Attestation(data=attestation_data)) if on_time: shard_transition = spec.get_shard_transition(state, shard, shard_blocks=[]) lastest_shard_data_root_index = len(shard_transition.shard_data_roots) - 1