예제 #1
0
def test_bitfield_some_votes():
    attesters = list(range(10))
    voters = [0, 4, 5,
              9]  # b'\x01\x00'  # b'\x10\x00'  # b'\x20\x00'  # b'\x00\x02'

    bitfield = get_empty_bitfield(len(attesters))
    for voter in voters:
        bitfield = set_voted(bitfield, voter)

    assert bitfield == (
        True,
        False,
        False,
        False,
        True,
        True,
        False,
        False,
        False,
        True,
    )

    for attester in attesters:
        if attester in voters:
            assert has_voted(bitfield, attester)
        else:
            assert not has_voted(bitfield, attester)
예제 #2
0
def test_bitfield_single_votes():
    attesters = list(range(10))
    bitfield = get_empty_bitfield(len(attesters))

    assert set_voted(bitfield, 0) == (True, False, False, False, False, False,
                                      False, False, False, False)
    assert set_voted(bitfield, 1) == (False, True, False, False, False, False,
                                      False, False, False, False)
    assert set_voted(bitfield, 2) == (False, False, True, False, False, False,
                                      False, False, False, False)
    assert set_voted(bitfield, 4) == (False, False, False, False, True, False,
                                      False, False, False, False)
    assert set_voted(bitfield, 5) == (False, False, False, False, False, True,
                                      False, False, False, False)
    assert set_voted(bitfield, 6) == (False, False, False, False, False, False,
                                      True, False, False, False)
    assert set_voted(bitfield, 7) == (False, False, False, False, False, False,
                                      False, True, False, False)
    assert set_voted(bitfield, 8) == (False, False, False, False, False, False,
                                      False, False, True, False)
    assert set_voted(bitfield, 9) == (False, False, False, False, False, False,
                                      False, False, False, True)

    for voter in attesters:
        bitfield = set_voted((False, ) * 16, voter)
        for attester in attesters:
            if attester == voter:
                assert has_voted(bitfield, attester)
            else:
                assert not has_voted(bitfield, attester)
예제 #3
0
def test_has_voted_random(votes_count):
    bit_count = 1000
    bitfield = get_empty_bitfield(bit_count)
    random_votes = random.sample(range(bit_count), votes_count)

    for index in random_votes:
        bitfield = set_voted(bitfield, index)
    assert get_vote_count(bitfield) == votes_count

    for index in range(bit_count):
        if index in random_votes:
            assert has_voted(bitfield, index)
        else:
            assert not has_voted(bitfield, index)
예제 #4
0
def test_bitfield_some_votes():
    attesters = list(range(10))
    voters = [0, 4, 5, 9]

    bitfield = get_empty_bitfield(len(attesters))
    for voter in voters:
        bitfield = set_voted(bitfield, voter)

    assert bitfield == b'\x8c\x40'

    for attester in attesters:
        if attester in voters:
            assert has_voted(bitfield, attester)
        else:
            assert not has_voted(bitfield, attester)
def test_or_bitfields_random(votes):
    bitfields = []
    bit_count = 100

    for vote in votes:
        bitfield = get_empty_bitfield(bit_count)
        for index in vote:
            bitfield = set_voted(bitfield, index)
        bitfields.append(bitfield)

    bitfield = or_bitfields(bitfields)

    for index in range(bit_count):
        if has_voted(bitfield, index):
            assert any(has_voted(b, index) for b in bitfields)
예제 #6
0
def _validate_custody_bitfield_from_aggregation_bitfield(
        committee_size: int, aggregation_bitfield: Bitfield,
        custody_bitfield: Bitfield) -> None:
    """
    Ensure that every unset bit in the ``aggregation_bitfield`` is also unset
    in the ``custody_bitfield`` to ensure a canonical representation of information
    between the two sources of data.

    Raise ``ValidationError`` if there is a mismatch.
    """
    for i in range(committee_size):
        if not bitfield.has_voted(aggregation_bitfield, i):
            if bitfield.has_voted(custody_bitfield, i):
                raise ValidationError(
                    "Invalid attestation bitfields:\n"
                    f"\tExpected index {i} to not have custody data because "
                    "they did not participate in this attestation.")
예제 #7
0
def test_bitfield_single_votes():
    attesters = list(range(10))
    bitfield = get_empty_bitfield(len(attesters))

    assert set_voted(bitfield, 0) == b'\x80\x00'
    assert set_voted(bitfield, 1) == b'\x40\x00'
    assert set_voted(bitfield, 2) == b'\x20\x00'
    assert set_voted(bitfield, 7) == b'\x01\x00'
    assert set_voted(bitfield, 8) == b'\x00\x80'
    assert set_voted(bitfield, 9) == b'\x00\x40'

    for voter in attesters:
        bitfield = set_voted(b'\x00\x00', voter)
        for attester in attesters:
            if attester == voter:
                assert has_voted(bitfield, attester)
            else:
                assert not has_voted(bitfield, attester)
