mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-09 12:31:21 +00:00
75 lines
3.0 KiB
Go
75 lines
3.0 KiB
Go
package statechange
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"github.com/ledgerwatch/erigon/cl/abstract"
|
|
|
|
"github.com/ledgerwatch/erigon/cl/cltypes/solid"
|
|
"github.com/ledgerwatch/erigon/cl/phase1/core/state"
|
|
|
|
"github.com/ledgerwatch/erigon/cl/clparams"
|
|
)
|
|
|
|
// computeActivationExitEpoch is Implementation of compute_activation_exit_epoch. Defined in https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#compute_activation_exit_epoch.
|
|
func computeActivationExitEpoch(beaconConfig *clparams.BeaconChainConfig, epoch uint64) uint64 {
|
|
return epoch + 1 + beaconConfig.MaxSeedLookahead
|
|
}
|
|
|
|
type minimizeQueuedValidator struct {
|
|
validatorIndex uint64
|
|
activationEligibilityEpoch uint64
|
|
}
|
|
|
|
// ProcessRegistyUpdates updates every epoch the activation status of validators. Specs at: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#registry-updates.
|
|
func ProcessRegistryUpdates(s abstract.BeaconState) error {
|
|
beaconConfig := s.BeaconConfig()
|
|
currentEpoch := state.Epoch(s)
|
|
// start also initializing the activation queue.
|
|
activationQueue := make([]minimizeQueuedValidator, 0)
|
|
// Process activation eligibility and ejections.
|
|
var err error
|
|
s.ForEachValidator(func(validator solid.Validator, validatorIndex, total int) bool {
|
|
activationEligibilityEpoch := validator.ActivationEligibilityEpoch()
|
|
effectivaBalance := validator.EffectiveBalance()
|
|
if activationEligibilityEpoch == s.BeaconConfig().FarFutureEpoch &&
|
|
validator.EffectiveBalance() == s.BeaconConfig().MaxEffectiveBalance {
|
|
s.SetActivationEligibilityEpochForValidatorAtIndex(validatorIndex, currentEpoch+1)
|
|
}
|
|
if validator.Active(currentEpoch) && effectivaBalance <= beaconConfig.EjectionBalance {
|
|
if err = s.InitiateValidatorExit(uint64(validatorIndex)); err != nil {
|
|
return false
|
|
}
|
|
}
|
|
// Insert in the activation queue in case.
|
|
if activationEligibilityEpoch <= s.FinalizedCheckpoint().Epoch() &&
|
|
validator.ActivationEpoch() == s.BeaconConfig().FarFutureEpoch {
|
|
activationQueue = append(activationQueue, minimizeQueuedValidator{
|
|
validatorIndex: uint64(validatorIndex),
|
|
activationEligibilityEpoch: activationEligibilityEpoch,
|
|
})
|
|
}
|
|
return true
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// order the queue accordingly.
|
|
sort.Slice(activationQueue, func(i, j int) bool {
|
|
// Order by the sequence of activation_eligibility_epoch setting and then index.
|
|
if activationQueue[i].activationEligibilityEpoch != activationQueue[j].activationEligibilityEpoch {
|
|
return activationQueue[i].activationEligibilityEpoch < activationQueue[j].activationEligibilityEpoch
|
|
}
|
|
return activationQueue[i].validatorIndex < activationQueue[j].validatorIndex
|
|
})
|
|
activationQueueLength := s.GetValidatorChurnLimit()
|
|
if len(activationQueue) > int(activationQueueLength) {
|
|
activationQueue = activationQueue[:activationQueueLength]
|
|
}
|
|
// Only process up to epoch limit.
|
|
for _, entry := range activationQueue {
|
|
s.SetActivationEpochForValidatorAtIndex(int(entry.validatorIndex), computeActivationExitEpoch(beaconConfig, currentEpoch))
|
|
}
|
|
return nil
|
|
}
|