Beispiel #1
0
def get_beacon_proposer_index(state: 'BeaconState',
                              slot: Slot,
                              committee_config: CommitteeConfig,
                              registry_change: bool=False) -> ValidatorIndex:
    """
    Return the beacon proposer index for the ``slot``.
    """
    epoch = slot_to_epoch(slot, committee_config.SLOTS_PER_EPOCH)
    previous_epoch = state.previous_epoch(committee_config.SLOTS_PER_EPOCH)
    next_epoch = state.next_epoch(committee_config.SLOTS_PER_EPOCH)

    validate_epoch_within_previous_and_next(epoch, previous_epoch, next_epoch)

    crosslink_committees_at_slot = get_crosslink_committees_at_slot(
        state=state,
        slot=slot,
        committee_config=committee_config,
        registry_change=registry_change,
    )
    try:
        first_crosslink_committee = crosslink_committees_at_slot[0]
    except IndexError:
        raise ValidationError("crosslink_committees should not be empty.")

    first_committee, _ = first_crosslink_committee
    if len(first_committee) <= 0:
        raise ValidationError(
            "The first committee should not be empty"
        )

    return first_committee[epoch % len(first_committee)]
Beispiel #2
0
def get_committee_assignment(
        state: BeaconState,
        config: BeaconConfig,
        epoch: Epoch,
        validator_index: ValidatorIndex,
        registry_change: bool = False) -> CommitteeAssignment:
    """
    Return the ``CommitteeAssignment`` in the ``epoch`` for ``validator_index``
    and ``registry_change``.
    ``CommitteeAssignment.committee`` is the tuple array of validators in the committee
    ``CommitteeAssignment.shard`` is the shard to which the committee is assigned
    ``CommitteeAssignment.slot`` is the slot at which the committee is assigned
    ``CommitteeAssignment.is_proposer`` is a bool signalling if the validator is expected to
        propose a beacon block at the assigned slot.
    """
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    previous_epoch = state.previous_epoch(config.SLOTS_PER_EPOCH,
                                          config.GENESIS_EPOCH)
    next_epoch = Epoch(current_epoch + 1)

    validate_epoch_within_previous_and_next(epoch, previous_epoch, next_epoch)

    epoch_start_slot = get_epoch_start_slot(epoch, config.SLOTS_PER_EPOCH)

    committee_config = CommitteeConfig(config)

    for slot in range(epoch_start_slot,
                      epoch_start_slot + config.SLOTS_PER_EPOCH):
        crosslink_committees = get_crosslink_committees_at_slot(
            state,
            slot,
            committee_config,
            registry_change=registry_change,
        )
        selected_committees = [
            committee for committee in crosslink_committees
            if validator_index in committee[0]
        ]
        if len(selected_committees) > 0:
            validators = selected_committees[0][0]
            shard = selected_committees[0][1]
            is_proposer = validator_index == get_beacon_proposer_index(
                state,
                Slot(slot),
                committee_config,
                registry_change=registry_change,
            )

            return CommitteeAssignment(validators, shard, Slot(slot),
                                       is_proposer)

    raise NoCommitteeAssignment
def test_validate_epoch_within_previous_and_next(epoch, previous_epoch,
                                                 next_epoch, success,
                                                 slots_per_epoch,
                                                 genesis_epoch):
    if success:
        validate_epoch_within_previous_and_next(
            epoch,
            previous_epoch,
            next_epoch,
        )
    else:
        with pytest.raises(ValidationError):
            validate_epoch_within_previous_and_next(
                epoch,
                previous_epoch,
                next_epoch,
            )
Beispiel #4
0
def get_crosslink_committees_at_slot(
        state: 'BeaconState',
        slot: Slot,
        committee_config: CommitteeConfig,
        registry_change: bool=False) -> Iterable[Tuple[Sequence[ValidatorIndex], Shard]]:
    """
    Return the list of ``(committee, shard)`` tuples for the ``slot``.
    """
    shard_count = committee_config.SHARD_COUNT
    slots_per_epoch = committee_config.SLOTS_PER_EPOCH

    epoch = slot_to_epoch(slot, slots_per_epoch)
    current_epoch = state.current_epoch(slots_per_epoch)
    previous_epoch = state.previous_epoch(slots_per_epoch)
    next_epoch = state.next_epoch(slots_per_epoch)

    validate_epoch_within_previous_and_next(epoch, previous_epoch, next_epoch)

    if epoch == current_epoch:
        shuffling_context = _get_shuffling_context_is_current_epoch(state, committee_config)
    elif epoch == previous_epoch:
        shuffling_context = _get_shuffling_context_is_previous_epoch(state, committee_config)
    elif epoch == next_epoch:
        epochs_since_last_registry_update = current_epoch - state.validator_registry_update_epoch
        should_reseed = (
            epochs_since_last_registry_update > 1 and
            is_power_of_two(epochs_since_last_registry_update)
        )

        if registry_change:
            shuffling_context = _get_shuffling_contextis_next_epoch_registry_change(
                state,
                next_epoch,
                committee_config,
            )
        elif should_reseed:
            shuffling_context = _get_shuffling_contextis_next_epoch_should_reseed(
                state,
                next_epoch,
                committee_config,
            )
        else:
            shuffling_context = _get_shuffling_contextis_next_epoch_no_registry_change_no_reseed(
                state,
                committee_config,
            )

    shuffling = get_shuffling(
        seed=shuffling_context.seed,
        validators=state.validator_registry,
        epoch=shuffling_context.shuffling_epoch,
        committee_config=committee_config,
    )
    offset = slot % slots_per_epoch
    committees_per_slot = shuffling_context.committees_per_epoch // slots_per_epoch
    slot_start_shard = (
        shuffling_context.shuffling_start_shard +
        committees_per_slot * offset
    ) % shard_count

    for index in range(committees_per_slot):
        committee = shuffling[committees_per_slot * offset + index]
        yield (
            committee,
            Shard((slot_start_shard + index) % shard_count),
        )