예제 #8
0
def test_bitfield_all_votes():
    attesters = list(range(10))

    bitfield = get_empty_bitfield(len(attesters))
    for attester in attesters:
        bitfield = set_voted(bitfield, attester)

    for attester in attesters:
        assert has_voted(bitfield, attester)
    assert bitfield == (True, ) * len(attesters)
    def custody_bit_indices(self) -> Tuple[Tuple[ValidatorIndex, ...], Tuple[ValidatorIndex, ...]]:
        custody_bit_0_indices = ()  # type: Tuple[ValidatorIndex, ...]
        custody_bit_1_indices = ()  # type: Tuple[ValidatorIndex, ...]
        for i, validator_index in enumerate(self.validator_indices):
            if not has_voted(self.custody_bitfield, i):
                custody_bit_0_indices += (validator_index,)
            else:
                custody_bit_1_indices += (validator_index,)

        return (custody_bit_0_indices, custody_bit_1_indices)
def test_bitfield_some_votes():
    attesters = list(range(10))
    voters = [
        0,  # b'\x01\x00'
        4,  # b'\x10\x00'
        5,  # b'\x20\x00'
        9,  # b'\x00\x02'
    ]

    bitfield = get_empty_bitfield(len(attesters))
    for voter in voters:
        bitfield = set_voted(bitfield, voter)

    assert bitfield == b'\x31\x02'

    for attester in attesters:
        if attester in voters:
            assert has_voted(bitfield, attester)
        else:
            assert not has_voted(bitfield, attester)
예제 #11
0
def validate_bitfield(bitfield: bytes, committee_size: int) -> None:
    """
    Verify ``bitfield`` against the ``committee_size``.
    """
    if len(bitfield) != get_bitfield_length(committee_size):
        raise ValidationError(
            f"len(bitfield) ({len(bitfield)}) != "
            f"get_bitfield_length(committee_size) ({get_bitfield_length(committee_size)}), "
            f"where committee_size={committee_size}")

    for i in range(committee_size, len(bitfield) * 8):
        if has_voted(bitfield, i):
            raise ValidationError(f"bit ({i}) should be zero")
예제 #12
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))
예제 #13
0
def get_attesting_indices(
    state: BeaconState,
    attestation_data: AttestationData,
    bitfield: Bitfield,
    config: CommitteeConfig,
) -> Set[ValidatorIndex]:
    """
    Return the sorted attesting indices corresponding to ``attestation_data`` and ``bitfield``.
    """
    committee = get_crosslink_committee(state, attestation_data.target.epoch,
                                        attestation_data.crosslink.shard,
                                        config)
    return set(index for i, index in enumerate(committee)
               if has_voted(bitfield, i))
예제 #14
0
def test_aggregate_votes(votes_count, random, privkeys, pubkeys):
    bit_count = 10
    pre_bitfield = get_empty_bitfield(bit_count)
    pre_sigs = ()
    domain = compute_domain(SignatureDomain.DOMAIN_ATTESTATION)

    random_votes = random.sample(range(bit_count), votes_count)
    message_hash = b"\x12" * 32

    # Get votes: (committee_index, sig, public_key)
    votes = [
        (
            committee_index,
            bls.sign(message_hash, privkeys[committee_index], domain),
            pubkeys[committee_index],
        )
        for committee_index in random_votes
    ]

    # Verify
    sigs, committee_indices = verify_votes(message_hash, votes, domain)

    # Aggregate the votes
    bitfield, sigs = aggregate_votes(
        bitfield=pre_bitfield,
        sigs=pre_sigs,
        voting_sigs=sigs,
        attesting_indices=committee_indices,
    )

    try:
        _, _, pubs = zip(*votes)
    except ValueError:
        pubs = ()

    voted_index = [
        committee_index
        for committee_index in random_votes
        if has_voted(bitfield, committee_index)
    ]
    assert len(voted_index) == len(votes)

    aggregated_pubs = bls.aggregate_pubkeys(pubs)

    if votes_count == 0 and bls.backend in (ChiaBackend, MilagroBackend):
        with pytest.raises(ValidationError):
            bls.validate(message_hash, aggregated_pubs, sigs, domain)
    else:
        bls.validate(message_hash, aggregated_pubs, sigs, domain)
