def test_get_attestation_participants( monkeypatch, num_validators, epoch_length, committee, aggregation_bitfield, expected, sample_state, target_committee_size, shard_count, sample_attestation_data_params): shard = 1 from eth2.beacon import helpers def mock_get_crosslink_committees_at_slot(state, slot, epoch_length, target_committee_size, shard_count): return ( (committee, shard,), ) monkeypatch.setattr( helpers, 'get_crosslink_committees_at_slot', mock_get_crosslink_committees_at_slot ) attestation_data = AttestationData(**sample_attestation_data_params).copy( slot=0, shard=shard, ) if isinstance(expected, Exception): with pytest.raises(ValidationError): get_attestation_participants( state=sample_state, attestation_data=attestation_data, aggregation_bitfield=aggregation_bitfield, epoch_length=epoch_length, target_committee_size=target_committee_size, shard_count=shard_count, ) else: result = get_attestation_participants( state=sample_state, attestation_data=attestation_data, aggregation_bitfield=aggregation_bitfield, epoch_length=epoch_length, target_committee_size=target_committee_size, shard_count=shard_count, ) assert result == expected
def test_get_attestation_participants( monkeypatch, num_validators, epoch_length, committee, participation_bitfield, expected, sample_state): from eth2.beacon import helpers def mock_get_shard_committees_at_slot(state, slot, epoch_length): return ( ShardCommittee( shard=0, committee=committee, total_validator_count=num_validators, ), ) monkeypatch.setattr( helpers, 'get_shard_committees_at_slot', mock_get_shard_committees_at_slot ) if isinstance(expected, Exception): with pytest.raises(ValidationError): get_attestation_participants( state=sample_state, slot=0, shard=0, participation_bitfield=participation_bitfield, epoch_length=epoch_length, ) else: result = get_attestation_participants( state=sample_state, slot=0, shard=0, participation_bitfield=participation_bitfield, epoch_length=epoch_length, ) assert result == expected
def validate_attestation_aggregate_signature(state: BeaconState, attestation: Attestation, epoch_length: int, target_committee_size: int, shard_count: int) -> None: """ Validate ``aggregate_signature`` field of ``attestation``. Raise ``ValidationError`` if it's invalid. Note: This is the phase 0 version of `aggregate_signature`` validation. All proof of custody bits are assumed to be 0 within the signed data. This will change to reflect real proof of custody bits in the Phase 1. """ participant_indices = get_attestation_participants( state=state, attestation_data=attestation.data, aggregation_bitfield=attestation.aggregation_bitfield, epoch_length=epoch_length, target_committee_size=target_committee_size, shard_count=shard_count, ) pubkeys = tuple(state.validator_registry[validator_index].pubkey for validator_index in participant_indices) group_public_key = bls.aggregate_pubkeys(pubkeys) # TODO: change to tree hashing when we have SSZ message = AttestationDataAndCustodyBit.create_attestation_message( attestation.data) domain = get_domain( fork=state.fork, slot=attestation.data.slot, domain_type=SignatureDomain.DOMAIN_ATTESTATION, ) is_valid_signature = bls.verify( message=message, pubkey=group_public_key, signature=attestation.aggregate_signature, domain=domain, ) if not is_valid_signature: raise ValidationError("Attestation aggregate_signature is invalid. " "message={}, participant_indices={} " "domain={}".format( message, participant_indices, domain, ))
def validate_serenity_attestation_aggregate_signature( state: BeaconState, attestation: Attestation, epoch_length: int) -> None: """ Validate ``aggregate_signature`` field of ``attestation``. Raise ``ValidationError`` if it's invalid. Note: This is the phase 0 version of `aggregate_signature`` validation. All proof of custody bits are assumed to be 0 within the signed data. This will change to reflect real proof of custody bits in the Phase 1. """ participant_indices = get_attestation_participants( state=state, slot=attestation.data.slot, shard=attestation.data.shard, participation_bitfield=attestation.participation_bitfield, epoch_length=epoch_length, ) pubkeys = tuple(state.validator_registry[validator_index].pubkey for validator_index in participant_indices) group_public_key = bls.aggregate_pubkeys(pubkeys) # TODO: change to tree hashing when we have SSZ # TODO: Replace with AttestationAndCustodyBit data structure message = hash_eth2(rlp.encode(attestation.data) + (0).to_bytes(1, "big")) is_valid_signature = bls.verify( message=message, pubkey=group_public_key, signature=attestation.aggregate_signature, domain=get_domain( fork_data=state.fork_data, slot=attestation.data.slot, domain_type=SignatureDomain.DOMAIN_ATTESTATION, ), ) if not is_valid_signature: raise ValidationError( "Attestation ``aggregate_signature`` is invalid.")