diff --git a/op-challenger/config/config.go b/op-challenger/config/config.go index 874acdcd145f2..d53eec9048d37 100644 --- a/op-challenger/config/config.go +++ b/op-challenger/config/config.go @@ -65,16 +65,17 @@ const ( // This also contains config options for auxiliary services. // It is used to initialize the challenger. type Config struct { - L1EthRpc string // L1 RPC Url - L1Beacon string // L1 Beacon API Url - GameFactoryAddress common.Address // Address of the dispute game factory - GameAllowlist []common.Address // Allowlist of fault game addresses - GameWindow time.Duration // Maximum time duration to look for games to progress - Datadir string // Data Directory - MaxConcurrency uint // Maximum number of threads to use when progressing games - PollInterval time.Duration // Polling interval for latest-block subscription when using an HTTP RPC provider - AllowInvalidPrestate bool // Whether to allow responding to games where the prestate does not match - MinUpdateInterval time.Duration // Minimum duration the L1 head block time must advance before scheduling a new update cycle + L1EthRpc string // L1 RPC Url + L1Beacon string // L1 Beacon API Url + L1BeaconSkipBlobVerification bool // Skip verification of the KZG proof for each blob. Not recommended unless the provided beacon endpoints are trusted. + GameFactoryAddress common.Address // Address of the dispute game factory + GameAllowlist []common.Address // Allowlist of fault game addresses + GameWindow time.Duration // Maximum time duration to look for games to progress + Datadir string // Data Directory + MaxConcurrency uint // Maximum number of threads to use when progressing games + PollInterval time.Duration // Polling interval for latest-block subscription when using an HTTP RPC provider + AllowInvalidPrestate bool // Whether to allow responding to games where the prestate does not match + MinUpdateInterval time.Duration // Minimum duration the L1 head block time must advance before scheduling a new update cycle AdditionalBondClaimants []common.Address // List of addresses to claim bonds for in addition to the tx manager sender @@ -151,42 +152,46 @@ func NewInteropConfig( Datadir: datadir, Cannon: vm.Config{ - VmType: types.TraceTypeCannon, - L1: l1EthRpc, - L1Beacon: l1BeaconApi, - L2s: l2Rpcs, - SnapshotFreq: DefaultCannonSnapshotFreq, - InfoFreq: DefaultCannonInfoFreq, - DebugInfo: true, - BinarySnapshots: true, + VmType: types.TraceTypeCannon, + L1: l1EthRpc, + L1Beacon: l1BeaconApi, + L1BeaconSkipBlobVerification: false, + L2s: l2Rpcs, + SnapshotFreq: DefaultCannonSnapshotFreq, + InfoFreq: DefaultCannonInfoFreq, + DebugInfo: true, + BinarySnapshots: true, }, CannonKona: vm.Config{ - VmType: types.TraceTypeCannonKona, - L1: l1EthRpc, - L1Beacon: l1BeaconApi, - L2s: l2Rpcs, - SnapshotFreq: DefaultCannonSnapshotFreq, - InfoFreq: DefaultCannonInfoFreq, - DebugInfo: true, - BinarySnapshots: true, + VmType: types.TraceTypeCannonKona, + L1: l1EthRpc, + L1Beacon: l1BeaconApi, + L1BeaconSkipBlobVerification: false, + L2s: l2Rpcs, + SnapshotFreq: DefaultCannonSnapshotFreq, + InfoFreq: DefaultCannonInfoFreq, + DebugInfo: true, + BinarySnapshots: true, }, Asterisc: vm.Config{ - VmType: types.TraceTypeAsterisc, - L1: l1EthRpc, - L1Beacon: l1BeaconApi, - L2s: l2Rpcs, - SnapshotFreq: DefaultAsteriscSnapshotFreq, - InfoFreq: DefaultAsteriscInfoFreq, - BinarySnapshots: true, + VmType: types.TraceTypeAsterisc, + L1: l1EthRpc, + L1Beacon: l1BeaconApi, + L1BeaconSkipBlobVerification: false, + L2s: l2Rpcs, + SnapshotFreq: DefaultAsteriscSnapshotFreq, + InfoFreq: DefaultAsteriscInfoFreq, + BinarySnapshots: true, }, AsteriscKona: vm.Config{ - VmType: types.TraceTypeAsteriscKona, - L1: l1EthRpc, - L1Beacon: l1BeaconApi, - L2s: l2Rpcs, - SnapshotFreq: DefaultAsteriscSnapshotFreq, - InfoFreq: DefaultAsteriscInfoFreq, - BinarySnapshots: true, + VmType: types.TraceTypeAsteriscKona, + L1: l1EthRpc, + L1Beacon: l1BeaconApi, + L1BeaconSkipBlobVerification: false, + L2s: l2Rpcs, + SnapshotFreq: DefaultAsteriscSnapshotFreq, + InfoFreq: DefaultAsteriscInfoFreq, + BinarySnapshots: true, }, GameWindow: DefaultGameWindow, } @@ -221,42 +226,46 @@ func NewConfig( Datadir: datadir, Cannon: vm.Config{ - VmType: types.TraceTypeCannon, - L1: l1EthRpc, - L1Beacon: l1BeaconApi, - L2s: []string{l2EthRpc}, - SnapshotFreq: DefaultCannonSnapshotFreq, - InfoFreq: DefaultCannonInfoFreq, - DebugInfo: true, - BinarySnapshots: true, + VmType: types.TraceTypeCannon, + L1: l1EthRpc, + L1Beacon: l1BeaconApi, + L1BeaconSkipBlobVerification: false, + L2s: []string{l2EthRpc}, + SnapshotFreq: DefaultCannonSnapshotFreq, + InfoFreq: DefaultCannonInfoFreq, + DebugInfo: true, + BinarySnapshots: true, }, CannonKona: vm.Config{ - VmType: types.TraceTypeCannonKona, - L1: l1EthRpc, - L1Beacon: l1BeaconApi, - L2s: []string{l2EthRpc}, - SnapshotFreq: DefaultCannonSnapshotFreq, - InfoFreq: DefaultCannonInfoFreq, - DebugInfo: true, - BinarySnapshots: true, + VmType: types.TraceTypeCannonKona, + L1: l1EthRpc, + L1Beacon: l1BeaconApi, + L1BeaconSkipBlobVerification: false, + L2s: []string{l2EthRpc}, + SnapshotFreq: DefaultCannonSnapshotFreq, + InfoFreq: DefaultCannonInfoFreq, + DebugInfo: true, + BinarySnapshots: true, }, Asterisc: vm.Config{ - VmType: types.TraceTypeAsterisc, - L1: l1EthRpc, - L1Beacon: l1BeaconApi, - L2s: []string{l2EthRpc}, - SnapshotFreq: DefaultAsteriscSnapshotFreq, - InfoFreq: DefaultAsteriscInfoFreq, - BinarySnapshots: true, + VmType: types.TraceTypeAsterisc, + L1: l1EthRpc, + L1Beacon: l1BeaconApi, + L1BeaconSkipBlobVerification: false, + L2s: []string{l2EthRpc}, + SnapshotFreq: DefaultAsteriscSnapshotFreq, + InfoFreq: DefaultAsteriscInfoFreq, + BinarySnapshots: true, }, AsteriscKona: vm.Config{ - VmType: types.TraceTypeAsteriscKona, - L1: l1EthRpc, - L1Beacon: l1BeaconApi, - L2s: []string{l2EthRpc}, - SnapshotFreq: DefaultAsteriscSnapshotFreq, - InfoFreq: DefaultAsteriscInfoFreq, - BinarySnapshots: true, + VmType: types.TraceTypeAsteriscKona, + L1: l1EthRpc, + L1Beacon: l1BeaconApi, + L1BeaconSkipBlobVerification: false, + L2s: []string{l2EthRpc}, + SnapshotFreq: DefaultAsteriscSnapshotFreq, + InfoFreq: DefaultAsteriscInfoFreq, + BinarySnapshots: true, }, GameWindow: DefaultGameWindow, } diff --git a/op-challenger/flags/flags.go b/op-challenger/flags/flags.go index a911eaaf1bfc7..4f4a16ac08c77 100644 --- a/op-challenger/flags/flags.go +++ b/op-challenger/flags/flags.go @@ -283,6 +283,13 @@ var ( EnvVars: prefixEnvVars("RESPONSE_DELAY_AFTER"), Value: config.DefaultResponseDelayAfter, } + L1BeaconSkipBlobVerificationFlag = &cli.BoolFlag{ + Name: "l1-beacon-skip-blob-verification", + Usage: "Skip verification of the KZG proof for each blob returned by the Beacon node. Not recommended unless the provided beacon endpoints are trusted.", + EnvVars: prefixEnvVars("L1_BEACON_SKIP_BLOB_VERIFICATION"), + Value: false, + Hidden: true, + } ) // requiredFlags are checked by [CheckRequired] @@ -330,6 +337,7 @@ var optionalFlags = []cli.Flag{ ResponseDelayFlag, ResponseDelayAfterFlag, L1GenesisFlag, + L1BeaconSkipBlobVerificationFlag, } func init() { @@ -695,103 +703,109 @@ func NewConfigFromCLI(ctx *cli.Context, logger log.Logger) (*config.Config, erro networks := ctx.StringSlice(flags.NetworkFlagName) l1EthRpc := ctx.String(L1EthRpcFlag.Name) l1Beacon := ctx.String(L1BeaconFlag.Name) + l1BeaconSkipBlobVerification := ctx.Bool(L1BeaconSkipBlobVerificationFlag.Name) l2Rpcs := ctx.StringSlice(L2EthRpcFlag.Name) l2Experimental := ctx.String(L2ExperimentalEthRpcFlag.Name) return &config.Config{ // Required Flags - L1EthRpc: l1EthRpc, - L1Beacon: l1Beacon, - TraceTypes: traceTypes, - GameFactoryAddress: gameFactoryAddress, - GameAllowlist: allowedGames, - GameWindow: ctx.Duration(GameWindowFlag.Name), - MaxConcurrency: maxConcurrency, - L2Rpcs: l2Rpcs, - MaxPendingTx: ctx.Uint64(MaxPendingTransactionsFlag.Name), - PollInterval: ctx.Duration(HTTPPollInterval.Name), - MinUpdateInterval: ctx.Duration(MinUpdateInterval.Name), - AdditionalBondClaimants: claimants, - RollupRpc: ctx.String(RollupRpcFlag.Name), - SupervisorRPC: ctx.String(SupervisorRpcFlag.Name), + L1EthRpc: l1EthRpc, + L1Beacon: l1Beacon, + L1BeaconSkipBlobVerification: l1BeaconSkipBlobVerification, + TraceTypes: traceTypes, + GameFactoryAddress: gameFactoryAddress, + GameAllowlist: allowedGames, + GameWindow: ctx.Duration(GameWindowFlag.Name), + MaxConcurrency: maxConcurrency, + L2Rpcs: l2Rpcs, + MaxPendingTx: ctx.Uint64(MaxPendingTransactionsFlag.Name), + PollInterval: ctx.Duration(HTTPPollInterval.Name), + MinUpdateInterval: ctx.Duration(MinUpdateInterval.Name), + AdditionalBondClaimants: claimants, + RollupRpc: ctx.String(RollupRpcFlag.Name), + SupervisorRPC: ctx.String(SupervisorRpcFlag.Name), Cannon: vm.Config{ - L1GenesisPath: ctx.String(L1GenesisFlag.Name), - VmType: types.TraceTypeCannon, - L1: l1EthRpc, - L1Beacon: l1Beacon, - L2s: l2Rpcs, - L2Experimental: l2Experimental, - VmBin: ctx.String(CannonBinFlag.Name), - Server: ctx.String(CannonServerFlag.Name), - Networks: networks, - L2Custom: ctx.Bool(CannonL2CustomFlag.Name), - RollupConfigPaths: RollupConfigFlag.StringSlice(ctx, types.TraceTypeCannon), - L2GenesisPaths: L2GenesisFlag.StringSlice(ctx, types.TraceTypeCannon), - DepsetConfigPath: DepsetConfigFlag.String(ctx, types.TraceTypeCannon), - SnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name), - InfoFreq: ctx.Uint(CannonInfoFreqFlag.Name), - DebugInfo: true, - BinarySnapshots: true, + L1GenesisPath: ctx.String(L1GenesisFlag.Name), + VmType: types.TraceTypeCannon, + L1: l1EthRpc, + L1Beacon: l1Beacon, + L1BeaconSkipBlobVerification: l1BeaconSkipBlobVerification, + L2s: l2Rpcs, + L2Experimental: l2Experimental, + VmBin: ctx.String(CannonBinFlag.Name), + Server: ctx.String(CannonServerFlag.Name), + Networks: networks, + L2Custom: ctx.Bool(CannonL2CustomFlag.Name), + RollupConfigPaths: RollupConfigFlag.StringSlice(ctx, types.TraceTypeCannon), + L2GenesisPaths: L2GenesisFlag.StringSlice(ctx, types.TraceTypeCannon), + DepsetConfigPath: DepsetConfigFlag.String(ctx, types.TraceTypeCannon), + SnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name), + InfoFreq: ctx.Uint(CannonInfoFreqFlag.Name), + DebugInfo: true, + BinarySnapshots: true, }, CannonAbsolutePreState: ctx.String(CannonPreStateFlag.Name), CannonAbsolutePreStateBaseURL: cannonPreStatesURL, CannonKona: vm.Config{ - L1GenesisPath: ctx.String(L1GenesisFlag.Name), - VmType: types.TraceTypeCannonKona, - L1: l1EthRpc, - L1Beacon: l1Beacon, - L2s: l2Rpcs, - L2Experimental: l2Experimental, - VmBin: ctx.String(CannonBinFlag.Name), - Server: ctx.String(CannonKonaServerFlag.Name), - Networks: networks, - L2Custom: ctx.Bool(CannonKonaL2CustomFlag.Name), - RollupConfigPaths: RollupConfigFlag.StringSlice(ctx, types.TraceTypeCannonKona), - L2GenesisPaths: L2GenesisFlag.StringSlice(ctx, types.TraceTypeCannonKona), - DepsetConfigPath: DepsetConfigFlag.String(ctx, types.TraceTypeCannonKona), - SnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name), - InfoFreq: ctx.Uint(CannonInfoFreqFlag.Name), - DebugInfo: true, - BinarySnapshots: true, + L1GenesisPath: ctx.String(L1GenesisFlag.Name), + VmType: types.TraceTypeCannonKona, + L1: l1EthRpc, + L1Beacon: l1Beacon, + L1BeaconSkipBlobVerification: l1BeaconSkipBlobVerification, + L2s: l2Rpcs, + L2Experimental: l2Experimental, + VmBin: ctx.String(CannonBinFlag.Name), + Server: ctx.String(CannonKonaServerFlag.Name), + Networks: networks, + L2Custom: ctx.Bool(CannonKonaL2CustomFlag.Name), + RollupConfigPaths: RollupConfigFlag.StringSlice(ctx, types.TraceTypeCannonKona), + L2GenesisPaths: L2GenesisFlag.StringSlice(ctx, types.TraceTypeCannonKona), + DepsetConfigPath: DepsetConfigFlag.String(ctx, types.TraceTypeCannonKona), + SnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name), + InfoFreq: ctx.Uint(CannonInfoFreqFlag.Name), + DebugInfo: true, + BinarySnapshots: true, }, CannonKonaAbsolutePreState: ctx.String(CannonKonaPreStateFlag.Name), CannonKonaAbsolutePreStateBaseURL: cannonKonaPreStatesURL, Datadir: ctx.String(DatadirFlag.Name), Asterisc: vm.Config{ - L1GenesisPath: ctx.String(L1GenesisFlag.Name), - VmType: types.TraceTypeAsterisc, - L1: l1EthRpc, - L1Beacon: l1Beacon, - L2s: l2Rpcs, - L2Experimental: l2Experimental, - VmBin: ctx.String(AsteriscBinFlag.Name), - Server: ctx.String(AsteriscServerFlag.Name), - Networks: networks, - RollupConfigPaths: RollupConfigFlag.StringSlice(ctx, types.TraceTypeAsterisc), - L2GenesisPaths: L2GenesisFlag.StringSlice(ctx, types.TraceTypeAsterisc), - DepsetConfigPath: DepsetConfigFlag.String(ctx, types.TraceTypeAsterisc), - SnapshotFreq: ctx.Uint(AsteriscSnapshotFreqFlag.Name), - InfoFreq: ctx.Uint(AsteriscInfoFreqFlag.Name), - BinarySnapshots: true, + L1GenesisPath: ctx.String(L1GenesisFlag.Name), + VmType: types.TraceTypeAsterisc, + L1: l1EthRpc, + L1Beacon: l1Beacon, + L1BeaconSkipBlobVerification: l1BeaconSkipBlobVerification, + L2s: l2Rpcs, + L2Experimental: l2Experimental, + VmBin: ctx.String(AsteriscBinFlag.Name), + Server: ctx.String(AsteriscServerFlag.Name), + Networks: networks, + RollupConfigPaths: RollupConfigFlag.StringSlice(ctx, types.TraceTypeAsterisc), + L2GenesisPaths: L2GenesisFlag.StringSlice(ctx, types.TraceTypeAsterisc), + DepsetConfigPath: DepsetConfigFlag.String(ctx, types.TraceTypeAsterisc), + SnapshotFreq: ctx.Uint(AsteriscSnapshotFreqFlag.Name), + InfoFreq: ctx.Uint(AsteriscInfoFreqFlag.Name), + BinarySnapshots: true, }, AsteriscAbsolutePreState: ctx.String(AsteriscPreStateFlag.Name), AsteriscAbsolutePreStateBaseURL: asteriscPreStatesURL, AsteriscKona: vm.Config{ - L1GenesisPath: ctx.String(L1GenesisFlag.Name), - VmType: types.TraceTypeAsteriscKona, - L1: l1EthRpc, - L1Beacon: l1Beacon, - L2s: l2Rpcs, - L2Experimental: l2Experimental, - VmBin: ctx.String(AsteriscBinFlag.Name), - Server: ctx.String(AsteriscKonaServerFlag.Name), - Networks: networks, - L2Custom: ctx.Bool(AsteriscKonaL2CustomFlag.Name), - RollupConfigPaths: RollupConfigFlag.StringSlice(ctx, types.TraceTypeAsteriscKona), - L2GenesisPaths: L2GenesisFlag.StringSlice(ctx, types.TraceTypeAsteriscKona), - DepsetConfigPath: DepsetConfigFlag.String(ctx, types.TraceTypeAsteriscKona), - SnapshotFreq: ctx.Uint(AsteriscSnapshotFreqFlag.Name), - InfoFreq: ctx.Uint(AsteriscInfoFreqFlag.Name), - BinarySnapshots: true, + L1GenesisPath: ctx.String(L1GenesisFlag.Name), + VmType: types.TraceTypeAsteriscKona, + L1: l1EthRpc, + L1Beacon: l1Beacon, + L1BeaconSkipBlobVerification: l1BeaconSkipBlobVerification, + L2s: l2Rpcs, + L2Experimental: l2Experimental, + VmBin: ctx.String(AsteriscBinFlag.Name), + Server: ctx.String(AsteriscKonaServerFlag.Name), + Networks: networks, + L2Custom: ctx.Bool(AsteriscKonaL2CustomFlag.Name), + RollupConfigPaths: RollupConfigFlag.StringSlice(ctx, types.TraceTypeAsteriscKona), + L2GenesisPaths: L2GenesisFlag.StringSlice(ctx, types.TraceTypeAsteriscKona), + DepsetConfigPath: DepsetConfigFlag.String(ctx, types.TraceTypeAsteriscKona), + SnapshotFreq: ctx.Uint(AsteriscSnapshotFreqFlag.Name), + InfoFreq: ctx.Uint(AsteriscInfoFreqFlag.Name), + BinarySnapshots: true, }, AsteriscKonaAbsolutePreState: ctx.String(AsteriscKonaPreStateFlag.Name), AsteriscKonaAbsolutePreStateBaseURL: asteriscKonaPreStatesURL, diff --git a/op-challenger/game/fault/trace/vm/executor.go b/op-challenger/game/fault/trace/vm/executor.go index 38fe3791c84dd..4aa2d7673e153 100644 --- a/op-challenger/game/fault/trace/vm/executor.go +++ b/op-challenger/game/fault/trace/vm/executor.go @@ -49,17 +49,18 @@ type Config struct { BinarySnapshots bool // Whether to use binary snapshots instead of JSON // Host Configuration - L1 string - L1Beacon string - L2s []string - L2Experimental string - Server string // Path to the executable that provides the pre-image oracle server - Networks []string - L2Custom bool - RollupConfigPaths []string - L1GenesisPath string - L2GenesisPaths []string - DepsetConfigPath string + L1 string + L1Beacon string + L1BeaconSkipBlobVerification bool // Skip verification of the KZG proof for each blob. Not recommended unless the provided beacon endpoints are trusted. + L2s []string + L2Experimental string + Server string // Path to the executable that provides the pre-image oracle server + Networks []string + L2Custom bool + RollupConfigPaths []string + L1GenesisPath string + L2GenesisPaths []string + DepsetConfigPath string } func (c *Config) Check() error { diff --git a/op-challenger/game/fault/trace/vm/kona_server_executor.go b/op-challenger/game/fault/trace/vm/kona_server_executor.go index 76da826975487..8d5337f9abeae 100644 --- a/op-challenger/game/fault/trace/vm/kona_server_executor.go +++ b/op-challenger/game/fault/trace/vm/kona_server_executor.go @@ -61,5 +61,9 @@ func (s *KonaExecutor) OracleCommand(cfg Config, dataDir string, inputs utils.Lo args = append(args, "--l1-config-path", cfg.L1GenesisPath) } + if cfg.L1BeaconSkipBlobVerification { + args = append(args, "--l1-beacon-skip-blob-verification") + } + return args, nil } diff --git a/op-challenger/game/fault/trace/vm/kona_server_executor_test.go b/op-challenger/game/fault/trace/vm/kona_server_executor_test.go index 8894bfab8b2fb..e55fd59cb51e2 100644 --- a/op-challenger/game/fault/trace/vm/kona_server_executor_test.go +++ b/op-challenger/game/fault/trace/vm/kona_server_executor_test.go @@ -46,3 +46,76 @@ func TestKonaFillHostCommand(t *testing.T) { require.True(t, slices.Contains(args, "--claimed-l2-block-number")) require.True(t, slices.Contains(args, "--l1-config-path")) } + +func TestKonaL1BeaconSkipBlobVerification(t *testing.T) { + dir := "mockdir" + baseCfg := Config{ + L1: "http://localhost:8888", + L1Beacon: "http://localhost:9000", + L2s: []string{"http://localhost:9999"}, + Server: "./bin/mockserver", + Networks: []string{"op-mainnet"}, + L1GenesisPath: "mockdir/l1-genesis-1.json", + } + inputs := utils.LocalGameInputs{ + L1Head: common.Hash{0x11}, + L2Head: common.Hash{0x22}, + L2OutputRoot: common.Hash{0x33}, + L2Claim: common.Hash{0x44}, + L2SequenceNumber: big.NewInt(3333), + } + + t.Run("NotIncludedByDefault", func(t *testing.T) { + cfg := baseCfg + cfg.L1BeaconSkipBlobVerification = false + vmConfig := NewKonaExecutor() + args, err := vmConfig.OracleCommand(cfg, dir, inputs) + require.NoError(t, err) + require.False(t, slices.Contains(args, "--l1-beacon-skip-blob-verification")) + }) + + t.Run("IncludedWhenTrue", func(t *testing.T) { + cfg := baseCfg + cfg.L1BeaconSkipBlobVerification = true + vmConfig := NewKonaExecutor() + args, err := vmConfig.OracleCommand(cfg, dir, inputs) + require.NoError(t, err) + require.True(t, slices.Contains(args, "--l1-beacon-skip-blob-verification")) + }) +} + +func TestKonaSuperL1BeaconSkipBlobVerification(t *testing.T) { + dir := "mockdir" + baseCfg := Config{ + L1: "http://localhost:8888", + L1Beacon: "http://localhost:9000", + L2s: []string{"http://localhost:9999", "http://localhost:9998"}, + Server: "./bin/mockserver", + RollupConfigPaths: []string{"rollup1.json", "rollup2.json"}, + L1GenesisPath: "mockdir/l1-genesis-1.json", + } + inputs := utils.LocalGameInputs{ + L1Head: common.Hash{0x11}, + AgreedPreState: []byte{1, 2, 3, 4}, + L2Claim: common.Hash{0x44}, + L2SequenceNumber: big.NewInt(3333), + } + + t.Run("NotIncludedByDefault", func(t *testing.T) { + cfg := baseCfg + cfg.L1BeaconSkipBlobVerification = false + vmConfig := NewKonaSuperExecutor() + args, err := vmConfig.OracleCommand(cfg, dir, inputs) + require.NoError(t, err) + require.False(t, slices.Contains(args, "--l1-beacon-skip-blob-verification")) + }) + + t.Run("IncludedWhenTrue", func(t *testing.T) { + cfg := baseCfg + cfg.L1BeaconSkipBlobVerification = true + vmConfig := NewKonaSuperExecutor() + args, err := vmConfig.OracleCommand(cfg, dir, inputs) + require.NoError(t, err) + require.True(t, slices.Contains(args, "--l1-beacon-skip-blob-verification")) + }) +} diff --git a/op-challenger/game/fault/trace/vm/kona_super_server_executor.go b/op-challenger/game/fault/trace/vm/kona_super_server_executor.go index 5aa347f70e5f7..8843abf33dec1 100644 --- a/op-challenger/game/fault/trace/vm/kona_super_server_executor.go +++ b/op-challenger/game/fault/trace/vm/kona_super_server_executor.go @@ -54,5 +54,9 @@ func (s *KonaSuperExecutor) OracleCommand(cfg Config, dataDir string, inputs uti args = append(args, "--l1-config-path", cfg.L1GenesisPath) } + if cfg.L1BeaconSkipBlobVerification { + args = append(args, "--l1-beacon-skip-blob-verification") + } + return args, nil } diff --git a/op-challenger/game/fault/trace/vm/op_program_server_executor.go b/op-challenger/game/fault/trace/vm/op_program_server_executor.go index c56d3aa4b79d0..a89b33894344f 100644 --- a/op-challenger/game/fault/trace/vm/op_program_server_executor.go +++ b/op-challenger/game/fault/trace/vm/op_program_server_executor.go @@ -75,5 +75,8 @@ func (s *OpProgramServerExecutor) OracleCommand(cfg Config, dataDir string, inpu if cfg.L1GenesisPath != "" { args = append(args, "--l1.config", cfg.L1GenesisPath) } + if cfg.L1BeaconSkipBlobVerification { + args = append(args, "--l1.beacon.skip-blob-verification") + } return args, nil } diff --git a/op-challenger/game/fault/trace/vm/op_program_server_executor_test.go b/op-challenger/game/fault/trace/vm/op_program_server_executor_test.go index 37fa6a2600733..72f7b20a7be9c 100644 --- a/op-challenger/game/fault/trace/vm/op_program_server_executor_test.go +++ b/op-challenger/game/fault/trace/vm/op_program_server_executor_test.go @@ -20,8 +20,8 @@ func TestOpProgramFillHostCommand(t *testing.T) { toPairs := func(args []string) map[string]string { pairs := make(map[string]string, len(args)/2) for i := 0; i < len(args); i += 2 { - // l2.custom is a boolean flag so can't accept a value after a space - if args[i] == "--l2.custom" { + // Boolean flags can't accept a value after a space + if args[i] == "--l2.custom" || args[i] == "--l1.beacon.skip-blob-verification" { pairs[args[i]] = "true" i-- continue @@ -217,4 +217,18 @@ func TestOpProgramFillHostCommand(t *testing.T) { require.Equal(t, pairs["--log.level"], logTest.arg) }) } + + t.Run("WithoutL1BeaconSkipBlobVerification", func(t *testing.T) { + pairs := oracleCommand(t, log.LvlInfo, func(c *Config, _ *utils.LocalGameInputs) { + c.L1BeaconSkipBlobVerification = false + }) + require.NotContains(t, pairs, "--l1.beacon.skip-blob-verification") + }) + + t.Run("WithL1BeaconSkipBlobVerification", func(t *testing.T) { + pairs := oracleCommand(t, log.LvlInfo, func(c *Config, _ *utils.LocalGameInputs) { + c.L1BeaconSkipBlobVerification = true + }) + require.Equal(t, "true", pairs["--l1.beacon.skip-blob-verification"]) + }) } diff --git a/op-program/host/config/config.go b/op-program/host/config/config.go index 3aa5190bdcdc6..5dde48f8695cd 100644 --- a/op-program/host/config/config.go +++ b/op-program/host/config/config.go @@ -60,11 +60,12 @@ type Config struct { DataFormat types.DataFormat // L1Head is the block hash of the L1 chain head block - L1Head common.Hash - L1URL string - L1BeaconURL string - L1TrustRPC bool - L1RPCKind sources.RPCProviderKind + L1Head common.Hash + L1URL string + L1BeaconURL string + L1BeaconSkipBlobVerification bool // Skip verification of the KZG proof for each blob. Not recommended unless the provided beacon endpoints are trusted. + L1TrustRPC bool + L1RPCKind sources.RPCProviderKind // L2Head is the l2 block hash contained in the L2 Output referenced by the L2OutputRoot for pre-interop mode L2Head common.Hash @@ -396,28 +397,29 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) { } return &Config{ - L2ChainID: l2ChainID, - Rollups: rollupCfgs, - L1ChainConfig: l1ChainConfig, - DataDir: ctx.String(flags.DataDir.Name), - DataFormat: dbFormat, - L2URLs: ctx.StringSlice(flags.L2NodeAddr.Name), - L2ExperimentalURLs: ctx.StringSlice(flags.L2NodeExperimentalAddr.Name), - L2ChainConfigs: l2ChainConfigs, - L2Head: l2Head, - L2OutputRoot: l2OutputRoot, - AgreedPrestate: agreedPrestate, - DependencySet: dependencySet, - L2Claim: l2Claim, - L2ClaimBlockNumber: l2ClaimBlockNum, - L1Head: l1Head, - L1URL: ctx.String(flags.L1NodeAddr.Name), - L1BeaconURL: ctx.String(flags.L1BeaconAddr.Name), - L1TrustRPC: ctx.Bool(flags.L1TrustRPC.Name), - L1RPCKind: sources.RPCProviderKind(ctx.String(flags.L1RPCProviderKind.Name)), - ExecCmd: ctx.String(flags.Exec.Name), - ServerMode: ctx.Bool(flags.Server.Name), - InteropEnabled: interopEnabled, + L2ChainID: l2ChainID, + Rollups: rollupCfgs, + L1ChainConfig: l1ChainConfig, + DataDir: ctx.String(flags.DataDir.Name), + DataFormat: dbFormat, + L2URLs: ctx.StringSlice(flags.L2NodeAddr.Name), + L2ExperimentalURLs: ctx.StringSlice(flags.L2NodeExperimentalAddr.Name), + L2ChainConfigs: l2ChainConfigs, + L2Head: l2Head, + L2OutputRoot: l2OutputRoot, + AgreedPrestate: agreedPrestate, + DependencySet: dependencySet, + L2Claim: l2Claim, + L2ClaimBlockNumber: l2ClaimBlockNum, + L1Head: l1Head, + L1URL: ctx.String(flags.L1NodeAddr.Name), + L1BeaconURL: ctx.String(flags.L1BeaconAddr.Name), + L1BeaconSkipBlobVerification: ctx.Bool(flags.L1BeaconSkipBlobVerification.Name), + L1TrustRPC: ctx.Bool(flags.L1TrustRPC.Name), + L1RPCKind: sources.RPCProviderKind(ctx.String(flags.L1RPCProviderKind.Name)), + ExecCmd: ctx.String(flags.Exec.Name), + ServerMode: ctx.Bool(flags.Server.Name), + InteropEnabled: interopEnabled, }, nil } diff --git a/op-program/host/config/config_test.go b/op-program/host/config/config_test.go index 0dc868adb6c77..b66b4eb2787ec 100644 --- a/op-program/host/config/config_test.go +++ b/op-program/host/config/config_test.go @@ -310,3 +310,24 @@ func validInteropConfig() *Config { cfg.L2OutputRoot = crypto.Keccak256Hash(cfg.AgreedPrestate) return cfg } + +func TestL1BeaconSkipBlobVerification(t *testing.T) { + t.Run("DefaultIsFalse", func(t *testing.T) { + cfg := validConfig() + require.False(t, cfg.L1BeaconSkipBlobVerification, "L1BeaconSkipBlobVerification should default to false") + }) + + t.Run("CanBeSetToTrue", func(t *testing.T) { + cfg := validConfig() + cfg.L1BeaconSkipBlobVerification = true + require.True(t, cfg.L1BeaconSkipBlobVerification) + require.NoError(t, cfg.Check()) + }) + + t.Run("WorksWithInterop", func(t *testing.T) { + cfg := validInteropConfig() + cfg.L1BeaconSkipBlobVerification = true + require.True(t, cfg.L1BeaconSkipBlobVerification) + require.NoError(t, cfg.Check()) + }) +} diff --git a/op-program/host/flags/flags.go b/op-program/host/flags/flags.go index 01aab1990718c..cd666b97b2cf7 100644 --- a/op-program/host/flags/flags.go +++ b/op-program/host/flags/flags.go @@ -112,6 +112,12 @@ var ( Usage: "Address of L1 Beacon API endpoint to use", EnvVars: prefixEnvVars("L1_BEACON_API"), } + L1BeaconSkipBlobVerification = &cli.BoolFlag{ + Name: "l1.beacon.skip-blob-verification", + Usage: "Skip verification of the kzg_proof for each blob returned by the Beacon node. Not recommended unless the provided beacon endpoints are trusted.", + Value: false, + EnvVars: prefixEnvVars("L1_BEACON_SKIP_BLOB_VERIFICATION"), + } L1TrustRPC = &cli.BoolFlag{ Name: "l1.trustrpc", Usage: "Trust the L1 RPC, sync faster at risk of malicious/buggy RPC providing bad or inconsistent L1 data", @@ -169,6 +175,7 @@ var programFlags = []cli.Flag{ L2GenesisPath, L1NodeAddr, L1BeaconAddr, + L1BeaconSkipBlobVerification, L1TrustRPC, L1RPCProviderKind, DepsetConfig, diff --git a/op-program/host/host.go b/op-program/host/host.go index be9063f316960..5f3a3f5479784 100644 --- a/op-program/host/host.go +++ b/op-program/host/host.go @@ -95,7 +95,10 @@ func makeDefaultPrefetcher(ctx context.Context, logger log.Logger, kv kvstore.KV logger.Info("Connecting to L1 beacon", "l1", cfg.L1BeaconURL) l1Beacon := sources.NewBeaconHTTPClient(client.NewBasicHTTPClient(cfg.L1BeaconURL, logger)) - l1BlobFetcher := sources.NewL1BeaconClient(l1Beacon, sources.L1BeaconClientConfig{FetchAllSidecars: false}) + l1BlobFetcher := sources.NewL1BeaconClient(l1Beacon, sources.L1BeaconClientConfig{ + FetchAllSidecars: false, + SkipBlobVerification: cfg.L1BeaconSkipBlobVerification, + }) logger.Info("Initializing L2 clients") sources, err := prefetcher.NewRetryingL2SourcesFromURLs(ctx, logger, cfg.Rollups, cfg.L2URLs, cfg.L2ExperimentalURLs)