예제 #15
0
def get_members_from_bitfield(committee: Sequence[ValidatorIndex],
                              bitfield: Bitfield) -> Iterable[ValidatorIndex]:
    """
    Return all indices in ``committee`` if they "voted" according to the
    ``bitfield``.

    Raise ``ValidationError`` if the ``bitfield`` does not conform to some
    basic checks around length and zero-padding based on the ``committee``
    length.
    """
    validate_bitfield(bitfield, len(committee))

    # Extract committee members if the corresponding bit is set in the bitfield
    for bitfield_index, validator_index in enumerate(committee):
        if has_voted(bitfield, bitfield_index):
            yield validator_index
예제 #16
0
def get_attestation_participants(state: 'BeaconState',
                                 attestation_data: 'AttestationData',
                                 aggregation_bitfield: Bitfield,
                                 genesis_epoch: EpochNumber, epoch_length: int,
                                 target_committee_size: int,
                                 shard_count: int) -> Iterable[ValidatorIndex]:
    """
    Return the participant indices at for the ``attestation_data`` and ``aggregation_bitfield``.
    """
    # Find the committee in the list with the desired shard
    crosslink_committees = get_crosslink_committees_at_slot(
        state=state,
        slot=attestation_data.slot,
        genesis_epoch=genesis_epoch,
        epoch_length=epoch_length,
        target_committee_size=target_committee_size,
        shard_count=shard_count,
    )

    if attestation_data.shard not in set(
        [shard for _, shard in crosslink_committees]):
        raise ValidationError(
            "attestation_data.shard ({}) is not in crosslink_committees".
            format(attestation_data.shard, ))

    try:
        # Filter by shard
        committee = tuple(
            _get_committee_for_shard(crosslink_committees,
                                     attestation_data.shard))
    except IndexError:
        raise ValidationError(
            "committee for shard={} should not be empty.".format(
                attestation_data.shard, ))

    committee_size = len(committee)
    if len(aggregation_bitfield) != get_bitfield_length(committee_size):
        raise ValidationError(
            f"Invalid bitfield length,"
            f"\texpected: {get_bitfield_length(committee_size)}, found: {len(aggregation_bitfield)}"
        )

    # Find the participating attesters in the committee
    for bitfield_index, validator_index in enumerate(committee):
        if has_voted(aggregation_bitfield, bitfield_index):
            yield validator_index
예제 #17
0
def test_aggregate_votes(votes_count, random, privkeys, pubkeys):
    bit_count = 10
    pre_bitfield = get_empty_bitfield(bit_count)
    pre_sigs = ()
    domain = 0

    random_votes = random.sample(range(bit_count), votes_count)
    message_hash = b'\x12' * 32

    # Get votes: (committee_index, sig, public_key)
    votes = [(
        committee_index,
        bls.sign(message_hash, privkeys[committee_index], domain),
        pubkeys[committee_index],
    ) for committee_index in random_votes]

    # Verify
    sigs, committee_indices = verify_votes(message_hash, votes, domain)

    # Aggregate the votes
    bitfield, sigs = aggregate_votes(bitfield=pre_bitfield,
                                     sigs=pre_sigs,
                                     voting_sigs=sigs,
                                     attesting_indices=committee_indices)

    try:
        _, _, pubs = zip(*votes)
    except ValueError:
        pubs = ()

    voted_index = [
        committee_index for committee_index in random_votes
        if has_voted(bitfield, committee_index)
    ]
    assert len(voted_index) == len(votes)

    aggregated_pubs = bls.aggregate_pubkeys(pubs)

    if votes_count != 0:
        bls.validate(message_hash, aggregated_pubs, sigs, domain)
    else:
        # EMPTY_SIGNATURE is considered invalid
        with pytest.raises(ValueError):
            bls.validate(message_hash, aggregated_pubs, sigs, domain)
예제 #18
0
def test_aggregate_votes(votes_count, random, privkeys, pubkeys):
    bit_count = 10
    pre_bitfield = get_empty_bitfield(bit_count)
    pre_sigs = ()

    random_votes = random.sample(range(bit_count), votes_count)
    message_hash = b"\x12" * 32

    # Get votes: (committee_index, sig, public_key)
    votes = [(
        committee_index,
        bls.sign(privkeys[committee_index], message_hash),
        pubkeys[committee_index],
    ) for committee_index in random_votes]

    # Verify
    sigs, committee_indices = verify_votes(message_hash, votes)

    # Aggregate the votes
    bitfield, sigs = aggregate_votes(
        bitfield=pre_bitfield,
        sigs=pre_sigs,
        voting_sigs=sigs,
        attesting_indices=committee_indices,
    )

    try:
        _, _, pubs = zip(*votes)
    except ValueError:
        pubs = ()

    voted_index = [
        committee_index for committee_index in random_votes
        if has_voted(bitfield, committee_index)
    ]
    assert len(voted_index) == len(votes)

    if votes_count == 0:
        with pytest.raises(ValidationError):
            bls.validate(message_hash, sigs, *pubs)
    else:
        bls.validate(message_hash, sigs, *pubs)
