From 8896e1bed67357f1063cc172d9498a9af32bba65 Mon Sep 17 00:00:00 2001 From: Joshua Gutow Date: Sun, 11 Sep 2022 11:30:36 +0200 Subject: [PATCH] op-node: Call FCU on new unsafe payload This calls a FCU to set the unsafe head of the L2 execution client immediately after NewPayload is called on the execution client. This means that the unsafe head in the node state matches the unsafe head on the execution client. This commit removes the FCU prior to the NewPayload call because we assert that the unsafe block that we are inserting extends the current unsafe head. As such, the L2 execution client is in a state to accept the new block. --- op-node/rollup/derive/engine_queue.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/op-node/rollup/derive/engine_queue.go b/op-node/rollup/derive/engine_queue.go index 887b0f66ade86..eccdb72fc412e 100644 --- a/op-node/rollup/derive/engine_queue.go +++ b/op-node/rollup/derive/engine_queue.go @@ -217,6 +217,7 @@ func (eq *EngineQueue) tryNextUnsafePayload(ctx context.Context) error { return nil } + // Ensure that the unsafe payload builds upon the current unsafe head // TODO: once we support snap-sync we can remove this condition, and handle the "SYNCING" status of the execution engine. if first.ParentHash != eq.unsafeHead.Hash { if uint64(first.BlockNumber) == eq.unsafeHead.Number+1 { @@ -233,12 +234,19 @@ func (eq *EngineQueue) tryNextUnsafePayload(ctx context.Context) error { return nil } - // Note: the parent hash does not have to equal the existing unsafe head, - // the unsafe part of the chain may reorg freely without resetting the derivation pipeline. + status, err := eq.engine.NewPayload(ctx, first) + if err != nil { + return NewTemporaryError(fmt.Errorf("failed to update insert payload: %w", err)) + } + if status.Status != eth.ExecutionValid { + eq.unsafePayloads.Pop() + return NewTemporaryError(fmt.Errorf("cannot process unsafe payload: new - %v; parent: %v; err: %w", + first.ID(), first.ParentID(), eth.NewPayloadErr(first, status))) + } - // prepare for processing the unsafe payload + // Mark the new payload as valid fc := eth.ForkchoiceState{ - HeadBlockHash: first.ParentHash, + HeadBlockHash: first.BlockHash, SafeBlockHash: eq.safeHead.Hash, // this should guarantee we do not reorg past the safe head FinalizedBlockHash: eq.finalized.Hash, } @@ -261,15 +269,7 @@ func (eq *EngineQueue) tryNextUnsafePayload(ctx context.Context) error { return NewTemporaryError(fmt.Errorf("cannot prepare unsafe chain for new payload: new - %v; parent: %v; err: %w", first.ID(), first.ParentID(), eth.ForkchoiceUpdateErr(fcRes.PayloadStatus))) } - status, err := eq.engine.NewPayload(ctx, first) - if err != nil { - return NewTemporaryError(fmt.Errorf("failed to update insert payload: %w", err)) - } - if status.Status != eth.ExecutionValid { - eq.unsafePayloads.Pop() - return NewTemporaryError(fmt.Errorf("cannot process unsafe payload: new - %v; parent: %v; err: %w", - first.ID(), first.ParentID(), eth.ForkchoiceUpdateErr(fcRes.PayloadStatus))) - } + eq.unsafeHead = ref eq.unsafePayloads.Pop() eq.metrics.RecordL2Ref("l2_unsafe", ref)