epoch

package
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 24, 2019 License: GPL-3.0 Imports: 12 Imported by: 0

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

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(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(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))
  ]

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL