mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-24 20:37:17 +00:00
38f0a81526
* Clarify circuit breaker logs * Revert bad changes * Fix test
90 lines
3.2 KiB
Go
90 lines
3.2 KiB
Go
package validator
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db/kv"
|
|
"github.com/prysmaticlabs/prysm/v3/config/params"
|
|
types "github.com/prysmaticlabs/prysm/v3/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 types.Slot, idx types.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 types.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 types.Slot) (bool, error) {
|
|
if vs.ForkFetcher == nil || vs.ForkFetcher.ForkChoicer() == nil {
|
|
return true, errors.New("no fork choicer configured")
|
|
}
|
|
|
|
// 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
|
|
}
|