예제 #19
0
파일: helpers.py 프로젝트: btcpimp/trinity
def get_attestation_participants(
        state: 'BeaconState', slot: SlotNumber, shard: ShardNumber,
        participation_bitfield: Bitfield,
        epoch_length: int) -> Iterable[ValidatorIndex]:
    """
    Return the participants' indices at the ``slot`` of shard ``shard``
    from ``participation_bitfield``.
    """
    # Find the relevant committee
    # Filter by slot
    shard_committees_at_slot = get_shard_committees_at_slot(
        state,
        slot,
        epoch_length,
    )
    # Filter by shard
    shard_committees = tuple([
        shard_committee for shard_committee in shard_committees_at_slot
        if shard_committee.shard == shard
    ])

    try:
        shard_committee = shard_committees[0]
    except IndexError:
        raise ValidationError("shard_committees should not be empty.")

    if len(participation_bitfield) != get_bitfield_length(
            len(shard_committee.committee)):
        raise ValidationError(
            'Invalid bitfield length,'
            "\texpected: %s, found: %s" % (
                get_bitfield_length(len(shard_committee.committee)),
                len(participation_bitfield),
            ))

    # Find the participating attesters in the committee
    for bitfield_index, validator_index in enumerate(
            shard_committee.committee):
        if has_voted(participation_bitfield, bitfield_index):
            yield validator_index
예제 #20
0
def test_aggregate_votes(votes_count, random, privkeys, pubkeys):
    bit_count = 10
    pre_bitfield = get_empty_bitfield(bit_count)
    pre_sigs = ()
    domain = 0

    random_votes = random.sample(range(bit_count), votes_count)
    message = b'hello'

    # Get votes: (committee_index, sig, public_key)
    votes = [(
        committee_index,
        bls.sign(message, privkeys[committee_index], domain),
        pubkeys[committee_index],
    ) for committee_index in random_votes]

    # Verify
    sigs, committee_indices = verify_votes(message, votes, domain)

    # Aggregate the votes
    bitfield, sigs = aggregate_votes(
        bitfield=pre_bitfield,
        sigs=pre_sigs,
        voting_sigs=sigs,
        voting_committee_indices=committee_indices)

    try:
        _, _, pubs = zip(*votes)
    except ValueError:
        pubs = ()

    voted_index = [
        committee_index for committee_index in random_votes
        if has_voted(bitfield, committee_index)
    ]
    assert len(voted_index) == len(votes)

    aggregated_pubs = bls.aggregate_pubkeys(pubs)
    assert bls.verify(message, aggregated_pubs, sigs, domain)
예제 #21
0
def get_attestation_participants(
        state: 'BeaconState', attestation_data: 'AttestationData',
        bitfield: Bitfield,
        committee_config: CommitteeConfig) -> Iterable[ValidatorIndex]:
    """
    Return the participant indices at for the ``attestation_data`` and ``bitfield``.
    """
    # Find the committee in the list with the desired shard
    crosslink_committees = get_crosslink_committees_at_slot(
        state=state,
        slot=attestation_data.slot,
        committee_config=committee_config,
    )

    if attestation_data.shard not in set(
        [shard for _, shard in crosslink_committees]):
        raise ValidationError(
            "attestation_data.shard ({}) is not in crosslink_committees".
            format(attestation_data.shard, ))

    try:
        # Filter by shard
        committee = tuple(
            _get_committee_for_shard(crosslink_committees,
                                     attestation_data.shard))
    except IndexError:
        raise ValidationError(
            "committee for shard={} should not be empty.".format(
                attestation_data.shard, ))

    validate_bitfield(bitfield, len(committee))

    # Find the participating attesters in the committee
    for bitfield_index, validator_index in enumerate(committee):
        if has_voted(bitfield, bitfield_index):
            yield validator_index
예제 #22
0
def test_bitfield_multiple_votes():
    bitfield = get_empty_bitfield(1)
    bitfield = set_voted(bitfield, 0)
    bitfield = set_voted(bitfield, 0)
    assert has_voted(bitfield, 0)
예제 #23
0
def test_set_vote_and_has_vote(bit_count):
    bitfield = get_empty_bitfield(bit_count)
    index = random.choice(range(bit_count))
    bitfield = set_voted(bitfield, index)
    assert has_voted(bitfield, index)
예제 #24
0
def test_empty_bitfield():
    attesters = list(range(10))
    bitfield = get_empty_bitfield(len(attesters))

    for attester in attesters:
        assert not has_voted(bitfield, attester)