Exemplo n.º 1
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)
Exemplo n.º 2
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)
Exemplo n.º 3
0
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)
Exemplo n.º 4
0
def validate_aggregate_sig(crystallized_state: 'CrystallizedState',
                           attestation: 'AttestationRecord',
                           attestation_indices: Iterable[int],
                           parent_hashes: Iterable[Hash32]) -> None:
    """
    Validate ``aggregate_sig`` field.

    Raise ``ValidationError`` if it's invalid.
    """
    pub_keys = [
        crystallized_state.validators[validator_index].pubkey
        for committee_index, validator_index in enumerate(attestation_indices)
        if has_voted(attestation.attester_bitfield, committee_index)
    ]

    message = create_signing_message(
        attestation.slot,
        parent_hashes,
        attestation.shard_id,
        attestation.shard_block_hash,
        attestation.justified_slot,
    )
    if not bls.verify(message, bls.aggregate_pubs(pub_keys),
                      attestation.aggregate_sig):
        raise ValidationError("Attestation aggregate signature fails")
Exemplo n.º 5
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 = b'hello'

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

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

    # 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_pubs(pubs)
    assert bls.verify(message, aggregated_pubs, sigs)
Exemplo n.º 6
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)
Exemplo n.º 7
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 == b'\xff\xc0'
Exemplo n.º 8
0
def validate_parent_block_proposer(crystallized_state: 'CrystallizedState',
                                   block: 'BaseBeaconBlock',
                                   parent_block: 'BaseBeaconBlock',
                                   cycle_length: int) -> None:
    if block.slot_number == 0:
        return

    block_committees_info = get_block_committees_info(
        parent_block,
        crystallized_state,
        cycle_length,
    )

    try:
        attestation = block.attestations[0]
    except IndexError:
        raise ValidationError("block.attestations should not be an empty list")

    is_proposer_attestation = (
        attestation.shard_id == block_committees_info.proposer_shard_id
        and attestation.slot == parent_block.slot_number
        and has_voted(attestation.attester_bitfield,
                      block_committees_info.proposer_index_in_committee))
    if not is_proposer_attestation:
        raise ValidationError(
            "Proposer of parent block should be one of the attesters in block.attestions[0]:\n"
            "\tExpected: proposer index in committee: %d, shard_id: %d, slot: %d\n"
            "\tFound: shard_id: %d, slot: %d, voted: %s" % (
                block_committees_info.proposer_index_in_committee,
                block_committees_info.proposer_shard_id,
                parent_block.slot_number,
                attestation.shard_id,
                attestation.slot,
                has_voted(
                    attestation.attester_bitfield,
                    block_committees_info.proposer_index_in_committee,
                ),
            ))
Exemplo n.º 9
0
def get_attestation_participants(state: 'BeaconState',
                                 slot: int,
                                 shard: int,
                                 participation_bitfield: bytes,
                                 epoch_length: int) -> Iterable[int]:
    """
    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
Exemplo n.º 10
0
def validate_bitfield(attestation: 'AttestationRecord',
                      attestation_indices: Sequence[int]) -> None:
    """
    Validate ``attester_bitfield`` field.

    Raise ``ValidationError`` if it's invalid.
    """
    if len(attestation.attester_bitfield) != get_bitfield_length(
            len(attestation_indices)):
        raise ValidationError(
            "Attestation has incorrect bitfield length. Found: %s, Expected: %s"
            % (len(attestation.attester_bitfield),
               get_bitfield_length(len(attestation_indices))))

    # check if end bits are zero
    last_bit = len(attestation_indices)
    if last_bit % 8 != 0:
        for i in range(8 - last_bit % 8):
            if has_voted(attestation.attester_bitfield, last_bit + i):
                raise ValidationError("Attestation has non-zero trailing bits")
Exemplo n.º 11
0
def test_propose_block(fixture_sm_class,
                       initial_chaindb,
                       genesis_block,
                       privkeys):
    chaindb = initial_chaindb

    # Propose a block
    block_1_shell = genesis_block.copy(
        parent_hash=genesis_block.hash,
        slot_number=genesis_block.slot_number + 1,
    )
    sm = fixture_sm_class(chaindb, block_1_shell)

    #
    # The proposer of block_1
    #
    block_committees_info = (
        get_block_committees_info(
            block_1_shell,
            sm.crystallized_state,
            sm.config.CYCLE_LENGTH,
        )
    )
    private_key = privkeys[block_committees_info.proposer_index]
    block_proposal = BlockProposal(
        block=block_1_shell,
        shard_id=block_committees_info.proposer_shard_id,
        shard_block_hash=ZERO_HASH32,
    )

    (block_1, post_crystallized_state, post_active_state, proposer_attestation) = (
        sm.propose_block(
            crystallized_state=sm.crystallized_state,
            active_state=sm.active_state,
            block_proposal=block_proposal,
            chaindb=sm.chaindb,
            config=sm.config,
            private_key=private_key,
        )
    )
    expect_block_1 = block_1_shell.copy(
        active_state_root=post_active_state.hash,
        crystallized_state_root=post_crystallized_state.hash,
    )
    assert block_1.hash == expect_block_1.hash

    # Persist block_1
    sm.import_block(block_1)
    sm.chaindb.persist_block(block_1)

    # Validate the attestation
    block_2_shell = block_1.copy(
        parent_hash=block_1.hash,
        slot_number=block_1.slot_number + 1,
        attestations=(proposer_attestation, ),
    )

    # Validate the parent block proposer
    validate_parent_block_proposer(
        sm.crystallized_state,
        block_2_shell,
        block_1,
        sm.config.CYCLE_LENGTH,
    )

    assert has_voted(
        proposer_attestation.attester_bitfield,
        block_committees_info.proposer_index_in_committee
    )

    #
    # The proposer of block_2
    #
    block_committees_info = (
        get_block_committees_info(
            block_2_shell,
            sm.crystallized_state,
            sm.config.CYCLE_LENGTH,
        )
    )
    private_key = privkeys[block_committees_info.proposer_index]
    block_proposal = BlockProposal(
        block=block_2_shell,
        shard_id=block_committees_info.proposer_shard_id,
        shard_block_hash=ZERO_HASH32,
    )

    (block_2, post_crystallized_state, post_active_state, proposer_attestation) = (
        sm.propose_block(
            crystallized_state=sm.crystallized_state,
            active_state=sm.active_state,
            block_proposal=block_proposal,
            chaindb=sm.chaindb,
            config=sm.config,
            private_key=private_key,
        )
    )
    expect_block_2 = block_2_shell.copy(
        active_state_root=post_active_state.hash,
        crystallized_state_root=post_crystallized_state.hash,
    )
    assert block_2.hash == expect_block_2.hash
Exemplo n.º 12
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)
Exemplo n.º 13
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)
Exemplo n.º 14
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)