def or_bitfields(bitfields: List[Bitfield]) -> Bitfield: byte_slices = zip_longest(*bitfields) if len(set((len(b) for b in bitfields))) != 1: raise ValueError("The bitfield sizes are different") return Bitfield(bytes(map(reduce(operator.or_), byte_slices)))
def get_attestation(self, public_key: BLSPubkey, slot: Slot, committee_index: CommitteeIndex) -> Attestation: current_tick = self.clock.compute_current_tick() state = advance_state_to_slot(self.chain, current_tick.slot) block = self.chain.get_block_by_slot(slot) if not block: # try to find earlier block, assuming skipped slots block = self.chain.get_canonical_head() # sanity check the assumption in this leg of the conditional assert block.slot < slot else: block = block.message target_checkpoint = _get_target_checkpoint(state, block.hash_tree_root, self.eth2_config) data = AttestationData.create( slot=slot, index=committee_index, beacon_block_root=block.hash_tree_root, source=state.current_justified_checkpoint, target=target_checkpoint, ) validator_index = state.get_validator_index_for_public_key(public_key) epoch = compute_epoch_at_slot(slot, self.eth2_config.SLOTS_PER_EPOCH) committee_assignment = get_committee_assignment( state, self.eth2_config, epoch, validator_index) committee = committee_assignment.committee committee_validator_index = committee.index(validator_index) aggregation_bits = Bitfield( tuple(i == committee_validator_index for i in range(len(committee)))) return Attestation.create(aggregation_bits=aggregation_bits, data=data)
def set_voted(bitfield: Bitfield, index: int) -> Bitfield: byte_index = index // 8 bit_index = index % 8 new_byte_value = bitfield[byte_index] | (128 >> bit_index) new_bitfield = bitfield[:byte_index] + bytes( [new_byte_value]) + bitfield[byte_index + 1:] return Bitfield(new_bitfield)
async def _get_attestation(self, request: web.Request) -> web.Response: # _public_key = BLSPubkey(decode_hex(request.query["validator_pubkey"])) slot = Slot(int(request.query["slot"])) committee_index = CommitteeIndex(int(request.query["committee_index"])) attestation = Attestation.create( aggregation_bits=Bitfield([True, False, False]), data=AttestationData.create(index=committee_index, slot=slot), ) return web.json_response(to_formatted_dict(attestation))
def _create_mock_signed_attestation( state: BeaconState, attestation_data: AttestationData, attestation_slot: Slot, committee: Sequence[ValidatorIndex], num_voted_attesters: int, keymap: Dict[BLSPubkey, int], slots_per_epoch: int, is_for_simulation: bool = True, attesting_indices: Sequence[CommitteeIndex] = None, ) -> Attestation: """ Create a mocking attestation of the given ``attestation_data`` slot with ``keymap``. """ message_hash = _get_mock_message(attestation_data) if is_for_simulation: simulation_attesting_indices = _get_mock_attesting_indices( committee, num_voted_attesters) privkeys = tuple( keymap[state.validators[committee[committee_index]].pubkey] for committee_index in simulation_attesting_indices) else: privkeys = tuple(keymap.values()) # Use privkeys to sign the attestation signatures = [ sign_transaction( message_hash=message_hash, privkey=privkey, state=state, slot=attestation_slot, signature_domain=SignatureDomain.DOMAIN_ATTESTATION, slots_per_epoch=slots_per_epoch, ) for privkey in privkeys ] # aggregate signatures and construct participant bitfield aggregation_bits, aggregate_signature = aggregate_votes( bitfield=get_empty_bitfield(len(committee)), sigs=(), voting_sigs=signatures, attesting_indices=attesting_indices if not is_for_simulation else simulation_attesting_indices, ) # create attestation from attestation_data, particpipant_bitfield, and signature return Attestation( aggregation_bits=aggregation_bits, data=attestation_data, custody_bits=Bitfield((False, ) * len(aggregation_bits)), signature=aggregate_signature, )
def _determine_updated_justification_data( justified_epoch: Epoch, bitfield: Bitfield, is_epoch_justifiable: bool, candidate_epoch: Epoch, bit_offset: int, ) -> Tuple[Epoch, Bitfield]: if is_epoch_justifiable: return ( candidate_epoch, Bitfield(update_tuple_item(bitfield, bit_offset, True)), ) else: return (justified_epoch, bitfield)
def create_mock_signed_attestation(state: BeaconState, attestation_data: AttestationData, committee: Sequence[ValidatorIndex], num_voted_attesters: int, keymap: Dict[BLSPubkey, int], slots_per_epoch: int) -> Attestation: """ Create a mocking attestation of the given ``attestation_data`` slot with ``keymap``. """ message_hash, voting_committee_indices = _get_mock_message_and_voting_committee_indices( attestation_data, committee, num_voted_attesters, ) # Use privkeys to sign the attestation signatures = [ sign_transaction( message_hash=message_hash, privkey=keymap[ state.validator_registry[ committee[committee_index] ].pubkey ], fork=state.fork, slot=attestation_data.slot, signature_domain=SignatureDomain.DOMAIN_ATTESTATION, slots_per_epoch=slots_per_epoch, ) for committee_index in voting_committee_indices ] # aggregate signatures and construct participant bitfield aggregation_bitfield, aggregate_signature = aggregate_votes( bitfield=get_empty_bitfield(len(committee)), sigs=(), voting_sigs=signatures, voting_committee_indices=voting_committee_indices, ) # create attestation from attestation_data, particpipant_bitfield, and signature return Attestation( aggregation_bitfield=aggregation_bitfield, data=attestation_data, custody_bitfield=Bitfield(b'\x00' * len(aggregation_bitfield)), aggregate_signature=aggregate_signature, )
def get_aggregate_from_valid_committee_attestations( attestations: Sequence[Attestation]) -> Attestation: """ Return the aggregate attestation. The given attestations SHOULD have the same `data: AttestationData` and are valid. """ signatures = [attestation.signature for attestation in attestations] aggregate_signature = bls.aggregate_signatures(signatures) all_aggregation_bits = [ attestation.aggregation_bits for attestation in attestations ] aggregation_bits = tuple(map(any, zip(*all_aggregation_bits))) assert len(attestations) > 0 return Attestation.create( data=attestations[0].data, aggregation_bits=Bitfield(aggregation_bits), signature=aggregate_signature, )
from eth2.configs import Eth2Config from .block_headers import BeaconBlockHeader, default_beacon_block_header from .checkpoints import Checkpoint, default_checkpoint from .defaults import ( default_slot, default_timestamp, default_tuple, default_tuple_of_size, ) from .eth1_data import Eth1Data, default_eth1_data from .forks import Fork, default_fork from .pending_attestations import PendingAttestation from .validators import Validator default_justification_bits = Bitfield((False, ) * JUSTIFICATION_BITS_LENGTH) TBeaconState = TypeVar("TBeaconState", bound="BeaconState") # Use mainnet constants for defaults. We can't import the config object because of an import cycle. # TODO: When py-ssz is updated to support size configs, the config will be passed to the `create` # classmethod and we can create the defaults dynamically there. default_block_roots = default_tuple_of_size(2**13, ZERO_SIGNING_ROOT) default_state_roots = default_tuple_of_size(2**13, ZERO_HASH32) default_randao_mixes = default_tuple_of_size(2**16, ZERO_HASH32) default_slashings = default_tuple_of_size(2**13, Gwei(0)) class BeaconState(HashableContainer): fields = [
def get_empty_bitfield(bit_count: int) -> Bitfield: return Bitfield((False,) * bit_count)
def set_voted(bitfield: Bitfield, index: int) -> Bitfield: return Bitfield(update_tuple_item(bitfield, index, True))
def get_empty_bitfield(bit_count: int) -> Bitfield: return Bitfield(b"\x00" * get_bitfield_length(bit_count))
def create_signed_attestation_at_slot(state: BeaconState, config: Eth2Config, state_machine: BaseBeaconStateMachine, attestation_slot: Slot, beacon_block_root: Hash32, validator_privkeys: Dict[ValidatorIndex, int], committee: Tuple[ValidatorIndex, ...], shard: Shard) -> Attestation: """ Create the attestations of the given ``attestation_slot`` slot with ``validator_privkeys``. """ state_transition = state_machine.state_transition state = state_transition.apply_state_transition_without_block( state, attestation_slot, ) # Get `target_root` target_root = _get_target_root(state, config, beacon_block_root) previous_crosslink = state.latest_crosslinks[shard] attestation_data = AttestationData( slot=attestation_slot, beacon_block_root=beacon_block_root, source_epoch=state.current_justified_epoch, source_root=state.current_justified_root, target_root=target_root, shard=shard, previous_crosslink=previous_crosslink, crosslink_data_root=ZERO_HASH32, ) message_hash = AttestationDataAndCustodyBit(data=attestation_data, custody_bit=False).root signatures = [ sign_transaction( message_hash=message_hash, privkey=privkey, fork=state.fork, slot=attestation_data.slot, signature_domain=SignatureDomain.DOMAIN_ATTESTATION, slots_per_epoch=config.SLOTS_PER_EPOCH, ) for _, privkey in validator_privkeys.items() ] voting_committee_indices = [ CommitteeIndex(committee.index(validator_index)) for validator_index in validator_privkeys ] # aggregate signatures and construct participant bitfield aggregation_bitfield, aggregate_signature = aggregate_votes( bitfield=get_empty_bitfield(len(committee)), sigs=(), voting_sigs=signatures, voting_committee_indices=voting_committee_indices, ) # create attestation from attestation_data, particpipant_bitfield, and signature return Attestation( aggregation_bitfield=aggregation_bitfield, data=attestation_data, custody_bitfield=Bitfield(get_empty_bitfield( len(aggregation_bitfield))), aggregate_signature=aggregate_signature, )