Example #1
0
def is_aggregator(
    state: BeaconState,
    slot: Slot,
    index: CommitteeIndex,
    signature: BLSSignature,
    config: Eth2Config,
) -> bool:
    """
    Check if the validator is one of the aggregators of the given ``slot``.

      .. note::
        - Probabilistically, with enought validators, the aggregator count should
        approach ``TARGET_AGGREGATORS_PER_COMMITTEE``.

        - With ``len(committee)`` is 128 and ``TARGET_AGGREGATORS_PER_COMMITTEE`` is 16,
        the expected length of selected validators is 16.

        - It's possible that this algorithm selects *no one* as the aggregator, but with the
        above parameters, the chance of having no aggregator has a probability of 3.78E-08.

        - Chart analysis: https://docs.google.com/spreadsheets/d/1C7pBqEWJgzk3_jesLkqJoDTnjZOODnGTOJUrxUMdxMA  # noqa: E501
    """
    committee = get_beacon_committee(state, slot, index, config)
    modulo = max(1, len(committee) // TARGET_AGGREGATORS_PER_COMMITTEE)
    return int.from_bytes(hash_eth2(signature)[0:8],
                          byteorder="little") % modulo == 0
def test_get_attesting_indices(genesis_state, config):
    state = genesis_state.set(
        "slot", compute_start_slot_at_epoch(3, config.SLOTS_PER_EPOCH))
    target_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    target_slot = compute_start_slot_at_epoch(target_epoch,
                                              config.SLOTS_PER_EPOCH)
    committee_index = 0
    some_committee = get_beacon_committee(state, target_slot, committee_index,
                                          config)

    data = AttestationData.create(
        slot=target_slot,
        index=committee_index,
        target=Checkpoint.create(epoch=target_epoch),
    )
    some_subset_count = random.randrange(1, len(some_committee) // 2)
    some_subset = random.sample(some_committee, some_subset_count)

    bitfield = get_empty_bitfield(len(some_committee))
    for i, index in enumerate(some_committee):
        if index in some_subset:
            bitfield = set_voted(bitfield, i)

    indices = get_attesting_indices(state, data, bitfield, config)

    assert set(indices) == set(some_subset)
    assert len(indices) == len(some_subset)
Example #3
0
def _validate_aggregation_bits(state: BeaconState, attestation: Attestation,
                               config: Eth2Config) -> None:
    data = attestation.data
    committee = get_beacon_committee(state, data.slot, data.index, config)
    if not (len(attestation.aggregation_bits) == len(committee)):
        raise ValidationError(
            f"The attestation bit lengths not match:"
            f"\tlen(attestation.aggregation_bits)={len(attestation.aggregation_bits)}\n"
            f"\tlen(committee)={len(committee)}")
Example #4
0
def get_attesting_indices(
    state: BeaconState,
    attestation_data: AttestationData,
    bitfield: Bitfield,
    config: CommitteeConfig,
) -> Set[ValidatorIndex]:
    """
    Return the attesting indices corresponding to ``attestation_data`` and ``bitfield``.
    """
    committee = get_beacon_committee(state, attestation_data.slot,
                                     attestation_data.index, config)
    return set(index for i, index in enumerate(committee)
               if has_voted(bitfield, i))
Example #5
0
def test_get_beacon_committee(genesis_state, config):
    state = genesis_state
    indices = tuple()
    epoch_start_slot = state.slot

    for slot in range(epoch_start_slot,
                      epoch_start_slot + config.SLOTS_PER_EPOCH):
        committees_at_slot = get_committee_count_at_slot(
            state,
            slot,
            config.MAX_COMMITTEES_PER_SLOT,
            config.SLOTS_PER_EPOCH,
            config.TARGET_COMMITTEE_SIZE,
        )
        for committee_index in range(committees_at_slot):
            some_committee = get_beacon_committee(state, slot, committee_index,
                                                  config)
            indices += tuple(some_committee)

    assert set(indices) == set(range(len(genesis_state.validators)))
    assert len(indices) == len(genesis_state.validators)
def test_get_unslashed_attesting_indices(genesis_state, config):
    state = genesis_state.set(
        "slot", compute_start_slot_at_epoch(3, config.SLOTS_PER_EPOCH)
    )
    target_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    target_slot = compute_start_slot_at_epoch(target_epoch, config.SLOTS_PER_EPOCH)
    committee_index = 0
    some_committee = get_beacon_committee(
        state, target_slot, committee_index, CommitteeConfig(config)
    )

    data = AttestationData.create(
        slot=state.slot,
        index=committee_index,
        target=Checkpoint.create(epoch=target_epoch),
    )
    some_subset_count = random.randrange(1, len(some_committee) // 2)
    some_subset = random.sample(some_committee, some_subset_count)

    bitfield = get_empty_bitfield(len(some_committee))
    for i, index in enumerate(some_committee):
        if index in some_subset:
            if random.choice([True, False]):
                state = state.transform(["validators", index, "slashed"], True)
            bitfield = set_voted(bitfield, i)

    some_subset = tuple(
        filter(lambda index: not state.validators[index].slashed, some_subset)
    )

    indices = get_unslashed_attesting_indices(
        state,
        (PendingAttestation.create(data=data, aggregation_bits=bitfield),),
        CommitteeConfig(config),
    )

    assert set(indices) == set(some_subset)
    assert len(indices) == len(some_subset)