def test_aggregate_votes(votes_count, random, privkeys, pubkeys): bit_count = 10 pre_bitfield = get_empty_bitfield(bit_count) pre_sigs = () 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]), pubkeys[committee_index]) for committee_index in random_votes] # Verify sigs, committee_indices = verify_votes(message, votes) # 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_pubs(pubs) assert bls.verify(message, aggregated_pubs, sigs)
def test_validate_bitfield(attestation_validation_fixture, cycle_length): ( crystallized_state, _, attestation, _, _, _, ) = attestation_validation_fixture attestation_indices = get_attestation_indices( crystallized_state, attestation, cycle_length, ) # Case 1: Attestation has incorrect bitfield length attestation_case_1 = attestation.copy( attester_bitfield=get_empty_bitfield(10), ) with pytest.raises(ValidationError): validate_bitfield(attestation_case_1, attestation_indices) # Case 2: End bits are not all zero last_bit = len(attestation_indices) attestation_case_2 = attestation.copy(attester_bitfield=set_voted( attestation.attester_bitfield, last_bit), ) with pytest.raises(ValidationError): validate_bitfield(attestation_case_2, attestation_indices)
def test_bitfield_all_votes(): attesters = list(range(10)) bitfield = get_empty_bitfield(len(attesters)) for attester in attesters: bitfield = set_voted(bitfield, attester) for attester in attesters: assert has_voted(bitfield, attester) assert bitfield == b'\xff\xc0'
def attest_proposed_block(cls, post_crystallized_state: CrystallizedState, post_active_state: ActiveState, block_proposal: 'BlockProposal', chaindb: BaseBeaconChainDB, private_key: int) -> 'AttestationRecord': """ Return the initial attestation by the block proposer. The proposer broadcasts their attestation with the proposed block. """ block_committees_info = get_block_committees_info( block_proposal.block, post_crystallized_state, cls.config.CYCLE_LENGTH, ) # Vote attester_bitfield = set_voted( get_empty_bitfield(block_committees_info.proposer_committee_size), block_committees_info.proposer_index_in_committee, ) # Get justified_slot and justified_block_hash justified_slot = post_crystallized_state.last_justified_slot justified_block_hash = chaindb.get_canonical_block_hash_by_slot( justified_slot) # Get signing message and sign it parent_hashes = get_hashes_to_sign( post_active_state.recent_block_hashes, block_proposal.block, cls.config.CYCLE_LENGTH, ) message = create_signing_message( block_proposal.block.slot_number, parent_hashes, block_proposal.shard_id, block_proposal.shard_block_hash, justified_slot, ) sig = bls.sign( message, private_key, ) return cls.get_attestation_record_class()( slot=block_proposal.block.slot_number, shard_id=block_proposal.shard_id, oblique_parent_hashes=(), shard_block_hash=block_proposal.shard_block_hash, attester_bitfield=attester_bitfield, justified_slot=justified_slot, justified_block_hash=justified_block_hash, aggregate_sig=sig, )
def test_or_bitfields(): bitfield_1 = get_empty_bitfield(2) bitfield_1 = set_voted(bitfield_1, 0) assert get_vote_count(bitfield_1) == 1 # same size as bitfield_1 bitfield_2 = get_empty_bitfield(2) bitfield_2 = set_voted(bitfield_2, 1) assert get_vote_count(bitfield_2) == 1 bitfield = or_bitfields([bitfield_1, bitfield_2]) assert get_vote_count(bitfield) == 2 # different size from bitfield_1 bitfield_3 = get_empty_bitfield(100) bitfield_3 = set_voted(bitfield_3, 99) assert get_vote_count(bitfield_3) == 1 with pytest.raises(ValueError): or_bitfields([bitfield_1, bitfield_3])
def test_has_voted_random(votes_count): bit_count = 1000 bitfield = get_empty_bitfield(bit_count) random_votes = random.sample(range(bit_count), votes_count) for index in random_votes: bitfield = set_voted(bitfield, index) assert get_vote_count(bitfield) == votes_count for index in range(bit_count): if index in random_votes: assert has_voted(bitfield, index) else: assert not has_voted(bitfield, index)
def test_bitfield_some_votes(): attesters = list(range(10)) voters = [0, 4, 5, 9] bitfield = get_empty_bitfield(len(attesters)) for voter in voters: bitfield = set_voted(bitfield, voter) assert bitfield == b'\x8c\x40' for attester in attesters: if attester in voters: assert has_voted(bitfield, attester) else: assert not has_voted(bitfield, attester)
def test_or_bitfields_random(votes): bitfields = [] bit_count = 100 for vote in votes: bitfield = get_empty_bitfield(bit_count) for index in vote: bitfield = set_voted(bitfield, index) bitfields.append(bitfield) bitfield = or_bitfields(bitfields) for index in range(bit_count): if has_voted(bitfield, index): assert any(has_voted(b, index) for b in bitfields)
def test_bitfield_single_votes(): attesters = list(range(10)) bitfield = get_empty_bitfield(len(attesters)) assert set_voted(bitfield, 0) == b'\x80\x00' assert set_voted(bitfield, 1) == b'\x40\x00' assert set_voted(bitfield, 2) == b'\x20\x00' assert set_voted(bitfield, 7) == b'\x01\x00' assert set_voted(bitfield, 8) == b'\x00\x80' assert set_voted(bitfield, 9) == b'\x00\x40' for voter in attesters: bitfield = set_voted(b'\x00\x00', voter) for attester in attesters: if attester == voter: assert has_voted(bitfield, attester) else: assert not has_voted(bitfield, attester)
def test_validate_parent_block_proposer(attestation_validation_fixture, cycle_length): ( crystallized_state, _, attestation, block, parent_block, _, ) = attestation_validation_fixture validate_parent_block_proposer( crystallized_state, block, parent_block, cycle_length, ) # Case 1: No attestations block = block.copy(attestations=()) with pytest.raises(ValidationError): validate_parent_block_proposer( crystallized_state, block, parent_block, cycle_length, ) # Case 2: Proposer didn't attest block = block.copy(attestations=[ attestation.copy(attester_bitfield=get_empty_bitfield(10), ) ]) with pytest.raises(ValidationError): validate_parent_block_proposer( crystallized_state, block, parent_block, cycle_length, )
def test_bitfield_multiple_votes(): bitfield = get_empty_bitfield(1) bitfield = set_voted(bitfield, 0) bitfield = set_voted(bitfield, 0) assert has_voted(bitfield, 0)
def test_empty_bitfield(): attesters = list(range(10)) bitfield = get_empty_bitfield(len(attesters)) for attester in attesters: assert not has_voted(bitfield, attester)
def test_set_vote_and_has_vote(bit_count): bitfield = get_empty_bitfield(bit_count) index = random.choice(range(bit_count)) bitfield = set_voted(bitfield, index) assert has_voted(bitfield, index)
def test_get_vote_count(): bitfield = get_empty_bitfield(5) bitfield = set_voted(bitfield, 0) bitfield = set_voted(bitfield, 3) assert get_vote_count(bitfield) == 2