diff --git a/op-challenger/cmd/main_test.go b/op-challenger/cmd/main_test.go index ca97f8b24cbc4..c06c94090133d 100644 --- a/op-challenger/cmd/main_test.go +++ b/op-challenger/cmd/main_test.go @@ -103,10 +103,13 @@ func TestOpSupervisor(t *testing.T) { t.Run("RequiredForSuperPermissioned", func(t *testing.T) { verifyArgsInvalid(t, "flag supervisor-rpc is required", addRequiredArgsExcept(types.TraceTypeSuperPermissioned, "--supervisor-rpc")) }) + t.Run("RequiredForSuperAsteriscKona", func(t *testing.T) { + verifyArgsInvalid(t, "flag supervisor-rpc is required", addRequiredArgsExcept(types.TraceTypeSuperAsteriscKona, "--supervisor-rpc")) + }) for _, traceType := range types.TraceTypes { traceType := traceType - if traceType == types.TraceTypeSuperCannon || traceType == types.TraceTypeSuperPermissioned { + if traceType == types.TraceTypeSuperCannon || traceType == types.TraceTypeSuperPermissioned || traceType == types.TraceTypeSuperAsteriscKona { continue } @@ -126,6 +129,12 @@ func TestOpSupervisor(t *testing.T) { cfg := configForArgs(t, addRequiredArgsExcept(types.TraceTypeSuperPermissioned, "--supervisor-rpc", "--supervisor-rpc", url)) require.Equal(t, url, cfg.SupervisorRPC) }) + + t.Run("Valid-SuperAsteriscKona", func(t *testing.T) { + url := "http://localhost/supervisor" + cfg := configForArgs(t, addRequiredArgsExcept(types.TraceTypeSuperAsteriscKona, "--supervisor-rpc", "--supervisor-rpc", url)) + require.Equal(t, url, cfg.SupervisorRPC) + }) } func TestTraceType(t *testing.T) { @@ -554,7 +563,7 @@ func TestAsteriscBaseRequiredArgs(t *testing.T) { t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndRollup-%v", traceType), func(t *testing.T) { verifyArgsInvalid( t, - "flag network can not be used with rollup-config and l2-genesis", + "flag network can not be used with rollup-config, l2-genesis or asterisc-kona-l2-custom", addRequiredArgs(traceType, "--rollup-config=rollup.json")) }) @@ -810,6 +819,112 @@ func TestSuperCannonCustomConfigArgs(t *testing.T) { } } +func TestSuperAsteriscKonaCustomConfigArgs(t *testing.T) { + for _, traceType := range []types.TraceType{types.TraceTypeSuperAsteriscKona} { + traceType := traceType + + t.Run(fmt.Sprintf("TestRequireEitherAsteriscKonaNetworkOrRollupAndGenesisAndDepset-%v", traceType), func(t *testing.T) { + expectedErrorMessage := "flag network or rollup-config/asterisc-kona-rollup-config, l2-genesis/asterisc-kona-l2-genesis and depset-config/asterisc-kona-depset-config is required" + // Missing all + verifyArgsInvalid( + t, + expectedErrorMessage, + addRequiredArgsExcept(traceType, "--network")) + // Missing l2-genesis + verifyArgsInvalid( + t, + expectedErrorMessage, + addRequiredArgsExcept(traceType, "--network", "--asterisc-kona-rollup-config=rollup.json", "--asterisc-kona-depset-config=depset.json")) + // Missing rollup-config + verifyArgsInvalid( + t, + expectedErrorMessage, + addRequiredArgsExcept(traceType, "--network", "--asterisc-kona-l2-genesis=gensis.json", "--asterisc-kona-depset-config=depset.json")) + // Missing depset-config + verifyArgsInvalid( + t, + expectedErrorMessage, + addRequiredArgsExcept(traceType, "--network", "--asterisc-kona-rollup-config=rollup.json", "--asterisc-kona-l2-genesis=gensis.json")) + }) + + t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndRollup-%v", traceType), func(t *testing.T) { + verifyArgsInvalid( + t, + "flag network can not be used with asterisc-kona-rollup-config, l2-genesis or asterisc-kona-l2-custom", + addRequiredArgs(traceType, "--asterisc-kona-rollup-config=rollup.json")) + }) + + t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndRollup-%v", traceType), func(t *testing.T) { + args := requiredArgs(traceType) + delete(args, "--network") + delete(args, "--game-factory-address") + args["--network"] = network + args["--asterisc-kona-rollup-config"] = "rollup.json" + args["--asterisc-kona-l2-genesis"] = "gensis.json" + args["--asterisc-kona-l2-custom"] = "true" + verifyArgsInvalid( + t, + "flag network can not be used with asterisc-kona-rollup-config, asterisc-kona-l2-genesis or asterisc-kona-l2-custom", + toArgList(args)) + }) + + t.Run(fmt.Sprintf("TestNetwork-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredWhenRollupGenesisAndDepsetIsSpecified", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(traceType, "--network", + "--asterisc-kona-rollup-config=rollup.json", "--asterisc-kona-l2-genesis=genesis.json", "--asterisc-kona-depset-config=depset.json")) + }) + + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--network", "--network", testNetwork)) + require.Equal(t, []string{testNetwork}, cfg.AsteriscKona.Networks) + }) + }) + + t.Run(fmt.Sprintf("TestSetAsteriscL2ChainId-%v", traceType), func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--network", + "--asterisc-kona-rollup-config=rollup.json", + "--asterisc-kona-l2-genesis=genesis.json", + "--asterisc-kona-depset-config=depset.json", + "--asterisc-kona-l2-custom")) + require.True(t, cfg.AsteriscKona.L2Custom) + }) + + t.Run(fmt.Sprintf("TestAsteriscRollupConfig-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-kona-rollup-config")) + }) + + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--network", + "--asterisc-kona-rollup-config=rollup.json", "--asterisc-kona-l2-genesis=genesis.json", "--asterisc-kona-depset-config=depset.json")) + require.Equal(t, []string{"rollup.json"}, cfg.AsteriscKona.RollupConfigPaths) + }) + }) + + t.Run(fmt.Sprintf("TestAsteriscL2Genesis-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-kona-l2-genesis")) + }) + + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--network", "--asterisc-kona-rollup-config=rollup.json", "--asterisc-kona-l2-genesis=genesis.json", "--asterisc-kona-depset-config=depset.json")) + require.Equal(t, []string{"genesis.json"}, cfg.AsteriscKona.L2GenesisPaths) + }) + }) + + t.Run(fmt.Sprintf("TestAsteriscDepsetConfig-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-kona-depset-config")) + }) + + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--network", "--asterisc-kona-rollup-config=rollup.json", "--asterisc-kona-l2-genesis=genesis.json", "--asterisc-kona-depset-config=depset.json")) + require.Equal(t, "depset.json", cfg.AsteriscKona.DepsetConfigPath) + }) + }) + } +} + func TestCannonRequiredArgs(t *testing.T) { for _, traceType := range []types.TraceType{types.TraceTypeCannon, types.TraceTypePermissioned, types.TraceTypeSuperCannon, types.TraceTypeSuperPermissioned} { traceType := traceType @@ -957,6 +1072,12 @@ func TestDepsetConfig(t *testing.T) { "flag network or rollup-config/cannon-rollup-config, l2-genesis/cannon-l2-genesis and depset-config/cannon-depset-config is required", addRequiredArgsExcept(traceType, "--network", "--rollup-config=rollup.json", "--l2-genesis=genesis.json")) }) + } else if traceType == types.TraceTypeSuperAsteriscKona { + t.Run("Required-"+traceType.String(), func(t *testing.T) { + verifyArgsInvalid(t, + "flag network or rollup-config/asterisc-kona-rollup-config, l2-genesis/asterisc-kona-l2-genesis and depset-config/asterisc-kona-depset-config is required", + addRequiredArgsExcept(traceType, "--network", "--rollup-config=rollup.json", "--l2-genesis=genesis.json")) + }) } else { t.Run("NotRequired-"+traceType.String(), func(t *testing.T) { cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--network", "--rollup-config=rollup.json", "--l2-genesis=genesis.json")) @@ -985,7 +1106,7 @@ func TestRollupRpc(t *testing.T) { for _, traceType := range types.TraceTypes { traceType := traceType - if traceType == types.TraceTypeSuperCannon || traceType == types.TraceTypeSuperPermissioned { + if traceType == types.TraceTypeSuperCannon || traceType == types.TraceTypeSuperPermissioned || traceType == types.TraceTypeSuperAsteriscKona { t.Run(fmt.Sprintf("NotRequiredFor-%v", traceType), func(t *testing.T) { configForArgs(t, addRequiredArgsExcept(traceType, "--rollup-rpc")) }) @@ -1172,6 +1293,8 @@ func requiredArgs(traceType types.TraceType) map[string]string { addRequiredAsteriscKonaArgs(args) case types.TraceTypeSuperCannon, types.TraceTypeSuperPermissioned: addRequiredSuperCannonArgs(args) + case types.TraceTypeSuperAsteriscKona: + addRequiredSuperAsteriscKonaArgs(args) case types.TraceTypeAlphabet, types.TraceTypeFast: addRequiredOutputRootArgs(args) } @@ -1215,6 +1338,11 @@ func addRequiredAsteriscKonaArgs(args map[string]string) { args["--asterisc-kona-prestate"] = asteriscPreState } +func addRequiredSuperAsteriscKonaArgs(args map[string]string) { + addRequiredAsteriscKonaArgs(args) + args["--supervisor-rpc"] = supervisorRpc +} + func toArgList(req map[string]string) []string { var combined []string for name, value := range req { diff --git a/op-challenger/config/config.go b/op-challenger/config/config.go index 23988265205ed..eb55ca2c978b1 100644 --- a/op-challenger/config/config.go +++ b/op-challenger/config/config.go @@ -287,17 +287,20 @@ func (c Config) Check() error { if c.RollupRpc == "" { return ErrMissingRollupRpc } - if err := c.AsteriscKona.Check(); err != nil { - return fmt.Errorf("asterisc kona: %w", err) + if err := c.validateBaseAsteriscKonaOptions(); err != nil { + return err } - if c.AsteriscKonaAbsolutePreState == "" && c.AsteriscKonaAbsolutePreStateBaseURL == nil { - return ErrMissingAsteriscKonaAbsolutePreState + } + if c.TraceTypeEnabled(types.TraceTypeSuperAsteriscKona) { + if c.SupervisorRPC == "" { + return ErrMissingSupervisorRpc } - if c.AsteriscKona.SnapshotFreq == 0 { - return ErrMissingAsteriscKonaSnapshotFreq + + if len(c.AsteriscKona.Networks) == 0 && c.AsteriscKona.DepsetConfigPath == "" { + return ErrMissingDepsetConfig } - if c.AsteriscKona.InfoFreq == 0 { - return ErrMissingAsteriscKonaInfoFreq + if err := c.validateBaseAsteriscKonaOptions(); err != nil { + return err } } if c.TraceTypeEnabled(types.TraceTypeAlphabet) || c.TraceTypeEnabled(types.TraceTypeFast) { @@ -332,3 +335,19 @@ func (c Config) validateBaseCannonOptions() error { } return nil } + +func (c Config) validateBaseAsteriscKonaOptions() error { + if err := c.AsteriscKona.Check(); err != nil { + return fmt.Errorf("asterisc kona: %w", err) + } + if c.AsteriscKonaAbsolutePreState == "" && c.AsteriscKonaAbsolutePreStateBaseURL == nil { + return ErrMissingAsteriscKonaAbsolutePreState + } + if c.AsteriscKona.SnapshotFreq == 0 { + return ErrMissingAsteriscKonaSnapshotFreq + } + if c.AsteriscKona.InfoFreq == 0 { + return ErrMissingAsteriscKonaInfoFreq + } + return nil +} diff --git a/op-challenger/config/config_test.go b/op-challenger/config/config_test.go index 7fea06a129f52..7602063b2d6bd 100644 --- a/op-challenger/config/config_test.go +++ b/op-challenger/config/config_test.go @@ -49,6 +49,7 @@ var superCannonTraceTypes = []types.TraceType{types.TraceTypeSuperCannon, types. var allCannonTraceTypes []types.TraceType var asteriscTraceTypes = []types.TraceType{types.TraceTypeAsterisc} var asteriscKonaTraceTypes = []types.TraceType{types.TraceTypeAsteriscKona} +var superAsteriscKonaTraceTypes = []types.TraceType{types.TraceTypeSuperAsteriscKona} func init() { allCannonTraceTypes = append(allCannonTraceTypes, singleCannonTraceTypes...) @@ -118,6 +119,11 @@ func applyValidConfigForAsteriscKona(t *testing.T, cfg *Config) { cfg.AsteriscKona.Networks = []string{validAsteriscKonaNetwork} } +func applyValidConfigForSuperAsteriscKona(t *testing.T, cfg *Config) { + cfg.SupervisorRPC = validSupervisorRpc + applyValidConfigForAsteriscKona(t, cfg) +} + func validConfig(t *testing.T, traceType types.TraceType) Config { cfg := NewConfig(validGameFactoryAddress, validL1EthRpc, validL1BeaconUrl, validRollupRpc, validL2Rpc, validDatadir, traceType) if traceType == types.TraceTypeSuperCannon || traceType == types.TraceTypeSuperPermissioned { @@ -132,6 +138,9 @@ func validConfig(t *testing.T, traceType types.TraceType) Config { if traceType == types.TraceTypeAsteriscKona { applyValidConfigForAsteriscKona(t, &cfg) } + if traceType == types.TraceTypeSuperAsteriscKona { + applyValidConfigForSuperAsteriscKona(t, &cfg) + } return cfg } @@ -327,6 +336,18 @@ func TestDepsetConfig(t *testing.T) { }) } + for _, traceType := range superAsteriscKonaTraceTypes { + traceType := traceType + t.Run(fmt.Sprintf("TestAsteriscNetworkOrDepsetConfigRequired-%v", traceType), func(t *testing.T) { + cfg := validConfig(t, traceType) + cfg.AsteriscKona.Networks = nil + cfg.AsteriscKona.RollupConfigPaths = []string{"foo.json"} + cfg.AsteriscKona.L2GenesisPaths = []string{"genesis.json"} + cfg.AsteriscKona.DepsetConfigPath = "" + require.ErrorIs(t, cfg.Check(), ErrMissingDepsetConfig) + }) + } + for _, traceType := range singleCannonTraceTypes { traceType := traceType t.Run(fmt.Sprintf("TestDepsetConfigNotRequired-%v", traceType), func(t *testing.T) { @@ -338,6 +359,18 @@ func TestDepsetConfig(t *testing.T) { require.NoError(t, cfg.Check()) }) } + + for _, traceType := range asteriscKonaTraceTypes { + traceType := traceType + t.Run(fmt.Sprintf("TestDepsetConfigNotRequired-%v", traceType), func(t *testing.T) { + cfg := validConfig(t, traceType) + cfg.AsteriscKona.Networks = nil + cfg.AsteriscKona.RollupConfigPaths = []string{"foo.json"} + cfg.AsteriscKona.L2GenesisPaths = []string{"genesis.json"} + cfg.AsteriscKona.DepsetConfigPath = "" + require.NoError(t, cfg.Check()) + }) + } } func TestAsteriscRequiredArgs(t *testing.T) { @@ -601,7 +634,7 @@ func TestHttpPollInterval(t *testing.T) { func TestRollupRpcRequired(t *testing.T) { for _, traceType := range types.TraceTypes { traceType := traceType - if traceType == types.TraceTypeSuperCannon || traceType == types.TraceTypeSuperPermissioned { + if traceType == types.TraceTypeSuperCannon || traceType == types.TraceTypeSuperPermissioned || traceType == types.TraceTypeSuperAsteriscKona { continue } t.Run(traceType.String(), func(t *testing.T) { @@ -624,12 +657,18 @@ func TestRollupRpcNotRequiredForInterop(t *testing.T) { config.RollupRpc = "" require.NoError(t, config.Check()) }) + + t.Run("SuperAsteriscKona", func(t *testing.T) { + config := validConfig(t, types.TraceTypeSuperAsteriscKona) + config.RollupRpc = "" + require.NoError(t, config.Check()) + }) } func TestSupervisorRpc(t *testing.T) { for _, traceType := range types.TraceTypes { traceType := traceType - if traceType == types.TraceTypeSuperCannon || traceType == types.TraceTypeSuperPermissioned { + if traceType == types.TraceTypeSuperCannon || traceType == types.TraceTypeSuperPermissioned || traceType == types.TraceTypeSuperAsteriscKona { t.Run("RequiredFor"+traceType.String(), func(t *testing.T) { config := validConfig(t, traceType) config.SupervisorRPC = "" diff --git a/op-challenger/flags/flags.go b/op-challenger/flags/flags.go index 1ce1da1c73aa2..235589c23327e 100644 --- a/op-challenger/flags/flags.go +++ b/op-challenger/flags/flags.go @@ -32,7 +32,7 @@ func prefixEnvVars(name string) []string { } var ( - faultDisputeVMs = []types.TraceType{types.TraceTypeCannon, types.TraceTypeAsterisc, types.TraceTypeAsteriscKona, types.TraceTypeSuperCannon} + faultDisputeVMs = []types.TraceType{types.TraceTypeCannon, types.TraceTypeAsterisc, types.TraceTypeAsteriscKona, types.TraceTypeSuperCannon, types.TraceTypeSuperAsteriscKona} // Required Flags L1EthRpcFlag = &cli.StringFlag{ Name: "l1-eth-rpc", @@ -195,6 +195,14 @@ var ( Usage: "Path to kona executable to use as pre-image oracle server when generating trace data (asterisc-kona trace type only)", EnvVars: prefixEnvVars("ASTERISC_KONA_SERVER"), } + AsteriscKonaL2CustomFlag = &cli.BoolFlag{ + Name: "asterisc-kona-l2-custom", + Usage: "Notify the kona-host that the L2 chain uses custom config to be loaded via the preimage oracle. " + + "WARNING: This is incompatible with on-chain testing and must only be used for testing purposes.", + EnvVars: prefixEnvVars("ASTERISC_KONA_L2_CUSTOM"), + Value: false, + Hidden: true, + } AsteriscPreStateFlag = &cli.StringFlag{ Name: "asterisc-prestate", Usage: "Path to absolute prestate to use when generating trace data (asterisc trace type only)", @@ -266,6 +274,7 @@ var optionalFlags = []cli.Flag{ CannonInfoFreqFlag, AsteriscBinFlag, AsteriscServerFlag, + AsteriscKonaL2CustomFlag, AsteriscKonaServerFlag, AsteriscPreStateFlag, AsteriscKonaPreStateFlag, @@ -355,18 +364,15 @@ func CheckCannonFlags(ctx *cli.Context) error { } func CheckAsteriscBaseFlags(ctx *cli.Context, traceType types.TraceType) error { - if err := checkOutputProviderFlags(ctx); err != nil { - return err - } if !ctx.IsSet(flags.NetworkFlagName) && !(RollupConfigFlag.IsSet(ctx, traceType) && L2GenesisFlag.IsSet(ctx, traceType)) { return fmt.Errorf("flag %v or %v and %v is required", flags.NetworkFlagName, RollupConfigFlag.EitherFlagName(traceType), L2GenesisFlag.EitherFlagName(traceType)) } if ctx.IsSet(flags.NetworkFlagName) && - (RollupConfigFlag.IsSet(ctx, traceType) || L2GenesisFlag.IsSet(ctx, traceType)) { - return fmt.Errorf("flag %v can not be used with %v and %v", - flags.NetworkFlagName, RollupConfigFlag.SourceFlagName(ctx, traceType), L2GenesisFlag.SourceFlagName(ctx, traceType)) + (RollupConfigFlag.IsSet(ctx, types.TraceTypeAsteriscKona) || L2GenesisFlag.IsSet(ctx, types.TraceTypeAsteriscKona) || ctx.Bool(AsteriscKonaL2CustomFlag.Name)) { + return fmt.Errorf("flag %v can not be used with %v, %v or %v", + flags.NetworkFlagName, RollupConfigFlag.SourceFlagName(ctx, types.TraceTypeAsteriscKona), L2GenesisFlag.SourceFlagName(ctx, types.TraceTypeAsteriscKona), AsteriscKonaL2CustomFlag.Name) } if !ctx.IsSet(AsteriscBinFlag.Name) { return fmt.Errorf("flag %s is required", AsteriscBinFlag.Name) @@ -375,6 +381,9 @@ func CheckAsteriscBaseFlags(ctx *cli.Context, traceType types.TraceType) error { } func CheckAsteriscFlags(ctx *cli.Context) error { + if err := checkOutputProviderFlags(ctx); err != nil { + return err + } if err := CheckAsteriscBaseFlags(ctx, types.TraceTypeAsterisc); err != nil { return err } @@ -388,6 +397,33 @@ func CheckAsteriscFlags(ctx *cli.Context) error { } func CheckAsteriscKonaFlags(ctx *cli.Context) error { + if err := checkOutputProviderFlags(ctx); err != nil { + return err + } + if err := CheckAsteriscBaseFlags(ctx, types.TraceTypeAsteriscKona); err != nil { + return err + } + if !ctx.IsSet(AsteriscKonaServerFlag.Name) { + return fmt.Errorf("flag %s is required", AsteriscKonaServerFlag.Name) + } + if !PreStatesURLFlag.IsSet(ctx, types.TraceTypeAsteriscKona) && !ctx.IsSet(AsteriscKonaPreStateFlag.Name) { + return fmt.Errorf("flag %s or %s is required", PreStatesURLFlag.EitherFlagName(types.TraceTypeAsteriscKona), AsteriscKonaPreStateFlag.Name) + } + return nil +} + +func CheckSuperAsteriscKonaFlags(ctx *cli.Context) error { + if !ctx.IsSet(SupervisorRpcFlag.Name) { + return fmt.Errorf("flag %v is required", SupervisorRpcFlag.Name) + } + if !ctx.IsSet(flags.NetworkFlagName) && + !(RollupConfigFlag.IsSet(ctx, types.TraceTypeAsteriscKona) && L2GenesisFlag.IsSet(ctx, types.TraceTypeAsteriscKona) && DepsetConfigFlag.IsSet(ctx, types.TraceTypeAsteriscKona)) { + return fmt.Errorf("flag %v or %v, %v and %v is required", + flags.NetworkFlagName, + RollupConfigFlag.EitherFlagName(types.TraceTypeAsteriscKona), + L2GenesisFlag.EitherFlagName(types.TraceTypeAsteriscKona), + DepsetConfigFlag.EitherFlagName(types.TraceTypeAsteriscKona)) + } if err := CheckAsteriscBaseFlags(ctx, types.TraceTypeAsteriscKona); err != nil { return err } @@ -427,6 +463,10 @@ func CheckRequired(ctx *cli.Context, traceTypes []types.TraceType) error { if err := CheckSuperCannonFlags(ctx); err != nil { return err } + case types.TraceTypeSuperAsteriscKona: + if err := CheckSuperAsteriscKonaFlags(ctx); err != nil { + return err + } case types.TraceTypeAlphabet, types.TraceTypeFast: if err := checkOutputProviderFlags(ctx); err != nil { return err @@ -632,6 +672,7 @@ func NewConfigFromCLI(ctx *cli.Context, logger log.Logger) (*config.Config, erro 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), diff --git a/op-challenger/game/fault/contracts/detect.go b/op-challenger/game/fault/contracts/detect.go index 91abca153f230..0e6e0b3641eb3 100644 --- a/op-challenger/game/fault/contracts/detect.go +++ b/op-challenger/game/fault/contracts/detect.go @@ -36,7 +36,8 @@ func DetectGameType(ctx context.Context, addr common.Address, caller *batching.M faultTypes.FastGameType, faultTypes.AsteriscKonaGameType, faultTypes.SuperCannonGameType, - faultTypes.SuperPermissionedGameType: + faultTypes.SuperPermissionedGameType, + faultTypes.SuperAsteriscKonaGameType: return gameType, nil default: return faultTypes.UnknownGameType, fmt.Errorf("unsupported game type: %d", gameType) diff --git a/op-challenger/game/fault/contracts/faultdisputegame.go b/op-challenger/game/fault/contracts/faultdisputegame.go index 547c8c32ff290..6ee07e69a3800 100644 --- a/op-challenger/game/fault/contracts/faultdisputegame.go +++ b/op-challenger/game/fault/contracts/faultdisputegame.go @@ -81,7 +81,7 @@ func NewFaultDisputeGameContract(ctx context.Context, metrics metrics.ContractMe return nil, fmt.Errorf("failed to detect game type: %w", err) } switch gameType { - case types.SuperCannonGameType, types.SuperPermissionedGameType: + case types.SuperCannonGameType, types.SuperPermissionedGameType, types.SuperAsteriscKonaGameType: return NewSuperFaultDisputeGameContract(ctx, metrics, addr, caller) default: return NewPreInteropFaultDisputeGameContract(ctx, metrics, addr, caller) diff --git a/op-challenger/game/fault/contracts/faultdisputegame_test.go b/op-challenger/game/fault/contracts/faultdisputegame_test.go index 151aec86325de..53a6f24afe33a 100644 --- a/op-challenger/game/fault/contracts/faultdisputegame_test.go +++ b/op-challenger/game/fault/contracts/faultdisputegame_test.go @@ -51,8 +51,8 @@ func (c contractVersion) String() string { return fmt.Sprintf("%s_%s", c.version, c.gameType) } -func (c contractVersion) IsSuperCannon() bool { - return c.gameType == faultTypes.SuperCannonGameType || c.gameType == faultTypes.SuperPermissionedGameType +func (c contractVersion) IsSuperGame() bool { + return c.gameType == faultTypes.SuperCannonGameType || c.gameType == faultTypes.SuperPermissionedGameType || c.gameType == faultTypes.SuperAsteriscKonaGameType } const ( @@ -543,7 +543,7 @@ func TestGetBlockRange(t *testing.T) { stubRpc, contract := setupFaultDisputeGameTest(t, version) expectedStart := uint64(65) expectedEnd := uint64(102) - if version.IsSuperCannon() { + if version.IsSuperGame() { stubRpc.SetResponse(fdgAddr, methodStartingSequenceNumber, rpcblock.Latest, nil, []interface{}{new(big.Int).SetUint64(expectedStart)}) stubRpc.SetResponse(fdgAddr, methodL2SequenceNumber, rpcblock.Latest, nil, []interface{}{new(big.Int).SetUint64(expectedEnd)}) } else { @@ -586,14 +586,14 @@ func TestGetGameMetadata(t *testing.T) { expectedL2BlockNumberChallenger := common.Address{0xee} block := rpcblock.ByNumber(889) stubRpc.SetResponse(fdgAddr, methodL1Head, block, nil, []interface{}{expectedL1Head}) - if version.IsSuperCannon() { + if version.IsSuperGame() { stubRpc.SetResponse(fdgAddr, methodL2SequenceNumber, block, nil, []interface{}{new(big.Int).SetUint64(expectedL2BlockNumber)}) } else { stubRpc.SetResponse(fdgAddr, methodL2BlockNumber, block, nil, []interface{}{new(big.Int).SetUint64(expectedL2BlockNumber)}) } stubRpc.SetResponse(fdgAddr, methodRootClaim, block, nil, []interface{}{expectedRootClaim}) stubRpc.SetResponse(fdgAddr, methodStatus, block, nil, []interface{}{expectedStatus}) - supportsL2BlockNumChallenge := (version.version != vers080 && version.version != vers0180) && !version.IsSuperCannon() + supportsL2BlockNumChallenge := (version.version != vers080 && version.version != vers0180) && !version.IsSuperGame() if supportsL2BlockNumChallenge { stubRpc.SetResponse(fdgAddr, methodMaxClockDuration, block, nil, []interface{}{expectedMaxClockDuration}) stubRpc.SetResponse(fdgAddr, methodL2BlockNumberChallenged, block, nil, []interface{}{expectedL2BlockNumberChallenged}) @@ -789,7 +789,7 @@ func TestFaultDisputeGameContractLatest_IsL2BlockNumberChallenged(t *testing.T) for _, version := range versions { version := version var expectations = []bool{true, false} - if version.IsSuperCannon() { + if version.IsSuperGame() { expectations = []bool{false} } for _, expected := range expectations { @@ -797,7 +797,7 @@ func TestFaultDisputeGameContractLatest_IsL2BlockNumberChallenged(t *testing.T) t.Run(fmt.Sprintf("%v-%v", version.String(), expected), func(t *testing.T) { block := rpcblock.ByHash(common.Hash{0x43}) stubRpc, game := setupFaultDisputeGameTest(t, version) - supportsL2BlockNumChallenge := (version.version != vers080 && version.version != vers0180) && !version.IsSuperCannon() + supportsL2BlockNumChallenge := (version.version != vers080 && version.version != vers0180) && !version.IsSuperGame() if supportsL2BlockNumChallenge { stubRpc.SetResponse(fdgAddr, methodL2BlockNumberChallenged, block, nil, []interface{}{expected}) } else if expected { @@ -827,7 +827,7 @@ func TestFaultDisputeGameContractLatest_ChallengeL2BlockNumberTx(t *testing.T) { }, Header: testutils.RandomHeader(rng), } - supportsL2BlockNumChallenge := (version.version != vers080 && version.version != vers0180) && !version.IsSuperCannon() + supportsL2BlockNumChallenge := (version.version != vers080 && version.version != vers0180) && !version.IsSuperGame() if supportsL2BlockNumChallenge { headerRlp, err := rlp.EncodeToBytes(challenge.Header) require.NoError(t, err) diff --git a/op-challenger/game/fault/register.go b/op-challenger/game/fault/register.go index b6878a3ad7ce8..68a4ad38ebd4b 100644 --- a/op-challenger/game/fault/register.go +++ b/op-challenger/game/fault/register.go @@ -102,6 +102,13 @@ func RegisterGameTypes( } registerTasks = append(registerTasks, NewAsteriscKonaRegisterTask(faultTypes.AsteriscKonaGameType, cfg, m, vm.NewKonaExecutor(), l2HeaderSource, rollupClient, syncValidator)) } + if cfg.TraceTypeEnabled(faultTypes.TraceTypeSuperAsteriscKona) { + rootProvider, syncValidator, err := clients.SuperchainClients() + if err != nil { + return nil, err + } + registerTasks = append(registerTasks, NewSuperAsteriscKonaRegisterTask(faultTypes.SuperAsteriscKonaGameType, cfg, m, vm.NewKonaSuperExecutor(), rootProvider, syncValidator)) + } if cfg.TraceTypeEnabled(faultTypes.TraceTypeFast) { l2HeaderSource, rollupClient, syncValidator, err := clients.SingleChainClients() if err != nil { diff --git a/op-challenger/game/fault/register_task.go b/op-challenger/game/fault/register_task.go index 1bc233b8aa90b..e28e57189a9bd 100644 --- a/op-challenger/game/fault/register_task.go +++ b/op-challenger/game/fault/register_task.go @@ -192,6 +192,42 @@ func NewAsteriscKonaRegisterTask(gameType faultTypes.GameType, cfg *config.Confi } } +func NewSuperAsteriscKonaRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, rootProvider super.RootProvider, syncValidator *super.SyncValidator) *RegisterTask { + stateConverter := asterisc.NewStateConverter(cfg.AsteriscKona) + return &RegisterTask{ + gameType: gameType, + syncValidator: syncValidator, + skipPrestateValidation: gameType == faultTypes.SuperPermissionedGameType, + getTopPrestateProvider: func(ctx context.Context, prestateTimestamp uint64) (faultTypes.PrestateProvider, error) { + return super.NewSuperRootPrestateProvider(rootProvider, prestateTimestamp), nil + }, + getBottomPrestateProvider: cachePrestates( + gameType, + stateConverter, + m, + cfg.AsteriscKonaAbsolutePreStateBaseURL, + cfg.AsteriscKonaAbsolutePreState, + filepath.Join(cfg.Datadir, "super-asterisc-kona-prestates"), + func(ctx context.Context, path string) faultTypes.PrestateProvider { + return vm.NewPrestateProvider(path, stateConverter) + }), + newTraceAccessor: func( + logger log.Logger, + m metrics.Metricer, + prestateProvider faultTypes.PrestateProvider, + vmPrestateProvider faultTypes.PrestateProvider, + dir string, + l1Head eth.BlockID, + splitDepth faultTypes.Depth, + prestateBlock uint64, + poststateBlock uint64) (*trace.Accessor, error) { + provider := vmPrestateProvider.(*vm.PrestateProvider) + preimagePrestateProvider := prestateProvider.(super.PreimagePrestateProvider) + return super.NewSuperAsteriscKonaTraceAccessor(logger, m, cfg.AsteriscKona, serverExecutor, preimagePrestateProvider, rootProvider, provider.PrestatePath(), dir, l1Head, splitDepth, prestateBlock, poststateBlock) + }, + } +} + func NewAlphabetRegisterTask(gameType faultTypes.GameType, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator SyncValidator) *RegisterTask { return &RegisterTask{ gameType: gameType, diff --git a/op-challenger/game/fault/register_task_test.go b/op-challenger/game/fault/register_task_test.go index 9bbefed1d20bb..debfc50ac1e91 100644 --- a/op-challenger/game/fault/register_task_test.go +++ b/op-challenger/game/fault/register_task_test.go @@ -40,7 +40,7 @@ func TestRegisterOracle_MissingGameImpl(t *testing.T) { } func TestRegisterOracle_AddsOracle(t *testing.T) { - for _, gameType := range []faultTypes.GameType{faultTypes.CannonGameType, faultTypes.SuperCannonGameType} { + for _, gameType := range []faultTypes.GameType{faultTypes.CannonGameType, faultTypes.SuperCannonGameType, faultTypes.SuperAsteriscKonaGameType} { t.Run(fmt.Sprintf("%v", gameType), func(t *testing.T) { gameFactoryAddr := common.Address{0xaa} gameImplAddr := common.Address{0xbb} @@ -49,7 +49,7 @@ func TestRegisterOracle_AddsOracle(t *testing.T) { rpc := test.NewAbiBasedRpc(t, gameFactoryAddr, snapshots.LoadDisputeGameFactoryABI()) if gameType == faultTypes.CannonGameType { rpc.AddContract(gameImplAddr, snapshots.LoadFaultDisputeGameABI()) - } else if gameType == faultTypes.SuperCannonGameType { + } else if gameType == faultTypes.SuperCannonGameType || gameType == faultTypes.SuperAsteriscKonaGameType { rpc.AddContract(gameImplAddr, snapshots.LoadSuperFaultDisputeGameABI()) } else { t.Fatalf("game type %v not supported", gameType) diff --git a/op-challenger/game/fault/trace/super/super_asterisc_kona.go b/op-challenger/game/fault/trace/super/super_asterisc_kona.go new file mode 100644 index 0000000000000..259f4c4ff66ae --- /dev/null +++ b/op-challenger/game/fault/trace/super/super_asterisc_kona.go @@ -0,0 +1,57 @@ +package super + +import ( + "context" + "fmt" + "math/big" + "path/filepath" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/asterisc" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/split" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum-optimism/optimism/op-challenger/metrics" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" +) + +func NewSuperAsteriscKonaTraceAccessor( + logger log.Logger, + m metrics.Metricer, + cfg vm.Config, + serverExecutor vm.OracleServerExecutor, + prestateProvider PreimagePrestateProvider, + rootProvider RootProvider, + asteriscPrestate string, + dir string, + l1Head eth.BlockID, + splitDepth types.Depth, + prestateTimestamp uint64, + poststateTimestamp uint64, +) (*trace.Accessor, error) { + rollupCfgs, err := NewRollupConfigs(cfg) + if err != nil { + return nil, fmt.Errorf("failed to load rollup configs: %w", err) + } + outputProvider := NewSuperTraceProvider(logger, rollupCfgs, prestateProvider, rootProvider, l1Head, splitDepth, prestateTimestamp, poststateTimestamp) + asteriscCreator := func(ctx context.Context, localContext common.Hash, depth types.Depth, claimInfo ClaimInfo) (types.TraceProvider, error) { + logger := logger.New("agreedPrestate", hexutil.Bytes(claimInfo.AgreedPrestate), "claim", claimInfo.Claim, "localContext", localContext) + subdir := filepath.Join(dir, localContext.Hex()) + localInputs := utils.LocalGameInputs{ + L1Head: l1Head.Hash, + AgreedPreState: claimInfo.AgreedPrestate, + L2Claim: claimInfo.Claim, + L2SequenceNumber: new(big.Int).SetUint64(poststateTimestamp), + } + provider := asterisc.NewTraceProvider(logger, m.ToTypedVmMetrics(cfg.VmType.String()), cfg, serverExecutor, prestateProvider, asteriscPrestate, localInputs, subdir, depth) + return provider, nil + } + + cache := NewProviderCache(m, "super_asterisc_kona_provider", asteriscCreator) + selector := split.NewSplitProviderSelector(outputProvider, splitDepth, SuperRootSplitAdapter(outputProvider, cache.GetOrCreate)) + return trace.NewAccessor(selector), nil +} diff --git a/op-challenger/game/fault/types/types.go b/op-challenger/game/fault/types/types.go index e530a7283ab3e..e57184a9d368a 100644 --- a/op-challenger/game/fault/types/types.go +++ b/op-challenger/game/fault/types/types.go @@ -9,6 +9,8 @@ import ( "math/big" "time" + "slices" + preimage "github.com/ethereum-optimism/optimism/op-preimage" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/common" @@ -32,6 +34,7 @@ const ( SuperCannonGameType GameType = 4 SuperPermissionedGameType GameType = 5 OPSuccinctGameType GameType = 6 + SuperAsteriscKonaGameType GameType = 7 FastGameType GameType = 254 AlphabetGameType GameType = 255 KailuaGameType GameType = 1337 @@ -58,6 +61,8 @@ func (t GameType) String() string { return "super-permissioned" case OPSuccinctGameType: return "op-succinct" + case SuperAsteriscKonaGameType: + return "super-asterisc-kona" case FastGameType: return "fast" case AlphabetGameType: @@ -80,9 +85,10 @@ const ( TraceTypePermissioned TraceType = "permissioned" TraceTypeSuperCannon TraceType = "super-cannon" TraceTypeSuperPermissioned TraceType = "super-permissioned" + TraceTypeSuperAsteriscKona TraceType = "super-asterisc-kona" ) -var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon, TraceTypePermissioned, TraceTypeAsterisc, TraceTypeAsteriscKona, TraceTypeFast, TraceTypeSuperCannon, TraceTypeSuperPermissioned} +var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon, TraceTypePermissioned, TraceTypeAsterisc, TraceTypeAsteriscKona, TraceTypeFast, TraceTypeSuperCannon, TraceTypeSuperPermissioned, TraceTypeSuperAsteriscKona} func (t TraceType) String() string { return string(t) @@ -103,12 +109,7 @@ func (t *TraceType) Clone() any { } func ValidTraceType(value TraceType) bool { - for _, t := range TraceTypes { - if t == value { - return true - } - } - return false + return slices.Contains(TraceTypes, value) } func (t TraceType) GameType() GameType { @@ -129,6 +130,8 @@ func (t TraceType) GameType() GameType { return SuperCannonGameType case TraceTypeSuperPermissioned: return SuperPermissionedGameType + case TraceTypeSuperAsteriscKona: + return SuperAsteriscKonaGameType default: return UnknownGameType } diff --git a/op-challenger/runner/factory.go b/op-challenger/runner/factory.go index aeae94b43400e..8c059867cdb1e 100644 --- a/op-challenger/runner/factory.go +++ b/op-challenger/runner/factory.go @@ -49,7 +49,16 @@ func createTraceProvider( return asterisc.NewTraceProvider(logger, m, cfg.Asterisc, serverExecutor, prestateProvider, prestate, localInputs, dir, 42), nil case types.TraceTypeAsteriscKona: serverExecutor := vm.NewKonaExecutor() - stateConverter := asterisc.NewStateConverter(cfg.Asterisc) + stateConverter := asterisc.NewStateConverter(cfg.AsteriscKona) + prestate, err := prestateSource.getPrestate(ctx, logger, cfg.AsteriscKonaAbsolutePreStateBaseURL, cfg.AsteriscKonaAbsolutePreState, dir, stateConverter) + if err != nil { + return nil, err + } + prestateProvider := vm.NewPrestateProvider(prestate, stateConverter) + return asterisc.NewTraceProvider(logger, m, cfg.AsteriscKona, serverExecutor, prestateProvider, prestate, localInputs, dir, 42), nil + case types.TraceTypeSuperAsteriscKona: + serverExecutor := vm.NewKonaSuperExecutor() + stateConverter := asterisc.NewStateConverter(cfg.AsteriscKona) prestate, err := prestateSource.getPrestate(ctx, logger, cfg.AsteriscKonaAbsolutePreStateBaseURL, cfg.AsteriscKonaAbsolutePreState, dir, stateConverter) if err != nil { return nil, err diff --git a/op-challenger/runner/game_inputs.go b/op-challenger/runner/game_inputs.go index 6540a4569c378..65d102b277c3b 100644 --- a/op-challenger/runner/game_inputs.go +++ b/op-challenger/runner/game_inputs.go @@ -17,7 +17,7 @@ import ( func createGameInputs(ctx context.Context, log log.Logger, rollupClient *sources.RollupClient, supervisorClient *sources.SupervisorClient, typeName string, traceType types.TraceType) (utils.LocalGameInputs, error) { switch traceType { - case types.TraceTypeSuperCannon, types.TraceTypeSuperPermissioned: + case types.TraceTypeSuperCannon, types.TraceTypeSuperPermissioned, types.TraceTypeSuperAsteriscKona: if supervisorClient == nil { return utils.LocalGameInputs{}, fmt.Errorf("trace type %s requires supervisor rpc to be set", traceType) } diff --git a/op-dispute-mon/mon/extract/caller.go b/op-dispute-mon/mon/extract/caller.go index cdd2d887d42ef..eff20e7effbdf 100644 --- a/op-dispute-mon/mon/extract/caller.go +++ b/op-dispute-mon/mon/extract/caller.go @@ -58,7 +58,8 @@ func (g *GameCallerCreator) CreateContract(ctx context.Context, game gameTypes.G faultTypes.FastGameType, faultTypes.AsteriscKonaGameType, faultTypes.SuperCannonGameType, - faultTypes.SuperPermissionedGameType: + faultTypes.SuperPermissionedGameType, + faultTypes.SuperAsteriscKonaGameType: fdg, err := contracts.NewFaultDisputeGameContract(ctx, g.m, game.Proxy, g.caller) if err != nil { return nil, fmt.Errorf("failed to create fault dispute game contract: %w", err) diff --git a/op-dispute-mon/mon/extract/caller_test.go b/op-dispute-mon/mon/extract/caller_test.go index c69f2d51c2309..bbca26d665341 100644 --- a/op-dispute-mon/mon/extract/caller_test.go +++ b/op-dispute-mon/mon/extract/caller_test.go @@ -59,6 +59,10 @@ func TestMetadataCreator_CreateContract(t *testing.T) { name: "validSuperPermissionedGameType", game: types.GameMetadata{GameType: uint32(faultTypes.SuperPermissionedGameType), Proxy: fdgAddr}, }, + { + name: "validSuperAsteriscKonaGameType", + game: types.GameMetadata{GameType: uint32(faultTypes.SuperAsteriscKonaGameType), Proxy: fdgAddr}, + }, { name: "InvalidGameType", game: types.GameMetadata{GameType: 6, Proxy: fdgAddr}, @@ -89,7 +93,7 @@ func TestMetadataCreator_CreateContract(t *testing.T) { func setupMetadataLoaderTest(t *testing.T, gameType uint32) (*batching.MultiCaller, *mockCacheMetrics) { fdgAbi := snapshots.LoadFaultDisputeGameABI() - if gameType == uint32(faultTypes.SuperPermissionedGameType) || gameType == uint32(faultTypes.SuperCannonGameType) { + if gameType == uint32(faultTypes.SuperPermissionedGameType) || gameType == uint32(faultTypes.SuperCannonGameType) || gameType == uint32(faultTypes.SuperAsteriscKonaGameType) { fdgAbi = snapshots.LoadSuperFaultDisputeGameABI() } stubRpc := batchingTest.NewAbiBasedRpc(t, fdgAddr, fdgAbi)