From a164ad9504595d17a323ad8f4c93eaab454787c1 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 29 Jan 2019 16:29:51 -0800 Subject: [PATCH 01/13] working through future shuffling notes --- specs/core/0_beacon-chain.md | 51 +++++++++++++++++---- specs/validator/0_beacon-chain-validator.md | 44 ++++++++++++++++++ 2 files changed, 87 insertions(+), 8 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index d804a90bc..1905bcc0d 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -800,6 +800,17 @@ def get_current_epoch_committee_count(state: BeaconState) -> int: return get_epoch_committee_count(len(current_active_validators)) ``` +### `get_next_epoch_committee_count` + +```python +def get_next_epoch_committee_count(state: BeaconState) -> int: + next_active_validators = get_active_validator_indices( + state.validator_registry, + get_current_epoch(state) + 1, + ) + return get_epoch_committee_count(len(next_active_validators)) +``` + ### `get_crosslink_committees_at_slot` ```python @@ -807,24 +818,33 @@ def get_crosslink_committees_at_slot(state: BeaconState, slot: SlotNumber) -> List[Tuple[List[ValidatorIndex], ShardNumber]]: """ Returns the list of ``(committee, shard)`` tuples for the ``slot``. + + Note: Crosslink committees for a ``slot`` in the next epoch are only valid + if a validator registry change occurs at the end of the current epoch. """ epoch = slot_to_epoch(slot) current_epoch = get_current_epoch(state) previous_epoch = current_epoch - 1 if current_epoch > GENESIS_EPOCH else current_epoch next_epoch = current_epoch + 1 - assert previous_epoch <= epoch < next_epoch + assert previous_epoch <= epoch <= next_epoch - if epoch < current_epoch: + if epoch == previous_epoch: committees_per_epoch = get_previous_epoch_committee_count(state) seed = state.previous_epoch_seed shuffling_epoch = state.previous_calculation_epoch shuffling_start_shard = state.previous_epoch_start_shard - else: + elif epoch == current_epoch: committees_per_epoch = get_current_epoch_committee_count(state) seed = state.current_epoch_seed shuffling_epoch = state.current_calculation_epoch shuffling_start_shard = state.current_epoch_start_shard + elif epoch == next_epoch: + current_committees_per_epoch = get_current_epoch_committee_count(state) + committees_per_epoch = get_next_epoch_committee_count(state) + seed = state.current_epoch_seed + shuffling_epoch = generate_seed(state, next_epoch) + shuffling_start_shard = (state.current_epoch_start_shard + current_committees_per_epoch) % SHARD_COUNT shuffling = get_shuffling( seed, @@ -881,7 +901,7 @@ def get_active_index_root(state: BeaconState, """ Returns the index root at a recent ``epoch``. """ - assert get_current_epoch(state) - LATEST_INDEX_ROOTS_LENGTH < epoch <= get_current_epoch(state) + assert get_current_epoch(state) - LATEST_INDEX_ROOTS_LENGTH < epoch <= get_current_epoch(state) + ENTRY_EXIT_DELAY return state.latest_index_roots[epoch % LATEST_INDEX_ROOTS_LENGTH] ``` @@ -900,6 +920,17 @@ def generate_seed(state: BeaconState, ) ``` +### `get_beacon_proposer_from_committee` + +```python +def get_beacon_proposer_index(committee: List[ValidatorIndex], + slot: SlotNumber) -> ValidatorIndex: + """ + Returns the beacon proposer index of the ``committee`` at the ``slot``. + """ + return first_committee[slot % len(committee)] +``` + ### `get_beacon_proposer_index` ```python @@ -909,7 +940,8 @@ def get_beacon_proposer_index(state: BeaconState, Returns the beacon proposer index for the ``slot``. """ first_committee, _ = get_crosslink_committees_at_slot(state, slot)[0] - return first_committee[slot % len(first_committee)] + return get_beacon_proposer_from_committee(first_committee, slot) + ``` ### `merkle_root` @@ -1458,7 +1490,10 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], if get_effective_balance(state, validator_index) >= MAX_DEPOSIT_AMOUNT: activate_validator(state, validator_index, True) - state.latest_index_roots[GENESIS_EPOCH % LATEST_INDEX_ROOTS_LENGTH] = hash_tree_root(get_active_validator_indices(state, GENESIS_EPOCH)) + for epoch in range(GENESIS_EPOCH, GENESIS_EPOCH + ENTRY_EXIT_DELAY): + state.latest_index_roots[epoch % LATEST_INDEX_ROOTS_LENGTH] = hash_tree_root( + get_active_validator_indices(state, epoch) + ) state.current_epoch_seed = generate_seed(state, GENESIS_EPOCH) return state @@ -1869,7 +1904,7 @@ First, update the following: * Set `state.previous_calculation_epoch = state.current_calculation_epoch`. * Set `state.previous_epoch_start_shard = state.current_epoch_start_shard`. * Set `state.previous_epoch_seed = state.current_epoch_seed`. -* Set `state.latest_index_roots[next_epoch % LATEST_INDEX_ROOTS_LENGTH] = hash_tree_root(get_active_validator_indices(state, next_epoch))`. +* Set `state.latest_index_roots[current_epoch + ENTRY_EXIT_DELAY % LATEST_INDEX_ROOTS_LENGTH] = hash_tree_root(get_active_validator_indices(state, current_epoch + ENTRY_EXIT_DELAY))`. If the following are satisfied: @@ -1932,7 +1967,7 @@ and perform the following updates: If a validator registry update does _not_ happen do the following: * Let `epochs_since_last_registry_update = current_epoch - state.validator_registry_update_epoch`. -* If `epochs_since_last_registry_update` is an exact power of 2: +* If `epochs_since_last_registry_update > 1` and `epochs_since_last_registry_update` is an exact power of 2: * Set `state.current_calculation_epoch = next_epoch`. * Set `state.current_epoch_seed = generate_seed(state, state.current_calculation_epoch)` * _Note_ that `state.current_epoch_start_shard` is left unchanged. diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 83ebb5751..b4184383e 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -327,6 +327,50 @@ signed_attestation_data = bls_sign( ) ``` +## Responsibility lookahead + +It is useful for a validator to have some amount of "lookahead" on the validator's upcoming responsibilities of proposing and attesting dictated by the shuffling and slot. +The beacon chain shufflings are designed to given a minimum of 1 epoch lookahead. + +There are three possibilities for the shuffling at the next epoch: +1. The shuffling remains the same (i.e. the validator is in the same shard committee). +2. The shuffling changes due to a "validator registry change". +3. The shuffling changes due to `epochs_since_last_registry_update` being an exact power of 2 greater than 1. + +(2) and (3) result in the same validator shuffling but with (potentially) different associated shards for each committee.o + +A validator should always plan for each as a possibility unless the validator +can concretely eliminate one or two. Planning for a future shuffling involves noting +at which slot one might have to attest and propose and also which shard +one should begin syncing. + +### Shuffling remains the same + +Validator remains in the same crosslink committee for the same shard and same slot position (`slot + EPOCH_LENGTH`) and might be called upon as as proposer depending upon the committee position and slot in the next epoch. Validator can safely check using `get_beacon_proposer_index` for the slot in question at the start of the next epoch. + +In phase 1, the validator would continue syncing the committee's associated shard in case the shuffling remains the same. + +### Shuffling change due to validator registry + +A validator registry change occurs when a new block has been finalied and all expected shards have been crosslinked. _This can only occur_ when `epochs_since_last_registry_update > 1`. +A validator can use `get_crosslink_committees_at_slot` for slots in the next epoch to find the expected new crosslink committee in the event of a validator registry change at the end of the current epoch. + +In phase 1, if the validator is uncertain as to whether a validator registry change will occur at the end of the current epoch, the validator should opportunistically begin to sync the potential new shard for the next epoch to be prepared in the event of a registry change. Re-checking `get_crosslink_committees_at_slot` at the start of the next epoch will affirm or deny whether the committee did in fact update. + +### Shuffling change due to power of 2 since last change + +In the event that a validator registry change does not occur at the end of the current epoch and `epochs_since_last_registry_update > 1` and `epochs_since_last_registry_update` is an exact power of two, a reshuffling occurs but the shards remain the same. + +In phase 1, if a power of 2 since last registry update is coming up and the validator is uncertain if a registry change will occur, the validator should opportunistically begin to sync the potential new shard for the new shuffling. + +To find what the shard to attempt to sync: +* Find the new `committee` using `get_crosslink_committees_at_slot` for slots in the next epoch. +* Let `slot` the be the future slot in which the validator is a committee. +* Let `committee_slot_position` be the position of the committee within the list of committees at that slot. +* Let `shard = get_crosslink_committees_at_slot(state, slot - EPOCH_LENGTH)[committee_slot_position][1]` + +Opportunistically sync `shard` during the current epoch. The validator can check `get_crosslink_committees_at_slot` at the start of the next committee to affirm or deny whether the power of 2 committee update did occur. + ## How to avoid slashing "Slashing" is the burning of some amount of validator funds and immediate ejection from the active validator set. In Phase 0, there are two ways in which funds can be slashed -- [proposal slashing](#proposal-slashing) and [attestation slashing](#casper-slashing). Although being slashed has serious repercussions, it is simple enough to avoid being slashed all together by remaining _consistent_ with respect to the messages you have previously signed. From f701b959f3da270c72dabf5e2d44e8132d7a4e40 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 29 Jan 2019 17:21:26 -0800 Subject: [PATCH 02/13] get_crosslink_committees.. has registry change field --- specs/core/0_beacon-chain.md | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 1905bcc0d..432c292b7 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -815,7 +815,8 @@ def get_next_epoch_committee_count(state: BeaconState) -> int: ```python def get_crosslink_committees_at_slot(state: BeaconState, - slot: SlotNumber) -> List[Tuple[List[ValidatorIndex], ShardNumber]]: + slot: SlotNumber, + registry_change=False: bool) -> List[Tuple[List[ValidatorIndex], ShardNumber]]: """ Returns the list of ``(committee, shard)`` tuples for the ``slot``. @@ -842,9 +843,19 @@ def get_crosslink_committees_at_slot(state: BeaconState, elif epoch == next_epoch: current_committees_per_epoch = get_current_epoch_committee_count(state) committees_per_epoch = get_next_epoch_committee_count(state) - seed = state.current_epoch_seed - shuffling_epoch = generate_seed(state, next_epoch) - shuffling_start_shard = (state.current_epoch_start_shard + current_committees_per_epoch) % SHARD_COUNT + shuffling_epoch = next_epoch + + epochs_since_last_registry_update = current_epoch - state.validator_registry_update_epoch + if registry_change: + seed = generate_seed(state, next_epoch) + shuffling_start_shard = (state.current_epoch_start_shard + current_committees_per_epoch) % SHARD_COUNT + elif epochs_since_last_registry_update > 1 and is_power_of_two(epochs_since_last_registry_update): + seed = generate_seed(state, next_epoch) + shuffling_start_shard = state.current_epoch_start_shard + else: + seed = state.current_epoch_seed + shuffling_start_shard = state.current_epoch_start_shard + shuffling = get_shuffling( seed, @@ -901,7 +912,7 @@ def get_active_index_root(state: BeaconState, """ Returns the index root at a recent ``epoch``. """ - assert get_current_epoch(state) - LATEST_INDEX_ROOTS_LENGTH < epoch <= get_current_epoch(state) + ENTRY_EXIT_DELAY + assert get_current_epoch(state) - LATEST_INDEX_ROOTS_LENGTH + ENTRY_EXIT_DELAY < epoch <= get_current_epoch(state) + ENTRY_EXIT_DELAY return state.latest_index_roots[epoch % LATEST_INDEX_ROOTS_LENGTH] ``` @@ -1490,10 +1501,9 @@ def get_initial_beacon_state(initial_validator_deposits: List[Deposit], if get_effective_balance(state, validator_index) >= MAX_DEPOSIT_AMOUNT: activate_validator(state, validator_index, True) - for epoch in range(GENESIS_EPOCH, GENESIS_EPOCH + ENTRY_EXIT_DELAY): - state.latest_index_roots[epoch % LATEST_INDEX_ROOTS_LENGTH] = hash_tree_root( - get_active_validator_indices(state, epoch) - ) + genesis_active_index_root = hash_tree_root(get_active_validator_indices(state, GENESIS_EPOCH)) + for index in range(LATEST_INDEX_ROOTS_LENGTH): + state.latest_index_roots[index % LATEST_INDEX_ROOTS_LENGTH] = genesis_active_index_root state.current_epoch_seed = generate_seed(state, GENESIS_EPOCH) return state @@ -1904,7 +1914,6 @@ First, update the following: * Set `state.previous_calculation_epoch = state.current_calculation_epoch`. * Set `state.previous_epoch_start_shard = state.current_epoch_start_shard`. * Set `state.previous_epoch_seed = state.current_epoch_seed`. -* Set `state.latest_index_roots[current_epoch + ENTRY_EXIT_DELAY % LATEST_INDEX_ROOTS_LENGTH] = hash_tree_root(get_active_validator_indices(state, current_epoch + ENTRY_EXIT_DELAY))`. If the following are satisfied: @@ -2014,6 +2023,7 @@ def process_penalties_and_exits(state: BeaconState) -> None: #### Final updates +* Set `state.latest_index_roots[(next_epoch + ENTRY_EXIT_DELAY) % LATEST_INDEX_ROOTS_LENGTH] = hash_tree_root(get_active_validator_indices(state, next_epoch + ENTRY_EXIT_DELAY))`. * Set `state.latest_penalized_balances[(next_epoch) % LATEST_PENALIZED_EXIT_LENGTH] = state.latest_penalized_balances[current_epoch % LATEST_PENALIZED_EXIT_LENGTH]`. * Set `state.latest_randao_mixes[next_epoch % LATEST_RANDAO_MIXES_LENGTH] = get_randao_mix(state, current_epoch)`. * Remove any `attestation` in `state.latest_attestations` such that `slot_to_epoch(attestation.data.slot) < current_epoch`. From 75d1247884c3c14a2f95e14015b54ab1fdf8c642 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 29 Jan 2019 17:23:24 -0800 Subject: [PATCH 03/13] delete new proposer function --- specs/core/0_beacon-chain.md | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 432c292b7..8a63bafe0 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -931,17 +931,6 @@ def generate_seed(state: BeaconState, ) ``` -### `get_beacon_proposer_from_committee` - -```python -def get_beacon_proposer_index(committee: List[ValidatorIndex], - slot: SlotNumber) -> ValidatorIndex: - """ - Returns the beacon proposer index of the ``committee`` at the ``slot``. - """ - return first_committee[slot % len(committee)] -``` - ### `get_beacon_proposer_index` ```python @@ -951,7 +940,7 @@ def get_beacon_proposer_index(state: BeaconState, Returns the beacon proposer index for the ``slot``. """ first_committee, _ = get_crosslink_committees_at_slot(state, slot)[0] - return get_beacon_proposer_from_committee(first_committee, slot) + return return first_committee[slot % len(first_committee)] ``` From 8ead89c4123526b2b12157288b99837255e2c007 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 30 Jan 2019 07:07:41 -0800 Subject: [PATCH 04/13] Add is_power_of_2 helper --- specs/core/0_beacon-chain.md | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 8a63bafe0..a3e23c299 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -72,6 +72,7 @@ - [`get_beacon_proposer_index`](#get_beacon_proposer_index) - [`merkle_root`](#merkle_root) - [`get_attestation_participants`](#get_attestation_participants) + - [`is_power_of_two`](#is_power_of_two) - [`int_to_bytes1`, `int_to_bytes2`, ...](#int_to_bytes1-int_to_bytes2-) - [`get_effective_balance`](#get_effective_balance) - [`get_fork_version`](#get_fork_version) @@ -820,8 +821,8 @@ def get_crosslink_committees_at_slot(state: BeaconState, """ Returns the list of ``(committee, shard)`` tuples for the ``slot``. - Note: Crosslink committees for a ``slot`` in the next epoch are only valid - if a validator registry change occurs at the end of the current epoch. + Note: There are two possible shufflings for crosslink committees for a + ``slot`` in the next epoch -- with and without a `registry_change` """ epoch = slot_to_epoch(slot) current_epoch = get_current_epoch(state) @@ -856,7 +857,6 @@ def get_crosslink_committees_at_slot(state: BeaconState, seed = state.current_epoch_seed shuffling_start_shard = state.current_epoch_start_shard - shuffling = get_shuffling( seed, state.validator_registry, @@ -983,6 +983,19 @@ def get_attestation_participants(state: BeaconState, return participants ``` +### `is_power_of_two` + +``` +def is_power_of_two(value: int) -> bool: + """ + Check if ``value`` is a power of two integer. + """ + if value == 0: + return False + else: + return 2**int(math.log2(value)) == value +``` + ### `int_to_bytes1`, `int_to_bytes2`, ... `int_to_bytes1(x): return x.to_bytes(1, 'big')`, `int_to_bytes2(x): return x.to_bytes(2, 'big')`, and so on for all integers, particularly 1, 2, 3, 4, 8, 32, 48, 96. @@ -1965,7 +1978,7 @@ and perform the following updates: If a validator registry update does _not_ happen do the following: * Let `epochs_since_last_registry_update = current_epoch - state.validator_registry_update_epoch`. -* If `epochs_since_last_registry_update > 1` and `epochs_since_last_registry_update` is an exact power of 2: +* If `epochs_since_last_registry_update > 1` and `is_power_of_two(epochs_since_last_registry_update)`: * Set `state.current_calculation_epoch = next_epoch`. * Set `state.current_epoch_seed = generate_seed(state, state.current_calculation_epoch)` * _Note_ that `state.current_epoch_start_shard` is left unchanged. From 75cb8b8cb95fa9e1fe8cd4c1f3e51062ceaec1c6 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 30 Jan 2019 07:35:56 -0800 Subject: [PATCH 05/13] add get_next_epoch_crosslink_committees helper in validator guide --- specs/validator/0_beacon-chain-validator.md | 56 ++++++++------------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index e9d095e91..8b59f69e3 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -331,48 +331,36 @@ signed_attestation_data = bls_sign( ## Responsibility lookahead -It is useful for a validator to have some amount of "lookahead" on the validator's upcoming responsibilities of proposing and attesting dictated by the shuffling and slot. -The beacon chain shufflings are designed to given a minimum of 1 epoch lookahead. +The beacon chain shufflings are designed to given a minimum of 1 epoch lookahead on the validator's upcoming responsibilities of proposing and attesting dictated by the shuffling and slot. There are three possibilities for the shuffling at the next epoch: -1. The shuffling remains the same (i.e. the validator is in the same shard committee). -2. The shuffling changes due to a "validator registry change". -3. The shuffling changes due to `epochs_since_last_registry_update` being an exact power of 2 greater than 1. +1. The shuffling changes due to a "validator registry change". +2. The shuffling changes due to `epochs_since_last_registry_update` being an exact power of 2 greater than 1. +3. The shuffling remains the same (i.e. the validator is in the same shard committee). -(2) and (3) result in the same validator shuffling but with (potentially) different associated shards for each committee.o +Either (2) or (3) occurs if (1) fails. The choice between (2) and (3) is deterministic based upon `epochs_since_last_registry_update`. -A validator should always plan for each as a possibility unless the validator -can concretely eliminate one or two. Planning for a future shuffling involves noting -at which slot one might have to attest and propose and also which shard -one should begin syncing. +`get_crosslink_committees_at_slot` is designed to be able to query slots in the next epoch. When querying slots in the next epoch there are two options -- with and without a `registry_change` -- which is the optional third parameter of the function. The following helper can be used to get the potential crosslink committees in the next epoch for a given `validator_index`. This function returns a list of 2 shard committee tuples. -### Shuffling remains the same +```python +get_next_epoch_crosslink_committees(state: BeaconState, + validator_index: ValidatorIndex) -> List[List[ValidatorIndex], ShardNumber]: + current_epoch = get_current_epoch(state) + next_epoch = current_epoch + 1 + next_epoch_start_slot = get_epoch_start_slot(next_epoch) + potential_committees = [] + for validator_registry in [False, True]: + for slot in range(next_epoch_start_slot, next_epoch_start_slot + EPOCH_LENGTH): + shard_committees = get_crosslink_committees_at_slot(state, slot, validator_registry) + selected_committees = [committee for committee in shard_committees if validator_index in committee[0]] + if len(selected_committees) > 0: + potential_assignments.append(selected_committees) -Validator remains in the same crosslink committee for the same shard and same slot position (`slot + EPOCH_LENGTH`) and might be called upon as as proposer depending upon the committee position and slot in the next epoch. Validator can safely check using `get_beacon_proposer_index` for the slot in question at the start of the next epoch. + return potential_assignments +``` -In phase 1, the validator would continue syncing the committee's associated shard in case the shuffling remains the same. +A validator should always plan for both values of `registry_change` as a possibility unless the validator can concretely eliminate one of the options. Planning for a future shuffling involves noting at which slot one might have to attest and propose and also which shard one should begin syncing (in phase 1+). -### Shuffling change due to validator registry - -A validator registry change occurs when a new block has been finalied and all expected shards have been crosslinked. _This can only occur_ when `epochs_since_last_registry_update > 1`. -A validator can use `get_crosslink_committees_at_slot` for slots in the next epoch to find the expected new crosslink committee in the event of a validator registry change at the end of the current epoch. - -In phase 1, if the validator is uncertain as to whether a validator registry change will occur at the end of the current epoch, the validator should opportunistically begin to sync the potential new shard for the next epoch to be prepared in the event of a registry change. Re-checking `get_crosslink_committees_at_slot` at the start of the next epoch will affirm or deny whether the committee did in fact update. - -### Shuffling change due to power of 2 since last change - -In the event that a validator registry change does not occur at the end of the current epoch and `epochs_since_last_registry_update > 1` and `epochs_since_last_registry_update` is an exact power of two, a reshuffling occurs but the shards remain the same. - -In phase 1, if a power of 2 since last registry update is coming up and the validator is uncertain if a registry change will occur, the validator should opportunistically begin to sync the potential new shard for the new shuffling. - -To find what the shard to attempt to sync: -* Find the new `committee` using `get_crosslink_committees_at_slot` for slots in the next epoch. -* Let `slot` the be the future slot in which the validator is a committee. -* Let `committee_slot_position` be the position of the committee within the list of committees at that slot. -* Let `shard = get_crosslink_committees_at_slot(state, slot - EPOCH_LENGTH)[committee_slot_position][1]` - -Opportunistically sync `shard` during the current epoch. The validator can check `get_crosslink_committees_at_slot` at the start of the next committee to affirm or deny whether the power of 2 committee update did occur. - ## How to avoid slashing "Slashing" is the burning of some amount of validator funds and immediate ejection from the active validator set. In Phase 0, there are two ways in which funds can be slashed -- [proposer slashing](#proposer-slashing) and [attester slashing](#attester-slashing). Although being slashed has serious repercussions, it is simple enough to avoid being slashed all together by remaining _consistent_ with respect to the messages a validator has previously signed. From d47f98a33faa11a89c21815c9f0146606f936315 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 30 Jan 2019 07:38:24 -0800 Subject: [PATCH 06/13] fix missing toc entry --- specs/core/0_beacon-chain.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 12f563ee7..86b9d3547 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -64,6 +64,7 @@ - [`get_shuffling`](#get_shuffling) - [`get_previous_epoch_committee_count`](#get_previous_epoch_committee_count) - [`get_current_epoch_committee_count`](#get_current_epoch_committee_count) + - [`get_next_epoch_committee_count`](#get_next_epoch_committee_count) - [`get_crosslink_committees_at_slot`](#get_crosslink_committees_at_slot) - [`get_block_root`](#get_block_root) - [`get_randao_mix`](#get_randao_mix) From 7365af59a7d3f2f0357cd6017e8fbd0868010793 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 30 Jan 2019 07:59:07 -0800 Subject: [PATCH 07/13] remove extra return --- specs/core/0_beacon-chain.md | 2 +- specs/validator/0_beacon-chain-validator.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 86b9d3547..01c90670a 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -941,7 +941,7 @@ def get_beacon_proposer_index(state: BeaconState, Returns the beacon proposer index for the ``slot``. """ first_committee, _ = get_crosslink_committees_at_slot(state, slot)[0] - return return first_committee[slot % len(first_committee)] + return first_committee[slot % len(first_committee)] ``` diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 8b59f69e3..7187407bc 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -344,7 +344,7 @@ Either (2) or (3) occurs if (1) fails. The choice between (2) and (3) is determi ```python get_next_epoch_crosslink_committees(state: BeaconState, - validator_index: ValidatorIndex) -> List[List[ValidatorIndex], ShardNumber]: + validator_index: ValidatorIndex) -> List[Tuple[ValidatorIndex], ShardNumber]: current_epoch = get_current_epoch(state) next_epoch = current_epoch + 1 next_epoch_start_slot = get_epoch_start_slot(next_epoch) From f0eeb71945c7b757cc81350932cf84d36b137e77 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 30 Jan 2019 08:00:48 -0800 Subject: [PATCH 08/13] fix fomratting --- specs/validator/0_beacon-chain-validator.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 7187407bc..fd6f69d6f 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -343,8 +343,8 @@ Either (2) or (3) occurs if (1) fails. The choice between (2) and (3) is determi `get_crosslink_committees_at_slot` is designed to be able to query slots in the next epoch. When querying slots in the next epoch there are two options -- with and without a `registry_change` -- which is the optional third parameter of the function. The following helper can be used to get the potential crosslink committees in the next epoch for a given `validator_index`. This function returns a list of 2 shard committee tuples. ```python -get_next_epoch_crosslink_committees(state: BeaconState, - validator_index: ValidatorIndex) -> List[Tuple[ValidatorIndex], ShardNumber]: +def get_next_epoch_crosslink_committees(state: BeaconState, + validator_index: ValidatorIndex) -> List[Tuple[ValidatorIndex], ShardNumber]: current_epoch = get_current_epoch(state) next_epoch = current_epoch + 1 next_epoch_start_slot = get_epoch_start_slot(next_epoch) From 8e50297543e6d7885162881f71bd761a01673086 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 30 Jan 2019 08:02:23 -0800 Subject: [PATCH 09/13] add break condition --- specs/validator/0_beacon-chain-validator.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index fd6f69d6f..9edfa4ba2 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -355,6 +355,7 @@ def get_next_epoch_crosslink_committees(state: BeaconState, selected_committees = [committee for committee in shard_committees if validator_index in committee[0]] if len(selected_committees) > 0: potential_assignments.append(selected_committees) + break return potential_assignments ``` From 8869dfff361307e194f540f981bd462a1a4c240b Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 30 Jan 2019 08:03:58 -0800 Subject: [PATCH 10/13] fix toc in validator g uide --- specs/validator/0_beacon-chain-validator.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 9edfa4ba2..36f26fea6 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -50,6 +50,7 @@ __NOTICE__: This document is a work-in-progress for researchers and implementers - [Participation bitfield](#participation-bitfield) - [Custody bitfield](#custody-bitfield) - [Aggregate signature](#aggregate-signature) + - [Responsibility lookahead](#responsibility-lookahead) - [How to avoid slashing](#how-to-avoid-slashing) - [Proposer slashing](#proposer-slashing) - [Attester slashing](#attester-slashing) From 3f836cad5f580d370c79ad9c3dfe398cca7d2e4a Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 30 Jan 2019 08:05:30 -0800 Subject: [PATCH 11/13] add extra note --- specs/validator/0_beacon-chain-validator.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 36f26fea6..0d3854e8f 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -361,7 +361,7 @@ def get_next_epoch_crosslink_committees(state: BeaconState, return potential_assignments ``` -A validator should always plan for both values of `registry_change` as a possibility unless the validator can concretely eliminate one of the options. Planning for a future shuffling involves noting at which slot one might have to attest and propose and also which shard one should begin syncing (in phase 1+). +`get_next_epoch_crosslink_committees` should be called at the beginning of each epoch to plan for the next epoch. A validator should always plan for both values of `registry_change` as a possibility unless the validator can concretely eliminate one of the options. Planning for a future shuffling involves noting at which slot one might have to attest and propose and also which shard one should begin syncing (in phase 1+). ## How to avoid slashing From 679421e48931d1fe252937831b3ab576490cd3fe Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Wed, 30 Jan 2019 12:46:03 -0800 Subject: [PATCH 12/13] Update specs/core/0_beacon-chain.md Co-Authored-By: djrtwo --- specs/core/0_beacon-chain.md | 1 - 1 file changed, 1 deletion(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 0b3a28d7a..418789999 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -957,7 +957,6 @@ def get_beacon_proposer_index(state: BeaconState, """ first_committee, _ = get_crosslink_committees_at_slot(state, slot)[0] return first_committee[slot % len(first_committee)] - ``` ### `merkle_root` From 8cfe3c3133e9dc4e071602a76cc28e7188167a9e Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 30 Jan 2019 17:24:27 -0800 Subject: [PATCH 13/13] typo --- specs/validator/0_beacon-chain-validator.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index d30fe3116..b01e7a3af 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -332,7 +332,7 @@ signed_attestation_data = bls_sign( ## Responsibility lookahead -The beacon chain shufflings are designed to given a minimum of 1 epoch lookahead on the validator's upcoming responsibilities of proposing and attesting dictated by the shuffling and slot. +The beacon chain shufflings are designed to provide a minimum of 1 epoch lookahead on the validator's upcoming responsibilities of proposing and attesting dictated by the shuffling and slot. There are three possibilities for the shuffling at the next epoch: 1. The shuffling changes due to a "validator registry change".