Commit b2f50fa2 authored by Adrian Sutton's avatar Adrian Sutton

op-challenger: Use single L2 client instance

parent 2fb5b4ea
...@@ -26,6 +26,8 @@ var ( ...@@ -26,6 +26,8 @@ var (
alphabetGameType = uint8(255) alphabetGameType = uint8(255)
) )
type CloseFunc func()
type Registry interface { type Registry interface {
RegisterGameType(gameType uint8, creator scheduler.PlayerCreator) RegisterGameType(gameType uint8, creator scheduler.PlayerCreator)
} }
...@@ -38,16 +40,34 @@ func RegisterGameTypes( ...@@ -38,16 +40,34 @@ func RegisterGameTypes(
cfg *config.Config, cfg *config.Config,
txMgr txmgr.TxManager, txMgr txmgr.TxManager,
client *ethclient.Client, client *ethclient.Client,
) { ) (CloseFunc, error) {
var closer CloseFunc
createL2Client := func() (cannon.L2HeaderSource, error) {
l2Client, err := ethclient.DialContext(ctx, cfg.CannonL2)
if err != nil {
return nil, fmt.Errorf("dial l2 client %v: %w", cfg.CannonL2, err)
}
closer = l2Client.Close
return l2Client, nil
}
if cfg.TraceTypeEnabled(config.TraceTypeOutputCannon) { if cfg.TraceTypeEnabled(config.TraceTypeOutputCannon) {
registerOutputCannon(registry, ctx, logger, m, cfg, txMgr, client) l2Client, err := createL2Client()
if err != nil {
return nil, err
}
registerOutputCannon(registry, ctx, logger, m, cfg, txMgr, client, l2Client)
} }
if cfg.TraceTypeEnabled(config.TraceTypeCannon) { if cfg.TraceTypeEnabled(config.TraceTypeCannon) {
registerCannon(registry, ctx, logger, m, cfg, txMgr, client) l2Client, err := createL2Client()
if err != nil {
return nil, err
}
registerCannon(registry, ctx, logger, m, cfg, txMgr, client, l2Client)
} }
if cfg.TraceTypeEnabled(config.TraceTypeAlphabet) { if cfg.TraceTypeEnabled(config.TraceTypeAlphabet) {
registerAlphabet(registry, ctx, logger, m, cfg, txMgr, client) registerAlphabet(registry, ctx, logger, m, cfg, txMgr, client)
} }
return closer, nil
} }
func registerOutputCannon( func registerOutputCannon(
...@@ -57,7 +77,8 @@ func registerOutputCannon( ...@@ -57,7 +77,8 @@ func registerOutputCannon(
m metrics.Metricer, m metrics.Metricer,
cfg *config.Config, cfg *config.Config,
txMgr txmgr.TxManager, txMgr txmgr.TxManager,
client *ethclient.Client) { client *ethclient.Client,
l2Client cannon.L2HeaderSource) {
resourceCreator := func(addr common.Address, contract *contracts.FaultDisputeGameContract, gameDepth uint64, dir string) (faultTypes.TraceAccessor, gameValidator, error) { resourceCreator := func(addr common.Address, contract *contracts.FaultDisputeGameContract, gameDepth uint64, dir string) (faultTypes.TraceAccessor, gameValidator, error) {
logger := logger.New("game", addr) logger := logger.New("game", addr)
// TODO(client-pod#43): Updated contracts should expose this as the pre and post state blocks // TODO(client-pod#43): Updated contracts should expose this as the pre and post state blocks
...@@ -65,7 +86,7 @@ func registerOutputCannon( ...@@ -65,7 +86,7 @@ func registerOutputCannon(
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
accessor, err := outputs.NewOutputCannonTraceAccessor(ctx, logger, m, cfg, contract, dir, gameDepth, agreed.L2BlockNumber.Uint64(), disputed.L2BlockNumber.Uint64()) accessor, err := outputs.NewOutputCannonTraceAccessor(ctx, logger, m, cfg, l2Client, contract, dir, gameDepth, agreed.L2BlockNumber.Uint64(), disputed.L2BlockNumber.Uint64())
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
...@@ -88,10 +109,11 @@ func registerCannon( ...@@ -88,10 +109,11 @@ func registerCannon(
m metrics.Metricer, m metrics.Metricer,
cfg *config.Config, cfg *config.Config,
txMgr txmgr.TxManager, txMgr txmgr.TxManager,
client *ethclient.Client) { client *ethclient.Client,
l2Client cannon.L2HeaderSource) {
resourceCreator := func(addr common.Address, contract *contracts.FaultDisputeGameContract, gameDepth uint64, dir string) (faultTypes.TraceAccessor, gameValidator, error) { resourceCreator := func(addr common.Address, contract *contracts.FaultDisputeGameContract, gameDepth uint64, dir string) (faultTypes.TraceAccessor, gameValidator, error) {
logger := logger.New("game", addr) logger := logger.New("game", addr)
provider, err := cannon.NewTraceProvider(ctx, logger, m, cfg, contract, faultTypes.NoLocalContext, dir, gameDepth) provider, err := cannon.NewTraceProvider(ctx, logger, m, cfg, l2Client, contract, faultTypes.NoLocalContext, dir, gameDepth)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("create cannon trace provider: %w", err) return nil, nil, fmt.Errorf("create cannon trace provider: %w", err)
} }
......
...@@ -18,8 +18,7 @@ type LocalGameInputs struct { ...@@ -18,8 +18,7 @@ type LocalGameInputs struct {
L2BlockNumber *big.Int L2BlockNumber *big.Int
} }
type L2DataSource interface { type L2HeaderSource interface {
ChainID(context.Context) (*big.Int, error)
HeaderByNumber(context.Context, *big.Int) (*ethtypes.Header, error) HeaderByNumber(context.Context, *big.Int) (*ethtypes.Header, error)
} }
...@@ -32,7 +31,7 @@ type GameInputsSource interface { ...@@ -32,7 +31,7 @@ type GameInputsSource interface {
GetProposals(ctx context.Context) (agreed contracts.Proposal, disputed contracts.Proposal, err error) GetProposals(ctx context.Context) (agreed contracts.Proposal, disputed contracts.Proposal, err error)
} }
func fetchLocalInputs(ctx context.Context, caller GameInputsSource, l2Client L2DataSource) (LocalGameInputs, error) { func fetchLocalInputs(ctx context.Context, caller GameInputsSource, l2Client L2HeaderSource) (LocalGameInputs, error) {
agreedOutput, claimedOutput, err := caller.GetProposals(ctx) agreedOutput, claimedOutput, err := caller.GetProposals(ctx)
if err != nil { if err != nil {
return LocalGameInputs{}, fmt.Errorf("fetch proposals: %w", err) return LocalGameInputs{}, fmt.Errorf("fetch proposals: %w", err)
...@@ -40,7 +39,7 @@ func fetchLocalInputs(ctx context.Context, caller GameInputsSource, l2Client L2D ...@@ -40,7 +39,7 @@ func fetchLocalInputs(ctx context.Context, caller GameInputsSource, l2Client L2D
return fetchLocalInputsFromProposals(ctx, caller, l2Client, agreedOutput, claimedOutput) return fetchLocalInputsFromProposals(ctx, caller, l2Client, agreedOutput, claimedOutput)
} }
func fetchLocalInputsFromProposals(ctx context.Context, caller L1HeadSource, l2Client L2DataSource, agreedOutput contracts.Proposal, claimedOutput contracts.Proposal) (LocalGameInputs, error) { func fetchLocalInputsFromProposals(ctx context.Context, caller L1HeadSource, l2Client L2HeaderSource, agreedOutput contracts.Proposal, claimedOutput contracts.Proposal) (LocalGameInputs, error) {
l1Head, err := caller.GetL1Head(ctx) l1Head, err := caller.GetL1Head(ctx)
if err != nil { if err != nil {
return LocalGameInputs{}, fmt.Errorf("fetch L1 head: %w", err) return LocalGameInputs{}, fmt.Errorf("fetch L1 head: %w", err)
......
...@@ -14,7 +14,6 @@ import ( ...@@ -14,7 +14,6 @@ import (
"github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum-optimism/optimism/op-service/ioutil"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm"
...@@ -56,12 +55,7 @@ type CannonTraceProvider struct { ...@@ -56,12 +55,7 @@ type CannonTraceProvider struct {
lastStep uint64 lastStep uint64
} }
func NewTraceProvider(ctx context.Context, logger log.Logger, m CannonMetricer, cfg *config.Config, gameContract *contracts.FaultDisputeGameContract, localContext common.Hash, dir string, gameDepth uint64) (*CannonTraceProvider, error) { func NewTraceProvider(ctx context.Context, logger log.Logger, m CannonMetricer, cfg *config.Config, l2Client L2HeaderSource, gameContract *contracts.FaultDisputeGameContract, localContext common.Hash, dir string, gameDepth uint64) (*CannonTraceProvider, error) {
l2Client, err := ethclient.DialContext(ctx, cfg.CannonL2)
if err != nil {
return nil, fmt.Errorf("dial l2 client %v: %w", cfg.CannonL2, err)
}
defer l2Client.Close() // Not needed after fetching the inputs
localInputs, err := fetchLocalInputs(ctx, gameContract, l2Client) localInputs, err := fetchLocalInputs(ctx, gameContract, l2Client)
if err != nil { if err != nil {
return nil, fmt.Errorf("fetch local game inputs: %w", err) return nil, fmt.Errorf("fetch local game inputs: %w", err)
...@@ -74,6 +68,7 @@ func NewTraceProviderFromProposals( ...@@ -74,6 +68,7 @@ func NewTraceProviderFromProposals(
logger log.Logger, logger log.Logger,
m CannonMetricer, m CannonMetricer,
cfg *config.Config, cfg *config.Config,
l2Client L2HeaderSource,
gameContract *contracts.FaultDisputeGameContract, gameContract *contracts.FaultDisputeGameContract,
localContext common.Hash, localContext common.Hash,
agreed contracts.Proposal, agreed contracts.Proposal,
...@@ -81,11 +76,6 @@ func NewTraceProviderFromProposals( ...@@ -81,11 +76,6 @@ func NewTraceProviderFromProposals(
dir string, dir string,
gameDepth uint64, gameDepth uint64,
) (*CannonTraceProvider, error) { ) (*CannonTraceProvider, error) {
l2Client, err := ethclient.DialContext(ctx, cfg.CannonL2)
if err != nil {
return nil, fmt.Errorf("dial l2 client %v: %w", cfg.CannonL2, err)
}
defer l2Client.Close() // Not needed after fetching the inputs
localInputs, err := fetchLocalInputsFromProposals(ctx, gameContract, l2Client, agreed, claimed) localInputs, err := fetchLocalInputsFromProposals(ctx, gameContract, l2Client, agreed, claimed)
if err != nil { if err != nil {
return nil, fmt.Errorf("fetch local game inputs: %w", err) return nil, fmt.Errorf("fetch local game inputs: %w", err)
......
...@@ -21,6 +21,7 @@ func NewOutputCannonTraceAccessor( ...@@ -21,6 +21,7 @@ func NewOutputCannonTraceAccessor(
logger log.Logger, logger log.Logger,
m metrics.Metricer, m metrics.Metricer,
cfg *config.Config, cfg *config.Config,
l2Client cannon.L2HeaderSource,
contract *contracts.FaultDisputeGameContract, contract *contracts.FaultDisputeGameContract,
dir string, dir string,
gameDepth uint64, gameDepth uint64,
...@@ -38,7 +39,7 @@ func NewOutputCannonTraceAccessor( ...@@ -38,7 +39,7 @@ func NewOutputCannonTraceAccessor(
cannonCreator := func(ctx context.Context, localContext common.Hash, agreed contracts.Proposal, claimed contracts.Proposal) (types.TraceProvider, error) { cannonCreator := func(ctx context.Context, localContext common.Hash, agreed contracts.Proposal, claimed contracts.Proposal) (types.TraceProvider, error) {
logger := logger.New("pre", agreed.OutputRoot, "post", claimed.OutputRoot, "localContext", localContext) logger := logger.New("pre", agreed.OutputRoot, "post", claimed.OutputRoot, "localContext", localContext)
subdir := filepath.Join(dir, localContext.Hex()) subdir := filepath.Join(dir, localContext.Hex())
provider, err := cannon.NewTraceProviderFromProposals(ctx, logger, m, cfg, contract, localContext, agreed, claimed, subdir, bottomDepth) provider, err := cannon.NewTraceProviderFromProposals(ctx, logger, m, cfg, l2Client, contract, localContext, agreed, claimed, subdir, bottomDepth)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create cannon trace provider: %w", err) return nil, fmt.Errorf("failed to create cannon trace provider: %w", err)
} }
......
...@@ -34,6 +34,8 @@ type Service struct { ...@@ -34,6 +34,8 @@ type Service struct {
monitor *gameMonitor monitor *gameMonitor
sched *scheduler.Scheduler sched *scheduler.Scheduler
faultGamesCloser fault.CloseFunc
txMgr *txmgr.SimpleTxManager txMgr *txmgr.SimpleTxManager
loader *loader.GameLoader loader *loader.GameLoader
...@@ -83,8 +85,10 @@ func (s *Service) initFromConfig(ctx context.Context, cfg *config.Config) error ...@@ -83,8 +85,10 @@ func (s *Service) initFromConfig(ctx context.Context, cfg *config.Config) error
if err := s.initGameLoader(cfg); err != nil { if err := s.initGameLoader(cfg); err != nil {
return err return err
} }
if err := s.initScheduler(ctx, cfg); err != nil {
return err
}
s.initScheduler(ctx, cfg)
s.initMonitor(cfg) s.initMonitor(cfg)
s.metrics.RecordInfo(version.SimpleWithMeta) s.metrics.RecordInfo(version.SimpleWithMeta)
...@@ -162,12 +166,17 @@ func (s *Service) initGameLoader(cfg *config.Config) error { ...@@ -162,12 +166,17 @@ func (s *Service) initGameLoader(cfg *config.Config) error {
return nil return nil
} }
func (s *Service) initScheduler(ctx context.Context, cfg *config.Config) { func (s *Service) initScheduler(ctx context.Context, cfg *config.Config) error {
gameTypeRegistry := registry.NewGameTypeRegistry() gameTypeRegistry := registry.NewGameTypeRegistry()
fault.RegisterGameTypes(gameTypeRegistry, ctx, s.logger, s.metrics, cfg, s.txMgr, s.l1Client) closer, err := fault.RegisterGameTypes(gameTypeRegistry, ctx, s.logger, s.metrics, cfg, s.txMgr, s.l1Client)
if err != nil {
return err
}
s.faultGamesCloser = closer
disk := newDiskManager(cfg.Datadir) disk := newDiskManager(cfg.Datadir)
s.sched = scheduler.NewScheduler(s.logger, s.metrics, disk, cfg.MaxConcurrency, gameTypeRegistry.CreatePlayer) s.sched = scheduler.NewScheduler(s.logger, s.metrics, disk, cfg.MaxConcurrency, gameTypeRegistry.CreatePlayer)
return nil
} }
func (s *Service) initMonitor(cfg *config.Config) { func (s *Service) initMonitor(cfg *config.Config) {
...@@ -200,6 +209,9 @@ func (s *Service) Stop(ctx context.Context) error { ...@@ -200,6 +209,9 @@ func (s *Service) Stop(ctx context.Context) error {
if s.monitor != nil { if s.monitor != nil {
s.monitor.StopMonitoring() s.monitor.StopMonitoring()
} }
if s.faultGamesCloser != nil {
s.faultGamesCloser()
}
if s.pprofSrv != nil { if s.pprofSrv != nil {
if err := s.pprofSrv.Stop(ctx); err != nil { if err := s.pprofSrv.Stop(ctx); err != nil {
result = errors.Join(result, fmt.Errorf("failed to close pprof server: %w", err)) result = errors.Join(result, fmt.Errorf("failed to close pprof server: %w", err))
......
...@@ -47,7 +47,10 @@ func (g *CannonGameHelper) CreateHonestActor(ctx context.Context, rollupCfg *rol ...@@ -47,7 +47,10 @@ func (g *CannonGameHelper) CreateHonestActor(ctx context.Context, rollupCfg *rol
maxDepth := g.MaxDepth(ctx) maxDepth := g.MaxDepth(ctx)
gameContract, err := contracts.NewFaultDisputeGameContract(g.addr, batching.NewMultiCaller(l1Client.Client(), batching.DefaultBatchSize)) gameContract, err := contracts.NewFaultDisputeGameContract(g.addr, batching.NewMultiCaller(l1Client.Client(), batching.DefaultBatchSize))
g.require.NoError(err, "Create game contract bindings") g.require.NoError(err, "Create game contract bindings")
provider, err := cannon.NewTraceProvider(ctx, logger, metrics.NoopMetrics, cfg, gameContract, types.NoLocalContext, filepath.Join(cfg.Datadir, "honest"), uint64(maxDepth)) l2Client, err := ethclient.DialContext(ctx, cfg.CannonL2)
g.require.NoErrorf(err, "dial l2 client %v", cfg.CannonL2)
defer l2Client.Close() // Not needed after fetching the inputs
provider, err := cannon.NewTraceProvider(ctx, logger, metrics.NoopMetrics, cfg, l2Client, gameContract, types.NoLocalContext, filepath.Join(cfg.Datadir, "honest"), uint64(maxDepth))
g.require.NoError(err, "create cannon trace provider") g.require.NoError(err, "create cannon trace provider")
return &HonestHelper{ return &HonestHelper{
......
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