prysm-pulse/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder.go
Potuz 0a87210514
Forkchoice external locks v2 (#12036)
* write locks

* fix forkchoice tests

* blockchain locks

* lock on IsOptimistic

* use forkchoice instead of chaininfo within savehead

* Use forkchoice HasNode to check if a block is consistent with finality

* interface fix

* Use forkchoice HasNode to check if a block is consistent with finality

* interface fix

* fix tests

* remove VerifyFinalizedBlkDescendant

* don't write lock wrappers

* fix validateBeaconBlock

* Terence's review and more missing locks

* add lock for InForkChoice

* lock head on fillMissingBlockPayload

* fix lock on IsOptimisticForRoot

* fix lock in fillMissingBlockPayloadId

* extra comments

* lock proposerBoost on spectests

* nishant's review

---------

Co-authored-by: Nishant Das <nishdas93@gmail.com>
2023-03-02 09:10:52 -03:00

93 lines
3.3 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"
"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 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
}