Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a5287b8
feat(op-challenger): add TEE Dispute Game support for XLayer
googgoog Mar 18, 2026
760882c
test(op-challenger): add unit tests for TEE Dispute Game support
googgoog Mar 18, 2026
1c8705a
feat(op-challenger): update TEE prover client to v1 API with retry lo…
googgoog Mar 18, 2026
19072f1
proposer support tee game type
JimmyShi22 Mar 19, 2026
e76259f
rm md
JimmyShi22 Mar 19, 2026
4c229cb
Merge branch 'tz/develop-challenger' into tz/dev
googgoog Mar 19, 2026
5e9fe83
fix(op-challenger): register TEE flags in init() instead of separate …
googgoog Mar 19, 2026
6bb00c8
Merge branch 'tz/develop-challenger' into tz/dev
googgoog Mar 19, 2026
0f3f3ab
fix(op-challenger): register TeeGameType directly in SupportedGameTypes
googgoog Mar 19, 2026
8ab2fa4
Merge branch 'tz/develop-challenger' into tz/dev
googgoog Mar 19, 2026
dcbf4b1
feat: add TeeDisputeGame, TeeProofVerifier, and DisputeGameFactoryRouter
doutv Mar 19, 2026
09d8599
Merge commit '8ab2fa42abb0b47186906a7de5618830fba850f7' into tz/dev
JimmyShi22 Mar 20, 2026
0eaf96a
Merge commit '4b5debf43271a4f6bec2030efd5a80302bf4939e' into tz/dev
JimmyShi22 Mar 20, 2026
5646b4e
add deploy tee game sol
JimmyShi22 Mar 20, 2026
d88abb3
support find last game index
JimmyShi22 Mar 20, 2026
c7adf53
fix(op-challenger): reject anchor-based games in GetProveParams inste…
googgoog Mar 20, 2026
8b46b80
fix jump retired game
JimmyShi22 Mar 23, 2026
d6ab202
update list game script
JimmyShi22 Mar 24, 2026
3dbb654
fix(op-challenger): address review findings for TEE game actor
googgoog Mar 24, 2026
a8b2817
fix according with review
JimmyShi22 Mar 24, 2026
4889f7e
update comments
JimmyShi22 Mar 24, 2026
f14f283
batch call
JimmyShi22 Mar 24, 2026
962875e
fix, support ignoring unrecognized game type
JimmyShi22 Mar 24, 2026
43b7b36
feat(op-challenger): filter games by enabled type on shared factory
googgoog Mar 24, 2026
f8ad6af
optimize code
JimmyShi22 Mar 25, 2026
21ed992
rm mockteerpc
JimmyShi22 Mar 25, 2026
4872a66
Merge branch 'tz/dev' of github.com:okx/optimism into tz/dev
JimmyShi22 Mar 25, 2026
db54779
fix(op-challenger): remove /v1 prefix from TEE prover task API path
googgoog Mar 25, 2026
cec4699
refactor(op-challenger): remove unused DeleteTask from TEE prover client
googgoog Mar 25, 2026
efc8ba2
refactor(op-challenger): deduplicate factoryContract param in ActorCr…
googgoog Mar 25, 2026
14f23b9
fix tee dispute game
JimmyShi22 Mar 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions op-challenger/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ type Config struct {
CannonKonaAbsolutePreState string // File to load the absolute pre-state for CannonKona traces from
CannonKonaAbsolutePreStateBaseURL *url.URL // Base URL to retrieve absolute pre-states for CannonKona traces from

// For XLayer: TEE Dispute Game config
TeeProverRpc string // TEE Prover HTTP service URL
TeeProvePollInterval time.Duration // Polling interval for TEE Prover task status
TeeProveTimeout time.Duration // Total timeout for a single game's prove attempt (including retries)

MaxPendingTx uint64 // Maximum number of pending transactions (0 == no limit)

TxMgrConfig txmgr.CLIConfig
Expand Down Expand Up @@ -225,10 +230,10 @@ func (c Config) Check() error {
if c.L1RPCKind == "" {
return ErrMissingL1RPCKind
}
if c.L1Beacon == "" {
if c.L1Beacon == "" && !c.onlyTeeGameType() { // For XLayer: TEE game type does not require L1 beacon
return ErrMissingL1Beacon
}
if len(c.L2Rpcs) == 0 {
if len(c.L2Rpcs) == 0 && !c.onlyTeeGameType() { // For XLayer: TEE game type does not require L2 RPC
return ErrMissingL2Rpc
}
if c.GameFactoryAddress == (common.Address{}) {
Expand Down Expand Up @@ -293,6 +298,9 @@ func (c Config) Check() error {
return ErrMissingRollupRpc
}
}
if err := c.CheckXLayer(); err != nil { // For XLayer
return err
}
if err := c.TxMgrConfig.Check(); err != nil {
return err
}
Expand Down
6 changes: 6 additions & 0 deletions op-challenger/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ func validConfig(t *testing.T, gameType gameTypes.GameType) Config {
if gameType == gameTypes.OptimisticZKGameType {
applyValidConfigForOptimisticZK(&cfg)
}
if gameType == gameTypes.TeeGameType { // For XLayer
applyValidConfigForTee(&cfg)
}
return cfg
}

Expand Down Expand Up @@ -508,6 +511,9 @@ func TestRollupRpcRequired(t *testing.T) {
if gameType == gameTypes.SuperCannonGameType || gameType == gameTypes.SuperPermissionedGameType || gameType == gameTypes.SuperCannonKonaGameType {
continue
}
if gameType == gameTypes.TeeGameType { // For XLayer: TEE doesn't require RollupRpc
continue
}
t.Run(gameType.String(), func(t *testing.T) {
config := validConfig(t, gameType)
config.RollupRpc = ""
Expand Down
62 changes: 62 additions & 0 deletions op-challenger/config/config_xlayer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package config

import (
"errors"
"time"

gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types"
)

var (
ErrMissingTeeProverRpc = errors.New("missing TEE prover rpc url")
ErrInvalidTeeProvePollInterval = errors.New("TEE prove poll interval must be greater than 0")
ErrInvalidTeeProveTimeout = errors.New("TEE prove timeout must be greater than 0")
)

const (
DefaultTeeProvePollInterval = 30 * time.Second
DefaultTeeProveTimeout = 1 * time.Hour
)

// xlayerConfigCheckers holds additional config validation functions registered by XLayer extensions.
var xlayerConfigCheckers []func(Config) error

func init() {
xlayerConfigCheckers = append(xlayerConfigCheckers, checkTeeConfig)
}

func checkTeeConfig(c Config) error {
if c.GameTypeEnabled(gameTypes.TeeGameType) {
if c.TeeProverRpc == "" {
return ErrMissingTeeProverRpc
}
if c.TeeProvePollInterval <= 0 {
return ErrInvalidTeeProvePollInterval
}
if c.TeeProveTimeout <= 0 {
return ErrInvalidTeeProveTimeout
}
}
return nil
}

// onlyTeeGameType returns true if all enabled game types are TEE (no L2/beacon needed).
func (c Config) onlyTeeGameType() bool {
for _, t := range c.GameTypes {
if t != gameTypes.TeeGameType {
return false
}
}
return len(c.GameTypes) > 0
}

// CheckXLayer runs all XLayer-specific config validations.
// Called from the main Check() method via _xlayer integration.
func (c Config) CheckXLayer() error {
for _, checker := range xlayerConfigCheckers {
if err := checker(c); err != nil {
return err
}
}
return nil
}
59 changes: 59 additions & 0 deletions op-challenger/config/config_xlayer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package config

import (
"fmt"
"testing"

gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/stretchr/testify/require"
)

var validTeeProverRpc = "http://localhost:8080"

func applyValidConfigForTee(cfg *Config) {
cfg.TeeProverRpc = validTeeProverRpc
}

func TestTeeProverRpcRequired(t *testing.T) {
cfg := validConfig(t, gameTypes.TeeGameType)
applyValidConfigForTee(&cfg)
cfg.TeeProverRpc = ""
require.ErrorIs(t, cfg.Check(), ErrMissingTeeProverRpc)
}

func TestTeeProverRpcNotRequiredForOtherTypes(t *testing.T) {
for _, gameType := range gameTypes.SupportedGameTypes {
if gameType == gameTypes.TeeGameType {
continue
}
gameType := gameType
t.Run(fmt.Sprintf("GameType-%v", gameType), func(t *testing.T) {
cfg := validConfig(t, gameType)
// TeeProverRpc is not set — should still be valid for non-TEE game types
require.NoError(t, cfg.Check())
})
}
}

func TestTeeOnlyModeNoL1BeaconRequired(t *testing.T) {
cfg := validConfig(t, gameTypes.TeeGameType)
applyValidConfigForTee(&cfg)
cfg.L1Beacon = ""
require.NoError(t, cfg.Check())
}

func TestTeeOnlyModeNoL2RpcRequired(t *testing.T) {
cfg := validConfig(t, gameTypes.TeeGameType)
applyValidConfigForTee(&cfg)
cfg.L2Rpcs = nil
require.NoError(t, cfg.Check())
}

func TestTeeMixedModeStillRequiresL1Beacon(t *testing.T) {
cfg := validConfig(t, gameTypes.CannonGameType)
// Add TEE game type alongside cannon
cfg.GameTypes = append(cfg.GameTypes, gameTypes.TeeGameType)
applyValidConfigForTee(&cfg)
cfg.L1Beacon = ""
require.ErrorIs(t, cfg.Check(), ErrMissingL1Beacon)
}
8 changes: 7 additions & 1 deletion op-challenger/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ func init() {
optionalFlags = append(optionalFlags, txmgr.CLIFlagsWithDefaults(EnvVarPrefix, txmgr.DefaultChallengerFlagValues)...)
optionalFlags = append(optionalFlags, opmetrics.CLIFlags(EnvVarPrefix)...)
optionalFlags = append(optionalFlags, oppprof.CLIFlags(EnvVarPrefix)...)
optionalFlags = append(optionalFlags, teeFlags...) // For XLayer

Flags = append(requiredFlags, optionalFlags...)
}
Expand Down Expand Up @@ -439,11 +440,13 @@ func CheckRequired(ctx *cli.Context, types []gameTypes.GameType) error {
return fmt.Errorf("flag %s is required", f.Names()[0])
}
}
if !ctx.IsSet(L2EthRpcFlag.Name) {
if !ctx.IsSet(L2EthRpcFlag.Name) && !onlyTeeGameTypes(types) { // For XLayer: TEE game type does not require L2 RPC
return fmt.Errorf("flag %s is required", L2EthRpcFlag.Name)
}
for _, gameType := range types {
switch gameType {
case gameTypes.TeeGameType: // For XLayer: TEE game type has no additional flag requirements
continue
case gameTypes.CannonGameType, gameTypes.PermissionedGameType:
if err := CheckCannonFlags(ctx); err != nil {
return err
Expand Down Expand Up @@ -665,5 +668,8 @@ func NewConfigFromCLI(ctx *cli.Context, logger log.Logger) (*config.Config, erro
AllowInvalidPrestate: ctx.Bool(UnsafeAllowInvalidPrestate.Name),
ResponseDelay: ctx.Duration(ResponseDelayFlag.Name),
ResponseDelayAfter: ctx.Uint64(ResponseDelayAfterFlag.Name),
TeeProverRpc: ctx.String(TeeProverRpcFlag.Name), // For XLayer
TeeProvePollInterval: ctx.Duration(TeeProvePollIntervalFlag.Name), // For XLayer
TeeProveTimeout: ctx.Duration(TeeProveTimeoutFlag.Name), // For XLayer
}, nil
}
39 changes: 39 additions & 0 deletions op-challenger/flags/flags_xlayer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package flags

import (
"github.com/ethereum-optimism/optimism/op-challenger/config"
gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/urfave/cli/v2"
)

var (
TeeProverRpcFlag = &cli.StringFlag{
Name: "tee-prover-rpc",
Usage: "HTTP provider URL for the TEE Prover service (tee game type only)",
EnvVars: prefixEnvVars("TEE_PROVER_RPC"),
}
TeeProvePollIntervalFlag = &cli.DurationFlag{
Name: "tee-prove-poll-interval",
Usage: "Polling interval for TEE Prover task status (tee game type only)",
EnvVars: prefixEnvVars("TEE_PROVE_POLL_INTERVAL"),
Value: config.DefaultTeeProvePollInterval,
}
TeeProveTimeoutFlag = &cli.DurationFlag{
Name: "tee-prove-timeout",
Usage: "Total timeout for a single game's prove attempt including retries (tee game type only)",
EnvVars: prefixEnvVars("TEE_PROVE_TIMEOUT"),
Value: config.DefaultTeeProveTimeout,
}

teeFlags = []cli.Flag{TeeProverRpcFlag, TeeProvePollIntervalFlag, TeeProveTimeoutFlag}
)

// onlyTeeGameTypes returns true if all enabled game types are TEE (which doesn't require L2 RPC).
func onlyTeeGameTypes(types []gameTypes.GameType) bool {
for _, t := range types {
if t != gameTypes.TeeGameType {
return false
}
}
return len(types) > 0
}
2 changes: 2 additions & 0 deletions op-challenger/game/fault/contracts/disputegame.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ func NewDisputeGameContract(ctx context.Context, metrics metrics.ContractMetrice
return NewPreInteropFaultDisputeGameContract(ctx, metrics, addr, caller)
case gameTypes.OptimisticZKGameType:
return NewOptimisticZKDisputeGameContract(metrics, addr, caller)
case gameTypes.TeeGameType: // For XLayer
return NewTeeDisputeGameContract(metrics, addr, caller)
default:
return nil, ErrUnsupportedGameType
}
Expand Down
Loading