l.log.Error("issue adding L2 Block to the channel","err",err,"channel_id",l.ch.ID())
continuemainLoop
}
l.log.Info("added L2 block to channel","block",eth.BlockID{Hash:block.Hash(),Number:block.NumberU64()},"channel_id",l.ch.ID(),"tx_count",len(block.Transactions()),"time",block.Time())
}
// TODO: above there are ugly "continue mainLoop" because we shouldn't progress if we're missing blocks, since the submitter logic can't handle gaps yet.
require.LessOrEqual(t,info.Number+seqConfDepth,l1Head.NumberU64(),"the L2 head block should have an origin older than the L1 head block by at least the sequencer conf depth")
require.LessOrEqual(t,l2VerHead.Time()+cfg.L1BlockTime*verConfDepth,l2SeqHead.Time(),"the L2 verifier head should lag behind the sequencer without delay by at least the verifier conf depth")
eq.log.Info("skipping unsafe payload, since it is older than safe head","safe",eq.safeHead.ID(),"unsafe",first.ID(),"payload",first.ID())
eq.unsafePayloads=eq.unsafePayloads[1:]
returnnil
}
// TODO: once we support snap-sync we can remove this condition, and handle the "SYNCING" status of the execution engine.
iffirst.ParentHash!=eq.unsafeHead.Hash{
eq.log.Info("skipping unsafe payload, since it does not build onto the existing unsafe chain","safe",eq.safeHead.ID(),"unsafe",first.ID(),"payload",first.ID())
eq.unsafePayloads=eq.unsafePayloads[1:]
returnnil
}
ref,err:=PayloadToBlockRef(first,&eq.cfg.Genesis)
iferr!=nil{
eq.log.Error("failed to decode L2 block ref from payload","err",err)
eq.unsafePayloads=eq.unsafePayloads[1:]
returnnil
}
// 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.
// prepare for processing the unsafe payload
fc:=eth.ForkchoiceState{
HeadBlockHash:first.ParentHash,
SafeBlockHash:eq.safeHead.Hash,// this should guarantee we do not reorg past the safe head
eq.log.Error("failed to update forkchoice to prepare for new unsafe payload","err",err)
returnnil// we can try again later
}
iffcRes.PayloadStatus.Status!=eth.ExecutionValid{
eq.log.Error("cannot prepare unsafe chain for new payload","new",first.ID(),"parent",first.ParentID(),"err",eth.ForkchoiceUpdateErr(fcRes.PayloadStatus))
eq.unsafePayloads=eq.unsafePayloads[1:]
returnnil
}
status,err:=eq.engine.NewPayload(ctx,first)
iferr!=nil{
eq.log.Error("failed to update insert payload","err",err)
returnnil// we can try again later
}
ifstatus.Status!=eth.ExecutionValid{
eq.log.Error("cannot process unsafe payload","new",first.ID(),"parent",first.ParentID(),"err",eth.ForkchoiceUpdateErr(fcRes.PayloadStatus))
// insertEpoch creates and inserts one epoch on top of the safe head. It prefers blocks it creates to what is recorded in the unsafe chain.
// It returns the new L2 head and L2 Safe head and if there was a reorg. This function must return if there was a reorg otherwise the L2 chain must be traversed.
s.log.Error("Could not extend the cached L1 window","err",err,"l2Head",s.l2Head,"l2SafeHead",s.l2SafeHead,"l1Head",s.l1Head,"window_end",s.l1WindowBufEnd())
returnfalse,err
}
s.l1WindowBuf=append(s.l1WindowBuf,nexts...)
}
// Ensure that there are enough blocks in the cached window
iflen(s.l1WindowBuf)<int(s.Config.SeqWindowSize){
s.log.Debug("Not enough cached blocks to run step","cached_window_len",len(s.l1WindowBuf))
// insertEpoch creates and inserts one epoch on top of the safe head. It prefers blocks it creates to what is recorded in the unsafe chain.
// It returns the new L2 head and L2 Safe head and if there was a reorg. This function must return if there was a reorg otherwise the L2 chain must be traversed.