예제 #1
0
def _get_epoch_committee_count(state, epoch, config):
    active_validators = get_active_validator_indices(state.validators, epoch)
    return get_epoch_committee_count(
        len(active_validators),
        config.SHARD_COUNT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    )
예제 #2
0
def test_get_epoch_committee_count(active_validator_count, slots_per_epoch,
                                   target_committee_size, shard_count,
                                   expected_committee_count):
    assert expected_committee_count == get_epoch_committee_count(
        active_validator_count=active_validator_count,
        shard_count=shard_count,
        slots_per_epoch=slots_per_epoch,
        target_committee_size=target_committee_size,
    )
예제 #3
0
def process_crosslinks(state: BeaconState, config: Eth2Config) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    previous_epoch = state.previous_epoch(config.SLOTS_PER_EPOCH, config.GENESIS_EPOCH)

    new_current_crosslinks = state.current_crosslinks

    for epoch in (previous_epoch, current_epoch):
        active_validators_indices = get_active_validator_indices(state.validators, epoch)
        epoch_committee_count = get_epoch_committee_count(
            len(active_validators_indices),
            config.SHARD_COUNT,
            config.SLOTS_PER_EPOCH,
            config.TARGET_COMMITTEE_SIZE,
        )
        epoch_start_shard = get_epoch_start_shard(
            state,
            epoch,
            CommitteeConfig(config),
        )
        for shard_offset in range(epoch_committee_count):
            shard = Shard((epoch_start_shard + shard_offset) % config.SHARD_COUNT)
            crosslink_committee = get_crosslink_committee(
                state,
                epoch,
                shard,
                CommitteeConfig(config),
            )

            if not crosslink_committee:
                # empty crosslink committee this epoch
                continue

            winning_crosslink, attesting_indices = get_winning_crosslink_and_attesting_indices(
                state=state,
                epoch=epoch,
                shard=shard,
                config=config,
            )
            threshold_met = _is_threshold_met_against_committee(
                state,
                attesting_indices,
                crosslink_committee,
            )
            if threshold_met:
                new_current_crosslinks = update_tuple_item(
                    new_current_crosslinks,
                    shard,
                    winning_crosslink,
                )

    return state.copy(
        previous_crosslinks=state.current_crosslinks,
        current_crosslinks=new_current_crosslinks,
    )
예제 #4
0
def _mk_attestation_inputs_in_epoch(epoch, state, config):
    active_validators_indices = get_active_validator_indices(
        state.validators, epoch)
    epoch_committee_count = get_epoch_committee_count(
        len(active_validators_indices),
        config.SHARD_COUNT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    )
    epoch_start_shard = get_epoch_start_shard(
        state,
        epoch,
        CommitteeConfig(config),
    )
    for shard_offset in random.sample(range(epoch_committee_count),
                                      epoch_committee_count):
        shard = Shard((epoch_start_shard + shard_offset) % config.SHARD_COUNT)
        committee = get_crosslink_committee(
            state,
            epoch,
            shard,
            CommitteeConfig(config),
        )

        if not committee:
            # empty crosslink committee this epoch
            continue

        attestation_data = AttestationData(
            target_epoch=epoch,
            crosslink=Crosslink(shard=shard, ),
        )
        committee_count = len(committee)
        aggregation_bitfield = bitfield.get_empty_bitfield(committee_count)
        for index in range(committee_count):
            aggregation_bitfield = bitfield.set_voted(aggregation_bitfield,
                                                      index)

            for index in committee:
                yield (
                    index,
                    (
                        get_attestation_data_slot(
                            state,
                            attestation_data,
                            config,
                        ),
                        (
                            aggregation_bitfield,
                            attestation_data,
                        ),
                    ),
                )
예제 #5
0
def get_committee_assignment(state: BeaconState,
                             config: Eth2Config,
                             epoch: Epoch,
                             validator_index: ValidatorIndex) -> CommitteeAssignment:
    """
    Return the ``CommitteeAssignment`` in the ``epoch`` for ``validator_index``.
    ``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.
    """
    next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH)
    if epoch > next_epoch:
        raise ValidationError(
            f"Epoch for committee assignment ({epoch}) must not be after next epoch {next_epoch}."
        )

    active_validators = get_active_validator_indices(state.validators, epoch)
    committees_per_slot = get_epoch_committee_count(
        len(active_validators),
        config.SHARD_COUNT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    ) // config.SLOTS_PER_EPOCH
    epoch_start_slot = get_epoch_start_slot(
        epoch,
        config.SLOTS_PER_EPOCH,
    )
    epoch_start_shard = get_epoch_start_shard(state, epoch, CommitteeConfig(config))

    for slot in range(epoch_start_slot, epoch_start_slot + config.SLOTS_PER_EPOCH):
        offset = committees_per_slot * (slot % config.SLOTS_PER_EPOCH)
        slot_start_shard = (epoch_start_shard + offset) % config.SHARD_COUNT
        for i in range(committees_per_slot):
            shard = Shard((slot_start_shard + i) % config.SHARD_COUNT)
            committee = get_crosslink_committee(state, epoch, shard, CommitteeConfig(config))
            if validator_index in committee:
                is_proposer = validator_index == get_beacon_proposer_index(
                    state.copy(
                        slot=slot,
                    ),
                    CommitteeConfig(config),
                )
                return CommitteeAssignment(committee, Shard(shard), Slot(slot), is_proposer)

    raise NoCommitteeAssignment
