def test_validate_bitfield_padding_zero(committee_size): bitfield = get_empty_bitfield(committee_size) for index in range(committee_size): bitfield = set_voted(bitfield, index) if committee_size % 8 != 0: bitfield = set_voted(bitfield, committee_size) with pytest.raises(ValidationError): validate_bitfield(bitfield, committee_size) else: validate_bitfield(bitfield, committee_size)
def test_validate_bitfield_bitfield_length(committee_size, is_valid): if is_valid: testing_committee_size = committee_size else: testing_committee_size = committee_size + 1 bitfield = get_empty_bitfield(testing_committee_size) if not is_valid and len(bitfield) != get_bitfield_length(committee_size): with pytest.raises(ValidationError): validate_bitfield(bitfield, committee_size) else: validate_bitfield(bitfield, committee_size)
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
def get_attesting_indices(state: BeaconState, attestation_data: AttestationData, bitfield: Bitfield, config: CommitteeConfig) -> Iterable[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, ) validate_bitfield(bitfield, len(committee)) return sorted(index for i, index in enumerate(committee) if has_voted(bitfield, i))
def validate_slashable_attestation(state: 'BeaconState', slashable_attestation: 'SlashableAttestation', max_indices_per_slashable_vote: int, epoch_length: int) -> None: """ Verify validity of ``slashable_attestation`` fields. Ensure that the ``slashable_attestation`` is properly assembled and contains the signature we expect from the validators we expect. Otherwise, return False as the ``slashable_attestation`` is invalid. """ # [TO BE REMOVED IN PHASE 1] if not slashable_attestation.is_custody_bitfield_empty: raise ValidationError( "`slashable_attestation.custody_bitfield` is not empty." ) if len(slashable_attestation.validator_indices) == 0: raise ValidationError( "`slashable_attestation.validator_indices` is empty." ) if not slashable_attestation.is_validator_indices_ascending: raise ValidationError( "`slashable_attestation.validator_indices` " f"({slashable_attestation.validator_indices}) " "is not ordered in ascending." ) validate_bitfield( slashable_attestation.custody_bitfield, len(slashable_attestation.validator_indices), ) if len(slashable_attestation.validator_indices) > max_indices_per_slashable_vote: raise ValidationError( f"`len(slashable_attestation.validator_indices)` " f"({len(slashable_attestation.validator_indices)}) greater than" f"MAX_INDICES_PER_SLASHABLE_VOTE ({max_indices_per_slashable_vote})" ) if not verify_slashable_attestation_signature(state, slashable_attestation, epoch_length): raise ValidationError( f"slashable_attestation.signature error" )
def get_attestation_participants(state: 'BeaconState', attestation_data: 'AttestationData', 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 ``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, )) 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