Documentation ¶
Overview ¶
Package epoch contains epoch processing libraries. These libraries process new balance for the validators, justify and finalize new check points, shuffle and reassign validators to different slots and shards.
Index ¶
- func AttestingBalance(state *pb.BeaconState, atts []*pb.PendingAttestation) (uint64, error)
- func BaseReward(state *pb.BeaconState, index uint64) (uint64, error)
- func ComputeValidatorParticipation(state *pb.BeaconState) (*ethpb.ValidatorParticipation, error)
- func ProcessCrosslinks(state *pb.BeaconState) (*pb.BeaconState, error)
- func ProcessFinalUpdates(state *pb.BeaconState) (*pb.BeaconState, error)
- func ProcessJustificationAndFinalization(state *pb.BeaconState, prevAttestedBal uint64, currAttestedBal uint64) (*pb.BeaconState, error)
- func ProcessRegistryUpdates(state *pb.BeaconState) (*pb.BeaconState, error)
- func ProcessRewardsAndPenalties(state *pb.BeaconState) (*pb.BeaconState, error)
- func ProcessSlashings(state *pb.BeaconState) (*pb.BeaconState, error)
- func WinningCrosslink(state *pb.BeaconState, shard uint64, epoch uint64) (*ethpb.Crosslink, []uint64, error)
- type MatchedAttestations
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AttestingBalance ¶
func AttestingBalance(state *pb.BeaconState, atts []*pb.PendingAttestation) (uint64, error)
AttestingBalance returns the total balance from all the attesting indices.
WARNING: This method allocates a new copy of the attesting validator indices set and is considered to be very memory expensive. Avoid using this unless you really need to get attesting balance from attestations.
Spec pseudocode definition:
def get_attesting_balance(state: BeaconState, attestations: List[PendingAttestation]) -> Gwei: return get_total_balance(state, get_unslashed_attesting_indices(state, attestations))
func BaseReward ¶
func BaseReward(state *pb.BeaconState, index uint64) (uint64, error)
BaseReward takes state and validator index and calculate individual validator's base reward quotient.
Note: Adjusted quotient is calculated of base reward because it's too inefficient to repeat the same calculation for every validator versus just doing it once.
Spec pseudocode definition:
def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei: total_balance = get_total_active_balance(state) effective_balance = state.validator_registry[index].effective_balance return effective_balance * BASE_REWARD_FACTOR // integer_squareroot(total_balance) // BASE_REWARDS_PER_EPOCH
func ComputeValidatorParticipation ¶
func ComputeValidatorParticipation(state *pb.BeaconState) (*ethpb.ValidatorParticipation, error)
ComputeValidatorParticipation by matching validator attestations during the epoch, computing the attesting balance, and how much attested compared to the total balances.
func ProcessCrosslinks ¶
func ProcessCrosslinks(state *pb.BeaconState) (*pb.BeaconState, error)
ProcessCrosslinks processes crosslink and finds the crosslink with enough state to make it canonical in state.
Spec pseudocode definition:
def process_crosslinks(state: BeaconState) -> None: state.previous_crosslinks = [c for c in state.current_crosslinks] for epoch in (get_previous_epoch(state), get_current_epoch(state)): for offset in range(get_epoch_committee_count(state, epoch)): shard = (get_epoch_start_shard(state, epoch) + offset) % SHARD_COUNT crosslink_committee = get_crosslink_committee(state, epoch, shard) winning_crosslink, attesting_indices = get_winning_crosslink_and_attesting_indices(state, epoch, shard) if 3 * get_total_balance(state, attesting_indices) >= 2 * get_total_balance(state, crosslink_committee): state.current_crosslinks[shard] = winning_crosslink
func ProcessFinalUpdates ¶
func ProcessFinalUpdates(state *pb.BeaconState) (*pb.BeaconState, error)
ProcessFinalUpdates processes the final updates during epoch processing.
Spec pseudocode definition:
def process_final_updates(state: BeaconState) -> None: current_epoch = get_current_epoch(state) next_epoch = Epoch(current_epoch + 1) # Reset eth1 data votes if (state.slot + 1) % SLOTS_PER_ETH1_VOTING_PERIOD == 0: state.eth1_data_votes = [] # Update effective balances with hysteresis for index, validator in enumerate(state.validators): balance = state.balances[index] HALF_INCREMENT = EFFECTIVE_BALANCE_INCREMENT // 2 if balance < validator.effective_balance or validator.effective_balance + 3 * HALF_INCREMENT < balance: validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE) # Set active index root index_epoch = Epoch(next_epoch + ACTIVATION_EXIT_DELAY) index_root_position = index_epoch % EPOCHS_PER_HISTORICAL_VECTOR indices_list = List[ValidatorIndex, VALIDATOR_REGISTRY_LIMIT](get_active_validator_indices(state, index_epoch)) state.active_index_roots[index_root_position] = hash_tree_root(indices_list) # Set committees root committee_root_position = next_epoch % EPOCHS_PER_HISTORICAL_VECTOR state.compact_committees_roots[committee_root_position] = get_compact_committees_root(state, next_epoch) # Reset slashings state.slashings[next_epoch % EPOCHS_PER_SLASHINGS_VECTOR] = Gwei(0) # Set randao mix state.randao_mixes[next_epoch % EPOCHS_PER_HISTORICAL_VECTOR] = get_randao_mix(state, current_epoch) # Set historical root accumulator if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0: historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots) state.historical_roots.append(hash_tree_root(historical_batch)) # Update start shard state.start_shard = Shard((state.start_shard + get_shard_delta(state, current_epoch)) % SHARD_COUNT) # Rotate current/previous epoch attestations state.previous_epoch_attestations = state.current_epoch_attestations state.current_epoch_attestations = []
func ProcessJustificationAndFinalization ¶
func ProcessJustificationAndFinalization(state *pb.BeaconState, prevAttestedBal uint64, currAttestedBal uint64) (*pb.BeaconState, error)
ProcessJustificationAndFinalization processes justification and finalization during epoch processing. This is where a beacon node can justify and finalize a new epoch.
Spec pseudocode definition:
def process_justification_and_finalization(state: BeaconState) -> None: if get_current_epoch(state) <= GENESIS_EPOCH + 1: return previous_epoch = get_previous_epoch(state) current_epoch = get_current_epoch(state) old_previous_justified_checkpoint = state.previous_justified_checkpoint old_current_justified_checkpoint = state.current_justified_checkpoint # Process justifications state.previous_justified_checkpoint = state.current_justified_checkpoint state.justification_bits[1:] = state.justification_bits[:-1] state.justification_bits[0] = 0b0 matching_target_attestations = get_matching_target_attestations(state, previous_epoch) # Previous epoch if get_attesting_balance(state, matching_target_attestations) * 3 >= get_total_active_balance(state) * 2: state.current_justified_checkpoint = Checkpoint(epoch=previous_epoch, root=get_block_root(state, previous_epoch)) state.justification_bits[1] = 0b1 matching_target_attestations = get_matching_target_attestations(state, current_epoch) # Current epoch if get_attesting_balance(state, matching_target_attestations) * 3 >= get_total_active_balance(state) * 2: state.current_justified_checkpoint = Checkpoint(epoch=current_epoch, root=get_block_root(state, current_epoch)) state.justification_bits[0] = 0b1 # Process finalizations bits = state.justification_bits # The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th as source if all(bits[1:4]) and old_previous_justified_checkpoint.epoch + 3 == current_epoch: state.finalized_checkpoint = old_previous_justified_checkpoint # The 2nd/3rd most recent epochs are justified, the 2nd using the 3rd as source if all(bits[1:3]) and old_previous_justified_checkpoint.epoch + 2 == current_epoch: state.finalized_checkpoint = old_previous_justified_checkpoint # The 1st/2nd/3rd most recent epochs are justified, the 1st using the 3rd as source if all(bits[0:3]) and old_current_justified_checkpoint.epoch + 2 == current_epoch: state.finalized_checkpoint = old_current_justified_checkpoint # The 1st/2nd most recent epochs are justified, the 1st using the 2nd as source if all(bits[0:2]) and old_current_justified_checkpoint.epoch + 1 == current_epoch: state.finalized_checkpoint = old_current_justified_checkpoint
func ProcessRegistryUpdates ¶
func ProcessRegistryUpdates(state *pb.BeaconState) (*pb.BeaconState, error)
ProcessRegistryUpdates rotates validators in and out of active pool. the amount to rotate is determined churn limit.
Spec pseudocode definition:
def process_registry_updates(state: BeaconState) -> None: # Process activation eligibility and ejections for index, validator in enumerate(state.validator_registry): if ( validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH and validator.effective_balance >= MAX_EFFECTIVE_BALANCE ): validator.activation_eligibility_epoch = get_current_epoch(state) if is_active_validator(validator, get_current_epoch(state)) and validator.effective_balance <= EJECTION_BALANCE: initiate_validator_exit(state, index) # Queue validators eligible for activation and not dequeued for activation prior to finalized epoch activation_queue = sorted([ index for index, validator in enumerate(state.validator_registry) if validator.activation_eligibility_epoch != FAR_FUTURE_EPOCH and validator.activation_epoch >= get_delayed_activation_exit_epoch(state.finalized_epoch) ], key=lambda index: state.validator_registry[index].activation_eligibility_epoch) # Dequeued validators for activation up to churn limit (without resetting activation epoch) for index in activation_queue[:get_churn_limit(state)]: validator = state.validator_registry[index] if validator.activation_epoch == FAR_FUTURE_EPOCH: validator.activation_epoch = get_delayed_activation_exit_epoch(get_current_epoch(state))
func ProcessRewardsAndPenalties ¶
func ProcessRewardsAndPenalties(state *pb.BeaconState) (*pb.BeaconState, error)
ProcessRewardsAndPenalties processes the rewards and penalties of individual validator.
Spec pseudocode definition:
def process_rewards_and_penalties(state: BeaconState) -> None: if get_current_epoch(state) == GENESIS_EPOCH: return rewards1, penalties1 = get_attestation_deltas(state) rewards2, penalties2 = get_crosslink_deltas(state) for i in range(len(state.validator_registry)): increase_balance(state, i, rewards1[i] + rewards2[i]) decrease_balance(state, i, penalties1[i] + penalties2[i])
func ProcessSlashings ¶
func ProcessSlashings(state *pb.BeaconState) (*pb.BeaconState, error)
ProcessSlashings processes the slashed validators during epoch processing,
def process_slashings(state: BeaconState) -> None: epoch = get_current_epoch(state) total_balance = get_total_active_balance(state) for index, validator in enumerate(state.validators): if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch: increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow penalty_numerator = validator.effective_balance // increment * min(sum(state.slashings) * 3, total_balance) penalty = penalty_numerator // total_balance * increment decrease_balance(state, ValidatorIndex(index), penalty)
func WinningCrosslink ¶
func WinningCrosslink(state *pb.BeaconState, shard uint64, epoch uint64) (*ethpb.Crosslink, []uint64, error)
WinningCrosslink returns the most staked balance-wise crosslink of a given shard and epoch. It also returns the attesting inaidces of the winning cross link.
Spec pseudocode definition:
def get_winning_crosslink_and_attesting_indices(state: BeaconState, epoch: Epoch, shard: Shard) -> Tuple[Crosslink, List[ValidatorIndex]]: attestations = [a for a in get_matching_source_attestations(state, epoch) if a.data.crosslink.shard == shard] crosslinks = list(filter( lambda c: hash_tree_root(state.current_crosslinks[shard]) in (c.parent_root, hash_tree_root(c)), [a.data.crosslink for a in attestations] )) # Winning crosslink has the crosslink data root with the most balance voting for it (ties broken lexicographically) winning_crosslink = max(crosslinks, key=lambda c: ( get_attesting_balance(state, [a for a in attestations if a.data.crosslink == c]), c.data_root ), default=Crosslink()) winning_attestations = [a for a in attestations if a.data.crosslink == winning_crosslink] return winning_crosslink, get_unslashed_attesting_indices(state, winning_attestations)
Types ¶
type MatchedAttestations ¶
type MatchedAttestations struct { Target []*pb.PendingAttestation // contains filtered or unexported fields }
MatchedAttestations is an object that contains the correctly voted attestations based on source, target and head criteria.
func MatchAttestations ¶
func MatchAttestations(state *pb.BeaconState, epoch uint64) (*MatchedAttestations, error)
MatchAttestations matches the attestations gathered in a span of an epoch and categorize them whether they correctly voted for source, target and head. We combined the individual helpers from spec for efficiency and to achieve O(N) run time.
Spec pseudocode definition:
def get_matching_source_attestations(state: BeaconState, epoch: Epoch) -> List[PendingAttestation]: assert epoch in (get_current_epoch(state), get_previous_epoch(state)) return state.current_epoch_attestations if epoch == get_current_epoch(state) else state.previous_epoch_attestations def get_matching_target_attestations(state: BeaconState, epoch: Epoch) -> List[PendingAttestation]: return [ a for a in get_matching_source_attestations(state, epoch) if a.data.target_root == get_block_root(state, epoch) ] def get_matching_head_attestations(state: BeaconState, epoch: Epoch) -> List[PendingAttestation]: return [ a for a in get_matching_source_attestations(state, epoch) if a.data.beacon_block_root == get_block_root_at_slot(state, get_attestation_data_slot(state, a.data)) ]