예제 #6
0
def _find_collision(state, config, index, epoch):
    """
    Given a target epoch, make the attestation expected for the
    validator w/ the given index.
    """
    active_validators = get_active_validator_indices(state.validators, epoch)
    committees_per_slot = get_epoch_committee_count(
        len(active_validators),
        config.SHARD_COUNT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    ) // config.SLOTS_PER_EPOCH
    epoch_start_slot = get_epoch_start_slot(
        epoch,
        config.SLOTS_PER_EPOCH,
    )
    epoch_start_shard = get_epoch_start_shard(state, epoch,
                                              CommitteeConfig(config))

    for slot in range(epoch_start_slot,
                      epoch_start_slot + config.SLOTS_PER_EPOCH):
        offset = committees_per_slot * (slot % config.SLOTS_PER_EPOCH)
        slot_start_shard = (epoch_start_shard + offset) % config.SHARD_COUNT
        for i in range(committees_per_slot):
            shard = Shard((slot_start_shard + i) % config.SHARD_COUNT)
            committee = get_crosslink_committee(state, epoch, shard,
                                                CommitteeConfig(config))
            if index in committee:
                # TODO(ralexstokes) refactor w/ tools/builder
                attestation_data = AttestationData(
                    target_epoch=epoch,
                    crosslink=Crosslink(shard=shard, ),
                )
                committee_count = len(committee)
                aggregation_bitfield = bitfield.get_empty_bitfield(
                    committee_count)
                for i in range(committee_count):
                    aggregation_bitfield = bitfield.set_voted(
                        aggregation_bitfield, i)

                return {
                    index: (slot, (aggregation_bitfield, attestation_data))
                    for index in committee
                }
    else:
        raise Exception("should have found a duplicate validator")
예제 #7
0
def get_crosslink_committees_at_slot(
    state: BeaconState, slot: Slot, config: Eth2Config
) -> Tuple[Tuple[Tuple[ValidatorIndex, ...], Shard], ...]:
    epoch = slot_to_epoch(slot, config.SLOTS_PER_EPOCH)
    active_validators = get_active_validator_indices(state.validators, epoch)
    committees_per_slot = get_epoch_committee_count(
        len(active_validators),
        config.SHARD_COUNT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    ) // config.SLOTS_PER_EPOCH
    results = []
    offset = committees_per_slot * (slot % config.SLOTS_PER_EPOCH)
    slot_start_shard = Shard(
        (get_epoch_start_shard(state, epoch, CommitteeConfig(config)) + offset)
        % config.SHARD_COUNT)
    for i in range(committees_per_slot):
        shard = (slot_start_shard + i) % config.SHARD_COUNT
        committee = get_crosslink_committee(state, epoch, shard,
                                            CommitteeConfig(config))
        results.append((committee, Shard(shard)))

    return tuple(results)
예제 #8
0
def get_crosslink_deltas(state: BeaconState,
                         config: Eth2Config) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
    rewards = tuple(
        0 for _ in range(len(state.validators))
    )
    penalties = tuple(
        0 for _ in range(len(state.validators))
    )
    epoch = state.previous_epoch(config.SLOTS_PER_EPOCH, config.GENESIS_EPOCH)
    active_validators_indices = get_active_validator_indices(state.validators, epoch)
    epoch_committee_count = get_epoch_committee_count(
        len(active_validators_indices),
        config.SHARD_COUNT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    )
    epoch_start_shard = get_epoch_start_shard(
        state,
        epoch,
        CommitteeConfig(config),
    )
    for shard_offset in range(epoch_committee_count):
        shard = Shard((epoch_start_shard + shard_offset) % config.SHARD_COUNT)
        crosslink_committee = get_crosslink_committee(
            state,
            epoch,
            shard,
            CommitteeConfig(config),
        )
        _, attesting_indices = get_winning_crosslink_and_attesting_indices(
            state=state,
            epoch=epoch,
            shard=shard,
            config=config,
        )
        total_attesting_balance = get_total_balance(
            state,
            attesting_indices,
        )
        total_committee_balance = get_total_balance(
            state,
            crosslink_committee,
        )
        for index in crosslink_committee:
            base_reward = get_base_reward(state, index, config)
            if index in attesting_indices:
                rewards = update_tuple_item_with_fn(
                    rewards,
                    index,
                    lambda balance, delta: balance + delta,
                    base_reward * total_attesting_balance // total_committee_balance
                )
            else:
                penalties = update_tuple_item_with_fn(
                    penalties,
                    index,
                    lambda balance, delta: balance + delta,
                    base_reward,
                )
    return tuple(
        Gwei(reward) for reward in rewards
    ), tuple(
        Gwei(penalty) for penalty in penalties
    )