diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1a591b720..c77ef3b770 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -132,8 +132,8 @@ jobs: - name: Set environment variables run: | - mkdir -p target/tmp - echo "TMPDIR=$(pwd)/target/tmp" >> "$GITHUB_ENV" + mkdir -p target/tmp/deadbeefbee + echo "TMPDIR=$(pwd)/target/tmp/deadbeefbee" >> "$GITHUB_ENV" echo "GOMEMLIMIT=6GiB" >> "$GITHUB_ENV" echo "GOGC=80" >> "$GITHUB_ENV" diff --git a/arbnode/dataposter/leveldb/leveldb.go b/arbnode/dataposter/leveldb/leveldb.go index c25cba6601..c271b71267 100644 --- a/arbnode/dataposter/leveldb/leveldb.go +++ b/arbnode/dataposter/leveldb/leveldb.go @@ -48,6 +48,7 @@ func idxToKey(idx uint64) []byte { func (s *Storage[Item]) GetContents(_ context.Context, startingIndex uint64, maxResults uint64) ([]*Item, error) { var res []*Item it := s.db.NewIterator([]byte(""), idxToKey(startingIndex)) + defer it.Release() for i := 0; i < int(maxResults); i++ { if !it.Next() { break @@ -91,6 +92,7 @@ func (s *Storage[Item]) Prune(ctx context.Context, keepStartingAt uint64) error } end := idxToKey(keepStartingAt) it := s.db.NewIterator([]byte{}, idxToKey(0)) + defer it.Release() b := s.db.NewBatch() for it.Next() { if bytes.Compare(it.Key(), end) >= 0 { diff --git a/staker/block_validator.go b/staker/block_validator.go index 108ef5710c..0ff74a8014 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -984,9 +984,12 @@ func (v *BlockValidator) checkLegacyValid() error { log.Warn("legacy valid batch ahead of db", "current", batchCount, "required", requiredBatchCount) return nil } - msgCount, err := v.inboxTracker.GetBatchMessageCount(v.legacyValidInfo.AfterPosition.BatchNumber) - if err != nil { - return err + var msgCount arbutil.MessageIndex + if v.legacyValidInfo.AfterPosition.BatchNumber > 0 { + msgCount, err = v.inboxTracker.GetBatchMessageCount(v.legacyValidInfo.AfterPosition.BatchNumber - 1) + if err != nil { + return err + } } msgCount += arbutil.MessageIndex(v.legacyValidInfo.AfterPosition.PosInBatch) processedCount, err := v.streamer.GetProcessedMessageCount() diff --git a/system_tests/forwarder_test.go b/system_tests/forwarder_test.go index 3691caf5d2..d4cf0d8eb7 100644 --- a/system_tests/forwarder_test.go +++ b/system_tests/forwarder_test.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "math/big" + "os" "path/filepath" "strings" "sync" @@ -157,7 +158,18 @@ func createSequencer( // tmpPath returns file path with specified filename from temporary directory of the test. func tmpPath(t *testing.T, filename string) string { - return filepath.Join(t.TempDir(), filename) + t.Helper() + // create a unique, maximum 10 characters-long temporary directory {name} with path as $TMPDIR/{name} + tmpDir, err := os.MkdirTemp("", "") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + t.Cleanup(func() { + if err = os.RemoveAll(tmpDir); err != nil { + t.Errorf("Failed to cleanup temp dir: %v", err) + } + }) + return filepath.Join(tmpDir, filename) } // testNodes creates specified number of paths for ipc from temporary directory of the test. diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index bb94808e74..16436cf47a 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -60,13 +60,14 @@ func retryableSetup(t *testing.T) ( } var submissionTxs []*types.Transaction for _, message := range messages { - if message.Message.Header.Kind != arbostypes.L1MessageType_SubmitRetryable { + k := message.Message.Header.Kind + if k != arbostypes.L1MessageType_SubmitRetryable && k != arbostypes.L1MessageType_EthDeposit { continue } txs, err := arbos.ParseL2Transactions(message.Message, params.ArbitrumDevTestChainConfig().ChainID, nil) Require(t, err) for _, tx := range txs { - if tx.Type() == types.ArbitrumSubmitRetryableTxType { + if tx.Type() == types.ArbitrumSubmitRetryableTxType || tx.Type() == types.ArbitrumDepositTxType { submissionTxs = append(submissionTxs, tx) } } @@ -398,6 +399,52 @@ func waitForL1DelayBlocks(t *testing.T, ctx context.Context, l1client *ethclient } } +func TestDepositETH(t *testing.T) { + t.Parallel() + _, l1info, l2client, l1client, delayedInbox, lookupSubmitRetryableL2TxHash, ctx, teardown := retryableSetup(t) + defer teardown() + + faucetAddr := l1info.GetAddress("Faucet") + + oldBalance, err := l2client.BalanceAt(ctx, faucetAddr, nil) + if err != nil { + t.Fatalf("BalanceAt(%v) unexpected error: %v", faucetAddr, err) + } + + txOpts := l1info.GetDefaultTransactOpts("Faucet", ctx) + txOpts.Value = big.NewInt(13) + + l1tx, err := delayedInbox.DepositEth0(&txOpts) + if err != nil { + t.Fatalf("DepositEth0() unexected error: %v", err) + } + + l1Receipt, err := EnsureTxSucceeded(ctx, l1client, 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) + + txHash := lookupSubmitRetryableL2TxHash(l1Receipt) + l2Receipt, err := WaitForTx(ctx, l2client, txHash, time.Second*5) + if err != nil { + t.Fatalf("WaitForTx(%v) unexpected error: %v", txHash, err) + } + if l2Receipt.Status != types.ReceiptStatusSuccessful { + t.Errorf("Got transaction status: %v, want: %v", l2Receipt.Status, types.ReceiptStatusSuccessful) + } + newBalance, err := l2client.BalanceAt(ctx, faucetAddr, l2Receipt.BlockNumber) + if err != nil { + t.Fatalf("BalanceAt(%v) unexpected error: %v", faucetAddr, err) + } + if got := new(big.Int); got.Sub(newBalance, oldBalance).Cmp(txOpts.Value) != 0 { + t.Errorf("Got transferred: %v, want: %v", got, txOpts.Value) + } +} + func TestArbitrumContractTx(t *testing.T) { ctx := context.Background() l2Info, node, l2Client, l1Info, _, l1Client, l1Stack := createTestNodeOnL1(t, ctx, true)