mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 11:32:09 +00:00
79bb7efbf8
* Check init sync before getting payload attributes This PR adds a helper to forkchoice to return the delay of the latest imported block. It also adds a helper with an heuristic to check if the node is during init sync. If the highest imported node was imported with a delay of less than an epoch then the node is considered in regular sync. If on the other hand, in addition the highest imported node is more than two epochs old, then the node is considered in init Sync. The helper to check this only uses forkchoice and therefore requires a read lock. There are four paths to call this 1) During regular block processing, we defer a function to send the second FCU call with attributes. This function may not be called at all if we are not regularly syncing 2) During regular block processing, we check in the path `postBlockProces->getFCUArgs->computePayloadAttributes` the payload attributes if we are syncing a late block. In this case forkchoice is already locked and we add a call in `getFCUArgs` to return early if not regularly syncing 3) During handling of late blocks on `lateBlockTasks` we simply return early if not in regular sync (This is the biggest change as it takes a longer FC lock for lateBlockTasks) 4) On Attestation processing, in UpdateHead, we are already locked so we just add a check to not update head on this path if not regularly syncing. * fix build * Fix mocks
172 lines
5.6 KiB
Go
172 lines
5.6 KiB
Go
package forkchoice
|
|
|
|
import (
|
|
forkchoicetypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/forkchoice/types"
|
|
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
|
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
|
)
|
|
|
|
// ROForkChoice is an implementation of forkchoice.Getter which calls `Rlock`/`RUnlock`
|
|
// around a delegated method call to the underlying Getter implementation.
|
|
type ROForkChoice struct {
|
|
getter FastGetter
|
|
l RLocker
|
|
}
|
|
|
|
var _ FastGetter = &ROForkChoice{}
|
|
|
|
// ROWrappable represents the subset of ForkChoicer a type needs to support
|
|
// in order for ROForkChoice to wrap it. This simplifies the creation of a mock
|
|
// type that can be used to assert that all of the wrapped methods are correctly
|
|
// called between mutex acquire/release.
|
|
type ROWrappable interface {
|
|
RLocker
|
|
FastGetter
|
|
}
|
|
|
|
// NewROForkChoice returns an ROForkChoice that delegates forkchoice.Getter calls to the
|
|
// given value after first using its Locker methods to make sure it is correctly locked.
|
|
func NewROForkChoice(w ROWrappable) *ROForkChoice {
|
|
return &ROForkChoice{getter: w, l: w}
|
|
}
|
|
|
|
// HasNode delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) HasNode(root [32]byte) bool {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.HasNode(root)
|
|
}
|
|
|
|
// ProposerBoost delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) ProposerBoost() [fieldparams.RootLength]byte {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.ProposerBoost()
|
|
}
|
|
|
|
// IsCanonical delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) IsCanonical(root [32]byte) bool {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.IsCanonical(root)
|
|
}
|
|
|
|
// FinalizedCheckpoint delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) FinalizedCheckpoint() *forkchoicetypes.Checkpoint {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.FinalizedCheckpoint()
|
|
}
|
|
|
|
// IsViableForCheckpoint delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) IsViableForCheckpoint(cp *forkchoicetypes.Checkpoint) (bool, error) {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.IsViableForCheckpoint(cp)
|
|
}
|
|
|
|
// FinalizedPayloadBlockHash delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) FinalizedPayloadBlockHash() [32]byte {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.FinalizedPayloadBlockHash()
|
|
}
|
|
|
|
// JustifiedCheckpoint delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) JustifiedCheckpoint() *forkchoicetypes.Checkpoint {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.JustifiedCheckpoint()
|
|
}
|
|
|
|
// PreviousJustifiedCheckpoint delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) PreviousJustifiedCheckpoint() *forkchoicetypes.Checkpoint {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.PreviousJustifiedCheckpoint()
|
|
}
|
|
|
|
// JustifiedPayloadBlockHash delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) JustifiedPayloadBlockHash() [32]byte {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.JustifiedPayloadBlockHash()
|
|
}
|
|
|
|
// UnrealizedJustifiedPayloadBlockHash delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) UnrealizedJustifiedPayloadBlockHash() [32]byte {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.UnrealizedJustifiedPayloadBlockHash()
|
|
}
|
|
|
|
// NodeCount delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) NodeCount() int {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.NodeCount()
|
|
}
|
|
|
|
// HighestReceivedBlockSlot delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) HighestReceivedBlockSlot() primitives.Slot {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.HighestReceivedBlockSlot()
|
|
}
|
|
|
|
// HighestReceivedBlockDelay delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) HighestReceivedBlockDelay() primitives.Slot {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.HighestReceivedBlockDelay()
|
|
}
|
|
|
|
// ReceivedBlocksLastEpoch delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) ReceivedBlocksLastEpoch() (uint64, error) {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.ReceivedBlocksLastEpoch()
|
|
}
|
|
|
|
// Weight delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) Weight(root [32]byte) (uint64, error) {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.Weight(root)
|
|
}
|
|
|
|
// IsOptimistic delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) IsOptimistic(root [32]byte) (bool, error) {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.IsOptimistic(root)
|
|
}
|
|
|
|
// ShouldOverrideFCU delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) ShouldOverrideFCU() bool {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.ShouldOverrideFCU()
|
|
}
|
|
|
|
// Slot delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) Slot(root [32]byte) (primitives.Slot, error) {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.Slot(root)
|
|
}
|
|
|
|
// LastRoot delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) LastRoot(e primitives.Epoch) [32]byte {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.LastRoot(e)
|
|
}
|
|
|
|
// TargetRootForEpoch delegates to the underlying forkchoice call, under a lock.
|
|
func (ro *ROForkChoice) TargetRootForEpoch(root [32]byte, epoch primitives.Epoch) ([32]byte, error) {
|
|
ro.l.RLock()
|
|
defer ro.l.RUnlock()
|
|
return ro.getter.TargetRootForEpoch(root, epoch)
|
|
}
|