Commit 978355d8 authored by protolambda's avatar protolambda Committed by GitHub

op-e2e: cleanup endpoints and dialing (#11594)

* op-e2e: cleanup endpoints and dialing

* op-e2e: fix accidental wrong dial, fix endpoint-test, adjust proposer poll interval

* op-e2e: fix test deadlock, fix L1 RPC no-HTTP exception

* op-e2e: any RPC for test, HTTP mode only applied to nodes

* op-e2e: fix lint
parent 99d677fb
......@@ -13,6 +13,7 @@ import (
)
func TestArtifacts(t *testing.T) {
InitParallel(t)
logger := testlog.Logger(t, log.LevelWarn) // lower this log level to get verbose test dump of all artifacts
af := foundry.OpenArtifactsDir("../packages/contracts-bedrock/forge-artifacts")
artifacts, err := af.ListArtifacts()
......
......@@ -29,13 +29,12 @@ func TestERC20BridgeDeposits(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
log := testlog.Logger(t, log.LevelInfo)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l1Client := sys.Clients["l1"]
l2Client := sys.Clients["sequencer"]
l1Client := sys.NodeClient("l1")
l2Client := sys.NodeClient("sequencer")
opts, err := bind.NewKeyedTransactorWithChainID(sys.Cfg.Secrets.Alice, cfg.L1ChainIDBig())
require.Nil(t, err)
......
......@@ -9,23 +9,19 @@ import (
"github.com/stretchr/testify/require"
batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testlog"
)
func setupAliceAccount(t *testing.T, cfg SystemConfig, sys *System, ethPrivKey *ecdsa.PrivateKey) {
l1Client := sys.Clients["l1"]
l2Verif := sys.Clients["verifier"]
l1Client := sys.NodeClient("l1")
l2Verif := sys.NodeClient("verifier")
// Send Transaction & wait for success
fromAddr := cfg.Secrets.Addresses().Alice
......@@ -68,13 +64,12 @@ func TestBrotliBatcherFjord(t *testing.T) {
// set up batcher to use brotli
sys, err := cfg.Start(t, SystemConfigOption{"compressionAlgo", "brotli", nil})
require.Nil(t, err, "Error starting up system")
defer sys.Close()
log := testlog.Logger(t, log.LevelInfo)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
l2Seq := sys.NodeClient("sequencer")
l2Verif := sys.NodeClient("verifier")
// Transactor Account and set up the account
ethPrivKey := cfg.Secrets.Alice
......@@ -101,9 +96,7 @@ func TestBrotliBatcherFjord(t *testing.T) {
require.Equal(t, verifBlock.ParentHash(), seqBlock.ParentHash(), "Verifier and sequencer blocks parent hashes not the same after including a batch tx")
require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx")
rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.NoError(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
rollupClient := sys.RollupClient("sequencer")
// basic check that sync status works
seqStatus, err := rollupClient.SyncStatus(context.Background())
require.NoError(t, err)
......
......@@ -52,11 +52,10 @@ func TestCheckFjordScript(t *testing.T) {
sys, err := cfg.Start(t)
require.NoError(t, err, "Error starting up system")
defer sys.Close()
checkFjordConfig := &fjordChecks.CheckFjordConfig{
Log: log,
L2: sys.Clients["sequencer"],
L2: sys.NodeClient("sequencer"),
Key: sys.Cfg.Secrets.Alice,
Addr: sys.Cfg.Secrets.Addresses().Alice,
}
......
......@@ -35,9 +35,9 @@ func TestCustomGasToken(t *testing.T) {
sys, err := cfg.Start(t)
require.NoError(t, err, "Error starting up system")
defer sys.Close()
l1Client := sys.Clients["l1"]
l2Client := sys.Clients["sequencer"]
l1Client := sys.NodeClient("l1")
l2Client := sys.NodeClient("sequencer")
aliceOpts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Alice, cfg.L1ChainIDBig())
require.NoError(t, err)
......@@ -134,7 +134,7 @@ func TestCustomGasToken(t *testing.T) {
// and assert token balance is increased on L1.
checkWithdrawal := func(t *testing.T) {
l2Seq := l2Client
l2Verif := sys.Clients["verifier"]
l2Verif := sys.NodeClient("verifier")
fromAddr := aliceOpts.From
ethPrivKey := cfg.Secrets.Alice
......@@ -463,7 +463,7 @@ func callViaSafe(opts *bind.TransactOpts, client *ethclient.Client, safeAddress
// It reads existing parameters from the SystemConfig contract, inserts the supplied cgtAddress and reinitializes that contract.
// To do this it uses the ProxyAdmin and StorageSetter from the supplied cfg.
func setCustomGasToken(t *testing.T, cfg SystemConfig, sys *System, cgtAddress common.Address) {
l1Client := sys.Clients["l1"]
l1Client := sys.NodeClient("l1")
deployerOpts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Deployer, cfg.L1ChainIDBig())
require.NoError(t, err)
......@@ -581,7 +581,7 @@ func setCustomGasToken(t *testing.T, cfg SystemConfig, sys *System, cgtAddress c
depositTx, err := derive.UnmarshalDepositLogEvent(&depositEvent.Raw)
require.NoError(t, err)
l2Client := sys.Clients["sequencer"]
l2Client := sys.NodeClient("sequencer")
receipt, err = wait.ForReceiptOK(context.Background(), l2Client, types.NewTx(depositTx).Hash())
require.NoError(t, err)
......
......@@ -21,10 +21,9 @@ func TestMintOnRevertedDeposit(t *testing.T) {
delete(cfg.Nodes, "verifier")
sys, err := cfg.Start(t)
require.NoError(t, err, "Error starting up system")
defer sys.Close()
l1Client := sys.Clients["l1"]
l2Verif := sys.Clients["sequencer"]
l1Client := sys.NodeClient("l1")
l2Verif := sys.NodeClient("sequencer")
// create signer
aliceKey := cfg.Secrets.Alice
......@@ -82,10 +81,9 @@ func TestDepositTxCreateContract(t *testing.T) {
sys, err := cfg.Start(t)
require.NoError(t, err, "Error starting up system")
defer sys.Close()
l1Client := sys.Clients["l1"]
l2Client := sys.Clients["sequencer"]
l1Client := sys.NodeClient("l1")
l2Client := sys.NodeClient("sequencer")
opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Alice, cfg.L1ChainIDBig())
require.NoError(t, err)
......
......@@ -11,7 +11,6 @@ import (
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-service/metrics"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require"
......@@ -26,13 +25,15 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-service/cliapp"
"github.com/ethereum-optimism/optimism/op-service/endpoint"
"github.com/ethereum-optimism/optimism/op-service/metrics"
"github.com/ethereum-optimism/optimism/op-service/testlog"
)
type EndpointProvider interface {
NodeEndpoint(name string) string
RollupEndpoint(name string) string
L1BeaconEndpoint() string
NodeEndpoint(name string) endpoint.RPC
RollupEndpoint(name string) endpoint.RPC
L1BeaconEndpoint() endpoint.RestHTTP
}
type Helper struct {
......@@ -155,9 +156,9 @@ func NewChallenger(t *testing.T, ctx context.Context, sys EndpointProvider, name
func NewChallengerConfig(t *testing.T, sys EndpointProvider, l2NodeName string, options ...Option) *config.Config {
// Use the NewConfig method to ensure we pick up any defaults that are set.
l1Endpoint := sys.NodeEndpoint("l1")
l1Beacon := sys.L1BeaconEndpoint()
cfg := config.NewConfig(common.Address{}, l1Endpoint, l1Beacon, sys.RollupEndpoint(l2NodeName), sys.NodeEndpoint(l2NodeName), t.TempDir())
l1Endpoint := sys.NodeEndpoint("l1").RPC()
l1Beacon := sys.L1BeaconEndpoint().RestHTTP()
cfg := config.NewConfig(common.Address{}, l1Endpoint, l1Beacon, sys.RollupEndpoint(l2NodeName).RPC(), sys.NodeEndpoint(l2NodeName).RPC(), t.TempDir())
// The devnet can't set the absolute prestate output root because the contracts are deployed in L1 genesis
// before the L2 genesis is known.
cfg.AllowInvalidPrestate = true
......
......@@ -19,6 +19,7 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-service/endpoint"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
......@@ -70,10 +71,10 @@ func WithFutureProposal() GameOpt {
}
type DisputeSystem interface {
L1BeaconEndpoint() string
NodeEndpoint(name string) string
L1BeaconEndpoint() endpoint.RestHTTP
NodeEndpoint(name string) endpoint.RPC
NodeClient(name string) *ethclient.Client
RollupEndpoint(name string) string
RollupEndpoint(name string) endpoint.RPC
RollupClient(name string) *sources.RollupClient
L1Deployments() *genesis.L1Deployments
......
......@@ -2,10 +2,8 @@ package geth
import (
"fmt"
"math/big"
"time"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
......@@ -22,11 +20,13 @@ import (
// Force-load the tracer engines to trigger registration
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
"github.com/ethereum-optimism/optimism/op-service/clock"
)
func InitL1(chainID uint64, blockTime uint64, finalizedDistance uint64, genesis *core.Genesis, c clock.Clock, blobPoolDir string, beaconSrv Beacon, opts ...GethOption) (*node.Node, *eth.Ethereum, error) {
func InitL1(blockTime uint64, finalizedDistance uint64, genesis *core.Genesis, c clock.Clock, blobPoolDir string, beaconSrv Beacon, opts ...GethOption) (*GethInstance, error) {
ethConfig := &ethconfig.Config{
NetworkId: chainID,
NetworkId: genesis.Config.ChainID.Uint64(),
Genesis: genesis,
BlobPool: blobpool.Config{
Datadir: blobPoolDir,
......@@ -53,24 +53,24 @@ func InitL1(chainID uint64, blockTime uint64, finalizedDistance uint64, genesis
HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"},
}
l1Node, l1Eth, err := createGethNode(false, nodeConfig, ethConfig, opts...)
gethInstance, err := createGethNode(false, nodeConfig, ethConfig, opts...)
if err != nil {
return nil, nil, err
return nil, err
}
// Instead of running a whole beacon node, we run this fake-proof-of-stake sidecar that sequences L1 blocks using the Engine API.
l1Node.RegisterLifecycle(&fakePoS{
gethInstance.Node.RegisterLifecycle(&fakePoS{
clock: c,
eth: l1Eth,
eth: gethInstance.Backend,
log: log.Root(), // geth logger is global anyway. Would be nice to replace with a local logger though.
blockTime: blockTime,
finalizedDistance: finalizedDistance,
safeDistance: 4,
engineAPI: catalyst.NewConsensusAPI(l1Eth),
engineAPI: catalyst.NewConsensusAPI(gethInstance.Backend),
beacon: beaconSrv,
})
return l1Node, l1Eth, nil
return gethInstance, nil
}
func defaultNodeConfig(name string, jwtPath string) *node.Config {
......@@ -91,9 +91,9 @@ func defaultNodeConfig(name string, jwtPath string) *node.Config {
type GethOption func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error
// InitL2 inits a L2 geth node.
func InitL2(name string, l2ChainID *big.Int, genesis *core.Genesis, jwtPath string, opts ...GethOption) (*node.Node, *eth.Ethereum, error) {
func InitL2(name string, genesis *core.Genesis, jwtPath string, opts ...GethOption) (*GethInstance, error) {
ethConfig := &ethconfig.Config{
NetworkId: l2ChainID.Uint64(),
NetworkId: genesis.Config.ChainID.Uint64(),
Genesis: genesis,
StateScheme: rawdb.HashScheme,
Miner: miner.Config{
......@@ -113,10 +113,10 @@ func InitL2(name string, l2ChainID *big.Int, genesis *core.Genesis, jwtPath stri
// The private keys are added to the keystore and are unlocked.
// If the node is l2, catalyst is enabled.
// The node should be started and then closed when done.
func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, opts ...GethOption) (*node.Node, *eth.Ethereum, error) {
func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, opts ...GethOption) (*GethInstance, error) {
for i, opt := range opts {
if err := opt(ethCfg, nodeCfg); err != nil {
return nil, nil, fmt.Errorf("failed to apply geth option %d: %w", i, err)
return nil, fmt.Errorf("failed to apply geth option %d: %w", i, err)
}
}
ethCfg.StateScheme = rawdb.HashScheme
......@@ -124,13 +124,13 @@ func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, opt
n, err := node.New(nodeCfg)
if err != nil {
n.Close()
return nil, nil, err
return nil, err
}
backend, err := eth.New(n, ethCfg)
if err != nil {
n.Close()
return nil, nil, err
return nil, err
}
......@@ -144,8 +144,11 @@ func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, opt
if l2 {
if err := catalyst.Register(n, backend); err != nil {
n.Close()
return nil, nil, err
return nil, err
}
}
return n, backend, nil
return &GethInstance{
Backend: backend,
Node: n,
}, nil
}
package geth
import (
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/services"
"github.com/ethereum-optimism/optimism/op-service/endpoint"
)
type GethInstance struct {
Backend *eth.Ethereum
Node *node.Node
}
var _ services.EthInstance = (*GethInstance)(nil)
func (gi *GethInstance) UserRPC() endpoint.RPC {
fallback := endpoint.WsOrHttpRPC{
WsURL: gi.Node.WSEndpoint(),
HttpURL: gi.Node.HTTPEndpoint(),
}
srv, err := gi.Node.RPCHandler()
if err != nil {
return fallback
}
return &endpoint.ServerRPC{
Fallback: fallback,
Server: srv,
}
}
func (gi *GethInstance) AuthRPC() endpoint.RPC {
// TODO: can we rely on the in-process RPC server to support the auth namespaces?
return endpoint.WsOrHttpRPC{
WsURL: gi.Node.WSAuthEndpoint(),
HttpURL: gi.Node.HTTPAuthEndpoint(),
}
}
func (gi *GethInstance) Close() error {
return gi.Node.Close()
}
package opnode
import (
"context"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/services"
"github.com/ethereum-optimism/optimism/op-node/metrics"
rollupNode "github.com/ethereum-optimism/optimism/op-node/node"
"github.com/ethereum-optimism/optimism/op-node/p2p"
"github.com/ethereum-optimism/optimism/op-service/cliapp"
"github.com/ethereum-optimism/optimism/op-service/endpoint"
)
type Opnode struct {
node *rollupNode.OpNode
}
func (o *Opnode) UserRPC() endpoint.RPC {
return endpoint.HttpURL(o.node.HTTPEndpoint())
}
func (o *Opnode) Stop(ctx context.Context) error {
return o.node.Stop(ctx)
}
func (o *Opnode) Stopped() bool {
return o.node.Stopped()
}
func (o *Opnode) RuntimeConfig() rollupNode.ReadonlyRuntimeConfig {
return o.node.RuntimeConfig()
}
func (o *Opnode) P2P() p2p.Node {
return o.node.P2P()
}
var _ services.RollupNode = (*Opnode)(nil)
func NewOpnode(l log.Logger, c *rollupNode.Config, errFn func(error)) (*Opnode, error) {
var cycle cliapp.Lifecycle
c.Cancel = func(errCause error) {
l.Warn("node requested early shutdown!", "err", errCause)
go func() {
postCtx, postCancel := context.WithCancel(context.Background())
postCancel() // don't allow the stopping to continue for longer than needed
if err := cycle.Stop(postCtx); err != nil {
errFn(err)
}
l.Warn("closed op-node!")
}()
}
node, err := rollupNode.New(context.Background(), c, l, "", metrics.NewMetrics(""))
if err != nil {
return nil, err
}
cycle = node
err = node.Start(context.Background())
if err != nil {
return nil, err
}
return &Opnode{node: node}, nil
}
package services
import (
"context"
rollupNode "github.com/ethereum-optimism/optimism/op-node/node"
"github.com/ethereum-optimism/optimism/op-node/p2p"
"github.com/ethereum-optimism/optimism/op-service/endpoint"
)
// EthInstance is either an in process Geth or external process exposing its
// endpoints over the network
type EthInstance interface {
UserRPC() endpoint.RPC
AuthRPC() endpoint.RPC
Close() error
}
type RollupNode interface {
UserRPC() endpoint.RPC
Stop(ctx context.Context) error
Stopped() bool
RuntimeConfig() rollupNode.ReadonlyRuntimeConfig
P2P() p2p.Node
}
......@@ -10,26 +10,22 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags"
"github.com/ethereum-optimism/optimism/op-e2e/bindings"
gethutils "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum-optimism/optimism/op-service/testutils"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
)
// TestSystem4844E2E runs the SystemE2E test with 4844 enabled on L1, and active on the rollup in
......@@ -64,7 +60,7 @@ func testSystem4844E2E(t *testing.T, multiBlob bool, daType batcherFlags.DataAva
// front. This lets us test the ability for the batcher to clear out the incompatible
// transaction. The hook used here makes sure we make the jamming call before batch submission
// is started, as is required by the function.
jamChan := make(chan error)
var jamChan chan error
jamCtx, jamCancel := context.WithTimeout(context.Background(), 20*time.Second)
action := SystemConfigOption{
key: "beforeBatcherStart",
......@@ -72,26 +68,28 @@ func testSystem4844E2E(t *testing.T, multiBlob bool, daType batcherFlags.DataAva
driver := s.BatchSubmitter.TestDriver()
err := driver.JamTxPool(jamCtx)
require.NoError(t, err)
jamChan = make(chan error)
go func() {
jamChan <- driver.WaitOnJammingTx(jamCtx)
}()
},
}
defer func() {
if jamChan != nil { // only check if we actually got to a successful batcher start
jamCancel()
require.NoError(t, <-jamChan, "jam tx error")
}
}()
sys, err := cfg.Start(t, action)
require.NoError(t, err, "Error starting up system")
defer sys.Close()
log := testlog.Logger(t, log.LevelInfo)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
l2Verif := sys.NodeClient("verifier")
// Transactor Account
ethPrivKey := cfg.Secrets.Alice
......@@ -144,9 +142,7 @@ func testSystem4844E2E(t *testing.T, multiBlob bool, daType batcherFlags.DataAva
require.Equal(t, verifBlock.ParentHash(), seqBlock.ParentHash(), "Verifier and sequencer blocks parent hashes not the same after including a batch tx")
require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx")
rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.NoError(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
rollupClient := sys.RollupClient("sequencer")
// basic check that sync status works
seqStatus, err := rollupClient.SyncStatus(context.Background())
require.NoError(t, err)
......@@ -258,12 +254,11 @@ func TestBatcherAutoDA(t *testing.T) {
sys, err := cfg.Start(t)
require.NoError(t, err, "Error starting up system")
defer sys.Close()
log := testlog.Logger(t, log.LevelInfo)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l1Client := sys.Clients["l1"]
l1Client := sys.NodeClient("l1")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
......
......@@ -12,6 +12,7 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-e2e/external"
"github.com/ethereum-optimism/optimism/op-service/endpoint"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
......@@ -34,20 +35,18 @@ type ExternalEthClient struct {
Endpoints external.Endpoints
}
func (eec *ExternalEthClient) HTTPEndpoint() string {
return eec.Endpoints.HTTPEndpoint
}
func (eec *ExternalEthClient) WSEndpoint() string {
return eec.Endpoints.WSEndpoint
}
func (eec *ExternalEthClient) HTTPAuthEndpoint() string {
return eec.Endpoints.HTTPAuthEndpoint
func (eec *ExternalEthClient) UserRPC() endpoint.RPC {
return endpoint.WsOrHttpRPC{
WsURL: eec.Endpoints.WSEndpoint,
HttpURL: eec.Endpoints.HTTPEndpoint,
}
}
func (eec *ExternalEthClient) WSAuthEndpoint() string {
return eec.Endpoints.WSAuthEndpoint
func (eec *ExternalEthClient) AuthRPC() endpoint.RPC {
return endpoint.WsOrHttpRPC{
WsURL: eec.Endpoints.WSAuthEndpoint,
HttpURL: eec.Endpoints.HTTPAuthEndpoint,
}
}
func (eec *ExternalEthClient) Close() error {
......
......@@ -9,9 +9,11 @@ import (
"testing"
"time"
"github.com/stretchr/testify/require"
e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-service/endpoint"
)
func TestShim(t *testing.T) {
......@@ -41,13 +43,13 @@ func TestShim(t *testing.T) {
}).Run(t)
t.Cleanup(func() { _ = ec.Close() })
for _, endpoint := range []string{
ec.HTTPEndpoint(),
ec.HTTPAuthEndpoint(),
ec.WSEndpoint(),
ec.WSAuthEndpoint(),
for _, rpcEndpoint := range []string{
ec.UserRPC().(endpoint.HttpRPC).HttpRPC(),
ec.AuthRPC().(endpoint.HttpRPC).HttpRPC(),
ec.UserRPC().(endpoint.WsRPC).WsRPC(),
ec.AuthRPC().(endpoint.WsRPC).WsRPC(),
} {
plainURL, err := url.ParseRequestURI(endpoint)
plainURL, err := url.ParseRequestURI(rpcEndpoint)
require.NoError(t, err)
_, err = net.DialTimeout("tcp", plainURL.Host, time.Second)
require.NoError(t, err, "could not connect to HTTP port")
......
......@@ -18,7 +18,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
......@@ -27,9 +26,7 @@ import (
op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-e2e/bindings"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/predeploys"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testlog"
)
......@@ -50,16 +47,13 @@ func TestBenchmarkCannon_FPP(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
log := testlog.Logger(t, log.LevelInfo)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.Nil(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
rollupClient := sys.RollupClient("sequencer")
require.NoError(t, wait.ForUnsafeBlock(ctx, rollupClient, 1))
// Agreed state: 200 Big Contracts deployed at max size - total codesize is 5.90 MB
......
......@@ -14,7 +14,6 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded"
......@@ -26,9 +25,7 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testlog"
)
......@@ -90,17 +87,13 @@ func TestPrecompiles(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
log := testlog.Logger(t, log.LevelInfo)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.Nil(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
rollupClient := sys.RollupClient("sequencer")
aliceKey := cfg.Secrets.Alice
t.Log("Capture current L2 head as agreed starting point")
......@@ -147,9 +140,8 @@ func TestPrecompiles(t *testing.T) {
}
ctx := context.Background()
sys, _ := StartFaultDisputeSystem(t, WithBlobBatches())
defer sys.Close()
l2Seq := sys.Clients["sequencer"]
l2Seq := sys.NodeClient("sequencer")
aliceKey := sys.Cfg.Secrets.Alice
receipt := op_e2e.SendL2Tx(t, sys.Cfg, l2Seq, aliceKey, func(opts *op_e2e.TxOpts) {
opts.Gas = 1_000_000
......@@ -194,17 +186,13 @@ func TestGranitePrecompiles(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
log := testlog.Logger(t, log.LevelInfo)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.Nil(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
rollupClient := sys.RollupClient("sequencer")
aliceKey := cfg.Secrets.Alice
t.Log("Capture current L2 head as agreed starting point")
......@@ -258,10 +246,10 @@ func TestGranitePrecompiles(t *testing.T) {
}
func runCannon(t *testing.T, ctx context.Context, sys *op_e2e.System, inputs utils.LocalGameInputs, l2Node string, extraVmArgs ...string) {
l1Endpoint := sys.NodeEndpoint("l1")
l1Beacon := sys.L1BeaconEndpoint()
rollupEndpoint := sys.RollupEndpoint("sequencer")
l2Endpoint := sys.NodeEndpoint("sequencer")
l1Endpoint := sys.NodeEndpoint("l1").RPC()
l1Beacon := sys.L1BeaconEndpoint().RestHTTP()
rollupEndpoint := sys.RollupEndpoint("sequencer").RPC()
l2Endpoint := sys.NodeEndpoint("sequencer").RPC()
cannonOpts := challenger.WithCannon(t, sys.RollupCfg(), sys.L2Genesis())
dir := t.TempDir()
proofsDir := filepath.Join(dir, "cannon-proofs")
......
......@@ -61,11 +61,11 @@ func StartFaultDisputeSystem(t *testing.T, opts ...faultDisputeConfigOpts) (*op_
}
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
return sys, sys.Clients["l1"]
return sys, sys.NodeClient("l1")
}
func SendKZGPointEvaluationTx(t *testing.T, sys *op_e2e.System, l2Node string, privateKey *ecdsa.PrivateKey) *types.Receipt {
return op_e2e.SendL2Tx(t, sys.Cfg, sys.Clients[l2Node], privateKey, func(opts *op_e2e.TxOpts) {
return op_e2e.SendL2Tx(t, sys.Cfg, sys.NodeClient(l2Node), privateKey, func(opts *op_e2e.TxOpts) {
precompile := common.BytesToAddress([]byte{0x0a})
opts.Gas = 100_000
opts.ToAddr = &precompile
......
......@@ -21,8 +21,8 @@ func TestTxGossip(t *testing.T) {
sys, err := cfg.Start(t)
require.NoError(t, err, "Start system")
seqClient := sys.Clients["sequencer"]
verifClient := sys.Clients["verifier"]
seqClient := sys.NodeClient("sequencer")
verifClient := sys.NodeClient("verifier")
geth.ConnectP2P(t, seqClient, verifClient)
// This prevents the below tx-sending from flaking in CI
......
......@@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"math/big"
"reflect"
"testing"
......@@ -12,6 +11,7 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/services"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-service/client"
......@@ -39,7 +39,7 @@ var (
// OpGeth is an actor that functions as a l2 op-geth node
// It provides useful functions for advancing and querying the chain
type OpGeth struct {
node EthInstance
node services.EthInstance
l2Engine *sources.EngineClient
L2Client *ethclient.Client
SystemConfig eth.SystemConfig
......@@ -85,11 +85,11 @@ func NewOpGeth(t testing.TB, ctx context.Context, cfg *SystemConfig) (*OpGeth, e
SystemConfig: e2eutils.SystemConfigFromDeployConfig(cfg.DeployConfig),
}
var node EthInstance
var node services.EthInstance
if cfg.ExternalL2Shim == "" {
gethNode, _, err := geth.InitL2("l2", big.NewInt(int64(cfg.DeployConfig.L2ChainID)), l2Genesis, cfg.JWTFilePath)
gethNode, err := geth.InitL2("l2", l2Genesis, cfg.JWTFilePath)
require.NoError(t, err)
require.NoError(t, gethNode.Start())
require.NoError(t, gethNode.Node.Start())
node = gethNode
} else {
externalNode := (&ExternalRunner{
......@@ -102,7 +102,7 @@ func NewOpGeth(t testing.TB, ctx context.Context, cfg *SystemConfig) (*OpGeth, e
}
auth := rpc.WithHTTPAuth(gn.NewJWTAuth(cfg.JWTSecret))
l2Node, err := client.NewRPC(ctx, logger, node.WSAuthEndpoint(), client.WithGethRPCOptions(auth))
l2Node, err := client.NewRPC(ctx, logger, node.AuthRPC().RPC(), client.WithGethRPCOptions(auth))
require.NoError(t, err)
// Finally create the engine client
......@@ -117,7 +117,7 @@ func NewOpGeth(t testing.TB, ctx context.Context, cfg *SystemConfig) (*OpGeth, e
)
require.NoError(t, err)
l2Client, err := ethclient.Dial(selectEndpoint(node))
l2Client, err := ethclient.Dial(node.UserRPC().RPC())
require.NoError(t, err)
genesisPayload, err := eth.BlockAsPayload(l2GenesisBlock, cfg.DeployConfig.CanyonTime(l2GenesisBlock.Time()))
......
......@@ -59,7 +59,6 @@ func TestTxGasSameAsBlockGasLimit(t *testing.T) {
cfg := DefaultSystemConfig(t)
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
ethPrivKey := sys.Cfg.Secrets.Alice
tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{
......@@ -68,7 +67,7 @@ func TestTxGasSameAsBlockGasLimit(t *testing.T) {
})
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
l2Seq := sys.Clients["sequencer"]
l2Seq := sys.NodeClient("sequencer")
err = l2Seq.SendTransaction(ctx, tx)
require.ErrorContains(t, err, txpool.ErrGasLimit.Error())
}
......
......@@ -82,7 +82,7 @@ func setupSequencerFailoverTest(t *testing.T) (*System, map[string]*conductor, f
// start sequencing on leader
lid, _ := findLeader(t, conductors)
unsafeHead, err := sys.Clients[lid].BlockByNumber(ctx, nil)
unsafeHead, err := sys.NodeClient(lid).BlockByNumber(ctx, nil)
require.NoError(t, err)
require.Equal(t, uint64(0), unsafeHead.NumberU64())
require.NoError(t, sys.RollupClient(lid).StartSequencer(ctx, unsafeHead.Hash()))
......@@ -93,9 +93,9 @@ func setupSequencerFailoverTest(t *testing.T) (*System, map[string]*conductor, f
// weirdly, batcher does not submit a batch until unsafe block 9.
// It became normal after that and submits a batch every L1 block (2s) per configuration.
// Since our health monitor checks on safe head progression, wait for batcher to become normal before proceeding.
_, err = wait.ForNextSafeBlock(ctx, sys.Clients[Sequencer1Name])
_, err = wait.ForNextSafeBlock(ctx, sys.NodeClient(Sequencer1Name))
require.NoError(t, err)
_, err = wait.ForNextSafeBlock(ctx, sys.Clients[Sequencer1Name])
_, err = wait.ForNextSafeBlock(ctx, sys.NodeClient(Sequencer1Name))
require.NoError(t, err)
// make sure conductor reports all sequencers as healthy, this means they're syncing correctly.
......@@ -189,8 +189,8 @@ func setupHAInfra(t *testing.T, ctx context.Context) (*System, map[string]*condu
}
for _, cfg := range conductorCfgs {
cfg := cfg
nodePRC := sys.RollupNodes[cfg.name].HTTPEndpoint()
engineRPC := sys.EthInstances[cfg.name].HTTPEndpoint()
nodePRC := sys.RollupNodes[cfg.name].UserRPC().RPC()
engineRPC := sys.EthInstances[cfg.name].UserRPC().RPC()
if conductors[cfg.name], err = setupConductor(t, cfg.name, t.TempDir(), nodePRC, engineRPC, cfg.port, cfg.bootstrap, *sys.RollupConfig); err != nil {
return nil, nil, err
}
......@@ -252,6 +252,7 @@ func setupConductor(
if err != nil {
return nil, err
}
t.Cleanup(rawClient.Close)
client := conrpc.NewAPIClient(rawClient)
return &conductor{
......@@ -277,7 +278,7 @@ func setupBatcher(t *testing.T, sys *System, conductors map[string]*conductor) {
conductors[Sequencer3Name].RPCEndpoint(),
}, ",")
batcherCLIConfig := &bss.CLIConfig{
L1EthRpc: sys.EthInstances["l1"].WSEndpoint(),
L1EthRpc: sys.EthInstances["l1"].UserRPC().RPC(),
L2EthRpc: l2EthRpc,
RollupRpc: rollupRpc,
MaxPendingTransactions: 0,
......@@ -287,7 +288,7 @@ func setupBatcher(t *testing.T, sys *System, conductors map[string]*conductor) {
ApproxComprRatio: 0.4,
SubSafetyMargin: 4,
PollInterval: 1 * time.Second,
TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), sys.Cfg.Secrets.Batcher),
TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].UserRPC().RPC(), sys.Cfg.Secrets.Batcher),
LogConfig: oplog.CLIConfig{
Level: log.LevelDebug,
Format: oplog.FormatText,
......
......@@ -100,8 +100,8 @@ func TestSequencerFailover_ConductorRPC(t *testing.T) {
nonvoter, err := retry.Do[*conductor](ctx, maxSetupRetries, retryStrategy, func() (*conductor, error) {
return setupConductor(
t, VerifierName, t.TempDir(),
sys.RollupEndpoint(Sequencer3Name),
sys.NodeEndpoint(Sequencer3Name),
sys.RollupEndpoint(Sequencer3Name).RPC(),
sys.NodeEndpoint(Sequencer3Name).RPC(),
findAvailablePort(t),
false,
*sys.RollupConfig,
......
......@@ -16,9 +16,9 @@ import (
"testing"
"time"
"github.com/stretchr/testify/require"
"golang.org/x/exp/maps"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/batcher"
ds "github.com/ipfs/go-datastore"
dsSync "github.com/ipfs/go-datastore/sync"
ic "github.com/libp2p/go-libp2p/core/crypto"
......@@ -28,13 +28,11 @@ import (
"github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem"
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
ma "github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
geth_eth "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
......@@ -46,10 +44,12 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/batcher"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/fakebeacon"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/opnode"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/services"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/metrics"
rollupNode "github.com/ethereum-optimism/optimism/op-node/node"
"github.com/ethereum-optimism/optimism/op-node/p2p"
"github.com/ethereum-optimism/optimism/op-node/p2p/store"
......@@ -58,10 +58,10 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup/driver"
"github.com/ethereum-optimism/optimism/op-node/rollup/sync"
l2os "github.com/ethereum-optimism/optimism/op-proposer/proposer"
"github.com/ethereum-optimism/optimism/op-service/cliapp"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum-optimism/optimism/op-service/dial"
"github.com/ethereum-optimism/optimism/op-service/endpoint"
"github.com/ethereum-optimism/optimism/op-service/eth"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum-optimism/optimism/op-service/predeploys"
......@@ -306,41 +306,6 @@ type SystemConfig struct {
MaxPendingTransactions uint64
}
type GethInstance struct {
Backend *geth_eth.Ethereum
Node *node.Node
}
func (gi *GethInstance) HTTPEndpoint() string {
return gi.Node.HTTPEndpoint()
}
func (gi *GethInstance) WSEndpoint() string {
return gi.Node.WSEndpoint()
}
func (gi *GethInstance) WSAuthEndpoint() string {
return gi.Node.WSAuthEndpoint()
}
func (gi *GethInstance) HTTPAuthEndpoint() string {
return gi.Node.HTTPAuthEndpoint()
}
func (gi *GethInstance) Close() error {
return gi.Node.Close()
}
// EthInstance is either an in process Geth or external process exposing its
// endpoints over the network
type EthInstance interface {
HTTPEndpoint() string
WSEndpoint() string
HTTPAuthEndpoint() string
WSAuthEndpoint() string
Close() error
}
type System struct {
Cfg SystemConfig
......@@ -349,15 +314,13 @@ type System struct {
L2GenesisCfg *core.Genesis
// Connections to running nodes
EthInstances map[string]EthInstance
Clients map[string]*ethclient.Client
RawClients map[string]*rpc.Client
RollupNodes map[string]*rollupNode.OpNode
EthInstances map[string]services.EthInstance
RollupNodes map[string]services.RollupNode
L2OutputSubmitter *l2os.ProposerService
BatchSubmitter *bss.BatcherService
Mocknet mocknet.Mocknet
L1BeaconAPIAddr string
L1BeaconAPIAddr endpoint.RestHTTP
// TimeTravelClock is nil unless SystemConfig.SupportL1TimeTravel was set to true
// It provides access to the clock instance used by the L1 node. Calling TimeTravelClock.AdvanceBy
......@@ -369,8 +332,13 @@ type System struct {
t *testing.T
closed atomic.Bool
// rollupClients caches the lazily created RollupClient instances so they can be reused and closed
// rollupClients caches the lazily created RollupClient
// instances so they can be reused and closed
rollupClients map[string]*sources.RollupClient
// clients caches lazily created L1/L2 ethclient.Client
// instances so they can be reused and closed
clients map[string]*ethclient.Client
}
func (sys *System) Config() SystemConfig { return sys.Cfg }
......@@ -383,38 +351,29 @@ func (sys *System) AdvanceTime(d time.Duration) {
}
}
func (sys *System) L1BeaconEndpoint() string {
func (sys *System) L1BeaconEndpoint() endpoint.RestHTTP {
return sys.L1BeaconAPIAddr
}
func (sys *System) L1BeaconHTTPClient() *sources.BeaconHTTPClient {
logger := testlog.Logger(sys.t, log.LevelInfo).New("component", "beaconClient")
return sources.NewBeaconHTTPClient(client.NewBasicHTTPClient(sys.L1BeaconEndpoint(), logger))
}
func (sys *System) NodeEndpoint(name string) string {
return selectEndpoint(sys.EthInstances[name])
return sources.NewBeaconHTTPClient(client.NewBasicHTTPClient(sys.L1BeaconEndpoint().RestHTTP(), logger))
}
func (sys *System) NodeClient(name string) *ethclient.Client {
return sys.Clients[name]
}
func (sys *System) RollupEndpoint(name string) string {
return sys.RollupNodes[name].HTTPEndpoint()
func (sys *System) NodeEndpoint(name string) endpoint.RPC {
ethInst, ok := sys.EthInstances[name]
if !ok {
sys.t.Fatalf("unknown eth instance: %s", name)
}
return ethInst.UserRPC()
}
func (sys *System) RollupClient(name string) *sources.RollupClient {
client, ok := sys.rollupClients[name]
if ok {
return client
func (sys *System) RollupEndpoint(name string) endpoint.RPC {
rNode, ok := sys.RollupNodes[name]
if !ok {
sys.t.Fatalf("unknown rollup node instance: %s", name)
}
logger := testlog.Logger(sys.t, log.LevelInfo).New("rollupClient", name)
endpoint := sys.RollupEndpoint(name)
client, err := dial.DialRollupClientWithTimeout(context.Background(), 30*time.Second, logger, endpoint)
require.NoErrorf(sys.t, err, "Failed to dial rollup client %v", name)
sys.rollupClients[name] = client
return client
return rNode.UserRPC()
}
func (sys *System) L1Deployments() *genesis.L1Deployments {
......@@ -435,6 +394,7 @@ func (sys *System) L1Slot(l1Timestamp uint64) uint64 {
}
func (sys *System) Close() {
sys.t.Log("CLOSING")
if !sys.closed.CompareAndSwap(false, true) {
// Already closed.
return
......@@ -464,6 +424,9 @@ func (sys *System) Close() {
combinedErr = errors.Join(combinedErr, fmt.Errorf("stop EthInstance %v: %w", name, err))
}
}
for _, client := range sys.clients {
client.Close()
}
for _, client := range sys.rollupClients {
client.Close()
}
......@@ -515,10 +478,9 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
sys := &System{
t: t,
Cfg: cfg,
EthInstances: make(map[string]EthInstance),
Clients: make(map[string]*ethclient.Client),
RawClients: make(map[string]*rpc.Client),
RollupNodes: make(map[string]*rollupNode.OpNode),
EthInstances: make(map[string]services.EthInstance),
RollupNodes: make(map[string]services.RollupNode),
clients: make(map[string]*ethclient.Client),
rollupClients: make(map[string]*sources.RollupClient),
}
// Automatically stop the system at the end of the test
......@@ -629,40 +591,33 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
require.NoError(t, bcn.Start("127.0.0.1:0"))
beaconApiAddr := bcn.BeaconAddr()
require.NotEmpty(t, beaconApiAddr, "beacon API listener must be up")
sys.L1BeaconAPIAddr = beaconApiAddr
sys.L1BeaconAPIAddr = endpoint.RestHTTPURL(beaconApiAddr)
// Initialize nodes
l1Node, l1Backend, err := geth.InitL1(cfg.DeployConfig.L1ChainID,
l1Geth, err := geth.InitL1(
cfg.DeployConfig.L1BlockTime, cfg.L1FinalizedDistance, l1Genesis, c,
path.Join(cfg.BlobsPath, "l1_el"), bcn, cfg.GethOptions[RoleL1]...)
if err != nil {
return nil, err
}
sys.EthInstances[RoleL1] = &GethInstance{
Backend: l1Backend,
Node: l1Node,
}
err = l1Node.Start()
sys.EthInstances[RoleL1] = l1Geth
err = l1Geth.Node.Start()
if err != nil {
return nil, err
}
for name := range cfg.Nodes {
var ethClient EthInstance
var ethClient services.EthInstance
if cfg.ExternalL2Shim == "" {
node, backend, err := geth.InitL2(name, big.NewInt(int64(cfg.DeployConfig.L2ChainID)), l2Genesis, cfg.JWTFilePath, cfg.GethOptions[name]...)
l2Geth, err := geth.InitL2(name, l2Genesis, cfg.JWTFilePath, cfg.GethOptions[name]...)
if err != nil {
return nil, err
}
gethInst := &GethInstance{
Backend: backend,
Node: node,
}
err = gethInst.Node.Start()
err = l2Geth.Node.Start()
if err != nil {
return nil, err
}
ethClient = gethInst
ethClient = l2Geth
} else {
if len(cfg.GethOptions[name]) > 0 {
t.Skip("External L2 nodes do not support configuration through GethOptions")
......@@ -684,31 +639,11 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
configureL1(nodeCfg, sys.EthInstances[RoleL1], sys.L1BeaconEndpoint())
configureL2(nodeCfg, sys.EthInstances[name], cfg.JWTSecret)
if sys.RollupConfig.EcotoneTime != nil {
nodeCfg.Beacon = &rollupNode.L1BeaconEndpointConfig{BeaconAddr: sys.L1BeaconAPIAddr}
}
}
// Geth Clients
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
l1Srv, err := l1Node.RPCHandler()
if err != nil {
return nil, err
}
rawL1Client := rpc.DialInProc(l1Srv)
l1Client := ethclient.NewClient(rawL1Client)
sys.Clients[RoleL1] = l1Client
sys.RawClients[RoleL1] = rawL1Client
for name, ethInst := range sys.EthInstances {
rawClient, err := rpc.DialContext(ctx, ethInst.WSEndpoint())
if err != nil {
return nil, err
nodeCfg.Beacon = &rollupNode.L1BeaconEndpointConfig{BeaconAddr: sys.L1BeaconAPIAddr.RestHTTP()}
}
client := ethclient.NewClient(rawClient)
sys.RawClients[name] = rawClient
sys.Clients[name] = client
}
l1Client := sys.NodeClient(RoleL1)
_, err = geth.WaitForBlock(big.NewInt(2), l1Client, 6*time.Second*time.Duration(cfg.DeployConfig.L1BlockTime))
if err != nil {
return nil, fmt.Errorf("waiting for blocks: %w", err)
......@@ -787,28 +722,13 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
c.Rollup.LogDescription(cfg.Loggers[name], chaincfg.L2ChainIDToNetworkDisplayName)
l := cfg.Loggers[name]
var cycle cliapp.Lifecycle
c.Cancel = func(errCause error) {
l.Warn("node requested early shutdown!", "err", errCause)
go func() {
postCtx, postCancel := context.WithCancel(context.Background())
postCancel() // don't allow the stopping to continue for longer than needed
if err := cycle.Stop(postCtx); err != nil {
n, err := opnode.NewOpnode(l, &c, func(err error) {
t.Error(err)
}
l.Warn("closed op-node!")
}()
}
node, err := rollupNode.New(context.Background(), &c, l, "", metrics.NewMetrics(""))
if err != nil {
return nil, err
}
cycle = node
err = node.Start(context.Background())
if err != nil {
return nil, err
}
sys.RollupNodes[name] = node
})
require.NoError(t, err)
sys.RollupNodes[name] = n
if action, ok := opts.Get("afterRollupNodeStart", name); ok {
action(&cfg, sys)
......@@ -845,13 +765,13 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
var proposerCLIConfig *l2os.CLIConfig
if e2eutils.UseFaultProofs() {
proposerCLIConfig = &l2os.CLIConfig{
L1EthRpc: sys.EthInstances[RoleL1].WSEndpoint(),
RollupRpc: sys.RollupNodes[RoleSeq].HTTPEndpoint(),
L1EthRpc: sys.EthInstances[RoleL1].UserRPC().RPC(),
RollupRpc: sys.RollupNodes[RoleSeq].UserRPC().RPC(),
DGFAddress: config.L1Deployments.DisputeGameFactoryProxy.Hex(),
ProposalInterval: 6 * time.Second,
DisputeGameType: 254, // Fast game type
PollInterval: 50 * time.Millisecond,
TxMgrConfig: newTxMgrConfig(sys.EthInstances[RoleL1].WSEndpoint(), cfg.Secrets.Proposer),
PollInterval: 500 * time.Millisecond,
TxMgrConfig: newTxMgrConfig(sys.EthInstances[RoleL1].UserRPC().RPC(), cfg.Secrets.Proposer),
AllowNonFinalized: cfg.NonFinalizedProposals,
LogConfig: oplog.CLIConfig{
Level: log.LvlInfo,
......@@ -860,11 +780,11 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
}
} else {
proposerCLIConfig = &l2os.CLIConfig{
L1EthRpc: sys.EthInstances[RoleL1].WSEndpoint(),
RollupRpc: sys.RollupNodes[RoleSeq].HTTPEndpoint(),
L1EthRpc: sys.EthInstances[RoleL1].UserRPC().RPC(),
RollupRpc: sys.RollupNodes[RoleSeq].UserRPC().RPC(),
L2OOAddress: config.L1Deployments.L2OutputOracleProxy.Hex(),
PollInterval: 50 * time.Millisecond,
TxMgrConfig: newTxMgrConfig(sys.EthInstances[RoleL1].WSEndpoint(), cfg.Secrets.Proposer),
PollInterval: 500 * time.Millisecond,
TxMgrConfig: newTxMgrConfig(sys.EthInstances[RoleL1].UserRPC().RPC(), cfg.Secrets.Proposer),
AllowNonFinalized: cfg.NonFinalizedProposals,
LogConfig: oplog.CLIConfig{
Level: log.LvlInfo,
......@@ -900,9 +820,9 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
}
batcherCLIConfig := &bss.CLIConfig{
L1EthRpc: sys.EthInstances[RoleL1].WSEndpoint(),
L2EthRpc: sys.EthInstances[RoleSeq].WSEndpoint(),
RollupRpc: sys.RollupNodes[RoleSeq].HTTPEndpoint(),
L1EthRpc: sys.EthInstances[RoleL1].UserRPC().RPC(),
L2EthRpc: sys.EthInstances[RoleSeq].UserRPC().RPC(),
RollupRpc: sys.RollupNodes[RoleSeq].UserRPC().RPC(),
MaxPendingTransactions: cfg.MaxPendingTransactions,
MaxChannelDuration: 1,
MaxL1TxSize: batcherMaxL1TxSizeBytes,
......@@ -911,7 +831,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
ApproxComprRatio: 0.4,
SubSafetyMargin: 4,
PollInterval: 50 * time.Millisecond,
TxMgrConfig: newTxMgrConfig(sys.EthInstances[RoleL1].WSEndpoint(), cfg.Secrets.Batcher),
TxMgrConfig: newTxMgrConfig(sys.EthInstances[RoleL1].UserRPC().RPC(), cfg.Secrets.Batcher),
LogConfig: oplog.CLIConfig{
Level: log.LevelInfo,
Format: oplog.FormatText,
......@@ -999,22 +919,9 @@ func (sys *System) TestAccount(idx int) *ecdsa.PrivateKey {
}
}
func UseHTTP() bool {
return os.Getenv("OP_E2E_USE_HTTP") == "true"
}
func selectEndpoint(node EthInstance) string {
if UseHTTP() {
log.Info("using HTTP client")
return node.HTTPEndpoint()
}
return node.WSEndpoint()
}
func configureL1(rollupNodeCfg *rollupNode.Config, l1Node EthInstance, beaconEndpoint string) {
l1EndpointConfig := selectEndpoint(l1Node)
func configureL1(rollupNodeCfg *rollupNode.Config, l1Node services.EthInstance, beaconEndpoint endpoint.RestHTTP) {
rollupNodeCfg.L1 = &rollupNode.L1EndpointConfig{
L1NodeAddr: l1EndpointConfig,
L1NodeAddr: endpoint.SelectRPC(EnvRPCPreference(), l1Node.UserRPC()),
L1TrustRPC: false,
L1RPCKind: sources.RPCKindStandard,
RateLimit: 0,
......@@ -1023,23 +930,13 @@ func configureL1(rollupNodeCfg *rollupNode.Config, l1Node EthInstance, beaconEnd
MaxConcurrency: 10,
}
rollupNodeCfg.Beacon = &rollupNode.L1BeaconEndpointConfig{
BeaconAddr: beaconEndpoint,
BeaconAddr: beaconEndpoint.RestHTTP(),
}
}
type WSOrHTTPEndpoint interface {
WSAuthEndpoint() string
HTTPAuthEndpoint() string
}
func configureL2(rollupNodeCfg *rollupNode.Config, l2Node WSOrHTTPEndpoint, jwtSecret [32]byte) {
l2EndpointConfig := l2Node.WSAuthEndpoint()
if UseHTTP() {
l2EndpointConfig = l2Node.HTTPAuthEndpoint()
}
func configureL2(rollupNodeCfg *rollupNode.Config, l2Node services.EthInstance, jwtSecret [32]byte) {
rollupNodeCfg.L2 = &rollupNode.L2EndpointConfig{
L2EngineAddr: l2EndpointConfig,
L2EngineAddr: endpoint.SelectRPC(EnvRPCPreference(), l2Node.AuthRPC()),
L2EngineJWTSecret: jwtSecret,
}
}
......@@ -1056,3 +953,47 @@ func hexPriv(in *ecdsa.PrivateKey) string {
b := e2eutils.EncodePrivKey(in)
return hexutil.Encode(b)
}
func (sys *System) RollupClient(name string) *sources.RollupClient {
rollupClient, ok := sys.rollupClients[name]
if ok {
return rollupClient
}
rpcClient := endpoint.DialRPC(endpoint.PreferAnyRPC, sys.RollupEndpoint(name), func(v string) *rpc.Client {
logger := testlog.Logger(sys.t, log.LevelInfo).New("rollupClient", name)
cl, err := dial.DialRPCClientWithTimeout(context.Background(), 30*time.Second, logger, v)
require.NoError(sys.t, err, "failed to dial rollup instance %s", name)
return cl
})
rollupClient = sources.NewRollupClient(client.NewBaseRPCClient(rpcClient))
sys.rollupClients[name] = rollupClient
return rollupClient
}
func (sys *System) NodeClient(name string) *ethclient.Client {
nodeClient, ok := sys.clients[name]
if ok {
return nodeClient
}
rpcCl := endpoint.DialRPC(endpoint.PreferAnyRPC, sys.NodeEndpoint(name), func(v string) *rpc.Client {
logger := testlog.Logger(sys.t, log.LevelInfo).New("node", name)
cl, err := dial.DialRPCClientWithTimeout(context.Background(), 30*time.Second, logger, v)
require.NoError(sys.t, err, "failed to dial eth node instance %s", name)
return cl
})
nodeClient = ethclient.NewClient(rpcCl)
sys.clients[name] = nodeClient
return nodeClient
}
// EnvRPCPreference reads the type of RPC that should be used.
// Some E2E tests are forced to run with HTTP,
// since HTTP does not support subscriptions, which thus could affect functionality.
// The alternative E2E tests are labeled "ws", but really just any transport here is the same.
func EnvRPCPreference() endpoint.RPCPreference {
// L1 is a legacy exception; the System setup itself depends on RPC subscriptions.
if os.Getenv("OP_E2E_USE_HTTP") == "true" {
return endpoint.PreferHttpRPC
}
return endpoint.PreferAnyRPC
}
......@@ -23,14 +23,10 @@ func TestStopStartSequencer(t *testing.T) {
cfg := DefaultSystemConfig(t)
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
l2Seq := sys.Clients["sequencer"]
rollupNode := sys.RollupNodes["sequencer"]
l2Seq := sys.NodeClient("sequencer")
nodeRPC, err := rpc.DialContext(context.Background(), rollupNode.HTTPEndpoint())
require.Nil(t, err, "Error dialing node")
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(nodeRPC))
rollupClient := sys.RollupClient("sequencer")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
......@@ -91,11 +87,10 @@ func TestPersistSequencerStateWhenChanged(t *testing.T) {
sys, err := cfg.Start(t)
require.NoError(t, err)
defer sys.Close()
assertPersistedSequencerState(t, stateFile, node.StateStarted)
rollupRPCClient, err := rpc.DialContext(ctx, sys.RollupNodes["sequencer"].HTTPEndpoint())
rollupRPCClient, err := rpc.DialContext(ctx, sys.RollupNodes["sequencer"].UserRPC().RPC())
require.Nil(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
......@@ -126,9 +121,8 @@ func TestLoadSequencerStateOnStarted_Stopped(t *testing.T) {
sys, err := cfg.Start(t)
require.NoError(t, err)
defer sys.Close()
rollupRPCClient, err := rpc.DialContext(ctx, sys.RollupNodes["sequencer"].HTTPEndpoint())
rollupRPCClient, err := rpc.DialContext(ctx, sys.RollupNodes["sequencer"].UserRPC().RPC())
require.Nil(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
......@@ -160,9 +154,8 @@ func TestLoadSequencerStateOnStarted_Started(t *testing.T) {
sys, err := cfg.Start(t)
require.NoError(t, err)
defer sys.Close()
rollupRPCClient, err := rpc.DialContext(ctx, sys.RollupNodes["sequencer"].HTTPEndpoint())
rollupRPCClient, err := rpc.DialContext(ctx, sys.RollupNodes["sequencer"].UserRPC().RPC())
require.Nil(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
......@@ -185,10 +178,9 @@ func TestPostUnsafePayload(t *testing.T) {
sys, err := cfg.Start(t)
require.NoError(t, err)
defer sys.Close()
l2Seq := sys.Clients["sequencer"]
l2Ver := sys.Clients["verifier"]
l2Seq := sys.NodeClient("sequencer")
l2Ver := sys.NodeClient("verifier")
rollupClient := sys.RollupClient("verifier")
require.NoError(t, wait.ForBlock(ctx, l2Seq, 2), "Chain did not advance after starting sequencer")
......
......@@ -20,8 +20,6 @@ import (
"github.com/ethereum-optimism/optimism/op-program/client/claim"
opp "github.com/ethereum-optimism/optimism/op-program/host"
oppconf "github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testlog"
)
......@@ -101,16 +99,13 @@ func testVerifyL2OutputRootEmptyBlock(t *testing.T, detached bool, spanBatchActi
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
log := testlog.Logger(t, log.LevelInfo)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.Nil(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
rollupClient := sys.RollupClient("sequencer")
// Avoids flaky test by avoiding reorgs at epoch 0
t.Log("Wait for safe head to advance once for setup")
......@@ -201,16 +196,14 @@ func testVerifyL2OutputRoot(t *testing.T, detached bool, spanBatchActivated bool
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
log := testlog.Logger(t, log.LevelInfo)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.Nil(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
rollupClient := sys.RollupClient("sequencer")
t.Log("Sending transactions to setup existing state, prior to challenged period")
aliceKey := cfg.Secrets.Alice
......@@ -286,8 +279,8 @@ type FaultProofProgramTestScenario struct {
func testFaultProofProgramScenario(t *testing.T, ctx context.Context, sys *System, s *FaultProofProgramTestScenario) {
preimageDir := t.TempDir()
fppConfig := oppconf.NewConfig(sys.RollupConfig, sys.L2GenesisCfg.Config, s.L1Head, s.L2Head, s.L2OutputRoot, common.Hash(s.L2Claim), s.L2ClaimBlockNumber)
fppConfig.L1URL = sys.NodeEndpoint("l1")
fppConfig.L2URL = sys.NodeEndpoint("sequencer")
fppConfig.L1URL = sys.NodeEndpoint("l1").RPC()
fppConfig.L2URL = sys.NodeEndpoint("sequencer").RPC()
fppConfig.DataDir = preimageDir
if s.Detached {
// When running in detached mode we need to compile the client executable since it will be called directly.
......
......@@ -11,9 +11,9 @@ import (
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
metrics2 "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
......@@ -28,9 +28,8 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
metrics2 "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics"
"github.com/ethereum-optimism/optimism/op-e2e/bindings"
"github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth"
......@@ -42,11 +41,12 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-node/rollup/driver"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/endpoint"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/oppprof"
"github.com/ethereum-optimism/optimism/op-service/predeploys"
"github.com/ethereum-optimism/optimism/op-service/retry"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/testlog"
)
......@@ -104,13 +104,10 @@ func TestL2OutputSubmitter(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
l1Client := sys.Clients["l1"]
l1Client := sys.NodeClient("l1")
rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.Nil(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
rollupClient := sys.RollupClient("sequencer")
// OutputOracle is already deployed
l2OutputOracle, err := bindings.NewL2OutputOracleCaller(cfg.L1Deployments.L2OutputOracleProxy, l1Client)
......@@ -124,7 +121,7 @@ func TestL2OutputSubmitter(t *testing.T) {
// when it creates it's first block and uses and old L1 Origin. It then does not submit a batch
// for that block and subsequently reorgs to match what the verifier derives when running the
// reconcillation process.
l2Verif := sys.Clients["verifier"]
l2Verif := sys.NodeClient("verifier")
_, err = geth.WaitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second)
require.Nil(t, err)
......@@ -173,13 +170,10 @@ func TestL2OutputSubmitterFaultProofs(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
l1Client := sys.Clients["l1"]
l1Client := sys.NodeClient("l1")
rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.Nil(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
rollupClient := sys.RollupClient("sequencer")
disputeGameFactory, err := bindings.NewDisputeGameFactoryCaller(cfg.L1Deployments.DisputeGameFactoryProxy, l1Client)
require.Nil(t, err)
......@@ -187,7 +181,7 @@ func TestL2OutputSubmitterFaultProofs(t *testing.T) {
initialGameCount, err := disputeGameFactory.GameCount(&bind.CallOpts{})
require.Nil(t, err)
l2Verif := sys.Clients["verifier"]
l2Verif := sys.NodeClient("verifier")
_, err = geth.WaitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second)
require.Nil(t, err)
......@@ -233,9 +227,9 @@ func TestSystemE2EDencunAtGenesis(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
runE2ESystemTest(t, sys)
head, err := sys.Clients["l1"].BlockByNumber(context.Background(), big.NewInt(0))
head, err := sys.NodeClient("l1").BlockByNumber(context.Background(), big.NewInt(0))
require.NoError(t, err)
require.NotNil(t, head.ExcessBlobGas(), "L1 is building dencun blocks since genesis")
}
......@@ -252,7 +246,6 @@ func TestSystemE2EDencunAtGenesisWithBlobs(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
// send a blob-containing txn on l1
ethPrivKey := sys.Cfg.Secrets.Alice
......@@ -262,14 +255,14 @@ func TestSystemE2EDencunAtGenesisWithBlobs(t *testing.T) {
sendCtx, sendCancel := context.WithTimeout(context.Background(), 15*time.Second)
defer sendCancel()
l1Client := sys.Clients["l1"]
l1Client := sys.NodeClient("l1")
err = l1Client.SendTransaction(sendCtx, tx)
require.NoError(t, err, "Sending L1 empty blob tx")
// Wait for transaction on L1
blockContainsBlob, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash())
require.Nil(t, err, "Waiting for blob tx on L1")
// end sending blob-containing txns on l1
l2Client := sys.Clients["sequencer"]
l2Client := sys.NodeClient("sequencer")
finalizedBlock, err := geth.WaitForL1OriginOnL2(sys.RollupConfig, blockContainsBlob.BlockNumber.Uint64(), l2Client, 30*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L1 origin of blob tx on L2")
finalizationTimeout := 30 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second
......@@ -287,16 +280,16 @@ func TestSystemE2E(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
runE2ESystemTest(t, sys)
defer sys.Close()
}
func runE2ESystemTest(t *testing.T, sys *System) {
log := testlog.Logger(t, log.LevelInfo)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
l2Verif := sys.NodeClient("verifier")
// Transactor Account
ethPrivKey := sys.Cfg.Secrets.Alice
......@@ -344,9 +337,7 @@ func runE2ESystemTest(t *testing.T, sys *System) {
require.Equal(t, verifBlock.ParentHash(), seqBlock.ParentHash(), "Verifier and sequencer blocks parent hashes not the same after including a batch tx")
require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx")
rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.Nil(t, err)
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient))
rollupClient := sys.RollupClient("sequencer")
// basic check that sync status works
seqStatus, err := rollupClient.SyncStatus(context.Background())
require.Nil(t, err)
......@@ -372,14 +363,13 @@ func TestConfirmationDepth(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
log := testlog.Logger(t, log.LevelInfo)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
l2Verif := sys.NodeClient("verifier")
// Wait enough time for the sequencer to submit a block with distance from L1 head, submit it,
// and for the slower verifier to read a full sequence window and cover confirmation depth for reading and some margin
......@@ -430,13 +420,12 @@ func TestPendingGasLimit(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
log := testlog.Logger(t, log.LevelInfo)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l2Verif := sys.Clients["verifier"]
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.NodeClient("verifier")
l2Seq := sys.NodeClient("sequencer")
checkGasLimit := func(client *ethclient.Client, number *big.Int, expected uint64) *types.Header {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
......@@ -472,9 +461,8 @@ func TestFinalize(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
l2Seq := sys.Clients["sequencer"]
l2Seq := sys.NodeClient("sequencer")
l2Finalized, err := geth.WaitForBlockToBeFinalized(big.NewInt(12), l2Seq, 1*time.Minute)
require.NoError(t, err, "must be able to fetch a finalized L2 block")
......@@ -496,13 +484,11 @@ func TestMissingBatchE2E(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
seqRollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.Nil(t, err)
seqRollupClient := sources.NewRollupClient(client.NewBaseRPCClient(seqRollupRPCClient))
l2Seq := sys.NodeClient("sequencer")
l2Verif := sys.NodeClient("verifier")
seqRollupClient := sys.RollupClient("sequencer")
// Transactor Account
ethPrivKey := cfg.Secrets.Alice
......@@ -646,11 +632,9 @@ func TestSystemMockP2P(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
// Enable the sequencer now that everyone is ready to receive payloads.
rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.Nil(t, err)
rollupClient := sys.RollupClient("sequencer")
verifierPeerID := sys.RollupNodes["verifier"].P2P().Host().ID()
check := func() bool {
......@@ -669,10 +653,10 @@ func TestSystemMockP2P(t *testing.T) {
}
require.True(t, check(), "verifier must be meshed with sequencer for gossip test to proceed")
require.NoError(t, rollupRPCClient.Call(nil, "admin_startSequencer", sys.L2GenesisCfg.ToBlock().Hash()))
require.NoError(t, rollupClient.StartSequencer(context.Background(), sys.L2GenesisCfg.ToBlock().Hash()))
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
l2Seq := sys.NodeClient("sequencer")
l2Verif := sys.NodeClient("verifier")
// Transactor Account
ethPrivKey := cfg.Secrets.Alice
......@@ -747,9 +731,8 @@ func TestSystemP2PAltSync(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
l2Seq := sys.Clients["sequencer"]
l2Seq := sys.NodeClient("sequencer")
// Transactor Account
ethPrivKey := cfg.Secrets.Alice
......@@ -797,9 +780,9 @@ func TestSystemP2PAltSync(t *testing.T) {
},
}
configureL1(syncNodeCfg, sys.EthInstances["l1"], sys.L1BeaconEndpoint())
syncerL2Engine, _, err := geth.InitL2("syncer", big.NewInt(int64(cfg.DeployConfig.L2ChainID)), sys.L2GenesisCfg, cfg.JWTFilePath)
syncerL2Engine, err := geth.InitL2("syncer", sys.L2GenesisCfg, cfg.JWTFilePath)
require.NoError(t, err)
require.NoError(t, syncerL2Engine.Start())
require.NoError(t, syncerL2Engine.Node.Start())
configureL2(syncNodeCfg, syncerL2Engine, cfg.JWTSecret)
......@@ -817,7 +800,7 @@ func TestSystemP2PAltSync(t *testing.T) {
_, err = sys.Mocknet.ConnectPeers(sys.RollupNodes["bob"].P2P().Host().ID(), syncerNode.P2P().Host().ID())
require.NoError(t, err)
rpc := syncerL2Engine.Attach()
rpc := syncerL2Engine.UserRPC().(endpoint.ClientRPC).ClientRPC()
l2Verif := ethclient.NewClient(rpc)
// It may take a while to sync, but eventually we should see the sequenced data show up
......@@ -903,12 +886,11 @@ func TestSystemDenseTopology(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
l2Verif2 := sys.Clients["verifier2"]
l2Verif3 := sys.Clients["verifier3"]
l2Seq := sys.NodeClient("sequencer")
l2Verif := sys.NodeClient("verifier")
l2Verif2 := sys.NodeClient("verifier2")
l2Verif3 := sys.NodeClient("verifier3")
// Transactor Account
ethPrivKey := cfg.Secrets.Alice
......@@ -943,11 +925,10 @@ func TestL1InfoContract(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
l2Verif := sys.NodeClient("verifier")
endVerifBlockNumber := big.NewInt(4)
endSeqBlockNumber := big.NewInt(6)
......@@ -1054,7 +1035,6 @@ func TestWithdrawals(t *testing.T) {
sys, err := cfg.Start(t)
require.NoError(t, err, "Error starting up system")
defer sys.Close()
RunWithdrawalsTest(t, sys)
}
......@@ -1115,11 +1095,10 @@ func TestFees(t *testing.T) {
func testFees(t *testing.T, cfg SystemConfig) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
l1 := sys.Clients["l1"]
l2Seq := sys.NodeClient("sequencer")
l2Verif := sys.NodeClient("verifier")
l1 := sys.NodeClient("l1")
// Wait for first block after genesis. The genesis block has zero L1Block values and will throw off the GPO checks
_, err = geth.WaitForBlock(big.NewInt(1), l2Verif, time.Minute)
......@@ -1304,12 +1283,11 @@ func StopStartBatcher(t *testing.T, cfgMod func(*SystemConfig)) {
cfgMod(&cfg)
sys, err := cfg.Start(t)
require.NoError(t, err, "Error starting up system")
defer sys.Close()
rollupClient := sys.RollupClient("verifier")
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
l2Seq := sys.NodeClient("sequencer")
l2Verif := sys.NodeClient("verifier")
// retrieve the initial sync status
seqStatus, err := rollupClient.SyncStatus(context.Background())
......@@ -1390,10 +1368,9 @@ func TestBatcherMultiTx(t *testing.T) {
cfg.DisableBatcher = true
sys, err := cfg.Start(t)
require.NoError(t, err, "Error starting up system")
defer sys.Close()
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
_, err = geth.WaitForBlock(big.NewInt(10), l2Seq, time.Duration(cfg.DeployConfig.L2BlockTime*15)*time.Second)
require.NoError(t, err, "Waiting for L2 blocks")
......@@ -1440,8 +1417,8 @@ func TestPendingBlockIsLatest(t *testing.T) {
cfg := DefaultSystemConfig(t)
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
l2Seq := sys.Clients["sequencer"]
l2Seq := sys.NodeClient("sequencer")
t.Run("block", func(t *testing.T) {
for i := 0; i < 10; i++ {
......@@ -1485,13 +1462,13 @@ func TestRuntimeConfigReload(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
initialRuntimeConfig := sys.RollupNodes["verifier"].RuntimeConfig()
// close the EL node, since we want to block derivation, to solely rely on the reloading mechanism for updates.
sys.EthInstances["verifier"].Close()
l1 := sys.Clients["l1"]
l1 := sys.NodeClient("l1")
// Change the system-config via L1
sysCfgContract, err := bindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1)
......@@ -1530,11 +1507,11 @@ func TestRecommendedProtocolVersionChange(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
runtimeConfig := sys.RollupNodes["verifier"].RuntimeConfig()
// Change the superchain-config via L1
l1 := sys.Clients["l1"]
l1 := sys.NodeClient("l1")
_, build, major, minor, patch, preRelease := params.OPStackSupport.Parse()
newRecommendedProtocolVersion := params.ProtocolVersionV0{Build: build, Major: major + 1, Minor: minor, Patch: patch, PreRelease: preRelease}.Encode()
......@@ -1585,11 +1562,11 @@ func TestRequiredProtocolVersionChangeAndHalt(t *testing.T) {
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
runtimeConfig := sys.RollupNodes["verifier"].RuntimeConfig()
// Change the superchain-config via L1
l1 := sys.Clients["l1"]
l1 := sys.NodeClient("l1")
_, build, major, minor, patch, preRelease := params.OPStackSupport.Parse()
newRequiredProtocolVersion := params.ProtocolVersionV0{Build: build, Major: major + 1, Minor: minor, Patch: patch, PreRelease: preRelease}.Encode()
......@@ -1622,13 +1599,13 @@ func TestRequiredProtocolVersionChangeAndHalt(t *testing.T) {
// Checking if the engine is down is not trivial in op-e2e.
// In op-geth we have halting tests covering the Engine API, in op-e2e we instead check if the API stops.
_, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
_, err := sys.Clients["verifier"].ChainID(ctx)
cancel()
if err != nil && !errors.Is(err, ctx.Err()) { // waiting for client to stop responding to chainID requests
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
available := client.IsURLAvailable(ctx, sys.NodeEndpoint("verifier").(endpoint.HttpRPC).HttpRPC())
if !available && ctx.Err() == nil { // waiting for client to stop responding to RPC requests (slow dials with timeout don't count)
return struct{}{}, nil
}
return struct{}{}, errors.New("verifier rollup node is not closed yet")
return struct{}{}, errors.New("verifier EL node is not closed yet")
})
require.NoError(t, err)
t.Log("verified that op-geth closed!")
......
......@@ -52,12 +52,11 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) {
cfg := DefaultSystemConfig(t)
sys, err := cfg.Start(t)
require.NoError(t, err, "Error starting up system")
defer sys.Close()
// Obtain our sequencer, verifier, and transactor keypair.
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
// l2Verif := sys.Clients["verifier"]
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
// l2Verif := sys.NodeClient("verifier")
ethPrivKey := cfg.Secrets.SysCfgOwner
// Bind to the SystemConfig & GasPriceOracle contracts
......@@ -128,11 +127,10 @@ func TestL2SequencerRPCDepositTx(t *testing.T) {
cfg := DefaultSystemConfig(t)
sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
// Obtain our sequencer, verifier, and transactor keypair.
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
l2Seq := sys.NodeClient("sequencer")
l2Verif := sys.NodeClient("verifier")
txSigningKey := sys.Cfg.Secrets.Alice
require.Nil(t, err)
......@@ -237,12 +235,11 @@ func TestMixedDepositValidity(t *testing.T) {
cfg := DefaultSystemConfig(t)
sys, testAccounts, err := startConfigWithTestAccounts(t, &cfg, accountUsedToDeposit)
require.Nil(t, err, "Error starting up system")
defer sys.Close()
// Obtain our sequencer, verifier, and transactor keypair.
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
l2Verif := sys.NodeClient("verifier")
require.NoError(t, err)
// Define our L1 transaction timeout duration.
......@@ -408,12 +405,11 @@ func TestMixedWithdrawalValidity(t *testing.T) {
require.Equal(t, cfg.DeployConfig.FundDevAccounts, true)
sys, err := cfg.Start(t)
require.NoError(t, err, "error starting up system")
defer sys.Close()
// Obtain our sequencer, verifier, and transactor keypair.
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
l2Verif := sys.NodeClient("verifier")
require.NoError(t, err)
systemConfig, err := legacybindings.NewSystemConfigCaller(cfg.L1Deployments.SystemConfigProxy, l1Client)
......@@ -554,7 +550,7 @@ func TestMixedWithdrawalValidity(t *testing.T) {
header, err = l2Verif.HeaderByNumber(ctx, new(big.Int).SetUint64(blockNumber))
require.Nil(t, err)
rpcClient, err := rpc.Dial(sys.EthInstances["verifier"].WSEndpoint())
rpcClient, err := rpc.Dial(sys.EthInstances["verifier"].UserRPC().RPC())
require.Nil(t, err)
proofCl := gethclient.New(rpcClient)
receiptCl := ethclient.NewClient(rpcClient)
......
package endpoint
// RestHTTP is an interface for an endpoint to provide flexibility.
// By default the RestHTTP just returns an REST-ful HTTP endpoint string.
// But the RestHTTP can implement one or more extension interfaces,
// to provide alternative ways of establishing a connection,
// or even a fully initialized client binding.
type RestHTTP interface {
RestHTTP() string
}
// RestHTTPURL is an HTTP endpoint URL string
type RestHTTPURL string
func (url RestHTTPURL) RestHTTP() string {
return string(url)
}
package endpoint
import (
"github.com/ethereum/go-ethereum/rpc"
)
// RPC is an interface for an endpoint to provide flexibility.
// By default the RPC just returns an RPC endpoint string.
// But the RPC can implement one or more extension interfaces,
// to provide alternative ways of establishing a connection,
// or even a fully initialized client binding.
type RPC interface {
RPC() string
}
// WsRPC is an RPC extension interface,
// to explicitly provide the Websocket RPC option.
type WsRPC interface {
RPC
WsRPC() string
}
// HttpRPC is an RPC extension interface,
// to explicitly provide the HTTP RPC option.
type HttpRPC interface {
RPC
HttpRPC() string
}
// ClientRPC is an RPC extension interface,
// providing the option to attach in-process to a client,
// rather than dialing an endpoint.
type ClientRPC interface {
RPC
ClientRPC() *rpc.Client
}
// HttpURL is an HTTP endpoint URL
type HttpURL string
func (url HttpURL) RPC() string {
return string(url)
}
func (url HttpURL) HttpRPC() string {
return string(url)
}
// WsURL is a websocket endpoint URL
type WsURL string
func (url WsURL) RPC() string {
return string(url)
}
func (url WsURL) WsRPC() string {
return string(url)
}
// WsOrHttpRPC provides optionality between
// a websocket RPC endpoint and a HTTP RPC endpoint.
// The default is the websocket endpoint.
type WsOrHttpRPC struct {
WsURL string
HttpURL string
}
func (r WsOrHttpRPC) RPC() string {
return r.WsURL
}
func (r WsOrHttpRPC) WsRPC() string {
return r.WsURL
}
func (r WsOrHttpRPC) HttpRPC() string {
return r.HttpURL
}
// ServerRPC is a very flexible RPC: it can attach in-process to a server,
// or select one of the fallback RPC methods.
type ServerRPC struct {
Fallback WsOrHttpRPC
Server *rpc.Server
}
func (e *ServerRPC) RPC() string {
return e.Fallback.RPC()
}
func (e *ServerRPC) WsRPC() string {
return e.Fallback.WsRPC()
}
func (e *ServerRPC) HttpRPC() string {
return e.Fallback.HttpRPC()
}
func (e *ServerRPC) ClientRPC() *rpc.Client {
return rpc.DialInProc(e.Server)
}
type Dialer func(v string) *rpc.Client
type RPCPreference int
const (
PreferAnyRPC RPCPreference = iota
PreferHttpRPC
PreferWSRPC
)
// DialRPC navigates the RPC interface,
// to find the optimal version of the PRC to dial or attach to.
func DialRPC(preference RPCPreference, rpc RPC, dialer Dialer) *rpc.Client {
if v, ok := rpc.(HttpRPC); preference == PreferHttpRPC && ok {
return dialer(v.HttpRPC())
}
if v, ok := rpc.(WsRPC); preference == PreferWSRPC && ok {
return dialer(v.WsRPC())
}
if v, ok := rpc.(ClientRPC); ok {
return v.ClientRPC()
}
return dialer(rpc.RPC())
}
// SelectRPC selects an endpoint URL, based on preference.
// For more optimal dialing, use DialRPC.
func SelectRPC(preference RPCPreference, rpc RPC) string {
if v, ok := rpc.(HttpRPC); preference == PreferHttpRPC && ok {
return v.HttpRPC()
}
if v, ok := rpc.(WsRPC); preference == PreferWSRPC && ok {
return v.WsRPC()
}
return rpc.RPC()
}
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