Commit 8910388c authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

op-challenger: Lazy create clients (#13810)

Make sync validator configurable per game type.
parent bd7c16b8
package fault
import (
"context"
"fmt"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-service/dial"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
)
type clientProvider struct {
ctx context.Context
logger log.Logger
cfg *config.Config
l2HeaderSource utils.L2HeaderSource
rollupClient RollupClient
syncValidator *syncStatusValidator
toClose []CloseFunc
}
func (c *clientProvider) Close() {
for _, closeFunc := range c.toClose {
closeFunc()
}
}
func (c *clientProvider) SingleChainClients() (utils.L2HeaderSource, RollupClient, *syncStatusValidator, error) {
headers, err := c.L2HeaderSource()
if err != nil {
return nil, nil, nil, err
}
rollup, err := c.RollupClient()
if err != nil {
return nil, nil, nil, err
}
return headers, rollup, c.syncValidator, nil
}
func (c *clientProvider) L2HeaderSource() (utils.L2HeaderSource, error) {
if c.l2HeaderSource != nil {
return c.l2HeaderSource, nil
}
l2Client, err := ethclient.DialContext(c.ctx, c.cfg.L2Rpc)
if err != nil {
return nil, fmt.Errorf("dial l2 client %v: %w", c.cfg.L2Rpc, err)
}
c.l2HeaderSource = l2Client
c.toClose = append(c.toClose, l2Client.Close)
return l2Client, nil
}
func (c *clientProvider) RollupClient() (RollupClient, error) {
if c.rollupClient != nil {
return c.rollupClient, nil
}
rollupClient, err := dial.DialRollupClientWithTimeout(c.ctx, dial.DefaultDialTimeout, c.logger, c.cfg.RollupRpc)
if err != nil {
return nil, fmt.Errorf("dial rollup client %v: %w", c.cfg.RollupRpc, err)
}
c.rollupClient = rollupClient
c.syncValidator = newSyncStatusValidator(rollupClient)
c.toClose = append(c.toClose, rollupClient.Close)
return rollupClient, nil
}
......@@ -14,10 +14,8 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum-optimism/optimism/op-service/dial"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
)
......@@ -60,45 +58,54 @@ func RegisterGameTypes(
selective bool,
claimants []common.Address,
) (CloseFunc, error) {
l2Client, err := ethclient.DialContext(ctx, cfg.L2Rpc)
if err != nil {
return nil, fmt.Errorf("dial l2 client %v: %w", cfg.L2Rpc, err)
}
closer := l2Client.Close
rollupClient, err := dial.DialRollupClientWithTimeout(ctx, dial.DefaultDialTimeout, logger, cfg.RollupRpc)
if err != nil {
return closer, fmt.Errorf("dial rollup client %v: %w", cfg.RollupRpc, err)
}
closer = func() {
l2Client.Close()
rollupClient.Close()
}
syncValidator := newSyncStatusValidator(rollupClient)
clients := &clientProvider{ctx: ctx, logger: logger, cfg: cfg}
var registerTasks []*RegisterTask
if cfg.TraceTypeEnabled(faultTypes.TraceTypeCannon) {
registerTasks = append(registerTasks, NewCannonRegisterTask(faultTypes.CannonGameType, cfg, m, vm.NewOpProgramServerExecutor(logger), l2Client, rollupClient))
l2HeaderSource, rollupClient, syncValidator, err := clients.SingleChainClients()
if err != nil {
return nil, err
}
registerTasks = append(registerTasks, NewCannonRegisterTask(faultTypes.CannonGameType, cfg, m, vm.NewOpProgramServerExecutor(logger), l2HeaderSource, rollupClient, syncValidator))
}
if cfg.TraceTypeEnabled(faultTypes.TraceTypePermissioned) {
registerTasks = append(registerTasks, NewCannonRegisterTask(faultTypes.PermissionedGameType, cfg, m, vm.NewOpProgramServerExecutor(logger), l2Client, rollupClient))
l2HeaderSource, rollupClient, syncValidator, err := clients.SingleChainClients()
if err != nil {
return nil, err
}
registerTasks = append(registerTasks, NewCannonRegisterTask(faultTypes.PermissionedGameType, cfg, m, vm.NewOpProgramServerExecutor(logger), l2HeaderSource, rollupClient, syncValidator))
}
if cfg.TraceTypeEnabled(faultTypes.TraceTypeAsterisc) {
registerTasks = append(registerTasks, NewAsteriscRegisterTask(faultTypes.AsteriscGameType, cfg, m, vm.NewOpProgramServerExecutor(logger), l2Client, rollupClient))
l2HeaderSource, rollupClient, syncValidator, err := clients.SingleChainClients()
if err != nil {
return nil, err
}
registerTasks = append(registerTasks, NewAsteriscRegisterTask(faultTypes.AsteriscGameType, cfg, m, vm.NewOpProgramServerExecutor(logger), l2HeaderSource, rollupClient, syncValidator))
}
if cfg.TraceTypeEnabled(faultTypes.TraceTypeAsteriscKona) {
registerTasks = append(registerTasks, NewAsteriscKonaRegisterTask(faultTypes.AsteriscKonaGameType, cfg, m, vm.NewKonaExecutor(), l2Client, rollupClient))
l2HeaderSource, rollupClient, syncValidator, err := clients.SingleChainClients()
if err != nil {
return nil, err
}
registerTasks = append(registerTasks, NewAsteriscKonaRegisterTask(faultTypes.AsteriscKonaGameType, cfg, m, vm.NewKonaExecutor(), l2HeaderSource, rollupClient, syncValidator))
}
if cfg.TraceTypeEnabled(faultTypes.TraceTypeFast) {
registerTasks = append(registerTasks, NewAlphabetRegisterTask(faultTypes.FastGameType, l2Client, rollupClient))
l2HeaderSource, rollupClient, syncValidator, err := clients.SingleChainClients()
if err != nil {
return nil, err
}
registerTasks = append(registerTasks, NewAlphabetRegisterTask(faultTypes.FastGameType, l2HeaderSource, rollupClient, syncValidator))
}
if cfg.TraceTypeEnabled(faultTypes.TraceTypeAlphabet) {
registerTasks = append(registerTasks, NewAlphabetRegisterTask(faultTypes.AlphabetGameType, l2Client, rollupClient))
l2HeaderSource, rollupClient, syncValidator, err := clients.SingleChainClients()
if err != nil {
return nil, err
}
registerTasks = append(registerTasks, NewAlphabetRegisterTask(faultTypes.AlphabetGameType, l2HeaderSource, rollupClient, syncValidator))
}
for _, task := range registerTasks {
if err := task.Register(ctx, registry, oracles, systemClock, l1Clock, logger, m, syncValidator, txSender, gameFactory, caller, l1HeaderSource, selective, claimants); err != nil {
return closer, fmt.Errorf("failed to register %v game type: %w", task.gameType, err)
if err := task.Register(ctx, registry, oracles, systemClock, l1Clock, logger, m, txSender, gameFactory, caller, l1HeaderSource, selective, claimants); err != nil {
return clients.Close, fmt.Errorf("failed to register %v game type: %w", task.gameType, err)
}
}
return closer, nil
return clients.Close, nil
}
......@@ -33,6 +33,8 @@ type RegisterTask struct {
gameType faultTypes.GameType
skipPrestateValidation bool
syncValidator SyncValidator
getTopPrestateProvider func(ctx context.Context, prestateBlock uint64) (faultTypes.PrestateProvider, error)
getBottomPrestateProvider func(ctx context.Context, prestateHash common.Hash) (faultTypes.PrestateProvider, error)
newTraceAccessor func(
......@@ -47,10 +49,11 @@ type RegisterTask struct {
poststateBlock uint64) (*trace.Accessor, error)
}
func NewCannonRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient) *RegisterTask {
func NewCannonRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator SyncValidator) *RegisterTask {
stateConverter := cannon.NewStateConverter(cfg.Cannon)
return &RegisterTask{
gameType: gameType,
gameType: gameType,
syncValidator: syncValidator,
// Don't validate the absolute prestate or genesis output root for permissioned games
// Only trusted actors participate in these games so they aren't expected to reach the step() call and
// are often configured without valid prestates but the challenger should still resolve the games.
......@@ -84,10 +87,11 @@ func NewCannonRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m c
}
}
func NewAsteriscRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient) *RegisterTask {
func NewAsteriscRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator SyncValidator) *RegisterTask {
stateConverter := asterisc.NewStateConverter(cfg.Asterisc)
return &RegisterTask{
gameType: gameType,
gameType: gameType,
syncValidator: syncValidator,
getTopPrestateProvider: func(ctx context.Context, prestateBlock uint64) (faultTypes.PrestateProvider, error) {
return outputs.NewPrestateProvider(rollupClient, prestateBlock), nil
},
......@@ -117,10 +121,11 @@ func NewAsteriscRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m
}
}
func NewAsteriscKonaRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient) *RegisterTask {
func NewAsteriscKonaRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator SyncValidator) *RegisterTask {
stateConverter := asterisc.NewStateConverter(cfg.Asterisc)
return &RegisterTask{
gameType: gameType,
gameType: gameType,
syncValidator: syncValidator,
getTopPrestateProvider: func(ctx context.Context, prestateBlock uint64) (faultTypes.PrestateProvider, error) {
return outputs.NewPrestateProvider(rollupClient, prestateBlock), nil
},
......@@ -150,9 +155,10 @@ func NewAsteriscKonaRegisterTask(gameType faultTypes.GameType, cfg *config.Confi
}
}
func NewAlphabetRegisterTask(gameType faultTypes.GameType, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient) *RegisterTask {
func NewAlphabetRegisterTask(gameType faultTypes.GameType, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator SyncValidator) *RegisterTask {
return &RegisterTask{
gameType: gameType,
gameType: gameType,
syncValidator: syncValidator,
getTopPrestateProvider: func(ctx context.Context, prestateBlock uint64) (faultTypes.PrestateProvider, error) {
return outputs.NewPrestateProvider(rollupClient, prestateBlock), nil
},
......@@ -203,7 +209,6 @@ func (e *RegisterTask) Register(
l1Clock faultTypes.ClockReader,
logger log.Logger,
m metrics.Metricer,
syncValidator SyncValidator,
txSender TxSender,
gameFactory *contracts.DisputeGameFactoryContract,
caller *batching.MultiCaller,
......@@ -259,7 +264,7 @@ func (e *RegisterTask) Register(
validators = append(validators, NewPrestateValidator(e.gameType.String(), contract.GetAbsolutePrestateHash, vmPrestateProvider))
validators = append(validators, NewPrestateValidator("output root", contract.GetStartingRootHash, prestateProvider))
}
return NewGamePlayer(ctx, systemClock, l1Clock, logger, m, dir, game.Proxy, txSender, contract, syncValidator, validators, creator, l1HeaderSource, selective, claimants)
return NewGamePlayer(ctx, systemClock, l1Clock, logger, m, dir, game.Proxy, txSender, contract, e.syncValidator, validators, creator, l1HeaderSource, selective, claimants)
}
err := registerOracle(ctx, logger, m, oracles, gameFactory, caller, e.gameType)
if err != nil {
......
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