From 461cd8b5995f1ea810c74e1643542686aaea5168 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Wed, 20 Feb 2019 00:46:28 -0600 Subject: [PATCH 1/3] Rename shard_block_root -> shard_data_commitment --- specs/core/0_beacon-chain.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 7db214795..1d3ae80ef 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -362,8 +362,8 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git 'beacon_block_root': 'bytes32', # Root of the ancestor at the epoch boundary 'epoch_boundary_root': 'bytes32', - # Shard block's hash of root - 'shard_block_root': 'bytes32', + # Data from the shard since the last attestation + 'shard_data_commitment': 'bytes32', # Last crosslink 'latest_crosslink': Crosslink, # Last justified epoch in the beacon state @@ -585,7 +585,7 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git # Epoch number 'epoch': 'uint64', # Shard block root - 'shard_block_root': 'bytes32', + 'shard_data_commitment': 'bytes32', } ``` @@ -1475,7 +1475,7 @@ def get_genesis_beacon_state(genesis_validator_deposits: List[Deposit], finalized_epoch=GENESIS_EPOCH, # Recent state - latest_crosslinks=[Crosslink(epoch=GENESIS_EPOCH, shard_block_root=ZERO_HASH) for _ in range(SHARD_COUNT)], + latest_crosslinks=[Crosslink(epoch=GENESIS_EPOCH, shard_data_commitment=ZERO_HASH) for _ in range(SHARD_COUNT)], latest_block_roots=[ZERO_HASH for _ in range(LATEST_BLOCK_ROOTS_LENGTH)], latest_active_index_roots=[ZERO_HASH for _ in range(LATEST_ACTIVE_INDEX_ROOTS_LENGTH)], latest_slashed_balances=[0 for _ in range(LATEST_SLASHED_EXIT_LENGTH)], @@ -1674,7 +1674,7 @@ For each `attestation` in `block.body.attestations`: * Verify that `attestation.data.slot <= state.slot - MIN_ATTESTATION_INCLUSION_DELAY < attestation.data.slot + SLOTS_PER_EPOCH`. * Verify that `attestation.data.justified_epoch` is equal to `state.justified_epoch if slot_to_epoch(attestation.data.slot + 1) >= get_current_epoch(state) else state.previous_justified_epoch`. * Verify that `attestation.data.justified_block_root` is equal to `get_block_root(state, get_epoch_start_slot(attestation.data.justified_epoch))`. -* Verify that either (i) `state.latest_crosslinks[attestation.data.shard] == attestation.data.latest_crosslink` or (ii) `state.latest_crosslinks[attestation.data.shard] == Crosslink(shard_block_root=attestation.data.shard_block_root, epoch=slot_to_epoch(attestation.data.slot))`. +* Verify that either (i) `state.latest_crosslinks[attestation.data.shard] == attestation.data.latest_crosslink` or (ii) `state.latest_crosslinks[attestation.data.shard] == Crosslink(shard_data_commitment=attestation.data.shard_data_commitment, epoch=slot_to_epoch(attestation.data.slot))`. * Verify bitfields and aggregate signature: ```python @@ -1707,7 +1707,7 @@ For each `attestation` in `block.body.attestations`: ) ``` -* [TO BE REMOVED IN PHASE 1] Verify that `attestation.data.shard_block_root == ZERO_HASH`. +* [TO BE REMOVED IN PHASE 1] Verify that `attestation.data.shard_data_commitment == ZERO_HASH`. * Append `PendingAttestation(data=attestation.data, aggregation_bitfield=attestation.aggregation_bitfield, custody_bitfield=attestation.custody_bitfield, inclusion_slot=state.slot)` to `state.latest_attestations`. ##### Deposits @@ -1815,10 +1815,10 @@ The steps below happen when `(state.slot + 1) % SLOTS_PER_EPOCH == 0`. For every `slot in range(get_epoch_start_slot(previous_epoch), get_epoch_start_slot(next_epoch))`, let `crosslink_committees_at_slot = get_crosslink_committees_at_slot(state, slot)`. For every `(crosslink_committee, shard)` in `crosslink_committees_at_slot`, compute: -* Let `shard_block_root` be `state.latest_crosslinks[shard].shard_block_root` -* Let `attesting_validator_indices(crosslink_committee, shard_block_root)` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in current_epoch_attestations + previous_epoch_attestations if a.data.shard == shard and a.data.shard_block_root == shard_block_root]`. -* Let `winning_root(crosslink_committee)` be equal to the value of `shard_block_root` such that `get_total_balance(state, attesting_validator_indices(crosslink_committee, shard_block_root))` is maximized (ties broken by favoring lower `shard_block_root` values). -* Let `attesting_validators(crosslink_committee)` be equal to `attesting_validator_indices(crosslink_committee, winning_root(crosslink_committee))` for convenience. +* Let `shard_data_commitment` be `state.latest_crosslinks[shard].shard_data_commitment` +* Let `attesting_validator_indices(crosslink_committee, shard_data_commitment)` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in current_epoch_attestations + previous_epoch_attestations if a.data.shard == shard and a.data.shard_data_commitment == shard_data_commitment]`. +* Let `winning_data_commitment(crosslink_committee)` be equal to the value of `shard_data_commitment` such that `get_total_balance(state, attesting_validator_indices(crosslink_committee, shard_data_commitment))` is maximized (ties broken by favoring lower `shard_data_commitment` values). +* Let `attesting_validators(crosslink_committee)` be equal to `attesting_validator_indices(crosslink_committee, winning_data_commitment(crosslink_committee))` for convenience. * Let `total_attesting_balance(crosslink_committee) = get_total_balance(state, attesting_validators(crosslink_committee))`. Define the following helpers to process attestation inclusion rewards and inclusion distance reward/penalty. For every attestation `a` in `previous_epoch_attestations`: @@ -1858,7 +1858,7 @@ Finally, update the following: For every `slot in range(get_epoch_start_slot(previous_epoch), get_epoch_start_slot(next_epoch))`, let `crosslink_committees_at_slot = get_crosslink_committees_at_slot(state, slot)`. For every `(crosslink_committee, shard)` in `crosslink_committees_at_slot`, compute: -* Set `state.latest_crosslinks[shard] = Crosslink(epoch=slot_to_epoch(slot), shard_block_root=winning_root(crosslink_committee))` if `3 * total_attesting_balance(crosslink_committee) >= 2 * get_total_balance(crosslink_committee)`. +* Set `state.latest_crosslinks[shard] = Crosslink(epoch=slot_to_epoch(slot), shard_data_commitment=winning_data_commitment(crosslink_committee))` if `3 * total_attesting_balance(crosslink_committee) >= 2 * get_total_balance(crosslink_committee)`. #### Rewards and penalties From f77b9e241435e7b67a81cf5feabe595265d5f4c8 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Fri, 22 Feb 2019 00:21:56 -0600 Subject: [PATCH 2/3] Changed name to crosslink data commitment --- specs/core/0_beacon-chain.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 1d3ae80ef..fcca0d47e 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -363,7 +363,7 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git # Root of the ancestor at the epoch boundary 'epoch_boundary_root': 'bytes32', # Data from the shard since the last attestation - 'shard_data_commitment': 'bytes32', + 'crosslink_data_root': 'bytes32', # Last crosslink 'latest_crosslink': Crosslink, # Last justified epoch in the beacon state @@ -584,8 +584,8 @@ The following data structures are defined as [SimpleSerialize (SSZ)](https://git { # Epoch number 'epoch': 'uint64', - # Shard block root - 'shard_data_commitment': 'bytes32', + # Shard data since the previous crosslink + 'crosslink_data_root': 'bytes32', } ``` @@ -1475,7 +1475,7 @@ def get_genesis_beacon_state(genesis_validator_deposits: List[Deposit], finalized_epoch=GENESIS_EPOCH, # Recent state - latest_crosslinks=[Crosslink(epoch=GENESIS_EPOCH, shard_data_commitment=ZERO_HASH) for _ in range(SHARD_COUNT)], + latest_crosslinks=[Crosslink(epoch=GENESIS_EPOCH, crosslink_data_root=ZERO_HASH) for _ in range(SHARD_COUNT)], latest_block_roots=[ZERO_HASH for _ in range(LATEST_BLOCK_ROOTS_LENGTH)], latest_active_index_roots=[ZERO_HASH for _ in range(LATEST_ACTIVE_INDEX_ROOTS_LENGTH)], latest_slashed_balances=[0 for _ in range(LATEST_SLASHED_EXIT_LENGTH)], @@ -1674,7 +1674,7 @@ For each `attestation` in `block.body.attestations`: * Verify that `attestation.data.slot <= state.slot - MIN_ATTESTATION_INCLUSION_DELAY < attestation.data.slot + SLOTS_PER_EPOCH`. * Verify that `attestation.data.justified_epoch` is equal to `state.justified_epoch if slot_to_epoch(attestation.data.slot + 1) >= get_current_epoch(state) else state.previous_justified_epoch`. * Verify that `attestation.data.justified_block_root` is equal to `get_block_root(state, get_epoch_start_slot(attestation.data.justified_epoch))`. -* Verify that either (i) `state.latest_crosslinks[attestation.data.shard] == attestation.data.latest_crosslink` or (ii) `state.latest_crosslinks[attestation.data.shard] == Crosslink(shard_data_commitment=attestation.data.shard_data_commitment, epoch=slot_to_epoch(attestation.data.slot))`. +* Verify that either (i) `state.latest_crosslinks[attestation.data.shard] == attestation.data.latest_crosslink` or (ii) `state.latest_crosslinks[attestation.data.shard] == Crosslink(crosslink_data_root=attestation.data.crosslink_data_root, epoch=slot_to_epoch(attestation.data.slot))`. * Verify bitfields and aggregate signature: ```python @@ -1707,7 +1707,7 @@ For each `attestation` in `block.body.attestations`: ) ``` -* [TO BE REMOVED IN PHASE 1] Verify that `attestation.data.shard_data_commitment == ZERO_HASH`. +* [TO BE REMOVED IN PHASE 1] Verify that `attestation.data.crosslink_data_root == ZERO_HASH`. * Append `PendingAttestation(data=attestation.data, aggregation_bitfield=attestation.aggregation_bitfield, custody_bitfield=attestation.custody_bitfield, inclusion_slot=state.slot)` to `state.latest_attestations`. ##### Deposits @@ -1815,10 +1815,10 @@ The steps below happen when `(state.slot + 1) % SLOTS_PER_EPOCH == 0`. For every `slot in range(get_epoch_start_slot(previous_epoch), get_epoch_start_slot(next_epoch))`, let `crosslink_committees_at_slot = get_crosslink_committees_at_slot(state, slot)`. For every `(crosslink_committee, shard)` in `crosslink_committees_at_slot`, compute: -* Let `shard_data_commitment` be `state.latest_crosslinks[shard].shard_data_commitment` -* Let `attesting_validator_indices(crosslink_committee, shard_data_commitment)` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in current_epoch_attestations + previous_epoch_attestations if a.data.shard == shard and a.data.shard_data_commitment == shard_data_commitment]`. -* Let `winning_data_commitment(crosslink_committee)` be equal to the value of `shard_data_commitment` such that `get_total_balance(state, attesting_validator_indices(crosslink_committee, shard_data_commitment))` is maximized (ties broken by favoring lower `shard_data_commitment` values). -* Let `attesting_validators(crosslink_committee)` be equal to `attesting_validator_indices(crosslink_committee, winning_data_commitment(crosslink_committee))` for convenience. +* Let `crosslink_data_root` be `state.latest_crosslinks[shard].crosslink_data_root` +* Let `attesting_validator_indices(crosslink_committee, crosslink_data_root)` be the union of the [validator](#dfn-validator) index sets given by `[get_attestation_participants(state, a.data, a.aggregation_bitfield) for a in current_epoch_attestations + previous_epoch_attestations if a.data.shard == shard and a.data.crosslink_data_root == crosslink_data_root]`. +* Let `winning_root(crosslink_committee)` be equal to the value of `crosslink_data_root` such that `get_total_balance(state, attesting_validator_indices(crosslink_committee, crosslink_data_root))` is maximized (ties broken by favoring lower `crosslink_data_root` values). +* Let `attesting_validators(crosslink_committee)` be equal to `attesting_validator_indices(crosslink_committee, winning_root(crosslink_committee))` for convenience. * Let `total_attesting_balance(crosslink_committee) = get_total_balance(state, attesting_validators(crosslink_committee))`. Define the following helpers to process attestation inclusion rewards and inclusion distance reward/penalty. For every attestation `a` in `previous_epoch_attestations`: @@ -1858,7 +1858,7 @@ Finally, update the following: For every `slot in range(get_epoch_start_slot(previous_epoch), get_epoch_start_slot(next_epoch))`, let `crosslink_committees_at_slot = get_crosslink_committees_at_slot(state, slot)`. For every `(crosslink_committee, shard)` in `crosslink_committees_at_slot`, compute: -* Set `state.latest_crosslinks[shard] = Crosslink(epoch=slot_to_epoch(slot), shard_data_commitment=winning_data_commitment(crosslink_committee))` if `3 * total_attesting_balance(crosslink_committee) >= 2 * get_total_balance(crosslink_committee)`. +* Set `state.latest_crosslinks[shard] = Crosslink(epoch=slot_to_epoch(slot), crosslink_data_root=winning_root(crosslink_committee))` if `3 * total_attesting_balance(crosslink_committee) >= 2 * get_total_balance(crosslink_committee)`. #### Rewards and penalties From b89cd234f0d6f3d62edacadec8884e40f52a400c Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 22 Feb 2019 08:50:03 -0700 Subject: [PATCH 3/3] change shard_block_root to crosslink_data_root throughout --- specs/core/1_shard-data-chains.md | 19 ++++++++++--------- specs/validator/0_beacon-chain-validator.md | 6 +++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 363437ae5..48eea7d2b 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -16,10 +16,10 @@ - [Max operations per block](#max-operations-per-block) - [Signature domains](#signature-domains) - [Helper functions](#helper-functions) - - [get_split_offset](#get_split_offset) - - [get_shuffled_committee](#get_shuffled_committee) - - [get_persistent_committee](#get_persistent_committee) - - [get_shard_proposer_index](#get_shard_proposer_index) + - [`get_split_offset`](#get_split_offset) + - [`get_shuffled_committee`](#get_shuffled_committee) + - [`get_persistent_committee`](#get_persistent_committee) + - [`get_shard_proposer_index`](#get_shard_proposer_index) - [Data Structures](#data-structures) - [Shard chain blocks](#shard-chain-blocks) - [Shard block processing](#shard-block-processing) @@ -100,7 +100,7 @@ Phase 1 depends upon all of the constants defined in [Phase 0](0_beacon-chain.md ## Helper functions -#### get_split_offset +#### `get_split_offset` ````python def get_split_offset(list_size: int, chunks: int, index: int) -> int: @@ -111,7 +111,7 @@ def get_split_offset(list_size: int, chunks: int, index: int) -> int: return (len(list_size) * index) // chunks ```` -#### get_shuffled_committee +#### `get_shuffled_committee` ```python def get_shuffled_committee(state: BeaconState, @@ -130,7 +130,7 @@ def get_shuffled_committee(state: BeaconState, ] ``` -#### get_persistent_committee +#### `get_persistent_committee` ```python def get_persistent_committee(state: BeaconState, @@ -158,7 +158,8 @@ def get_persistent_committee(state: BeaconState, [i for i in later_committee if epoch % PERSISTENT_COMMITTEE_PERIOD >= get_switchover_epoch(i)] ))) ``` -#### get_shard_proposer_index + +#### `get_shard_proposer_index` ```python def get_shard_proposer_index(state: BeaconState, @@ -289,7 +290,7 @@ The `shard_chain_commitment` is only valid if it equals `compute_commitment(head ### Shard block fork choice rule -The fork choice rule for any shard is LMD GHOST using the shard chain attestations of the persistent committee and the beacon chain attestations of the crosslink committee currently assigned to that shard, but instead of being rooted in the genesis it is rooted in the block referenced in the most recent accepted crosslink (ie. `state.crosslinks[shard].shard_block_root`). Only blocks whose `beacon_chain_ref` is the block in the main beacon chain at the specified `slot` should be considered (if the beacon chain skips a slot, then the block at that slot is considered to be the block in the beacon chain at the highest slot lower than a slot). +The fork choice rule for any shard is LMD GHOST using the shard chain attestations of the persistent committee and the beacon chain attestations of the crosslink committee currently assigned to that shard, but instead of being rooted in the genesis it is rooted in the latest block referenced in the most recent accepted crosslink (ie. `state.crosslinks[shard].crosslink_data_root`). Only blocks whose `beacon_chain_ref` is the block in the main beacon chain at the specified `slot` should be considered (if the beacon chain skips a slot, then the block at that slot is considered to be the block in the beacon chain at the highest slot lower than a slot). # Updates to the beacon chain diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 6fdeafb49..15188a929 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -41,7 +41,7 @@ __NOTICE__: This document is a work-in-progress for researchers and implementers - [Shard](#shard) - [Beacon block root](#beacon-block-root) - [Epoch boundary root](#epoch-boundary-root) - - [Shard block root](#shard-block-root) + - [Crosslink data root](#crosslink-data-root) - [Latest crosslink](#latest-crosslink) - [Justified epoch](#justified-epoch) - [Justified block root](#justified-block-root) @@ -264,9 +264,9 @@ Set `attestation_data.epoch_boundary_root = hash_tree_root(epoch_boundary)` wher _Note:_ This can be looked up in the state using `get_block_root(state, get_epoch_start_slot(slot_to_epoch(head.slot)))`. -##### Shard block root +##### Crosslink data root -Set `attestation_data.shard_block_root = ZERO_HASH`. +Set `attestation_data.crosslink_data_root = ZERO_HASH`. _Note:_ This is a stub for phase 0.