Commit 915e76f0 authored by EvanJRichard's avatar EvanJRichard

op-service, op-proposer, op-batcher: Add L2EndpointProvider and its first...

op-service, op-proposer, op-batcher: Add L2EndpointProvider and its first struct, StaticL2EndpointProvider.
parent 7ade8653
......@@ -17,6 +17,7 @@ import (
"github.com/ethereum-optimism/optimism/op-batcher/metrics"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-service/dial"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
)
......@@ -37,15 +38,14 @@ type RollupClient interface {
// DriverSetup is the collection of input/output interfaces and configuration that the driver operates on.
type DriverSetup struct {
Log log.Logger
Metr metrics.Metricer
RollupConfig *rollup.Config
Config BatcherConfig
Txmgr txmgr.TxManager
L1Client L1Client
L2Client L2Client
RollupClient RollupClient
ChannelConfig ChannelConfig
Log log.Logger
Metr metrics.Metricer
RollupConfig *rollup.Config
Config BatcherConfig
Txmgr txmgr.TxManager
L1Client L1Client
EndpointProvider dial.L2EndpointProvider
ChannelConfig ChannelConfig
}
// BatchSubmitter encapsulates a service responsible for submitting L2 tx
......@@ -185,7 +185,11 @@ func (l *BatchSubmitter) loadBlocksIntoState(ctx context.Context) error {
func (l *BatchSubmitter) loadBlockIntoState(ctx context.Context, blockNumber uint64) (*types.Block, error) {
ctx, cancel := context.WithTimeout(ctx, l.Config.NetworkTimeout)
defer cancel()
block, err := l.L2Client.BlockByNumber(ctx, new(big.Int).SetUint64(blockNumber))
l2Client, err := l.EndpointProvider.EthClient(ctx)
if err != nil {
return nil, fmt.Errorf("getting L2 client: %w", err)
}
block, err := l2Client.BlockByNumber(ctx, new(big.Int).SetUint64(blockNumber))
if err != nil {
return nil, fmt.Errorf("getting L2 block: %w", err)
}
......@@ -203,7 +207,11 @@ func (l *BatchSubmitter) loadBlockIntoState(ctx context.Context, blockNumber uin
func (l *BatchSubmitter) calculateL2BlockRangeToStore(ctx context.Context) (eth.BlockID, eth.BlockID, error) {
ctx, cancel := context.WithTimeout(ctx, l.Config.NetworkTimeout)
defer cancel()
syncStatus, err := l.RollupClient.SyncStatus(ctx)
rollupClient, err := l.EndpointProvider.RollupClient(ctx)
if err != nil {
return eth.BlockID{}, eth.BlockID{}, fmt.Errorf("getting rollup client: %w", err)
}
syncStatus, err := rollupClient.SyncStatus(ctx)
// Ensure that we have the sync status
if err != nil {
return eth.BlockID{}, eth.BlockID{}, fmt.Errorf("failed to get sync status: %w", err)
......
......@@ -23,7 +23,6 @@ import (
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
oppprof "github.com/ethereum-optimism/optimism/op-service/pprof"
oprpc "github.com/ethereum-optimism/optimism/op-service/rpc"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
)
......@@ -40,12 +39,11 @@ type BatcherConfig struct {
// BatcherService represents a full batch-submitter instance and its resources,
// and conforms to the op-service CLI Lifecycle interface.
type BatcherService struct {
Log log.Logger
Metrics metrics.Metricer
L1Client *ethclient.Client
L2Client *ethclient.Client
RollupNode *sources.RollupClient
TxManager txmgr.TxManager
Log log.Logger
Metrics metrics.Metricer
L1Client *ethclient.Client
EndpointProvider dial.L2EndpointProvider
TxManager txmgr.TxManager
BatcherConfig
......@@ -127,17 +125,12 @@ func (bs *BatcherService) initRPCClients(ctx context.Context, cfg *CLIConfig) er
}
bs.L1Client = l1Client
l2Client, err := dial.DialEthClientWithTimeout(ctx, dial.DefaultDialTimeout, bs.Log, cfg.L2EthRpc)
endpointProvider, err := dial.NewStaticL2EndpointProvider(ctx, bs.Log, cfg.L2EthRpc, cfg.RollupRpc)
if err != nil {
return fmt.Errorf("failed to dial L2 engine RPC: %w", err)
return fmt.Errorf("failed to create L2 endpoint provider: %w", err)
}
bs.L2Client = l2Client
bs.EndpointProvider = endpointProvider
rollupClient, err := dial.DialRollupClientWithTimeout(ctx, dial.DefaultDialTimeout, bs.Log, cfg.RollupRpc)
if err != nil {
return fmt.Errorf("failed to dial L2 rollup-client RPC: %w", err)
}
bs.RollupNode = rollupClient
return nil
}
......@@ -158,7 +151,11 @@ func (bs *BatcherService) initBalanceMonitor(cfg *CLIConfig) {
}
func (bs *BatcherService) initRollupConfig(ctx context.Context) error {
rollupConfig, err := bs.RollupNode.RollupConfig(ctx)
rollupNode, err := bs.EndpointProvider.RollupClient(ctx)
if err != nil {
return fmt.Errorf("failed to retrieve rollup client: %w", err)
}
rollupConfig, err := rollupNode.RollupConfig(ctx)
if err != nil {
return fmt.Errorf("failed to retrieve rollup config: %w", err)
}
......@@ -229,15 +226,14 @@ func (bs *BatcherService) initMetricsServer(cfg *CLIConfig) error {
func (bs *BatcherService) initDriver() {
bs.driver = NewBatchSubmitter(DriverSetup{
Log: bs.Log,
Metr: bs.Metrics,
RollupConfig: bs.RollupConfig,
Config: bs.BatcherConfig,
Txmgr: bs.TxManager,
L1Client: bs.L1Client,
L2Client: bs.L2Client,
RollupClient: bs.RollupNode,
ChannelConfig: bs.ChannelConfig,
Log: bs.Log,
Metr: bs.Metrics,
RollupConfig: bs.RollupConfig,
Config: bs.BatcherConfig,
Txmgr: bs.TxManager,
L1Client: bs.L1Client,
EndpointProvider: bs.EndpointProvider,
ChannelConfig: bs.ChannelConfig,
})
}
......@@ -329,11 +325,8 @@ func (bs *BatcherService) Stop(ctx context.Context) error {
if bs.L1Client != nil {
bs.L1Client.Close()
}
if bs.L2Client != nil {
bs.L2Client.Close()
}
if bs.RollupNode != nil {
bs.RollupNode.Close()
if bs.EndpointProvider != nil {
bs.EndpointProvider.Close()
}
if result == nil {
......
......@@ -20,6 +20,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-proposer/metrics"
"github.com/ethereum-optimism/optimism/op-proposer/proposer"
"github.com/ethereum-optimism/optimism/op-service/dial"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
)
......@@ -64,13 +65,15 @@ func NewL2Proposer(t Testing, log log.Logger, cfg *ProposerCfg, l1 *ethclient.Cl
L2OutputOracleAddr: cfg.OutputOracleAddr,
AllowNonFinalized: cfg.AllowNonFinalized,
}
rollupProvider, err := dial.NewStaticL2RollupProviderFromExistingRollup(rollupCl)
require.NoError(t, err)
driverSetup := proposer.DriverSetup{
Log: log,
Metr: metrics.NoopMetrics,
Cfg: proposerConfig,
Txmgr: fakeTxMgr{from: crypto.PubkeyToAddress(cfg.ProposerKey.PublicKey)},
L1Client: l1,
RollupClient: rollupCl,
Log: log,
Metr: metrics.NoopMetrics,
Cfg: proposerConfig,
Txmgr: fakeTxMgr{from: crypto.PubkeyToAddress(cfg.ProposerKey.PublicKey)},
L1Client: l1,
RollupProvider: rollupProvider,
}
dr, err := proposer.NewL2OutputSubmitter(driverSetup)
......
......@@ -18,6 +18,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-proposer/metrics"
"github.com/ethereum-optimism/optimism/op-service/dial"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
)
......@@ -48,8 +49,8 @@ type DriverSetup struct {
Txmgr txmgr.TxManager
L1Client L1Client
// RollupClient is used to retrieve output roots from
RollupClient RollupClient
// RollupProvider's RollupClient() is used to retrieve output roots from
RollupProvider dial.RollupProvider
}
// L2OutputSubmitter is responsible for proposing outputs
......@@ -167,7 +168,12 @@ func (l *L2OutputSubmitter) FetchNextOutputInfo(ctx context.Context) (*eth.Outpu
// Fetch the current L2 heads
cCtx, cancel = context.WithTimeout(ctx, l.Cfg.NetworkTimeout)
defer cancel()
status, err := l.RollupClient.SyncStatus(cCtx)
rollupClient, err := l.RollupProvider.RollupClient(cCtx)
if err != nil {
l.Log.Error("proposer unable to get rollup client", "err", err)
return nil, false, err
}
status, err := rollupClient.SyncStatus(cCtx)
if err != nil {
l.Log.Error("proposer unable to get sync status", "err", err)
return nil, false, err
......@@ -192,7 +198,13 @@ func (l *L2OutputSubmitter) FetchNextOutputInfo(ctx context.Context) (*eth.Outpu
func (l *L2OutputSubmitter) fetchOutput(ctx context.Context, block *big.Int) (*eth.OutputResponse, bool, error) {
ctx, cancel := context.WithTimeout(ctx, l.Cfg.NetworkTimeout)
defer cancel()
output, err := l.RollupClient.OutputAtBlock(ctx, block.Uint64())
rollupClient, err := l.RollupProvider.RollupClient(ctx)
if err != nil {
l.Log.Error("proposer unable to get rollup client", "err", err)
return nil, false, err
}
output, err := rollupClient.OutputAtBlock(ctx, block.Uint64())
if err != nil {
l.Log.Error("failed to fetch output at block %d: %w", block, err)
return nil, false, err
......
......@@ -19,7 +19,6 @@ import (
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
oppprof "github.com/ethereum-optimism/optimism/op-service/pprof"
oprpc "github.com/ethereum-optimism/optimism/op-service/rpc"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
......@@ -49,9 +48,9 @@ type ProposerService struct {
ProposerConfig
TxManager txmgr.TxManager
L1Client *ethclient.Client
RollupClient *sources.RollupClient
TxManager txmgr.TxManager
L1Client *ethclient.Client
RollupProvider dial.RollupProvider
driver *L2OutputSubmitter
......@@ -122,11 +121,11 @@ func (ps *ProposerService) initRPCClients(ctx context.Context, cfg *CLIConfig) e
}
ps.L1Client = l1Client
rollupClient, err := dial.DialRollupClientWithTimeout(ctx, dial.DefaultDialTimeout, ps.Log, cfg.RollupRpc)
rollupProvider, err := dial.NewStaticL2RollupProvider(ctx, ps.Log, cfg.RollupRpc)
if err != nil {
return fmt.Errorf("failed to dial L2 rollup-client RPC: %w", err)
return fmt.Errorf("failed to build L2 endpoint provider: %w", err)
}
ps.RollupClient = rollupClient
ps.RollupProvider = rollupProvider
return nil
}
......@@ -199,12 +198,12 @@ func (ps *ProposerService) initL2ooAddress(cfg *CLIConfig) error {
func (ps *ProposerService) initDriver() error {
driver, err := NewL2OutputSubmitter(DriverSetup{
Log: ps.Log,
Metr: ps.Metrics,
Cfg: ps.ProposerConfig,
Txmgr: ps.TxManager,
L1Client: ps.L1Client,
RollupClient: ps.RollupClient,
Log: ps.Log,
Metr: ps.Metrics,
Cfg: ps.ProposerConfig,
Txmgr: ps.TxManager,
L1Client: ps.L1Client,
RollupProvider: ps.RollupProvider,
})
if err != nil {
return err
......@@ -298,8 +297,8 @@ func (ps *ProposerService) Stop(ctx context.Context) error {
ps.L1Client.Close()
}
if ps.RollupClient != nil {
ps.RollupClient.Close()
if ps.RollupProvider != nil {
ps.RollupProvider.Close()
}
if result == nil {
......
package dial
import (
"context"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
)
// L2EndpointProvider is an interface for providing a RollupClient and l2 eth client
// It manages the lifecycle of the RollupClient and eth client for callers
// It does this by extending the RollupProvider interface to add the ability to get an EthClient
type L2EndpointProvider interface {
RollupProvider
// EthClient(ctx) returns the underlying ethclient pointing to the L2 execution node
EthClient(ctx context.Context) (*ethclient.Client, error)
}
// StaticL2EndpointProvider is a L2EndpointProvider that always returns the same static RollupClient and eth client
// It is meant for scenarios where a single, unchanging (L2 rollup node, L2 execution node) pair is used
type StaticL2EndpointProvider struct {
StaticL2RollupProvider
ethClient *ethclient.Client
}
func NewStaticL2EndpointProvider(ctx context.Context, log log.Logger, ethClientUrl string, rollupClientUrl string) (*StaticL2EndpointProvider, error) {
ethClient, err := DialEthClientWithTimeout(ctx, DefaultDialTimeout, log, ethClientUrl)
if err != nil {
return nil, err
}
rollupProvider, err := NewStaticL2RollupProvider(ctx, log, rollupClientUrl)
if err != nil {
return nil, err
}
return &StaticL2EndpointProvider{
StaticL2RollupProvider: *rollupProvider,
ethClient: ethClient,
}, nil
}
func (p *StaticL2EndpointProvider) EthClient(context.Context) (*ethclient.Client, error) {
return p.ethClient, nil
}
func (p *StaticL2EndpointProvider) Close() {
if p.ethClient != nil {
p.ethClient.Close()
}
p.StaticL2RollupProvider.Close()
}
package dial
import (
"context"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum/go-ethereum/log"
)
// RollupProvider is an interface for providing a RollupClient
// It manages the lifecycle of the RollupClient for callers
type RollupProvider interface {
// RollupClient(ctx) returns the underlying sources.RollupClient pointing to the L2 rollup consensus node
RollupClient(ctx context.Context) (*sources.RollupClient, error)
// Close() closes the underlying client or clients
Close()
}
// StaticL2RollupProvider is a RollupProvider that always returns the same static RollupClient
// It is meant for scenarios where a single, unchanging L2 rollup node is used
type StaticL2RollupProvider struct {
rollupClient *sources.RollupClient
}
func NewStaticL2RollupProvider(ctx context.Context, log log.Logger, rollupClientUrl string) (*StaticL2RollupProvider, error) {
rollupClient, err := DialRollupClientWithTimeout(ctx, DefaultDialTimeout, log, rollupClientUrl)
if err != nil {
return nil, err
}
return &StaticL2RollupProvider{
rollupClient: rollupClient,
}, nil
}
// The NewStaticL2EndpointProviderFromExistingRollup constructor is used in e2e testing
func NewStaticL2RollupProviderFromExistingRollup(rollupCl *sources.RollupClient) (*StaticL2RollupProvider, error) {
return &StaticL2RollupProvider{
rollupClient: rollupCl,
}, nil
}
func (p *StaticL2RollupProvider) RollupClient(context.Context) (*sources.RollupClient, error) {
return p.rollupClient, nil
}
func (p *StaticL2RollupProvider) Close() {
if p.rollupClient != nil {
p.rollupClient.Close()
}
}
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