diff --git a/op-e2e/actions/l2_verifier.go b/op-e2e/actions/l2_verifier.go index 305f161e8d..52887dfc7d 100644 --- a/op-e2e/actions/l2_verifier.go +++ b/op-e2e/actions/l2_verifier.go @@ -65,7 +65,7 @@ type safeDB interface { func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, blobsSrc derive.L1BlobsFetcher, plasmaSrc derive.PlasmaInputFetcher, eng L2API, cfg *rollup.Config, syncCfg *sync.Config, safeHeadListener safeDB) *L2Verifier { metrics := &testutils.TestDerivationMetrics{} - engine := derive.NewEngineController(eng, log, metrics, cfg, syncCfg.SyncMode) + engine := derive.NewEngineController(eng, log, metrics, cfg, syncCfg) pipeline := derive.NewDerivationPipeline(log, cfg, l1, blobsSrc, plasmaSrc, eng, engine, metrics, syncCfg, safeHeadListener) pipeline.Reset() diff --git a/op-node/flags/flags.go b/op-node/flags/flags.go index 30e98a6f6d..a6037d1ce9 100644 --- a/op-node/flags/flags.go +++ b/op-node/flags/flags.go @@ -324,6 +324,20 @@ var ( EnvVars: prefixEnvVars("SAFEDB_PATH"), Category: OperationsCategory, } + + FastnodeMode = &cli.BoolFlag{ + Name: "fastnode", + Usage: "Fastnode has a strong dependency on a specific synchronization mode during synchronization, so please set this flag when running fastnode.", + EnvVars: prefixEnvVars("FASTNODE"), + Value: false, + } + + ELTriggerGap = &cli.IntFlag{ + Name: "el-trigger.gap", + Usage: "gap to trigger el-sync", + Value: 86400, + EnvVars: prefixEnvVars("EL_TRIGGER_GAP"), + } /* Deprecated Flags */ L2EngineSyncEnabled = &cli.BoolFlag{ Name: "l2.engine-sync", @@ -395,6 +409,8 @@ var optionalFlags = []cli.Flag{ BeaconCheckIgnore, BeaconFetchAllSidecars, SyncModeFlag, + FastnodeMode, + ELTriggerGap, RPCListenAddr, RPCListenPort, L1TrustRPC, diff --git a/op-node/rollup/derive/engine_controller.go b/op-node/rollup/derive/engine_controller.go index a0417b3c05..f73ce21891 100644 --- a/op-node/rollup/derive/engine_controller.go +++ b/op-node/rollup/derive/engine_controller.go @@ -45,14 +45,15 @@ type ExecEngine interface { } type EngineController struct { - engine ExecEngine // Underlying execution engine RPC - log log.Logger - metrics Metrics - syncMode sync.Mode - syncStatus syncStatusEnum - rollupCfg *rollup.Config - elStart time.Time - clock clock.Clock + engine ExecEngine // Underlying execution engine RPC + log log.Logger + metrics Metrics + syncMode sync.Mode + elTriggerGap int + syncStatus syncStatusEnum + rollupCfg *rollup.Config + elStart time.Time + clock clock.Clock // Block Head State unsafeHead eth.L2BlockRef @@ -75,20 +76,21 @@ type EngineController struct { safeAttrs *AttributesWithParent } -func NewEngineController(engine ExecEngine, log log.Logger, metrics Metrics, rollupCfg *rollup.Config, syncMode sync.Mode) *EngineController { +func NewEngineController(engine ExecEngine, log log.Logger, metrics Metrics, rollupCfg *rollup.Config, syncConfig *sync.Config) *EngineController { syncStatus := syncStatusCL - if syncMode == sync.ELSync { + if syncConfig.SyncMode == sync.ELSync { syncStatus = syncStatusWillStartEL } return &EngineController{ - engine: engine, - log: log, - metrics: metrics, - rollupCfg: rollupCfg, - syncMode: syncMode, - syncStatus: syncStatus, - clock: clock.SystemClock, + engine: engine, + log: log, + metrics: metrics, + rollupCfg: rollupCfg, + syncMode: syncConfig.SyncMode, + elTriggerGap: syncConfig.ELTriggerGap, + syncStatus: syncStatus, + clock: clock.SystemClock, } } @@ -328,7 +330,8 @@ func (e *EngineController) InsertUnsafePayload(ctx context.Context, envelope *et if e.syncStatus == syncStatusWillStartEL { b, err := e.engine.L2BlockRefByLabel(ctx, eth.Finalized) isTransitionBlock := e.rollupCfg.Genesis.L2.Number != 0 && b.Hash == e.rollupCfg.Genesis.L2.Hash - if errors.Is(err, ethereum.NotFound) || isTransitionBlock { + isGapSyncNeeded := ref.Number-e.UnsafeL2Head().Number > uint64(e.elTriggerGap) + if errors.Is(err, ethereum.NotFound) || isTransitionBlock || isGapSyncNeeded { e.syncStatus = syncStatusStartedEL e.log.Info("Starting EL sync") e.elStart = e.clock.Now() diff --git a/op-node/rollup/derive/engine_queue_test.go b/op-node/rollup/derive/engine_queue_test.go index 493554388c..ad6e32c85b 100644 --- a/op-node/rollup/derive/engine_queue_test.go +++ b/op-node/rollup/derive/engine_queue_test.go @@ -253,7 +253,11 @@ func TestEngineQueue_Finalize(t *testing.T) { prev := &fakeAttributesQueue{} - ec := NewEngineController(eng, logger, metrics, &rollup.Config{}, sync.CLSync) + ec := NewEngineController(eng, logger, metrics, &rollup.Config{}, &sync.Config{ + SyncMode: sync.CLSync, + SkipSyncStartCheck: false, + ELTriggerGap: 0, + }) eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}, safedb.Disabled) require.ErrorIs(t, eq.Reset(context.Background(), eth.L1BlockRef{}, eth.SystemConfig{}), io.EOF) @@ -493,7 +497,11 @@ func TestEngineQueue_ResetWhenUnsafeOriginNotCanonical(t *testing.T) { prev := &fakeAttributesQueue{origin: refE} - ec := NewEngineController(eng, logger, metrics, &rollup.Config{}, sync.CLSync) + ec := NewEngineController(eng, logger, metrics, &rollup.Config{}, &sync.Config{ + SyncMode: sync.CLSync, + SkipSyncStartCheck: false, + ELTriggerGap: 0, + }) eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}, safedb.Disabled) require.ErrorIs(t, eq.Reset(context.Background(), eth.L1BlockRef{}, eth.SystemConfig{}), io.EOF) @@ -832,7 +840,11 @@ func TestVerifyNewL1Origin(t *testing.T) { }, nil) prev := &fakeAttributesQueue{origin: refE} - ec := NewEngineController(eng, logger, metrics, &rollup.Config{}, sync.CLSync) + ec := NewEngineController(eng, logger, metrics, &rollup.Config{}, &sync.Config{ + SyncMode: sync.CLSync, + SkipSyncStartCheck: false, + ELTriggerGap: 0, + }) eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}, safedb.Disabled) require.ErrorIs(t, eq.Reset(context.Background(), eth.L1BlockRef{}, eth.SystemConfig{}), io.EOF) @@ -934,7 +946,11 @@ func TestBlockBuildingRace(t *testing.T) { } prev := &fakeAttributesQueue{origin: refA, attrs: attrs, islastInSpan: true} - ec := NewEngineController(eng, logger, metrics, &rollup.Config{}, sync.CLSync) + ec := NewEngineController(eng, logger, metrics, &rollup.Config{}, &sync.Config{ + SyncMode: sync.CLSync, + SkipSyncStartCheck: false, + ELTriggerGap: 0, + }) eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}, safedb.Disabled) require.ErrorIs(t, eq.Reset(context.Background(), eth.L1BlockRef{}, eth.SystemConfig{}), io.EOF) @@ -1108,7 +1124,11 @@ func TestResetLoop(t *testing.T) { prev := &fakeAttributesQueue{origin: refA, attrs: attrs, islastInSpan: true} - ec := NewEngineController(eng, logger, metrics.NoopMetrics, &rollup.Config{}, sync.CLSync) + ec := NewEngineController(eng, logger, metrics.NoopMetrics, &rollup.Config{}, &sync.Config{ + SyncMode: sync.CLSync, + SkipSyncStartCheck: false, + ELTriggerGap: 0, + }) eq := NewEngineQueue(logger, cfg, eng, ec, metrics.NoopMetrics, prev, l1F, &sync.Config{}, safedb.Disabled) eq.ec.SetUnsafeHead(refA2) eq.ec.SetSafeHead(refA1) @@ -1216,7 +1236,11 @@ func TestEngineQueue_StepPopOlderUnsafe(t *testing.T) { prev := &fakeAttributesQueue{origin: refA} - ec := NewEngineController(eng, logger, metrics.NoopMetrics, &rollup.Config{}, sync.CLSync) + ec := NewEngineController(eng, logger, metrics.NoopMetrics, &rollup.Config{}, &sync.Config{ + SyncMode: sync.CLSync, + SkipSyncStartCheck: false, + ELTriggerGap: 0, + }) eq := NewEngineQueue(logger, cfg, eng, ec, metrics.NoopMetrics, prev, l1F, &sync.Config{}, safedb.Disabled) eq.ec.SetUnsafeHead(refA2) eq.ec.SetSafeHead(refA0) @@ -1296,7 +1320,11 @@ func TestPlasmaFinalityData(t *testing.T) { SequenceNumber: 1, } - ec := NewEngineController(eng, logger, metrics.NoopMetrics, &rollup.Config{}, sync.CLSync) + ec := NewEngineController(eng, logger, metrics.NoopMetrics, &rollup.Config{}, &sync.Config{ + SyncMode: sync.CLSync, + SkipSyncStartCheck: false, + ELTriggerGap: 0, + }) eq := NewEngineQueue(logger, cfg, eng, ec, metrics.NoopMetrics, prev, l1F, &sync.Config{}, safedb.Disabled) require.Equal(t, expFinalityLookback, cap(eq.finalityData)) diff --git a/op-node/rollup/driver/driver.go b/op-node/rollup/driver/driver.go index c81a44bba6..ce800bd190 100644 --- a/op-node/rollup/driver/driver.go +++ b/op-node/rollup/driver/driver.go @@ -136,7 +136,7 @@ func NewDriver( sequencerConfDepth := NewConfDepth(driverCfg.SequencerConfDepth, l1State.L1Head, l1) findL1Origin := NewL1OriginSelector(log, cfg, sequencerConfDepth) verifConfDepth := NewConfDepth(driverCfg.VerifierConfDepth, l1State.L1Head, l1) - engine := derive.NewEngineController(l2, log, metrics, cfg, syncCfg.SyncMode) + engine := derive.NewEngineController(l2, log, metrics, cfg, syncCfg) derivationPipeline := derive.NewDerivationPipeline(log, cfg, verifConfDepth, l1Blobs, plasma, l2, engine, metrics, syncCfg, safeHeadListener) attrBuilder := derive.NewFetchingAttributesBuilder(cfg, l1, l2) meteredEngine := NewMeteredEngine(cfg, engine, metrics, log) // Only use the metered engine in the sequencer b/c it records sequencing metrics. diff --git a/op-node/rollup/sync/config.go b/op-node/rollup/sync/config.go index 3b0b6b2188..dcab50d824 100644 --- a/op-node/rollup/sync/config.go +++ b/op-node/rollup/sync/config.go @@ -70,4 +70,6 @@ type Config struct { // Note: We probably need to detect the condition that snap sync has not complete when we do a restart prior to running sync-start if we are doing // snap sync with a genesis finalization data. SkipSyncStartCheck bool `json:"skip_sync_start_check"` + // gap for trigger el-sync + ELTriggerGap int `json:"el_trigger_gap"` } diff --git a/op-node/service.go b/op-node/service.go index 0c8f713850..26a7de00e1 100644 --- a/op-node/service.go +++ b/op-node/service.go @@ -298,9 +298,19 @@ func NewSyncConfig(ctx *cli.Context, log log.Logger) (*sync.Config, error) { if err != nil { return nil, err } + + //fastnode config + elTriggerGap := ctx.Int(flags.ELTriggerGap.Name) + if ctx.Bool(flags.FastnodeMode.Name) { + mode = sync.ELSync + // fastnode needs a smaller gap + elTriggerGap = 120 + } + cfg := &sync.Config{ SyncMode: mode, SkipSyncStartCheck: ctx.Bool(flags.SkipSyncStartCheck.Name), + ELTriggerGap: elTriggerGap, } if ctx.Bool(flags.L2EngineSyncEnabled.Name) { cfg.SyncMode = sync.ELSync diff --git a/op-program/client/driver/driver.go b/op-program/client/driver/driver.go index 95cba25037..51abe56bc0 100644 --- a/op-program/client/driver/driver.go +++ b/op-program/client/driver/driver.go @@ -40,7 +40,12 @@ type Driver struct { } func NewDriver(logger log.Logger, cfg *rollup.Config, l1Source derive.L1Fetcher, l1BlobsSource derive.L1BlobsFetcher, l2Source L2Source, targetBlockNum uint64) *Driver { - engine := derive.NewEngineController(l2Source, logger, metrics.NoopMetrics, cfg, sync.CLSync) + engine := derive.NewEngineController(l2Source, logger, metrics.NoopMetrics, cfg, + &sync.Config{ + SyncMode: sync.CLSync, + SkipSyncStartCheck: false, + ELTriggerGap: 0, + }) pipeline := derive.NewDerivationPipeline(logger, cfg, l1Source, l1BlobsSource, plasma.Disabled, l2Source, engine, metrics.NoopMetrics, &sync.Config{}, safedb.Disabled) pipeline.Reset() return &Driver{