def verify_slashable_attestation_signature( state: 'BeaconState', slashable_attestation: 'SlashableAttestation', epoch_length: int) -> bool: """ Ensure we have a valid aggregate signature for the ``slashable_attestation``. """ pubkeys = generate_aggregate_pubkeys(state.validator_registry, slashable_attestation) messages = slashable_attestation.messages signature = slashable_attestation.aggregate_signature domain = get_domain( state.fork, slot_to_epoch(slashable_attestation.data.slot, epoch_length), SignatureDomain.DOMAIN_ATTESTATION, ) return bls.verify_multiple( pubkeys=pubkeys, messages=messages, signature=signature, domain=domain, )
def verify_slashable_attestation_signature( state: 'BeaconState', slashable_attestation: 'SlashableAttestation', slots_per_epoch: int) -> bool: """ Ensure we have a valid aggregate signature for the ``slashable_attestation``. """ all_indices = slashable_attestation.custody_bit_indices pubkeys: Tuple[BLSPubkey, ...] = generate_aggregate_pubkeys_from_indices( state.validator_registry, *all_indices, ) message_hashes: Tuple[Hash32, ...] = slashable_attestation.message_hashes signature = slashable_attestation.aggregate_signature domain = get_domain( state.fork, slot_to_epoch(slashable_attestation.data.slot, slots_per_epoch), SignatureDomain.DOMAIN_ATTESTATION, ) # No custody bit 1 indice votes in phase 0, so we only need to process custody bit 0 # for efficiency. # TODO: to be removed in phase 1. if len(all_indices[1]) == 0: pubkeys = pubkeys[:1] message_hashes = message_hashes[:1] return bls.verify_multiple( pubkeys=pubkeys, message_hashes=message_hashes, signature=signature, domain=domain, )
def verify_slashable_vote_data_signature( state: 'BeaconState', vote_data: 'SlashableVoteData') -> bool: """ Ensure we have a valid aggregate signature for the ``vote_data``. """ pubkeys = generate_aggregate_pubkeys(state.validator_registry, vote_data) messages = vote_data.messages signature = vote_data.aggregate_signature domain = get_domain(state.fork, vote_data.data.slot, SignatureDomain.DOMAIN_ATTESTATION) return bls.verify_multiple( pubkeys=pubkeys, messages=messages, signature=signature, domain=domain, )
def test_multi_aggregation(msg_1, msg_2, privkeys_1, privkeys_2): domain = 0 sigs_1 = [sign(msg_1, k, domain=domain) for k in privkeys_1] pubs_1 = [privtopub(k) for k in privkeys_1] aggsig_1 = aggregate_signatures(sigs_1) aggpub_1 = aggregate_pubkeys(pubs_1) sigs_2 = [sign(msg_2, k, domain=domain) for k in privkeys_2] pubs_2 = [privtopub(k) for k in privkeys_2] aggsig_2 = aggregate_signatures(sigs_2) aggpub_2 = aggregate_pubkeys(pubs_2) msgs = [msg_1, msg_2] pubs = [aggpub_1, aggpub_2] aggsig = aggregate_signatures([aggsig_1, aggsig_2]) assert verify_multiple( pubkeys=pubs, messages=msgs, signature=aggsig, domain=domain, )
def validate_attestation_aggregate_signature( state: BeaconState, attestation: Attestation, committee_config: CommitteeConfig) -> 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. """ _validate_custody_bitfield(attestation.custody_bitfield) _validate_aggregation_bitfield(attestation.aggregation_bitfield) committee = get_crosslink_committee_for_attestation( state=state, attestation_data=attestation.data, committee_config=committee_config, ) _validate_custody_bitfield_from_aggregation_bitfield( len(committee), attestation.aggregation_bitfield, attestation.custody_bitfield, ) participants = get_members_from_bitfield(committee, attestation.aggregation_bitfield) custody_bit_1_participants = get_members_from_bitfield( committee, attestation.custody_bitfield) custody_bit_0_participants = (i for i in participants if i not in custody_bit_1_participants) pubkeys = generate_aggregate_pubkeys_from_indices( state.validator_registry, custody_bit_0_participants, custody_bit_1_participants, ) # TODO: change to tree hashing (hash_tree_root) when we have SSZ message_hashes = ( AttestationDataAndCustodyBit(data=attestation.data, custody_bit=False).root, AttestationDataAndCustodyBit(data=attestation.data, custody_bit=True).root, ) domain = get_domain( fork=state.fork, epoch=slot_to_epoch(attestation.data.slot, committee_config.SLOTS_PER_EPOCH), domain_type=SignatureDomain.DOMAIN_ATTESTATION, ) is_valid_signature = bls.verify_multiple( pubkeys=pubkeys, message_hashes=message_hashes, signature=attestation.aggregate_signature, domain=domain, ) if not is_valid_signature: raise ValidationError( "Attestation aggregate_signature is invalid. " "message_hashes={}, custody_bit_0_participants={}, custody_bit_1_participants={} " "domain={}".format( message_hashes, custody_bit_0_participants, custody_bit_1_participants, domain, ))