diff --git a/op-wheel/commands.go b/op-wheel/commands.go index c8915ebaeac7..e0b2e16c73d7 100644 --- a/op-wheel/commands.go +++ b/op-wheel/commands.go @@ -78,11 +78,17 @@ var ( EnvVar: opservice.PrefixEnvVar(envVarPrefix, "BUILDING_TIME"), Value: time.Second * 6, } + AllowGaps = cli.BoolFlag{ + Name: "allow-gaps", + Usage: "allow gaps in block building, like missed slots on the beacon chain.", + EnvVar: opservice.PrefixEnvVar(envVarPrefix, "ALLOW_GAPS"), + } ) func ParseBuildingArgs(ctx *cli.Context) *engine.BlockBuildingSettings { return &engine.BlockBuildingSettings{ BlockTime: ctx.Uint64(BlockTimeFlag.Name), + AllowGaps: ctx.Bool(AllowGaps.Name), Random: hashFlagValue(RandaoFlag.Name, ctx), FeeRecipient: addrFlagValue(FeeRecipientFlag.Name, ctx), BuildTime: ctx.Duration(BuildingTime.Name), @@ -336,7 +342,7 @@ var ( Usage: "build the next block using the Engine API", Flags: []cli.Flag{ EngineEndpoint, EngineJWTPath, - FeeRecipientFlag, RandaoFlag, BlockTimeFlag, BuildingTime, + FeeRecipientFlag, RandaoFlag, BlockTimeFlag, BuildingTime, AllowGaps, }, // TODO: maybe support transaction and tx pool engine flags, since we use op-geth? // TODO: reorg flag @@ -362,7 +368,7 @@ var ( Description: "The block time can be changed. The execution engine must be synced to a post-Merge state first.", Flags: append(append([]cli.Flag{ EngineEndpoint, EngineJWTPath, - FeeRecipientFlag, RandaoFlag, BlockTimeFlag, BuildingTime, + FeeRecipientFlag, RandaoFlag, BlockTimeFlag, BuildingTime, AllowGaps, }, oplog.CLIFlags(envVarPrefix)...), opmetrics.CLIFlags(envVarPrefix)...), Action: EngineAction(func(ctx *cli.Context, client client.RPC) error { logCfg := oplog.ReadLocalCLIConfig(ctx) diff --git a/op-wheel/engine/engine.go b/op-wheel/engine/engine.go index e22673113a55..fceafc6db0e3 100644 --- a/op-wheel/engine/engine.go +++ b/op-wheel/engine/engine.go @@ -95,13 +95,22 @@ func updateForkchoice(ctx context.Context, client client.RPC, head, safe, finali } type BlockBuildingSettings struct { - BlockTime uint64 + BlockTime uint64 + // skip a block; timestamps will still increase in multiples of BlockTime like L1, but there may be gaps. + AllowGaps bool Random common.Hash FeeRecipient common.Address BuildTime time.Duration } func BuildBlock(ctx context.Context, client client.RPC, status *StatusData, settings *BlockBuildingSettings) (*engine.ExecutableData, error) { + timestamp := status.Head.Time + settings.BlockTime + if settings.AllowGaps { + now := uint64(time.Now().Unix()) + if now > timestamp { + timestamp = now - ((now - timestamp) % settings.BlockTime) + } + } var pre engine.ForkChoiceResponse if err := client.CallContext(ctx, &pre, "engine_forkchoiceUpdatedV1", engine.ForkchoiceStateV1{ @@ -109,7 +118,7 @@ func BuildBlock(ctx context.Context, client client.RPC, status *StatusData, sett SafeBlockHash: status.Safe.Hash, FinalizedBlockHash: status.Finalized.Hash, }, engine.PayloadAttributes{ - Timestamp: status.Head.Time + settings.BlockTime, + Timestamp: timestamp, Random: settings.Random, SuggestedFeeRecipient: settings.FeeRecipient, // TODO: maybe use the L2 fields to hack in tx embedding CLI option? @@ -210,6 +219,7 @@ func Auto(ctx context.Context, metrics Metricer, client client.RPC, log log.Logg payload, err := BuildBlock(ctx, client, status, &BlockBuildingSettings{ BlockTime: settings.BlockTime, + AllowGaps: settings.AllowGaps, Random: settings.Random, FeeRecipient: settings.FeeRecipient, BuildTime: buildTime,