From 2bd6057c127273baa77e126ee647117d430bdfed Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 21 Feb 2019 16:53:52 -0700 Subject: [PATCH 1/5] make getting assignments more generic --- specs/validator/0_beacon-chain-validator.md | 46 ++++++++++++--------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 6fdeafb49..21577c610 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -50,7 +50,8 @@ __NOTICE__: This document is a work-in-progress for researchers and implementers - [Aggregation bitfield](#aggregation-bitfield) - [Custody bitfield](#custody-bitfield) - [Aggregate signature](#aggregate-signature) - - [Responsibility lookahead](#responsibility-lookahead) + - [Validator assigments](#validator-assignments) + - [Lookahead](#lookahead) - [How to avoid slashing](#how-to-avoid-slashing) - [Proposer slashing](#proposer-slashing) - [Attester slashing](#attester-slashing) @@ -330,26 +331,18 @@ signed_attestation_data = bls_sign( ) ``` -## Responsibility lookahead +## Validator assignments -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". -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). - -Either (2) or (3) occurs if (1) fails. The choice between (2) and (3) is deterministic based upon `epochs_since_last_registry_update`. - -`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 committee assignments in the next epoch for a given `validator_index` and `registry_change`. +A validator can get the current and previous epoch committee assignments using the following helper via `get_committee_assignment(state, epoch, validator_index)` where `previous_epoch <= epoch <= current_epoch`. ```python -def get_next_epoch_committee_assignment( +def get_committee_assignment( state: BeaconState, + epoch: Epoch, validator_index: ValidatorIndex, - registry_change: bool) -> Tuple[List[ValidatorIndex], Shard, Slot, bool]: + registry_change: bool=False) -> Tuple[List[ValidatorIndex], Shard, Slot, bool]: """ - Return the committee assignment in the next epoch for ``validator_index`` and ``registry_change``. + Return the committee assignment in the ``epoch`` for ``validator_index`` and ``registry_change``. ``assignment`` returned is a tuple of the following form: * ``assignment[0]`` is the list of validators in the committee * ``assignment[1]`` is the shard to which the committee is assigned @@ -357,10 +350,10 @@ def get_next_epoch_committee_assignment( * ``assignment[3]`` is a bool signalling if the validator is expected to propose a beacon block at the assigned slot. """ - current_epoch = get_current_epoch(state) - next_epoch = current_epoch + 1 - next_epoch_start_slot = get_epoch_start_slot(next_epoch) - for slot in range(next_epoch_start_slot, next_epoch_start_slot + SLOTS_PER_EPOCH): + assert previous_epoch <= epoch <= next_epoch + + epoch_start_slot = get_epoch_start_slot(epoch) + for slot in range(epoch_start_slot, epoch_start_slot + SLOTS_PER_EPOCH): crosslink_committees = get_crosslink_committees_at_slot( state, slot, @@ -381,7 +374,20 @@ def get_next_epoch_committee_assignment( return assignment ``` -`get_next_epoch_committee_assignment` should be called at the start of each epoch to get the assignment for the next epoch (slots during `current_epoch + 1`). A validator should always plan for assignments from both values of `registry_change` unless the validator can concretely eliminate one of the options. Planning for future assignments involves noting at which future slot one might have to attest and propose and also which shard one should begin syncing (in phase 1+). +### Lookahead + +The beacon chain shufflings are designed to provide a minimum of 1 epoch lookahead on the validator's upcoming assignemnts 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". +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). + +Either (2) or (3) occurs if (1) fails. The choice between (2) and (3) is deterministic based upon `epochs_since_last_registry_update`. + +`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 `get_committee_assignment` helper can be used to get the potential crosslink committee assignments in the next epoch for a given `validator_index` and `registry_change`. +`get_committee_assignment` should be called at the start of each epoch to get the assignment for the next epoch (`current_epoch + 1`). A validator should always plan for assignments from both values of `registry_change` unless the validator can concretely eliminate one of the options. Planning for future assignments involves noting at which future slot one might have to attest and propose and also which shard one should begin syncing (in phase 1+). +Specifically, a validator should call both `get_committee_assignment(state, next_epoch, validator_index, registry_chang=True)` and `get_committee_assignment(state, next_epoch, validator_index, registry_change=False)` when checking for next epoch assignments. ## How to avoid slashing From f28af3f72b52baf43a9fec72038c0280c611993d Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 21 Feb 2019 16:56:43 -0700 Subject: [PATCH 2/5] Add spacing --- specs/validator/0_beacon-chain-validator.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 21577c610..74ab2e098 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -386,7 +386,9 @@ There are three possibilities for the shuffling at the next epoch: Either (2) or (3) occurs if (1) fails. The choice between (2) and (3) is deterministic based upon `epochs_since_last_registry_update`. `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 `get_committee_assignment` helper can be used to get the potential crosslink committee assignments in the next epoch for a given `validator_index` and `registry_change`. + `get_committee_assignment` should be called at the start of each epoch to get the assignment for the next epoch (`current_epoch + 1`). A validator should always plan for assignments from both values of `registry_change` unless the validator can concretely eliminate one of the options. Planning for future assignments involves noting at which future slot one might have to attest and propose and also which shard one should begin syncing (in phase 1+). + Specifically, a validator should call both `get_committee_assignment(state, next_epoch, validator_index, registry_chang=True)` and `get_committee_assignment(state, next_epoch, validator_index, registry_change=False)` when checking for next epoch assignments. ## How to avoid slashing From 8169229f5aa033a5f9d394aea463b8d5a5b49b6b Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 21 Feb 2019 16:58:58 -0700 Subject: [PATCH 3/5] clean up --- 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 74ab2e098..5d75e7142 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -385,7 +385,7 @@ There are three possibilities for the shuffling at the next epoch: Either (2) or (3) occurs if (1) fails. The choice between (2) and (3) is deterministic based upon `epochs_since_last_registry_update`. -`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 `get_committee_assignment` helper can be used to get the potential crosslink committee assignments in the next epoch for a given `validator_index` and `registry_change`. +When querying for assignments in the next epoch there are two options -- with and without a `registry_change` -- which is the optional fourth parameter of the `get_committee_assignment`. `get_committee_assignment` should be called at the start of each epoch to get the assignment for the next epoch (`current_epoch + 1`). A validator should always plan for assignments from both values of `registry_change` unless the validator can concretely eliminate one of the options. Planning for future assignments involves noting at which future slot one might have to attest and propose and also which shard one should begin syncing (in phase 1+). From 68b5fe5b9fd5576661f4874c7ba31efed44765f7 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Fri, 22 Feb 2019 08:15:40 -0700 Subject: [PATCH 4/5] small typo Co-Authored-By: djrtwo --- 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 5d75e7142..7b4404484 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -389,7 +389,7 @@ When querying for assignments in the next epoch there are two options -- with an `get_committee_assignment` should be called at the start of each epoch to get the assignment for the next epoch (`current_epoch + 1`). A validator should always plan for assignments from both values of `registry_change` unless the validator can concretely eliminate one of the options. Planning for future assignments involves noting at which future slot one might have to attest and propose and also which shard one should begin syncing (in phase 1+). -Specifically, a validator should call both `get_committee_assignment(state, next_epoch, validator_index, registry_chang=True)` and `get_committee_assignment(state, next_epoch, validator_index, registry_change=False)` when checking for next epoch assignments. +Specifically, a validator should call both `get_committee_assignment(state, next_epoch, validator_index, registry_change=True)` and `get_committee_assignment(state, next_epoch, validator_index, registry_change=False)` when checking for next epoch assignments. ## How to avoid slashing From c96f7095053bd451527df1f8405b28da5f00768c Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Sat, 23 Feb 2019 00:31:27 +0800 Subject: [PATCH 5/5] Update 0_beacon-chain-validator.md --- specs/validator/0_beacon-chain-validator.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 7b4404484..82b1827a5 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -350,6 +350,8 @@ def get_committee_assignment( * ``assignment[3]`` is a bool signalling if the validator is expected to propose a beacon block at the assigned slot. """ + previous_epoch = get_previous_epoch(state) + next_epoch = get_current_epoch(state) assert previous_epoch <= epoch <= next_epoch epoch_start_slot = get_epoch_start_slot(epoch)