prysm-pulse/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder.go
terencechain 38f0a81526
Clarify circuit breaker logs (#11876)
* Clarify circuit breaker logs

* Revert bad changes

* Fix test
2023-01-16 17:49:23 +00:00

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
}