From 2ec0a4412828c6adcc9345a139d3ba9e558648df Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Mon, 23 Oct 2023 22:23:54 -0500 Subject: [PATCH 1/2] Refactor System Tests --- system_tests/arbtrace_test.go | 33 +++--- system_tests/common_test.go | 5 + system_tests/conditionaltx_test.go | 143 ++++++++++++------------- system_tests/debugapi_test.go | 19 ++-- system_tests/fees_test.go | 80 +++++++------- system_tests/forwarder_test.go | 141 ++++++++++-------------- system_tests/ipc_test.go | 14 +-- system_tests/meaningless_reorg_test.go | 40 ++++--- system_tests/seq_coordinator_test.go | 68 ++++++------ system_tests/seqfeed_test.go | 114 +++++++++++--------- system_tests/seqinbox_test.go | 81 +++++++------- system_tests/staker_test.go | 80 +++++++------- 12 files changed, 398 insertions(+), 420 deletions(-) diff --git a/system_tests/arbtrace_test.go b/system_tests/arbtrace_test.go index a4995e3979..36e4cc9402 100644 --- a/system_tests/arbtrace_test.go +++ b/system_tests/arbtrace_test.go @@ -10,8 +10,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" - "github.com/offchainlabs/nitro/execution/gethexec" - "github.com/offchainlabs/nitro/util/testhelpers" ) type callTxArgs struct { @@ -140,18 +138,17 @@ func TestArbTraceForwarding(t *testing.T) { Public: false, }) listener, srv, err := rpc.StartIPCEndpoint(ipcPath, apis) - testhelpers.RequireImpl(t, err) + Require(t, err) defer srv.Stop() defer listener.Close() - execConfig := gethexec.ConfigDefaultTest() - execConfig.RPC.ClassicRedirect = ipcPath - execConfig.RPC.ClassicRedirectTimeout = time.Second - _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, execConfig, nil, nil, nil) - defer requireClose(t, l1stack) - defer requireClose(t, l2stack) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.execConfig.RPC.ClassicRedirect = ipcPath + builder.execConfig.RPC.ClassicRedirectTimeout = time.Second + cleanup := builder.Build(t) + defer cleanup() - l2rpc, _ := l2stack.Attach() + l2rpc, _ := builder.L2.Stack.Attach() txArgs := callTxArgs{} traceTypes := []string{"trace"} blockNum := rpc.BlockNumberOrHash{} @@ -162,22 +159,22 @@ func TestArbTraceForwarding(t *testing.T) { filter := filterRequest{} var result traceResult err = l2rpc.CallContext(ctx, &result, "arbtrace_call", txArgs, traceTypes, blockNum) - testhelpers.RequireImpl(t, err) + Require(t, err) var results []*traceResult err = l2rpc.CallContext(ctx, &results, "arbtrace_callMany", traceRequests, blockNum) - testhelpers.RequireImpl(t, err) + Require(t, err) err = l2rpc.CallContext(ctx, &results, "arbtrace_replayBlockTransactions", blockNum, traceTypes) - testhelpers.RequireImpl(t, err) + Require(t, err) err = l2rpc.CallContext(ctx, &result, "arbtrace_replayTransaction", txHash, traceTypes) - testhelpers.RequireImpl(t, err) + Require(t, err) var frames []traceFrame err = l2rpc.CallContext(ctx, &frames, "arbtrace_transaction", txHash) - testhelpers.RequireImpl(t, err) + Require(t, err) var frame traceFrame err = l2rpc.CallContext(ctx, &frame, "arbtrace_get", txHash, path) - testhelpers.RequireImpl(t, err) + Require(t, err) err = l2rpc.CallContext(ctx, &frames, "arbtrace_block", blockNum) - testhelpers.RequireImpl(t, err) + Require(t, err) err = l2rpc.CallContext(ctx, &frames, "arbtrace_filter", filter) - testhelpers.RequireImpl(t, err) + Require(t, err) } diff --git a/system_tests/common_test.go b/system_tests/common_test.go index d233631d4c..41a3fd1417 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -115,6 +115,10 @@ func (tc *TestClient) DeploySimple(t *testing.T, auth bind.TransactOpts) (common return deploySimple(t, tc.ctx, auth, tc.Client) } +func (tc *TestClient) EnsureTxSucceeded(transaction *types.Transaction) (*types.Receipt, error) { + return EnsureTxSucceeded(tc.ctx, tc.Client, transaction) +} + type NodeBuilder struct { // NodeBuilder configuration ctx context.Context @@ -212,6 +216,7 @@ func (b *NodeBuilder) Build2ndNode(t *testing.T, params *SecondNodeParams) (*Tes l2 := NewTestClient(b.ctx) l2.Client, l2.ConsensusNode = Create2ndNodeWithConfig(t, b.ctx, b.L2.ConsensusNode, b.L1.Stack, b.L1Info, params.initData, params.nodeConfig, params.execConfig, params.stackConfig) + l2.ExecNode = getExecNode(t, l2.ConsensusNode) l2.cleanup = func() { l2.ConsensusNode.StopAndWait() } return l2, func() { l2.cleanup() } } diff --git a/system_tests/conditionaltx_test.go b/system_tests/conditionaltx_test.go index 211908a883..d75dd27255 100644 --- a/system_tests/conditionaltx_test.go +++ b/system_tests/conditionaltx_test.go @@ -202,43 +202,42 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, l2client, _, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - execNode := getExecNode(t, node) - auth := l2info.GetDefaultTransactOpts("Owner", ctx) - contractAddress1, simple1 := deploySimple(t, ctx, auth, l2client) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + contractAddress1, simple1 := builder.L2.DeploySimple(t, auth) tx, err := simple1.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - contractAddress2, simple2 := deploySimple(t, ctx, auth, l2client) + contractAddress2, simple2 := builder.L2.DeploySimple(t, auth) tx, err = simple2.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) tx, err = simple2.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - currentRootHash1 := getStorageRootHash(t, execNode, contractAddress1) - currentSlotValueMap1 := getStorageSlotValue(t, execNode, contractAddress1) - currentRootHash2 := getStorageRootHash(t, execNode, contractAddress2) - currentSlotValueMap2 := getStorageSlotValue(t, execNode, contractAddress2) + currentRootHash1 := getStorageRootHash(t, builder.L2.ExecNode, contractAddress1) + currentSlotValueMap1 := getStorageSlotValue(t, builder.L2.ExecNode, contractAddress1) + currentRootHash2 := getStorageRootHash(t, builder.L2.ExecNode, contractAddress2) + currentSlotValueMap2 := getStorageSlotValue(t, builder.L2.ExecNode, contractAddress2) - rpcClient, err := node.Stack.Attach() + rpcClient, err := builder.L2.ConsensusNode.Stack.Attach() Require(t, err) - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - testConditionalTxThatShouldSucceed(t, ctx, -1, l2info, rpcClient, nil) + testConditionalTxThatShouldSucceed(t, ctx, -1, builder.L2Info, rpcClient, nil) for i, options := range getEmptyOptions(contractAddress1) { - testConditionalTxThatShouldSucceed(t, ctx, i, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, i, builder.L2Info, rpcClient, options) } - block, err := l1client.BlockByNumber(ctx, nil) + block, err := builder.L1.Client.BlockByNumber(ctx, nil) Require(t, err) blockNumber := block.NumberU64() blockTime := block.Time() @@ -249,33 +248,33 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { options1 := dedupOptions(t, append(append(optionsAB, optionsA...), optionsB...)) options1 = optionsDedupProduct(t, options1, getFulfillableBlockTimeLimits(t, blockNumber, blockTime)) for i, options := range options1 { - testConditionalTxThatShouldSucceed(t, ctx, i, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, i, builder.L2Info, rpcClient, options) } tx, err = simple1.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) tx, err = simple2.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) previousStorageRootHash1 := currentRootHash1 - currentRootHash1 = getStorageRootHash(t, execNode, contractAddress1) + currentRootHash1 = getStorageRootHash(t, builder.L2.ExecNode, contractAddress1) if bytes.Equal(previousStorageRootHash1.Bytes(), currentRootHash1.Bytes()) { Fatal(t, "storage root hash didn't change as expected") } - currentSlotValueMap1 = getStorageSlotValue(t, execNode, contractAddress1) + currentSlotValueMap1 = getStorageSlotValue(t, builder.L2.ExecNode, contractAddress1) previousStorageRootHash2 := currentRootHash2 - currentRootHash2 = getStorageRootHash(t, execNode, contractAddress2) + currentRootHash2 = getStorageRootHash(t, builder.L2.ExecNode, contractAddress2) if bytes.Equal(previousStorageRootHash2.Bytes(), currentRootHash2.Bytes()) { Fatal(t, "storage root hash didn't change as expected") } - currentSlotValueMap2 = getStorageSlotValue(t, execNode, contractAddress2) + currentSlotValueMap2 = getStorageSlotValue(t, builder.L2.ExecNode, contractAddress2) - block, err = l1client.BlockByNumber(ctx, nil) + block, err = builder.L1.Client.BlockByNumber(ctx, nil) Require(t, err) blockNumber = block.NumberU64() blockTime = block.Time() @@ -286,35 +285,38 @@ func TestSendRawTransactionConditionalBasic(t *testing.T) { options2 := dedupOptions(t, append(append(optionsCD, optionsC...), optionsD...)) options2 = optionsDedupProduct(t, options2, getFulfillableBlockTimeLimits(t, blockNumber, blockTime)) for i, options := range options2 { - testConditionalTxThatShouldSucceed(t, ctx, i, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, i, builder.L2Info, rpcClient, options) } for i, options := range options1 { - testConditionalTxThatShouldFail(t, ctx, i, l2info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, i, builder.L2Info, rpcClient, options, -32003) } - block, err = l1client.BlockByNumber(ctx, nil) + block, err = builder.L1.Client.BlockByNumber(ctx, nil) Require(t, err) blockNumber = block.NumberU64() blockTime = block.Time() options3 := optionsDedupProduct(t, options2, getUnfulfillableBlockTimeLimits(t, blockNumber, blockTime)) for i, options := range options3 { - testConditionalTxThatShouldFail(t, ctx, i, l2info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, i, builder.L2Info, rpcClient, options, -32003) } options4 := optionsDedupProduct(t, options2, options1) for i, options := range options4 { - testConditionalTxThatShouldFail(t, ctx, i, l2info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, i, builder.L2Info, rpcClient, options, -32003) } } func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() - rpcClient, err := node.Stack.Attach() + + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() + + rpcClient, err := builder.L2.ConsensusNode.Stack.Attach() Require(t, err) - auth := l2info.GetDefaultTransactOpts("Owner", ctx) - contractAddress, simple := deploySimple(t, ctx, auth, client) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + contractAddress, simple := builder.L2.DeploySimple(t, auth) simpleContract, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) Require(t, err) @@ -325,11 +327,11 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { var options []*arbitrum_types.ConditionalOptions for i := 0; i < numTxes; i++ { account := fmt.Sprintf("User%v", i) - l2info.GenerateAccount(account) - tx := l2info.PrepareTx("Owner", account, l2info.TransferGas, big.NewInt(1e16), nil) - err := client.SendTransaction(ctx, tx) + builder.L2Info.GenerateAccount(account) + tx := builder.L2Info.PrepareTx("Owner", account, builder.L2Info.TransferGas, big.NewInt(1e16), nil) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) } for i := numTxes - 1; i >= 0; i-- { @@ -337,7 +339,7 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { data, err := simpleContract.Pack("logAndIncrement", big.NewInt(int64(expected))) Require(t, err) account := fmt.Sprintf("User%v", i) - txes = append(txes, l2info.PrepareTxTo(account, &contractAddress, l2info.TransferGas, big.NewInt(0), data)) + txes = append(txes, builder.L2Info.PrepareTxTo(account, &contractAddress, builder.L2Info.TransferGas, big.NewInt(0), data)) options = append(options, &arbitrum_types.ConditionalOptions{KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{contractAddress: {SlotValue: map[common.Hash]common.Hash{{0}: common.BigToHash(big.NewInt(int64(expected)))}}}}) } ctxWithTimeout, cancelCtxWithTimeout := context.WithTimeout(ctx, 5*time.Second) @@ -367,8 +369,7 @@ func TestSendRawTransactionConditionalMultiRoutine(t *testing.T) { } cancelCtxWithTimeout() wg.Wait() - execNode := getExecNode(t, node) - bc := execNode.Backend.ArbInterface().BlockChain() + bc := builder.L2.ExecNode.Backend.ArbInterface().BlockChain() genesis := bc.Config().ArbitrumChainParams.GenesisBlockNum var receipts types.Receipts @@ -404,41 +405,39 @@ func TestSendRawTransactionConditionalPreCheck(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - execConfig := gethexec.ConfigDefaultTest() - execConfig.Sequencer.MaxBlockSpeed = 0 - execConfig.TxPreChecker.Strictness = gethexec.TxPreCheckerStrictnessLikelyCompatible - execConfig.TxPreChecker.RequiredStateAge = 1 - execConfig.TxPreChecker.RequiredStateMaxBlocks = 2 + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.execConfig.Sequencer.MaxBlockSpeed = 0 + builder.execConfig.TxPreChecker.Strictness = gethexec.TxPreCheckerStrictnessLikelyCompatible + builder.execConfig.TxPreChecker.RequiredStateAge = 1 + builder.execConfig.TxPreChecker.RequiredStateMaxBlocks = 2 + cleanup := builder.Build(t) + defer cleanup() - l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, execConfig, nil, nil) - defer requireClose(t, l1stack) - defer node.StopAndWait() - rpcClient, err := node.Stack.Attach() + rpcClient, err := builder.L2.ConsensusNode.Stack.Attach() Require(t, err) - execNode := getExecNode(t, node) - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) start := time.Now().Unix() - contractAddress, simple := deploySimple(t, ctx, auth, l2client) + contractAddress, simple := builder.L2.DeploySimple(t, auth) if time.Since(time.Unix(start, 0)) > 200*time.Millisecond { start++ time.Sleep(time.Until(time.Unix(start, 0))) } tx, err := simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - currentRootHash := getStorageRootHash(t, execNode, contractAddress) + currentRootHash := getStorageRootHash(t, builder.L2.ExecNode, contractAddress) options := &arbitrum_types.ConditionalOptions{ KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{ contractAddress: {RootHash: ¤tRootHash}, }, } - testConditionalTxThatShouldFail(t, ctx, 0, l2info, rpcClient, options, -32003) + testConditionalTxThatShouldFail(t, ctx, 0, builder.L2Info, rpcClient, options, -32003) time.Sleep(time.Until(time.Unix(start+1, 0))) - testConditionalTxThatShouldSucceed(t, ctx, 1, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, 1, builder.L2Info, rpcClient, options) start = time.Now().Unix() if time.Since(time.Unix(start, 0)) > 200*time.Millisecond { @@ -447,23 +446,23 @@ func TestSendRawTransactionConditionalPreCheck(t *testing.T) { } tx, err = simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - currentRootHash = getStorageRootHash(t, execNode, contractAddress) + currentRootHash = getStorageRootHash(t, builder.L2.ExecNode, contractAddress) options = &arbitrum_types.ConditionalOptions{ KnownAccounts: map[common.Address]arbitrum_types.RootHashOrSlots{ contractAddress: {RootHash: ¤tRootHash}, }, } - testConditionalTxThatShouldFail(t, ctx, 2, l2info, rpcClient, options, -32003) - tx = l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) - Require(t, l2client.SendTransaction(ctx, tx)) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + testConditionalTxThatShouldFail(t, ctx, 2, builder.L2Info, rpcClient, options, -32003) + tx = builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) + Require(t, builder.L2.Client.SendTransaction(ctx, tx)) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - testConditionalTxThatShouldFail(t, ctx, 3, l2info, rpcClient, options, -32003) - tx = l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) - Require(t, l2client.SendTransaction(ctx, tx)) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + testConditionalTxThatShouldFail(t, ctx, 3, builder.L2Info, rpcClient, options, -32003) + tx = builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) + Require(t, builder.L2.Client.SendTransaction(ctx, tx)) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - testConditionalTxThatShouldSucceed(t, ctx, 4, l2info, rpcClient, options) + testConditionalTxThatShouldSucceed(t, ctx, 4, builder.L2Info, rpcClient, options) } diff --git a/system_tests/debugapi_test.go b/system_tests/debugapi_test.go index ff28e2350c..b8fbffcfee 100644 --- a/system_tests/debugapi_test.go +++ b/system_tests/debugapi_test.go @@ -8,32 +8,31 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/rpc" - "github.com/offchainlabs/nitro/util/testhelpers" ) func TestDebugAPI(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, _, _, l2stack, _, _, _, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, nil, nil, nil) - defer requireClose(t, l1stack) - defer requireClose(t, l2stack) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - l2rpc, _ := l2stack.Attach() + l2rpc, _ := builder.L2.Stack.Attach() var dump state.Dump err := l2rpc.CallContext(ctx, &dump, "debug_dumpBlock", rpc.LatestBlockNumber) - testhelpers.RequireImpl(t, err) + Require(t, err) err = l2rpc.CallContext(ctx, &dump, "debug_dumpBlock", rpc.PendingBlockNumber) - testhelpers.RequireImpl(t, err) + Require(t, err) var badBlocks []eth.BadBlockArgs err = l2rpc.CallContext(ctx, &badBlocks, "debug_getBadBlocks") - testhelpers.RequireImpl(t, err) + Require(t, err) var dumpIt state.IteratorDump err = l2rpc.CallContext(ctx, &dumpIt, "debug_accountRange", rpc.LatestBlockNumber, hexutil.Bytes{}, 10, true, true, false) - testhelpers.RequireImpl(t, err) + Require(t, err) err = l2rpc.CallContext(ctx, &dumpIt, "debug_accountRange", rpc.PendingBlockNumber, hexutil.Bytes{}, 10, true, true, false) - testhelpers.RequireImpl(t, err) + Require(t, err) } diff --git a/system_tests/fees_test.go b/system_tests/fees_test.go index 750293622d..17ab7b69c4 100644 --- a/system_tests/fees_test.go +++ b/system_tests/fees_test.go @@ -20,7 +20,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbcompress" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/l1pricing" "github.com/ethereum/go-ethereum/common" @@ -33,20 +32,20 @@ func TestSequencerFeePaid(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, l2client, _, _, _, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() - execNode := getExecNode(t, l2node) - version := execNode.ArbInterface.BlockChain().Config().ArbitrumChainParams.InitialArbOSVersion - callOpts := l2info.GetDefaultCallOpts("Owner", ctx) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() + + version := builder.L2.ExecNode.ArbInterface.BlockChain().Config().ArbitrumChainParams.InitialArbOSVersion + callOpts := builder.L2Info.GetDefaultCallOpts("Owner", ctx) // get the network fee account - arbOwnerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("0x6b"), l2client) + arbOwnerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("0x6b"), builder.L2.Client) Require(t, err, "failed to deploy contract") - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), builder.L2.Client) Require(t, err, "failed to deploy contract") - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), builder.L2.Client) Require(t, err, "failed to deploy contract") networkFeeAccount, err := arbOwnerPublic.GetNetworkFeeAccount(callOpts) Require(t, err, "could not get the network fee account") @@ -54,24 +53,24 @@ func TestSequencerFeePaid(t *testing.T) { l1Estimate, err := arbGasInfo.GetL1BaseFeeEstimate(callOpts) Require(t, err) - baseFee := GetBaseFee(t, l2client, ctx) - l2info.GasPrice = baseFee + baseFee := GetBaseFee(t, builder.L2.Client, ctx) + builder.L2Info.GasPrice = baseFee testFees := func(tip uint64) (*big.Int, *big.Int) { tipCap := arbmath.BigMulByUint(baseFee, tip) - txOpts := l2info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) txOpts.GasTipCap = tipCap gasPrice := arbmath.BigAdd(baseFee, tipCap) - networkBefore := GetBalance(t, ctx, l2client, networkFeeAccount) + networkBefore := builder.L2.GetBalance(t, networkFeeAccount) tx, err := arbDebug.Events(&txOpts, true, [32]byte{}) Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, l2client, tx) + receipt, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) - networkAfter := GetBalance(t, ctx, l2client, networkFeeAccount) - l1Charge := arbmath.BigMulByUint(l2info.GasPrice, receipt.GasUsedForL1) + networkAfter := builder.L2.GetBalance(t, networkFeeAccount) + l1Charge := arbmath.BigMulByUint(builder.L2Info.GasPrice, receipt.GasUsedForL1) // the network should receive // 1. compute costs @@ -93,7 +92,7 @@ func TestSequencerFeePaid(t *testing.T) { l1GasBought := arbmath.BigDiv(l1Charge, l1Estimate).Uint64() l1ChargeExpected := arbmath.BigMulByUint(l1Estimate, txSize*params.TxDataNonZeroGasEIP2028) // L1 gas can only be charged in terms of L2 gas, so subtract off any rounding error from the expected value - l1ChargeExpected.Sub(l1ChargeExpected, new(big.Int).Mod(l1ChargeExpected, l2info.GasPrice)) + l1ChargeExpected.Sub(l1ChargeExpected, new(big.Int).Mod(l1ChargeExpected, builder.L2Info.GasPrice)) colors.PrintBlue("bytes ", l1GasBought/params.TxDataNonZeroGasEIP2028, txSize) @@ -132,42 +131,39 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - chainConfig := params.ArbitrumDevTestChainConfig() - conf := arbnode.ConfigDefaultL1Test() - conf.DelayedSequencer.FinalizeDistance = 1 - - l2info, node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, chainConfig, nil) - defer requireClose(t, l1stack) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig.DelayedSequencer.FinalizeDistance = 1 + cleanup := builder.Build(t) + defer cleanup() - ownerAuth := l2info.GetDefaultTransactOpts("Owner", ctx) + ownerAuth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) // make ownerAuth a chain owner - arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) + arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), builder.L2.Client) Require(t, err) tx, err := arbdebug.BecomeChainOwner(&ownerAuth) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) // use ownerAuth to set the L1 price per unit Require(t, err) - arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), l2client) + arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), builder.L2.Client) Require(t, err) tx, err = arbOwner.SetL1PricePerUnit(&ownerAuth, arbmath.UintToBig(initialEstimate)) Require(t, err) - _, err = WaitForTx(ctx, l2client, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, builder.L2.Client, tx.Hash(), time.Second*5) Require(t, err) - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), builder.L2.Client) Require(t, err) lastEstimate, err := arbGasInfo.GetL1BaseFeeEstimate(&bind.CallOpts{Context: ctx}) Require(t, err) - lastBatchCount, err := node.InboxTracker.GetBatchCount() + lastBatchCount, err := builder.L2.ConsensusNode.InboxTracker.GetBatchCount() Require(t, err) - l1Header, err := l1client.HeaderByNumber(ctx, nil) + l1Header, err := builder.L1.Client.HeaderByNumber(ctx, nil) Require(t, err) - rewardRecipientBalanceBefore := GetBalance(t, ctx, l2client, l1pricing.BatchPosterAddress) + rewardRecipientBalanceBefore := builder.L2.GetBalance(t, l1pricing.BatchPosterAddress) timesPriceAdjusted := 0 colors.PrintBlue("Initial values") @@ -176,17 +172,17 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { numRetrogradeMoves := 0 for i := 0; i < 256; i++ { - tx, receipt := TransferBalance(t, "Owner", "Owner", common.Big1, l2info, l2client, ctx) - header, err := l2client.HeaderByHash(ctx, receipt.BlockHash) + tx, receipt := builder.L2.TransferBalance(t, "Owner", "Owner", common.Big1, builder.L2Info) + header, err := builder.L2.Client.HeaderByHash(ctx, receipt.BlockHash) Require(t, err) - TransferBalance(t, "Faucet", "Faucet", common.Big1, l1info, l1client, ctx) // generate l1 traffic + builder.L1.TransferBalance(t, "Faucet", "Faucet", common.Big1, builder.L1Info) // generate l1 traffic units := compressedTxSize(t, tx) * params.TxDataNonZeroGasEIP2028 estimatedL1FeePerUnit := arbmath.BigDivByUint(arbmath.BigMulByUint(header.BaseFee, receipt.GasUsedForL1), units) if !arbmath.BigEquals(lastEstimate, estimatedL1FeePerUnit) { - l1Header, err = l1client.HeaderByNumber(ctx, nil) + l1Header, err = builder.L1.Client.HeaderByNumber(ctx, nil) Require(t, err) callOpts := &bind.CallOpts{Context: ctx, BlockNumber: receipt.BlockNumber} @@ -235,7 +231,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { // see that the inbox advances for j := 16; j > 0; j-- { - newBatchCount, err := node.InboxTracker.GetBatchCount() + newBatchCount, err := builder.L2.ConsensusNode.InboxTracker.GetBatchCount() Require(t, err) if newBatchCount > lastBatchCount { colors.PrintGrey("posted new batch ", newBatchCount) @@ -250,7 +246,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { } } - rewardRecipientBalanceAfter := GetBalance(t, ctx, l2client, chainConfig.ArbitrumChainParams.InitialChainOwner) + rewardRecipientBalanceAfter := builder.L2.GetBalance(t, builder.chainConfig.ArbitrumChainParams.InitialChainOwner) colors.PrintMint("reward recipient balance ", rewardRecipientBalanceBefore, " ➤ ", rewardRecipientBalanceAfter) colors.PrintMint("price changes ", timesPriceAdjusted) @@ -261,7 +257,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { Fatal(t, "reward recipient didn't get paid") } - arbAggregator, err := precompilesgen.NewArbAggregator(common.HexToAddress("0x6d"), l2client) + arbAggregator, err := precompilesgen.NewArbAggregator(common.HexToAddress("0x6d"), builder.L2.Client) Require(t, err) batchPosterAddresses, err := arbAggregator.GetBatchPosters(&bind.CallOpts{Context: ctx}) Require(t, err) @@ -269,7 +265,7 @@ func testSequencerPriceAdjustsFrom(t *testing.T, initialEstimate uint64) { for _, bpAddr := range batchPosterAddresses { if bpAddr != l1pricing.BatchPosterAddress && bpAddr != l1pricing.L1PricerFundsPoolAddress { numReimbursed++ - bal, err := l1client.BalanceAt(ctx, bpAddr, nil) + bal, err := builder.L1.Client.BalanceAt(ctx, bpAddr, nil) Require(t, err) if bal.Sign() == 0 { Fatal(t, "Batch poster balance is zero for", bpAddr) diff --git a/system_tests/forwarder_test.go b/system_tests/forwarder_test.go index fc7eb4cc2d..d29e82c12c 100644 --- a/system_tests/forwarder_test.go +++ b/system_tests/forwarder_test.go @@ -15,13 +15,9 @@ import ( "time" "github.com/alicebob/miniredis/v2" - "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/node" "github.com/offchainlabs/nitro/arbnode" - "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/execution/gethexec" - "github.com/offchainlabs/nitro/statetransfer" "github.com/offchainlabs/nitro/util/redisutil" ) @@ -33,16 +29,14 @@ func TestStaticForwarder(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ipcPath := tmpPath(t, "test.ipc") - ipcConfig := genericconf.IPCConfigDefault - ipcConfig.Path = ipcPath - stackConfig := createStackConfigForTest(t.TempDir()) - ipcConfig.Apply(stackConfig) - nodeConfigA := arbnode.ConfigDefaultL1Test() - nodeConfigA.BatchPoster.Enable = false - l2info, nodeA, clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfigA, nil, nil, stackConfig) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig.BatchPoster.Enable = false + builder.l2StackConfig.IPCPath = ipcPath + cleanupA := builder.Build(t) + defer cleanupA() + + clientA := builder.L2.Client nodeConfigB := arbnode.ConfigDefaultL1Test() execConfigB := gethexec.ConfigDefaultTest() @@ -53,18 +47,22 @@ func TestStaticForwarder(t *testing.T) { execConfigB.ForwardingTarget = ipcPath nodeConfigB.BatchPoster.Enable = false - clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, nodeConfigB, execConfigB, nil) - defer nodeB.StopAndWait() + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{ + nodeConfig: nodeConfigB, + execConfig: execConfigB, + }) + defer cleanupB() + clientB := testClientB.Client - l2info.GenerateAccount("User2") - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, transferAmount, nil) + builder.L2Info.GenerateAccount("User2") + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, transferAmount, nil) err := clientB.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, clientA, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - l2balance, err := clientA.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := clientA.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(transferAmount) != 0 { @@ -95,36 +93,18 @@ type fallbackSequencerOpts struct { enableSecCoordinator bool } -func fallbackSequencer( - ctx context.Context, t *testing.T, opts *fallbackSequencerOpts, -) (l2info info, currentNode *arbnode.Node, l2client *ethclient.Client, - l1info info, l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node) { - stackConfig := createStackConfigForTest(t.TempDir()) - ipcConfig := genericconf.IPCConfigDefault - ipcConfig.Path = opts.ipcPath - ipcConfig.Apply(stackConfig) - nodeConfig := arbnode.ConfigDefaultL1Test() - nodeConfig.SeqCoordinator.Enable = opts.enableSecCoordinator - nodeConfig.SeqCoordinator.RedisUrl = opts.redisUrl - nodeConfig.SeqCoordinator.MyUrl = opts.ipcPath - return createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, nil, stackConfig) +func fallbackSequencer(ctx context.Context, t *testing.T, opts *fallbackSequencerOpts) *NodeBuilder { + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.l2StackConfig.IPCPath = opts.ipcPath + builder.nodeConfig.SeqCoordinator.Enable = opts.enableSecCoordinator + builder.nodeConfig.SeqCoordinator.RedisUrl = opts.redisUrl + builder.nodeConfig.SeqCoordinator.MyUrl = opts.ipcPath + return builder } -func createForwardingNode( - ctx context.Context, t *testing.T, - first *arbnode.Node, - l1stack *node.Node, - l1info *BlockchainTestInfo, - l2InitData *statetransfer.ArbosInitializationInfo, - ipcPath string, - redisUrl string, - fallbackPath string, -) (*ethclient.Client, *arbnode.Node) { - stackConfig := createStackConfigForTest(t.TempDir()) +func createForwardingNode(t *testing.T, builder *NodeBuilder, ipcPath string, redisUrl string, fallbackPath string) (*TestClient, func()) { if ipcPath != "" { - ipcConfig := genericconf.IPCConfigDefault - ipcConfig.Path = ipcPath - ipcConfig.Apply(stackConfig) + builder.l2StackConfig.IPCPath = ipcPath } nodeConfig := arbnode.ConfigDefaultL1Test() nodeConfig.Sequencer = false @@ -136,29 +116,18 @@ func createForwardingNode( execConfig.ForwardingTarget = fallbackPath // nodeConfig.Feed.Output.Enable = false - return Create2ndNodeWithConfig(t, ctx, first, l1stack, l1info, l2InitData, nodeConfig, execConfig, stackConfig) + return builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: nodeConfig, execConfig: execConfig}) } -func createSequencer( - ctx context.Context, t *testing.T, - first *arbnode.Node, - l1stack *node.Node, - l1info *BlockchainTestInfo, - l2InitData *statetransfer.ArbosInitializationInfo, - ipcPath string, - redisUrl string, -) (*ethclient.Client, *arbnode.Node) { - stackConfig := createStackConfigForTest(t.TempDir()) - ipcConfig := genericconf.IPCConfigDefault - ipcConfig.Path = ipcPath - ipcConfig.Apply(stackConfig) +func createSequencer(t *testing.T, builder *NodeBuilder, ipcPath string, redisUrl string) (*TestClient, func()) { + builder.l2StackConfig.IPCPath = ipcPath nodeConfig := arbnode.ConfigDefaultL1Test() nodeConfig.BatchPoster.Enable = false nodeConfig.SeqCoordinator.Enable = true nodeConfig.SeqCoordinator.RedisUrl = redisUrl nodeConfig.SeqCoordinator.MyUrl = ipcPath - return Create2ndNodeWithConfig(t, ctx, first, l1stack, l1info, l2InitData, nodeConfig, gethexec.ConfigDefaultTest(), stackConfig) + return builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: nodeConfig}) } // tmpPath returns file path with specified filename from temporary directory of the test. @@ -252,34 +221,36 @@ func TestRedisForwarder(t *testing.T) { redisServer, redisUrl := initRedis(ctx, t, append(nodePaths, fbNodePath)) defer redisServer.Close() - l2info, fallbackNode, fallbackClient, l1info, _, _, l1stack := fallbackSequencer(ctx, t, + builder := fallbackSequencer(ctx, t, &fallbackSequencerOpts{ ipcPath: fbNodePath, redisUrl: redisUrl, enableSecCoordinator: true, }) - defer requireClose(t, l1stack) - defer fallbackNode.StopAndWait() + cleanup := builder.Build(t) + defer cleanup() + fallbackNode, fallbackClient := builder.L2.ConsensusNode, builder.L2.Client - forwardingClient, forwardingNode := createForwardingNode(ctx, t, fallbackNode, l1stack, l1info, &l2info.ArbInitData, "", redisUrl, fbNodePath) - defer forwardingNode.StopAndWait() + TestClientForwarding, cleanupForwarding := createForwardingNode(t, builder, "", redisUrl, fbNodePath) + defer cleanupForwarding() + forwardingClient := TestClientForwarding.Client var seqNodes []*arbnode.Node var seqClients []*ethclient.Client for _, path := range nodePaths { - client, node := createSequencer(ctx, t, fallbackNode, l1stack, l1info, &l2info.ArbInitData, path, redisUrl) - seqNodes = append(seqNodes, node) - seqClients = append(seqClients, client) + testClientSeq, _ := createSequencer(t, builder, path, redisUrl) + seqNodes = append(seqNodes, testClientSeq.ConsensusNode) + seqClients = append(seqClients, testClientSeq.Client) } defer stopNodes(seqNodes) for i := range seqClients { userA := user("A", i) - l2info.GenerateAccount(userA) - tx := l2info.PrepareTx("Owner", userA, l2info.TransferGas, big.NewInt(1e12+int64(l2info.TransferGas)*l2info.GasPrice.Int64()), nil) + builder.L2Info.GenerateAccount(userA) + tx := builder.L2Info.PrepareTx("Owner", userA, builder.L2Info.TransferGas, big.NewInt(1e12+int64(builder.L2Info.TransferGas)*builder.L2Info.GasPrice.Int64()), nil) err := fallbackClient.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, fallbackClient, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) } @@ -289,8 +260,8 @@ func TestRedisForwarder(t *testing.T) { } userA := user("A", i) userB := user("B", i) - l2info.GenerateAccount(userB) - tx := l2info.PrepareTx(userA, userB, l2info.TransferGas, transferAmount, nil) + builder.L2Info.GenerateAccount(userB) + tx := builder.L2Info.PrepareTx(userA, userB, builder.L2Info.TransferGas, transferAmount, nil) sendFunc := func() error { return forwardingClient.SendTransaction(ctx, tx) } if err := tryWithTimeout(ctx, sendFunc, gethexec.DefaultTestForwarderConfig.UpdateInterval*10); err != nil { @@ -299,7 +270,7 @@ func TestRedisForwarder(t *testing.T) { _, err := EnsureTxSucceeded(ctx, seqClients[i], tx) Require(t, err) - l2balance, err := seqClients[i].BalanceAt(ctx, l2info.GetAddress(userB), nil) + l2balance, err := seqClients[i].BalanceAt(ctx, builder.L2Info.GetAddress(userB), nil) Require(t, err) if l2balance.Cmp(transferAmount) != 0 { @@ -320,29 +291,31 @@ func TestRedisForwarderFallbackNoRedis(t *testing.T) { redisServer, redisUrl := initRedis(ctx, t, nodePaths) redisServer.Close() - l2info, fallbackNode, fallbackClient, l1info, _, _, l1stack := fallbackSequencer(ctx, t, + builder := fallbackSequencer(ctx, t, &fallbackSequencerOpts{ ipcPath: fallbackIpcPath, redisUrl: redisUrl, enableSecCoordinator: false, }) - defer requireClose(t, l1stack) - defer fallbackNode.StopAndWait() + cleanup := builder.Build(t) + defer cleanup() + fallbackClient := builder.L2.Client - forwardingClient, forwardingNode := createForwardingNode(ctx, t, fallbackNode, l1stack, l1info, &l2info.ArbInitData, "", redisUrl, fallbackIpcPath) - defer forwardingNode.StopAndWait() + TestClientForwarding, cleanupForwarding := createForwardingNode(t, builder, "", redisUrl, fallbackIpcPath) + defer cleanupForwarding() + forwardingClient := TestClientForwarding.Client user := "User2" - l2info.GenerateAccount(user) - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, transferAmount, nil) + builder.L2Info.GenerateAccount(user) + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, transferAmount, nil) sendFunc := func() error { return forwardingClient.SendTransaction(ctx, tx) } err := tryWithTimeout(ctx, sendFunc, gethexec.DefaultTestForwarderConfig.UpdateInterval*10) Require(t, err) - _, err = EnsureTxSucceeded(ctx, fallbackClient, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - l2balance, err := fallbackClient.BalanceAt(ctx, l2info.GetAddress(user), nil) + l2balance, err := fallbackClient.BalanceAt(ctx, builder.L2Info.GetAddress(user), nil) Require(t, err) if l2balance.Cmp(transferAmount) != 0 { diff --git a/system_tests/ipc_test.go b/system_tests/ipc_test.go index dc73825a13..511a608e67 100644 --- a/system_tests/ipc_test.go +++ b/system_tests/ipc_test.go @@ -9,24 +9,18 @@ import ( "testing" "github.com/ethereum/go-ethereum/ethclient" - "github.com/offchainlabs/nitro/cmd/genericconf" ) func TestIpcRpc(t *testing.T) { ipcPath := filepath.Join(t.TempDir(), "test.ipc") - ipcConfig := genericconf.IPCConfigDefault - ipcConfig.Path = ipcPath - - stackConf := createStackConfigForTest(t.TempDir()) - ipcConfig.Apply(stackConf) - ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, l2node, _, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, nil, nil, stackConf) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.l2StackConfig.IPCPath = ipcPath + cleanup := builder.Build(t) + defer cleanup() _, err := ethclient.Dial(ipcPath) Require(t, err) diff --git a/system_tests/meaningless_reorg_test.go b/system_tests/meaningless_reorg_test.go index 7fb6934e84..f09f68041a 100644 --- a/system_tests/meaningless_reorg_test.go +++ b/system_tests/meaningless_reorg_test.go @@ -10,7 +10,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/solgen/go/bridgegen" ) @@ -18,27 +17,26 @@ func TestMeaninglessBatchReorg(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - conf := arbnode.ConfigDefaultL1Test() - conf.BatchPoster.Enable = false - l2Info, arbNode, l2Client, l1Info, l1Backend, l1Client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, conf, nil, nil, nil) - defer requireClose(t, l1stack) - defer arbNode.StopAndWait() - seqInbox, err := bridgegen.NewSequencerInbox(l1Info.GetAddress("SequencerInbox"), l1Client) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig.BatchPoster.Enable = false + cleanup := builder.Build(t) + defer cleanup() + + seqInbox, err := bridgegen.NewSequencerInbox(builder.L1Info.GetAddress("SequencerInbox"), builder.L1.Client) Require(t, err) - seqOpts := l1Info.GetDefaultTransactOpts("Sequencer", ctx) + seqOpts := builder.L1Info.GetDefaultTransactOpts("Sequencer", ctx) tx, err := seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(1), nil, big.NewInt(1), common.Address{}) Require(t, err) - batchReceipt, err := EnsureTxSucceeded(ctx, l1Client, tx) + batchReceipt, err := builder.L1.EnsureTxSucceeded(tx) Require(t, err) - execNode := getExecNode(t, arbNode) for i := 0; ; i++ { if i >= 500 { Fatal(t, "Failed to read batch from L1") } - msgNum, err := execNode.ExecEngine.HeadMessageNumber() + msgNum, err := builder.L2.ExecNode.ExecEngine.HeadMessageNumber() Require(t, err) if msgNum == 1 { break @@ -47,33 +45,33 @@ func TestMeaninglessBatchReorg(t *testing.T) { } time.Sleep(10 * time.Millisecond) } - metadata, err := arbNode.InboxTracker.GetBatchMetadata(1) + metadata, err := builder.L2.ConsensusNode.InboxTracker.GetBatchMetadata(1) Require(t, err) originalBatchBlock := batchReceipt.BlockNumber.Uint64() if metadata.ParentChainBlock != originalBatchBlock { Fatal(t, "Posted batch in block", originalBatchBlock, "but metadata says L1 block was", metadata.ParentChainBlock) } - _, l2Receipt := TransferBalance(t, "Owner", "Owner", common.Big1, l2Info, l2Client, ctx) + _, l2Receipt := builder.L2.TransferBalance(t, "Owner", "Owner", common.Big1, builder.L2Info) // Make the reorg larger to force the miner to discard transactions. // The miner usually collects transactions from deleted blocks and puts them in the mempool. // However, this code doesn't run on reorgs larger than 64 blocks for performance reasons. // Therefore, we make a bunch of small blocks to prevent the code from running. for j := uint64(0); j < 70; j++ { - TransferBalance(t, "Faucet", "Faucet", common.Big1, l1Info, l1Client, ctx) + builder.L1.TransferBalance(t, "Faucet", "Faucet", common.Big1, builder.L1Info) } - parentBlock := l1Backend.BlockChain().GetBlockByNumber(batchReceipt.BlockNumber.Uint64() - 1) - err = l1Backend.BlockChain().ReorgToOldBlock(parentBlock) + parentBlock := builder.L1.L1Backend.BlockChain().GetBlockByNumber(batchReceipt.BlockNumber.Uint64() - 1) + err = builder.L1.L1Backend.BlockChain().ReorgToOldBlock(parentBlock) Require(t, err) // Produce a new l1Block so that the batch ends up in a different l1Block than before - TransferBalance(t, "User", "User", common.Big1, l1Info, l1Client, ctx) + builder.L1.TransferBalance(t, "User", "User", common.Big1, builder.L1Info) tx, err = seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(1), nil, big.NewInt(1), common.Address{}) Require(t, err) - newBatchReceipt, err := EnsureTxSucceeded(ctx, l1Client, tx) + newBatchReceipt, err := builder.L1.EnsureTxSucceeded(tx) Require(t, err) newBatchBlock := newBatchReceipt.BlockNumber.Uint64() @@ -87,7 +85,7 @@ func TestMeaninglessBatchReorg(t *testing.T) { if i >= 500 { Fatal(t, "Failed to read batch reorg from L1") } - metadata, err = arbNode.InboxTracker.GetBatchMetadata(1) + metadata, err = builder.L2.ConsensusNode.InboxTracker.GetBatchMetadata(1) Require(t, err) if metadata.ParentChainBlock == newBatchBlock { break @@ -97,10 +95,10 @@ func TestMeaninglessBatchReorg(t *testing.T) { time.Sleep(10 * time.Millisecond) } - _, err = arbNode.InboxReader.GetSequencerMessageBytes(ctx, 1) + _, err = builder.L2.ConsensusNode.InboxReader.GetSequencerMessageBytes(ctx, 1) Require(t, err) - l2Header, err := l2Client.HeaderByNumber(ctx, l2Receipt.BlockNumber) + l2Header, err := builder.L2.Client.HeaderByNumber(ctx, l2Receipt.BlockNumber) Require(t, err) if l2Header.Hash() != l2Receipt.BlockHash { diff --git a/system_tests/seq_coordinator_test.go b/system_tests/seq_coordinator_test.go index a213c366cf..ac3167a604 100644 --- a/system_tests/seq_coordinator_test.go +++ b/system_tests/seq_coordinator_test.go @@ -14,7 +14,6 @@ import ( "github.com/go-redis/redis/v8" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/arbostypes" @@ -47,11 +46,12 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - nodeConfig := arbnode.ConfigDefaultL2Test() - nodeConfig.SeqCoordinator.Enable = true - nodeConfig.SeqCoordinator.RedisUrl = redisutil.CreateTestRedis(ctx, t) + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.takeOwnership = false + builder.nodeConfig.SeqCoordinator.Enable = true + builder.nodeConfig.SeqCoordinator.RedisUrl = redisutil.CreateTestRedis(ctx, t) - l2Info := NewArbTestInfo(t, params.ArbitrumDevTestChainConfig().ChainID) + l2Info := builder.L2Info // stdio protocol makes sure forwarder initialization doesn't fail nodeNames := []string{"stdio://A", "stdio://B", "stdio://C", "stdio://D", "stdio://E"} @@ -59,12 +59,13 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { nodes := make([]*arbnode.Node, len(nodeNames)) // init DB to known state - initRedisForTest(t, ctx, nodeConfig.SeqCoordinator.RedisUrl, nodeNames) + initRedisForTest(t, ctx, builder.nodeConfig.SeqCoordinator.RedisUrl, nodeNames) createStartNode := func(nodeNum int) { - nodeConfig.SeqCoordinator.MyUrl = nodeNames[nodeNum] - _, node, _ := CreateTestL2WithConfig(t, ctx, l2Info, nodeConfig, nil, false) - nodes[nodeNum] = node + builder.nodeConfig.SeqCoordinator.MyUrl = nodeNames[nodeNum] + builder.L2Info = l2Info + builder.Build(t) + nodes[nodeNum] = builder.L2.ConsensusNode } trySequencing := func(nodeNum int) bool { @@ -128,7 +129,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { if attempts > 10 { Fatal(t, "timeout waiting for msg ", msgNum, " debug: ", currentNode.SeqCoordinator.DebugPrint()) } - <-time.After(nodeConfig.SeqCoordinator.UpdateInterval / 3) + <-time.After(builder.nodeConfig.SeqCoordinator.UpdateInterval / 3) } } } @@ -232,7 +233,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { } if sequencer == -1 || (addNodes && (sequencer == currentSequencer+1)) { - time.Sleep(nodeConfig.SeqCoordinator.LockoutDuration / 5) + time.Sleep(builder.nodeConfig.SeqCoordinator.LockoutDuration / 5) continue } if sequencer == currentSequencer { @@ -270,21 +271,20 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - nodeConfig := arbnode.ConfigDefaultL1Test() - nodeConfig.SeqCoordinator.Enable = true - nodeConfig.SeqCoordinator.RedisUrl = redisutil.CreateTestRedis(ctx, t) - nodeConfig.BatchPoster.Enable = false + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig.SeqCoordinator.Enable = true + builder.nodeConfig.SeqCoordinator.RedisUrl = redisutil.CreateTestRedis(ctx, t) + builder.nodeConfig.BatchPoster.Enable = false nodeNames := []string{"stdio://A", "stdio://B"} + initRedisForTest(t, ctx, builder.nodeConfig.SeqCoordinator.RedisUrl, nodeNames) + builder.nodeConfig.SeqCoordinator.MyUrl = nodeNames[0] - initRedisForTest(t, ctx, nodeConfig.SeqCoordinator.RedisUrl, nodeNames) + cleanup := builder.Build(t) + defer cleanup() + clientA := builder.L2.Client - nodeConfig.SeqCoordinator.MyUrl = nodeNames[0] - l2Info, nodeA, clientA, l1info, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfig, nil, params.ArbitrumDevTestChainConfig(), nil) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() - - redisClient, err := redisutil.RedisClientFromURL(nodeConfig.SeqCoordinator.RedisUrl) + redisClient, err := redisutil.RedisClientFromURL(builder.nodeConfig.SeqCoordinator.RedisUrl) Require(t, err) defer redisClient.Close() @@ -292,27 +292,29 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { for { err := redisClient.Get(ctx, redisutil.CHOSENSEQ_KEY).Err() if errors.Is(err, redis.Nil) { - time.Sleep(nodeConfig.SeqCoordinator.UpdateInterval) + time.Sleep(builder.nodeConfig.SeqCoordinator.UpdateInterval) continue } Require(t, err) break } - l2Info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - nodeConfigDup := *nodeConfig - nodeConfig = &nodeConfigDup + nodeConfigDup := *builder.nodeConfig + builder.nodeConfig = &nodeConfigDup - nodeConfig.SeqCoordinator.MyUrl = nodeNames[1] + builder.nodeConfig.SeqCoordinator.MyUrl = nodeNames[1] if !successCase { - nodeConfig.SeqCoordinator.Signer.ECDSA.AcceptSequencer = false - nodeConfig.SeqCoordinator.Signer.ECDSA.AllowedAddresses = []string{l2Info.GetAddress("User2").Hex()} + builder.nodeConfig.SeqCoordinator.Signer.ECDSA.AcceptSequencer = false + builder.nodeConfig.SeqCoordinator.Signer.ECDSA.AllowedAddresses = []string{builder.L2Info.GetAddress("User2").Hex()} } - clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2Info.ArbInitData, nodeConfig, nil, nil) - defer nodeB.StopAndWait() - tx := l2Info.PrepareTx("Owner", "User2", l2Info.TransferGas, big.NewInt(1e12), nil) + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: builder.nodeConfig}) + defer cleanupB() + clientB := testClientB.Client + + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) err = clientA.SendTransaction(ctx, tx) Require(t, err) @@ -323,7 +325,7 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { if successCase { _, err = WaitForTx(ctx, clientB, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := clientB.BalanceAt(ctx, l2Info.GetAddress("User2"), nil) + l2balance, err := clientB.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index d0d05d569e..749a91e3b1 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -13,7 +13,6 @@ import ( "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/broadcastclient" - "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/relay" "github.com/offchainlabs/nitro/util/signature" "github.com/offchainlabs/nitro/wsbroadcastserver" @@ -43,30 +42,33 @@ func TestSequencerFeed(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - seqNodeConfig := arbnode.ConfigDefaultL2Test() - seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true) - defer nodeA.StopAndWait() - clientNodeConfig := arbnode.ConfigDefaultL2Test() - port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port - clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) + builderSeq := NewNodeBuilder(ctx).DefaultConfig(t, false) + builderSeq.nodeConfig.Feed.Output = *newBroadcasterConfigTest() + cleanupSeq := builderSeq.Build(t) + defer cleanupSeq() + seqInfo, seqNode, seqClient := builderSeq.L2Info, builderSeq.L2.ConsensusNode, builderSeq.L2.Client - _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false) - defer nodeB.StopAndWait() + port := seqNode.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.nodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) + builder.takeOwnership = false + cleanup := builder.Build(t) + defer cleanup() + client := builder.L2.Client - l2info1.GenerateAccount("User2") + seqInfo.GenerateAccount("User2") - tx := l2info1.PrepareTx("Owner", "User2", l2info1.TransferGas, big.NewInt(1e12), nil) + tx := seqInfo.PrepareTx("Owner", "User2", seqInfo.TransferGas, big.NewInt(1e12), nil) - err := client1.SendTransaction(ctx, tx) + err := seqClient.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client1, tx) + _, err = builderSeq.L2.EnsureTxSucceeded(tx) Require(t, err) - _, err = WaitForTx(ctx, client2, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, client, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := client2.BalanceAt(ctx, l2info1.GetAddress("User2"), nil) + l2balance, err := client.BalanceAt(ctx, seqInfo.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) @@ -78,16 +80,17 @@ func TestRelayedSequencerFeed(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - seqNodeConfig := arbnode.ConfigDefaultL2Test() - seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true) - defer nodeA.StopAndWait() + builderSeq := NewNodeBuilder(ctx).DefaultConfig(t, false) + builderSeq.nodeConfig.Feed.Output = *newBroadcasterConfigTest() + cleanupSeq := builderSeq.Build(t) + defer cleanupSeq() + seqInfo, seqNode, seqClient := builderSeq.L2Info, builderSeq.L2.ConsensusNode, builderSeq.L2.Client - bigChainId, err := client1.ChainID(ctx) + bigChainId, err := seqClient.ChainID(ctx) Require(t, err) config := relay.ConfigDefault - port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port + port := seqNode.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port config.Node.Feed.Input = *newBroadcastClientConfigTest(port) config.Node.Feed.Output = *newBroadcasterConfigTest() config.Chain.ID = bigChainId.Uint64() @@ -99,26 +102,28 @@ func TestRelayedSequencerFeed(t *testing.T) { Require(t, err) defer currentRelay.StopAndWait() - clientNodeConfig := arbnode.ConfigDefaultL2Test() port = currentRelay.GetListenerAddr().(*net.TCPAddr).Port - clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - _, nodeC, client3 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false) - defer nodeC.StopAndWait() - StartWatchChanErr(t, ctx, feedErrChan, nodeC) + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.nodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) + builder.takeOwnership = false + cleanup := builder.Build(t) + defer cleanup() + node, client := builder.L2.ConsensusNode, builder.L2.Client + StartWatchChanErr(t, ctx, feedErrChan, node) - l2info1.GenerateAccount("User2") + seqInfo.GenerateAccount("User2") - tx := l2info1.PrepareTx("Owner", "User2", l2info1.TransferGas, big.NewInt(1e12), nil) + tx := seqInfo.PrepareTx("Owner", "User2", seqInfo.TransferGas, big.NewInt(1e12), nil) - err = client1.SendTransaction(ctx, tx) + err = seqClient.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client1, tx) + _, err = builderSeq.L2.EnsureTxSucceeded(tx) Require(t, err) - _, err = WaitForTx(ctx, client3, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, client, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := client3.BalanceAt(ctx, l2info1.GetAddress("User2"), nil) + l2balance, err := client.BalanceAt(ctx, seqInfo.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) @@ -136,11 +141,16 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigA.BatchPoster.Enable = true nodeConfigA.Feed.Output.Enable = false - l2infoA, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nodeConfigA, nil, chainConfig, nil) - defer requireClose(t, l1stack, "unable to close l1stack") - defer nodeA.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig = nodeConfigA + builder.chainConfig = chainConfig + builder.L2Info = nil + cleanup := builder.Build(t) + defer cleanup() - authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) + l2clientA := builder.L2.Client + + authorizeDASKeyset(t, ctx, dasSignerKey, builder.L1Info, builder.L1.Client) // The lying sequencer nodeConfigC := arbnode.ConfigDefaultL1Test() @@ -148,8 +158,9 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigC.DataAvailability = nodeConfigA.DataAvailability nodeConfigC.DataAvailability.RPCAggregator.Enable = false nodeConfigC.Feed.Output = *newBroadcasterConfigTest() - l2clientC, nodeC := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2infoA.ArbInitData, nodeConfigC, gethexec.ConfigDefaultTest(), nil) - defer nodeC.StopAndWait() + testClientC, cleanupC := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: nodeConfigC}) + defer cleanupC() + l2clientC, nodeC := testClientC.Client, testClientC.ConsensusNode port := nodeC.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port @@ -159,15 +170,16 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { nodeConfigB.Feed.Input = *newBroadcastClientConfigTest(port) nodeConfigB.DataAvailability = nodeConfigA.DataAvailability nodeConfigB.DataAvailability.RPCAggregator.Enable = false - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2infoA.ArbInitData, nodeConfigB, nil, nil) - defer nodeB.StopAndWait() + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: nodeConfigB}) + defer cleanupB() + l2clientB := testClientB.Client - l2infoA.GenerateAccount("FraudUser") - l2infoA.GenerateAccount("RealUser") + builder.L2Info.GenerateAccount("FraudUser") + builder.L2Info.GenerateAccount("RealUser") - fraudTx := l2infoA.PrepareTx("Owner", "FraudUser", l2infoA.TransferGas, big.NewInt(1e12), nil) - l2infoA.GetInfoWithPrivKey("Owner").Nonce -= 1 // Use same l2info object for different l2s - realTx := l2infoA.PrepareTx("Owner", "RealUser", l2infoA.TransferGas, big.NewInt(1e12), nil) + fraudTx := builder.L2Info.PrepareTx("Owner", "FraudUser", builder.L2Info.TransferGas, big.NewInt(1e12), nil) + builder.L2Info.GetInfoWithPrivKey("Owner").Nonce -= 1 // Use same l2info object for different l2s + realTx := builder.L2Info.PrepareTx("Owner", "RealUser", builder.L2Info.TransferGas, big.NewInt(1e12), nil) for i := 0; i < 10; i++ { err := l2clientC.SendTransaction(ctx, fraudTx) @@ -180,7 +192,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { } } - _, err := EnsureTxSucceeded(ctx, l2clientC, fraudTx) + _, err := testClientC.EnsureTxSucceeded(fraudTx) if err != nil { t.Fatal("error ensuring fraud transaction succeeded:", err) } @@ -190,7 +202,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { if err != nil { t.Fatal("error waiting for tx:", err) } - l2balance, err := l2clientB.BalanceAt(ctx, l2infoA.GetAddress("FraudUser"), nil) + l2balance, err := l2clientB.BalanceAt(ctx, builder.L2Info.GetAddress("FraudUser"), nil) if err != nil { t.Fatal("error getting balance:", err) } @@ -204,7 +216,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { t.Fatal("error sending real transaction:", err) } - _, err = EnsureTxSucceeded(ctx, l2clientA, realTx) + _, err = builder.L2.EnsureTxSucceeded(realTx) if err != nil { t.Fatal("error ensuring real transaction succeeded:", err) } @@ -214,7 +226,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { if err != nil { t.Fatal("error waiting for transaction to get to node b:", err) } - l2balanceFraudAcct, err := l2clientB.BalanceAt(ctx, l2infoA.GetAddress("FraudUser"), nil) + l2balanceFraudAcct, err := l2clientB.BalanceAt(ctx, builder.L2Info.GetAddress("FraudUser"), nil) if err != nil { t.Fatal("error getting fraud balance:", err) } @@ -222,7 +234,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { t.Fatal("Unexpected balance (fraud acct should be empty) was:", l2balanceFraudAcct) } - l2balanceRealAcct, err := l2clientB.BalanceAt(ctx, l2infoA.GetAddress("RealUser"), nil) + l2balanceRealAcct, err := l2clientB.BalanceAt(ctx, builder.L2Info.GetAddress("RealUser"), nil) if err != nil { t.Fatal("error getting real balance:", err) } diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index a456dc5fe9..c90617455a 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -138,32 +138,33 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - conf := arbnode.ConfigDefaultL1Test() - conf.InboxReader.HardReorg = true + + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig.InboxReader.HardReorg = true if validator { - conf.BlockValidator.Enable = true + builder.nodeConfig.BlockValidator.Enable = true } - l2Info, arbNode, _, l1Info, l1backend, l1Client, l1stack := createTestNodeOnL1WithConfig(t, ctx, false, conf, nil, nil, nil) - execNode := getExecNode(t, arbNode) - l2Backend := execNode.Backend - defer requireClose(t, l1stack) - defer arbNode.StopAndWait() + builder.isSequencer = false + cleanup := builder.Build(t) + defer cleanup() + + l2Backend := builder.L2.ExecNode.Backend - l1BlockChain := l1backend.BlockChain() + l1BlockChain := builder.L1.L1Backend.BlockChain() - rpcC, err := l1stack.Attach() + rpcC, err := builder.L1.Stack.Attach() if err != nil { t.Fatalf("Error connecting to l1 node: %v", err) } gethClient := gethclient.New(rpcC) - seqInbox, err := bridgegen.NewSequencerInbox(l1Info.GetAddress("SequencerInbox"), l1Client) + seqInbox, err := bridgegen.NewSequencerInbox(builder.L1Info.GetAddress("SequencerInbox"), builder.L1.Client) Require(t, err) - seqOpts := l1Info.GetDefaultTransactOpts("Sequencer", ctx) + seqOpts := builder.L1Info.GetDefaultTransactOpts("Sequencer", ctx) - gasRefunderAddr := deployGasRefunder(ctx, t, l1Info, l1Client) + gasRefunderAddr := deployGasRefunder(ctx, t, builder.L1Info, builder.L1.Client) - ownerAddress := l2Info.GetAddress("Owner") + ownerAddress := builder.L2Info.GetAddress("Owner") var startL2BlockNumber uint64 = 0 startState, _, err := l2Backend.APIBackend().StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) @@ -196,10 +197,10 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { } var faucetTxs []*types.Transaction for _, acct := range accounts { - l1Info.GenerateAccount(acct) - faucetTxs = append(faucetTxs, l1Info.PrepareTx("Faucet", acct, 30000, big.NewInt(1e16), nil)) + builder.L1Info.GenerateAccount(acct) + faucetTxs = append(faucetTxs, builder.L1Info.PrepareTx("Faucet", acct, 30000, big.NewInt(1e16), nil)) } - SendWaitTestTransactions(t, ctx, l1Client, faucetTxs) + SendWaitTestTransactions(t, ctx, builder.L1.Client, faucetTxs) seqABI, err := bridgegen.SequencerInboxMetaData.GetAbi() if err != nil { @@ -216,7 +217,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { // The miner usually collects transactions from deleted blocks and puts them in the mempool. // However, this code doesn't run on reorgs larger than 64 blocks for performance reasons. // Therefore, we make a bunch of small blocks to prevent the code from running. - padAddr := l1Info.GetAddress("ReorgPadding") + padAddr := builder.L1Info.GetAddress("ReorgPadding") for j := uint64(0); j < 70; j++ { rawTx := &types.DynamicFeeTx{ To: &padAddr, @@ -225,12 +226,12 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { Value: new(big.Int), Nonce: j, } - tx := l1Info.SignTxAs("ReorgPadding", rawTx) - Require(t, l1Client.SendTransaction(ctx, tx)) - _, _ = EnsureTxSucceeded(ctx, l1Client, tx) + tx := builder.L1Info.SignTxAs("ReorgPadding", rawTx) + Require(t, builder.L1.Client.SendTransaction(ctx, tx)) + _, _ = builder.L1.EnsureTxSucceeded(tx) } reorgTargetNumber := blockStates[reorgTo].l1BlockNumber - currentHeader, err := l1Client.HeaderByNumber(ctx, nil) + currentHeader, err := builder.L1.Client.HeaderByNumber(ctx, nil) Require(t, err) if currentHeader.Number.Int64()-int64(reorgTargetNumber) < 65 { Fatal(t, "Less than 65 blocks of difference between current block", currentHeader.Number, "and target", reorgTargetNumber) @@ -245,10 +246,10 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { // Sometimes, this causes it to drop the next tx. // To work around this, we create a sacrificial tx, which may or may not succeed. // Whichever happens, by the end of this block, the miner will have processed the reorg. - tx := l1Info.PrepareTx(fmt.Sprintf("ReorgSacrifice%v", i/10), "Faucet", 30000, big.NewInt(0), nil) - err = l1Client.SendTransaction(ctx, tx) + tx := builder.L1Info.PrepareTx(fmt.Sprintf("ReorgSacrifice%v", i/10), "Faucet", 30000, big.NewInt(0), nil) + err = builder.L1.Client.SendTransaction(ctx, tx) Require(t, err) - _, _ = WaitForTx(ctx, l1Client, tx.Hash(), time.Second) + _, _ = WaitForTx(ctx, builder.L1.Client, tx.Hash(), time.Second) } else { state := blockStates[len(blockStates)-1] newBalances := make(map[common.Address]*big.Int) @@ -276,10 +277,10 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { var dest common.Address if j == 0 && amount.Cmp(reserveAmount) >= 0 { name := accountName(len(state.accounts)) - if !l2Info.HasAccount(name) { - l2Info.GenerateAccount(name) + if !builder.L2Info.HasAccount(name) { + builder.L2Info.GenerateAccount(name) } - dest = l2Info.GetAddress(name) + dest = builder.L2Info.GetAddress(name) state.accounts = append(state.accounts, dest) state.balances[dest] = big.NewInt(0) } else { @@ -294,7 +295,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { Nonce: state.nonces[source], } state.nonces[source]++ - tx := l2Info.SignTxAs(accountName(sourceNum), rawTx) + tx := builder.L2Info.SignTxAs(accountName(sourceNum), rawTx) txData, err := tx.MarshalBinary() Require(t, err) var segment []byte @@ -314,7 +315,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { seqNonce := len(blockStates) - 1 for j := 0; ; j++ { - haveNonce, err := l1Client.PendingNonceAt(ctx, seqOpts.From) + haveNonce, err := builder.L1.Client.PendingNonceAt(ctx, seqOpts.From) Require(t, err) if haveNonce == uint64(seqNonce) { break @@ -326,7 +327,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { } seqOpts.Nonce = big.NewInt(int64(seqNonce)) var tx *types.Transaction - before, err := l1Client.BalanceAt(ctx, seqOpts.From, nil) + before, err := builder.L1.Client.BalanceAt(ctx, seqOpts.From, nil) if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", seqOpts.From, err) } @@ -335,7 +336,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { if err != nil { t.Fatalf("Error encoding batch data: %v", err) } - si := l1Info.GetAddress("SequencerInbox") + si := builder.L1Info.GetAddress("SequencerInbox") wantAL, _, _, err := gethClient.CreateAccessList(ctx, ethereum.CallMsg{ From: seqOpts.From, To: &si, @@ -345,8 +346,8 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { t.Fatalf("Error creating access list: %v", err) } accessed := arbnode.AccessList(&arbnode.AccessListOpts{ - SequencerInboxAddr: l1Info.GetAddress("SequencerInbox"), - BridgeAddr: l1Info.GetAddress("Bridge"), + SequencerInboxAddr: builder.L1Info.GetAddress("SequencerInbox"), + BridgeAddr: builder.L1Info.GetAddress("Bridge"), DataPosterAddr: seqOpts.From, GasRefunderAddr: gasRefunderAddr, SequencerInboxAccs: len(blockStates), @@ -361,18 +362,18 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { tx, err = seqInbox.AddSequencerL2BatchFromOrigin(&seqOpts, big.NewInt(int64(len(blockStates))), batchData, big.NewInt(1), gasRefunderAddr) } Require(t, err) - txRes, err := EnsureTxSucceeded(ctx, l1Client, tx) + txRes, err := builder.L1.EnsureTxSucceeded(tx) if err != nil { // Geth's clique miner is finicky. // Unfortunately this is so rare that I haven't had an opportunity to test this workaround. // Specifically, I suspect there's a race where it thinks there's no txs to put in the new block, // if a new tx arrives at the same time as it tries to create a block. // Resubmit the transaction in an attempt to get the miner going again. - _ = l1Client.SendTransaction(ctx, tx) - txRes, err = EnsureTxSucceeded(ctx, l1Client, tx) + _ = builder.L1.Client.SendTransaction(ctx, tx) + txRes, err = builder.L1.EnsureTxSucceeded(tx) Require(t, err) } - after, err := l1Client.BalanceAt(ctx, seqOpts.From, nil) + after, err := builder.L1.Client.BalanceAt(ctx, seqOpts.From, nil) if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", seqOpts.From, err) } @@ -414,9 +415,9 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { if validator && i%15 == 0 { for i := 0; ; i++ { - expectedPos, err := execNode.ExecEngine.BlockNumberToMessageIndex(expectedBlockNumber) + expectedPos, err := builder.L2.ExecNode.ExecEngine.BlockNumberToMessageIndex(expectedBlockNumber) Require(t, err) - lastValidated := arbNode.BlockValidator.Validated(t) + lastValidated := builder.L2.ConsensusNode.BlockValidator.Validated(t) if lastValidated == expectedPos+1 { break } else if i >= 1000 { diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 6267abe0c5..0239491422 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -28,7 +28,6 @@ import ( "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/arbutil" - "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/staker" @@ -60,29 +59,32 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) ctx, cancelCtx := context.WithCancel(context.Background()) defer cancelCtx() var transferGas = util.NormalizeL2GasForL1GasInitial(800_000, params.GWei) // include room for aggregator L1 costs - l2chainConfig := params.ArbitrumDevTestChainConfig() - l2info := NewBlockChainTestInfo( + + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.L2Info = NewBlockChainTestInfo( t, - types.NewArbitrumSigner(types.NewLondonSigner(l2chainConfig.ChainID)), big.NewInt(l2pricing.InitialBaseFeeWei*2), + types.NewArbitrumSigner(types.NewLondonSigner(builder.chainConfig.ChainID)), big.NewInt(l2pricing.InitialBaseFeeWei*2), transferGas, ) - _, l2nodeA, l2clientA, _, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfigImpl(t, ctx, true, nil, nil, l2chainConfig, nil, l2info) - defer requireClose(t, l1stack) - defer l2nodeA.StopAndWait() - execNodeA := getExecNode(t, l2nodeA) + cleanupA := builder.Build(t) + defer cleanupA() + + l2nodeA := builder.L2.ConsensusNode + execNodeA := builder.L2.ExecNode if faultyStaker { - l2info.GenerateGenesisAccount("FaultyAddr", common.Big1) + builder.L2Info.GenerateGenesisAccount("FaultyAddr", common.Big1) } config := arbnode.ConfigDefaultL1Test() - execConfig := gethexec.ConfigDefaultTest() - execConfig.Sequencer.Enable = false config.Sequencer = false config.DelayedSequencer.Enable = false config.BatchPoster.Enable = false - _, l2nodeB := Create2ndNodeWithConfig(t, ctx, l2nodeA, l1stack, l1info, &l2info.ArbInitData, config, execConfig, nil) - defer l2nodeB.StopAndWait() - execNodeB := getExecNode(t, l2nodeB) + builder.execConfig.Sequencer.Enable = false + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: config}) + defer cleanupB() + + l2nodeB := testClientB.ConsensusNode + execNodeB := testClientB.ExecNode nodeAGenesis := execNodeA.Backend.APIBackend().CurrentHeader().Hash() nodeBGenesis := execNodeB.Backend.APIBackend().CurrentHeader().Hash() @@ -96,19 +98,19 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } } - BridgeBalance(t, "Faucet", big.NewInt(1).Mul(big.NewInt(params.Ether), big.NewInt(10000)), l1info, l2info, l1client, l2clientA, ctx) + builder.BridgeBalance(t, "Faucet", big.NewInt(1).Mul(big.NewInt(params.Ether), big.NewInt(10000))) - deployAuth := l1info.GetDefaultTransactOpts("RollupOwner", ctx) + deployAuth := builder.L1Info.GetDefaultTransactOpts("RollupOwner", ctx) balance := big.NewInt(params.Ether) balance.Mul(balance, big.NewInt(100)) - l1info.GenerateAccount("ValidatorA") - TransferBalance(t, "Faucet", "ValidatorA", balance, l1info, l1client, ctx) - l1authA := l1info.GetDefaultTransactOpts("ValidatorA", ctx) + builder.L1Info.GenerateAccount("ValidatorA") + builder.L1.TransferBalance(t, "Faucet", "ValidatorA", balance, builder.L1Info) + l1authA := builder.L1Info.GetDefaultTransactOpts("ValidatorA", ctx) - l1info.GenerateAccount("ValidatorB") - TransferBalance(t, "Faucet", "ValidatorB", balance, l1info, l1client, ctx) - l1authB := l1info.GetDefaultTransactOpts("ValidatorB", ctx) + builder.L1Info.GenerateAccount("ValidatorB") + builder.L1.TransferBalance(t, "Faucet", "ValidatorB", balance, builder.L1Info) + l1authB := builder.L1Info.GetDefaultTransactOpts("ValidatorB", ctx) valWalletAddrAPtr, err := validatorwallet.GetValidatorWalletContract(ctx, l2nodeA.DeployInfo.ValidatorWalletCreator, 0, &l1authA, l2nodeA.L1Reader, true) Require(t, err) @@ -119,19 +121,19 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Require(t, err, "didn't cache validator wallet address", valWalletAddrA.String(), "vs", valWalletAddrCheck.String()) } - rollup, err := rollupgen.NewRollupAdminLogic(l2nodeA.DeployInfo.Rollup, l1client) + rollup, err := rollupgen.NewRollupAdminLogic(l2nodeA.DeployInfo.Rollup, builder.L1.Client) Require(t, err) tx, err := rollup.SetValidator(&deployAuth, []common.Address{valWalletAddrA, l1authB.From}, []bool{true, true}) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = builder.L1.EnsureTxSucceeded(tx) Require(t, err) tx, err = rollup.SetMinimumAssertionPeriod(&deployAuth, big.NewInt(1)) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = builder.L1.EnsureTxSucceeded(tx) Require(t, err) - validatorUtils, err := rollupgen.NewValidatorUtils(l2nodeA.DeployInfo.ValidatorUtils, l1client) + validatorUtils, err := rollupgen.NewValidatorUtils(l2nodeA.DeployInfo.ValidatorUtils, builder.L1.Client) Require(t, err) valConfig := staker.TestL1ValidatorConfig @@ -223,7 +225,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) err = valWalletB.Initialize(ctx) Require(t, err) } - valWalletC := validatorwallet.NewNoOp(l1client, l2nodeA.DeployInfo.Rollup) + valWalletC := validatorwallet.NewNoOp(builder.L1.Client, l2nodeA.DeployInfo.Rollup) valConfig.Strategy = "Watchtower" stakerC, err := staker.NewStaker( l2nodeA.L1Reader, @@ -245,11 +247,11 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) err = stakerC.Initialize(ctx) Require(t, err) - l2info.GenerateAccount("BackgroundUser") - tx = l2info.PrepareTx("Faucet", "BackgroundUser", l2info.TransferGas, balance, nil) - err = l2clientA.SendTransaction(ctx, tx) + builder.L2Info.GenerateAccount("BackgroundUser") + tx = builder.L2Info.PrepareTx("Faucet", "BackgroundUser", builder.L2Info.TransferGas, balance, nil) + err = builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2clientA, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) // Continually make L2 transactions in a background thread @@ -261,7 +263,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) })() go (func() { defer close(backgroundTxsShutdownChan) - err := makeBackgroundTxs(backgroundTxsCtx, l2info, l2clientA) + err := makeBackgroundTxs(backgroundTxsCtx, builder.L2Info, builder.L2.Client) if !errors.Is(err, context.Canceled) { log.Warn("error making background txs", "err", err) } @@ -304,26 +306,26 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) if !challengeMangerTimedOut { // Upgrade the ChallengeManager contract to an implementation which says challenges are always timed out - mockImpl, tx, _, err := mocksgen.DeployTimedOutChallengeManager(&deployAuth, l1client) + mockImpl, tx, _, err := mocksgen.DeployTimedOutChallengeManager(&deployAuth, builder.L1.Client) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = builder.L1.EnsureTxSucceeded(tx) Require(t, err) managerAddr := valWalletA.ChallengeManagerAddress() // 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 proxyAdminSlot := common.BigToHash(arbmath.BigSub(crypto.Keccak256Hash([]byte("eip1967.proxy.admin")).Big(), common.Big1)) - proxyAdminBytes, err := l1client.StorageAt(ctx, managerAddr, proxyAdminSlot, nil) + proxyAdminBytes, err := builder.L1.Client.StorageAt(ctx, managerAddr, proxyAdminSlot, nil) Require(t, err) proxyAdminAddr := common.BytesToAddress(proxyAdminBytes) if proxyAdminAddr == (common.Address{}) { Fatal(t, "failed to get challenge manager proxy admin") } - proxyAdmin, err := mocksgen.NewProxyAdminForBinding(proxyAdminAddr, l1client) + proxyAdmin, err := mocksgen.NewProxyAdminForBinding(proxyAdminAddr, builder.L1.Client) Require(t, err) tx, err = proxyAdmin.Upgrade(&deployAuth, managerAddr, mockImpl) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = builder.L1.EnsureTxSucceeded(tx) Require(t, err) challengeMangerTimedOut = true @@ -343,7 +345,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } Require(t, err, "Staker", stakerName, "failed to act") if tx != nil { - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = builder.L1.EnsureTxSucceeded(tx) Require(t, err, "EnsureTxSucceeded failed for staker", stakerName, "tx") } if faultyStaker { @@ -379,7 +381,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) Require(t, err) } for j := 0; j < 5; j++ { - TransferBalance(t, "Faucet", "Faucet", common.Big0, l1info, l1client, ctx) + builder.L1.TransferBalance(t, "Faucet", "Faucet", common.Big0, builder.L1Info) } } From 7315e8ac0fe1d9a161a12f88a15a7b2c1a2c35d1 Mon Sep 17 00:00:00 2001 From: ganeshvanahalli Date: Wed, 25 Oct 2023 11:18:13 -0500 Subject: [PATCH 2/2] add more functions to TestClient, refactor all tests --- system_tests/aliasing_test.go | 26 +- system_tests/batch_poster_test.go | 54 ++--- system_tests/block_hash_test.go | 10 +- system_tests/block_validator_test.go | 73 +++--- system_tests/bloom_test.go | 6 +- system_tests/common_test.go | 67 +----- system_tests/contract_tx_test.go | 18 +- system_tests/delayedinbox_test.go | 15 +- system_tests/delayedinboxlong_test.go | 26 +- system_tests/estimation_test.go | 79 ++++--- system_tests/fees_test.go | 2 +- system_tests/infra_fee_test.go | 29 +-- system_tests/initialization_test.go | 8 +- system_tests/log_subscription_test.go | 15 +- system_tests/nodeinterface_test.go | 14 +- system_tests/outbox_test.go | 17 +- system_tests/precompile_test.go | 32 +-- system_tests/recreatestate_rpc_test.go | 19 +- system_tests/reorg_resequencing_test.go | 45 ++-- system_tests/retryable_test.go | 302 ++++++++++++------------ system_tests/seq_coordinator_test.go | 44 ++-- system_tests/seq_nonce_test.go | 54 +++-- system_tests/seq_pause_test.go | 22 +- system_tests/seq_reject_test.go | 57 +++-- system_tests/seq_whitelist_test.go | 23 +- system_tests/seqcompensation_test.go | 28 +-- system_tests/seqinbox_test.go | 29 ++- system_tests/staker_test.go | 13 +- system_tests/transfer_test.go | 17 +- system_tests/triedb_race_test.go | 38 ++- system_tests/twonodes_test.go | 33 +-- system_tests/twonodeslong_test.go | 82 ++++--- 32 files changed, 634 insertions(+), 663 deletions(-) diff --git a/system_tests/aliasing_test.go b/system_tests/aliasing_test.go index 5e4e65a2ca..60a89468a5 100644 --- a/system_tests/aliasing_test.go +++ b/system_tests/aliasing_test.go @@ -22,20 +22,20 @@ func TestAliasing(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) - user := l1info.GetDefaultTransactOpts("User", ctx) - TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), l2info, l2client, ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + user := builder.L1Info.GetDefaultTransactOpts("User", ctx) + builder.L2.TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), builder.L2Info) - simpleAddr, simple := deploySimple(t, ctx, auth, l2client) + simpleAddr, simple := builder.L2.DeploySimple(t, auth) simpleContract, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) Require(t, err) // Test direct calls - arbsys, err := precompilesgen.NewArbSys(types.ArbSysAddress, l2client) + arbsys, err := precompilesgen.NewArbSys(types.ArbSysAddress, builder.L2.Client) Require(t, err) top, err := arbsys.IsTopLevelCall(nil) Require(t, err) @@ -56,14 +56,14 @@ func TestAliasing(t *testing.T) { // check via L2 tx, err := simple.CheckCalls(&auth, top, direct, static, delegate, callcode, call) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) // check signed txes via L1 data, err := simpleContract.Pack("checkCalls", top, direct, static, delegate, callcode, call) Require(t, err) - tx = l2info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) - SendSignedTxViaL1(t, ctx, l1info, l1client, l2client, tx) + tx = builder.L2Info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) + builder.L1.SendSignedTx(t, builder.L2.Client, tx, builder.L1Info) } testUnsigned := func(top, direct, static, delegate, callcode, call bool) { @@ -72,8 +72,8 @@ func TestAliasing(t *testing.T) { // check unsigned txes via L1 data, err := simpleContract.Pack("checkCalls", top, direct, static, delegate, callcode, call) Require(t, err) - tx := l2info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) - SendUnsignedTxViaL1(t, ctx, l1info, l1client, l2client, tx) + tx := builder.L2Info.PrepareTxTo("Owner", &simpleAddr, 500000, big.NewInt(0), data) + builder.L1.SendUnsignedTx(t, builder.L2.Client, tx, builder.L1Info) } testL2Signed(true, true, false, false, false, false) diff --git a/system_tests/batch_poster_test.go b/system_tests/batch_poster_test.go index 8c0de8c6db..8561e3ffc7 100644 --- a/system_tests/batch_poster_test.go +++ b/system_tests/batch_poster_test.go @@ -50,10 +50,9 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { builder.nodeConfig.BatchPoster.RedisUrl = redisUrl cleanup := builder.Build(t) defer cleanup() - l1A, l2A := builder.L1, builder.L2 - l2B, cleanup2nd := builder.Build2ndNode(t, &SecondNodeParams{}) - defer cleanup2nd() + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{}) + defer cleanupB() builder.L2Info.GenerateAccount("User2") @@ -63,12 +62,12 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) txs = append(txs, tx) - err := l2A.Client.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) } for _, tx := range txs { - _, err := EnsureTxSucceeded(ctx, l2A.Client, tx) + _, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) } @@ -77,7 +76,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { seqTxOpts := builder.L1Info.GetDefaultTransactOpts("Sequencer", ctx) builder.nodeConfig.BatchPoster.Enable = true builder.nodeConfig.BatchPoster.MaxSize = len(firstTxData) * 2 - startL1Block, err := l1A.Client.BlockNumber(ctx) + startL1Block, err := builder.L1.Client.BlockNumber(ctx) Require(t, err) for i := 0; i < parallelBatchPosters; i++ { // Make a copy of the batch poster config so NewBatchPoster calling Validate() on it doesn't race @@ -85,12 +84,12 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { batchPoster, err := arbnode.NewBatchPoster(ctx, &arbnode.BatchPosterOpts{ DataPosterDB: nil, - L1Reader: l2A.ConsensusNode.L1Reader, - Inbox: l2A.ConsensusNode.InboxTracker, - Streamer: l2A.ConsensusNode.TxStreamer, - SyncMonitor: l2A.ConsensusNode.SyncMonitor, + L1Reader: builder.L2.ConsensusNode.L1Reader, + Inbox: builder.L2.ConsensusNode.InboxTracker, + Streamer: builder.L2.ConsensusNode.TxStreamer, + SyncMonitor: builder.L2.ConsensusNode.SyncMonitor, Config: func() *arbnode.BatchPosterConfig { return &batchPosterConfig }, - DeployInfo: l2A.ConsensusNode.DeployInfo, + DeployInfo: builder.L2.ConsensusNode.DeployInfo, TransactOpts: &seqTxOpts, DAWriter: nil, }, @@ -102,11 +101,11 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { lastTxHash := txs[len(txs)-1].Hash() for i := 90; i > 0; i-- { - SendWaitTestTransactions(t, ctx, l1A.Client, []*types.Transaction{ + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) time.Sleep(500 * time.Millisecond) - _, err := l2B.Client.TransactionReceipt(ctx, lastTxHash) + _, err := testClientB.Client.TransactionReceipt(ctx, lastTxHash) if err == nil { break } @@ -121,9 +120,9 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { // However, setting the clique period to 1 slows everything else (including the L1 deployment for this test) down to a crawl. if false { // Make sure the batch poster is able to post multiple batches in one block - endL1Block, err := l1A.Client.BlockNumber(ctx) + endL1Block, err := builder.L1.Client.BlockNumber(ctx) Require(t, err) - seqInbox, err := arbnode.NewSequencerInbox(l1A.Client, l2A.ConsensusNode.DeployInfo.SequencerInbox, 0) + seqInbox, err := arbnode.NewSequencerInbox(builder.L1.Client, builder.L2.ConsensusNode.DeployInfo.SequencerInbox, 0) Require(t, err) batches, err := seqInbox.LookupBatchesInRange(ctx, new(big.Int).SetUint64(startL1Block), new(big.Int).SetUint64(endL1Block)) Require(t, err) @@ -143,7 +142,7 @@ func testBatchPosterParallel(t *testing.T, useRedis bool) { } } - l2balance, err := l2B.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) + l2balance, err := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Sign() == 0 { @@ -160,10 +159,9 @@ func TestBatchPosterLargeTx(t *testing.T) { builder.execConfig.Sequencer.MaxTxDataSize = 110000 cleanup := builder.Build(t) defer cleanup() - l2A := builder.L2 - l2B, cleanup2nd := builder.Build2ndNode(t, &SecondNodeParams{}) - defer cleanup2nd() + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{}) + defer cleanupB() data := make([]byte, 100000) _, err := rand.Read(data) @@ -171,11 +169,11 @@ func TestBatchPosterLargeTx(t *testing.T) { faucetAddr := builder.L2Info.GetAddress("Faucet") gas := builder.L2Info.TransferGas + 20000*uint64(len(data)) tx := builder.L2Info.PrepareTxTo("Faucet", &faucetAddr, gas, common.Big0, data) - err = l2A.Client.SendTransaction(ctx, tx) + err = builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - receiptA, err := EnsureTxSucceeded(ctx, l2A.Client, tx) + receiptA, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) - receiptB, err := EnsureTxSucceededWithTimeout(ctx, l2B.Client, tx, time.Second*30) + receiptB, err := testClientB.EnsureTxSucceededWithTimeout(tx, time.Second*30) Require(t, err) if receiptA.BlockHash != receiptB.BlockHash { Fatal(t, "receipt A block hash", receiptA.BlockHash, "does not equal receipt B block hash", receiptB.BlockHash) @@ -193,7 +191,7 @@ func TestBatchPosterKeepsUp(t *testing.T) { builder.execConfig.RPC.RPCTxFeeCap = 1000. cleanup := builder.Build(t) defer cleanup() - l2A := builder.L2 + builder.L2Info.GasPrice = big.NewInt(100e9) go func() { @@ -203,9 +201,9 @@ func TestBatchPosterKeepsUp(t *testing.T) { for { gas := builder.L2Info.TransferGas + 20000*uint64(len(data)) tx := builder.L2Info.PrepareTx("Faucet", "Faucet", gas, common.Big0, data) - err = l2A.Client.SendTransaction(ctx, tx) + err = builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err := EnsureTxSucceeded(ctx, l2A.Client, tx) + _, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) } }() @@ -213,11 +211,11 @@ func TestBatchPosterKeepsUp(t *testing.T) { start := time.Now() for { time.Sleep(time.Second) - batches, err := l2A.ConsensusNode.InboxTracker.GetBatchCount() + batches, err := builder.L2.ConsensusNode.InboxTracker.GetBatchCount() Require(t, err) - postedMessages, err := l2A.ConsensusNode.InboxTracker.GetBatchMessageCount(batches - 1) + postedMessages, err := builder.L2.ConsensusNode.InboxTracker.GetBatchMessageCount(batches - 1) Require(t, err) - haveMessages, err := l2A.ConsensusNode.TxStreamer.GetMessageCount() + haveMessages, err := builder.L2.ConsensusNode.TxStreamer.GetMessageCount() Require(t, err) duration := time.Since(start) fmt.Printf("batches posted: %v over %v (%.2f batches/second)\n", batches, duration, float64(batches)/(float64(duration)/float64(time.Second))) diff --git a/system_tests/block_hash_test.go b/system_tests/block_hash_test.go index 2b8051242e..b437f3dad9 100644 --- a/system_tests/block_hash_test.go +++ b/system_tests/block_hash_test.go @@ -16,13 +16,13 @@ func TestBlockHash(t *testing.T) { defer cancel() // Even though we don't use the L1, we need to create this node on L1 to get accurate L1 block numbers - l2info, l2node, l2client, _, _, _, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Faucet", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) - _, _, simple, err := mocksgen.DeploySimple(&auth, l2client) + _, _, simple, err := mocksgen.DeploySimple(&auth, builder.L2.Client) Require(t, err) _, err = simple.CheckBlockHashes(&bind.CallOpts{Context: ctx}) diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index 1699346b17..d0409f8679 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -51,20 +51,23 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops delayEvery = workloadLoops / 3 } - l2info, nodeA, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, nil, chainConfig, nil) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig = l1NodeConfigA + builder.chainConfig = chainConfig + builder.L2Info = nil + cleanup := builder.Build(t) + defer cleanup() - authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) + authorizeDASKeyset(t, ctx, dasSignerKey, builder.L1Info, builder.L1.Client) validatorConfig := arbnode.ConfigDefaultL1NonSequencerTest() validatorConfig.BlockValidator.Enable = true validatorConfig.DataAvailability = l1NodeConfigA.DataAvailability validatorConfig.DataAvailability.RPCAggregator.Enable = false AddDefaultValNode(t, ctx, validatorConfig, !arbitrator) - l2clientB, nodeB := Create2ndNodeWithConfig(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, validatorConfig, nil, nil) - defer nodeB.StopAndWait() - l2info.GenerateAccount("User2") + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: validatorConfig}) + defer cleanupB() + builder.L2Info.GenerateAccount("User2") perTransfer := big.NewInt(1e12) @@ -73,7 +76,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops var tx *types.Transaction if workload == ethSend { - tx = l2info.PrepareTx("Owner", "User2", l2info.TransferGas, perTransfer, nil) + tx = builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, perTransfer, nil) } else { var contractCode []byte var gas uint64 @@ -87,10 +90,10 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops contractCode = append(contractCode, byte(vm.CODECOPY)) contractCode = append(contractCode, byte(vm.PUSH0)) contractCode = append(contractCode, byte(vm.RETURN)) - basefee := GetBaseFee(t, l2client, ctx) + basefee := builder.L2.GetBaseFee(t) var err error - gas, err = l2client.EstimateGas(ctx, ethereum.CallMsg{ - From: l2info.GetAddress("Owner"), + gas, err = builder.L2.Client.EstimateGas(ctx, ethereum.CallMsg{ + From: builder.L2Info.GetAddress("Owner"), GasPrice: basefee, Value: big.NewInt(0), Data: contractCode, @@ -102,14 +105,14 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops contractCode = append(contractCode, 0x60, 0x00, 0x60, 0x00, 0x52) // PUSH1 0 MSTORE } contractCode = append(contractCode, 0x60, 0x00, 0x56) // JUMP - gas = l2info.TransferGas*2 + l2pricing.InitialPerBlockGasLimitV6 + gas = builder.L2Info.TransferGas*2 + l2pricing.InitialPerBlockGasLimitV6 } - tx = l2info.PrepareTxTo("Owner", nil, gas, common.Big0, contractCode) + tx = builder.L2Info.PrepareTxTo("Owner", nil, gas, common.Big0, contractCode) } - err := l2client.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceededWithTimeout(ctx, l2client, tx, time.Second*5) + _, err = builder.L2.EnsureTxSucceeded(tx) if workload != depleteGas { Require(t, err) } @@ -118,49 +121,49 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops } } } else { - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) // make auth a chain owner - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), builder.L2.Client) Require(t, err) tx, err := arbDebug.BecomeChainOwner(&auth) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), l2client) + arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), builder.L2.Client) Require(t, err) tx, err = arbOwner.ScheduleArbOSUpgrade(&auth, 11, 0) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - tx = l2info.PrepareTxTo("Owner", nil, l2info.TransferGas, perTransfer, []byte{byte(vm.PUSH0)}) - err = l2client.SendTransaction(ctx, tx) + tx = builder.L2Info.PrepareTxTo("Owner", nil, builder.L2Info.TransferGas, perTransfer, []byte{byte(vm.PUSH0)}) + err = builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceededWithTimeout(ctx, l2client, tx, time.Second*5) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) } if workload != depleteGas { - delayedTx := l2info.PrepareTx("Owner", "User2", 30002, perTransfer, nil) - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - WrapL2ForDelayed(t, delayedTx, l1info, "User", 100000), + delayedTx := builder.L2Info.PrepareTx("Owner", "User2", 30002, perTransfer, nil) + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + WrapL2ForDelayed(t, delayedTx, builder.L1Info, "User", 100000), }) // give the inbox reader a bit of time to pick up the delayed message time.Sleep(time.Millisecond * 500) // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } - _, err := WaitForTx(ctx, l2clientB, delayedTx.Hash(), time.Second*5) + _, err := WaitForTx(ctx, testClientB.Client, delayedTx.Hash(), time.Second*5) Require(t, err) } if workload == ethSend { - l2balance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) expectedBalance := new(big.Int).Mul(perTransfer, big.NewInt(int64(workloadLoops+1))) @@ -169,7 +172,7 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops } } - lastBlock, err := l2clientB.BlockByNumber(ctx, nil) + lastBlock, err := testClientB.Client.BlockByNumber(ctx, nil) Require(t, err) for { usefulBlock := false @@ -182,22 +185,22 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, workloadLoops if usefulBlock { break } - lastBlock, err = l2clientB.BlockByHash(ctx, lastBlock.ParentHash()) + lastBlock, err = testClientB.Client.BlockByHash(ctx, lastBlock.ParentHash()) Require(t, err) } t.Log("waiting for block: ", lastBlock.NumberU64()) timeout := getDeadlineTimeout(t, time.Minute*10) // messageindex is same as block number here - if !nodeB.BlockValidator.WaitForPos(t, ctx, arbutil.MessageIndex(lastBlock.NumberU64()), timeout) { + if !testClientB.ConsensusNode.BlockValidator.WaitForPos(t, ctx, arbutil.MessageIndex(lastBlock.NumberU64()), timeout) { Fatal(t, "did not validate all blocks") } - gethExec, ok := nodeB.Execution.(*gethexec.ExecutionNode) + gethExec, ok := testClientB.ConsensusNode.Execution.(*gethexec.ExecutionNode) if !ok { t.Fail() } gethExec.Recorder.TrimAllPrepared(t) finalRefCount := gethExec.Recorder.RecordingDBReferenceCount() - lastBlockNow, err := l2clientB.BlockByNumber(ctx, nil) + lastBlockNow, err := testClientB.Client.BlockByNumber(ctx, nil) Require(t, err) // up to 3 extra references: awaiting validation, recently valid, lastValidatedHeader largestRefCount := lastBlockNow.NumberU64() - lastBlock.NumberU64() + 3 diff --git a/system_tests/bloom_test.go b/system_tests/bloom_test.go index 9079fd35f1..a3cab748e2 100644 --- a/system_tests/bloom_test.go +++ b/system_tests/bloom_test.go @@ -36,7 +36,7 @@ func TestBloom(t *testing.T) { ownerTxOpts := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) ownerTxOpts.Context = ctx - _, simple := deploySimple(t, ctx, ownerTxOpts, builder.L2.Client) + _, simple := builder.L2.DeploySimple(t, ownerTxOpts) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) @@ -64,7 +64,7 @@ func TestBloom(t *testing.T) { if sendNullEvent { tx, err = simple.EmitNullEvent(&ownerTxOpts) Require(t, err) - _, err = EnsureTxSucceeded(ctx, builder.L2.Client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) } @@ -75,7 +75,7 @@ func TestBloom(t *testing.T) { tx, err = simple.Increment(&ownerTxOpts) } Require(t, err) - _, err = EnsureTxSucceeded(ctx, builder.L2.Client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) if i%100 == 0 { t.Log("counts: ", i, "/", countsNum) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 41a3fd1417..0d7cd2dfaa 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -103,6 +103,10 @@ func (tc *TestClient) GetBalance(t *testing.T, account common.Address) *big.Int return GetBalance(t, tc.ctx, tc.Client, account) } +func (tc *TestClient) GetBaseFee(t *testing.T) *big.Int { + return GetBaseFee(t, tc.Client, tc.ctx) +} + func (tc *TestClient) GetBaseFeeAt(t *testing.T, blockNum *big.Int) *big.Int { return GetBaseFeeAt(t, tc.Client, tc.ctx, blockNum) } @@ -116,7 +120,11 @@ func (tc *TestClient) DeploySimple(t *testing.T, auth bind.TransactOpts) (common } func (tc *TestClient) EnsureTxSucceeded(transaction *types.Transaction) (*types.Receipt, error) { - return EnsureTxSucceeded(tc.ctx, tc.Client, transaction) + return tc.EnsureTxSucceededWithTimeout(transaction, time.Second*5) +} + +func (tc *TestClient) EnsureTxSucceededWithTimeout(transaction *types.Transaction, timeout time.Duration) (*types.Receipt, error) { + return EnsureTxSucceededWithTimeout(tc.ctx, tc.Client, transaction, timeout) } type NodeBuilder struct { @@ -169,13 +177,13 @@ func (b *NodeBuilder) Build(t *testing.T) func() { if b.withL1 { l1, l2 := NewTestClient(b.ctx), NewTestClient(b.ctx) b.L2Info, l2.ConsensusNode, l2.Client, l2.Stack, b.L1Info, l1.L1Backend, l1.Client, l1.Stack = - createTestNodeOnL1WithConfigImpl(t, b.ctx, b.isSequencer, b.nodeConfig, b.execConfig, b.chainConfig, b.l2StackConfig, b.L2Info) + createTestNodeWithL1(t, b.ctx, b.isSequencer, b.nodeConfig, b.execConfig, b.chainConfig, b.l2StackConfig, b.L2Info) b.L1, b.L2 = l1, l2 b.L1.cleanup = func() { requireClose(t, b.L1.Stack) } } else { l2 := NewTestClient(b.ctx) b.L2Info, l2.ConsensusNode, l2.Client = - CreateTestL2WithConfig(t, b.ctx, b.L2Info, b.nodeConfig, b.execConfig, b.takeOwnership) + createTestNode(t, b.ctx, b.L2Info, b.nodeConfig, b.execConfig, b.takeOwnership) b.L2 = l2 } b.L2.ExecNode = getExecNode(t, b.L2.ConsensusNode) @@ -702,34 +710,7 @@ func ClientForStack(t *testing.T, backend *node.Node) *ethclient.Client { } // Create and deploy L1 and arbnode for L2 -func createTestNodeOnL1( - t *testing.T, - ctx context.Context, - isSequencer bool, -) ( - l2info info, node *arbnode.Node, l2client *ethclient.Client, l1info info, - l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node, -) { - return createTestNodeOnL1WithConfig(t, ctx, isSequencer, nil, nil, nil, nil) -} - -func createTestNodeOnL1WithConfig( - t *testing.T, - ctx context.Context, - isSequencer bool, - nodeConfig *arbnode.Config, - execConfig *gethexec.Config, - chainConfig *params.ChainConfig, - stackConfig *node.Config, -) ( - l2info info, currentNode *arbnode.Node, l2client *ethclient.Client, l1info info, - l1backend *eth.Ethereum, l1client *ethclient.Client, l1stack *node.Node, -) { - l2info, currentNode, l2client, _, l1info, l1backend, l1client, l1stack = createTestNodeOnL1WithConfigImpl(t, ctx, isSequencer, nodeConfig, execConfig, chainConfig, stackConfig, nil) - return -} - -func createTestNodeOnL1WithConfigImpl( +func createTestNodeWithL1( t *testing.T, ctx context.Context, isSequencer bool, @@ -801,11 +782,7 @@ func createTestNodeOnL1WithConfigImpl( // L2 -Only. Enough for tests that needs no interface to L1 // Requires precompiles.AllowDebugPrecompiles = true -func CreateTestL2(t *testing.T, ctx context.Context) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { - return CreateTestL2WithConfig(t, ctx, nil, nil, nil, true) -} - -func CreateTestL2WithConfig( +func createTestNode( t *testing.T, ctx context.Context, l2Info *BlockchainTestInfo, nodeConfig *arbnode.Config, execConfig *gethexec.Config, takeOwnership bool, ) (*BlockchainTestInfo, *arbnode.Node, *ethclient.Client) { if nodeConfig == nil { @@ -879,24 +856,6 @@ func Fatal(t *testing.T, printables ...interface{}) { testhelpers.FailImpl(t, printables...) } -func Create2ndNode( - t *testing.T, - ctx context.Context, - first *arbnode.Node, - l1stack *node.Node, - l1info *BlockchainTestInfo, - l2InitData *statetransfer.ArbosInitializationInfo, - dasConfig *das.DataAvailabilityConfig, -) (*ethclient.Client, *arbnode.Node) { - nodeConf := arbnode.ConfigDefaultL1NonSequencerTest() - if dasConfig == nil { - nodeConf.DataAvailability.Enable = false - } else { - nodeConf.DataAvailability = *dasConfig - } - return Create2ndNodeWithConfig(t, ctx, first, l1stack, l1info, l2InitData, nodeConf, nil, nil) -} - func Create2ndNodeWithConfig( t *testing.T, ctx context.Context, diff --git a/system_tests/contract_tx_test.go b/system_tests/contract_tx_test.go index d6c2eb5f38..56d79b36d9 100644 --- a/system_tests/contract_tx_test.go +++ b/system_tests/contract_tx_test.go @@ -25,18 +25,20 @@ func TestContractTxDeploy(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, nil, false) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.takeOwnership = false + cleanup := builder.Build(t) + defer cleanup() from := common.HexToAddress("0x123412341234") - TransferBalanceTo(t, "Faucet", from, big.NewInt(1e18), l2info, client, ctx) + builder.L2.TransferBalanceTo(t, "Faucet", from, big.NewInt(1e18), builder.L2Info) for stateNonce := uint64(0); stateNonce < 2; stateNonce++ { - pos, err := node.TxStreamer.GetMessageCount() + pos, err := builder.L2.ConsensusNode.TxStreamer.GetMessageCount() Require(t, err) var delayedMessagesRead uint64 if pos > 0 { - lastMessage, err := node.TxStreamer.GetMessage(pos - 1) + lastMessage, err := builder.L2.ConsensusNode.TxStreamer.GetMessage(pos - 1) Require(t, err) delayedMessagesRead = lastMessage.DelayedMessagesRead } @@ -68,7 +70,7 @@ func TestContractTxDeploy(t *testing.T) { l2Msg = append(l2Msg, math.U256Bytes(contractTx.Value)...) l2Msg = append(l2Msg, contractTx.Data...) - err = node.TxStreamer.AddMessages(pos, true, []arbostypes.MessageWithMetadata{ + err = builder.L2.ConsensusNode.TxStreamer.AddMessages(pos, true, []arbostypes.MessageWithMetadata{ { Message: &arbostypes.L1IncomingMessage{ Header: &arbostypes.L1IncomingMessageHeader{ @@ -89,7 +91,7 @@ func TestContractTxDeploy(t *testing.T) { txHash := types.NewTx(contractTx).Hash() t.Log("made contract tx", contractTx, "with hash", txHash) - receipt, err := WaitForTx(ctx, client, txHash, time.Second*10) + receipt, err := WaitForTx(ctx, builder.L2.Client, txHash, time.Second*10) Require(t, err) if receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "Receipt has non-successful status", receipt.Status) @@ -102,7 +104,7 @@ func TestContractTxDeploy(t *testing.T) { t.Log("deployed contract", receipt.ContractAddress, "from address", from, "with nonce", stateNonce) stateNonce++ - code, err := client.CodeAt(ctx, receipt.ContractAddress, nil) + code, err := builder.L2.Client.CodeAt(ctx, receipt.ContractAddress, nil) Require(t, err) if !bytes.Equal(code, []byte{0xFE}) { Fatal(t, "expected contract", receipt.ContractAddress, "code of 0xFE but got", hex.EncodeToString(code)) diff --git a/system_tests/delayedinbox_test.go b/system_tests/delayedinbox_test.go index e48cb37028..ca3e7b5999 100644 --- a/system_tests/delayedinbox_test.go +++ b/system_tests/delayedinbox_test.go @@ -38,16 +38,17 @@ func TestDelayInboxSimple(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() - l2info.GenerateAccount("User2") + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - delayedTx := l2info.PrepareTx("Owner", "User2", 50001, big.NewInt(1e6), nil) - SendSignedTxViaL1(t, ctx, l1info, l1client, l2client, delayedTx) + builder.L2Info.GenerateAccount("User2") - l2balance, err := l2client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + delayedTx := builder.L2Info.PrepareTx("Owner", "User2", 50001, big.NewInt(1e6), nil) + builder.L1.SendSignedTx(t, builder.L2.Client, delayedTx, builder.L1Info) + + l2balance, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e6)) != 0 { Fatal(t, "Unexpected balance:", l2balance) diff --git a/system_tests/delayedinboxlong_test.go b/system_tests/delayedinboxlong_test.go index b1c8ea361b..7c57771f50 100644 --- a/system_tests/delayedinboxlong_test.go +++ b/system_tests/delayedinboxlong_test.go @@ -25,11 +25,11 @@ func TestDelayInboxLong(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, l2client, l1info, l1backend, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer l2node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") fundsPerDelayed := int64(1000000) delayedMessages := int64(0) @@ -42,22 +42,22 @@ func TestDelayInboxLong(t *testing.T) { randNum := rand.Int() % messagesPerDelayed var l1tx *types.Transaction if randNum == 0 { - delayedTx := l2info.PrepareTx("Owner", "User2", 50001, big.NewInt(fundsPerDelayed), nil) - l1tx = WrapL2ForDelayed(t, delayedTx, l1info, "User", 100000) + delayedTx := builder.L2Info.PrepareTx("Owner", "User2", 50001, big.NewInt(fundsPerDelayed), nil) + l1tx = WrapL2ForDelayed(t, delayedTx, builder.L1Info, "User", 100000) lastDelayedMessage = delayedTx delayedMessages++ } else { - l1tx = l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) + l1tx = builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) } l1Txs = append(l1Txs, l1tx) } // adding multiple messages in the same AddLocal to get them in the same L1 block - errs := l1backend.TxPool().AddLocals(l1Txs) + errs := builder.L1.L1Backend.TxPool().AddLocals(l1Txs) for _, err := range errs { Require(t, err) } // Checking every tx is expensive, so we just check the last, assuming that the others succeeded too - _, err := EnsureTxSucceeded(ctx, l1client, l1Txs[len(l1Txs)-1]) + _, err := builder.L1.EnsureTxSucceeded(l1Txs[len(l1Txs)-1]) Require(t, err) } @@ -68,14 +68,14 @@ func TestDelayInboxLong(t *testing.T) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 100; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } - _, err := WaitForTx(ctx, l2client, lastDelayedMessage.Hash(), time.Second*5) + _, err := WaitForTx(ctx, builder.L2.Client, lastDelayedMessage.Hash(), time.Second*5) Require(t, err) - l2balance, err := l2client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(fundsPerDelayed*delayedMessages)) != 0 { Fatal(t, "Unexpected balance:", "balance", l2balance, "expected", fundsPerDelayed*delayedMessages) diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index 9f2db62dab..691b02a123 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -26,17 +26,18 @@ func TestDeploy(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) auth.GasMargin = 0 // don't adjust, we want to see if the estimate alone is sufficient - _, simple := deploySimple(t, ctx, auth, client) + _, simple := builder.L2.DeploySimple(t, auth) tx, err := simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) counter, err := simple.Counter(&bind.CallOpts{}) @@ -51,24 +52,25 @@ func TestEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) auth.GasMargin = 0 // don't adjust, we want to see if the estimate alone is sufficient gasPrice := big.NewInt(params.GWei / 10) // set the gas price - arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), client) + arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), builder.L2.Client) Require(t, err, "could not deploy ArbOwner contract") tx, err := arbOwner.SetMinimumL2BaseFee(&auth, gasPrice) Require(t, err, "could not set L2 gas price") - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) // connect to arbGasInfo precompile - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), builder.L2.Client) Require(t, err, "could not deploy contract") // wait for price to come to equilibrium @@ -76,8 +78,8 @@ func TestEstimate(t *testing.T) { numTriesLeft := 20 for !equilibrated && numTriesLeft > 0 { // make an empty block to let the gas price update - l2info.GasPrice = new(big.Int).Mul(l2info.GasPrice, big.NewInt(2)) - TransferBalance(t, "Owner", "Owner", common.Big0, l2info, client, ctx) + builder.L2Info.GasPrice = new(big.Int).Mul(builder.L2Info.GasPrice, big.NewInt(2)) + builder.L2.TransferBalance(t, "Owner", "Owner", common.Big0, builder.L2Info) // check if the price has equilibrated _, _, _, _, _, setPrice, err := arbGasInfo.GetPricesInWei(&bind.CallOpts{}) @@ -91,22 +93,22 @@ func TestEstimate(t *testing.T) { Fatal(t, "L2 gas price did not converge", gasPrice) } - initialBalance, err := client.BalanceAt(ctx, auth.From, nil) + initialBalance, err := builder.L2.Client.BalanceAt(ctx, auth.From, nil) Require(t, err, "could not get balance") // deploy a test contract - _, tx, simple, err := mocksgen.DeploySimple(&auth, client) + _, tx, simple, err := mocksgen.DeploySimple(&auth, builder.L2.Client) Require(t, err, "could not deploy contract") - receipt, err := EnsureTxSucceeded(ctx, client, tx) + receipt, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) - header, err := client.HeaderByNumber(ctx, receipt.BlockNumber) + header, err := builder.L2.Client.HeaderByNumber(ctx, receipt.BlockNumber) Require(t, err, "could not get header") if header.BaseFee.Cmp(gasPrice) != 0 { Fatal(t, "Header has wrong basefee", header.BaseFee, gasPrice) } - balance, err := client.BalanceAt(ctx, auth.From, nil) + balance, err := builder.L2.Client.BalanceAt(ctx, auth.From, nil) Require(t, err, "could not get balance") expectedCost := receipt.GasUsed * gasPrice.Uint64() observedCost := initialBalance.Uint64() - balance.Uint64() @@ -116,7 +118,7 @@ func TestEstimate(t *testing.T) { tx, err = simple.Increment(&auth) Require(t, err, "failed to call Increment()") - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) counter, err := simple.Counter(&bind.CallOpts{}) @@ -131,11 +133,12 @@ func TestComponentEstimate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() l1BaseFee := new(big.Int).Set(arbostypes.DefaultInitialL1BaseFee) - l2BaseFee := GetBaseFee(t, client, ctx) + l2BaseFee := builder.L2.GetBaseFee(t) colors.PrintGrey("l1 basefee ", l1BaseFee) colors.PrintGrey("l2 basefee ", l2BaseFee) @@ -144,10 +147,10 @@ func TestComponentEstimate(t *testing.T) { maxPriorityFeePerGas := big.NewInt(0) maxFeePerGas := arbmath.BigMulByUfrac(l2BaseFee, 3, 2) - l2info.GenerateAccount("User") - TransferBalance(t, "Owner", "User", userBalance, l2info, client, ctx) + builder.L2Info.GenerateAccount("User") + builder.L2.TransferBalance(t, "Owner", "User", userBalance, builder.L2Info) - from := l2info.GetAddress("User") + from := builder.L2Info.GetAddress("User") to := testhelpers.RandomAddress() gas := uint64(100000000) calldata := []byte{0x00, 0x12} @@ -171,7 +174,7 @@ func TestComponentEstimate(t *testing.T) { Value: value, Data: estimateCalldata, } - returnData, err := client.CallContract(ctx, msg, nil) + returnData, err := builder.L2.Client.CallContract(ctx, msg, nil) Require(t, err) outputs, err := nodeMethod.Outputs.Unpack(returnData) @@ -185,9 +188,8 @@ func TestComponentEstimate(t *testing.T) { baseFee, _ := outputs[2].(*big.Int) l1BaseFeeEstimate, _ := outputs[3].(*big.Int) - execNode := getExecNode(t, node) - tx := l2info.SignTxAs("User", &types.DynamicFeeTx{ - ChainID: execNode.ArbInterface.BlockChain().Config().ChainID, + tx := builder.L2Info.SignTxAs("User", &types.DynamicFeeTx{ + ChainID: builder.L2.ExecNode.ArbInterface.BlockChain().Config().ChainID, Nonce: 0, GasTipCap: maxPriorityFeePerGas, GasFeeCap: maxFeePerGas, @@ -208,8 +210,8 @@ func TestComponentEstimate(t *testing.T) { Fatal(t, baseFee, l2BaseFee.Uint64()) } - Require(t, client.SendTransaction(ctx, tx)) - receipt, err := EnsureTxSucceeded(ctx, client, tx) + Require(t, builder.L2.Client.SendTransaction(ctx, tx)) + receipt, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) l2Used := receipt.GasUsed - receipt.GasUsedForL1 @@ -224,14 +226,15 @@ func TestDisableL1Charging(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() addr := common.HexToAddress("0x12345678") - gasWithL1Charging, err := client.EstimateGas(ctx, ethereum.CallMsg{To: &addr}) + gasWithL1Charging, err := builder.L2.Client.EstimateGas(ctx, ethereum.CallMsg{To: &addr}) Require(t, err) - gasWithoutL1Charging, err := client.EstimateGas(ctx, ethereum.CallMsg{To: &addr, SkipL1Charging: true}) + gasWithoutL1Charging, err := builder.L2.Client.EstimateGas(ctx, ethereum.CallMsg{To: &addr, SkipL1Charging: true}) Require(t, err) if gasWithL1Charging <= gasWithoutL1Charging { @@ -241,14 +244,14 @@ func TestDisableL1Charging(t *testing.T) { Fatal(t, "Incorrect gas estimate with disabled L1 charging") } - _, err = client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithL1Charging}, nil) + _, err = builder.L2.Client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithL1Charging}, nil) Require(t, err) - _, err = client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging}, nil) + _, err = builder.L2.Client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging}, nil) if err == nil { Fatal(t, "CallContract passed with insufficient gas") } - _, err = client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging, SkipL1Charging: true}, nil) + _, err = builder.L2.Client.CallContract(ctx, ethereum.CallMsg{To: &addr, Gas: gasWithoutL1Charging, SkipL1Charging: true}, nil) Require(t, err) } diff --git a/system_tests/fees_test.go b/system_tests/fees_test.go index 17ab7b69c4..3ac5b29b0a 100644 --- a/system_tests/fees_test.go +++ b/system_tests/fees_test.go @@ -53,7 +53,7 @@ func TestSequencerFeePaid(t *testing.T) { l1Estimate, err := arbGasInfo.GetL1BaseFeeEstimate(callOpts) Require(t, err) - baseFee := GetBaseFee(t, builder.L2.Client, ctx) + baseFee := builder.L2.GetBaseFee(t) builder.L2Info.GasPrice = baseFee testFees := func(tip uint64) (*big.Int, *big.Int) { diff --git a/system_tests/infra_fee_test.go b/system_tests/infra_fee_test.go index a56e054563..9366fc204e 100644 --- a/system_tests/infra_fee_test.go +++ b/system_tests/infra_fee_test.go @@ -23,45 +23,46 @@ func TestInfraFee(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, nil, true) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) + ownerTxOpts := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) ownerTxOpts.Context = ctx - ownerCallOpts := l2info.GetDefaultCallOpts("Owner", ctx) + ownerCallOpts := builder.L2Info.GetDefaultCallOpts("Owner", ctx) - arbowner, err := precompilesgen.NewArbOwner(common.HexToAddress("70"), client) + arbowner, err := precompilesgen.NewArbOwner(common.HexToAddress("70"), builder.L2.Client) Require(t, err) - arbownerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("6b"), client) + arbownerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("6b"), builder.L2.Client) Require(t, err) networkFeeAddr, err := arbownerPublic.GetNetworkFeeAccount(ownerCallOpts) Require(t, err) infraFeeAddr := common.BytesToAddress(crypto.Keccak256([]byte{3, 2, 6})) tx, err := arbowner.SetInfraFeeAccount(&ownerTxOpts, infraFeeAddr) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - _, simple := deploySimple(t, ctx, ownerTxOpts, client) + _, simple := builder.L2.DeploySimple(t, ownerTxOpts) - netFeeBalanceBefore, err := client.BalanceAt(ctx, networkFeeAddr, nil) + netFeeBalanceBefore, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - infraFeeBalanceBefore, err := client.BalanceAt(ctx, infraFeeAddr, nil) + infraFeeBalanceBefore, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) tx, err = simple.Increment(&ownerTxOpts) Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, client, tx) + receipt, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) l2GasUsed := receipt.GasUsed - receipt.GasUsedForL1 expectedFunds := arbmath.BigMulByUint(arbmath.UintToBig(l2pricing.InitialBaseFeeWei), l2GasUsed) expectedBalanceAfter := arbmath.BigAdd(infraFeeBalanceBefore, expectedFunds) - netFeeBalanceAfter, err := client.BalanceAt(ctx, networkFeeAddr, nil) + netFeeBalanceAfter, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - infraFeeBalanceAfter, err := client.BalanceAt(ctx, infraFeeAddr, nil) + infraFeeBalanceAfter, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) if !arbmath.BigEquals(netFeeBalanceBefore, netFeeBalanceAfter) { diff --git a/system_tests/initialization_test.go b/system_tests/initialization_test.go index 0e055adc5f..6707df1c64 100644 --- a/system_tests/initialization_test.go +++ b/system_tests/initialization_test.go @@ -62,14 +62,16 @@ func TestInitContract(t *testing.T) { l2info.ArbInitData.Accounts = append(l2info.ArbInitData.Accounts, accountInfo) expectedSums[accountAddress] = sum } - _, node, client := CreateTestL2WithConfig(t, ctx, l2info, nil, nil, true) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.L2Info = l2info + cleanup := builder.Build(t) + defer cleanup() for accountAddress, sum := range expectedSums { msg := ethereum.CallMsg{ To: &accountAddress, } - res, err := client.CallContract(ctx, msg, big.NewInt(0)) + res, err := builder.L2.Client.CallContract(ctx, msg, big.NewInt(0)) Require(t, err) resBig := new(big.Int).SetBytes(res) if resBig.Cmp(sum) != 0 { diff --git a/system_tests/log_subscription_test.go b/system_tests/log_subscription_test.go index 5ee1732fb0..e4402533a6 100644 --- a/system_tests/log_subscription_test.go +++ b/system_tests/log_subscription_test.go @@ -19,21 +19,22 @@ func TestLogSubscription(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) - arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, client) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, builder.L2.Client) Require(t, err) logChan := make(chan types.Log, 128) - subscription, err := client.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, logChan) + subscription, err := builder.L2.Client.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, logChan) Require(t, err) defer subscription.Unsubscribe() tx, err := arbSys.WithdrawEth(&auth, common.Address{}) Require(t, err) - receipt, err := EnsureTxSucceeded(ctx, client, tx) + receipt, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) if len(receipt.Logs) != 1 { @@ -52,6 +53,6 @@ func TestLogSubscription(t *testing.T) { if !reflect.DeepEqual(receiptLog, subscriptionLog) { Fatal(t, "Receipt log", receiptLog, "is different than subscription log", subscriptionLog) } - _, err = client.BlockByHash(ctx, subscriptionLog.BlockHash) + _, err = builder.L2.Client.BlockByHash(ctx, subscriptionLog.BlockHash) Require(t, err) } diff --git a/system_tests/nodeinterface_test.go b/system_tests/nodeinterface_test.go index 167f2204cd..40953a449d 100644 --- a/system_tests/nodeinterface_test.go +++ b/system_tests/nodeinterface_test.go @@ -19,23 +19,23 @@ func TestL2BlockRangeForL1(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, l2client, l1info, _, _, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer node.StopAndWait() - user := l1info.GetDefaultTransactOpts("User", ctx) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() + user := builder.L1Info.GetDefaultTransactOpts("User", ctx) numTransactions := 200 for i := 0; i < numTransactions; i++ { - TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), l2info, l2client, ctx) + builder.L2.TransferBalanceTo(t, "Owner", util.RemapL1Address(user.From), big.NewInt(1e18), builder.L2Info) } - nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client) + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, builder.L2.Client) if err != nil { t.Fatalf("Error creating node interface: %v", err) } l1BlockNums := map[uint64]*[2]uint64{} - latestL2, err := l2client.BlockNumber(ctx) + latestL2, err := builder.L2.Client.BlockNumber(ctx) if err != nil { t.Fatalf("Error querying most recent l2 block: %v", err) } diff --git a/system_tests/outbox_test.go b/system_tests/outbox_test.go index 6b43cc83b0..d0ca0ccda3 100644 --- a/system_tests/outbox_test.go +++ b/system_tests/outbox_test.go @@ -35,14 +35,15 @@ func TestOutboxProofs(t *testing.T) { withdrawTopic := arbSysAbi.Events["L2ToL1Tx"].ID merkleTopic := arbSysAbi.Events["SendMerkleUpdate"].ID - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - auth := l2info.GetDefaultTransactOpts("Owner", ctx) + auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) - arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, client) + arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, builder.L2.Client) Require(t, err) - nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, client) + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, builder.L2.Client) Require(t, err) txnCount := int64(1 + rand.Intn(16)) @@ -71,7 +72,7 @@ func TestOutboxProofs(t *testing.T) { txns = append(txns, tx.Hash()) time.Sleep(4 * time.Millisecond) // Geth takes a few ms for the receipt to show up - _, err = client.TransactionReceipt(ctx, tx.Hash()) + _, err = builder.L2.Client.TransactionReceipt(ctx, tx.Hash()) if err == nil { merkleState, err := arbSys.SendMerkleTreeState(&bind.CallOpts{}) Require(t, err, "could not get merkle root") @@ -86,7 +87,7 @@ func TestOutboxProofs(t *testing.T) { for _, tx := range txns { var receipt *types.Receipt - receipt, err = client.TransactionReceipt(ctx, tx) + receipt, err = builder.L2.Client.TransactionReceipt(ctx, tx) Require(t, err, "No receipt for txn") if receipt.Status != types.ReceiptStatusSuccessful { @@ -187,7 +188,7 @@ func TestOutboxProofs(t *testing.T) { // in one lookup, query geth for all the data we need to construct a proof var logs []types.Log if len(query) > 0 { - logs, err = client.FilterLogs(ctx, ethereum.FilterQuery{ + logs, err = builder.L2.Client.FilterLogs(ctx, ethereum.FilterQuery{ Addresses: []common.Address{ types.ArbSysAddress, }, diff --git a/system_tests/precompile_test.go b/system_tests/precompile_test.go index ad08ff7471..10db09275b 100644 --- a/system_tests/precompile_test.go +++ b/system_tests/precompile_test.go @@ -21,10 +21,11 @@ func TestPurePrecompileMethodCalls(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - arbSys, err := precompilesgen.NewArbSys(common.HexToAddress("0x64"), client) + arbSys, err := precompilesgen.NewArbSys(common.HexToAddress("0x64"), builder.L2.Client) Require(t, err, "could not deploy ArbSys contract") chainId, err := arbSys.ArbChainID(&bind.CallOpts{}) Require(t, err, "failed to get the ChainID") @@ -37,10 +38,11 @@ func TestViewLogReverts(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), builder.L2.Client) Require(t, err, "could not deploy ArbSys contract") err = arbDebug.EventsView(nil) @@ -53,11 +55,12 @@ func TestCustomSolidityErrors(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() callOpts := &bind.CallOpts{Context: ctx} - arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), client) + arbDebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), builder.L2.Client) Require(t, err, "could not bind ArbDebug contract") customError := arbDebug.CustomRevert(callOpts, 1024) if customError == nil { @@ -69,7 +72,7 @@ func TestCustomSolidityErrors(t *testing.T) { Fatal(t, observedMessage) } - arbSys, err := precompilesgen.NewArbSys(arbos.ArbSysAddress, client) + arbSys, err := precompilesgen.NewArbSys(arbos.ArbSysAddress, builder.L2.Client) Require(t, err, "could not bind ArbSys contract") _, customError = arbSys.ArbBlockHash(callOpts, big.NewInt(1e9)) if customError == nil { @@ -86,11 +89,12 @@ func TestPrecompileErrorGasLeft(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - auth := info.GetDefaultTransactOpts("Faucet", ctx) - _, _, simple, err := mocksgen.DeploySimple(&auth, client) + auth := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) + _, _, simple, err := mocksgen.DeploySimple(&auth, builder.L2.Client) Require(t, err) assertNotAllGasConsumed := func(to common.Address, input []byte) { diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index 285548dcdb..9429155d7c 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -23,26 +23,23 @@ import ( func prepareNodeWithHistory(t *testing.T, ctx context.Context, execConfig *gethexec.Config, txCount uint64) (node *arbnode.Node, executionNode *gethexec.ExecutionNode, l2client *ethclient.Client, cancel func()) { t.Helper() - l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, execConfig, nil, nil) - cancel = func() { - defer requireClose(t, l1stack) - defer node.StopAndWait() - } - l2info.GenerateAccount("User2") + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.execConfig = execConfig + cleanup := builder.Build(t) + builder.L2Info.GenerateAccount("User2") var txs []*types.Transaction for i := uint64(0); i < txCount; i++ { - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, common.Big1, nil) + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil) txs = append(txs, tx) - err := l2client.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) } for _, tx := range txs { - _, err := EnsureTxSucceeded(ctx, l2client, tx) + _, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) } - exec := getExecNode(t, node) - return node, exec, l2client, cancel + return builder.L2.ConsensusNode, builder.L2.ExecNode, builder.L2.Client, cleanup } func fillHeaderCache(t *testing.T, bc *core.BlockChain, from, to uint64) { diff --git a/system_tests/reorg_resequencing_test.go b/system_tests/reorg_resequencing_test.go index bdd4c4af45..fcc6603aed 100644 --- a/system_tests/reorg_resequencing_test.go +++ b/system_tests/reorg_resequencing_test.go @@ -19,29 +19,28 @@ func TestReorgResequencing(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, node, client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - execNode := getExecNode(t, node) - - startMsgCount, err := node.TxStreamer.GetMessageCount() + startMsgCount, err := builder.L2.ConsensusNode.TxStreamer.GetMessageCount() Require(t, err) - l2info.GenerateAccount("Intermediate") - l2info.GenerateAccount("User1") - l2info.GenerateAccount("User2") - l2info.GenerateAccount("User3") - l2info.GenerateAccount("User4") - TransferBalance(t, "Owner", "User1", big.NewInt(params.Ether), l2info, client, ctx) - TransferBalance(t, "Owner", "Intermediate", big.NewInt(params.Ether*3), l2info, client, ctx) - TransferBalance(t, "Intermediate", "User2", big.NewInt(params.Ether), l2info, client, ctx) - TransferBalance(t, "Intermediate", "User3", big.NewInt(params.Ether), l2info, client, ctx) + builder.L2Info.GenerateAccount("Intermediate") + builder.L2Info.GenerateAccount("User1") + builder.L2Info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User3") + builder.L2Info.GenerateAccount("User4") + builder.L2.TransferBalance(t, "Owner", "User1", big.NewInt(params.Ether), builder.L2Info) + builder.L2.TransferBalance(t, "Owner", "Intermediate", big.NewInt(params.Ether*3), builder.L2Info) + builder.L2.TransferBalance(t, "Intermediate", "User2", big.NewInt(params.Ether), builder.L2Info) + builder.L2.TransferBalance(t, "Intermediate", "User3", big.NewInt(params.Ether), builder.L2Info) // Intermediate does not have exactly 1 ether because of fees accountsWithBalance := []string{"User1", "User2", "User3"} verifyBalances := func(scenario string) { for _, account := range accountsWithBalance { - balance, err := client.BalanceAt(ctx, l2info.GetAddress(account), nil) + balance, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress(account), nil) Require(t, err) if balance.Int64() != params.Ether { Fatal(t, "expected account", account, "to have a balance of 1 ether but instead it has", balance, "wei "+scenario) @@ -50,15 +49,15 @@ func TestReorgResequencing(t *testing.T) { } verifyBalances("before reorg") - err = node.TxStreamer.ReorgTo(startMsgCount) + err = builder.L2.ConsensusNode.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = execNode.ExecEngine.HeadMessageNumberSync(t) + _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t) Require(t, err) verifyBalances("after empty reorg") - prevMessage, err := node.TxStreamer.GetMessage(startMsgCount - 1) + prevMessage, err := builder.L2.ConsensusNode.TxStreamer.GetMessage(startMsgCount - 1) Require(t, err) delayedIndexHash := common.BigToHash(big.NewInt(int64(prevMessage.DelayedMessagesRead))) newMessage := &arbostypes.L1IncomingMessage{ @@ -70,24 +69,24 @@ func TestReorgResequencing(t *testing.T) { RequestId: &delayedIndexHash, L1BaseFee: common.Big0, }, - L2msg: append(l2info.GetAddress("User4").Bytes(), math.U256Bytes(big.NewInt(params.Ether))...), + L2msg: append(builder.L2Info.GetAddress("User4").Bytes(), math.U256Bytes(big.NewInt(params.Ether))...), } - err = node.TxStreamer.AddMessages(startMsgCount, true, []arbostypes.MessageWithMetadata{{ + err = builder.L2.ConsensusNode.TxStreamer.AddMessages(startMsgCount, true, []arbostypes.MessageWithMetadata{{ Message: newMessage, DelayedMessagesRead: prevMessage.DelayedMessagesRead + 1, }}) Require(t, err) - _, err = execNode.ExecEngine.HeadMessageNumberSync(t) + _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t) Require(t, err) accountsWithBalance = append(accountsWithBalance, "User4") verifyBalances("after reorg with new deposit") - err = node.TxStreamer.ReorgTo(startMsgCount) + err = builder.L2.ConsensusNode.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = execNode.ExecEngine.HeadMessageNumberSync(t) + _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t) Require(t, err) verifyBalances("after second empty reorg") diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index 0fc6d24ed0..3400af335d 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -14,16 +14,15 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/arbos/arbostypes" + "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/arbos/retryables" "github.com/offchainlabs/nitro/arbos/util" "github.com/offchainlabs/nitro/execution/gethexec" - "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/node_interfacegen" @@ -33,25 +32,23 @@ import ( ) func retryableSetup(t *testing.T) ( - *BlockchainTestInfo, - *BlockchainTestInfo, - *ethclient.Client, - *ethclient.Client, + *NodeBuilder, *bridgegen.Inbox, func(*types.Receipt) *types.Transaction, context.Context, func(), ) { ctx, cancel := context.WithCancel(context.Background()) - l2info, l2node, l2client, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.Build(t) - l2info.GenerateAccount("User2") - l2info.GenerateAccount("Beneficiary") - l2info.GenerateAccount("Burn") + builder.L2Info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("Beneficiary") + builder.L2Info.GenerateAccount("Burn") - delayedInbox, err := bridgegen.NewInbox(l1info.GetAddress("Inbox"), l1client) + delayedInbox, err := bridgegen.NewInbox(builder.L1Info.GetAddress("Inbox"), builder.L1.Client) Require(t, err) - delayedBridge, err := arbnode.NewDelayedBridge(l1client, l1info.GetAddress("Bridge"), 0) + delayedBridge, err := arbnode.NewDelayedBridge(builder.L1.Client, builder.L1Info.GetAddress("Bridge"), 0) Require(t, err) lookupL2Tx := func(l1Receipt *types.Receipt) *types.Transaction { @@ -91,15 +88,15 @@ func retryableSetup(t *testing.T) ( // burn some gas so that the faucet's Callvalue + Balance never exceeds a uint256 discard := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) - TransferBalance(t, "Faucet", "Burn", discard, l2info, l2client, ctx) + builder.L2.TransferBalance(t, "Faucet", "Burn", discard, builder.L2Info) teardown := func() { // check the integrity of the RPC - blockNum, err := l2client.BlockNumber(ctx) + blockNum, err := builder.L2.Client.BlockNumber(ctx) Require(t, err, "failed to get L2 block number") for number := uint64(0); number < blockNum; number++ { - block, err := l2client.BlockByNumber(ctx, arbmath.UintToBig(number)) + block, err := builder.L2.Client.BlockByNumber(ctx, arbmath.UintToBig(number)) Require(t, err, "failed to get L2 block", number, "of", blockNum) if block.Number().Uint64() != number { Fatal(t, "block number mismatch", number, block.Number().Uint64()) @@ -108,19 +105,20 @@ func retryableSetup(t *testing.T) ( cancel() - l2node.StopAndWait() - requireClose(t, l1stack) + builder.L2.ConsensusNode.StopAndWait() + requireClose(t, builder.L1.Stack) } - return l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown + return builder, delayedInbox, lookupL2Tx, ctx, teardown } func TestRetryableNoExist(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, node, l2client := CreateTestL2(t, ctx) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) + arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), builder.L2.Client) Require(t, err) _, err = arbRetryableTx.GetTimeout(&bind.CallOpts{}, common.Hash{}) if err.Error() != "execution reverted: error NoTicketWithID()" { @@ -130,20 +128,20 @@ func TestRetryableNoExist(t *testing.T) { func TestSubmitRetryableImmediateSuccess(t *testing.T) { t.Parallel() - l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - user2Address := l2info.GetAddress("User2") - beneficiaryAddress := l2info.GetAddress("Beneficiary") + user2Address := builder.L2Info.GetAddress("User2") + beneficiaryAddress := builder.L2Info.GetAddress("Beneficiary") deposit := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) callValue := big.NewInt(1e6) - nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client) + nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, builder.L2.Client) Require(t, err, "failed to deploy NodeInterface") // estimate the gas needed to auto redeem the retryable - usertxoptsL2 := l2info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL2 := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL2.NoSend = true usertxoptsL2.GasMargin = 0 tx, err := nodeInterface.EstimateRetryableTicket( @@ -161,7 +159,7 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { colors.PrintBlue("estimate: ", estimate) // submit & auto redeem the retryable using the gas estimate - usertxoptsL1 := l1info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL1 := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL1.Value = deposit l1tx, err := delayedInbox.CreateRetryableTicket( &usertxoptsL1, @@ -176,21 +174,21 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := builder.L1.EnsureTxSucceeded(l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, builder) - receipt, err := EnsureTxSucceeded(ctx, l2client, lookupL2Tx(l1Receipt)) + receipt, err := builder.L2.EnsureTxSucceeded(lookupL2Tx(l1Receipt)) Require(t, err) if receipt.Status != types.ReceiptStatusSuccessful { Fatal(t) } - l2balance, err := l2client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if !arbmath.BigEquals(l2balance, big.NewInt(1e6)) { @@ -200,18 +198,18 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { func TestSubmitRetryableFailThenRetry(t *testing.T) { t.Parallel() - l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) - usertxopts := l1info.GetDefaultTransactOpts("Faucet", ctx) + ownerTxOpts := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + usertxopts := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxopts.Value = arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) - simpleAddr, simple := deploySimple(t, ctx, ownerTxOpts, l2client) + simpleAddr, simple := builder.L2.DeploySimple(t, ownerTxOpts) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) - beneficiaryAddress := l2info.GetAddress("Beneficiary") + beneficiaryAddress := builder.L2Info.GetAddress("Beneficiary") l1tx, err := delayedInbox.CreateRetryableTicket( &usertxopts, simpleAddr, @@ -226,15 +224,15 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := builder.L1.EnsureTxSucceeded(l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, builder) - receipt, err := EnsureTxSucceeded(ctx, l2client, lookupL2Tx(l1Receipt)) + receipt, err := builder.L2.EnsureTxSucceeded(lookupL2Tx(l1Receipt)) Require(t, err) if len(receipt.Logs) != 2 { Fatal(t, len(receipt.Logs)) @@ -243,23 +241,23 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { firstRetryTxId := receipt.Logs[1].Topics[2] // get receipt for the auto redeem, make sure it failed - receipt, err = WaitForTx(ctx, l2client, firstRetryTxId, time.Second*5) + receipt, err = WaitForTx(ctx, builder.L2.Client, firstRetryTxId, time.Second*5) Require(t, err) if receipt.Status != types.ReceiptStatusFailed { Fatal(t, receipt.GasUsed) } - arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) + arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), builder.L2.Client) Require(t, err) tx, err := arbRetryableTx.Redeem(&ownerTxOpts, ticketId) Require(t, err) - receipt, err = EnsureTxSucceeded(ctx, l2client, tx) + receipt, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) retryTxId := receipt.Logs[0].Topics[2] // check the receipt for the retry - receipt, err = WaitForTx(ctx, l2client, retryTxId, time.Second*1) + receipt, err = WaitForTx(ctx, builder.L2.Client, retryTxId, time.Second*1) Require(t, err) if receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, receipt.Status) @@ -289,32 +287,32 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { func TestSubmissionGasCosts(t *testing.T) { t.Parallel() - l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, l2client, l2info) - elevateL2Basefee(t, ctx, l2client, l2info) + infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, builder) + elevateL2Basefee(t, ctx, builder) - usertxopts := l1info.GetDefaultTransactOpts("Faucet", ctx) + usertxopts := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxopts.Value = arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) - l2info.GenerateAccount("Refund") - l2info.GenerateAccount("Receive") - faucetAddress := util.RemapL1Address(l1info.GetAddress("Faucet")) - beneficiaryAddress := l2info.GetAddress("Beneficiary") - feeRefundAddress := l2info.GetAddress("Refund") - receiveAddress := l2info.GetAddress("Receive") + builder.L2Info.GenerateAccount("Refund") + builder.L2Info.GenerateAccount("Receive") + faucetAddress := util.RemapL1Address(builder.L1Info.GetAddress("Faucet")) + beneficiaryAddress := builder.L2Info.GetAddress("Beneficiary") + feeRefundAddress := builder.L2Info.GetAddress("Refund") + receiveAddress := builder.L2Info.GetAddress("Receive") colors.PrintBlue("Faucet ", faucetAddress) colors.PrintBlue("Receive ", receiveAddress) colors.PrintBlue("Beneficiary ", beneficiaryAddress) colors.PrintBlue("Fee Refund ", feeRefundAddress) - fundsBeforeSubmit, err := l2client.BalanceAt(ctx, faucetAddress, nil) + fundsBeforeSubmit, err := builder.L2.Client.BalanceAt(ctx, faucetAddress, nil) Require(t, err) - infraBalanceBefore, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceBefore, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceBefore, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceBefore, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) usefulGas := params.TxGas @@ -338,28 +336,28 @@ func TestSubmissionGasCosts(t *testing.T) { ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := builder.L1.EnsureTxSucceeded(l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, builder) submissionTxOuter := lookupL2Tx(l1Receipt) - submissionReceipt, err := EnsureTxSucceeded(ctx, l2client, submissionTxOuter) + submissionReceipt, err := builder.L2.EnsureTxSucceeded(submissionTxOuter) Require(t, err) if len(submissionReceipt.Logs) != 2 { Fatal(t, "Unexpected number of logs:", len(submissionReceipt.Logs)) } firstRetryTxId := submissionReceipt.Logs[1].Topics[2] // get receipt for the auto redeem - redeemReceipt, err := WaitForTx(ctx, l2client, firstRetryTxId, time.Second*5) + redeemReceipt, err := WaitForTx(ctx, builder.L2.Client, firstRetryTxId, time.Second*5) Require(t, err) if redeemReceipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "first retry tx failed") } - redeemBlock, err := l2client.HeaderByNumber(ctx, redeemReceipt.BlockNumber) + redeemBlock, err := builder.L2.Client.HeaderByNumber(ctx, redeemReceipt.BlockNumber) Require(t, err) l2BaseFee := redeemBlock.BaseFee @@ -367,18 +365,18 @@ func TestSubmissionGasCosts(t *testing.T) { excessWei := arbmath.BigMulByUint(l2BaseFee, excessGasLimit) excessWei.Add(excessWei, arbmath.BigMul(excessGasPrice, retryableGas)) - fundsAfterSubmit, err := l2client.BalanceAt(ctx, faucetAddress, nil) + fundsAfterSubmit, err := builder.L2.Client.BalanceAt(ctx, faucetAddress, nil) Require(t, err) - beneficiaryFunds, err := l2client.BalanceAt(ctx, beneficiaryAddress, nil) + beneficiaryFunds, err := builder.L2.Client.BalanceAt(ctx, beneficiaryAddress, nil) Require(t, err) - refundFunds, err := l2client.BalanceAt(ctx, feeRefundAddress, nil) + refundFunds, err := builder.L2.Client.BalanceAt(ctx, feeRefundAddress, nil) Require(t, err) - receiveFunds, err := l2client.BalanceAt(ctx, receiveAddress, nil) + receiveFunds, err := builder.L2.Client.BalanceAt(ctx, receiveAddress, nil) Require(t, err) - infraBalanceAfter, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceAfter, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceAfter, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceAfter, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) colors.PrintBlue("CallGas ", retryableGas) @@ -425,7 +423,7 @@ func TestSubmissionGasCosts(t *testing.T) { Fatal(t, "Supplied gas was improperly deducted\n", fundsBeforeSubmit, "\n", fundsAfterSubmit) } - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), builder.L2.Client) Require(t, err) minimumBaseFee, err := arbGasInfo.GetMinimumGasPrice(&bind.CallOpts{Context: ctx}) Require(t, err) @@ -450,28 +448,28 @@ func TestSubmissionGasCosts(t *testing.T) { } } -func waitForL1DelayBlocks(t *testing.T, ctx context.Context, l1client *ethclient.Client, l1info *BlockchainTestInfo) { +func waitForL1DelayBlocks(t *testing.T, ctx context.Context, builder *NodeBuilder) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } } func TestDepositETH(t *testing.T) { t.Parallel() - _, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - faucetAddr := l1info.GetAddress("Faucet") + faucetAddr := builder.L1Info.GetAddress("Faucet") - oldBalance, err := l2client.BalanceAt(ctx, faucetAddr, nil) + oldBalance, err := builder.L2.Client.BalanceAt(ctx, faucetAddr, nil) if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", faucetAddr, err) } - txOpts := l1info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) txOpts.Value = big.NewInt(13) l1tx, err := delayedInbox.DepositEth0(&txOpts) @@ -479,20 +477,20 @@ func TestDepositETH(t *testing.T) { t.Fatalf("DepositEth0() unexected error: %v", err) } - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := builder.L1.EnsureTxSucceeded(l1tx) if err != nil { t.Fatalf("EnsureTxSucceeded() unexpected error: %v", err) } if l1Receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("Got transaction status: %v, want: %v", l1Receipt.Status, types.ReceiptStatusSuccessful) } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, builder) - l2Receipt, err := EnsureTxSucceeded(ctx, l2client, lookupL2Tx(l1Receipt)) + l2Receipt, err := builder.L2.EnsureTxSucceeded(lookupL2Tx(l1Receipt)) if err != nil { t.Fatalf("EnsureTxSucceeded unexpected error: %v", err) } - newBalance, err := l2client.BalanceAt(ctx, faucetAddr, l2Receipt.BlockNumber) + newBalance, err := builder.L2.Client.BalanceAt(ctx, faucetAddr, l2Receipt.BlockNumber) if err != nil { t.Fatalf("BalanceAt(%v) unexpected error: %v", faucetAddr, err) } @@ -502,13 +500,13 @@ func TestDepositETH(t *testing.T) { } func TestArbitrumContractTx(t *testing.T) { - l2Info, l1Info, l2Client, l1Client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - faucetL2Addr := util.RemapL1Address(l1Info.GetAddress("Faucet")) - TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), l2Info, l2Client, ctx) + faucetL2Addr := util.RemapL1Address(builder.L1Info.GetAddress("Faucet")) + builder.L2.TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), builder.L2Info) - l2TxOpts := l2Info.GetDefaultTransactOpts("Faucet", ctx) - l2ContractAddr, _ := deploySimple(t, ctx, l2TxOpts, l2Client) + l2TxOpts := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) + l2ContractAddr, _ := builder.L2.DeploySimple(t, l2TxOpts) l2ContractABI, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) if err != nil { t.Fatalf("Error parsing contract ABI: %v", err) @@ -518,15 +516,15 @@ func TestArbitrumContractTx(t *testing.T) { t.Fatalf("Error packing method's call data: %v", err) } unsignedTx := types.NewTx(&types.ArbitrumContractTx{ - ChainId: l2Info.Signer.ChainID(), + ChainId: builder.L2Info.Signer.ChainID(), From: faucetL2Addr, - GasFeeCap: l2Info.GasPrice.Mul(l2Info.GasPrice, big.NewInt(2)), + GasFeeCap: builder.L2Info.GasPrice.Mul(builder.L2Info.GasPrice, big.NewInt(2)), Gas: 1e6, To: &l2ContractAddr, Value: common.Big0, Data: data, }) - txOpts := l1Info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) l1tx, err := delayedInbox.SendContractTransaction( &txOpts, arbmath.UintToBig(unsignedTx.Gas()), @@ -538,15 +536,15 @@ func TestArbitrumContractTx(t *testing.T) { if err != nil { t.Fatalf("Error sending unsigned transaction: %v", err) } - receipt, err := EnsureTxSucceeded(ctx, l1Client, l1tx) + receipt, err := builder.L1.EnsureTxSucceeded(l1tx) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", l1tx.Hash(), err) } if receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("L1 transaction: %v has failed", l1tx.Hash()) } - waitForL1DelayBlocks(t, ctx, l1Client, l1Info) - receipt, err = EnsureTxSucceeded(ctx, l2Client, lookupL2Tx(receipt)) + waitForL1DelayBlocks(t, ctx, builder) + _, err = builder.L2.EnsureTxSucceeded(lookupL2Tx(receipt)) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", unsignedTx.Hash(), err) } @@ -555,17 +553,17 @@ func TestArbitrumContractTx(t *testing.T) { func TestL1FundedUnsignedTransaction(t *testing.T) { t.Parallel() ctx := context.Background() - l2Info, node, l2Client, l1Info, _, l1Client, l1Stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1Stack) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - faucetL2Addr := util.RemapL1Address(l1Info.GetAddress("Faucet")) + faucetL2Addr := util.RemapL1Address(builder.L1Info.GetAddress("Faucet")) // Transfer balance to Faucet's corresponding L2 address, so that there is // enough balance on its' account for executing L2 transaction. - TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), l2Info, l2Client, ctx) + builder.L2.TransferBalanceTo(t, "Faucet", faucetL2Addr, big.NewInt(1e18), builder.L2Info) - l2TxOpts := l2Info.GetDefaultTransactOpts("Faucet", ctx) - contractAddr, _ := deploySimple(t, ctx, l2TxOpts, l2Client) + l2TxOpts := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) + contractAddr, _ := builder.L2.DeploySimple(t, l2TxOpts) contractABI, err := abi.JSON(strings.NewReader(mocksgen.SimpleABI)) if err != nil { t.Fatalf("Error parsing contract ABI: %v", err) @@ -574,27 +572,27 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { if err != nil { t.Fatalf("Error packing method's call data: %v", err) } - nonce, err := l2Client.NonceAt(ctx, faucetL2Addr, nil) + nonce, err := builder.L2.Client.NonceAt(ctx, faucetL2Addr, nil) if err != nil { t.Fatalf("Error getting nonce at address: %v, error: %v", faucetL2Addr, err) } unsignedTx := types.NewTx(&types.ArbitrumUnsignedTx{ - ChainId: l2Info.Signer.ChainID(), + ChainId: builder.L2Info.Signer.ChainID(), From: faucetL2Addr, Nonce: nonce, - GasFeeCap: l2Info.GasPrice, + GasFeeCap: builder.L2Info.GasPrice, Gas: 1e6, To: &contractAddr, Value: common.Big0, Data: data, }) - delayedInbox, err := bridgegen.NewInbox(l1Info.GetAddress("Inbox"), l1Client) + delayedInbox, err := bridgegen.NewInbox(builder.L1Info.GetAddress("Inbox"), builder.L1.Client) if err != nil { t.Fatalf("Error getting Go binding of L1 Inbox contract: %v", err) } - txOpts := l1Info.GetDefaultTransactOpts("Faucet", ctx) + txOpts := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) l1tx, err := delayedInbox.SendUnsignedTransaction( &txOpts, arbmath.UintToBig(unsignedTx.Gas()), @@ -607,15 +605,15 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { if err != nil { t.Fatalf("Error sending unsigned transaction: %v", err) } - receipt, err := EnsureTxSucceeded(ctx, l1Client, l1tx) + receipt, err := builder.L1.EnsureTxSucceeded(l1tx) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", l1tx.Hash(), err) } if receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("L1 transaction: %v has failed", l1tx.Hash()) } - waitForL1DelayBlocks(t, ctx, l1Client, l1Info) - receipt, err = EnsureTxSucceeded(ctx, l2Client, unsignedTx) + waitForL1DelayBlocks(t, ctx, builder) + receipt, err = builder.L2.EnsureTxSucceeded(unsignedTx) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", unsignedTx.Hash(), err) } @@ -625,28 +623,28 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { } func TestRetryableSubmissionAndRedeemFees(t *testing.T) { - l2info, l1info, l2client, l1client, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) defer teardown() - infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, l2client, l2info) + infraFeeAddr, networkFeeAddr := setupFeeAddresses(t, ctx, builder) - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) - simpleAddr, simple := deploySimple(t, ctx, ownerTxOpts, l2client) + ownerTxOpts := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + simpleAddr, simple := builder.L2.DeploySimple(t, ownerTxOpts) simpleABI, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) - elevateL2Basefee(t, ctx, l2client, l2info) + elevateL2Basefee(t, ctx, builder) - infraBalanceBefore, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceBefore, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceBefore, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceBefore, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - beneficiaryAddress := l2info.GetAddress("Beneficiary") + beneficiaryAddress := builder.L2Info.GetAddress("Beneficiary") deposit := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) callValue := common.Big0 - usertxoptsL1 := l1info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL1 := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL1.Value = deposit - baseFee := GetBaseFee(t, l2client, ctx) + baseFee := builder.L2.GetBaseFee(t) l1tx, err := delayedInbox.CreateRetryableTicket( &usertxoptsL1, simpleAddr, @@ -660,16 +658,16 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { simpleABI.Methods["incrementRedeem"].ID, ) Require(t, err) - l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + l1Receipt, err := builder.L1.EnsureTxSucceeded(l1tx) Require(t, err) if l1Receipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, l1client, l1info) + waitForL1DelayBlocks(t, ctx, builder) submissionTxOuter := lookupL2Tx(l1Receipt) - submissionReceipt, err := EnsureTxSucceeded(ctx, l2client, submissionTxOuter) + submissionReceipt, err := builder.L2.EnsureTxSucceeded(submissionTxOuter) Require(t, err) if len(submissionReceipt.Logs) != 2 { Fatal(t, len(submissionReceipt.Logs)) @@ -677,36 +675,36 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { ticketId := submissionReceipt.Logs[0].Topics[1] firstRetryTxId := submissionReceipt.Logs[1].Topics[2] // get receipt for the auto redeem, make sure it failed - autoRedeemReceipt, err := WaitForTx(ctx, l2client, firstRetryTxId, time.Second*5) + autoRedeemReceipt, err := WaitForTx(ctx, builder.L2.Client, firstRetryTxId, time.Second*5) Require(t, err) if autoRedeemReceipt.Status != types.ReceiptStatusFailed { Fatal(t, "first retry tx shouldn't have succeeded") } - infraBalanceAfterSubmission, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceAfterSubmission, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceAfterSubmission, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceAfterSubmission, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) - usertxoptsL2 := l2info.GetDefaultTransactOpts("Faucet", ctx) - arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) + usertxoptsL2 := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx) + arbRetryableTx, err := precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), builder.L2.Client) Require(t, err) tx, err := arbRetryableTx.Redeem(&usertxoptsL2, ticketId) Require(t, err) - redeemReceipt, err := EnsureTxSucceeded(ctx, l2client, tx) + redeemReceipt, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) retryTxId := redeemReceipt.Logs[0].Topics[2] // check the receipt for the retry - retryReceipt, err := WaitForTx(ctx, l2client, retryTxId, time.Second*1) + retryReceipt, err := WaitForTx(ctx, builder.L2.Client, retryTxId, time.Second*1) Require(t, err) if retryReceipt.Status != types.ReceiptStatusSuccessful { Fatal(t, "retry failed") } - infraBalanceAfterRedeem, err := l2client.BalanceAt(ctx, infraFeeAddr, nil) + infraBalanceAfterRedeem, err := builder.L2.Client.BalanceAt(ctx, infraFeeAddr, nil) Require(t, err) - networkBalanceAfterRedeem, err := l2client.BalanceAt(ctx, networkFeeAddr, nil) + networkBalanceAfterRedeem, err := builder.L2.Client.BalanceAt(ctx, networkFeeAddr, nil) Require(t, err) // verify that the increment happened, so we know the retry succeeded @@ -735,11 +733,11 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { infraRedeemFee := arbmath.BigSub(infraBalanceAfterRedeem, infraBalanceAfterSubmission) networkRedeemFee := arbmath.BigSub(networkBalanceAfterRedeem, networkBalanceAfterSubmission) - arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), l2client) + arbGasInfo, err := precompilesgen.NewArbGasInfo(common.HexToAddress("0x6c"), builder.L2.Client) Require(t, err) minimumBaseFee, err := arbGasInfo.GetMinimumGasPrice(&bind.CallOpts{Context: ctx}) Require(t, err) - submissionBaseFee := GetBaseFeeAt(t, l2client, ctx, submissionReceipt.BlockNumber) + submissionBaseFee := builder.L2.GetBaseFeeAt(t, submissionReceipt.BlockNumber) submissionTx, ok := submissionTxOuter.GetInner().(*types.ArbitrumSubmitRetryableTx) if !ok { Fatal(t, "inner tx isn't ArbitrumSubmitRetryableTx") @@ -753,13 +751,13 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { retryableSubmissionFee, ) - retryTxOuter, _, err := l2client.TransactionByHash(ctx, retryTxId) + retryTxOuter, _, err := builder.L2.Client.TransactionByHash(ctx, retryTxId) Require(t, err) retryTx, ok := retryTxOuter.GetInner().(*types.ArbitrumRetryTx) if !ok { Fatal(t, "inner tx isn't ArbitrumRetryTx") } - redeemBaseFee := GetBaseFeeAt(t, l2client, ctx, redeemReceipt.BlockNumber) + redeemBaseFee := builder.L2.GetBaseFeeAt(t, redeemReceipt.BlockNumber) t.Log("redeem base fee:", redeemBaseFee) // redeem & retry expected fees @@ -795,59 +793,59 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { } // elevateL2Basefee by burning gas exceeding speed limit -func elevateL2Basefee(t *testing.T, ctx context.Context, l2client *ethclient.Client, l2info *BlockchainTestInfo) { - baseFeeBefore := GetBaseFee(t, l2client, ctx) +func elevateL2Basefee(t *testing.T, ctx context.Context, builder *NodeBuilder) { + baseFeeBefore := builder.L2.GetBaseFee(t) colors.PrintBlue("Elevating base fee...") arbostestabi, err := precompilesgen.ArbosTestMetaData.GetAbi() Require(t, err) - _, err = precompilesgen.NewArbosTest(common.HexToAddress("0x69"), l2client) + _, err = precompilesgen.NewArbosTest(common.HexToAddress("0x69"), builder.L2.Client) Require(t, err, "failed to deploy ArbosTest") burnAmount := gethexec.ConfigDefaultTest().RPC.RPCGasCap burnTarget := uint64(5 * l2pricing.InitialSpeedLimitPerSecondV6 * l2pricing.InitialBacklogTolerance) for i := uint64(0); i < (burnTarget+burnAmount)/burnAmount; i++ { burnArbGas := arbostestabi.Methods["burnArbGas"] - data, err := burnArbGas.Inputs.Pack(arbmath.UintToBig(burnAmount - l2info.TransferGas)) + data, err := burnArbGas.Inputs.Pack(arbmath.UintToBig(burnAmount - builder.L2Info.TransferGas)) Require(t, err) input := append([]byte{}, burnArbGas.ID...) input = append(input, data...) to := common.HexToAddress("0x69") - tx := l2info.PrepareTxTo("Faucet", &to, burnAmount, big.NewInt(0), input) - Require(t, l2client.SendTransaction(ctx, tx)) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + tx := builder.L2Info.PrepareTxTo("Faucet", &to, burnAmount, big.NewInt(0), input) + Require(t, builder.L2.Client.SendTransaction(ctx, tx)) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) } - baseFee := GetBaseFee(t, l2client, ctx) + baseFee := builder.L2.GetBaseFee(t) colors.PrintBlue("New base fee: ", baseFee, " diff:", baseFee.Uint64()-baseFeeBefore.Uint64()) } -func setupFeeAddresses(t *testing.T, ctx context.Context, l2client *ethclient.Client, l2info *BlockchainTestInfo) (common.Address, common.Address) { - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) - ownerCallOpts := l2info.GetDefaultCallOpts("Owner", ctx) +func setupFeeAddresses(t *testing.T, ctx context.Context, builder *NodeBuilder) (common.Address, common.Address) { + ownerTxOpts := builder.L2Info.GetDefaultTransactOpts("Owner", ctx) + ownerCallOpts := builder.L2Info.GetDefaultCallOpts("Owner", ctx) // make "Owner" a chain owner - arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), l2client) + arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), builder.L2.Client) Require(t, err, "failed to deploy ArbDebug") tx, err := arbdebug.BecomeChainOwner(&ownerTxOpts) Require(t, err, "failed to deploy ArbDebug") - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - arbowner, err := precompilesgen.NewArbOwner(common.HexToAddress("70"), l2client) + arbowner, err := precompilesgen.NewArbOwner(common.HexToAddress("70"), builder.L2.Client) Require(t, err) - arbownerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("6b"), l2client) + arbownerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("6b"), builder.L2.Client) Require(t, err) - l2info.GenerateAccount("InfraFee") - l2info.GenerateAccount("NetworkFee") - networkFeeAddr := l2info.GetAddress("NetworkFee") - infraFeeAddr := l2info.GetAddress("InfraFee") + builder.L2Info.GenerateAccount("InfraFee") + builder.L2Info.GenerateAccount("NetworkFee") + networkFeeAddr := builder.L2Info.GetAddress("NetworkFee") + infraFeeAddr := builder.L2Info.GetAddress("InfraFee") tx, err = arbowner.SetNetworkFeeAccount(&ownerTxOpts, networkFeeAddr) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) networkFeeAccount, err := arbownerPublic.GetNetworkFeeAccount(ownerCallOpts) Require(t, err) tx, err = arbowner.SetInfraFeeAccount(&ownerTxOpts, infraFeeAddr) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) infraFeeAccount, err := arbownerPublic.GetInfraFeeAccount(ownerCallOpts) Require(t, err) diff --git a/system_tests/seq_coordinator_test.go b/system_tests/seq_coordinator_test.go index ac3167a604..886a0528c7 100644 --- a/system_tests/seq_coordinator_test.go +++ b/system_tests/seq_coordinator_test.go @@ -56,7 +56,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { // stdio protocol makes sure forwarder initialization doesn't fail nodeNames := []string{"stdio://A", "stdio://B", "stdio://C", "stdio://D", "stdio://E"} - nodes := make([]*arbnode.Node, len(nodeNames)) + testNodes := make([]*TestClient, len(nodeNames)) // init DB to known state initRedisForTest(t, ctx, builder.nodeConfig.SeqCoordinator.RedisUrl, nodeNames) @@ -65,11 +65,11 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { builder.nodeConfig.SeqCoordinator.MyUrl = nodeNames[nodeNum] builder.L2Info = l2Info builder.Build(t) - nodes[nodeNum] = builder.L2.ConsensusNode + testNodes[nodeNum] = builder.L2 } trySequencing := func(nodeNum int) bool { - node := nodes[nodeNum] + node := testNodes[nodeNum].ConsensusNode curMsgs, err := node.TxStreamer.GetMessageCountSync(t) Require(t, err) emptyMessage := arbostypes.MessageWithMetadata{ @@ -98,14 +98,15 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { // node(n) has higher prio than node(n+1), so should be impossible for more than one to succeed trySequencingEverywhere := func() int { succeeded := -1 - for nodeNum, node := range nodes { + for nodeNum, testNode := range testNodes { + node := testNode.ConsensusNode if node == nil { continue } if trySequencing(nodeNum) { if succeeded >= 0 { t.Fatal("sequnced succeeded in parallel", - "index1:", succeeded, "debug", nodes[succeeded].SeqCoordinator.DebugPrint(), + "index1:", succeeded, "debug", testNodes[succeeded].ConsensusNode.SeqCoordinator.DebugPrint(), "index2:", nodeNum, "debug", node.SeqCoordinator.DebugPrint(), "now", time.Now().UnixMilli()) } @@ -116,7 +117,8 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { } waitForMsgEverywhere := func(msgNum arbutil.MessageIndex) { - for _, currentNode := range nodes { + for _, testNode := range testNodes { + currentNode := testNode.ConsensusNode if currentNode == nil { continue } @@ -137,16 +139,16 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { var needsStop []*arbnode.Node killNode := func(nodeNum int) { if nodeNum%3 == 0 { - nodes[nodeNum].SeqCoordinator.PrepareForShutdown() - needsStop = append(needsStop, nodes[nodeNum]) + testNodes[nodeNum].ConsensusNode.SeqCoordinator.PrepareForShutdown() + needsStop = append(needsStop, testNodes[nodeNum].ConsensusNode) } else { - nodes[nodeNum].StopAndWait() + testNodes[nodeNum].ConsensusNode.StopAndWait() } - nodes[nodeNum] = nil + testNodes[nodeNum].ConsensusNode = nil } nodeForwardTarget := func(nodeNum int) int { - execNode := getExecNode(t, nodes[nodeNum]) + execNode := testNodes[nodeNum].ExecNode fwTarget := execNode.TxPublisher.(*gethexec.TxPreChecker).TransactionPublisher.(*gethexec.Sequencer).ForwardTarget() if fwTarget == "" { return -1 @@ -178,7 +180,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { t.Log("Starting other nodes") - for i := 1; i < len(nodes); i++ { + for i := 1; i < len(testNodes); i++ { createStartNode(i) } @@ -189,7 +191,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { for { // all remaining nodes know which is the chosen one - for i := currentSequencer + 1; i < len(nodes); i++ { + for i := currentSequencer + 1; i < len(testNodes); i++ { for attempts := 1; nodeForwardTarget(i) != currentSequencer; attempts++ { if attempts > 10 { t.Fatal("initial forward target not set") @@ -206,7 +208,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { sequencedMesssages++ } - if currentSequencer == len(nodes)-1 { + if currentSequencer == len(testNodes)-1 { addNodes = true } if addNodes { @@ -258,7 +260,7 @@ func TestRedisSeqCoordinatorPriorities(t *testing.T) { waitForMsgEverywhere(sequencedMesssages) } - for nodeNum := range nodes { + for nodeNum := range testNodes { killNode(nodeNum) } for _, node := range needsStop { @@ -282,7 +284,6 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { cleanup := builder.Build(t) defer cleanup() - clientA := builder.L2.Client redisClient, err := redisutil.RedisClientFromURL(builder.nodeConfig.SeqCoordinator.RedisUrl) Require(t, err) @@ -312,26 +313,25 @@ func testCoordinatorMessageSync(t *testing.T, successCase bool) { testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: builder.nodeConfig}) defer cleanupB() - clientB := testClientB.Client tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) - err = clientA.SendTransaction(ctx, tx) + err = builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, clientA, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) if successCase { - _, err = WaitForTx(ctx, clientB, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, testClientB.Client, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := clientB.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) + l2balance, err := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance:", l2balance) } } else { - _, err = WaitForTx(ctx, clientB, tx.Hash(), time.Second) + _, err = WaitForTx(ctx, testClientB.Client, tx.Hash(), time.Second) if err == nil { Fatal(t, "tx received by node with different seq coordinator signing key") } diff --git a/system_tests/seq_nonce_test.go b/system_tests/seq_nonce_test.go index d70f47a146..f0e3dcffd7 100644 --- a/system_tests/seq_nonce_test.go +++ b/system_tests/seq_nonce_test.go @@ -15,7 +15,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/arbmath" ) @@ -24,12 +23,13 @@ func TestSequencerParallelNonces(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - config := gethexec.ConfigDefaultTest() - config.Sequencer.NonceFailureCacheExpiry = time.Minute - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.takeOwnership = false + builder.execConfig.Sequencer.NonceFailureCacheExpiry = time.Minute + cleanup := builder.Build(t) + defer cleanup() - l2info.GenerateAccount("Destination") + builder.L2Info.GenerateAccount("Destination") wg := sync.WaitGroup{} for thread := 0; thread < 10; thread++ { @@ -37,11 +37,11 @@ func TestSequencerParallelNonces(t *testing.T) { go func() { defer wg.Done() for i := 0; i < 10; i++ { - tx := l2info.PrepareTx("Owner", "Destination", l2info.TransferGas, common.Big1, nil) + tx := builder.L2Info.PrepareTx("Owner", "Destination", builder.L2Info.TransferGas, common.Big1, nil) // Sleep a random amount of time up to 20 milliseconds time.Sleep(time.Millisecond * time.Duration(rand.Intn(20))) t.Log("Submitting transaction with nonce", tx.Nonce()) - err := client.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) t.Log("Got response for transaction with nonce", tx.Nonce()) } @@ -49,8 +49,8 @@ func TestSequencerParallelNonces(t *testing.T) { } wg.Wait() - addr := l2info.GetAddress("Destination") - balance, err := client.BalanceAt(ctx, addr, nil) + addr := builder.L2Info.GetAddress("Destination") + balance, err := builder.L2.Client.BalanceAt(ctx, addr, nil) Require(t, err) if !arbmath.BigEquals(balance, big.NewInt(100)) { Fatal(t, "Unexpected user balance", balance) @@ -62,15 +62,16 @@ func TestSequencerNonceTooHigh(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - config := gethexec.ConfigDefaultTest() - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.takeOwnership = false + cleanup := builder.Build(t) + defer cleanup() - l2info.GetInfoWithPrivKey("Owner").Nonce++ + builder.L2Info.GetInfoWithPrivKey("Owner").Nonce++ before := time.Now() - tx := l2info.PrepareTx("Owner", "Owner", l2info.TransferGas, common.Big0, nil) - err := client.SendTransaction(ctx, tx) + tx := builder.L2Info.PrepareTx("Owner", "Owner", builder.L2Info.TransferGas, common.Big0, nil) + err := builder.L2.Client.SendTransaction(ctx, tx) if err == nil { Fatal(t, "No error when nonce was too high") } @@ -78,7 +79,7 @@ func TestSequencerNonceTooHigh(t *testing.T) { Fatal(t, "Unexpected transaction error", err) } elapsed := time.Since(before) - if elapsed > 2*config.Sequencer.NonceFailureCacheExpiry { + if elapsed > 2*builder.execConfig.Sequencer.NonceFailureCacheExpiry { Fatal(t, "Sequencer took too long to respond with nonce too high") } } @@ -88,19 +89,20 @@ func TestSequencerNonceTooHighQueueFull(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - config := gethexec.ConfigDefaultTest() - config.Sequencer.NonceFailureCacheSize = 5 - config.Sequencer.NonceFailureCacheExpiry = time.Minute - l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, false) - defer node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.takeOwnership = false + builder.execConfig.Sequencer.NonceFailureCacheSize = 5 + builder.execConfig.Sequencer.NonceFailureCacheExpiry = time.Minute + cleanup := builder.Build(t) + defer cleanup() count := 15 var completed uint64 for i := 0; i < count; i++ { - l2info.GetInfoWithPrivKey("Owner").Nonce++ - tx := l2info.PrepareTx("Owner", "Owner", l2info.TransferGas, common.Big0, nil) + builder.L2Info.GetInfoWithPrivKey("Owner").Nonce++ + tx := builder.L2Info.PrepareTx("Owner", "Owner", builder.L2Info.TransferGas, common.Big0, nil) go func() { - err := client.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) if err == nil { Fatal(t, "No error when nonce was too high") } @@ -110,7 +112,7 @@ func TestSequencerNonceTooHighQueueFull(t *testing.T) { for wait := 9; wait >= 0; wait-- { got := int(atomic.LoadUint64(&completed)) - expected := count - config.Sequencer.NonceFailureCacheSize + expected := count - builder.execConfig.Sequencer.NonceFailureCacheSize if got == expected { break } diff --git a/system_tests/seq_pause_test.go b/system_tests/seq_pause_test.go index 3817768517..6ce464d8da 100644 --- a/system_tests/seq_pause_test.go +++ b/system_tests/seq_pause_test.go @@ -16,13 +16,13 @@ func TestSequencerPause(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info1, nodeA, client := CreateTestL2(t, ctx) - defer nodeA.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() const numUsers = 100 - execA := getExecNode(t, nodeA) - prechecker, ok := execA.TxPublisher.(*gethexec.TxPreChecker) + prechecker, ok := builder.L2.ExecNode.TxPublisher.(*gethexec.TxPreChecker) if !ok { t.Error("prechecker not found on node") } @@ -35,15 +35,15 @@ func TestSequencerPause(t *testing.T) { for num := 0; num < numUsers; num++ { userName := fmt.Sprintf("My_User_%d", num) - l2info1.GenerateAccount(userName) + builder.L2Info.GenerateAccount(userName) users = append(users, userName) } for _, userName := range users { - tx := l2info1.PrepareTx("Owner", userName, l2info1.TransferGas, big.NewInt(1e16), nil) - err := client.SendTransaction(ctx, tx) + tx := builder.L2Info.PrepareTx("Owner", userName, builder.L2Info.TransferGas, big.NewInt(1e16), nil) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) } @@ -52,7 +52,7 @@ func TestSequencerPause(t *testing.T) { var txs types.Transactions for _, userName := range users { - tx := l2info1.PrepareTx(userName, "Owner", l2info1.TransferGas, big.NewInt(2), nil) + tx := builder.L2Info.PrepareTx(userName, "Owner", builder.L2Info.TransferGas, big.NewInt(2), nil) txs = append(txs, tx) } @@ -63,7 +63,7 @@ func TestSequencerPause(t *testing.T) { }(tx) } - _, err := EnsureTxSucceededWithTimeout(ctx, client, txs[0], time.Second) + _, err := builder.L2.EnsureTxSucceededWithTimeout(txs[0], time.Second) if err == nil { t.Error("tx passed while sequencer paused") } @@ -71,7 +71,7 @@ func TestSequencerPause(t *testing.T) { sequencer.Activate() for _, tx := range txs { - _, err := EnsureTxSucceeded(ctx, client, tx) + _, err := builder.L2.EnsureTxSucceeded(tx) Require(t, err) } } diff --git a/system_tests/seq_reject_test.go b/system_tests/seq_reject_test.go index 34a14c660e..76bdfc2612 100644 --- a/system_tests/seq_reject_test.go +++ b/system_tests/seq_reject_test.go @@ -17,7 +17,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" - "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/colors" @@ -28,21 +27,21 @@ func TestSequencerRejection(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - seqNodeConfig := arbnode.ConfigDefaultL2Test() - seqNodeConfig.Feed.Output = *newBroadcasterConfigTest() feedErrChan := make(chan error, 10) - l2info1, nodeA, client1 := CreateTestL2WithConfig(t, ctx, nil, seqNodeConfig, nil, true) - defer nodeA.StopAndWait() - - clientNodeConfig := arbnode.ConfigDefaultL2Test() - port := nodeA.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port - clientNodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) - - _, nodeB, client2 := CreateTestL2WithConfig(t, ctx, nil, clientNodeConfig, nil, false) - defer nodeB.StopAndWait() - - auth := l2info1.GetDefaultTransactOpts("Owner", ctx) - simpleAddr, _ := deploySimple(t, ctx, auth, client1) + builderSeq := NewNodeBuilder(ctx).DefaultConfig(t, false) + builderSeq.nodeConfig.Feed.Output = *newBroadcasterConfigTest() + cleanupSeq := builderSeq.Build(t) + defer cleanupSeq() + + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.takeOwnership = false + port := builderSeq.L2.ConsensusNode.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port + builder.nodeConfig.Feed.Input = *newBroadcastClientConfigTest(port) + cleanup := builder.Build(t) + defer cleanup() + + auth := builderSeq.L2Info.GetDefaultTransactOpts("Owner", ctx) + simpleAddr, _ := builderSeq.L2.DeploySimple(t, auth) simpleAbi, err := mocksgen.SimpleMetaData.GetAbi() Require(t, err) noopId := simpleAbi.Methods["noop"].ID @@ -51,7 +50,7 @@ func TestSequencerRejection(t *testing.T) { // Generate the accounts before hand to avoid races for user := 0; user < 9; user++ { name := fmt.Sprintf("User%v", user) - l2info1.GenerateAccount(name) + builderSeq.L2Info.GenerateAccount(name) } wg := sync.WaitGroup{} @@ -59,24 +58,24 @@ func TestSequencerRejection(t *testing.T) { for user := 0; user < 9; user++ { user := user name := fmt.Sprintf("User%v", user) - tx := l2info1.PrepareTx("Owner", name, l2info1.TransferGas, big.NewInt(params.Ether), nil) + tx := builderSeq.L2Info.PrepareTx("Owner", name, builderSeq.L2Info.TransferGas, big.NewInt(params.Ether), nil) - err := client1.SendTransaction(ctx, tx) + err := builderSeq.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client1, tx) + _, err = builderSeq.L2.EnsureTxSucceeded(tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client2, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) wg.Add(1) go func() { defer wg.Done() - info := l2info1.GetInfoWithPrivKey(name) + info := builderSeq.L2Info.GetInfoWithPrivKey(name) txData := &types.DynamicFeeTx{ To: &simpleAddr, - Gas: l2info1.TransferGas + 10000, - GasFeeCap: arbmath.BigMulByUint(l2info1.GasPrice, 100), + Gas: builderSeq.L2Info.TransferGas + 10000, + GasFeeCap: arbmath.BigMulByUint(builderSeq.L2Info.GasPrice, 100), Value: common.Big0, } for atomic.LoadInt32(&stopBackground) == 0 { @@ -92,8 +91,8 @@ func TestSequencerRejection(t *testing.T) { txData.Nonce = 1 << 32 expectedErr = "nonce too high" } - tx = l2info1.SignTxAs(name, txData) - err = client1.SendTransaction(ctx, tx) + tx = builderSeq.L2Info.SignTxAs(name, txData) + err = builderSeq.L2.Client.SendTransaction(ctx, tx) if err != nil && (expectedErr == "" || !strings.Contains(err.Error(), expectedErr)) { Require(t, err, "failed to send tx for user", user) } @@ -102,7 +101,7 @@ func TestSequencerRejection(t *testing.T) { } for i := 100; i >= 0; i-- { - block, err := client1.BlockNumber(ctx) + block, err := builderSeq.L2.Client.BlockNumber(ctx) Require(t, err) if block >= 200 { break @@ -120,11 +119,11 @@ func TestSequencerRejection(t *testing.T) { atomic.StoreInt32(&stopBackground, 1) wg.Wait() - header1, err := client1.HeaderByNumber(ctx, nil) + header1, err := builderSeq.L2.Client.HeaderByNumber(ctx, nil) Require(t, err) for i := 100; i >= 0; i-- { - header2, err := client2.HeaderByNumber(ctx, header1.Number) + header2, err := builder.L2.Client.HeaderByNumber(ctx, header1.Number) if err != nil { select { case err := <-feedErrChan: @@ -132,7 +131,7 @@ func TestSequencerRejection(t *testing.T) { case <-time.After(time.Millisecond * 100): } if i == 0 { - client2Block, _ := client2.BlockNumber(ctx) + client2Block, _ := builder.L2.Client.BlockNumber(ctx) Fatal(t, "client2 failed to reach client1 block ", header1.Number, ", only reached block", client2Block) } continue diff --git a/system_tests/seq_whitelist_test.go b/system_tests/seq_whitelist_test.go index 36e309a5d7..efa30171ac 100644 --- a/system_tests/seq_whitelist_test.go +++ b/system_tests/seq_whitelist_test.go @@ -9,31 +9,30 @@ import ( "testing" "github.com/ethereum/go-ethereum/params" - "github.com/offchainlabs/nitro/execution/gethexec" ) func TestSequencerWhitelist(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - config := gethexec.ConfigDefaultTest() - config.Sequencer.SenderWhitelist = GetTestAddressForAccountName(t, "Owner").String() + "," + GetTestAddressForAccountName(t, "User").String() - l2info, l2node, client := CreateTestL2WithConfig(t, ctx, nil, nil, config, true) - defer l2node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.execConfig.Sequencer.SenderWhitelist = GetTestAddressForAccountName(t, "Owner").String() + "," + GetTestAddressForAccountName(t, "User").String() + cleanup := builder.Build(t) + defer cleanup() - l2info.GenerateAccount("User") - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User") + builder.L2Info.GenerateAccount("User2") // Owner is on the whitelist - TransferBalance(t, "Owner", "User", big.NewInt(params.Ether), l2info, client, ctx) - TransferBalance(t, "Owner", "User2", big.NewInt(params.Ether), l2info, client, ctx) + builder.L2.TransferBalance(t, "Owner", "User", big.NewInt(params.Ether), builder.L2Info) + builder.L2.TransferBalance(t, "Owner", "User2", big.NewInt(params.Ether), builder.L2Info) // User is on the whitelist - TransferBalance(t, "User", "User2", big.NewInt(params.Ether/10), l2info, client, ctx) + builder.L2.TransferBalance(t, "User", "User2", big.NewInt(params.Ether/10), builder.L2Info) // User2 is *not* on the whitelist, therefore this should fail - tx := l2info.PrepareTx("User2", "User", l2info.TransferGas, big.NewInt(params.Ether/10), nil) - err := client.SendTransaction(ctx, tx) + tx := builder.L2Info.PrepareTx("User2", "User", builder.L2Info.TransferGas, big.NewInt(params.Ether/10), nil) + err := builder.L2.Client.SendTransaction(ctx, tx) if err == nil { Fatal(t, "transaction from user not on whitelist accepted") } diff --git a/system_tests/seqcompensation_test.go b/system_tests/seqcompensation_test.go index 362acf6a30..156ced6bfc 100644 --- a/system_tests/seqcompensation_test.go +++ b/system_tests/seqcompensation_test.go @@ -18,19 +18,19 @@ func TestSequencerCompensation(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1(t, ctx, true) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() - l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, nil) - defer nodeB.StopAndWait() + TestClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{}) + defer cleanupB() - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) - err := l2clientA.SendTransaction(ctx, tx) + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2clientA, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) // give the inbox reader a bit of time to pick up the delayed message @@ -38,22 +38,22 @@ func TestSequencerCompensation(t *testing.T) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } - _, err = WaitForTx(ctx, l2clientB, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, TestClientB.Client, tx.Hash(), time.Second*5) Require(t, err) // clientB sees balance means sequencer message was sent - l2balance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := TestClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { Fatal(t, "Unexpected balance:", l2balance) } - initialSeqBalance, err := l2clientB.BalanceAt(ctx, l1pricing.BatchPosterAddress, big.NewInt(0)) + initialSeqBalance, err := TestClientB.Client.BalanceAt(ctx, l1pricing.BatchPosterAddress, big.NewInt(0)) Require(t, err) if initialSeqBalance.Sign() != 0 { Fatal(t, "Unexpected initial sequencer balance:", initialSeqBalance) diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index c90617455a..69aeab0c83 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -18,7 +18,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient/gethclient" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" @@ -91,44 +90,44 @@ func diffAccessList(accessed, al types.AccessList) string { return diff } -func deployGasRefunder(ctx context.Context, t *testing.T, info *BlockchainTestInfo, client *ethclient.Client) common.Address { +func deployGasRefunder(ctx context.Context, t *testing.T, builder *NodeBuilder) common.Address { t.Helper() abi, err := bridgegen.GasRefunderMetaData.GetAbi() if err != nil { t.Fatalf("Error getting gas refunder abi: %v", err) } - fauOpts := info.GetDefaultTransactOpts("Faucet", ctx) - addr, tx, _, err := bind.DeployContract(&fauOpts, *abi, common.FromHex(bridgegen.GasRefunderBin), client) + fauOpts := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) + addr, tx, _, err := bind.DeployContract(&fauOpts, *abi, common.FromHex(bridgegen.GasRefunderBin), builder.L1.Client) if err != nil { t.Fatalf("Error getting gas refunder contract deployment transaction: %v", err) } - if _, err := EnsureTxSucceeded(ctx, client, tx); err != nil { + if _, err := builder.L1.EnsureTxSucceeded(tx); err != nil { t.Fatalf("Error deploying gas refunder contract: %v", err) } - tx = info.PrepareTxTo("Faucet", &addr, 30000, big.NewInt(9223372036854775807), nil) - if err := client.SendTransaction(ctx, tx); err != nil { + tx = builder.L1Info.PrepareTxTo("Faucet", &addr, 30000, big.NewInt(9223372036854775807), nil) + if err := builder.L1.Client.SendTransaction(ctx, tx); err != nil { t.Fatalf("Error sending gas refunder funding transaction") } - if _, err := EnsureTxSucceeded(ctx, client, tx); err != nil { + if _, err := builder.L1.EnsureTxSucceeded(tx); err != nil { t.Fatalf("Error funding gas refunder") } - contract, err := bridgegen.NewGasRefunder(addr, client) + contract, err := bridgegen.NewGasRefunder(addr, builder.L1.Client) if err != nil { t.Fatalf("Error getting gas refunder contract binding: %v", err) } - tx, err = contract.AllowContracts(&fauOpts, []common.Address{info.GetAddress("SequencerInbox")}) + tx, err = contract.AllowContracts(&fauOpts, []common.Address{builder.L1Info.GetAddress("SequencerInbox")}) if err != nil { t.Fatalf("Error creating transaction for altering allowlist in refunder: %v", err) } - if _, err := EnsureTxSucceeded(ctx, client, tx); err != nil { + if _, err := builder.L1.EnsureTxSucceeded(tx); err != nil { t.Fatalf("Error addting sequencer inbox in gas refunder allowlist: %v", err) } - tx, err = contract.AllowRefundees(&fauOpts, []common.Address{info.GetAddress("Sequencer")}) + tx, err = contract.AllowRefundees(&fauOpts, []common.Address{builder.L1Info.GetAddress("Sequencer")}) if err != nil { t.Fatalf("Error creating transaction for altering allowlist in refunder: %v", err) } - if _, err := EnsureTxSucceeded(ctx, client, tx); err != nil { + if _, err := builder.L1.EnsureTxSucceeded(tx); err != nil { t.Fatalf("Error addting sequencer in gas refunder allowlist: %v", err) } return addr @@ -162,7 +161,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { Require(t, err) seqOpts := builder.L1Info.GetDefaultTransactOpts("Sequencer", ctx) - gasRefunderAddr := deployGasRefunder(ctx, t, builder.L1Info, builder.L1.Client) + gasRefunderAddr := deployGasRefunder(ctx, t, builder) ownerAddress := builder.L2Info.GetAddress("Owner") var startL2BlockNumber uint64 = 0 @@ -200,7 +199,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { builder.L1Info.GenerateAccount(acct) faucetTxs = append(faucetTxs, builder.L1Info.PrepareTx("Faucet", acct, 30000, big.NewInt(1e16), nil)) } - SendWaitTestTransactions(t, ctx, builder.L1.Client, faucetTxs) + builder.L1.SendWaitTestTransactions(t, faucetTxs) seqABI, err := bridgegen.SequencerInboxMetaData.GetAbi() if err != nil { diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 0239491422..e9eb884c95 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -27,7 +27,6 @@ import ( "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" "github.com/offchainlabs/nitro/arbos/l2pricing" - "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/solgen/go/mocksgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/staker" @@ -38,15 +37,15 @@ import ( "github.com/offchainlabs/nitro/validator/valnode" ) -func makeBackgroundTxs(ctx context.Context, l2info *BlockchainTestInfo, l2clientA arbutil.L1Interface) error { +func makeBackgroundTxs(ctx context.Context, builder *NodeBuilder) error { for i := uint64(0); ctx.Err() == nil; i++ { - l2info.Accounts["BackgroundUser"].Nonce = i - tx := l2info.PrepareTx("BackgroundUser", "BackgroundUser", l2info.TransferGas, common.Big0, nil) - err := l2clientA.SendTransaction(ctx, tx) + builder.L2Info.Accounts["BackgroundUser"].Nonce = i + tx := builder.L2Info.PrepareTx("BackgroundUser", "BackgroundUser", builder.L2Info.TransferGas, common.Big0, nil) + err := builder.L2.Client.SendTransaction(ctx, tx) if err != nil { return err } - _, err = EnsureTxSucceeded(ctx, l2clientA, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) if err != nil { return err } @@ -263,7 +262,7 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) })() go (func() { defer close(backgroundTxsShutdownChan) - err := makeBackgroundTxs(backgroundTxsCtx, builder.L2Info, builder.L2.Client) + err := makeBackgroundTxs(backgroundTxsCtx, builder) if !errors.Is(err, context.Canceled) { log.Warn("error making background txs", "err", err) } diff --git a/system_tests/transfer_test.go b/system_tests/transfer_test.go index 2e3317907b..a270cca76b 100644 --- a/system_tests/transfer_test.go +++ b/system_tests/transfer_test.go @@ -13,23 +13,24 @@ import ( func TestTransfer(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - l2info, l2node, client := CreateTestL2(t, ctx) - defer l2node.StopAndWait() + builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + cleanup := builder.Build(t) + defer cleanup() - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) - err := client.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, client, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) - bal, err := client.BalanceAt(ctx, l2info.GetAddress("Owner"), nil) + bal, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("Owner"), nil) Require(t, err) fmt.Println("Owner balance is: ", bal) - bal2, err := client.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + bal2, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if bal2.Cmp(big.NewInt(1e12)) != 0 { Fatal(t, "Unexpected recipient balance: ", bal2) diff --git a/system_tests/triedb_race_test.go b/system_tests/triedb_race_test.go index 8174a9b6a2..6d9415df83 100644 --- a/system_tests/triedb_race_test.go +++ b/system_tests/triedb_race_test.go @@ -10,7 +10,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" - "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/testhelpers" ) @@ -18,24 +17,21 @@ func TestTrieDBCommitRace(t *testing.T) { _ = testhelpers.InitTestLog(t, log.LvlError) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - execConfig := gethexec.ConfigDefaultTest() - execConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth - execConfig.Sequencer.MaxBlockSpeed = 0 - execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 - execConfig.Caching.Archive = true - execConfig.Caching.BlockCount = 127 - execConfig.Caching.BlockAge = 0 - execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 127 - execConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 - l2info, node, l2client, _, _, _, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, nil, execConfig, nil, nil) - cancel = func() { - defer requireClose(t, l1stack) - defer node.StopAndWait() - } - defer cancel() - execNode := getExecNode(t, node) - l2info.GenerateAccount("User2") - bc := execNode.Backend.ArbInterface().BlockChain() + + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.execConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth + builder.execConfig.Sequencer.MaxBlockSpeed = 0 + builder.execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 + builder.execConfig.Caching.Archive = true + builder.execConfig.Caching.BlockCount = 127 + builder.execConfig.Caching.BlockAge = 0 + builder.execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 127 + builder.execConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0 + cleanup := builder.Build(t) + defer cleanup() + + builder.L2Info.GenerateAccount("User2") + bc := builder.L2.ExecNode.Backend.ArbInterface().BlockChain() var wg sync.WaitGroup quit := make(chan struct{}) @@ -45,13 +41,13 @@ func TestTrieDBCommitRace(t *testing.T) { for { select { default: - TransferBalance(t, "Faucet", "User2", common.Big1, l2info, l2client, ctx) + builder.L2.TransferBalance(t, "Faucet", "User2", common.Big1, builder.L2Info) case <-quit: return } } }() - api := execNode.Backend.APIBackend() + api := builder.L2.ExecNode.Backend.APIBackend() blockNumber := 1 for i := 0; i < 5; i++ { var roots []common.Hash diff --git a/system_tests/twonodes_test.go b/system_tests/twonodes_test.go index 6280a4a575..c8e348cffb 100644 --- a/system_tests/twonodes_test.go +++ b/system_tests/twonodes_test.go @@ -20,24 +20,27 @@ func testTwoNodesSimple(t *testing.T, dasModeStr string) { chainConfig, l1NodeConfigA, lifecycleManager, _, dasSignerKey := setupConfigWithDAS(t, ctx, dasModeStr) defer lifecycleManager.StopAndWaitUntil(time.Second) - l2info, nodeA, l2clientA, l1info, _, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, nil, chainConfig, nil) - defer requireClose(t, l1stack) - defer nodeA.StopAndWait() - - authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig = l1NodeConfigA + builder.chainConfig = chainConfig + builder.L2Info = nil + cleanup := builder.Build(t) + defer cleanup() + + authorizeDASKeyset(t, ctx, dasSignerKey, builder.L1Info, builder.L1.Client) l1NodeConfigBDataAvailability := l1NodeConfigA.DataAvailability l1NodeConfigBDataAvailability.RPCAggregator.Enable = false - l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, &l1NodeConfigBDataAvailability) - defer nodeB.StopAndWait() + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{dasConfig: &l1NodeConfigBDataAvailability}) + defer cleanupB() - l2info.GenerateAccount("User2") + builder.L2Info.GenerateAccount("User2") - tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, big.NewInt(1e12), nil) + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) - err := l2clientA.SendTransaction(ctx, tx) + err := builder.L2.Client.SendTransaction(ctx, tx) Require(t, err) - _, err = EnsureTxSucceeded(ctx, l2clientA, tx) + _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) // give the inbox reader a bit of time to pick up the delayed message @@ -45,15 +48,15 @@ func testTwoNodesSimple(t *testing.T, dasModeStr string) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } - _, err = WaitForTx(ctx, l2clientB, tx.Hash(), time.Second*5) + _, err = WaitForTx(ctx, testClientB.Client, tx.Hash(), time.Second*5) Require(t, err) - l2balance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("User2"), nil) + l2balance, err := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if l2balance.Cmp(big.NewInt(1e12)) != 0 { diff --git a/system_tests/twonodeslong_test.go b/system_tests/twonodeslong_test.go index 16c369df46..09203e3bcd 100644 --- a/system_tests/twonodeslong_test.go +++ b/system_tests/twonodeslong_test.go @@ -42,32 +42,36 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { chainConfig, l1NodeConfigA, lifecycleManager, _, dasSignerKey := setupConfigWithDAS(t, ctx, dasModeStr) defer lifecycleManager.StopAndWaitUntil(time.Second) - l2info, nodeA, l2client, l1info, l1backend, l1client, l1stack := createTestNodeOnL1WithConfig(t, ctx, true, l1NodeConfigA, nil, chainConfig, nil) - defer requireClose(t, l1stack) + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.nodeConfig = l1NodeConfigA + builder.chainConfig = chainConfig + builder.L2Info = nil + builder.Build(t) + defer requireClose(t, builder.L1.Stack) - authorizeDASKeyset(t, ctx, dasSignerKey, l1info, l1client) + authorizeDASKeyset(t, ctx, dasSignerKey, builder.L1Info, builder.L1.Client) l1NodeConfigBDataAvailability := l1NodeConfigA.DataAvailability l1NodeConfigBDataAvailability.RPCAggregator.Enable = false - l2clientB, nodeB := Create2ndNode(t, ctx, nodeA, l1stack, l1info, &l2info.ArbInitData, &l1NodeConfigBDataAvailability) - defer nodeB.StopAndWait() + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{dasConfig: &l1NodeConfigBDataAvailability}) + defer cleanupB() - l2info.GenerateAccount("DelayedFaucet") - l2info.GenerateAccount("DelayedReceiver") - l2info.GenerateAccount("DirectReceiver") + builder.L2Info.GenerateAccount("DelayedFaucet") + builder.L2Info.GenerateAccount("DelayedReceiver") + builder.L2Info.GenerateAccount("DirectReceiver") - l2info.GenerateAccount("ErrorTxSender") + builder.L2Info.GenerateAccount("ErrorTxSender") - SendWaitTestTransactions(t, ctx, l2client, []*types.Transaction{ - l2info.PrepareTx("Faucet", "ErrorTxSender", l2info.TransferGas, big.NewInt(l2pricing.InitialBaseFeeWei*int64(l2info.TransferGas)), nil), + builder.L2.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L2Info.PrepareTx("Faucet", "ErrorTxSender", builder.L2Info.TransferGas, big.NewInt(l2pricing.InitialBaseFeeWei*int64(builder.L2Info.TransferGas)), nil), }) delayedMsgsToSendMax := big.NewInt(int64(largeLoops * avgDelayedMessagesPerLoop * 10)) delayedFaucetNeeds := new(big.Int).Mul(new(big.Int).Add(fundsPerDelayed, new(big.Int).SetUint64(l2pricing.InitialBaseFeeWei*100000)), delayedMsgsToSendMax) - SendWaitTestTransactions(t, ctx, l2client, []*types.Transaction{ - l2info.PrepareTx("Faucet", "DelayedFaucet", l2info.TransferGas, delayedFaucetNeeds, nil), + builder.L2.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L2Info.PrepareTx("Faucet", "DelayedFaucet", builder.L2Info.TransferGas, delayedFaucetNeeds, nil), }) - delayedFaucetBalance, err := l2client.BalanceAt(ctx, l2info.GetAddress("DelayedFaucet"), nil) + delayedFaucetBalance, err := builder.L2.Client.BalanceAt(ctx, builder.L2Info.GetAddress("DelayedFaucet"), nil) Require(t, err) if delayedFaucetBalance.Cmp(delayedFaucetNeeds) != 0 { @@ -85,17 +89,17 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { randNum := rand.Int() % avgTotalL1MessagesPerLoop var l1tx *types.Transaction if randNum < avgDelayedMessagesPerLoop { - delayedTx := l2info.PrepareTx("DelayedFaucet", "DelayedReceiver", 30001, fundsPerDelayed, nil) - l1tx = WrapL2ForDelayed(t, delayedTx, l1info, "User", 100000) + delayedTx := builder.L2Info.PrepareTx("DelayedFaucet", "DelayedReceiver", 30001, fundsPerDelayed, nil) + l1tx = WrapL2ForDelayed(t, delayedTx, builder.L1Info, "User", 100000) delayedTxs = append(delayedTxs, delayedTx) delayedTransfers++ } else { - l1tx = l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) + l1tx = builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) } l1Txs = append(l1Txs, l1tx) } // adding multiple messages in the same AddLocal to get them in the same L1 block - errs := l1backend.TxPool().AddLocals(l1Txs) + errs := builder.L1.L1Backend.TxPool().AddLocals(l1Txs) for _, err := range errs { if err != nil { Fatal(t, err) @@ -104,26 +108,26 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { l2TxsThisTime := rand.Int() % (avgL2MsgsPerLoop * 2) l2Txs := make([]*types.Transaction, 0, l2TxsThisTime) for len(l2Txs) < l2TxsThisTime { - l2Txs = append(l2Txs, l2info.PrepareTx("Faucet", "DirectReceiver", l2info.TransferGas, fundsPerDirect, nil)) + l2Txs = append(l2Txs, builder.L2Info.PrepareTx("Faucet", "DirectReceiver", builder.L2Info.TransferGas, fundsPerDirect, nil)) } - SendWaitTestTransactions(t, ctx, l2client, l2Txs) + builder.L2.SendWaitTestTransactions(t, l2Txs) directTransfers += int64(l2TxsThisTime) if len(l1Txs) > 0 { - _, err := EnsureTxSucceeded(ctx, l1client, l1Txs[len(l1Txs)-1]) + _, err := builder.L1.EnsureTxSucceeded(l1Txs[len(l1Txs)-1]) if err != nil { Fatal(t, err) } } // create bad tx on delayed inbox - l2info.GetInfoWithPrivKey("ErrorTxSender").Nonce = 10 - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - WrapL2ForDelayed(t, l2info.PrepareTx("ErrorTxSender", "DelayedReceiver", 30002, delayedFaucetNeeds, nil), l1info, "User", 100000), + builder.L2Info.GetInfoWithPrivKey("ErrorTxSender").Nonce = 10 + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + WrapL2ForDelayed(t, builder.L2Info.PrepareTx("ErrorTxSender", "DelayedReceiver", 30002, delayedFaucetNeeds, nil), builder.L1Info, "User", 100000), }) extrBlocksThisTime := rand.Int() % (avgExtraBlocksPerLoop * 2) for i := 0; i < extrBlocksThisTime; i++ { - SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ - l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil), }) } } @@ -137,45 +141,45 @@ func testTwoNodesLong(t *testing.T, dasModeStr string) { for i := 0; i < finalPropagateLoops; i++ { var tx *types.Transaction for j := 0; j < 30; j++ { - tx = l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) - err := l1client.SendTransaction(ctx, tx) + tx = builder.L1Info.PrepareTx("Faucet", "User", 30000, big.NewInt(1e12), nil) + err := builder.L1.Client.SendTransaction(ctx, tx) if err != nil { Fatal(t, err) } - _, err = EnsureTxSucceeded(ctx, l1client, tx) + _, err = builder.L1.EnsureTxSucceeded(tx) if err != nil { Fatal(t, err) } } } - _, err = EnsureTxSucceededWithTimeout(ctx, l2client, delayedTxs[len(delayedTxs)-1], time.Second*10) + _, err = builder.L2.EnsureTxSucceededWithTimeout(delayedTxs[len(delayedTxs)-1], time.Second*10) Require(t, err, "Failed waiting for Tx on main node") - _, err = EnsureTxSucceededWithTimeout(ctx, l2clientB, delayedTxs[len(delayedTxs)-1], time.Second*10) + _, err = testClientB.EnsureTxSucceededWithTimeout(delayedTxs[len(delayedTxs)-1], time.Second*10) Require(t, err, "Failed waiting for Tx on secondary node") - delayedBalance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("DelayedReceiver"), nil) + delayedBalance, err := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("DelayedReceiver"), nil) Require(t, err) - directBalance, err := l2clientB.BalanceAt(ctx, l2info.GetAddress("DirectReceiver"), nil) + directBalance, err := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("DirectReceiver"), nil) Require(t, err) delayedExpectd := new(big.Int).Mul(fundsPerDelayed, big.NewInt(delayedTransfers)) directExpectd := new(big.Int).Mul(fundsPerDirect, big.NewInt(directTransfers)) if (delayedBalance.Cmp(delayedExpectd) != 0) || (directBalance.Cmp(directExpectd) != 0) { t.Error("delayed balance", delayedBalance, "expected", delayedExpectd, "transfers", delayedTransfers) t.Error("direct balance", directBalance, "expected", directExpectd, "transfers", directTransfers) - ownerBalance, _ := l2clientB.BalanceAt(ctx, l2info.GetAddress("Owner"), nil) - delayedFaucetBalance, _ := l2clientB.BalanceAt(ctx, l2info.GetAddress("DelayedFaucet"), nil) + ownerBalance, _ := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("Owner"), nil) + delayedFaucetBalance, _ := testClientB.Client.BalanceAt(ctx, builder.L2Info.GetAddress("DelayedFaucet"), nil) t.Error("owner balance", ownerBalance, "delayed faucet", delayedFaucetBalance) Fatal(t, "Unexpected balance") } - nodeA.StopAndWait() + builder.L2.ConsensusNode.StopAndWait() - if nodeB.BlockValidator != nil { - lastBlockHeader, err := l2clientB.HeaderByNumber(ctx, nil) + if testClientB.ConsensusNode.BlockValidator != nil { + lastBlockHeader, err := testClientB.Client.HeaderByNumber(ctx, nil) Require(t, err) timeout := getDeadlineTimeout(t, time.Minute*30) // messageindex is same as block number here - if !nodeB.BlockValidator.WaitForPos(t, ctx, arbutil.MessageIndex(lastBlockHeader.Number.Uint64()), timeout) { + if !testClientB.ConsensusNode.BlockValidator.WaitForPos(t, ctx, arbutil.MessageIndex(lastBlockHeader.Number.Uint64()), timeout) { Fatal(t, "did not validate all blocks") } }