async def propose_or_skip_block(self, slot: Slot, is_second_tick: bool) -> None: head = self.chain.get_canonical_head() state_machine = self.chain.get_state_machine() state = state_machine.state self.logger.debug( bold_green( f"head: slot={head.slot}, state root={head.state_root.hex()}")) proposer_index = _get_proposer_index( state, slot, state_machine.config, ) # Since it's expected to tick twice in one slot, `latest_proposed_epoch` is used to prevent # proposing twice in the same slot. has_proposed = slot_to_epoch( slot, self.slots_per_epoch) <= self.latest_proposed_epoch if not has_proposed and proposer_index in self.validator_privkeys: self.propose_block( proposer_index=proposer_index, slot=slot, state=state, state_machine=state_machine, head_block=head, ) self.latest_proposed_epoch = slot_to_epoch(slot, self.slots_per_epoch) # skip the block if it's second half of the slot and we are not proposing elif is_second_tick and proposer_index not in self.validator_privkeys: self.skip_block( slot=slot, state=state, state_machine=state_machine, )
def _correct_slashable_attestation_params(epoch_length, num_validators, params, messages, privkeys, fork): valid_params = copy.deepcopy(params) key = "custody_bit_0_indices" (poc_0_indices, poc_0_signatures) = _get_indices_and_signatures( num_validators, messages[0], privkeys, fork, slot_to_epoch(params["data"].slot, epoch_length), ) valid_params[key] = poc_0_indices key = "custody_bit_1_indices" # NOTE: does not guarantee non-empty intersection (poc_1_indices, poc_1_signatures) = _get_indices_and_signatures( num_validators, messages[1], privkeys, fork, slot_to_epoch(params["data"].slot, epoch_length), ) valid_params[key] = poc_1_indices signatures = poc_0_signatures + poc_1_signatures aggregate_signature = bls.aggregate_signatures(signatures) valid_params["aggregate_signature"] = aggregate_signature return valid_params
def validate_proposer_slashing_epoch(proposer_slashing: ProposerSlashing, slots_per_epoch: int) -> None: epoch_1 = slot_to_epoch(proposer_slashing.header_1.slot, slots_per_epoch) epoch_2 = slot_to_epoch(proposer_slashing.header_2.slot, slots_per_epoch) if epoch_1 != epoch_2: raise ValidationError( f"Epoch of proposer_slashing.proposal_1 ({epoch_1}) !=" f" epoch of proposer_slashing.proposal_2 ({epoch_2})")
def process_final_updates(state: BeaconState, config: BeaconConfig) -> BeaconState: current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH) next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH) state = _update_latest_active_index_roots(state, CommitteeConfig(config)) state = state.copy( latest_slashed_balances=update_tuple_item( state.latest_slashed_balances, next_epoch % config.LATEST_SLASHED_EXIT_LENGTH, state.latest_slashed_balances[current_epoch % config.LATEST_SLASHED_EXIT_LENGTH], ), latest_randao_mixes=update_tuple_item( state.latest_randao_mixes, next_epoch % config.LATEST_SLASHED_EXIT_LENGTH, get_randao_mix( state=state, epoch=current_epoch, slots_per_epoch=config.SLOTS_PER_EPOCH, latest_randao_mixes_length=config.LATEST_RANDAO_MIXES_LENGTH, ), ), ) latest_attestations = tuple( filter( lambda attestation: (slot_to_epoch(attestation.data.slot, config.SLOTS_PER_EPOCH) >= current_epoch), state.latest_attestations)) state = state.copy(latest_attestations=latest_attestations, ) return state
def get_beacon_proposer_index(state: 'BeaconState', slot: Slot, committee_config: CommitteeConfig, registry_change: bool=False) -> ValidatorIndex: """ Return the beacon proposer index for the ``slot``. """ epoch = slot_to_epoch(slot, committee_config.SLOTS_PER_EPOCH) previous_epoch = state.previous_epoch(committee_config.SLOTS_PER_EPOCH) next_epoch = state.next_epoch(committee_config.SLOTS_PER_EPOCH) validate_epoch_within_previous_and_next(epoch, previous_epoch, next_epoch) crosslink_committees_at_slot = get_crosslink_committees_at_slot( state=state, slot=slot, committee_config=committee_config, registry_change=registry_change, ) try: first_crosslink_committee = crosslink_committees_at_slot[0] except IndexError: raise ValidationError("crosslink_committees should not be empty.") first_committee, _ = first_crosslink_committee if len(first_committee) <= 0: raise ValidationError( "The first committee should not be empty" ) return first_committee[epoch % len(first_committee)]
def process_final_updates(state: BeaconState, config: BeaconConfig) -> BeaconState: current_epoch = state.current_epoch(config.EPOCH_LENGTH) next_epoch = state.next_epoch(config.EPOCH_LENGTH) state = state.copy( latest_penalized_balances=update_tuple_item( state.latest_penalized_balances, next_epoch % config.LATEST_PENALIZED_EXIT_LENGTH, state.latest_penalized_balances[ current_epoch % config.LATEST_PENALIZED_EXIT_LENGTH], ), latest_randao_mixes=update_tuple_item( state.latest_randao_mixes, next_epoch % config.LATEST_PENALIZED_EXIT_LENGTH, get_randao_mix( state=state, epoch=current_epoch, epoch_length=config.EPOCH_LENGTH, latest_randao_mixes_length=config.LATEST_RANDAO_MIXES_LENGTH, ), ), ) latest_attestations = tuple( filter( lambda attestation: (slot_to_epoch(attestation.data.slot, config. EPOCH_LENGTH) >= current_epoch), state.latest_attestations)) state = state.copy(latest_attestations=latest_attestations, ) return state
def test_update_latest_active_index_roots(genesis_state, committee_config, state_slot, slots_per_epoch, latest_active_index_roots_length, activation_exit_delay): state = genesis_state.copy( slot=state_slot, ) result_state = _update_latest_active_index_roots(state, committee_config) # TODO: chanege to hash_tree_root index_root = hash_eth2( b''.join( [ index.to_bytes(32, 'little') for index in get_active_validator_indices( state.validator_registry, # TODO: change to `per-epoch` version slot_to_epoch(state.slot, slots_per_epoch), ) ] ) ) target_epoch = state.next_epoch(slots_per_epoch) + activation_exit_delay assert result_state.latest_active_index_roots[ target_epoch % latest_active_index_roots_length ] == index_root
def create_block_on_state( *, state: BeaconState, config: BeaconConfig, state_machine: BaseBeaconStateMachine, block_class: BaseBeaconBlock, parent_block: BaseBeaconBlock, slot: SlotNumber, validator_index: ValidatorIndex, privkey: int, attestations: Sequence[Attestation], check_proposer_index: bool = True) -> BaseBeaconBlock: """ Create a beacon block with the given parameters. """ # Check proposer if check_proposer_index: validate_proposer_index(state, config, slot, validator_index) # Prepare block: slot and parent_root block = block_class.from_parent( parent_block=parent_block, block_params=FromBlockParams(slot=slot), ) # TODO: Add more operations randao_reveal = ZERO_HASH32 eth1_data = Eth1Data.create_empty_data() body = BeaconBlockBody.create_empty_body().copy( attestations=attestations, ) block = block.copy( randao_reveal=randao_reveal, eth1_data=eth1_data, body=body, ) # Apply state transition to get state root state, block = state_machine.import_block(block, check_proposer_signature=True) # Sign empty_signature_block_root = block.block_without_signature_root proposal_root = ProposalSignedData( slot, config.BEACON_CHAIN_SHARD_NUMBER, empty_signature_block_root, ).root domain = get_domain( state.fork, slot_to_epoch(slot, config.EPOCH_LENGTH), SignatureDomain.DOMAIN_PROPOSAL, ) block = block.copy(signature=bls.sign( message=proposal_root, privkey=privkey, domain=domain, ), ) return block
async def test_validator_attest(event_loop, event_bus, monkeypatch): alice_indices = [i for i in range(8)] alice = await get_validator(event_loop=event_loop, event_bus=event_bus, indices=alice_indices) head = alice.chain.get_canonical_head() state_machine = alice.chain.get_state_machine() state = state_machine.state epoch = slot_to_epoch(state.slot, state_machine.config.SLOTS_PER_EPOCH) assignment = alice._get_this_epoch_assignment(alice_indices[0], epoch) attestations = await alice.attest(assignment.slot) assert len(attestations) == 1 attestation = attestations[0] assert get_attestation_data_slot( state, attestation.data, state_machine.config, ) == assignment.slot assert attestation.data.beacon_block_root == head.signing_root assert attestation.data.crosslink.shard == assignment.shard # Advance the state and validate the attestation config = state_machine.config future_state = state_machine.state_transition.apply_state_transition( state, future_slot=assignment.slot + config.MIN_ATTESTATION_INCLUSION_DELAY, ) validate_attestation( future_state, attestation, config, )
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 validate_attestation_previous_crosslink_or_root( attestation_data: AttestationData, state_latest_crosslink: CrosslinkRecord, slots_per_epoch: int) -> None: """ Validate that either the attestation ``previous_crosslink`` or ``crosslink_data_root`` field of ``attestation_data`` is the provided ``latest_crosslink``. Raise ``ValidationError`` if it's invalid. """ attestation_creating_crosslink = CrosslinkRecord( epoch=slot_to_epoch(attestation_data.slot, slots_per_epoch), crosslink_data_root=attestation_data.crosslink_data_root, ) acceptable_crosslink_data = { # Case 1: Latest crosslink matches the one in the state attestation_data.previous_crosslink, # Case 2: State has already been updated, state's latest crosslink matches the crosslink # the attestation is trying to create attestation_creating_crosslink, } if state_latest_crosslink not in acceptable_crosslink_data: raise ValidationError( f"State's latests crosslink ({state_latest_crosslink}) doesn't match " " case 1: the `attestation_data.previous_crosslink` " f"({attestation_data.previous_crosslink.root}) or " "`case 2: the crosslink the attestation is trying to create " f"({attestation_creating_crosslink})")
def _get_highest_justified_epoch(self, db: BaseDB) -> Epoch: try: justified_head_root = self._get_justified_head_root(db) slot = self.get_slot_by_root(justified_head_root) return slot_to_epoch(slot, self.config.SLOTS_PER_EPOCH) except JustifiedHeadNotFound: return self.config.GENESIS_EPOCH
def _correct_slashable_attestation_params( slots_per_epoch, num_validators, params, message_hashes, privkeys, fork): valid_params = copy.deepcopy(params) (validator_indices, signatures) = _get_indices_and_signatures( num_validators, message_hashes[0], # custody bit is False privkeys, fork, slot_to_epoch(params["data"].slot, slots_per_epoch), ) valid_params["validator_indices"] = validator_indices valid_params["custody_bitfield"] = get_empty_bitfield(len(validator_indices)) aggregate_signature = bls.aggregate_signatures(signatures) valid_params["aggregate_signature"] = aggregate_signature return valid_params
def get_crosslink_committees_at_slot( state: 'BeaconState', slot: SlotNumber, genesis_epoch: EpochNumber, epoch_length: int, target_committee_size: int, shard_count: int ) -> Iterable[Tuple[Iterable[ValidatorIndex], ShardNumber]]: """ Return the list of ``(committee, shard)`` tuples for the ``slot``. """ epoch = slot_to_epoch(slot, epoch_length) current_epoch = state.current_epoch(epoch_length) validate_epoch_for_current_epoch( current_epoch=current_epoch, given_epoch=epoch, genesis_epoch=genesis_epoch, epoch_length=epoch_length, ) # TODO: need to update according to https://github.com/ethereum/eth2.0-specs/pull/520 if epoch < current_epoch: committees_per_epoch = get_previous_epoch_committee_count( state=state, shard_count=shard_count, epoch_length=epoch_length, target_committee_size=target_committee_size, ) seed = state.previous_epoch_seed shuffling_epoch = state.previous_calculation_epoch shuffling_start_shard = state.previous_epoch_start_shard else: committees_per_epoch = get_current_epoch_committee_count( state=state, shard_count=shard_count, epoch_length=epoch_length, target_committee_size=target_committee_size, ) seed = state.current_epoch_seed shuffling_epoch = state.current_calculation_epoch shuffling_start_shard = state.current_epoch_start_shard shuffling = get_shuffling( seed=seed, validators=state.validator_registry, epoch=shuffling_epoch, epoch_length=epoch_length, target_committee_size=target_committee_size, shard_count=shard_count, ) offset = slot % epoch_length committees_per_slot = committees_per_epoch // epoch_length slot_start_shard = (shuffling_start_shard + committees_per_slot * offset) % shard_count for index in range(committees_per_slot): committee = shuffling[committees_per_slot * offset + index] yield ( committee, ShardNumber((slot_start_shard + index) % shard_count), )
def get_current_epoch_attestations( state: 'BeaconState', slots_per_epoch: int) -> Iterable[PendingAttestationRecord]: current_epoch = state.current_epoch(slots_per_epoch) for attestation in state.latest_attestations: if current_epoch == slot_to_epoch(attestation.data.slot, slots_per_epoch): yield attestation
def get_previous_epoch_attestations( state: 'BeaconState', slots_per_epoch: int, genesis_epoch: Epoch) -> Iterable[PendingAttestationRecord]: previous_epoch = state.previous_epoch(slots_per_epoch, genesis_epoch) for attestation in state.latest_attestations: if previous_epoch == slot_to_epoch(attestation.data.slot, slots_per_epoch): yield attestation
def test_process_validator_registry( monkeypatch, genesis_state, epoch_length, state_slot, need_to_update, num_shards_in_committees, validator_registry_update_epoch, epochs_since_last_registry_change_is_power_of_two, current_calculation_epoch, latest_randao_mixes, expected_current_calculation_epoch, entry_exit_delay, config): # Mock check_if_update_validator_registry from eth2.beacon.state_machines.forks.serenity import epoch_processing def mock_check_if_update_validator_registry(state, config): return need_to_update, num_shards_in_committees monkeypatch.setattr(epoch_processing, '_check_if_update_validator_registry', mock_check_if_update_validator_registry) # Mock generate_seed new_seed = b'\x88' * 32 def mock_generate_seed(state, epoch, epoch_length, seed_lookahead, entry_exit_delay, latest_index_roots_length, latest_randao_mixes_length): return new_seed monkeypatch.setattr('eth2.beacon.helpers.generate_seed', mock_generate_seed) # Set state state = genesis_state.copy( slot=state_slot, validator_registry_update_epoch=validator_registry_update_epoch, current_calculation_epoch=current_calculation_epoch, latest_randao_mixes=latest_randao_mixes, ) result_state = process_validator_registry(state, config) assert result_state.previous_calculation_epoch == state.current_calculation_epoch assert result_state.previous_epoch_start_shard == state.current_epoch_start_shard assert result_state.previous_epoch_seed == state.current_epoch_seed if need_to_update: assert result_state.current_calculation_epoch == slot_to_epoch( state_slot, epoch_length) assert result_state.current_epoch_seed == new_seed # TODO: Add test for validator registry updates else: assert (result_state.current_calculation_epoch == expected_current_calculation_epoch) # state.current_epoch_start_shard is left unchanged. assert result_state.current_epoch_start_shard == state.current_epoch_start_shard if epochs_since_last_registry_change_is_power_of_two: assert result_state.current_epoch_seed == new_seed else: assert result_state.current_epoch_seed != new_seed
async def test_validator_get_committee_assigment(event_loop, event_bus): alice_indices = [7] alice = await get_validator(event_loop=event_loop, event_bus=event_bus, indices=alice_indices) state_machine = alice.chain.get_state_machine() state = state_machine.state epoch = slot_to_epoch(state.slot, state_machine.config.SLOTS_PER_EPOCH) assert alice.this_epoch_assignment[alice_indices[0]][0] == -1 alice._get_this_epoch_assignment(alice_indices[0], epoch) assert alice.this_epoch_assignment[alice_indices[0]][0] == epoch
def create_mock_signed_attestations_at_slot( state: BeaconState, config: Eth2Config, state_machine: BaseBeaconStateMachine, attestation_slot: Slot, beacon_block_root: Hash32, keymap: Dict[BLSPubkey, int], voted_attesters_ratio: float = 1.0) -> Iterable[Attestation]: """ Create the mocking attestations of the given ``attestation_slot`` slot with ``keymap``. """ crosslink_committees_at_slot = get_crosslink_committees_at_slot( state, attestation_slot, config, ) # Get `target_root` target_root = _get_target_root(state, config, beacon_block_root) target_epoch = slot_to_epoch( state.slot, config.SLOTS_PER_EPOCH, ) for crosslink_committee in crosslink_committees_at_slot: committee, shard = crosslink_committee parent_crosslink = state.current_crosslinks[shard] attestation_data = AttestationData( beacon_block_root=beacon_block_root, source_epoch=state.current_justified_epoch, source_root=state.current_justified_root, target_root=target_root, target_epoch=target_epoch, crosslink=Crosslink( shard=shard, parent_root=parent_crosslink.root, start_epoch=parent_crosslink.end_epoch, end_epoch=min( target_epoch, parent_crosslink.end_epoch + config.MAX_EPOCHS_PER_CROSSLINK), )) num_voted_attesters = int(len(committee) * voted_attesters_ratio) yield _create_mock_signed_attestation( state, attestation_data, attestation_slot, committee, num_voted_attesters, keymap, config.SLOTS_PER_EPOCH, )
async def test_validator_propose_or_skip_block(event_loop, event_bus, monkeypatch): alice, bob = await get_linked_validators(event_loop=event_loop, event_bus=event_bus) state_machine = alice.chain.get_state_machine() state = state_machine.state # test: `propose_or_skip_block` should call `propose_block` if the validator get selected def is_alice_selected(proposer_index): return proposer_index in alice.validator_privkeys slot_to_propose, index = _get_slot_with_validator_selected( is_desired_proposer_index=is_alice_selected, start_slot=state.slot + 1, state=state, state_machine=state_machine, ) alice.latest_proposed_epoch = slot_to_epoch(slot_to_propose, alice.slots_per_epoch) - 1 is_proposing = None def propose_block(proposer_index, slot, state, state_machine, head_block): nonlocal is_proposing is_proposing = True def skip_block(slot, state, state_machine): nonlocal is_proposing is_proposing = False monkeypatch.setattr(alice, 'propose_block', propose_block) monkeypatch.setattr(alice, 'skip_block', skip_block) await alice.propose_or_skip_block(slot_to_propose, False) assert is_proposing is_proposing = None # test: `propose_or_skip_block` should call `skip_block`. def is_not_alice_bob_selected(proposer_index): return (proposer_index not in alice.validator_privkeys and proposer_index not in bob.validator_privkeys) slot_to_skip, index = _get_slot_with_validator_selected( is_desired_proposer_index=is_not_alice_bob_selected, start_slot=state.slot + 1, state=state, state_machine=state_machine, ) await alice.propose_or_skip_block(slot_to_skip, is_second_tick=False) assert is_proposing is None, "`skip_block` should not be called if `is_second_tick == False`" await alice.propose_or_skip_block(slot_to_skip, is_second_tick=True) assert is_proposing is False, "`skip_block` should have been called"
async def handle_first_tick(self, slot: Slot) -> None: head = self.chain.get_canonical_head() state_machine = self.chain.get_state_machine() state = state_machine.state self.logger.debug( # Align with debug log below bold_green("Head epoch=%s slot=%s state_root=%s"), state.current_epoch(self.slots_per_epoch), head.slot, encode_hex(head.state_root), ) self.logger.debug( bold_green("Justified epoch=%s root=%s (current)"), state.current_justified_epoch, encode_hex(state.current_justified_root), ) self.logger.debug( bold_green("Justified epoch=%s root=%s (previous)"), state.previous_justified_epoch, encode_hex(state.previous_justified_root), ) self.logger.debug( bold_green("Finalized epoch=%s root=%s"), state.finalized_epoch, encode_hex(state.finalized_root), ) self.logger.debug( bold_green("current_epoch_attestations %s"), state.current_epoch_attestations, ) self.logger.debug( bold_green("previous_epoch_attestations %s"), state.previous_epoch_attestations, ) proposer_index = _get_proposer_index( state, slot, state_machine.config, ) # `latest_proposed_epoch` is used to prevent validator from erraneously proposing twice # in the same epoch due to service crashing. epoch = slot_to_epoch(slot, self.slots_per_epoch) if proposer_index in self.validator_privkeys: has_proposed = epoch <= self.latest_proposed_epoch[proposer_index] if not has_proposed: self.propose_block( proposer_index=proposer_index, slot=slot, state=state, state_machine=state_machine, head_block=head, ) self.latest_proposed_epoch[proposer_index] = epoch
def _corrupt_signature(slots_per_epoch, params, fork): message_hash = b'\x12' * 32 privkey = 42 domain_type = SignatureDomain.DOMAIN_ATTESTATION domain = get_domain( fork=fork, epoch=slot_to_epoch(params["data"].slot, slots_per_epoch), domain_type=domain_type, ) corrupt_signature = bls.sign(message_hash, privkey, domain) return assoc(params, "aggregate_signature", corrupt_signature)
def sign_attestation(message: bytes, privkey: int, fork: Fork, slot: SlotNumber, epoch_length: int) -> BLSSignature: domain = get_domain( fork, slot_to_epoch(slot, epoch_length), SignatureDomain.DOMAIN_ATTESTATION, ) return bls.sign( message=message, privkey=privkey, domain=domain, )
def validate_attestation_aggregate_signature(state: BeaconState, attestation: Attestation, genesis_epoch: EpochNumber, 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, bitfield=attestation.aggregation_bitfield, genesis_epoch=genesis_epoch, 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, epoch=slot_to_epoch(attestation.data.slot, epoch_length), 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 _corrupt_signature(epoch_length, params, fork): message = bytes.fromhex("deadbeefcafe") privkey = 42 domain_type = SignatureDomain.DOMAIN_ATTESTATION domain = get_domain( fork=fork, epoch=slot_to_epoch(params["data"].slot, epoch_length), domain_type=domain_type, ) corrupt_signature = bls.sign(message, privkey, domain) return assoc(params, "aggregate_signature", corrupt_signature)
def sign_transaction(*, message_hash: Hash32, privkey: int, fork: Fork, slot: Slot, signature_domain: SignatureDomain, slots_per_epoch: int) -> BLSSignature: domain = get_domain( fork, slot_to_epoch(slot, slots_per_epoch), signature_domain, ) return bls.sign( message_hash=message_hash, privkey=privkey, domain=domain, )
def sign_proof_of_possession(deposit_input: DepositInput, privkey: int, fork: Fork, slot: Slot, slots_per_epoch: int) -> BLSSignature: domain = get_domain( fork, slot_to_epoch(slot, slots_per_epoch), SignatureDomain.DOMAIN_DEPOSIT, ) return bls.sign( message_hash=deposit_input.root, privkey=privkey, domain=domain, )
def _find_latest_attestation_targets( state: BeaconState, store: Store, config: Eth2Config) -> Iterable[AttestationTarget]: epoch = slot_to_epoch(state.slot, config.SLOTS_PER_EPOCH) active_validators = get_active_validator_indices( state.validators, epoch, ) return filter( second, map( _find_latest_attestation_target(store), active_validators, ))
def sign_transaction(*, message_hash: Hash32, privkey: int, state: BeaconState, slot: Slot, signature_domain: SignatureDomain, slots_per_epoch: int) -> BLSSignature: domain = get_domain( state, signature_domain, slots_per_epoch, message_epoch=slot_to_epoch(slot, slots_per_epoch), ) return bls.sign( message_hash=message_hash, privkey=privkey, domain=domain, )
def _get_target_root(state: BeaconState, config: Eth2Config, beacon_block_root: Hash32) -> Hash32: epoch_start_slot = get_epoch_start_slot( slot_to_epoch(state.slot, config.SLOTS_PER_EPOCH), config.SLOTS_PER_EPOCH, ) if epoch_start_slot == state.slot: return beacon_block_root else: return get_block_root( state, epoch_start_slot, config.SLOTS_PER_HISTORICAL_ROOT, )