mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-05 01:04:29 +00:00
5a66807989
* First take at updating everything to v5 * Patch gRPC gateway to use prysm v5 Fix patch * Update go ssz --------- Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>
151 lines
5.3 KiB
Go
151 lines
5.3 KiB
Go
package blockchain
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
doublylinkedtree "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/doubly-linked-tree"
|
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
|
"github.com/prysmaticlabs/prysm/v5/config/params"
|
|
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
|
payloadattribute "github.com/prysmaticlabs/prysm/v5/consensus-types/payload-attribute"
|
|
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
|
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
|
"github.com/sirupsen/logrus"
|
|
"go.opencensus.io/trace"
|
|
)
|
|
|
|
func (s *Service) isNewHead(r [32]byte) bool {
|
|
s.headLock.RLock()
|
|
defer s.headLock.RUnlock()
|
|
|
|
currentHeadRoot := s.originBlockRoot
|
|
if s.head != nil {
|
|
currentHeadRoot = s.headRoot()
|
|
}
|
|
|
|
return r != currentHeadRoot || r == [32]byte{}
|
|
}
|
|
|
|
func (s *Service) getStateAndBlock(ctx context.Context, r [32]byte) (state.BeaconState, interfaces.ReadOnlySignedBeaconBlock, error) {
|
|
if !s.hasBlockInInitSyncOrDB(ctx, r) {
|
|
return nil, nil, errors.New("block does not exist")
|
|
}
|
|
newHeadBlock, err := s.getBlock(ctx, r)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
headState, err := s.cfg.StateGen.StateByRoot(ctx, r)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return headState, newHeadBlock, nil
|
|
}
|
|
|
|
type fcuConfig struct {
|
|
headState state.BeaconState
|
|
headBlock interfaces.ReadOnlySignedBeaconBlock
|
|
headRoot [32]byte
|
|
proposingSlot primitives.Slot
|
|
attributes payloadattribute.Attributer
|
|
}
|
|
|
|
// sendFCU handles the logic to notify the engine of a forckhoice update
|
|
// for the first time when processing an incoming block during regular sync. It
|
|
// always updates the shuffling caches and handles epoch transitions when the
|
|
// incoming block is late, preparing payload attributes in this case while it
|
|
// only sends a message with empty attributes for early blocks.
|
|
func (s *Service) sendFCU(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) error {
|
|
if !s.isNewHead(cfg.headRoot) {
|
|
return nil
|
|
}
|
|
if fcuArgs.attributes != nil && !fcuArgs.attributes.IsEmpty() && s.shouldOverrideFCU(cfg.headRoot, s.CurrentSlot()+1) {
|
|
return nil
|
|
}
|
|
return s.forkchoiceUpdateWithExecution(cfg.ctx, fcuArgs)
|
|
}
|
|
|
|
// sendFCUWithAttributes computes the payload attributes and sends an FCU message
|
|
// to the engine if needed
|
|
func (s *Service) sendFCUWithAttributes(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) {
|
|
slotCtx, cancel := context.WithTimeout(context.Background(), slotDeadline)
|
|
defer cancel()
|
|
cfg.ctx = slotCtx
|
|
s.cfg.ForkChoiceStore.RLock()
|
|
defer s.cfg.ForkChoiceStore.RUnlock()
|
|
if err := s.computePayloadAttributes(cfg, fcuArgs); err != nil {
|
|
log.WithError(err).Error("could not compute payload attributes")
|
|
return
|
|
}
|
|
if fcuArgs.attributes.IsEmpty() {
|
|
return
|
|
}
|
|
if _, err := s.notifyForkchoiceUpdate(cfg.ctx, fcuArgs); err != nil {
|
|
log.WithError(err).Error("could not update forkchoice with payload attributes for proposal")
|
|
}
|
|
}
|
|
|
|
// fockchoiceUpdateWithExecution is a wrapper around notifyForkchoiceUpdate. It decides whether a new call to FCU should be made.
|
|
func (s *Service) forkchoiceUpdateWithExecution(ctx context.Context, args *fcuConfig) error {
|
|
_, span := trace.StartSpan(ctx, "beacon-chain.blockchain.forkchoiceUpdateWithExecution")
|
|
defer span.End()
|
|
// Note: Use the service context here to avoid the parent context being ended during a forkchoice update.
|
|
ctx = trace.NewContext(s.ctx, span)
|
|
_, err := s.notifyForkchoiceUpdate(ctx, args)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not notify forkchoice update")
|
|
}
|
|
|
|
if err := s.saveHead(ctx, args.headRoot, args.headBlock, args.headState); err != nil {
|
|
log.WithError(err).Error("could not save head")
|
|
}
|
|
|
|
// Only need to prune attestations from pool if the head has changed.
|
|
if err := s.pruneAttsFromPool(args.headBlock); err != nil {
|
|
log.WithError(err).Error("could not prune attestations from pool")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// shouldOverrideFCU checks whether the incoming block is still subject to being
|
|
// reorged or not by the next proposer.
|
|
func (s *Service) shouldOverrideFCU(newHeadRoot [32]byte, proposingSlot primitives.Slot) bool {
|
|
headWeight, err := s.cfg.ForkChoiceStore.Weight(newHeadRoot)
|
|
if err != nil {
|
|
log.WithError(err).WithField("root", fmt.Sprintf("%#x", newHeadRoot)).Warn("could not determine node weight")
|
|
}
|
|
currentSlot := s.CurrentSlot()
|
|
if proposingSlot == currentSlot {
|
|
proposerHead := s.cfg.ForkChoiceStore.GetProposerHead()
|
|
if proposerHead != newHeadRoot {
|
|
return true
|
|
}
|
|
log.WithFields(logrus.Fields{
|
|
"root": fmt.Sprintf("%#x", newHeadRoot),
|
|
"weight": headWeight,
|
|
}).Infof("Attempted late block reorg aborted due to attestations at %d seconds",
|
|
params.BeaconConfig().SecondsPerSlot)
|
|
lateBlockFailedAttemptSecondThreshold.Inc()
|
|
} else {
|
|
if s.cfg.ForkChoiceStore.ShouldOverrideFCU() {
|
|
return true
|
|
}
|
|
secs, err := slots.SecondsSinceSlotStart(currentSlot,
|
|
uint64(s.genesisTime.Unix()), uint64(time.Now().Unix()))
|
|
if err != nil {
|
|
log.WithError(err).Error("could not compute seconds since slot start")
|
|
}
|
|
if secs >= doublylinkedtree.ProcessAttestationsThreshold {
|
|
log.WithFields(logrus.Fields{
|
|
"root": fmt.Sprintf("%#x", newHeadRoot),
|
|
"weight": headWeight,
|
|
}).Infof("Attempted late block reorg aborted due to attestations at %d seconds",
|
|
doublylinkedtree.ProcessAttestationsThreshold)
|
|
lateBlockFailedAttemptFirstThreshold.Inc()
|
|
}
|
|
}
|
|
return false
|
|
}
|