def validate_proof_of_possession(state: BeaconState, pubkey: BLSPubkey, proof_of_possession: BLSSignature, withdrawal_credentials: Hash32, randao_commitment: Hash32) -> None: deposit_input = DepositInput( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, proof_of_possession=EMPTY_SIGNATURE, ) is_valid_signature = bls.verify( pubkey=pubkey, # TODO: change to hash_tree_root(deposit_input) when we have SSZ tree hashing message=deposit_input.root, signature=proof_of_possession, domain=get_domain( state.fork_data, state.slot, SignatureDomain.DOMAIN_DEPOSIT, ), ) if not is_valid_signature: raise ValidationError("BLS signature verification error")
def validate_serenity_proposer_signature( state: BeaconState, block: BaseBeaconBlock, beacon_chain_shard_number: ShardNumber, epoch_length: int) -> None: block_without_signature_root = block.block_without_signature_root # TODO: Replace this root with tree hash root proposal_root = ProposalSignedData( state.slot, beacon_chain_shard_number, block_without_signature_root, ).root # Get the public key of proposer beacon_proposer_index = get_beacon_proposer_index(state, state.slot, epoch_length) proposer_pubkey = state.validator_registry[beacon_proposer_index].pubkey is_valid_signature = bls.verify( pubkey=proposer_pubkey, message=proposal_root, signature=block.signature, domain=get_domain(state.fork_data, state.slot, SignatureDomain.DOMAIN_PROPOSAL), ) if not is_valid_signature: raise ValidationError("Invalid Proposer Signature on block")
def test_signature_aggregation(msg, privkeys): domain = 0 sigs = [sign(msg, k, domain=domain) for k in privkeys] pubs = [privtopub(k) for k in privkeys] aggsig = aggregate_signatures(sigs) aggpub = aggregate_pubkeys(pubs) assert verify(msg, aggpub, aggsig, domain=domain)
def test_bls_core(privkey): domain = 0 p1 = multiply(G1, privkey) p2 = multiply(G2, privkey) msg = str(privkey).encode('utf-8') msghash = hash_to_G2(msg, domain=domain) assert normalize(decompress_G1(compress_G1(p1))) == normalize(p1) assert normalize(decompress_G2(compress_G2(p2))) == normalize(p2) assert normalize(decompress_G2(compress_G2(msghash))) == normalize(msghash) sig = sign(msg, privkey, domain=domain) pub = privtopub(privkey) assert verify(msg, pub, sig, domain=domain)
def verify_votes( message: bytes, votes: Iterable[Tuple[CommitteeIndex, BLSSignature, BLSPubkey]], domain: SignatureDomain ) -> Tuple[Tuple[BLSSignature, ...], Tuple[CommitteeIndex, ...]]: """ Verify the given votes. vote: (committee_index, sig, public_key) """ sigs_with_committe_info = tuple( (sig, committee_index) for (committee_index, sig, public_key) in votes if bls.verify(message, public_key, sig, domain)) try: sigs, committee_indices = zip(*sigs_with_committe_info) except ValueError: sigs = tuple() committee_indices = tuple() return sigs, committee_indices
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.")
def test_aggregate_votes(votes_count, random, privkeys, pubkeys): bit_count = 10 pre_bitfield = get_empty_bitfield(bit_count) pre_sigs = () domain = 0 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], domain), pubkeys[committee_index], ) for committee_index in random_votes] # Verify sigs, committee_indices = verify_votes(message, votes, domain) # 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_pubkeys(pubs) assert bls.verify(message, aggregated_pubs, sigs, domain)