From 378e1ba9a681be900e86fd87e9729c657aceb8cf Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Sat, 2 Feb 2019 02:06:53 +0800 Subject: [PATCH 1/3] Misc fixes of `get_next_epoch_crosslink_committees` --- specs/core/0_beacon-chain.md | 2 +- specs/validator/0_beacon-chain-validator.md | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index d93cb21d7..dbc8db0e9 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -833,7 +833,7 @@ def get_next_epoch_committee_count(state: BeaconState) -> int: ```python def get_crosslink_committees_at_slot(state: BeaconState, slot: SlotNumber, - registry_change=False: bool) -> List[Tuple[List[ValidatorIndex], ShardNumber]]: + registry_change: bool=False) -> List[Tuple[List[ValidatorIndex], ShardNumber]]: """ Return the list of ``(committee, shard)`` tuples for the ``slot``. diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index b01e7a3af..3df3d758d 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -345,15 +345,23 @@ Either (2) or (3) occurs if (1) fails. The choice between (2) and (3) is determi ```python def get_next_epoch_crosslink_committees(state: BeaconState, - validator_index: ValidatorIndex) -> List[Tuple[ValidatorIndex], ShardNumber]: + validator_index: ValidatorIndex) -> List[Tuple[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 registry_change 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]] + crosslink_committees = get_crosslink_committees_at_slot( + state, + slot, + registry_change=registry_change, + ) + selected_committees = [ + committee # type: Tuple[List[ValidatorIndex], ShardNumber] + for committee in crosslink_committees + if validator_index in committee[0] + ] if len(selected_committees) > 0: potential_assignments.append(selected_committees) break From d4901be1984e44a61d410bda9d4592caa25cf470 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Thu, 7 Feb 2019 11:48:36 -0700 Subject: [PATCH 2/3] get_next_epoch_committee_assignments returns slot and is_proposer --- specs/validator/0_beacon-chain-validator.md | 26 +++++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index 3df3d758d..093f29f5b 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -344,12 +344,22 @@ 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 -def get_next_epoch_crosslink_committees(state: BeaconState, - validator_index: ValidatorIndex) -> List[Tuple[List[ValidatorIndex], ShardNumber]]: +def get_next_epoch_committee_assignments( + state: BeaconState, + validator_index: ValidatorIndex) -> List[Tuple[List[ValidatorIndex], ShardNumber, SlotNumber, bool]]: + """ + Return a list of the two possible committee assignments for ``validator_index`` at the next epoch. + Possible committee ``assignment`` is of the form (List[ValidatorIndex], ShardNumber, SlotNumber, bool). + * ``assignment[0]`` is the list of validators in the committee + * ``assignment[1]`` is the shard to which the committee is assigned + * ``assignment[2]`` is the slot at which the committee is assigned + * ``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) - potential_committees = [] + potential_assignments = [] for registry_change in [False, True]: for slot in range(next_epoch_start_slot, next_epoch_start_slot + EPOCH_LENGTH): crosslink_committees = get_crosslink_committees_at_slot( @@ -363,13 +373,19 @@ def get_next_epoch_crosslink_committees(state: BeaconState, if validator_index in committee[0] ] if len(selected_committees) > 0: - potential_assignments.append(selected_committees) + assignment = selected_committees[0] + assignment += (slot,) + first_committee_at_slot = crosslink_committees[0] + is_proposer = first_committee_at_slot[slot % len(first_committee_at_slot)] == validator_index + assignment += (is_proposer,) + + potential_assignments.append(assignment) break return potential_assignments ``` -`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+). +`get_next_epoch_committee_assignments` 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 e4f5efadb79dcfe6f83b71a3bf339fd11b224f0a Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Fri, 8 Feb 2019 04:03:13 +0800 Subject: [PATCH 3/3] Fix `first_committee_at_slot` --- 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 093f29f5b..4d8d5eadf 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -368,14 +368,14 @@ def get_next_epoch_committee_assignments( registry_change=registry_change, ) selected_committees = [ - committee # type: Tuple[List[ValidatorIndex], ShardNumber] + committee # Tuple[List[ValidatorIndex], ShardNumber] for committee in crosslink_committees if validator_index in committee[0] ] if len(selected_committees) > 0: assignment = selected_committees[0] assignment += (slot,) - first_committee_at_slot = crosslink_committees[0] + first_committee_at_slot = crosslink_committees[0][0] # List[ValidatorIndex] is_proposer = first_committee_at_slot[slot % len(first_committee_at_slot)] == validator_index assignment += (is_proposer,)