Commit 3a5fb5e8 authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

op-challenger: Add support for permissioned games. (#9535)

parent 9cca805d
This diff is collapsed.
...@@ -39,23 +39,12 @@ var ( ...@@ -39,23 +39,12 @@ var (
type TraceType string type TraceType string
const ( const (
TraceTypeAlphabet TraceType = "alphabet" TraceTypeAlphabet TraceType = "alphabet"
TraceTypeCannon TraceType = "cannon" TraceTypeCannon TraceType = "cannon"
TraceTypePermissioned TraceType = "permissioned"
// Mainnet games
CannonFaultGameID = 0
// Devnet games
AlphabetFaultGameID = 255
) )
var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon} var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon, TraceTypePermissioned}
// GameIdToString maps game IDs to their string representation.
var GameIdToString = map[uint8]string{
CannonFaultGameID: "Cannon",
AlphabetFaultGameID: "Alphabet",
}
func (t TraceType) String() string { func (t TraceType) String() string {
return string(t) return string(t)
...@@ -189,7 +178,7 @@ func (c Config) Check() error { ...@@ -189,7 +178,7 @@ func (c Config) Check() error {
if c.MaxConcurrency == 0 { if c.MaxConcurrency == 0 {
return ErrMaxConcurrencyZero return ErrMaxConcurrencyZero
} }
if c.TraceTypeEnabled(TraceTypeCannon) { if c.TraceTypeEnabled(TraceTypeCannon) || c.TraceTypeEnabled(TraceTypePermissioned) {
if c.CannonBin == "" { if c.CannonBin == "" {
return ErrMissingCannonBin return ErrMissingCannonBin
} }
......
package config package config
import ( import (
"fmt"
"runtime" "runtime"
"testing" "testing"
...@@ -23,9 +24,11 @@ var ( ...@@ -23,9 +24,11 @@ var (
validRollupRpc = "http://localhost:8555" validRollupRpc = "http://localhost:8555"
) )
var cannonTraceTypes = []TraceType{TraceTypeCannon, TraceTypePermissioned}
func validConfig(traceType TraceType) Config { func validConfig(traceType TraceType) Config {
cfg := NewConfig(validGameFactoryAddress, validL1EthRpc, validL1BeaconUrl, validDatadir, traceType) cfg := NewConfig(validGameFactoryAddress, validL1EthRpc, validL1BeaconUrl, validDatadir, traceType)
if traceType == TraceTypeCannon { if traceType == TraceTypeCannon || traceType == TraceTypePermissioned {
cfg.CannonBin = validCannonBin cfg.CannonBin = validCannonBin
cfg.CannonServer = validCannonOpProgramBin cfg.CannonServer = validCannonOpProgramBin
cfg.CannonAbsolutePreState = validCannonAbsolutPreState cfg.CannonAbsolutePreState = validCannonAbsolutPreState
...@@ -79,22 +82,88 @@ func TestGameAllowlistNotRequired(t *testing.T) { ...@@ -79,22 +82,88 @@ func TestGameAllowlistNotRequired(t *testing.T) {
require.NoError(t, config.Check()) require.NoError(t, config.Check())
} }
func TestCannonBinRequired(t *testing.T) { func TestCannonRequiredArgs(t *testing.T) {
config := validConfig(TraceTypeCannon) for _, traceType := range cannonTraceTypes {
config.CannonBin = "" traceType := traceType
require.ErrorIs(t, config.Check(), ErrMissingCannonBin)
}
func TestCannonServerRequired(t *testing.T) { t.Run(fmt.Sprintf("TestCannonBinRequired-%v", traceType), func(t *testing.T) {
config := validConfig(TraceTypeCannon) config := validConfig(traceType)
config.CannonServer = "" config.CannonBin = ""
require.ErrorIs(t, config.Check(), ErrMissingCannonServer) require.ErrorIs(t, config.Check(), ErrMissingCannonBin)
} })
func TestCannonAbsolutePreStateRequired(t *testing.T) { t.Run(fmt.Sprintf("TestCannonServerRequired-%v", traceType), func(t *testing.T) {
config := validConfig(TraceTypeCannon) config := validConfig(traceType)
config.CannonAbsolutePreState = "" config.CannonServer = ""
require.ErrorIs(t, config.Check(), ErrMissingCannonAbsolutePreState) require.ErrorIs(t, config.Check(), ErrMissingCannonServer)
})
t.Run(fmt.Sprintf("TestCannonAbsolutePreStateRequired-%v", traceType), func(t *testing.T) {
config := validConfig(traceType)
config.CannonAbsolutePreState = ""
require.ErrorIs(t, config.Check(), ErrMissingCannonAbsolutePreState)
})
t.Run(fmt.Sprintf("TestCannonL2Required-%v", traceType), func(t *testing.T) {
config := validConfig(traceType)
config.CannonL2 = ""
require.ErrorIs(t, config.Check(), ErrMissingCannonL2)
})
t.Run(fmt.Sprintf("TestCannonSnapshotFreq-%v", traceType), func(t *testing.T) {
t.Run("MustNotBeZero", func(t *testing.T) {
cfg := validConfig(traceType)
cfg.CannonSnapshotFreq = 0
require.ErrorIs(t, cfg.Check(), ErrMissingCannonSnapshotFreq)
})
})
t.Run(fmt.Sprintf("TestCannonInfoFreq-%v", traceType), func(t *testing.T) {
t.Run("MustNotBeZero", func(t *testing.T) {
cfg := validConfig(traceType)
cfg.CannonInfoFreq = 0
require.ErrorIs(t, cfg.Check(), ErrMissingCannonInfoFreq)
})
})
t.Run(fmt.Sprintf("TestCannonNetworkOrRollupConfigRequired-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType)
cfg.CannonNetwork = ""
cfg.CannonRollupConfigPath = ""
cfg.CannonL2GenesisPath = "genesis.json"
require.ErrorIs(t, cfg.Check(), ErrMissingCannonRollupConfig)
})
t.Run(fmt.Sprintf("TestCannonNetworkOrL2GenesisRequired-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType)
cfg.CannonNetwork = ""
cfg.CannonRollupConfigPath = "foo.json"
cfg.CannonL2GenesisPath = ""
require.ErrorIs(t, cfg.Check(), ErrMissingCannonL2Genesis)
})
t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndRollup-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType)
cfg.CannonNetwork = validCannonNetwork
cfg.CannonRollupConfigPath = "foo.json"
cfg.CannonL2GenesisPath = ""
require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndRollupConfig)
})
t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndL2Genesis-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType)
cfg.CannonNetwork = validCannonNetwork
cfg.CannonRollupConfigPath = ""
cfg.CannonL2GenesisPath = "foo.json"
require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndL2Genesis)
})
t.Run(fmt.Sprintf("TestNetworkMustBeValid-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType)
cfg.CannonNetwork = "unknown"
require.ErrorIs(t, cfg.Check(), ErrCannonNetworkUnknown)
})
}
} }
func TestDatadirRequired(t *testing.T) { func TestDatadirRequired(t *testing.T) {
...@@ -123,76 +192,15 @@ func TestHttpPollInterval(t *testing.T) { ...@@ -123,76 +192,15 @@ func TestHttpPollInterval(t *testing.T) {
}) })
} }
func TestRollupRpcRequired_Cannon(t *testing.T) { func TestRollupRpcRequired(t *testing.T) {
config := validConfig(TraceTypeCannon) for _, traceType := range TraceTypes {
config.RollupRpc = "" traceType := traceType
require.ErrorIs(t, config.Check(), ErrMissingRollupRpc) t.Run(traceType.String(), func(t *testing.T) {
} config := validConfig(traceType)
config.RollupRpc = ""
func TestRollupRpcRequired_Alphabet(t *testing.T) { require.ErrorIs(t, config.Check(), ErrMissingRollupRpc)
config := validConfig(TraceTypeAlphabet) })
config.RollupRpc = "" }
require.ErrorIs(t, config.Check(), ErrMissingRollupRpc)
}
func TestCannonL2Required(t *testing.T) {
config := validConfig(TraceTypeCannon)
config.CannonL2 = ""
require.ErrorIs(t, config.Check(), ErrMissingCannonL2)
}
func TestCannonSnapshotFreq(t *testing.T) {
t.Run("MustNotBeZero", func(t *testing.T) {
cfg := validConfig(TraceTypeCannon)
cfg.CannonSnapshotFreq = 0
require.ErrorIs(t, cfg.Check(), ErrMissingCannonSnapshotFreq)
})
}
func TestCannonInfoFreq(t *testing.T) {
t.Run("MustNotBeZero", func(t *testing.T) {
cfg := validConfig(TraceTypeCannon)
cfg.CannonInfoFreq = 0
require.ErrorIs(t, cfg.Check(), ErrMissingCannonInfoFreq)
})
}
func TestCannonNetworkOrRollupConfigRequired(t *testing.T) {
cfg := validConfig(TraceTypeCannon)
cfg.CannonNetwork = ""
cfg.CannonRollupConfigPath = ""
cfg.CannonL2GenesisPath = "genesis.json"
require.ErrorIs(t, cfg.Check(), ErrMissingCannonRollupConfig)
}
func TestCannonNetworkOrL2GenesisRequired(t *testing.T) {
cfg := validConfig(TraceTypeCannon)
cfg.CannonNetwork = ""
cfg.CannonRollupConfigPath = "foo.json"
cfg.CannonL2GenesisPath = ""
require.ErrorIs(t, cfg.Check(), ErrMissingCannonL2Genesis)
}
func TestMustNotSpecifyNetworkAndRollup(t *testing.T) {
cfg := validConfig(TraceTypeCannon)
cfg.CannonNetwork = validCannonNetwork
cfg.CannonRollupConfigPath = "foo.json"
cfg.CannonL2GenesisPath = ""
require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndRollupConfig)
}
func TestMustNotSpecifyNetworkAndL2Genesis(t *testing.T) {
cfg := validConfig(TraceTypeCannon)
cfg.CannonNetwork = validCannonNetwork
cfg.CannonRollupConfigPath = ""
cfg.CannonL2GenesisPath = "foo.json"
require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndL2Genesis)
}
func TestNetworkMustBeValid(t *testing.T) {
cfg := validConfig(TraceTypeCannon)
cfg.CannonNetwork = "unknown"
require.ErrorIs(t, cfg.Check(), ErrCannonNetworkUnknown)
} }
func TestRequireConfigForMultipleTraceTypes(t *testing.T) { func TestRequireConfigForMultipleTraceTypes(t *testing.T) {
......
...@@ -223,7 +223,7 @@ func CheckRequired(ctx *cli.Context, traceTypes []config.TraceType) error { ...@@ -223,7 +223,7 @@ func CheckRequired(ctx *cli.Context, traceTypes []config.TraceType) error {
} }
for _, traceType := range traceTypes { for _, traceType := range traceTypes {
switch traceType { switch traceType {
case config.TraceTypeCannon: case config.TraceTypeCannon, config.TraceTypePermissioned:
if err := CheckCannonFlags(ctx); err != nil { if err := CheckCannonFlags(ctx); err != nil {
return err return err
} }
......
...@@ -41,7 +41,7 @@ func RegisterGameTypes( ...@@ -41,7 +41,7 @@ func RegisterGameTypes(
) (CloseFunc, error) { ) (CloseFunc, error) {
var closer CloseFunc var closer CloseFunc
var l2Client *ethclient.Client var l2Client *ethclient.Client
if cfg.TraceTypeEnabled(config.TraceTypeCannon) { if cfg.TraceTypeEnabled(config.TraceTypeCannon) || cfg.TraceTypeEnabled(config.TraceTypePermissioned) {
l2, err := ethclient.DialContext(ctx, cfg.CannonL2) l2, err := ethclient.DialContext(ctx, cfg.CannonL2)
if err != nil { if err != nil {
return nil, fmt.Errorf("dial l2 client %v: %w", cfg.CannonL2, err) return nil, fmt.Errorf("dial l2 client %v: %w", cfg.CannonL2, err)
...@@ -50,10 +50,15 @@ func RegisterGameTypes( ...@@ -50,10 +50,15 @@ func RegisterGameTypes(
closer = l2Client.Close closer = l2Client.Close
} }
if cfg.TraceTypeEnabled(config.TraceTypeCannon) { if cfg.TraceTypeEnabled(config.TraceTypeCannon) {
if err := registerCannon(registry, ctx, cl, logger, m, cfg, rollupClient, txSender, gameFactory, caller, l2Client); err != nil { if err := registerCannon(faultTypes.CannonGameType, registry, ctx, cl, logger, m, cfg, rollupClient, txSender, gameFactory, caller, l2Client); err != nil {
return nil, fmt.Errorf("failed to register cannon game type: %w", err) return nil, fmt.Errorf("failed to register cannon game type: %w", err)
} }
} }
if cfg.TraceTypeEnabled(config.TraceTypePermissioned) {
if err := registerCannon(faultTypes.PermissionedGameType, registry, ctx, cl, logger, m, cfg, rollupClient, txSender, gameFactory, caller, l2Client); err != nil {
return nil, fmt.Errorf("failed to register permissioned cannon game type: %w", err)
}
}
if cfg.TraceTypeEnabled(config.TraceTypeAlphabet) { if cfg.TraceTypeEnabled(config.TraceTypeAlphabet) {
if err := registerAlphabet(registry, ctx, cl, logger, m, rollupClient, txSender, gameFactory, caller); err != nil { if err := registerAlphabet(registry, ctx, cl, logger, m, rollupClient, txSender, gameFactory, caller); err != nil {
return nil, fmt.Errorf("failed to register alphabet game type: %w", err) return nil, fmt.Errorf("failed to register alphabet game type: %w", err)
...@@ -128,6 +133,7 @@ func createOracle(ctx context.Context, gameFactory *contracts.DisputeGameFactory ...@@ -128,6 +133,7 @@ func createOracle(ctx context.Context, gameFactory *contracts.DisputeGameFactory
} }
func registerCannon( func registerCannon(
gameType uint32,
registry Registry, registry Registry,
ctx context.Context, ctx context.Context,
cl faultTypes.ClockReader, cl faultTypes.ClockReader,
...@@ -165,15 +171,15 @@ func registerCannon( ...@@ -165,15 +171,15 @@ func registerCannon(
genesisValidator := NewPrestateValidator("output root", contract.GetGenesisOutputRoot, prestateProvider) genesisValidator := NewPrestateValidator("output root", contract.GetGenesisOutputRoot, prestateProvider)
return NewGamePlayer(ctx, cl, logger, m, dir, game.Proxy, txSender, contract, []Validator{prestateValidator, genesisValidator}, creator) return NewGamePlayer(ctx, cl, logger, m, dir, game.Proxy, txSender, contract, []Validator{prestateValidator, genesisValidator}, creator)
} }
oracle, err := createOracle(ctx, gameFactory, caller, faultTypes.CannonGameType) oracle, err := createOracle(ctx, gameFactory, caller, gameType)
if err != nil { if err != nil {
return err return err
} }
registry.RegisterGameType(faultTypes.CannonGameType, playerCreator, oracle) registry.RegisterGameType(gameType, playerCreator, oracle)
contractCreator := func(game types.GameMetadata) (claims.BondContract, error) { contractCreator := func(game types.GameMetadata) (claims.BondContract, error) {
return contracts.NewFaultDisputeGameContract(game.Proxy, caller) return contracts.NewFaultDisputeGameContract(game.Proxy, caller)
} }
registry.RegisterBondContract(faultTypes.CannonGameType, contractCreator) registry.RegisterBondContract(gameType, contractCreator)
return nil return nil
} }
...@@ -19,8 +19,9 @@ var ( ...@@ -19,8 +19,9 @@ var (
) )
const ( const (
CannonGameType uint32 = 0 CannonGameType uint32 = 0
AlphabetGameType uint32 = 255 PermissionedGameType uint32 = 1
AlphabetGameType uint32 = 255
) )
type ClockReader interface { type ClockReader interface {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment