mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-09 19:21:19 +00:00
d17996f8b0
* Update V3 from V4 * Fix build v3 -> v4 * Update ssz * Update beacon_chain.pb.go * Fix formatter import * Update update-mockgen.sh comment to v4 * Fix conflicts. Pass build and tests * Fix test
93 lines
3.3 KiB
Go
93 lines
3.3 KiB
Go
package validator
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db/kv"
|
|
"github.com/prysmaticlabs/prysm/v4/config/params"
|
|
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// Returns true if builder (ie outsourcing block construction) can be used. Both conditions have to meet:
|
|
// - Validator has registered to use builder (ie called registerBuilder API end point)
|
|
// - Circuit breaker has not been activated (ie the liveness of the chain is healthy)
|
|
func (vs *Server) canUseBuilder(ctx context.Context, slot primitives.Slot, idx primitives.ValidatorIndex) (bool, error) {
|
|
activated, err := vs.circuitBreakBuilder(slot)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if activated {
|
|
return false, nil
|
|
}
|
|
return vs.validatorRegistered(ctx, idx)
|
|
}
|
|
|
|
// validatorRegistered returns true if validator with index `id` was previously registered in the database.
|
|
func (vs *Server) validatorRegistered(ctx context.Context, id primitives.ValidatorIndex) (bool, error) {
|
|
if vs.BeaconDB == nil {
|
|
return false, errors.New("nil beacon db")
|
|
}
|
|
_, err := vs.BeaconDB.RegistrationByValidatorID(ctx, id)
|
|
switch {
|
|
case errors.Is(err, kv.ErrNotFoundFeeRecipient):
|
|
return false, nil
|
|
case err != nil:
|
|
return false, err
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
// circuitBreakBuilder returns true if the builder is not allowed to be used due to circuit breaker conditions.
|
|
func (vs *Server) circuitBreakBuilder(s primitives.Slot) (bool, error) {
|
|
if vs.ForkFetcher == nil || vs.ForkFetcher.ForkChoicer() == nil {
|
|
return true, errors.New("no fork choicer configured")
|
|
}
|
|
|
|
vs.ForkFetcher.ForkChoicer().RLock()
|
|
defer vs.ForkFetcher.ForkChoicer().RUnlock()
|
|
|
|
// Circuit breaker is active if the missing consecutive slots greater than `MaxBuilderConsecutiveMissedSlots`.
|
|
highestReceivedSlot := vs.ForkFetcher.ForkChoicer().HighestReceivedBlockSlot()
|
|
maxConsecutiveSkipSlotsAllowed := params.BeaconConfig().MaxBuilderConsecutiveMissedSlots
|
|
diff, err := s.SafeSubSlot(highestReceivedSlot)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
|
|
if diff >= maxConsecutiveSkipSlotsAllowed {
|
|
log.WithFields(logrus.Fields{
|
|
"currentSlot": s,
|
|
"highestReceivedSlot": highestReceivedSlot,
|
|
"maxConsecutiveSkipSlotsAllowed": maxConsecutiveSkipSlotsAllowed,
|
|
}).Warn("Circuit breaker activated due to missing consecutive slot. Ignore if mev-boost is not used")
|
|
return true, nil
|
|
}
|
|
|
|
// Not much reason to check missed slots epoch rolling window if input slot is less than epoch.
|
|
if s < params.BeaconConfig().SlotsPerEpoch {
|
|
return false, nil
|
|
}
|
|
|
|
// Circuit breaker is active if the missing slots per epoch (rolling window) greater than `MaxBuilderEpochMissedSlots`.
|
|
receivedCount, err := vs.ForkFetcher.ForkChoicer().ReceivedBlocksLastEpoch()
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
maxEpochSkipSlotsAllowed := params.BeaconConfig().MaxBuilderEpochMissedSlots
|
|
diff, err = params.BeaconConfig().SlotsPerEpoch.SafeSub(receivedCount)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
if diff >= maxEpochSkipSlotsAllowed {
|
|
log.WithFields(logrus.Fields{
|
|
"totalMissed": diff,
|
|
"maxEpochSkipSlotsAllowed": maxEpochSkipSlotsAllowed,
|
|
}).Warn("Circuit breaker activated due to missing enough slots last epoch. Ignore if mev-boost is not used")
|
|
return true, nil
|
|
}
|
|
|
|
return false, nil
|
|
}
|