def calc_merkle_tree_from_leaves(leaves: Sequence[Hash32]) -> MerkleTree: if len(leaves) == 0: raise ValueError("No leaves given") tree: Tuple[Sequence[Hash32], ...] = (leaves, ) for i in range(TreeDepth): if len(tree[0]) % 2 == 1: tree = update_tuple_item( tree, 0, tuple(tree[0]) + (EmptyNodeHashes[i], ), ) tree = tuple(cons(_hash_layer(tree[0]), tree)) return MerkleTree(tree)
def _compute_next_randao_mixes(state: BeaconState, config: Eth2Config) -> Tuple[Hash32, ...]: current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH) next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH) return update_tuple_item( state.randao_mixes, next_epoch % config.EPOCHS_PER_HISTORICAL_VECTOR, get_randao_mix( state, current_epoch, config.SLOTS_PER_EPOCH, config.EPOCHS_PER_HISTORICAL_VECTOR, ), )
def _compute_next_active_index_roots(state: BeaconState, config: Eth2Config) -> Tuple[Hash32, ...]: next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH) index_root_position = (next_epoch + config.ACTIVATION_EXIT_DELAY ) % config.EPOCHS_PER_HISTORICAL_VECTOR validator_indices_for_new_active_index_root = get_active_validator_indices( state.validators, Epoch(next_epoch + config.ACTIVATION_EXIT_DELAY)) new_active_index_root = ssz.get_hash_tree_root( validator_indices_for_new_active_index_root, ssz.sedes.List(ssz.uint64, config.VALIDATOR_REGISTRY_LIMIT), ) return update_tuple_item(state.active_index_roots, index_root_position, new_active_index_root)
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 = _update_latest_index_roots(state, CommitteeConfig(config)) 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 _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 test_process_final_updates(genesis_state, state_slot, attestation_slot, len_latest_attestations, expected_result_len_latest_attestations, config, sample_attestation_params): state = genesis_state.copy( slot=state_slot, ) epoch = state.slot // config.EPOCH_LENGTH current_index = (epoch + 1) % config.LATEST_PENALIZED_EXIT_LENGTH previous_index = epoch % config.LATEST_PENALIZED_EXIT_LENGTH # Assume `len_latest_attestations` attestations in state.latest_attestations # with attestation.data.slot = attestation_slot attestation = Attestation(**sample_attestation_params) latest_attestations = [ attestation.copy( data=attestation.data.copy( slot=attestation_slot ) ) for i in range(len_latest_attestations) ] # Fill latest_penalized_balances penalized_balance_of_previous_epoch = 100 latest_penalized_balances = update_tuple_item( state.latest_penalized_balances, previous_index, penalized_balance_of_previous_epoch, ) state = state.copy( latest_penalized_balances=latest_penalized_balances, latest_attestations=latest_attestations, ) result_state = process_final_updates(state, config) assert ( result_state.latest_penalized_balances[current_index] == penalized_balance_of_previous_epoch ) assert len(result_state.latest_attestations) == expected_result_len_latest_attestations for attestation in result_state.latest_attestations: assert attestation.data.slot >= state_slot - config.EPOCH_LENGTH
def _update_validator_balance(self, validator_index: ValidatorIndex, balance: Gwei) -> 'BeaconState': """ Update the balance of validator of the given ``validator_index``. """ if validator_index >= len(self.balances) or validator_index < 0: raise IndexError("Incorrect validator index") return self.copy( balances=update_tuple_item( self.balances, validator_index, balance, ) )
def process_final_updates(state: BeaconState, config: BeaconConfig) -> BeaconState: epoch = state.slot // config.EPOCH_LENGTH current_index = (epoch + 1) % config.LATEST_PENALIZED_EXIT_LENGTH previous_index = epoch % config.LATEST_PENALIZED_EXIT_LENGTH state = state.copy(latest_penalized_balances=update_tuple_item( state.latest_penalized_balances, current_index, state.latest_penalized_balances[previous_index], ), ) epoch_start = state.slot - config.EPOCH_LENGTH latest_attestations = tuple( filter(lambda attestation: attestation.data.slot >= epoch_start, state.latest_attestations)) state = state.copy(latest_attestations=latest_attestations, ) return state
def test_check_if_update_validator_registry(genesis_state, state_slot, validator_registry_update_epoch, finalized_epoch, has_crosslink, crosslink_epoch, expected_need_to_update, config): state = genesis_state.copy( slot=state_slot, finalized_epoch=finalized_epoch, validator_registry_update_epoch=validator_registry_update_epoch, ) if has_crosslink: crosslink = CrosslinkRecord( epoch=crosslink_epoch, crosslink_data_root=ZERO_HASH32, ) latest_crosslinks = state.latest_crosslinks for shard in range(config.SHARD_COUNT): latest_crosslinks = update_tuple_item( latest_crosslinks, shard, crosslink, ) state = state.copy( latest_crosslinks=latest_crosslinks, ) need_to_update, num_shards_in_committees = _check_if_update_validator_registry(state, config) assert need_to_update == expected_need_to_update if expected_need_to_update: expected_num_shards_in_committees = get_current_epoch_committee_count( state, shard_count=config.SHARD_COUNT, slots_per_epoch=config.SLOTS_PER_EPOCH, target_committee_size=config.TARGET_COMMITTEE_SIZE, ) assert num_shards_in_committees == expected_num_shards_in_committees else: assert num_shards_in_committees == 0
def process_crosslinks(state: BeaconState, config: Eth2Config) -> BeaconState: current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH) previous_epoch = state.previous_epoch(config.SLOTS_PER_EPOCH, config.GENESIS_EPOCH) new_current_crosslinks = state.current_crosslinks for epoch in (previous_epoch, current_epoch): active_validators_indices = get_active_validator_indices( state.validators, epoch ) epoch_committee_count = get_committee_count( len(active_validators_indices), config.SHARD_COUNT, config.SLOTS_PER_EPOCH, config.TARGET_COMMITTEE_SIZE, ) epoch_start_shard = get_start_shard(state, epoch, CommitteeConfig(config)) for shard_offset in range(epoch_committee_count): shard = Shard((epoch_start_shard + shard_offset) % config.SHARD_COUNT) crosslink_committee = set( get_crosslink_committee(state, epoch, shard, CommitteeConfig(config)) ) if not crosslink_committee: # empty crosslink committee this epoch continue winning_crosslink, attesting_indices = get_winning_crosslink_and_attesting_indices( state=state, epoch=epoch, shard=shard, config=config ) threshold_met = _is_threshold_met_against_committee( state, attesting_indices, crosslink_committee ) if threshold_met: new_current_crosslinks = update_tuple_item( new_current_crosslinks, shard, winning_crosslink ) return state.copy( previous_crosslinks=state.current_crosslinks, current_crosslinks=new_current_crosslinks, )
def process_eth1_data(state: BeaconState, block: BaseBeaconBlock) -> BeaconState: try: vote_index, original_vote = first( (index, eth1_data_vote) for index, eth1_data_vote in enumerate(state.eth1_data_votes) if block.eth1_data == eth1_data_vote.eth1_data) except StopIteration: new_vote = Eth1DataVote( eth1_data=block.eth1_data, vote_count=1, ) state = state.copy(eth1_data_votes=state.eth1_data_votes + (new_vote, )) else: updated_vote = original_vote.copy(vote_count=original_vote.vote_count + 1) state = state.copy(eth1_data_votes=update_tuple_item( state.eth1_data_votes, vote_index, updated_vote)) return state
def test_get_matching_target_attestations(genesis_state, config): some_epoch = config.GENESIS_EPOCH + 20 some_slot = compute_start_slot_of_epoch(some_epoch, config.SLOTS_PER_EPOCH) some_target_root = b"\x33" * 32 target_attestations = tuple((PendingAttestation(data=AttestationData( target=Checkpoint(root=some_target_root))) for _ in range(3))) current_epoch_attestations = target_attestations + tuple( (PendingAttestation(data=AttestationData(target=Checkpoint( root=b"\x44" * 32))) for _ in range(3))) state = genesis_state.copy( slot=some_slot + 1, block_roots=update_tuple_item( genesis_state.block_roots, some_slot % config.SLOTS_PER_HISTORICAL_ROOT, some_target_root, ), current_epoch_attestations=current_epoch_attestations, ) attestations = get_matching_target_attestations(state, some_epoch, config) assert attestations == target_attestations
def get_compact_committees_root(state: BeaconState, epoch: Epoch, config: CommitteeConfig) -> Hash32: shard_count = config.SHARD_COUNT committees = (CompactCommittee(), ) * shard_count start_shard = get_start_shard(state, epoch, config) active_validator_indices = get_active_validator_indices( state.validators, epoch) committee_count = get_committee_count( len(active_validator_indices), config.SHARD_COUNT, config.SLOTS_PER_EPOCH, config.TARGET_COMMITTEE_SIZE, ) for committee_number in range(committee_count): shard = Shard((start_shard + committee_number) % shard_count) compact_committee = _compute_compact_committee_for_shard_in_epoch( state, epoch, shard, config) committees = update_tuple_item(committees, shard, compact_committee) return ssz.get_hash_tree_root(committees, sedes=ssz.sedes.Vector( CompactCommittee, shard_count))
def _update_latest_index_roots(state: BeaconState, config: BeaconConfig) -> BeaconState: """ Return the BeaconState with updated `latest_index_roots`. """ next_epoch = state.next_epoch(config.EPOCH_LENGTH) # TODO: chanege to hash_tree_root active_validator_indices = get_active_validator_indices( state.validator_registry, next_epoch, ) index_root = hash_eth2(b''.join( [index.to_bytes(32, 'big') for index in active_validator_indices])) latest_index_roots = update_tuple_item( state.latest_index_roots, next_epoch % config.LATEST_INDEX_ROOTS_LENGTH, index_root, ) return state.copy(latest_index_roots=latest_index_roots, )
def _update_latest_active_index_roots( state: BeaconState, committee_config: CommitteeConfig) -> BeaconState: """ Return the BeaconState with updated `latest_active_index_roots`. """ next_epoch = state.next_epoch(committee_config.SLOTS_PER_EPOCH) # TODO: chanege to hash_tree_root active_validator_indices = get_active_validator_indices( state.validator_registry, Epoch(next_epoch + committee_config.ACTIVATION_EXIT_DELAY), ) index_root = hash_eth2(b''.join( [index.to_bytes(32, 'little') for index in active_validator_indices])) latest_active_index_roots = update_tuple_item( state.latest_active_index_roots, ((next_epoch + committee_config.ACTIVATION_EXIT_DELAY) % committee_config.LATEST_ACTIVE_INDEX_ROOTS_LENGTH), index_root, ) return state.copy(latest_active_index_roots=latest_active_index_roots, )
def process_randao(state: BeaconState, block: BaseBeaconBlock, config: BeaconConfig) -> BeaconState: proposer_index = get_beacon_proposer_index( state=state, slot=state.slot, committee_config=CommitteeConfig(config), ) proposer = state.validator_registry[proposer_index] epoch = state.current_epoch(config.EPOCH_LENGTH) validate_randao_reveal( randao_reveal=block.randao_reveal, proposer_pubkey=proposer.pubkey, epoch=epoch, fork=state.fork, ) randao_mix_index = epoch % config.LATEST_RANDAO_MIXES_LENGTH new_randao_mix = bitwise_xor( get_randao_mix( state=state, epoch=epoch, epoch_length=config.EPOCH_LENGTH, latest_randao_mixes_length=config.LATEST_RANDAO_MIXES_LENGTH, ), hash_eth2(block.randao_reveal), ) return state.copy( latest_randao_mixes=update_tuple_item( state.latest_randao_mixes, randao_mix_index, new_randao_mix, ), )
def _update_latest_active_index_roots( state: BeaconState, committee_config: CommitteeConfig) -> BeaconState: """ Return the BeaconState with updated `latest_active_index_roots`. """ next_epoch = state.next_epoch(committee_config.SLOTS_PER_EPOCH) active_validator_indices = get_active_validator_indices( state.validator_registry, Epoch(next_epoch + committee_config.ACTIVATION_EXIT_DELAY), ) index_root = ssz.hash_tree_root( active_validator_indices, ssz.sedes.List(ssz.uint64), ) latest_active_index_roots = update_tuple_item( state.latest_active_index_roots, ((next_epoch + committee_config.ACTIVATION_EXIT_DELAY) % committee_config.LATEST_ACTIVE_INDEX_ROOTS_LENGTH), index_root, ) return state.copy(latest_active_index_roots=latest_active_index_roots, )
def process_crosslinks(state: BeaconState, config: BeaconConfig) -> BeaconState: """ Implement 'per-epoch-processing.crosslinks' portion of Phase 0 spec: https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#crosslinks For each shard from the past two epochs, find the shard block root that has been attested to by the most stake. If enough(>= 2/3 total stake) attesting stake, update the crosslink record of that shard. Return resulting ``state`` """ latest_crosslinks = state.latest_crosslinks previous_epoch_attestations = get_previous_epoch_attestations( state, config.EPOCH_LENGTH, config.GENESIS_EPOCH, ) current_epoch_attestations = get_current_epoch_attestations(state, config.EPOCH_LENGTH) prev_epoch_start_slot = get_epoch_start_slot( state.previous_epoch(config.EPOCH_LENGTH, config.GENESIS_EPOCH), config.EPOCH_LENGTH, ) next_epoch_start_slot = get_epoch_start_slot( state.next_epoch(config.EPOCH_LENGTH), config.EPOCH_LENGTH, ) for slot in range(prev_epoch_start_slot, next_epoch_start_slot): crosslink_committees_at_slot = get_crosslink_committees_at_slot( state, slot, CommitteeConfig(config), ) for crosslink_committee, shard in crosslink_committees_at_slot: try: winning_root, total_attesting_balance = get_winning_root( state=state, shard=shard, # Use `_filter_attestations_by_shard` to filter out attestations # not attesting to this shard so we don't need to going over # irrelevent attestations over and over again. attestations=_filter_attestations_by_shard( previous_epoch_attestations + current_epoch_attestations, shard, ), max_deposit_amount=config.MAX_DEPOSIT_AMOUNT, committee_config=CommitteeConfig(config), ) except NoWinningRootError: # No winning shard block root found for this shard. pass else: total_balance = sum( get_effective_balance(state.validator_balances, i, config.MAX_DEPOSIT_AMOUNT) for i in crosslink_committee ) if 3 * total_attesting_balance >= 2 * total_balance: latest_crosslinks = update_tuple_item( latest_crosslinks, shard, CrosslinkRecord( epoch=state.current_epoch(config.EPOCH_LENGTH), shard_block_root=winning_root, ), ) else: # Don't update the crosslink of this shard pass state = state.copy( latest_crosslinks=latest_crosslinks, ) return state
def _settle_penality_to_validator_and_whistleblower( *, state: BeaconState, validator_index: ValidatorIndex, latest_penalized_exit_length: int, whistleblower_reward_quotient: int, genesis_epoch: EpochNumber, epoch_length: int, max_deposit_amount: Gwei, target_committee_size: int, shard_count: int) -> BeaconState: """ Apply penality/reward to validator and whistleblower and update the meta data More intuitive pseudo-code: current_epoch_penalization_index = (state.slot // EPOCH_LENGTH) % LATEST_PENALIZED_EXIT_LENGTH state.latest_penalized_balances[current_epoch_penalization_index] += ( get_effective_balance(state, index) ) whistleblower_index = get_beacon_proposer_index(state, state.slot) whistleblower_reward = get_effective_balance(state, index) // WHISTLEBLOWER_REWARD_QUOTIENT state.validator_balances[whistleblower_index] += whistleblower_reward state.validator_balances[index] -= whistleblower_reward validator.penalized_epoch = slot_to_epoch(state.slot) """ # Update `state.latest_penalized_balances` current_epoch_penalization_index = state.current_epoch( epoch_length) % latest_penalized_exit_length effective_balance = get_effective_balance( state.validator_balances, validator_index, max_deposit_amount, ) penalized_exit_balance = ( state.latest_penalized_balances[current_epoch_penalization_index] + effective_balance ) latest_penalized_balances = update_tuple_item( tuple_data=state.latest_penalized_balances, index=current_epoch_penalization_index, new_value=penalized_exit_balance, ) state = state.copy( latest_penalized_balances=latest_penalized_balances, ) # Update whistleblower's balance whistleblower_reward = ( effective_balance // whistleblower_reward_quotient ) whistleblower_index = get_beacon_proposer_index( state, state.slot, genesis_epoch=genesis_epoch, epoch_length=epoch_length, target_committee_size=target_committee_size, shard_count=shard_count, ) state = state.update_validator_balance( whistleblower_index, state.validator_balances[whistleblower_index] + whistleblower_reward, ) # Update validator's balance and `penalized_epoch` field validator = state.validator_registry[validator_index] validator = validator.copy( penalized_epoch=state.current_epoch(epoch_length), ) state = state.update_validator( validator_index, validator, state.validator_balances[validator_index] - whistleblower_reward, ) return state
def process_crosslinks(state: BeaconState, config: Eth2Config) -> BeaconState: """ Implement 'per-epoch-processing.crosslinks' portion of Phase 0 spec: https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#crosslinks For each shard from the past two epochs, find the shard block root that has been attested to by the most stake. If enough(>= 2/3 total stake) attesting stake, update the crosslink record of that shard. Return resulting ``state`` """ latest_crosslinks = state.latest_crosslinks effective_balances = { ValidatorIndex(index): get_effective_balance( state.validator_balances, ValidatorIndex(index), config.MAX_DEPOSIT_AMOUNT, ) for index in range(len(state.validator_registry)) } previous_epoch_start_slot = get_epoch_start_slot( state.previous_epoch(config.SLOTS_PER_EPOCH), config.SLOTS_PER_EPOCH, ) next_epoch_start_slot = get_epoch_start_slot( state.next_epoch(config.SLOTS_PER_EPOCH), config.SLOTS_PER_EPOCH, ) for slot in range(previous_epoch_start_slot, next_epoch_start_slot): crosslink_committees_at_slot = get_crosslink_committees_at_slot( state, slot, CommitteeConfig(config), ) for crosslink_committee, shard in crosslink_committees_at_slot: winning_root, attesting_validator_indices = get_winning_root_and_participants( state=state, shard=shard, effective_balances=effective_balances, committee_config=CommitteeConfig(config), ) if len(attesting_validator_indices) > 0: total_attesting_balance = get_total_balance( state.validator_balances, attesting_validator_indices, config.MAX_DEPOSIT_AMOUNT, ) total_balance = get_total_balance( state.validator_balances, crosslink_committee, config.MAX_DEPOSIT_AMOUNT, ) if 3 * total_attesting_balance >= 2 * total_balance: latest_crosslinks = update_tuple_item( latest_crosslinks, shard, CrosslinkRecord( epoch=slot_to_epoch(Slot(slot), config.SLOTS_PER_EPOCH), crosslink_data_root=winning_root, ), ) state = state.copy(latest_crosslinks=latest_crosslinks, ) return state
def test_process_rewards_and_penalties_for_finality( n_validators_state, config, slots_per_epoch, target_committee_size, shard_count, min_attestation_inclusion_delay, inactivity_penalty_quotient, finalized_epoch, current_slot, penalized_validator_indices, previous_epoch_active_validator_indices, previous_epoch_attester_indices, previous_epoch_boundary_head_attester_indices, inclusion_distances, effective_balance, base_reward, expected_rewards_received, sample_pending_attestation_record_params, sample_attestation_data_params): validator_registry = n_validators_state.validator_registry for index in penalized_validator_indices: validator_record = validator_registry[index].copy( slashed=True, ) validator_registry = update_tuple_item(validator_registry, index, validator_record) state = n_validators_state.copy( slot=current_slot, finalized_epoch=finalized_epoch, validator_registry=validator_registry, ) previous_total_balance = len(previous_epoch_active_validator_indices) * effective_balance attestation_slot = current_slot - slots_per_epoch inclusion_infos = { index: InclusionInfo( attestation_slot + inclusion_distances[index], attestation_slot, ) for index in previous_epoch_attester_indices } effective_balances = { index: effective_balance for index in previous_epoch_active_validator_indices } base_rewards = { index: base_reward for index in previous_epoch_active_validator_indices } rewards_received = { index: 0 for index in range(len(state.validator_registry)) } prev_epoch_start_slot = get_epoch_start_slot( state.previous_epoch(config.SLOTS_PER_EPOCH, config.GENESIS_EPOCH), slots_per_epoch, ) prev_epoch_crosslink_committees = [ get_crosslink_committees_at_slot( state, slot, CommitteeConfig(config), )[0] for slot in range(prev_epoch_start_slot, prev_epoch_start_slot + slots_per_epoch) ] prev_epoch_attestations = [] for i in range(slots_per_epoch): committee, shard = prev_epoch_crosslink_committees[i] participants_bitfield = get_empty_bitfield(target_committee_size) for index in previous_epoch_boundary_head_attester_indices: if index in committee: participants_bitfield = set_voted(participants_bitfield, committee.index(index)) prev_epoch_attestations.append( PendingAttestationRecord(**sample_pending_attestation_record_params).copy( data=AttestationData(**sample_attestation_data_params).copy( slot=(prev_epoch_start_slot + i), shard=shard, epoch_boundary_root=get_block_root( state, prev_epoch_start_slot, config.LATEST_BLOCK_ROOTS_LENGTH, ), beacon_block_root=get_block_root( state, (prev_epoch_start_slot + i), config.LATEST_BLOCK_ROOTS_LENGTH, ), ), aggregation_bitfield=participants_bitfield, ) ) state = state.copy( latest_attestations=prev_epoch_attestations, ) rewards_received = _process_rewards_and_penalties_for_finality( state, config, previous_epoch_active_validator_indices, previous_total_balance, prev_epoch_attestations, previous_epoch_attester_indices, inclusion_infos, effective_balances, base_rewards, rewards_received, ) for index, reward_received in rewards_received.items(): assert reward_received == expected_rewards_received[index]
def _settle_penality_to_validator_and_whistleblower( *, state: BeaconState, validator_index: ValidatorIndex, latest_slashed_exit_length: int, whistleblower_reward_quotient: int, max_deposit_amount: Gwei, committee_config: CommitteeConfig) -> BeaconState: """ Apply penality/reward to validator and whistleblower and update the meta data More intuitive pseudo-code: current_epoch_penalization_index = (state.slot // SLOTS_PER_EPOCH) % LATEST_SLASHED_EXIT_LENGTH state.latest_slashed_balances[current_epoch_penalization_index] += ( get_effective_balance(state, index) ) whistleblower_index = get_beacon_proposer_index(state, state.slot) whistleblower_reward = get_effective_balance(state, index) // WHISTLEBLOWER_REWARD_QUOTIENT state.validator_balances[whistleblower_index] += whistleblower_reward state.validator_balances[index] -= whistleblower_reward validator.slashed = True validator.withdrawable_epoch = get_current_epoch(state) + LATEST_SLASHED_EXIT_LENGTH """ slots_per_epoch = committee_config.SLOTS_PER_EPOCH # Update `state.latest_slashed_balances` current_epoch_penalization_index = state.current_epoch( slots_per_epoch) % latest_slashed_exit_length effective_balance = get_effective_balance( state.validator_balances, validator_index, max_deposit_amount, ) slashed_exit_balance = ( state.latest_slashed_balances[current_epoch_penalization_index] + effective_balance) latest_slashed_balances = update_tuple_item( tuple_data=state.latest_slashed_balances, index=current_epoch_penalization_index, new_value=slashed_exit_balance, ) state = state.copy(latest_slashed_balances=latest_slashed_balances, ) # Update whistleblower's balance whistleblower_reward = (effective_balance // whistleblower_reward_quotient) whistleblower_index = get_beacon_proposer_index( state, state.slot, committee_config, ) state = state.update_validator_balance( whistleblower_index, state.validator_balances[whistleblower_index] + whistleblower_reward, ) # Update validator's balance and `slashed`, `withdrawable_epoch` field validator = state.validator_registry[validator_index].copy( slashed=True, withdrawable_epoch=state.current_epoch(slots_per_epoch) + latest_slashed_exit_length, ) state = state.update_validator( validator_index, validator, state.validator_balances[validator_index] - whistleblower_reward, ) return state
def get_initial_beacon_state(*, initial_validator_deposits: Sequence[Deposit], genesis_time: Timestamp, latest_eth1_data: Eth1Data, genesis_slot: SlotNumber, genesis_epoch: EpochNumber, genesis_fork_version: int, genesis_start_shard: ShardNumber, shard_count: int, seed_lookahead: int, latest_block_roots_length: int, latest_index_roots_length: int, epoch_length: int, max_deposit_amount: Gwei, latest_penalized_exit_length: int, latest_randao_mixes_length: int, entry_exit_delay: int) -> BeaconState: state = BeaconState( # Misc slot=genesis_slot, genesis_time=genesis_time, fork=Fork( previous_version=genesis_fork_version, current_version=genesis_fork_version, epoch=genesis_epoch, ), # Validator registry validator_registry=(), validator_balances=(), validator_registry_update_epoch=genesis_epoch, validator_registry_exit_count=0, # Randomness and committees latest_randao_mixes=tuple(ZERO_HASH32 for _ in range(latest_randao_mixes_length)), previous_epoch_start_shard=genesis_start_shard, current_epoch_start_shard=genesis_start_shard, previous_calculation_epoch=genesis_epoch, current_calculation_epoch=genesis_epoch, previous_epoch_seed=ZERO_HASH32, current_epoch_seed=ZERO_HASH32, # Finality previous_justified_epoch=genesis_epoch, justified_epoch=genesis_epoch, justification_bitfield=0, finalized_epoch=genesis_epoch, # Recent state latest_crosslinks=tuple([ CrosslinkRecord(epoch=genesis_epoch, shard_block_root=ZERO_HASH32) for _ in range(shard_count) ]), latest_block_roots=tuple(ZERO_HASH32 for _ in range(latest_block_roots_length)), latest_index_roots=tuple(ZERO_HASH32 for _ in range(latest_index_roots_length)), latest_penalized_balances=tuple( Gwei(0) for _ in range(latest_penalized_exit_length)), latest_attestations=(), batched_block_roots=(), # Ethereum 1.0 chain data latest_eth1_data=latest_eth1_data, eth1_data_votes=(), ) # Process initial deposits for deposit in initial_validator_deposits: state = process_deposit( state=state, pubkey=deposit.deposit_data.deposit_input.pubkey, amount=deposit.deposit_data.amount, proof_of_possession=deposit.deposit_data.deposit_input. proof_of_possession, withdrawal_credentials=deposit.deposit_data.deposit_input. withdrawal_credentials, randao_commitment=deposit.deposit_data.deposit_input. randao_commitment, epoch_length=epoch_length, ) # Process initial activations for validator_index, _ in enumerate(state.validator_registry): validator_index = ValidatorIndex(validator_index) is_enough_effective_balance = get_effective_balance( state.validator_balances, validator_index, max_deposit_amount, ) >= max_deposit_amount if is_enough_effective_balance: state = activate_validator( state=state, index=validator_index, is_genesis=True, genesis_epoch=genesis_epoch, epoch_length=epoch_length, entry_exit_delay=entry_exit_delay, ) # TODO: chanege to hash_tree_root active_validator_indices = get_active_validator_indices( state.validator_registry, genesis_epoch, ) index_root = hash_eth2(b''.join( [index.to_bytes(32, 'big') for index in active_validator_indices])) latest_index_roots = update_tuple_item( state.latest_index_roots, genesis_epoch % latest_index_roots_length, index_root, ) state = state.copy(latest_index_roots=latest_index_roots, ) current_epoch_seed = generate_seed( state=state, epoch=genesis_epoch, epoch_length=epoch_length, seed_lookahead=seed_lookahead, entry_exit_delay=entry_exit_delay, latest_index_roots_length=latest_index_roots_length, latest_randao_mixes_length=latest_randao_mixes_length, ) state = state.copy(current_epoch_seed=current_epoch_seed, ) return state
def _compute_next_slashings(state: BeaconState, config: Eth2Config) -> Tuple[Gwei, ...]: next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH) return update_tuple_item( state.slashings, next_epoch % config.EPOCHS_PER_SLASHINGS_VECTOR, Gwei(0) )