Example #1
0
def validate_attestation(crystallized_state: CrystallizedState,
                         active_state: ActiveState,
                         attestation: 'AttestationRecord',
                         block: 'Block',
                         config: Dict[str, Any]=DEFAULT_CONFIG) -> None:
    if not attestation.slot < block.slot_number:
        raise Exception("Attestation slot number too high")

    if not (attestation.slot > block.slot_number - config['cycle_length']):
        raise Exception(
            "Attestation slot number too low:\n"
            "\tFound: %s, Needed greater than: %s" %
            (attestation.slot, block.slot_number - config['cycle_length'])
        )

    parent_hashes = get_signed_parent_hashes(
        active_state,
        block,
        attestation,
        config
    )
    attestation_indices = get_attestation_indices(
        crystallized_state,
        attestation,
        config
    )

    #
    # validate bitfield
    #
    if not (len(attestation.attester_bitfield) == get_bitfield_length(len(attestation_indices))):
        raise Exception(
            "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 Exception("Attestation has non-zero trailing bits")

    #
    # validate aggregate_sig
    #
    in_cycle_slot_height = attestation.slot % config['cycle_length']
    pub_keys = [
        crystallized_state.validators[index].pubkey
        for i, index in enumerate(attestation_indices)
        if has_voted(attestation.attester_bitfield, i)
    ]
    message = blake(
        in_cycle_slot_height.to_bytes(8, byteorder='big') +
        b''.join(parent_hashes) +
        attestation.shard_id.to_bytes(2, byteorder='big') +
        attestation.shard_block_hash
    )
    if not bls.verify(message, bls.aggregate_pubs(pub_keys), attestation.aggregate_sig):
        raise Exception("Attestation aggregate signature fails")
Example #2
0
def update_ffg_and_crosslink_progress(crystallized_state,
                                      crosslinks,
                                      ffg_voter_bitfield,
                                      votes,
                                      config=DEFAULT_CONFIG):
    # Verify the attestations of crosslink hashes
    crosslink_votes = {
        vote.shard_block_hash + vote.shard_id.to_bytes(2, 'big'):
        vote.voter_bitfield
        for vote in crosslinks
    }
    new_ffg_bitfield = ffg_voter_bitfield
    total_voters = 0

    # The shards that are selected to be crosslinking
    crosslink_shards = get_crosslink_shards(crystallized_state, config=config)

    for vote in votes:
        attestation = get_crosslink_aggvote_msg(vote.shard_id,
                                                vote.shard_block_hash,
                                                crystallized_state)
        # Check if this shard is in the crosslink shards list
        assert vote.shard_id in crosslink_shards

        indices = get_crosslink_notaries(
            crystallized_state,
            vote.shard_id,
            crosslink_shards=crosslink_shards,
            config=config,
        )
        votekey = vote.shard_block_hash + vote.shard_id.to_bytes(2, 'big')
        if votekey not in crosslink_votes:
            crosslink_votes[votekey] = b"" * get_bitfield_length(len(indices))
        bitfield = crosslink_votes[votekey]
        pubs = []
        for i, index in enumerate(indices):
            if has_voted(vote.notary_bitfield, i):
                pubs.append(crystallized_state.active_validators[index].pubkey)
                if has_voted(new_ffg_bitfield, index):
                    new_ffg_bitfield = set_voted(new_ffg_bitfield, index)
                    bitfield = set_voted(bitfield, i)
                    total_voters += 1
        assert bls.verify(attestation, bls.aggregate_pubs(pubs),
                          vote.aggregate_sig)
        crosslink_votes[votekey] = bitfield
        print('Verified aggregate vote')

    new_crosslinks = [
        PartialCrosslinkRecord(shard_id=int.from_bytes(h[32:], 'big'),
                               shard_block_hash=h[:32],
                               voter_bitfield=crosslink_votes[h])
        for h in sorted(crosslink_votes.keys())
    ]

    return new_crosslinks, new_ffg_bitfield, total_voters
Example #3
0
def process_attestations(validator_set, attestation_indices,
                         attestation_bitfield, msg, aggregate_sig):
    # Verify the attestations of the parent
    pubs = []
    attesters = []
    assert len(attestation_bitfield) == get_bitfield_length(
        len(attestation_indices))
    for i, index in enumerate(attestation_indices):
        if has_voted(attestation_bitfield, i):
            pubs.append(validator_set[index].pubkey)
            attesters.append(index)
    assert len(attesters) <= 128
    assert bls.verify(msg, bls.aggregate_pubs(pubs), aggregate_sig)
    print('Verified aggregate sig')
    return attesters
def validate_attestation(crystallized_state: CrystallizedState,
                         active_state: ActiveState,
                         attestation: 'AttestationRecord',
                         block: 'Block',
                         parent_block: 'Block',
                         config: Dict[str, Any] = DEFAULT_CONFIG) -> None:
    # Verify attestation.slot_number
    if not attestation.slot <= parent_block.slot_number:
        raise Exception("Attestation slot number too high:\n"
                        "\tFound: %s Needed less than or equal to %s" %
                        (attestation.slot, parent_block.slot_number))
    if not (attestation.slot >= max(
            parent_block.slot_number - config['cycle_length'] + 1, 0)):
        raise Exception(
            "Attestation slot number too low:\n"
            "\tFound: %s, Needed greater than or equalt to: %s" %
            (attestation.slot,
             max(parent_block.slot_number - config['cycle_length'] + 1, 0)))

    # TODO: Verify that the justified_slot and justified_block_hash given are in
    # the chain and are equal to or earlier than the last_justified_slot
    # in the crystallized state.

    parent_hashes = get_signed_parent_hashes(active_state, block, attestation,
                                             config)
    attestation_indices = get_attestation_indices(crystallized_state,
                                                  attestation, config)

    #
    # validate bitfield
    #
    if not (len(attestation.attester_bitfield) == get_bitfield_length(
            len(attestation_indices))):
        raise Exception(
            "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 Exception("Attestation has non-zero trailing bits")

    #
    # validate aggregate_sig
    #
    pub_keys = [
        crystallized_state.validators[index].pubkey
        for i, index in enumerate(attestation_indices)
        if has_voted(attestation.attester_bitfield, i)
    ]
    message = blake(
        attestation.slot.to_bytes(8, byteorder='big') +
        b''.join(parent_hashes) +
        attestation.shard_id.to_bytes(2, byteorder='big') +
        attestation.shard_block_hash +
        attestation.justified_slot.to_bytes(8, 'big'))
    if not bls.verify(message, bls.aggregate_pubs(pub_keys),
                      attestation.aggregate_sig):
        raise Exception("Attestation aggregate signature fails")
def test_bitfield_length(attester_count, bitfield_length):
    assert get_bitfield_length(attester_count) == bitfield_length
Example #6
0
def validate_attestation(crystallized_state: CrystallizedState,
                         active_state: ActiveState,
                         attestation: 'AttestationRecord',
                         block: 'Block',
                         parent_block: 'Block',
                         config: Dict[str, Any] = DEFAULT_CONFIG) -> bool:
    #
    # validate slot number
    #
    if not attestation.slot <= parent_block.slot_number:
        raise ValidationError("Attestation slot number too high:\n"
                              "\tFound: %s Needed less than or equal to %s" %
                              (attestation.slot, parent_block.slot_number))
    if not (attestation.slot >= max(
            parent_block.slot_number - config['cycle_length'] + 1, 0)):
        raise ValidationError(
            "Attestation slot number too low:\n"
            "\tFound: %s, Needed greater than or equalt to: %s" %
            (attestation.slot,
             max(parent_block.slot_number - config['cycle_length'] + 1, 0)))

    #
    # validate justified_slot and justified_block_hash
    #
    if attestation.justified_slot > crystallized_state.last_justified_slot:
        raise ValidationError(
            "attestation.justified_slot %s should be equal to or earlier than"
            " crystallized_state.last_justified_slot %s" % (
                attestation.justified_slot,
                crystallized_state.last_justified_slot,
            ))

    justified_block = active_state.chain.get_block_by_hash(
        attestation.justified_block_hash)
    if justified_block is None:
        raise ValidationError(
            "justified_block_hash %s is not in the canonical chain" %
            attestation.justified_block_hash)
    if justified_block.slot_number != attestation.justified_slot:
        raise ValidationError(
            "justified_slot %s doesn't match justified_block_hash" %
            attestation.justified_slot)

    parent_hashes = get_signed_parent_hashes(active_state, block, attestation,
                                             config)
    attestation_indices = get_attestation_indices(crystallized_state,
                                                  attestation, config)

    #
    # validate bitfield
    #
    if not (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")

    #
    # validate aggregate_sig
    #
    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 = blake(
        attestation.slot.to_bytes(8, byteorder='big') +
        b''.join(parent_hashes) +
        attestation.shard_id.to_bytes(2, byteorder='big') +
        attestation.shard_block_hash +
        attestation.justified_slot.to_bytes(8, 'big'))
    if not bls.verify(message, bls.aggregate_pubs(pub_keys),
                      attestation.aggregate_sig):
        raise ValidationError("Attestation aggregate signature fails")

    return True