2023-01-03 04:46:08 +00:00
|
|
|
package validator
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
2023-03-17 18:52:56 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db/kv"
|
|
|
|
"github.com/prysmaticlabs/prysm/v4/config/params"
|
|
|
|
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
2023-01-03 04:46:08 +00:00
|
|
|
"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)
|
2023-01-26 14:40:12 +00:00
|
|
|
func (vs *Server) canUseBuilder(ctx context.Context, slot primitives.Slot, idx primitives.ValidatorIndex) (bool, error) {
|
2023-04-14 10:21:46 +00:00
|
|
|
if !vs.BlockBuilder.Configured() {
|
|
|
|
return false, nil
|
|
|
|
}
|
2023-01-03 04:46:08 +00:00
|
|
|
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.
|
2023-01-26 14:40:12 +00:00
|
|
|
func (vs *Server) validatorRegistered(ctx context.Context, id primitives.ValidatorIndex) (bool, error) {
|
2023-01-03 04:46:08 +00:00
|
|
|
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.
|
2023-01-26 14:40:12 +00:00
|
|
|
func (vs *Server) circuitBreakBuilder(s primitives.Slot) (bool, error) {
|
2023-03-22 01:12:54 +00:00
|
|
|
if vs.ForkchoiceFetcher == nil {
|
2023-01-03 04:46:08 +00:00
|
|
|
return true, errors.New("no fork choicer configured")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Circuit breaker is active if the missing consecutive slots greater than `MaxBuilderConsecutiveMissedSlots`.
|
2023-03-22 01:12:54 +00:00
|
|
|
highestReceivedSlot := vs.ForkchoiceFetcher.HighestReceivedBlockSlot()
|
2023-01-03 04:46:08 +00:00
|
|
|
maxConsecutiveSkipSlotsAllowed := params.BeaconConfig().MaxBuilderConsecutiveMissedSlots
|
|
|
|
diff, err := s.SafeSubSlot(highestReceivedSlot)
|
|
|
|
if err != nil {
|
|
|
|
return true, err
|
|
|
|
}
|
|
|
|
|
2023-03-05 19:10:41 +00:00
|
|
|
if diff >= maxConsecutiveSkipSlotsAllowed {
|
2023-01-03 04:46:08 +00:00
|
|
|
log.WithFields(logrus.Fields{
|
|
|
|
"currentSlot": s,
|
|
|
|
"highestReceivedSlot": highestReceivedSlot,
|
|
|
|
"maxConsecutiveSkipSlotsAllowed": maxConsecutiveSkipSlotsAllowed,
|
2023-01-16 17:49:23 +00:00
|
|
|
}).Warn("Circuit breaker activated due to missing consecutive slot. Ignore if mev-boost is not used")
|
2023-01-03 04:46:08 +00:00
|
|
|
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`.
|
2023-03-22 01:12:54 +00:00
|
|
|
receivedCount, err := vs.ForkchoiceFetcher.ReceivedBlocksLastEpoch()
|
2023-01-03 04:46:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return true, err
|
|
|
|
}
|
|
|
|
maxEpochSkipSlotsAllowed := params.BeaconConfig().MaxBuilderEpochMissedSlots
|
|
|
|
diff, err = params.BeaconConfig().SlotsPerEpoch.SafeSub(receivedCount)
|
|
|
|
if err != nil {
|
|
|
|
return true, err
|
|
|
|
}
|
2023-03-05 19:10:41 +00:00
|
|
|
if diff >= maxEpochSkipSlotsAllowed {
|
2023-01-03 04:46:08 +00:00
|
|
|
log.WithFields(logrus.Fields{
|
|
|
|
"totalMissed": diff,
|
|
|
|
"maxEpochSkipSlotsAllowed": maxEpochSkipSlotsAllowed,
|
2023-01-16 17:49:23 +00:00
|
|
|
}).Warn("Circuit breaker activated due to missing enough slots last epoch. Ignore if mev-boost is not used")
|
2023-01-03 04:46:08 +00:00
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return false, nil
|
|
|
|
}
|