diff --git a/op-node/flags/flags.go b/op-node/flags/flags.go index e8694e0476cee..5867f8b46981f 100644 --- a/op-node/flags/flags.go +++ b/op-node/flags/flags.go @@ -419,6 +419,16 @@ var ( Destination: new(string), Category: InteropCategory, } + + IgnoreMissingPectraBlobSchedule = &cli.BoolFlag{ + Name: "ignore-missing-pectra-blob-schedule", + Usage: "Ignore missing pectra blob schedule fix for Sepolia and Holesky chains. Only set if you know what you are doing!" + + "Ask your chain's operator for the correct Pectra blob schedule activation time and set it via the rollup.json config" + + "or use the --override.pectrablobschedule flag.", + EnvVars: prefixEnvVars("IGNORE_MISSING_PECTRA_BLOB_SCHEDULE"), + Category: RollupCategory, + Hidden: true, + } ) var requiredFlags = []cli.Flag{ @@ -471,6 +481,7 @@ var optionalFlags = []cli.Flag{ InteropRPCAddr, InteropRPCPort, InteropJWTSecret, + IgnoreMissingPectraBlobSchedule, } var DeprecatedFlags = []cli.Flag{ diff --git a/op-node/node/config.go b/op-node/node/config.go index 9fb112eb39a06..12587e1c396dd 100644 --- a/op-node/node/config.go +++ b/op-node/node/config.go @@ -76,6 +76,8 @@ type Config struct { // AltDA config AltDA altda.CLIConfig + + IgnoreMissingPectraBlobSchedule bool } // ConductorRPCFunc retrieves the endpoint. The RPC may not immediately be available. @@ -127,6 +129,8 @@ func (cfg *Config) LoadPersisted(log log.Logger) error { return nil } +var ErrMissingPectraBlobSchedule = errors.New("probably missing Pectra blob schedule") + // Check verifies that the given configuration makes sense func (cfg *Config) Check() error { if err := cfg.L1.Check(); err != nil { @@ -154,6 +158,13 @@ func (cfg *Config) Check() error { if err := cfg.Rollup.Check(); err != nil { return fmt.Errorf("rollup config error: %w", err) } + if !cfg.IgnoreMissingPectraBlobSchedule && cfg.Rollup.ProbablyMissingPectraBlobSchedule() { + log.Error("Your rollup config seems to be missing the Pectra blob schedule fix. " + + "Reach out to your chain operator for the correct Pectra blob schedule configuration. " + + "If you know what you are doing, you can disable this error by setting the " + + "'--ignore-missing-pectra-blob-schedule' flag or 'IGNORE_MISSING_PECTRA_BLOB_SCHEDULE' env var.") + return ErrMissingPectraBlobSchedule + } if err := cfg.Metrics.Check(); err != nil { return fmt.Errorf("metrics config error: %w", err) } diff --git a/op-node/rollup/types.go b/op-node/rollup/types.go index b35da90649c77..949914c48d985 100644 --- a/op-node/rollup/types.go +++ b/op-node/rollup/types.go @@ -358,6 +358,32 @@ func (cfg *Config) HasOptimismWithdrawalsRoot(timestamp uint64) bool { return cfg.IsIsthmus(timestamp) } +// ProbablyMissingPectraBlobSchedule returns whether the chain is likely missing the Pectra blob +// schedule fix. +// A chain probably needs the Pectra blob schedule fix if: +// - its L1 in Holesky or Sepolia, and +// - its genesis is before the L1's Prague activation. +func (cfg *Config) ProbablyMissingPectraBlobSchedule() bool { + if cfg.PectraBlobScheduleTime != nil { + return false + } + + var pragueTime uint64 + if cfg.L1ChainID.Cmp(params.HoleskyChainConfig.ChainID) == 0 { + pragueTime = *params.HoleskyChainConfig.PragueTime + } else if cfg.L1ChainID.Cmp(params.SepoliaChainConfig.ChainID) == 0 { + pragueTime = *params.SepoliaChainConfig.PragueTime + } else { + // Only Holesky and Sepolia chains may have run into the + // Pectra blob schedule bug. + return false + } + + // Only chains whose genesis was before the L1's prague activation need + // the Pectra blob schedule fix. + return pragueTime >= cfg.Genesis.L2Time +} + // validateAltDAConfig checks the two approaches to configuring alt-da mode. // If the legacy values are set, they are copied to the new location. If both are set, they are check for consistency. func validateAltDAConfig(cfg *Config) error { diff --git a/op-node/rollup/types_test.go b/op-node/rollup/types_test.go index f714bc94723f4..4f1e6a5750637 100644 --- a/op-node/rollup/types_test.go +++ b/op-node/rollup/types_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -823,3 +824,66 @@ func TestConfigImplementsBlockType(t *testing.T) { }) } } + +func TestConfig_ProbablyMissingPectraBlobSchedule(t *testing.T) { + hol, sep := params.HoleskyChainConfig, params.SepoliaChainConfig + + for _, tt := range []struct { + name string + pectraBlobScheduleTime *uint64 + l2genesisTime uint64 + l1chainID *big.Int + expMissing bool + }{ + { + name: "sepolia-ok", + pectraBlobScheduleTime: u64ptr(1742486400), // sepolia superchain + l2genesisTime: 1691802540, // op-sepolia + l1chainID: sep.ChainID, + }, + { + name: "holesky-ok", + pectraBlobScheduleTime: u64ptr(1742486400), // sepolia superchain + l2genesisTime: 1691802540, // op-sepolia + l1chainID: hol.ChainID, + }, + { + name: "sepolia-missing", + l2genesisTime: 1691802540, // op-sepolia + l1chainID: sep.ChainID, + expMissing: true, + }, + { + name: "holesky-missing", + l2genesisTime: 1691802540, // op-sepolia + l1chainID: hol.ChainID, + expMissing: true, + }, + { + name: "sepolia-young-genesis", + l2genesisTime: *sep.PragueTime + 1, + l1chainID: sep.ChainID, + }, + { + name: "holesky-young-genesis", + l2genesisTime: *hol.PragueTime + 1, + l1chainID: hol.ChainID, + }, + { + name: "other-missing-ok", + l2genesisTime: 1691802540, + l1chainID: big.NewInt(1), + }, + } { + t.Run(tt.name, func(t *testing.T) { + cfg := &Config{ + Genesis: Genesis{ + L2Time: tt.l2genesisTime, + }, + PectraBlobScheduleTime: tt.pectraBlobScheduleTime, + L1ChainID: tt.l1chainID, + } + assert.Equal(t, tt.expMissing, cfg.ProbablyMissingPectraBlobSchedule()) + }) + } +} diff --git a/op-node/service.go b/op-node/service.go index 81f269ed08c19..350bbbe26e3a4 100644 --- a/op-node/service.go +++ b/op-node/service.go @@ -115,6 +115,8 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { ConductorRpcTimeout: ctx.Duration(flags.ConductorRpcTimeoutFlag.Name), AltDA: altda.ReadCLIConfig(ctx), + + IgnoreMissingPectraBlobSchedule: ctx.Bool(flags.IgnoreMissingPectraBlobSchedule.Name), } if err := cfg.LoadPersisted(log); err != nil {