Commit caf41c55 authored by Sam Stokes's avatar Sam Stokes Committed by GitHub

op-proposer: Add option to wait for rollup sync during startup (#10262)

parent 08f3dbed
...@@ -72,6 +72,13 @@ var ( ...@@ -72,6 +72,13 @@ var (
Value: 2 * time.Minute, Value: 2 * time.Minute,
EnvVars: prefixEnvVars("ACTIVE_SEQUENCER_CHECK_DURATION"), EnvVars: prefixEnvVars("ACTIVE_SEQUENCER_CHECK_DURATION"),
} }
WaitNodeSyncFlag = &cli.BoolFlag{
Name: "wait-node-sync",
Usage: "Indicates if, during startup, the proposer should wait for the rollup node to sync to " +
"the current L1 tip before proceeding with its driver loop.",
Value: false,
EnvVars: prefixEnvVars("WAIT_NODE_SYNC"),
}
// Legacy Flags // Legacy Flags
L2OutputHDPathFlag = txmgr.L2OutputHDPathFlag L2OutputHDPathFlag = txmgr.L2OutputHDPathFlag
) )
...@@ -90,6 +97,7 @@ var optionalFlags = []cli.Flag{ ...@@ -90,6 +97,7 @@ var optionalFlags = []cli.Flag{
ProposalIntervalFlag, ProposalIntervalFlag,
DisputeGameTypeFlag, DisputeGameTypeFlag,
ActiveSequencerCheckDurationFlag, ActiveSequencerCheckDurationFlag,
WaitNodeSyncFlag,
} }
func init() { func init() {
......
...@@ -58,6 +58,9 @@ type CLIConfig struct { ...@@ -58,6 +58,9 @@ type CLIConfig struct {
// ActiveSequencerCheckDuration is the duration between checks to determine the active sequencer endpoint. // ActiveSequencerCheckDuration is the duration between checks to determine the active sequencer endpoint.
ActiveSequencerCheckDuration time.Duration ActiveSequencerCheckDuration time.Duration
// Whether to wait for the sequencer to sync to a recent block at startup.
WaitNodeSync bool
} }
func (c *CLIConfig) Check() error { func (c *CLIConfig) Check() error {
...@@ -106,5 +109,6 @@ func NewConfig(ctx *cli.Context) *CLIConfig { ...@@ -106,5 +109,6 @@ func NewConfig(ctx *cli.Context) *CLIConfig {
ProposalInterval: ctx.Duration(flags.ProposalIntervalFlag.Name), ProposalInterval: ctx.Duration(flags.ProposalIntervalFlag.Name),
DisputeGameType: uint32(ctx.Uint(flags.DisputeGameTypeFlag.Name)), DisputeGameType: uint32(ctx.Uint(flags.DisputeGameTypeFlag.Name)),
ActiveSequencerCheckDuration: ctx.Duration(flags.ActiveSequencerCheckDurationFlag.Name), ActiveSequencerCheckDuration: ctx.Duration(flags.ActiveSequencerCheckDurationFlag.Name),
WaitNodeSync: ctx.Bool(flags.WaitNodeSyncFlag.Name),
} }
} }
...@@ -415,6 +415,14 @@ func (l *L2OutputSubmitter) loop() { ...@@ -415,6 +415,14 @@ func (l *L2OutputSubmitter) loop() {
defer l.wg.Done() defer l.wg.Done()
ctx := l.ctx ctx := l.ctx
if l.Cfg.WaitNodeSync {
err := l.waitNodeSync()
if err != nil {
l.Log.Error("Error waiting for node sync", "err", err)
return
}
}
if l.dgfContract == nil { if l.dgfContract == nil {
l.loopL2OO(ctx) l.loopL2OO(ctx)
} else { } else {
...@@ -422,6 +430,23 @@ func (l *L2OutputSubmitter) loop() { ...@@ -422,6 +430,23 @@ func (l *L2OutputSubmitter) loop() {
} }
} }
func (l *L2OutputSubmitter) waitNodeSync() error {
ctx, cancel := context.WithTimeout(l.ctx, l.Cfg.NetworkTimeout)
defer cancel()
l1head, err := l.Txmgr.BlockNumber(ctx)
if err != nil {
return fmt.Errorf("failed to retrieve current L1 block number: %w", err)
}
rollupClient, err := l.RollupProvider.RollupClient(ctx)
if err != nil {
return fmt.Errorf("failed to get rollup client: %w", err)
}
return dial.WaitRollupSync(l.ctx, l.Log, rollupClient, l1head, time.Second*12)
}
func (l *L2OutputSubmitter) loopL2OO(ctx context.Context) { func (l *L2OutputSubmitter) loopL2OO(ctx context.Context) {
ticker := time.NewTicker(l.Cfg.PollInterval) ticker := time.NewTicker(l.Cfg.PollInterval)
defer ticker.Stop() defer ticker.Stop()
......
...@@ -44,6 +44,8 @@ type ProposerConfig struct { ...@@ -44,6 +44,8 @@ type ProposerConfig struct {
// is never valid on an alternative L1 chain that would produce different L2 data. // is never valid on an alternative L1 chain that would produce different L2 data.
// This option is not necessary when higher proposal latency is acceptable and L1 is healthy. // This option is not necessary when higher proposal latency is acceptable and L1 is healthy.
AllowNonFinalized bool AllowNonFinalized bool
WaitNodeSync bool
} }
type ProposerService struct { type ProposerService struct {
...@@ -89,6 +91,7 @@ func (ps *ProposerService) initFromCLIConfig(ctx context.Context, version string ...@@ -89,6 +91,7 @@ func (ps *ProposerService) initFromCLIConfig(ctx context.Context, version string
ps.PollInterval = cfg.PollInterval ps.PollInterval = cfg.PollInterval
ps.NetworkTimeout = cfg.TxMgrConfig.NetworkTimeout ps.NetworkTimeout = cfg.TxMgrConfig.NetworkTimeout
ps.AllowNonFinalized = cfg.AllowNonFinalized ps.AllowNonFinalized = cfg.AllowNonFinalized
ps.WaitNodeSync = cfg.WaitNodeSync
ps.initL2ooAddress(cfg) ps.initL2ooAddress(cfg)
ps.initDGF(cfg) ps.initDGF(cfg)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment