diff --git a/cmd/workload/filtertest.go b/cmd/workload/filtertest.go index 0e709ac0fed7..bc76857911a6 100644 --- a/cmd/workload/filtertest.go +++ b/cmd/workload/filtertest.go @@ -108,7 +108,7 @@ func (s *filterTestSuite) filterFullRange(t *utesting.T) { } func (s *filterTestSuite) queryAndCheck(t *utesting.T, query *filterQuery) { - query.run(s.cfg.client) + query.run(s.cfg.client, s.cfg.historyPruneBlock) if query.Err != nil { t.Errorf("Filter query failed (fromBlock: %d toBlock: %d addresses: %v topics: %v error: %v)", query.FromBlock, query.ToBlock, query.Address, query.Topics, query.Err) return @@ -125,7 +125,7 @@ func (s *filterTestSuite) fullRangeQueryAndCheck(t *utesting.T, query *filterQue Address: query.Address, Topics: query.Topics, } - frQuery.run(s.cfg.client) + frQuery.run(s.cfg.client, s.cfg.historyPruneBlock) if frQuery.Err != nil { t.Errorf("Full range filter query failed (addresses: %v topics: %v error: %v)", frQuery.Address, frQuery.Topics, frQuery.Err) return @@ -197,7 +197,7 @@ func (fq *filterQuery) calculateHash() common.Hash { return crypto.Keccak256Hash(enc) } -func (fq *filterQuery) run(client *client) { +func (fq *filterQuery) run(client *client, historyPruneBlock *uint64) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) defer cancel() logs, err := client.Eth.FilterLogs(ctx, ethereum.FilterQuery{ @@ -207,10 +207,13 @@ func (fq *filterQuery) run(client *client) { Topics: fq.Topics, }) if err != nil { + if err = validateHistoryPruneErr(fq.Err, uint64(fq.FromBlock), historyPruneBlock); err == errPrunedHistory { + return + } else if err != nil { + fmt.Printf("Filter query failed: fromBlock: %d toBlock: %d addresses: %v topics: %v error: %v\n", + fq.FromBlock, fq.ToBlock, fq.Address, fq.Topics, err) + } fq.Err = err - fmt.Printf("Filter query failed: fromBlock: %d toBlock: %d addresses: %v topics: %v error: %v\n", - fq.FromBlock, fq.ToBlock, fq.Address, fq.Topics, err) - return } fq.results = logs } diff --git a/cmd/workload/filtertestgen.go b/cmd/workload/filtertestgen.go index 29aad9ddd9dd..e50ec57b4791 100644 --- a/cmd/workload/filtertestgen.go +++ b/cmd/workload/filtertestgen.go @@ -70,7 +70,7 @@ func filterGenCmd(ctx *cli.Context) error { f.updateFinalizedBlock() query := f.newQuery() - query.run(f.client) + query.run(f.client, nil) if query.Err != nil { f.errors = append(f.errors, query) continue @@ -81,7 +81,7 @@ func filterGenCmd(ctx *cli.Context) error { if extQuery == nil { break } - extQuery.run(f.client) + extQuery.run(f.client, nil) if extQuery.Err == nil && len(extQuery.results) < len(query.results) { extQuery.Err = fmt.Errorf("invalid result length; old range %d %d; old length %d; new range %d %d; new length %d; address %v; Topics %v", query.FromBlock, query.ToBlock, len(query.results), diff --git a/cmd/workload/filtertestperf.go b/cmd/workload/filtertestperf.go index c1f2aff580ed..7f4cad4ab983 100644 --- a/cmd/workload/filtertestperf.go +++ b/cmd/workload/filtertestperf.go @@ -70,7 +70,7 @@ func filterPerfCmd(ctx *cli.Context) error { queries[pick] = queries[len(queries)-1] queries = queries[:len(queries)-1] start := time.Now() - qt.query.run(cfg.client) + qt.query.run(cfg.client, cfg.historyPruneBlock) qt.runtime = append(qt.runtime, time.Since(start)) slices.Sort(qt.runtime) qt.medianTime = qt.runtime[len(qt.runtime)/2] diff --git a/cmd/workload/historytest.go b/cmd/workload/historytest.go index a681510422b6..29fe3f5098ad 100644 --- a/cmd/workload/historytest.go +++ b/cmd/workload/historytest.go @@ -108,8 +108,11 @@ func (s *historyTestSuite) testGetBlockByHash(t *utesting.T) { for i, num := range s.tests.BlockNumbers { bhash := s.tests.BlockHashes[i] b, err := s.cfg.client.getBlockByHash(ctx, bhash, false) - if err != nil { - t.Fatalf("block %d (hash %v): error %v", num, bhash, err) + if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory { + continue + } else if err != nil { + t.Errorf("block %d (hash %v): error %v", num, bhash, err) + continue } if b == nil { t.Errorf("block %d (hash %v): not found", num, bhash) @@ -127,8 +130,11 @@ func (s *historyTestSuite) testGetBlockByNumber(t *utesting.T) { for i, num := range s.tests.BlockNumbers { bhash := s.tests.BlockHashes[i] b, err := s.cfg.client.getBlockByNumber(ctx, num, false) - if err != nil { - t.Fatalf("block %d (hash %v): error %v", num, bhash, err) + if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory { + continue + } else if err != nil { + t.Errorf("block %d (hash %v): error %v", num, bhash, err) + continue } if b == nil { t.Errorf("block %d (hash %v): not found", num, bhash) @@ -146,8 +152,11 @@ func (s *historyTestSuite) testGetBlockTransactionCountByHash(t *utesting.T) { for i, num := range s.tests.BlockNumbers { bhash := s.tests.BlockHashes[i] count, err := s.cfg.client.getBlockTransactionCountByHash(ctx, bhash) - if err != nil { - t.Fatalf("block %d (hash %v): error %v", num, bhash, err) + if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory { + continue + } else if err != nil { + t.Errorf("block %d (hash %v): error %v", num, bhash, err) + continue } expectedCount := uint64(s.tests.TxCounts[i]) if count != expectedCount { @@ -162,8 +171,11 @@ func (s *historyTestSuite) testGetBlockTransactionCountByNumber(t *utesting.T) { for i, num := range s.tests.BlockNumbers { bhash := s.tests.BlockHashes[i] count, err := s.cfg.client.getBlockTransactionCountByNumber(ctx, num) - if err != nil { - t.Fatalf("block %d (hash %v): error %v", num, bhash, err) + if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory { + continue + } else if err != nil { + t.Errorf("block %d (hash %v): error %v", num, bhash, err) + continue } expectedCount := uint64(s.tests.TxCounts[i]) if count != expectedCount { @@ -178,8 +190,11 @@ func (s *historyTestSuite) testGetBlockReceiptsByHash(t *utesting.T) { for i, num := range s.tests.BlockNumbers { bhash := s.tests.BlockHashes[i] receipts, err := s.cfg.client.getBlockReceipts(ctx, bhash) - if err != nil { - t.Fatalf("block %d (hash %v): error %v", num, bhash, err) + if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory { + continue + } else if err != nil { + t.Errorf("block %d (hash %v): error %v", num, bhash, err) + continue } hash := calcReceiptsHash(receipts) expectedHash := s.tests.ReceiptsHashes[i] @@ -195,8 +210,11 @@ func (s *historyTestSuite) testGetBlockReceiptsByNumber(t *utesting.T) { for i, num := range s.tests.BlockNumbers { bhash := s.tests.BlockHashes[i] receipts, err := s.cfg.client.getBlockReceipts(ctx, hexutil.Uint64(num)) - if err != nil { - t.Fatalf("block %d (hash %v): error %v", num, bhash, err) + if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory { + continue + } else if err != nil { + t.Errorf("block %d (hash %v): error %v", num, bhash, err) + continue } hash := calcReceiptsHash(receipts) expectedHash := s.tests.ReceiptsHashes[i] @@ -218,8 +236,11 @@ func (s *historyTestSuite) testGetTransactionByBlockHashAndIndex(t *utesting.T) } tx, err := s.cfg.client.getTransactionByBlockHashAndIndex(ctx, bhash, uint64(txIndex)) - if err != nil { - t.Fatalf("block %d (hash %v): error %v", num, bhash, err) + if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory { + continue + } else if err != nil { + t.Errorf("block %d (hash %v): error %v", num, bhash, err) + continue } if tx == nil { t.Errorf("block %d (hash %v): txIndex %d not found", num, bhash, txIndex) @@ -243,8 +264,11 @@ func (s *historyTestSuite) testGetTransactionByBlockNumberAndIndex(t *utesting.T } tx, err := s.cfg.client.getTransactionByBlockNumberAndIndex(ctx, num, uint64(txIndex)) - if err != nil { - t.Fatalf("block %d (hash %v): error %v", num, bhash, err) + if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory { + continue + } else if err != nil { + t.Errorf("block %d (hash %v): error %v", num, bhash, err) + continue } if tx == nil { t.Errorf("block %d (hash %v): txIndex %d not found", num, bhash, txIndex) diff --git a/cmd/workload/testsuite.go b/cmd/workload/testsuite.go index 3e3ea1d00135..e7019e20558b 100644 --- a/cmd/workload/testsuite.go +++ b/cmd/workload/testsuite.go @@ -18,13 +18,17 @@ package main import ( "embed" + "fmt" "io/fs" "os" "slices" + "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/utesting" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" "github.com/urfave/cli/v2" ) @@ -77,10 +81,31 @@ var ( // testConfig holds the parameters for testing. type testConfig struct { - client *client - fsys fs.FS - filterQueryFile string - historyTestFile string + client *client + fsys fs.FS + filterQueryFile string + historyTestFile string + historyPruneBlock *uint64 +} + +var errPrunedHistory = fmt.Errorf("attempt to access pruned history") + +// validateHistoryPruneErr checks whether the given error is caused by access +// to history before the pruning threshold block (it is an rpc.Error with code 4444). +// In this case, errPrunedHistory is returned. +// If the error is a pruned history error that occurs when accessing a block past the +// historyPrune block, an error is returned. +// Otherwise, the original value of err is returned. +func validateHistoryPruneErr(err error, blockNum uint64, historyPruneBlock *uint64) error { + if err != nil { + if rpcErr, ok := err.(rpc.Error); ok && rpcErr.ErrorCode() == 4444 { + if historyPruneBlock != nil && blockNum > *historyPruneBlock { + return fmt.Errorf("pruned history error returned after pruning threshold") + } + return errPrunedHistory + } + } + return err } func testConfigFromCLI(ctx *cli.Context) (cfg testConfig) { @@ -98,10 +123,14 @@ func testConfigFromCLI(ctx *cli.Context) (cfg testConfig) { cfg.fsys = builtinTestFiles cfg.filterQueryFile = "queries/filter_queries_mainnet.json" cfg.historyTestFile = "queries/history_mainnet.json" + cfg.historyPruneBlock = new(uint64) + *cfg.historyPruneBlock = ethconfig.HistoryPrunePoints[params.MainnetGenesisHash].BlockNumber case ctx.Bool(testSepoliaFlag.Name): cfg.fsys = builtinTestFiles cfg.filterQueryFile = "queries/filter_queries_sepolia.json" cfg.historyTestFile = "queries/history_sepolia.json" + cfg.historyPruneBlock = new(uint64) + *cfg.historyPruneBlock = ethconfig.HistoryPrunePoints[params.SepoliaGenesisHash].BlockNumber default: cfg.fsys = os.DirFS(".") cfg.filterQueryFile = ctx.String(filterQueryFileFlag.Name)