From f2545318dbc394d05629c2909585fa1f62ac7979 Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Thu, 7 Feb 2019 19:27:13 +0000 Subject: [PATCH] get_crosslink_committees_at_slot updates (#95) --- beacon_chain/spec/beaconstate.nim | 1 + beacon_chain/spec/helpers.nim | 23 +++++++++++------ beacon_chain/spec/validator.nim | 42 +++++++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/beacon_chain/spec/beaconstate.nim b/beacon_chain/spec/beaconstate.nim index c4b456b1a..310220f52 100644 --- a/beacon_chain/spec/beaconstate.nim +++ b/beacon_chain/spec/beaconstate.nim @@ -217,6 +217,7 @@ func get_initial_beacon_state*( state +# https://github.com/ethereum/eth2.0-specs/blob/v0.1/specs/core/0_beacon-chain.md#get_block_root func get_block_root*(state: BeaconState, slot: uint64): Eth2Digest = doAssert state.slot <= slot + LATEST_BLOCK_ROOTS_LENGTH diff --git a/beacon_chain/spec/helpers.nim b/beacon_chain/spec/helpers.nim index fcd955df1..85fa6cc8d 100644 --- a/beacon_chain/spec/helpers.nim +++ b/beacon_chain/spec/helpers.nim @@ -135,14 +135,20 @@ func get_domain*( # Get the domain number that represents the fork meta and signature domain. (get_fork_version(fork, epoch) shl 32) + domain_type.uint32 +# https://github.com/ethereum/eth2.0-specs/blob/v0.1/specs/core/0_beacon-chain.md#is_power_of_two func is_power_of_2*(v: uint64): bool = (v and (v-1)) == 0 +# https://github.com/ethereum/eth2.0-specs/blob/v0.1/specs/core/0_beacon-chain.md#merkle_root func merkle_root*(values: openArray[Eth2Digest]): Eth2Digest = - # o = [0] * len(values) + values - # for i in range(len(values)-1, 0, -1): - # o[i] = hash(o[i*2] + o[i*2+1]) - # return o[1] - # TODO + ## Merkleize ``values`` (where ``len(values)`` is a power of two) and return + ## the Merkle root. + #var o = array[len(values) * 2, Eth2Digest] + #o[len(values) .. 2*len(values)] = values + #for i in countdown(len(values)-1, 0): + # discard + #o[i] = hash(o[i*2] + o[i*2+1]) + #return o[1] + #TODO discard proc is_double_vote*(attestation_data_1: AttestationData, @@ -194,6 +200,7 @@ func get_epoch_committee_count*(active_validator_count: int): uint64 = active_validator_count div EPOCH_LENGTH div TARGET_COMMITTEE_SIZE, 1, SHARD_COUNT div EPOCH_LENGTH).uint64 * EPOCH_LENGTH +# https://github.com/ethereum/eth2.0-specs/blob/v0.1/specs/core/0_beacon-chain.md#get_current_epoch_committee_count func get_current_epoch_committee_count*(state: BeaconState): uint64 = let current_active_validators = get_active_validator_indices( state.validator_registry, @@ -205,9 +212,7 @@ func get_current_epoch_committee_count*(state: BeaconState): uint64 = func get_current_epoch*(state: BeaconState): EpochNumber = slot_to_epoch(state.slot) -## TODO I've been moving things into helpers because of layering issues -## but create DAG of which helper functions ref others and topo sort to -## refactor all of this mess. +# https://github.com/ethereum/eth2.0-specs/blob/v0.1/specs/core/0_beacon-chain.md#get_randao_mix func get_randao_mix*(state: BeaconState, epoch: EpochNumber): Eth2Digest = ## Returns the randao mix at a recent ``epoch``. @@ -216,12 +221,14 @@ func get_randao_mix*(state: BeaconState, state.latest_randao_mixes[epoch mod LATEST_RANDAO_MIXES_LENGTH] +# https://github.com/ethereum/eth2.0-specs/blob/v0.1/specs/core/0_beacon-chain.md#get_active_index_root func get_active_index_root(state: BeaconState, epoch: EpochNumber): Eth2Digest = # Returns the index root at a recent ``epoch``. assert get_current_epoch(state) - LATEST_INDEX_ROOTS_LENGTH < epoch assert epoch <= get_current_epoch(state) + 1 state.latest_index_roots[epoch mod LATEST_INDEX_ROOTS_LENGTH] +# https://github.com/ethereum/eth2.0-specs/blob/v0.1/specs/core/0_beacon-chain.md#generate_seed func generate_seed*(state: BeaconState, epoch: EpochNumber): Eth2Digest = # Generate a seed for the given ``epoch``. diff --git a/beacon_chain/spec/validator.nim b/beacon_chain/spec/validator.nim index bc699101f..d79fa33c7 100644 --- a/beacon_chain/spec/validator.nim +++ b/beacon_chain/spec/validator.nim @@ -20,6 +20,7 @@ func xorSeed(seed: Eth2Digest, x: uint64): Eth2Digest = for i in 0 ..< 8: result.data[31 - i] = result.data[31 - i] xor byte((x shr i*8) and 0xff) +# https://github.com/ethereum/eth2.0-specs/blob/v0.1/specs/core/0_beacon-chain.md#get_shuffling func get_shuffling*(seed: Eth2Digest, validators: openArray[Validator], epoch: EpochNumber @@ -59,6 +60,7 @@ func get_new_validator_registry_delta_chain_tip*( flag: flag )) +# https://github.com/ethereum/eth2.0-specs/blob/v0.1/specs/core/0_beacon-chain.md#get_previous_epoch_committee_count func get_previous_epoch_committee_count(state: BeaconState): uint64 = let previous_active_validators = get_active_validator_indices( state.validator_registry, @@ -66,9 +68,22 @@ func get_previous_epoch_committee_count(state: BeaconState): uint64 = ) get_epoch_committee_count(len(previous_active_validators)) -func get_crosslink_committees_at_slot*(state: BeaconState, slot: uint64): +# https://github.com/ethereum/eth2.0-specs/blob/v0.1/specs/core/0_beacon-chain.md#get_next_epoch_committee_count +func get_next_epoch_committee_count(state: BeaconState): uint64 = + let next_active_validators = get_active_validator_indices( + state.validator_registry, + get_current_epoch(state) + 1, + ) + get_epoch_committee_count(len(next_active_validators)) + +# https://github.com/ethereum/eth2.0-specs/blob/v0.1/specs/core/0_beacon-chain.md#get_crosslink_committees_at_slot +func get_crosslink_committees_at_slot*(state: BeaconState, slot: uint64, + registry_change: bool = false): seq[CrosslinkCommittee] = ## Returns the list of ``(committee, shard)`` tuples for the ``slot``. + ## + ## Note: There are two possible shufflings for crosslink committees for a + ## ``slot`` in the next epoch -- with and without a `registry_change` let epoch = slot_to_epoch(slot) @@ -87,13 +102,35 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: uint64): shuffling_epoch = state.previous_calculation_epoch shuffling_start_shard = state.previous_epoch_start_shard (committees_per_epoch, seed, shuffling_epoch, shuffling_start_shard) - else: + elif epoch == current_epoch: let 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 (committees_per_epoch, seed, shuffling_epoch, shuffling_start_shard) + else: + assert epoch == next_epoch + + let + current_committees_per_epoch = get_current_epoch_committee_count(state) + committees_per_epoch = get_next_epoch_committee_count(state) + shuffling_epoch = next_epoch + + epochs_since_last_registry_update = current_epoch - state.validator_registry_update_epoch + condition = epochs_since_last_registry_update > 1'u64 and + is_power_of_2(epochs_since_last_registry_update) + seed = if registry_change or condition: + generate_seed(state, next_epoch) + else: + state.current_epoch_seed + shuffling_start_shard = + if registry_change: + (state.current_epoch_start_shard + + current_committees_per_epoch) mod SHARD_COUNT + else: + state.current_epoch_start_shard + (committees_per_epoch, seed, shuffling_epoch, shuffling_start_shard) let (committees_per_epoch, seed, shuffling_epoch, shuffling_start_shard) = get_epoch_specific_params() @@ -114,6 +151,7 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: uint64): (slot_start_shard + i.uint64) mod SHARD_COUNT ) +# https://github.com/ethereum/eth2.0-specs/blob/v0.1/specs/core/0_beacon-chain.md#get_beacon_proposer_index func get_beacon_proposer_index*(state: BeaconState, slot: uint64): ValidatorIndex = ## From Casper RPJ mini-spec: ## When slot i begins, validator Vidx is expected