diff --git a/specs/phase1/beacon-chain.md b/specs/phase1/beacon-chain.md index 5ab1fdffc..4e4778abe 100644 --- a/specs/phase1/beacon-chain.md +++ b/specs/phase1/beacon-chain.md @@ -379,7 +379,6 @@ class ShardBlockHeader(Container): class ShardState(Container): slot: Slot gasprice: Gwei - transition_digest: Bytes32 latest_block_root: Root ``` diff --git a/specs/phase1/phase1-fork.md b/specs/phase1/phase1-fork.md index e229ac9e5..496191e07 100644 --- a/specs/phase1/phase1-fork.md +++ b/specs/phase1/phase1-fork.md @@ -104,7 +104,6 @@ def upgrade_to_phase1(pre: phase0.BeaconState) -> BeaconState: ShardState( slot=pre.slot, gasprice=MIN_GASPRICE, - transition_digest=Root(), 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 e051054fe..411ad9b6b 100644 --- a/specs/phase1/shard-fork-choice.md +++ b/specs/phase1/shard-fork-choice.md @@ -124,7 +124,7 @@ def get_pending_shard_blocks(store: Store, shard_store: ShardStore) -> Sequence[ beacon_head_state = store.block_states[beacon_head_root] latest_shard_block_root = beacon_head_state.shard_states[shard].latest_block_root - shard_head_root = tget_shard_head(store, shard_store) + shard_head_root = get_shard_head(store, shard_store) root = shard_head_root shard_blocks = [] while root != latest_shard_block_root: @@ -172,7 +172,7 @@ def on_shard_block(store: Store, shard_store: ShardStore, signed_shard_block: Si assert verify_shard_block_message(beacon_parent_state, shard_parent_state, shard_block) assert verify_shard_block_signature(beacon_parent_state, signed_shard_block) - post_state = get_post_shard_state(beacon_parent_state, shard_parent_state, shard_block) + post_state = get_post_shard_state(shard_parent_state, shard_block) # Add new block to the store shard_store.blocks[hash_tree_root(shard_block)] = shard_block diff --git a/specs/phase1/shard-transition.md b/specs/phase1/shard-transition.md index ea19b813d..24c39aa3d 100644 --- a/specs/phase1/shard-transition.md +++ b/specs/phase1/shard-transition.md @@ -10,7 +10,6 @@ - [Introduction](#introduction) - [Helper functions](#helper-functions) - - [Misc](#misc) - [Shard block verification functions](#shard-block-verification-functions) - [Shard state transition](#shard-state-transition) - [Fraud proofs](#fraud-proofs) @@ -24,19 +23,6 @@ This document describes the shard transition function and fraud proofs as part o ## Helper functions -### Misc - -```python -def compute_shard_transition_digest(beacon_parent_state: BeaconState, - shard_state: ShardState, - beacon_parent_root: Root, - shard_body_root: Root) -> Bytes32: - # TODO: use SSZ hash tree root - return hash( - hash_tree_root(shard_state) + beacon_parent_root + shard_body_root - ) -``` - ### Shard block verification functions ```python @@ -77,11 +63,10 @@ def verify_shard_block_signature(beacon_state: BeaconState, ## Shard state transition ```python -def shard_state_transition(beacon_state: BeaconState, - shard_state: ShardState, +def shard_state_transition(shard_state: ShardState, block: ShardBlock) -> None: """ - Update ``shard_state`` with shard ``block`` and ``beacon_state`. + Update ``shard_state`` with shard ``block``. """ shard_state.slot = block.slot prev_gasprice = shard_state.gasprice @@ -91,25 +76,18 @@ def shard_state_transition(beacon_state: BeaconState, else: latest_block_root = hash_tree_root(block) shard_state.latest_block_root = latest_block_root - shard_state.transition_digest = compute_shard_transition_digest( - beacon_state, - shard_state, - block.beacon_parent_root, - hash_tree_root(block.body), - ) ``` We have a pure function `get_post_shard_state` for describing the fraud proof verification and honest validator behavior. ```python -def get_post_shard_state(beacon_state: BeaconState, - shard_state: ShardState, +def get_post_shard_state(shard_state: ShardState, block: ShardBlock) -> ShardState: """ A pure function that returns a new post ShardState instead of modifying the given `shard_state`. """ post_state = shard_state.copy() - shard_state_transition(beacon_state, post_state, block) + shard_state_transition(post_state, block) return post_state ``` @@ -151,8 +129,8 @@ def is_valid_fraud_proof(beacon_state: BeaconState, else: shard_state = transition.shard_states[offset_index - 1] # Not doing the actual state updates here. - shard_state = get_post_shard_state(beacon_state, shard_state, block) - if shard_state.transition_digest != transition.shard_states[offset_index].transition_digest: + shard_state = get_post_shard_state(shard_state, block) + if shard_state != transition.shard_states[offset_index]: return True return False diff --git a/specs/phase1/validator.md b/specs/phase1/validator.md index cde79535e..aef8fbb99 100644 --- a/specs/phase1/validator.md +++ b/specs/phase1/validator.md @@ -296,7 +296,7 @@ def get_shard_transition_fields( else: shard_block = SignedShardBlock(message=ShardBlock(slot=slot, shard=shard)) shard_data_roots.append(Root()) - shard_state = get_post_shard_state(beacon_state, shard_state, shard_block.message) + shard_state = get_post_shard_state(shard_state, shard_block.message) shard_states.append(shard_state) shard_block_lengths.append(len(shard_block.message.body)) @@ -419,8 +419,6 @@ If the validator is in the next light client committee, they must join the `ligh ```python def is_in_next_light_client_committee(state: BeaconState, index: ValidatorIndex) -> bool: - current_source_epoch = compute_committee_source_epoch(get_current_epoch(state), LIGHT_CLIENT_COMMITTEE_PERIOD) - next_source_epoch = current_source_epoch + LIGHT_CLIENT_COMMITTEE_PERIOD next_committee = get_light_client_committee(state, get_current_epoch(state) + LIGHT_CLIENT_COMMITTEE_PERIOD) return index in next_committee ``` @@ -578,13 +576,17 @@ Proposer and Attester slashings described in Phase 0 remain in place with the To avoid custody slashings, the attester must never sign any shard transition for which the custody bit is one. The custody bit is computed using the custody secret: ```python -def get_custody_secret(spec, state, validator_index, epoch=None): - period = spec.get_custody_period_for_validator(validator_index, epoch if epoch is not None - else spec.get_current_epoch(state)) - epoch_to_sign = spec.get_randao_epoch_for_custody_period(period, validator_index) - domain = spec.get_domain(state, spec.DOMAIN_RANDAO, epoch_to_sign) - signing_root = spec.compute_signing_root(spec.Epoch(epoch_to_sign), domain) - return bls.Sign(privkeys[validator_index], signing_root) +def get_custody_secret(state: BeaconState, + validator_index: ValidatorIndex, + privkey: int, + epoch: Epoch=None) -> BLSSignature: + if epoch is None: + epoch = get_current_epoch(state) + period = get_custody_period_for_validator(validator_index, epoch) + epoch_to_sign = get_randao_epoch_for_custody_period(period, validator_index) + domain = get_domain(state, DOMAIN_RANDAO, epoch_to_sign) + signing_root = compute_signing_root(Epoch(epoch_to_sign), domain) + return bls.Sign(privkey, signing_root) ``` Note that the valid custody secret is always the one for the **attestation target epoch**, not to be confused with the epoch in which the shard block was generated. While they are the same most of the time, getting this wrong at custody epoch boundaries would result in a custody slashing. diff --git a/tests/core/pyspec/eth2spec/test/helpers/attestations.py b/tests/core/pyspec/eth2spec/test/helpers/attestations.py index 07e227022..23eba34da 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/attestations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/attestations.py @@ -91,7 +91,7 @@ def build_attestation_data(spec, state, slot, index, shard_transition=None, on_t 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: - attestation_data.shard_head_root = state.shard_states[shard].transition_digest + attestation_data.shard_head_root = state.shard_states[shard].latest_block_root attestation_data.shard_transition_root = spec.Root() return attestation_data