From 0f79baf29edeb8138900e7f021d9b47d198df0cd Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Mon, 3 Oct 2022 09:35:55 -0600 Subject: [PATCH 1/4] ci: Parallelize op-e2e Replaces my previous PRs since `t.Parallel()` works fine. Also exposes the listener on the op-node, so that we can use a port of zero and allow the kernel to allocate a port. --- .circleci/config.yml | 2 +- op-e2e/setup.go | 10 ++-------- op-e2e/system_test.go | 16 +++++++++++++--- op-node/node/node.go | 8 ++++++++ 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 94060ca51e9..b63a5a0c00a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -288,7 +288,7 @@ jobs: - run: name: test op-e2e command: | - gotestsum --junitfile /test-results/op-e2e.xml -- -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... + gotestsum --format standard-verbose --junitfile /test-results/op-e2e.xml -- -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out -covermode=atomic ./... working_directory: op-e2e - run: name: test op-service diff --git a/op-e2e/setup.go b/op-e2e/setup.go index e2ae888e2d4..c3c0ad75897 100644 --- a/op-e2e/setup.go +++ b/op-e2e/setup.go @@ -541,17 +541,11 @@ func (cfg SystemConfig) start() (*System, error) { } } - rollupEndpoint := fmt.Sprintf( - "http://%s:%d", - sys.cfg.Nodes["sequencer"].RPC.ListenAddr, - sys.cfg.Nodes["sequencer"].RPC.ListenPort, - ) - // L2Output Submitter sys.l2OutputSubmitter, err = l2os.NewL2OutputSubmitter(l2os.Config{ L1EthRpc: sys.nodes["l1"].WSEndpoint(), L2EthRpc: sys.nodes["sequencer"].WSEndpoint(), - RollupRpc: rollupEndpoint, + RollupRpc: sys.rollupNodes["sequencer"].HTTPEndpoint(), L2OOAddress: sys.L2OOContractAddr.String(), PollInterval: 50 * time.Millisecond, NumConfirmations: 1, @@ -576,7 +570,7 @@ func (cfg SystemConfig) start() (*System, error) { sys.batchSubmitter, err = bss.NewBatchSubmitter(bss.Config{ L1EthRpc: sys.nodes["l1"].WSEndpoint(), L2EthRpc: sys.nodes["sequencer"].WSEndpoint(), - RollupRpc: rollupEndpoint, + RollupRpc: sys.rollupNodes["sequencer"].HTTPEndpoint(), MinL1TxSize: 1, MaxL1TxSize: 120000, ChannelTimeout: sys.cfg.RollupConfig.ChannelTimeout, diff --git a/op-e2e/system_test.go b/op-e2e/system_test.go index 07569143de0..3db12ad3d5e 100644 --- a/op-e2e/system_test.go +++ b/op-e2e/system_test.go @@ -121,7 +121,7 @@ func defaultSystemConfig(t *testing.T) SystemConfig { // Submitter PrivKey is set in system start for rollup nodes where sequencer = true RPC: node.RPCConfig{ ListenAddr: "127.0.0.1", - ListenPort: 9093, + ListenPort: 0, EnableAdmin: true, }, L1EpochPollInterval: time.Second * 4, @@ -154,6 +154,7 @@ func defaultSystemConfig(t *testing.T) SystemConfig { } func TestL2OutputSubmitter(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } @@ -166,7 +167,7 @@ func TestL2OutputSubmitter(t *testing.T) { l1Client := sys.Clients["l1"] - rollupRPCClient, err := rpc.DialContext(context.Background(), cfg.Nodes["sequencer"].RPC.HttpEndpoint()) + rollupRPCClient, err := rpc.DialContext(context.Background(), sys.rollupNodes["sequencer"].HTTPEndpoint()) require.Nil(t, err) rollupClient := sources.NewRollupClient(rollupRPCClient) @@ -229,6 +230,7 @@ func TestL2OutputSubmitter(t *testing.T) { // TestSystemE2E sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that L1 deposits are reflected on L2. // All nodes are run in process (but are the full nodes, not mocked or stubbed). func TestSystemE2E(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } @@ -328,7 +330,7 @@ func TestSystemE2E(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(), cfg.Nodes["sequencer"].RPC.HttpEndpoint()) + rollupRPCClient, err := rpc.DialContext(context.Background(), sys.rollupNodes["sequencer"].HTTPEndpoint()) require.Nil(t, err) rollupClient := sources.NewRollupClient(rollupRPCClient) // basic check that sync status works @@ -343,6 +345,7 @@ func TestSystemE2E(t *testing.T) { // TestConfirmationDepth runs the rollup with both sequencer and verifier not immediately processing the tip of the chain. func TestConfirmationDepth(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } @@ -390,6 +393,7 @@ func TestConfirmationDepth(t *testing.T) { // TestFinalize tests if L2 finalizes after sufficient time after L1 finalizes func TestFinalize(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } @@ -417,6 +421,7 @@ func TestFinalize(t *testing.T) { } func TestMintOnRevertedDeposit(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } @@ -490,6 +495,7 @@ func TestMintOnRevertedDeposit(t *testing.T) { } func TestMissingBatchE2E(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } @@ -599,6 +605,7 @@ func L1InfoFromState(ctx context.Context, contract *bindings.L1Block, l2Number * // TestSystemMockP2P sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that // the nodes can sync L2 blocks before they are confirmed on L1. func TestSystemMockP2P(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } @@ -672,6 +679,7 @@ func TestSystemMockP2P(t *testing.T) { } func TestL1InfoContract(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } @@ -795,6 +803,7 @@ func calcL1GasUsed(data []byte, overhead *big.Int) *big.Int { // balance changes on L1 and L2 and has to include gas fees in the balance checks. // It does not check that the withdrawal can be executed prior to the end of the finality period. func TestWithdrawals(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } @@ -970,6 +979,7 @@ func TestWithdrawals(t *testing.T) { // TestFees checks that L1/L2 fees are handled. func TestFees(t *testing.T) { + t.Parallel() if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } diff --git a/op-node/node/node.go b/op-node/node/node.go index e1fbf98187a..c7668081851 100644 --- a/op-node/node/node.go +++ b/op-node/node/node.go @@ -355,3 +355,11 @@ func (n *OpNode) Close() error { } return result.ErrorOrNil() } + +func (n *OpNode) ListenAddr() string { + return n.server.listenAddr.String() +} + +func (n *OpNode) HTTPEndpoint() string { + return fmt.Sprintf("http://%s", n.ListenAddr()) +} From 30eaa5d9f7ba515999533f13790bbdd265e500e7 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Mon, 3 Oct 2022 09:49:10 -0600 Subject: [PATCH 2/4] close other geth nodes --- op-e2e/actions/l1_miner_test.go | 3 ++- op-e2e/actions/l1_replica.go | 4 ++-- op-e2e/actions/l1_replica_test.go | 9 ++++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/op-e2e/actions/l1_miner_test.go b/op-e2e/actions/l1_miner_test.go index 8979d0ead7d..bc36cd2e93f 100644 --- a/op-e2e/actions/l1_miner_test.go +++ b/op-e2e/actions/l1_miner_test.go @@ -52,7 +52,8 @@ func TestL1Miner_BuildBlock(gt *testing.T) { require.Equal(t, tx.Hash(), bl.Transactions()[0].Hash()) // now make a replica that syncs these two blocks from the miner - replica := NewL1Replica(log, sd.L1Cfg) + replica, done := NewL1Replica(log, sd.L1Cfg) + defer done() replica.ActL1Sync(miner.CanonL1Chain())(t) replica.ActL1Sync(miner.CanonL1Chain())(t) require.Equal(t, replica.l1Chain.CurrentBlock().Hash(), miner.l1Chain.CurrentBlock().Hash()) diff --git a/op-e2e/actions/l1_replica.go b/op-e2e/actions/l1_replica.go index 8097f55886f..1450bea1029 100644 --- a/op-e2e/actions/l1_replica.go +++ b/op-e2e/actions/l1_replica.go @@ -45,7 +45,7 @@ type L1Replica struct { } // NewL1Replica constructs a L1Replica starting at the given genesis. -func NewL1Replica(log log.Logger, genesis *core.Genesis) *L1Replica { +func NewL1Replica(log log.Logger, genesis *core.Genesis) (*L1Replica, func() error) { ethCfg := ðconfig.Config{ NetworkId: genesis.Config.ChainID.Uint64(), Genesis: genesis, @@ -87,7 +87,7 @@ func NewL1Replica(log log.Logger, genesis *core.Genesis) *L1Replica { l1Cfg: genesis, l1Signer: types.LatestSigner(genesis.Config), failL1RPC: nil, - } + }, n.Close } // ActL1RewindToParent rewinds the L1 chain to parent block of head diff --git a/op-e2e/actions/l1_replica_test.go b/op-e2e/actions/l1_replica_test.go index 5b88aa74991..592bc685ff0 100644 --- a/op-e2e/actions/l1_replica_test.go +++ b/op-e2e/actions/l1_replica_test.go @@ -32,7 +32,8 @@ func TestL1Replica_ActL1RPCFail(gt *testing.T) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) sd := e2eutils.Setup(t, dp, defaultAlloc) log := testlog.Logger(t, log.LvlDebug) - replica := NewL1Replica(log, sd.L1Cfg) + replica, done := NewL1Replica(log, sd.L1Cfg) + defer done() // mock an RPC failure replica.ActL1RPCFail(t) // check RPC failure @@ -75,7 +76,8 @@ func TestL1Replica_ActL1Sync(gt *testing.T) { } // Enough setup, create the test actor and run the actual actions - replica1 := NewL1Replica(log, sd.L1Cfg) + replica1, done1 := NewL1Replica(log, sd.L1Cfg) + defer done1() syncFromA := replica1.ActL1Sync(canonL1(chainA)) // sync canonical chain A for replica1.l1Chain.CurrentBlock().NumberU64()+1 < uint64(len(chainA)) { @@ -93,7 +95,8 @@ func TestL1Replica_ActL1Sync(gt *testing.T) { require.Equal(t, replica1.l1Chain.CurrentBlock().Hash(), chainB[len(chainB)-1].Hash(), "sync replica1 to head of chain B") // Adding and syncing a new replica - replica2 := NewL1Replica(log, sd.L1Cfg) + replica2, done2 := NewL1Replica(log, sd.L1Cfg) + defer done2() syncFromOther := replica2.ActL1Sync(replica1.CanonL1Chain()) for replica2.l1Chain.CurrentBlock().NumberU64()+1 < uint64(len(chainB)) { syncFromOther(t) From 9c3634a0f23315b8a74c5ed09b30c505658e4935 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Mon, 3 Oct 2022 09:53:23 -0600 Subject: [PATCH 3/4] missed one --- op-e2e/actions/l1_miner.go | 6 +++--- op-e2e/actions/l1_miner_test.go | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/op-e2e/actions/l1_miner.go b/op-e2e/actions/l1_miner.go index d94124a8167..7a8a6442c99 100644 --- a/op-e2e/actions/l1_miner.go +++ b/op-e2e/actions/l1_miner.go @@ -29,11 +29,11 @@ type L1Miner struct { } // NewL1Miner creates a new L1Replica that can also build blocks. -func NewL1Miner(log log.Logger, genesis *core.Genesis) *L1Miner { - rep := NewL1Replica(log, genesis) +func NewL1Miner(log log.Logger, genesis *core.Genesis) (*L1Miner, func() error) { + rep, done := NewL1Replica(log, genesis) return &L1Miner{ L1Replica: *rep, - } + }, done } // ActL1StartBlock returns an action to build a new L1 block on top of the head block, diff --git a/op-e2e/actions/l1_miner_test.go b/op-e2e/actions/l1_miner_test.go index bc36cd2e93f..d3e2a9427b1 100644 --- a/op-e2e/actions/l1_miner_test.go +++ b/op-e2e/actions/l1_miner_test.go @@ -18,7 +18,8 @@ func TestL1Miner_BuildBlock(gt *testing.T) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) sd := e2eutils.Setup(t, dp, defaultAlloc) log := testlog.Logger(t, log.LvlDebug) - miner := NewL1Miner(log, sd.L1Cfg) + miner, done := NewL1Miner(log, sd.L1Cfg) + defer done() cl := miner.EthClient() signer := types.LatestSigner(sd.L1Cfg.Config) From 57d361ae6e4d5d72e25d8014ff014ab12c7c03d1 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Mon, 3 Oct 2022 10:16:28 -0600 Subject: [PATCH 4/4] use t.cleanup --- op-e2e/actions/l1_miner.go | 10 +++++++--- op-e2e/actions/l1_miner_test.go | 12 ++++++++---- op-e2e/actions/l1_replica.go | 8 ++++++-- op-e2e/actions/l1_replica_test.go | 18 ++++++++++++------ op-e2e/actions/l2_engine.go | 4 ++++ op-e2e/actions/l2_engine_test.go | 3 +++ 6 files changed, 40 insertions(+), 15 deletions(-) diff --git a/op-e2e/actions/l1_miner.go b/op-e2e/actions/l1_miner.go index 7a8a6442c99..d0e4a58ee83 100644 --- a/op-e2e/actions/l1_miner.go +++ b/op-e2e/actions/l1_miner.go @@ -29,11 +29,11 @@ type L1Miner struct { } // NewL1Miner creates a new L1Replica that can also build blocks. -func NewL1Miner(log log.Logger, genesis *core.Genesis) (*L1Miner, func() error) { - rep, done := NewL1Replica(log, genesis) +func NewL1Miner(log log.Logger, genesis *core.Genesis) *L1Miner { + rep := NewL1Replica(log, genesis) return &L1Miner{ L1Replica: *rep, - }, done + } } // ActL1StartBlock returns an action to build a new L1 block on top of the head block, @@ -140,3 +140,7 @@ func (s *L1Miner) ActL1EndBlock(t Testing) { t.Fatalf("failed to insert block into l1 chain") } } + +func (s *L1Miner) Close() error { + return s.L1Replica.Close() +} diff --git a/op-e2e/actions/l1_miner_test.go b/op-e2e/actions/l1_miner_test.go index d3e2a9427b1..8d4c790b831 100644 --- a/op-e2e/actions/l1_miner_test.go +++ b/op-e2e/actions/l1_miner_test.go @@ -18,8 +18,10 @@ func TestL1Miner_BuildBlock(gt *testing.T) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) sd := e2eutils.Setup(t, dp, defaultAlloc) log := testlog.Logger(t, log.LvlDebug) - miner, done := NewL1Miner(log, sd.L1Cfg) - defer done() + miner := NewL1Miner(log, sd.L1Cfg) + t.Cleanup(func() { + _ = miner.Close() + }) cl := miner.EthClient() signer := types.LatestSigner(sd.L1Cfg.Config) @@ -53,8 +55,10 @@ func TestL1Miner_BuildBlock(gt *testing.T) { require.Equal(t, tx.Hash(), bl.Transactions()[0].Hash()) // now make a replica that syncs these two blocks from the miner - replica, done := NewL1Replica(log, sd.L1Cfg) - defer done() + replica := NewL1Replica(log, sd.L1Cfg) + t.Cleanup(func() { + _ = replica.Close() + }) replica.ActL1Sync(miner.CanonL1Chain())(t) replica.ActL1Sync(miner.CanonL1Chain())(t) require.Equal(t, replica.l1Chain.CurrentBlock().Hash(), miner.l1Chain.CurrentBlock().Hash()) diff --git a/op-e2e/actions/l1_replica.go b/op-e2e/actions/l1_replica.go index 1450bea1029..81611f76edc 100644 --- a/op-e2e/actions/l1_replica.go +++ b/op-e2e/actions/l1_replica.go @@ -45,7 +45,7 @@ type L1Replica struct { } // NewL1Replica constructs a L1Replica starting at the given genesis. -func NewL1Replica(log log.Logger, genesis *core.Genesis) (*L1Replica, func() error) { +func NewL1Replica(log log.Logger, genesis *core.Genesis) *L1Replica { ethCfg := ðconfig.Config{ NetworkId: genesis.Config.ChainID.Uint64(), Genesis: genesis, @@ -87,7 +87,7 @@ func NewL1Replica(log log.Logger, genesis *core.Genesis) (*L1Replica, func() err l1Cfg: genesis, l1Signer: types.LatestSigner(genesis.Config), failL1RPC: nil, - }, n.Close + } } // ActL1RewindToParent rewinds the L1 chain to parent block of head @@ -186,3 +186,7 @@ func (s *L1Replica) ActL1SafeNext(t Testing) { } s.l1Chain.SetSafe(next) } + +func (s *L1Replica) Close() error { + return s.node.Close() +} diff --git a/op-e2e/actions/l1_replica_test.go b/op-e2e/actions/l1_replica_test.go index 592bc685ff0..84d37bb11da 100644 --- a/op-e2e/actions/l1_replica_test.go +++ b/op-e2e/actions/l1_replica_test.go @@ -32,8 +32,10 @@ func TestL1Replica_ActL1RPCFail(gt *testing.T) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) sd := e2eutils.Setup(t, dp, defaultAlloc) log := testlog.Logger(t, log.LvlDebug) - replica, done := NewL1Replica(log, sd.L1Cfg) - defer done() + replica := NewL1Replica(log, sd.L1Cfg) + t.Cleanup(func() { + _ = replica.Close() + }) // mock an RPC failure replica.ActL1RPCFail(t) // check RPC failure @@ -76,8 +78,10 @@ func TestL1Replica_ActL1Sync(gt *testing.T) { } // Enough setup, create the test actor and run the actual actions - replica1, done1 := NewL1Replica(log, sd.L1Cfg) - defer done1() + replica1 := NewL1Replica(log, sd.L1Cfg) + t.Cleanup(func() { + _ = replica1.Close() + }) syncFromA := replica1.ActL1Sync(canonL1(chainA)) // sync canonical chain A for replica1.l1Chain.CurrentBlock().NumberU64()+1 < uint64(len(chainA)) { @@ -95,8 +99,10 @@ func TestL1Replica_ActL1Sync(gt *testing.T) { require.Equal(t, replica1.l1Chain.CurrentBlock().Hash(), chainB[len(chainB)-1].Hash(), "sync replica1 to head of chain B") // Adding and syncing a new replica - replica2, done2 := NewL1Replica(log, sd.L1Cfg) - defer done2() + replica2 := NewL1Replica(log, sd.L1Cfg) + t.Cleanup(func() { + _ = replica2.Close() + }) syncFromOther := replica2.ActL1Sync(replica1.CanonL1Chain()) for replica2.l1Chain.CurrentBlock().NumberU64()+1 < uint64(len(chainB)) { syncFromOther(t) diff --git a/op-e2e/actions/l2_engine.go b/op-e2e/actions/l2_engine.go index 111efd83cae..1dc7ebb6228 100644 --- a/op-e2e/actions/l2_engine.go +++ b/op-e2e/actions/l2_engine.go @@ -175,3 +175,7 @@ func (e *L2Engine) ActL2IncludeTx(from common.Address) Action { e.l2Transactions = append(e.l2Transactions, tx) } } + +func (e *L2Engine) Close() error { + return e.node.Close() +} diff --git a/op-e2e/actions/l2_engine_test.go b/op-e2e/actions/l2_engine_test.go index 3a9b8c93bcf..edc6a3f00a8 100644 --- a/op-e2e/actions/l2_engine_test.go +++ b/op-e2e/actions/l2_engine_test.go @@ -95,6 +95,9 @@ func TestL2EngineAPIBlockBuilding(gt *testing.T) { sd.L2Cfg.MustCommit(db) engine := NewL2Engine(log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + t.Cleanup(func() { + _ = engine.Close() + }) cl := engine.EthClient() signer := types.LatestSigner(sd.L2Cfg.Config)