Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions beacon/blockchain/finalize_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
ctypes "github.com/berachain/beacon-kit/consensus-types/types"
"github.com/berachain/beacon-kit/consensus/types"
datypes "github.com/berachain/beacon-kit/da/types"
"github.com/berachain/beacon-kit/primitives/crypto"
"github.com/berachain/beacon-kit/primitives/math"
"github.com/berachain/beacon-kit/primitives/transition"
statedb "github.com/berachain/beacon-kit/state-transition/core/state"
Expand All @@ -49,21 +48,6 @@ func (s *Service) FinalizeBlock(
blk := signedBlk.GetBeaconBlock()
st := s.storageBackend.StateFromContext(ctx)

// Send an FCU to force the HEAD of the chain on the EL on startup.
var finalizeErr error
s.forceStartupSyncOnce.Do(func() {
var parentProposerPubkey *crypto.BLSPubkey
parentProposerPubkey, finalizeErr = st.ParentProposerPubkey(blk.GetTimestamp())
if finalizeErr != nil {
finalizeErr = fmt.Errorf("force sync upon finalize: failed retrieving parent proposer pubkey: %w", finalizeErr)
} else {
finalizeErr = s.forceSyncUponFinalize(ctx, blk, parentProposerPubkey)
}
})
if finalizeErr != nil {
return nil, finalizeErr
}

// STEP 2: Finalize sidecars first (block will check for sidecar availability).
if err = s.FinalizeSidecars(ctx, req.SyncingToHeight, blk, blobs); err != nil {
return nil, fmt.Errorf("failed finalizing sidecars: %w", err)
Expand Down
58 changes: 0 additions & 58 deletions beacon/blockchain/payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ import (
payloadtime "github.com/berachain/beacon-kit/beacon/payload-time"
ctypes "github.com/berachain/beacon-kit/consensus-types/types"
engineprimitives "github.com/berachain/beacon-kit/engine-primitives/engine-primitives"
engineerrors "github.com/berachain/beacon-kit/engine-primitives/errors"
"github.com/berachain/beacon-kit/errors"
"github.com/berachain/beacon-kit/payload/builder"
"github.com/berachain/beacon-kit/primitives/crypto"
"github.com/berachain/beacon-kit/primitives/math"
statedb "github.com/berachain/beacon-kit/state-transition/core/state"
)
Expand Down Expand Up @@ -74,61 +71,6 @@ func (s *Service) forceSyncUponProcess(
}
}

// forceSyncUponFinalize sends a new payload and force startup FCU to the Execution
// Layer client. This informs the EL client of the new head and forces a SYNC
// if blocks are missing. This function should only be run once at startup.
func (s *Service) forceSyncUponFinalize(
ctx context.Context,
beaconBlock *ctypes.BeaconBlock,
parentProposerPubkey *crypto.BLSPubkey,
) error {
// NewPayload call first to load payload into EL client.
executionPayload := beaconBlock.GetBody().GetExecutionPayload()
payloadReq, err := ctypes.BuildNewPayloadRequestFromFork(beaconBlock, parentProposerPubkey)
if err != nil {
return err
}

if err = payloadReq.HasValidVersionedAndBlockHashes(); err != nil {
return err
}

// We set retryOnSyncingStatus to false here. We can ignore SYNCING status and proceed
// to the FCU.
err = s.executionEngine.NotifyNewPayload(ctx, payloadReq, false)
if err != nil {
return fmt.Errorf("startSyncUponFinalize NotifyNewPayload failed: %w", err)
}

// Submit the forkchoice update to the EL client. This will ensure that it is either synced or
// starts up a sync.
req := ctypes.BuildForkchoiceUpdateRequestNoAttrs(
&engineprimitives.ForkchoiceStateV1{
HeadBlockHash: executionPayload.GetBlockHash(),
SafeBlockHash: executionPayload.GetParentHash(),
FinalizedBlockHash: executionPayload.GetParentHash(),
},
s.chainSpec.ActiveForkVersionForTimestamp(executionPayload.GetTimestamp()),
)

switch _, err = s.executionEngine.NotifyForkchoiceUpdate(ctx, req); {
case err == nil:
return nil

case errors.IsAny(err,
engineerrors.ErrSyncingPayloadStatus,
engineerrors.ErrAcceptedPayloadStatus):
s.logger.Warn(
//nolint:lll // long message on one line for readability.
`Your execution client is syncing. It should be downloading eth blocks from its peers. Restart the beacon node once the execution client is caught up.`,
)
return err

default:
return fmt.Errorf("force startup NotifyForkchoiceUpdate failed: %w", err)
}
}

// Once you provide the right state, we really need to carry out the very same operations
// to extract the data necessary to build the next block, whether current block is
// being rejected or accepted. This is way there can be (and so should be)
Expand Down
25 changes: 12 additions & 13 deletions beacon/blockchain/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ type Service struct {
// metrics is the metrics for the service.
metrics *chainMetrics
// forceStartupSyncOnce is used to force a sync of the startup head.
forceStartupSyncOnce *sync.Once
forceStartupSyncOnce sync.Once

// latestFcuReq holds a copy of the latest FCU sent to the execution layer.
// It helps avoid resending the same FCU data (and spares a network call)
Expand All @@ -84,18 +84,17 @@ func NewService(
telemetrySink TelemetrySink,
) *Service {
return &Service{
storageBackend: storageBackend,
blobProcessor: blobProcessor,
depositContract: depositContract,
eth1FollowDistance: math.U64(chainSpec.Eth1FollowDistance()),
failedBlocks: make(map[math.Slot]struct{}),
logger: logger,
chainSpec: chainSpec,
executionEngine: executionEngine,
localBuilder: localBuilder,
stateProcessor: stateProcessor,
metrics: newChainMetrics(telemetrySink),
forceStartupSyncOnce: new(sync.Once),
storageBackend: storageBackend,
blobProcessor: blobProcessor,
depositContract: depositContract,
eth1FollowDistance: math.U64(chainSpec.Eth1FollowDistance()),
failedBlocks: make(map[math.Slot]struct{}),
logger: logger,
chainSpec: chainSpec,
executionEngine: executionEngine,
localBuilder: localBuilder,
stateProcessor: stateProcessor,
metrics: newChainMetrics(telemetrySink),
}
}

Expand Down
13 changes: 8 additions & 5 deletions state-transition/core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,12 @@ func (sp *StateProcessor) Transition(

// Prepare the state for the next block's fork version.
// Ideally we want to log only in case we are processing the
// block to be finalized. Pre cache activation this is easy.
// Post activation we log every time we verify a block
logForkProcessing := ctx.VerifyPayload() && !ctx.VerifyRandao()
// block to be finalized.
inFinalizeBlock := ctx.VerifyPayload() && !ctx.VerifyRandao()

// Log if we are in finalizeBlock. However, post cache-activation, we log every time we
// verify a block.
logForkProcessing := inFinalizeBlock
if cache.IsStateCachingActive(sp.cs, blk.Slot) {
logForkProcessing = ctx.VerifyPayload()
}
Expand All @@ -111,7 +113,7 @@ func (sp *StateProcessor) Transition(
}

// Process the block.
if err = sp.ProcessBlock(ctx, st, blk); err != nil {
if err = sp.ProcessBlock(ctx, st, blk, inFinalizeBlock); err != nil {
return nil, err
}

Expand Down Expand Up @@ -212,6 +214,7 @@ func (sp *StateProcessor) ProcessBlock(
ctx ReadOnlyContext,
st *state.StateDB,
blk *ctypes.BeaconBlock,
inFinalizeBlock bool,
) error {
// Before processing block header, we need to retrieve public key of
// parent block proposer to be able to inform the EL client.
Expand All @@ -224,7 +227,7 @@ func (sp *StateProcessor) ProcessBlock(
return err
}

if err = sp.processExecutionPayload(ctx, st, blk, parentProposerPubkey); err != nil {
if err = sp.processExecutionPayload(ctx, st, blk, inFinalizeBlock, parentProposerPubkey); err != nil {
return err
}

Expand Down
13 changes: 8 additions & 5 deletions state-transition/core/state_processor_payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func (sp *StateProcessor) processExecutionPayload(
txCtx ReadOnlyContext,
st *statedb.StateDB,
blk *ctypes.BeaconBlock,
inFinalizeBlock bool,
parentProposerPubkey *crypto.BLSPubkey,
) error {
var (
Expand Down Expand Up @@ -77,7 +78,7 @@ func (sp *StateProcessor) processExecutionPayload(
// Perform payload verification only if the context is configured as such.
if txCtx.VerifyPayload() {
g.Go(func() error {
return sp.validateExecutionPayload(ctx, txCtx.ConsensusTime(), st, blk, parentProposerPubkey)
return sp.validateExecutionPayload(ctx, txCtx.ConsensusTime(), st, blk, inFinalizeBlock, parentProposerPubkey)
})
}

Expand Down Expand Up @@ -109,12 +110,14 @@ func (sp *StateProcessor) validateExecutionPayload(
consensusTime math.U64,
st ReadOnlyBeaconState,
blk *ctypes.BeaconBlock,
inFinalizeBlock bool,
parentProposerPubkey *crypto.BLSPubkey,
) error {
if err := sp.validateStatelessPayload(blk); err != nil {
return err
}
return sp.validateStatefulPayload(ctx, consensusTime, st, blk, parentProposerPubkey)

return sp.validateStatefulPayload(ctx, consensusTime, st, blk, inFinalizeBlock, parentProposerPubkey)
}

// validateStatelessPayload performs stateless checks on the execution payload.
Expand Down Expand Up @@ -143,6 +146,7 @@ func (sp *StateProcessor) validateStatefulPayload(
consensusTime math.U64,
st ReadOnlyBeaconState,
blk *ctypes.BeaconBlock,
inFinalizeBlock bool,
parentProposerPubkey *crypto.BLSPubkey,
) error {
body := blk.GetBody()
Expand Down Expand Up @@ -185,9 +189,8 @@ func (sp *StateProcessor) validateStatefulPayload(
return err
}

// TODO: set retryOnSyncingStatus to false if we are in FinalizeBlock.
// Otherwise leave as true. This is ok to leave this way for now.
if err = sp.executionEngine.NotifyNewPayload(ctx, payloadReq, true); err != nil {
// We only retry on syncing status if we are not in FinalizeBlock.
if err = sp.executionEngine.NotifyNewPayload(ctx, payloadReq, !inFinalizeBlock); err != nil {
return err
}

Expand Down
Loading