Commit cfe3cdd5 authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

op-challenger: Extract RegistrationTask to dedeuplicate registration code...

op-challenger: Extract RegistrationTask to dedeuplicate registration code between different game types. (#11413)
parent 46930eab
......@@ -381,7 +381,7 @@ func CheckRequired(ctx *cli.Context, traceTypes []types.TraceType) error {
}
case types.TraceTypeAlphabet, types.TraceTypeFast:
default:
return fmt.Errorf("invalid trace type. must be one of %v", types.TraceTypes)
return fmt.Errorf("invalid trace type %v. must be one of %v", traceType, types.TraceTypes)
}
}
return nil
......
......@@ -3,25 +3,17 @@ package fault
import (
"context"
"fmt"
"path/filepath"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/claims"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/asterisc"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/outputs"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/prestates"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm"
faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
......@@ -74,313 +66,29 @@ func RegisterGameTypes(
}
syncValidator := newSyncStatusValidator(rollupClient)
var registerTasks []*RegisterTask
if cfg.TraceTypeEnabled(faultTypes.TraceTypeCannon) {
vmConfig := vm.NewOpProgramVmConfig()
if err := registerCannon(faultTypes.CannonGameType, registry, oracles, ctx, systemClock, l1Clock, logger, m, cfg, vmConfig, syncValidator, rollupClient, txSender, gameFactory, caller, l2Client, l1HeaderSource, selective, claimants); err != nil {
return nil, fmt.Errorf("failed to register cannon game type: %w", err)
}
registerTasks = append(registerTasks, NewCannonRegisterTask(faultTypes.CannonGameType, cfg, m, vm.NewOpProgramServerExecutor()))
}
if cfg.TraceTypeEnabled(faultTypes.TraceTypePermissioned) {
vmConfig := vm.NewOpProgramVmConfig()
if err := registerCannon(faultTypes.PermissionedGameType, registry, oracles, ctx, systemClock, l1Clock, logger, m, cfg, vmConfig, syncValidator, rollupClient, txSender, gameFactory, caller, l2Client, l1HeaderSource, selective, claimants); err != nil {
return nil, fmt.Errorf("failed to register permissioned cannon game type: %w", err)
}
registerTasks = append(registerTasks, NewCannonRegisterTask(faultTypes.PermissionedGameType, cfg, m, vm.NewOpProgramServerExecutor()))
}
if cfg.TraceTypeEnabled(faultTypes.TraceTypeAsterisc) {
vmConfig := vm.NewOpProgramVmConfig()
if err := registerAsterisc(faultTypes.AsteriscGameType, registry, oracles, ctx, systemClock, l1Clock, logger, m, cfg, vmConfig, syncValidator, rollupClient, txSender, gameFactory, caller, l2Client, l1HeaderSource, selective, claimants); err != nil {
return nil, fmt.Errorf("failed to register asterisc game type: %w", err)
}
registerTasks = append(registerTasks, NewAsteriscRegisterTask(faultTypes.AsteriscGameType, cfg, m, vm.NewOpProgramServerExecutor()))
}
if cfg.TraceTypeEnabled(faultTypes.TraceTypeAsteriscKona) {
vmConfig := vm.NewKonaVmConfig()
if err := registerAsterisc(faultTypes.AsteriscKonaGameType, registry, oracles, ctx, systemClock, l1Clock, logger, m, cfg, vmConfig, syncValidator, rollupClient, txSender, gameFactory, caller, l2Client, l1HeaderSource, selective, claimants); err != nil {
return nil, fmt.Errorf("failed to register asterisc kona game type: %w", err)
}
registerTasks = append(registerTasks, NewAsteriscRegisterTask(faultTypes.AsteriscKonaGameType, cfg, m, vm.NewKonaServerExecutor()))
}
if cfg.TraceTypeEnabled(faultTypes.TraceTypeFast) {
if err := registerAlphabet(faultTypes.FastGameType, registry, oracles, ctx, systemClock, l1Clock, logger, m, syncValidator, rollupClient, l2Client, txSender, gameFactory, caller, l1HeaderSource, selective, claimants); err != nil {
return nil, fmt.Errorf("failed to register fast game type: %w", err)
}
registerTasks = append(registerTasks, NewAlphabetRegisterTask(faultTypes.FastGameType))
}
if cfg.TraceTypeEnabled(faultTypes.TraceTypeAlphabet) {
if err := registerAlphabet(faultTypes.AlphabetGameType, registry, oracles, ctx, systemClock, l1Clock, logger, m, syncValidator, rollupClient, l2Client, txSender, gameFactory, caller, l1HeaderSource, selective, claimants); err != nil {
return nil, fmt.Errorf("failed to register alphabet game type: %w", err)
}
}
return l2Client.Close, nil
}
func registerAlphabet(
gameType faultTypes.GameType,
registry Registry,
oracles OracleRegistry,
ctx context.Context,
systemClock clock.Clock,
l1Clock faultTypes.ClockReader,
logger log.Logger,
m metrics.Metricer,
syncValidator SyncValidator,
rollupClient RollupClient,
l2Client utils.L2HeaderSource,
txSender TxSender,
gameFactory *contracts.DisputeGameFactoryContract,
caller *batching.MultiCaller,
l1HeaderSource L1HeaderSource,
selective bool,
claimants []common.Address,
) error {
playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) {
contract, err := contracts.NewFaultDisputeGameContract(ctx, m, game.Proxy, caller)
if err != nil {
return nil, fmt.Errorf("failed to create fault dispute game contract: %w", err)
}
oracle, err := contract.GetOracle(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load oracle for game %v: %w", game.Proxy, err)
}
oracles.RegisterOracle(oracle)
prestateBlock, poststateBlock, err := contract.GetBlockRange(ctx)
if err != nil {
return nil, err
}
splitDepth, err := contract.GetSplitDepth(ctx)
if err != nil {
return nil, err
}
l1Head, err := loadL1Head(contract, ctx, l1HeaderSource)
if err != nil {
return nil, err
}
prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock)
creator := func(ctx context.Context, logger log.Logger, gameDepth faultTypes.Depth, dir string) (faultTypes.TraceAccessor, error) {
accessor, err := outputs.NewOutputAlphabetTraceAccessor(logger, m, prestateProvider, rollupClient, l2Client, l1Head, splitDepth, prestateBlock, poststateBlock)
if err != nil {
return nil, err
}
return accessor, nil
registerTasks = append(registerTasks, NewAlphabetRegisterTask(faultTypes.AlphabetGameType))
}
prestateValidator := NewPrestateValidator("alphabet", contract.GetAbsolutePrestateHash, alphabet.PrestateProvider)
startingValidator := NewPrestateValidator("output root", contract.GetStartingRootHash, prestateProvider)
return NewGamePlayer(ctx, systemClock, l1Clock, logger, m, dir, game.Proxy, txSender, contract, syncValidator, []Validator{prestateValidator, startingValidator}, creator, l1HeaderSource, selective, claimants)
for _, task := range registerTasks {
if err := task.Register(ctx, registry, oracles, systemClock, l1Clock, logger, m, syncValidator, rollupClient, txSender, gameFactory, caller, l2Client, l1HeaderSource, selective, claimants); err != nil {
return nil, fmt.Errorf("failed to register %v game type: %w", task.gameType, err)
}
err := registerOracle(ctx, m, oracles, gameFactory, caller, gameType)
if err != nil {
return err
}
registry.RegisterGameType(gameType, playerCreator)
contractCreator := func(game types.GameMetadata) (claims.BondContract, error) {
return contracts.NewFaultDisputeGameContract(ctx, m, game.Proxy, caller)
}
registry.RegisterBondContract(gameType, contractCreator)
return nil
}
func registerOracle(ctx context.Context, m metrics.Metricer, oracles OracleRegistry, gameFactory *contracts.DisputeGameFactoryContract, caller *batching.MultiCaller, gameType faultTypes.GameType) error {
implAddr, err := gameFactory.GetGameImpl(ctx, gameType)
if err != nil {
return fmt.Errorf("failed to load implementation for game type %v: %w", gameType, err)
}
contract, err := contracts.NewFaultDisputeGameContract(ctx, m, implAddr, caller)
if err != nil {
return fmt.Errorf("failed to create fault dispute game contracts: %w", err)
}
oracle, err := contract.GetOracle(ctx)
if err != nil {
return fmt.Errorf("failed to load oracle address: %w", err)
}
oracles.RegisterOracle(oracle)
return nil
}
func registerAsterisc(
gameType faultTypes.GameType,
registry Registry,
oracles OracleRegistry,
ctx context.Context,
systemClock clock.Clock,
l1Clock faultTypes.ClockReader,
logger log.Logger,
m metrics.Metricer,
cfg *config.Config,
vmCfg vm.OracleServerExecutor,
syncValidator SyncValidator,
rollupClient outputs.OutputRollupClient,
txSender TxSender,
gameFactory *contracts.DisputeGameFactoryContract,
caller *batching.MultiCaller,
l2Client utils.L2HeaderSource,
l1HeaderSource L1HeaderSource,
selective bool,
claimants []common.Address,
) error {
prestateSource := prestates.NewPrestateSource(cfg.AsteriscAbsolutePreStateBaseURL, cfg.AsteriscAbsolutePreState, filepath.Join(cfg.Datadir, "asterisc-prestates"))
prestateProviderCache := prestates.NewPrestateProviderCache(m, fmt.Sprintf("prestates-%v", gameType), func(prestateHash common.Hash) (faultTypes.PrestateProvider, error) {
prestatePath, err := prestateSource.PrestatePath(prestateHash)
if err != nil {
return nil, fmt.Errorf("required prestate %v not available: %w", prestateHash, err)
}
return asterisc.NewPrestateProvider(prestatePath), nil
})
playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) {
contract, err := contracts.NewFaultDisputeGameContract(ctx, m, game.Proxy, caller)
if err != nil {
return nil, fmt.Errorf("failed to create fault dispute game contracts: %w", err)
}
requiredPrestatehash, err := contract.GetAbsolutePrestateHash(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load prestate hash for game %v: %w", game.Proxy, err)
}
asteriscPrestateProvider, err := prestateProviderCache.GetOrCreate(requiredPrestatehash)
if err != nil {
return nil, fmt.Errorf("required prestate %v not available for game %v: %w", requiredPrestatehash, game.Proxy, err)
}
oracle, err := contract.GetOracle(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load oracle for game %v: %w", game.Proxy, err)
}
oracles.RegisterOracle(oracle)
prestateBlock, poststateBlock, err := contract.GetBlockRange(ctx)
if err != nil {
return nil, err
}
splitDepth, err := contract.GetSplitDepth(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load split depth: %w", err)
}
l1HeadID, err := loadL1Head(contract, ctx, l1HeaderSource)
if err != nil {
return nil, err
}
prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock)
creator := func(ctx context.Context, logger log.Logger, gameDepth faultTypes.Depth, dir string) (faultTypes.TraceAccessor, error) {
asteriscPrestate, err := prestateSource.PrestatePath(requiredPrestatehash)
if err != nil {
return nil, fmt.Errorf("failed to get asterisc prestate: %w", err)
}
accessor, err := outputs.NewOutputAsteriscTraceAccessor(logger, m, cfg.Asterisc, vmCfg, l2Client, prestateProvider, asteriscPrestate, rollupClient, dir, l1HeadID, splitDepth, prestateBlock, poststateBlock)
if err != nil {
return nil, err
}
return accessor, nil
}
prestateValidator := NewPrestateValidator("asterisc", contract.GetAbsolutePrestateHash, asteriscPrestateProvider)
genesisValidator := NewPrestateValidator("output root", contract.GetStartingRootHash, prestateProvider)
return NewGamePlayer(ctx, systemClock, l1Clock, logger, m, dir, game.Proxy, txSender, contract, syncValidator, []Validator{prestateValidator, genesisValidator}, creator, l1HeaderSource, selective, claimants)
}
err := registerOracle(ctx, m, oracles, gameFactory, caller, gameType)
if err != nil {
return err
}
registry.RegisterGameType(gameType, playerCreator)
contractCreator := func(game types.GameMetadata) (claims.BondContract, error) {
return contracts.NewFaultDisputeGameContract(ctx, m, game.Proxy, caller)
}
registry.RegisterBondContract(gameType, contractCreator)
return nil
}
func registerCannon(
gameType faultTypes.GameType,
registry Registry,
oracles OracleRegistry,
ctx context.Context,
systemClock clock.Clock,
l1Clock faultTypes.ClockReader,
logger log.Logger,
m metrics.Metricer,
cfg *config.Config,
vmCfg vm.OracleServerExecutor,
syncValidator SyncValidator,
rollupClient outputs.OutputRollupClient,
txSender TxSender,
gameFactory *contracts.DisputeGameFactoryContract,
caller *batching.MultiCaller,
l2Client utils.L2HeaderSource,
l1HeaderSource L1HeaderSource,
selective bool,
claimants []common.Address,
) error {
prestateSource := prestates.NewPrestateSource(cfg.CannonAbsolutePreStateBaseURL, cfg.CannonAbsolutePreState, filepath.Join(cfg.Datadir, "cannon-prestates"))
prestateProviderCache := prestates.NewPrestateProviderCache(m, fmt.Sprintf("prestates-%v", gameType), func(prestateHash common.Hash) (faultTypes.PrestateProvider, error) {
prestatePath, err := prestateSource.PrestatePath(prestateHash)
if err != nil {
return nil, fmt.Errorf("required prestate %v not available: %w", prestateHash, err)
}
return cannon.NewPrestateProvider(prestatePath), nil
})
playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) {
contract, err := contracts.NewFaultDisputeGameContract(ctx, m, game.Proxy, caller)
if err != nil {
return nil, fmt.Errorf("failed to create fault dispute game contracts: %w", err)
}
requiredPrestatehash, err := contract.GetAbsolutePrestateHash(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load prestate hash for game %v: %w", game.Proxy, err)
}
cannonPrestateProvider, err := prestateProviderCache.GetOrCreate(requiredPrestatehash)
if err != nil {
return nil, fmt.Errorf("required prestate %v not available for game %v: %w", requiredPrestatehash, game.Proxy, err)
}
oracle, err := contract.GetOracle(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load oracle for game %v: %w", game.Proxy, err)
}
oracles.RegisterOracle(oracle)
prestateBlock, poststateBlock, err := contract.GetBlockRange(ctx)
if err != nil {
return nil, err
}
splitDepth, err := contract.GetSplitDepth(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load split depth: %w", err)
}
l1HeadID, err := loadL1Head(contract, ctx, l1HeaderSource)
if err != nil {
return nil, err
}
prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock)
creator := func(ctx context.Context, logger log.Logger, gameDepth faultTypes.Depth, dir string) (faultTypes.TraceAccessor, error) {
cannonPrestate, err := prestateSource.PrestatePath(requiredPrestatehash)
if err != nil {
return nil, fmt.Errorf("failed to get cannon prestate: %w", err)
}
accessor, err := outputs.NewOutputCannonTraceAccessor(logger, m, cfg.Cannon, vmCfg, l2Client, prestateProvider, cannonPrestate, rollupClient, dir, l1HeadID, splitDepth, prestateBlock, poststateBlock)
if err != nil {
return nil, err
}
return accessor, nil
}
prestateValidator := NewPrestateValidator("cannon", contract.GetAbsolutePrestateHash, cannonPrestateProvider)
startingValidator := NewPrestateValidator("output root", contract.GetStartingRootHash, prestateProvider)
return NewGamePlayer(ctx, systemClock, l1Clock, logger, m, dir, game.Proxy, txSender, contract, syncValidator, []Validator{prestateValidator, startingValidator}, creator, l1HeaderSource, selective, claimants)
}
err := registerOracle(ctx, m, oracles, gameFactory, caller, gameType)
if err != nil {
return err
}
registry.RegisterGameType(gameType, playerCreator)
contractCreator := func(game types.GameMetadata) (claims.BondContract, error) {
return contracts.NewFaultDisputeGameContract(ctx, m, game.Proxy, caller)
}
registry.RegisterBondContract(gameType, contractCreator)
return nil
}
func loadL1Head(contract contracts.FaultDisputeGameContract, ctx context.Context, l1HeaderSource L1HeaderSource) (eth.BlockID, error) {
l1Head, err := contract.GetL1Head(ctx)
if err != nil {
return eth.BlockID{}, fmt.Errorf("failed to load L1 head: %w", err)
}
l1Header, err := l1HeaderSource.HeaderByHash(ctx, l1Head)
if err != nil {
return eth.BlockID{}, fmt.Errorf("failed to load L1 header: %w", err)
}
return eth.HeaderBlockID(l1Header), nil
return l2Client.Close, nil
}
package fault
import (
"context"
"fmt"
"net/url"
"path/filepath"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/claims"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/asterisc"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/outputs"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/prestates"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm"
faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/sources/caching"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
)
type RegisterTask struct {
gameType faultTypes.GameType
getPrestateProvider func(prestateHash common.Hash) (faultTypes.PrestateProvider, error)
newTraceAccessor func(
logger log.Logger,
m metrics.Metricer,
l2Client utils.L2HeaderSource,
prestateProvider faultTypes.PrestateProvider,
vmPrestateProvider faultTypes.PrestateProvider,
rollupClient outputs.OutputRollupClient,
dir string,
l1Head eth.BlockID,
splitDepth faultTypes.Depth,
prestateBlock uint64,
poststateBlock uint64) (*trace.Accessor, error)
}
func NewCannonRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor) *RegisterTask {
return &RegisterTask{
gameType: gameType,
getPrestateProvider: cachePrestates(
gameType,
m,
cfg.CannonAbsolutePreStateBaseURL,
cfg.CannonAbsolutePreState,
filepath.Join(cfg.Datadir, "cannon-prestates"),
func(path string) faultTypes.PrestateProvider {
return cannon.NewPrestateProvider(path)
}),
newTraceAccessor: func(
logger log.Logger,
m metrics.Metricer,
l2Client utils.L2HeaderSource,
prestateProvider faultTypes.PrestateProvider,
vmPrestateProvider faultTypes.PrestateProvider,
rollupClient outputs.OutputRollupClient,
dir string,
l1Head eth.BlockID,
splitDepth faultTypes.Depth,
prestateBlock uint64,
poststateBlock uint64) (*trace.Accessor, error) {
provider := vmPrestateProvider.(*cannon.CannonPrestateProvider)
return outputs.NewOutputCannonTraceAccessor(logger, m, cfg.Cannon, serverExecutor, l2Client, prestateProvider, provider.PrestatePath(), rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock)
},
}
}
func NewAsteriscRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor) *RegisterTask {
return &RegisterTask{
gameType: gameType,
getPrestateProvider: cachePrestates(
gameType,
m,
cfg.AsteriscAbsolutePreStateBaseURL,
cfg.AsteriscAbsolutePreState,
filepath.Join(cfg.Datadir, "asterisc-prestates"),
func(path string) faultTypes.PrestateProvider {
return asterisc.NewPrestateProvider(path)
}),
newTraceAccessor: func(
logger log.Logger,
m metrics.Metricer,
l2Client utils.L2HeaderSource,
prestateProvider faultTypes.PrestateProvider,
vmPrestateProvider faultTypes.PrestateProvider,
rollupClient outputs.OutputRollupClient,
dir string,
l1Head eth.BlockID,
splitDepth faultTypes.Depth,
prestateBlock uint64,
poststateBlock uint64) (*trace.Accessor, error) {
provider := vmPrestateProvider.(*asterisc.AsteriscPreStateProvider)
return outputs.NewOutputAsteriscTraceAccessor(logger, m, cfg.Asterisc, serverExecutor, l2Client, prestateProvider, provider.PrestatePath(), rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock)
},
}
}
func NewAlphabetRegisterTask(gameType faultTypes.GameType) *RegisterTask {
return &RegisterTask{
gameType: gameType,
getPrestateProvider: func(_ common.Hash) (faultTypes.PrestateProvider, error) {
return alphabet.PrestateProvider, nil
},
newTraceAccessor: func(
logger log.Logger,
m metrics.Metricer,
l2Client utils.L2HeaderSource,
prestateProvider faultTypes.PrestateProvider,
vmPrestateProvider faultTypes.PrestateProvider,
rollupClient outputs.OutputRollupClient,
dir string,
l1Head eth.BlockID,
splitDepth faultTypes.Depth,
prestateBlock uint64,
poststateBlock uint64) (*trace.Accessor, error) {
return outputs.NewOutputAlphabetTraceAccessor(logger, m, prestateProvider, rollupClient, l2Client, l1Head, splitDepth, prestateBlock, poststateBlock)
},
}
}
func cachePrestates(
gameType faultTypes.GameType,
m caching.Metrics,
prestateBaseURL *url.URL,
preStatePath string,
prestateDir string,
newPrestateProvider func(path string) faultTypes.PrestateProvider,
) func(prestateHash common.Hash) (faultTypes.PrestateProvider, error) {
prestateSource := prestates.NewPrestateSource(prestateBaseURL, preStatePath, prestateDir)
prestateProviderCache := prestates.NewPrestateProviderCache(m, fmt.Sprintf("prestates-%v", gameType), func(prestateHash common.Hash) (faultTypes.PrestateProvider, error) {
prestatePath, err := prestateSource.PrestatePath(prestateHash)
if err != nil {
return nil, fmt.Errorf("required prestate %v not available: %w", prestateHash, err)
}
return newPrestateProvider(prestatePath), nil
})
return prestateProviderCache.GetOrCreate
}
func (e *RegisterTask) Register(
ctx context.Context,
registry Registry,
oracles OracleRegistry,
systemClock clock.Clock,
l1Clock faultTypes.ClockReader,
logger log.Logger,
m metrics.Metricer,
syncValidator SyncValidator,
rollupClient outputs.OutputRollupClient,
txSender TxSender,
gameFactory *contracts.DisputeGameFactoryContract,
caller *batching.MultiCaller,
l2Client utils.L2HeaderSource,
l1HeaderSource L1HeaderSource,
selective bool,
claimants []common.Address) error {
playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) {
contract, err := contracts.NewFaultDisputeGameContract(ctx, m, game.Proxy, caller)
if err != nil {
return nil, fmt.Errorf("failed to create fault dispute game contracts: %w", err)
}
requiredPrestatehash, err := contract.GetAbsolutePrestateHash(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load prestate hash for game %v: %w", game.Proxy, err)
}
vmPrestateProvider, err := e.getPrestateProvider(requiredPrestatehash)
if err != nil {
return nil, fmt.Errorf("required prestate %v not available for game %v: %w", requiredPrestatehash, game.Proxy, err)
}
oracle, err := contract.GetOracle(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load oracle for game %v: %w", game.Proxy, err)
}
oracles.RegisterOracle(oracle)
prestateBlock, poststateBlock, err := contract.GetBlockRange(ctx)
if err != nil {
return nil, err
}
splitDepth, err := contract.GetSplitDepth(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load split depth: %w", err)
}
l1HeadID, err := loadL1Head(contract, ctx, l1HeaderSource)
if err != nil {
return nil, err
}
prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock)
creator := func(ctx context.Context, logger log.Logger, gameDepth faultTypes.Depth, dir string) (faultTypes.TraceAccessor, error) {
accessor, err := e.newTraceAccessor(logger, m, l2Client, prestateProvider, vmPrestateProvider, rollupClient, dir, l1HeadID, splitDepth, prestateBlock, poststateBlock)
if err != nil {
return nil, err
}
return accessor, nil
}
prestateValidator := NewPrestateValidator(e.gameType.String(), contract.GetAbsolutePrestateHash, vmPrestateProvider)
startingValidator := NewPrestateValidator("output root", contract.GetStartingRootHash, prestateProvider)
return NewGamePlayer(ctx, systemClock, l1Clock, logger, m, dir, game.Proxy, txSender, contract, syncValidator, []Validator{prestateValidator, startingValidator}, creator, l1HeaderSource, selective, claimants)
}
err := registerOracle(ctx, m, oracles, gameFactory, caller, e.gameType)
if err != nil {
return err
}
registry.RegisterGameType(e.gameType, playerCreator)
contractCreator := func(game types.GameMetadata) (claims.BondContract, error) {
return contracts.NewFaultDisputeGameContract(ctx, m, game.Proxy, caller)
}
registry.RegisterBondContract(e.gameType, contractCreator)
return nil
}
func registerOracle(ctx context.Context, m metrics.Metricer, oracles OracleRegistry, gameFactory *contracts.DisputeGameFactoryContract, caller *batching.MultiCaller, gameType faultTypes.GameType) error {
implAddr, err := gameFactory.GetGameImpl(ctx, gameType)
if err != nil {
return fmt.Errorf("failed to load implementation for game type %v: %w", gameType, err)
}
contract, err := contracts.NewFaultDisputeGameContract(ctx, m, implAddr, caller)
if err != nil {
return fmt.Errorf("failed to create fault dispute game contracts: %w", err)
}
oracle, err := contract.GetOracle(ctx)
if err != nil {
return fmt.Errorf("failed to load oracle address: %w", err)
}
oracles.RegisterOracle(oracle)
return nil
}
func loadL1Head(contract contracts.FaultDisputeGameContract, ctx context.Context, l1HeaderSource L1HeaderSource) (eth.BlockID, error) {
l1Head, err := contract.GetL1Head(ctx)
if err != nil {
return eth.BlockID{}, fmt.Errorf("failed to load L1 head: %w", err)
}
l1Header, err := l1HeaderSource.HeaderByHash(ctx, l1Head)
if err != nil {
return eth.BlockID{}, fmt.Errorf("failed to load L1 header: %w", err)
}
return eth.HeaderBlockID(l1Header), nil
}
......@@ -39,3 +39,7 @@ func (p *AsteriscPreStateProvider) AbsolutePreStateCommitment(_ context.Context)
p.prestateCommitment = state.StateHash
return state.StateHash, nil
}
func (p *AsteriscPreStateProvider) PrestatePath() string {
return p.prestate
}
......@@ -177,7 +177,7 @@ func NewTraceProviderForTest(logger log.Logger, m vm.Metricer, cfg *config.Confi
logger: logger,
dir: dir,
prestate: cfg.AsteriscAbsolutePreState,
generator: vm.NewExecutor(logger, m, cfg.Asterisc, vm.NewOpProgramVmConfig(), cfg.AsteriscAbsolutePreState, localInputs),
generator: vm.NewExecutor(logger, m, cfg.Asterisc, vm.NewOpProgramServerExecutor(), cfg.AsteriscAbsolutePreState, localInputs),
gameDepth: gameDepth,
preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(vm.PreimageDir(dir)).Get),
}
......
......@@ -41,3 +41,7 @@ func (p *CannonPrestateProvider) AbsolutePreStateCommitment(_ context.Context) (
p.prestateCommitment = hash
return hash, nil
}
func (p *CannonPrestateProvider) PrestatePath() string {
return p.prestate
}
......@@ -181,7 +181,7 @@ func NewTraceProviderForTest(logger log.Logger, m vm.Metricer, cfg *config.Confi
logger: logger,
dir: dir,
prestate: cfg.CannonAbsolutePreState,
generator: vm.NewExecutor(logger, m, cfg.Cannon, vm.NewOpProgramVmConfig(), cfg.CannonAbsolutePreState, localInputs),
generator: vm.NewExecutor(logger, m, cfg.Cannon, vm.NewOpProgramServerExecutor(), cfg.CannonAbsolutePreState, localInputs),
gameDepth: gameDepth,
preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(vm.PreimageDir(dir)).Get),
}
......
......@@ -22,7 +22,7 @@ func NewOutputCannonTraceAccessor(
logger log.Logger,
m metrics.Metricer,
cfg vm.Config,
vmCfg vm.OracleServerExecutor,
serverExecutor vm.OracleServerExecutor,
l2Client utils.L2HeaderSource,
prestateProvider types.PrestateProvider,
cannonPrestate string,
......@@ -41,7 +41,7 @@ func NewOutputCannonTraceAccessor(
if err != nil {
return nil, fmt.Errorf("failed to fetch cannon local inputs: %w", err)
}
provider := cannon.NewTraceProvider(logger, m, cfg, vmCfg, prestateProvider, cannonPrestate, localInputs, subdir, depth)
provider := cannon.NewTraceProvider(logger, m, cfg, serverExecutor, prestateProvider, cannonPrestate, localInputs, subdir, depth)
return provider, nil
}
......
......@@ -42,7 +42,7 @@ func TestGenerateProof(t *testing.T) {
}
captureExec := func(t *testing.T, cfg Config, proofAt uint64) (string, string, map[string]string) {
m := &stubVmMetrics{}
executor := NewExecutor(testlog.Logger(t, log.LevelInfo), m, cfg, NewOpProgramVmConfig(), prestate, inputs)
executor := NewExecutor(testlog.Logger(t, log.LevelInfo), m, cfg, NewOpProgramServerExecutor(), prestate, inputs)
executor.selectSnapshot = func(logger log.Logger, dir string, absolutePreState string, i uint64) (string, error) {
return input, nil
}
......
......@@ -8,16 +8,16 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
)
type KonaVmConfig struct {
type KonaServerExecutor struct {
}
var _ OracleServerExecutor = (*KonaVmConfig)(nil)
var _ OracleServerExecutor = (*KonaServerExecutor)(nil)
func NewKonaVmConfig() *KonaVmConfig {
return &KonaVmConfig{}
func NewKonaServerExecutor() *KonaServerExecutor {
return &KonaServerExecutor{}
}
func (s *KonaVmConfig) OracleCommand(cfg Config, dataDir string, inputs utils.LocalGameInputs) ([]string, error) {
func (s *KonaServerExecutor) OracleCommand(cfg Config, dataDir string, inputs utils.LocalGameInputs) ([]string, error) {
if cfg.Network == "" {
return nil, errors.New("network is not defined")
}
......
......@@ -26,7 +26,7 @@ func TestKonaFillHostCommand(t *testing.T) {
L2Claim: common.Hash{0x44},
L2BlockNumber: big.NewInt(3333),
}
vmConfig := NewKonaVmConfig()
vmConfig := NewKonaServerExecutor()
args, err := vmConfig.OracleCommand(cfg, dir, inputs)
require.NoError(t, err)
......
......@@ -4,16 +4,16 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
)
type OpProgramVmConfig struct {
type OpProgramServerExecutor struct {
}
var _ OracleServerExecutor = (*OpProgramVmConfig)(nil)
var _ OracleServerExecutor = (*OpProgramServerExecutor)(nil)
func NewOpProgramVmConfig() *OpProgramVmConfig {
return &OpProgramVmConfig{}
func NewOpProgramServerExecutor() *OpProgramServerExecutor {
return &OpProgramServerExecutor{}
}
func (s *OpProgramVmConfig) OracleCommand(cfg Config, dataDir string, inputs utils.LocalGameInputs) ([]string, error) {
func (s *OpProgramServerExecutor) OracleCommand(cfg Config, dataDir string, inputs utils.LocalGameInputs) ([]string, error) {
args := []string{
cfg.Server, "--server",
"--l1", cfg.L1,
......
......@@ -40,7 +40,7 @@ func TestOpProgramFillHostCommand(t *testing.T) {
}
t.Run("NoExtras", func(t *testing.T) {
vmConfig := NewOpProgramVmConfig()
vmConfig := NewOpProgramServerExecutor()
args, err := vmConfig.OracleCommand(cfg, dir, inputs)
require.NoError(t, err)
......@@ -50,7 +50,7 @@ func TestOpProgramFillHostCommand(t *testing.T) {
t.Run("WithNetwork", func(t *testing.T) {
cfg.Network = "op-test"
vmConfig := NewOpProgramVmConfig()
vmConfig := NewOpProgramServerExecutor()
args, err := vmConfig.OracleCommand(cfg, dir, inputs)
require.NoError(t, err)
......@@ -61,7 +61,7 @@ func TestOpProgramFillHostCommand(t *testing.T) {
t.Run("WithRollupConfigPath", func(t *testing.T) {
cfg.RollupConfigPath = "rollup.config"
vmConfig := NewOpProgramVmConfig()
vmConfig := NewOpProgramServerExecutor()
args, err := vmConfig.OracleCommand(cfg, dir, inputs)
require.NoError(t, err)
......@@ -72,7 +72,7 @@ func TestOpProgramFillHostCommand(t *testing.T) {
t.Run("WithL2GenesisPath", func(t *testing.T) {
cfg.L2GenesisPath = "l2.genesis"
vmConfig := NewOpProgramVmConfig()
vmConfig := NewOpProgramServerExecutor()
args, err := vmConfig.OracleCommand(cfg, dir, inputs)
require.NoError(t, err)
......@@ -85,7 +85,7 @@ func TestOpProgramFillHostCommand(t *testing.T) {
cfg.Network = "op-test"
cfg.RollupConfigPath = "rollup.config"
cfg.L2GenesisPath = "l2.genesis"
vmConfig := NewOpProgramVmConfig()
vmConfig := NewOpProgramServerExecutor()
args, err := vmConfig.OracleCommand(cfg, dir, inputs)
require.NoError(t, err)
......
......@@ -28,7 +28,7 @@ func createTraceProvider(
) (types.TraceProvider, error) {
switch traceType {
case types.TraceTypeCannon:
vmConfig := vm.NewOpProgramVmConfig()
vmConfig := vm.NewOpProgramServerExecutor()
prestate, err := getPrestate(prestateHash, cfg.CannonAbsolutePreStateBaseURL, cfg.CannonAbsolutePreState, dir)
if err != nil {
return nil, err
......@@ -36,7 +36,7 @@ func createTraceProvider(
prestateProvider := cannon.NewPrestateProvider(prestate)
return cannon.NewTraceProvider(logger, m, cfg.Cannon, vmConfig, prestateProvider, prestate, localInputs, dir, 42), nil
case types.TraceTypeAsterisc:
vmConfig := vm.NewOpProgramVmConfig()
vmConfig := vm.NewOpProgramServerExecutor()
prestate, err := getPrestate(prestateHash, cfg.AsteriscAbsolutePreStateBaseURL, cfg.AsteriscAbsolutePreState, dir)
if err != nil {
return nil, err
......@@ -44,7 +44,7 @@ func createTraceProvider(
prestateProvider := asterisc.NewPrestateProvider(prestate)
return asterisc.NewTraceProvider(logger, m, cfg.Asterisc, vmConfig, prestateProvider, prestate, localInputs, dir, 42), nil
case types.TraceTypeAsteriscKona:
vmConfig := vm.NewKonaVmConfig()
vmConfig := vm.NewKonaServerExecutor()
prestate, err := getPrestate(prestateHash, cfg.AsteriscAbsolutePreStateBaseURL, cfg.AsteriscAbsolutePreState, dir)
if err != nil {
return nil, err
......
......@@ -51,7 +51,11 @@ func (g *GameCallerCreator) CreateContract(ctx context.Context, game gameTypes.G
return fdg, nil
}
switch faultTypes.GameType(game.GameType) {
case faultTypes.CannonGameType, faultTypes.PermissionedGameType, faultTypes.AsteriscGameType, faultTypes.AlphabetGameType:
case faultTypes.CannonGameType,
faultTypes.PermissionedGameType,
faultTypes.AsteriscGameType,
faultTypes.AlphabetGameType,
faultTypes.FastGameType:
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)
......
......@@ -31,6 +31,10 @@ func TestMetadataCreator_CreateContract(t *testing.T) {
name: "validCannonGameType",
game: types.GameMetadata{GameType: uint32(faultTypes.CannonGameType), Proxy: fdgAddr},
},
{
name: "validPermissionedGameType",
game: types.GameMetadata{GameType: uint32(faultTypes.PermissionedGameType), Proxy: fdgAddr},
},
{
name: "validAsteriscGameType",
game: types.GameMetadata{GameType: uint32(faultTypes.AsteriscGameType), Proxy: fdgAddr},
......@@ -39,6 +43,10 @@ func TestMetadataCreator_CreateContract(t *testing.T) {
name: "validAlphabetGameType",
game: types.GameMetadata{GameType: uint32(faultTypes.AlphabetGameType), Proxy: fdgAddr},
},
{
name: "validFastGameType",
game: types.GameMetadata{GameType: uint32(faultTypes.FastGameType), Proxy: fdgAddr},
},
{
name: "InvalidGameType",
game: types.GameMetadata{GameType: 3, Proxy: fdgAddr},
......
......@@ -63,7 +63,7 @@ func (g *OutputCannonGameHelper) CreateHonestActor(ctx context.Context, l2Node s
prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock)
l1Head := g.GetL1Head(ctx)
accessor, err := outputs.NewOutputCannonTraceAccessor(
logger, metrics.NoopMetrics, cfg.Cannon, vm.NewOpProgramVmConfig(), l2Client, prestateProvider, cfg.CannonAbsolutePreState, rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock)
logger, metrics.NoopMetrics, cfg.Cannon, vm.NewOpProgramServerExecutor(), l2Client, prestateProvider, cfg.CannonAbsolutePreState, rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock)
g.Require.NoError(err, "Failed to create output cannon trace accessor")
return NewOutputHonestHelper(g.T, g.Require, &g.OutputGameHelper, g.Game, accessor)
}
......
......@@ -225,7 +225,7 @@ func runCannon(t *testing.T, ctx context.Context, sys *op_e2e.System, inputs uti
cannonOpts(&cfg)
logger := testlog.Logger(t, log.LevelInfo).New("role", "cannon")
executor := vm.NewExecutor(logger, metrics.NoopMetrics, cfg.Cannon, vm.NewOpProgramVmConfig(), cfg.CannonAbsolutePreState, inputs)
executor := vm.NewExecutor(logger, metrics.NoopMetrics, cfg.Cannon, vm.NewOpProgramServerExecutor(), cfg.CannonAbsolutePreState, inputs)
t.Log("Running cannon")
err := executor.DoGenerateProof(ctx, proofsDir, math.MaxUint, math.MaxUint, extraVmArgs...)
......
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