To remove ReqRes P2P sync (RRSync) and replace the functionality it provides with the ELSync, we must make sure that the L2CL pushes forward to the L2EL the unsafe payloads that it receives, rather than just add them to its payloads heap within the EngineController.
So when we start with sync.CLSync, or sync.ELSync with initial EL Sync done,
func (s *SyncDeriver) OnUnsafeL2Payload(ctx context.Context, envelope *eth.ExecutionPayloadEnvelope) {
// If we are doing CL sync or done with engine syncing, fallback to the unsafe payload queue & CL P2P sync.
if s.SyncCfg.SyncMode == sync.CLSync || !s.Engine.IsEngineSyncing() {
s.Log.Info("Optimistically queueing unsafe L2 execution payload", "id", envelope.ExecutionPayload.ID())
s.Engine.AddUnsafePayload(ctx, envelope)
} else if s.SyncCfg.SyncMode == sync.ELSync {
...
The op-node will queue the unsafe payload at the unsafe payload queue, at s.Engine.AddUnsafePayload(ctx, envelope), and trigger EngineController.onForkChoiceUpdate.
onForkChoiceUpdate will peek the unsafe payload queue, and only apply when
// Only process the next payload if it is applicable on top of the current unsafe head.
// This avoids prematurely attempting to insert non-adjacent payloads (e.g. height gaps),
// which could otherwise trigger EL sync behavior.
refParentHash := nextEnvelope.ExecutionPayload.ParentHash
refBlockNumber := uint64(nextEnvelope.ExecutionPayload.BlockNumber)
if refParentHash != event.UnsafeL2Head.Hash || refBlockNumber != event.UnsafeL2Head.Number+1 {
e.log.Debug("Next unsafe payload is not applicable yet",
"nextHash", nextEnvelope.ExecutionPayload.BlockHash, "nextNumber", refBlockNumber, "unsafe", event.UnsafeL2Head)
return
}
// We don't pop from the queue. If there is a temporary error then we can retry.
// Upon next forkchoice update or invalid-payload event we can remove it from the queue.
e.processUnsafePayload(ctx, nextEnvelope)
We specifically need to allow that we may send the unsafe payload to the EL to trigger EL Sync again. This way, EL will get payloads signaled that won't be built on top of the current unsafe head at the EL. The notified EL will actively ask other EL peers to fill in the gap. Meanwhile, op-node will still consolidating and advancing its unsafe heads due to safe head advances. EL and CL will cooperatively close the gap.
To remove ReqRes P2P sync (RRSync) and replace the functionality it provides with the ELSync, we must make sure that the L2CL pushes forward to the L2EL the unsafe payloads that it receives, rather than just add them to its payloads heap within the
EngineController.So when we start with
sync.CLSync, orsync.ELSyncwith initial EL Sync done,The op-node will queue the unsafe payload at the unsafe payload queue, at
s.Engine.AddUnsafePayload(ctx, envelope), and triggerEngineController.onForkChoiceUpdate.onForkChoiceUpdatewill peek the unsafe payload queue, and only apply whenWe specifically need to allow that we may send the unsafe payload to the EL to trigger EL Sync again. This way, EL will get payloads signaled that won't be built on top of the current unsafe head at the EL. The notified EL will actively ask other EL peers to fill in the gap. Meanwhile, op-node will still consolidating and advancing its unsafe heads due to safe head advances. EL and CL will cooperatively close the gap.