github.com/ethereum/go-ethereum@v1.16.1/cmd/workload/historytest.go (about)

     1  // Copyright 2025 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // go-ethereum is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package main
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/common/hexutil"
    26  	"github.com/ethereum/go-ethereum/internal/utesting"
    27  )
    28  
    29  // historyTest is the content of a history test.
    30  type historyTest struct {
    31  	BlockNumbers   []uint64       `json:"blockNumbers"`
    32  	BlockHashes    []common.Hash  `json:"blockHashes"`
    33  	TxCounts       []int          `json:"txCounts"`
    34  	TxHashIndex    []int          `json:"txHashIndex"`
    35  	TxHashes       []*common.Hash `json:"txHashes"`
    36  	ReceiptsHashes []common.Hash  `json:"blockReceiptsHashes"`
    37  }
    38  
    39  type historyTestSuite struct {
    40  	cfg   testConfig
    41  	tests historyTest
    42  }
    43  
    44  func newHistoryTestSuite(cfg testConfig) *historyTestSuite {
    45  	s := &historyTestSuite{cfg: cfg}
    46  	if err := s.loadTests(); err != nil {
    47  		exit(err)
    48  	}
    49  	return s
    50  }
    51  
    52  func (s *historyTestSuite) loadTests() error {
    53  	file, err := s.cfg.fsys.Open(s.cfg.historyTestFile)
    54  	if err != nil {
    55  		return fmt.Errorf("can't open historyTestFile: %v", err)
    56  	}
    57  	defer file.Close()
    58  	if err := json.NewDecoder(file).Decode(&s.tests); err != nil {
    59  		return fmt.Errorf("invalid JSON in %s: %v", s.cfg.historyTestFile, err)
    60  	}
    61  	if len(s.tests.BlockNumbers) == 0 {
    62  		return fmt.Errorf("historyTestFile %s has no test data", s.cfg.historyTestFile)
    63  	}
    64  	return nil
    65  }
    66  
    67  func (s *historyTestSuite) allTests() []workloadTest {
    68  	return []workloadTest{
    69  		newWorkLoadTest("History/getBlockByHash", s.testGetBlockByHash),
    70  		newWorkLoadTest("History/getBlockByNumber", s.testGetBlockByNumber),
    71  		newWorkLoadTest("History/getBlockReceiptsByHash", s.testGetBlockReceiptsByHash),
    72  		newWorkLoadTest("History/getBlockReceiptsByNumber", s.testGetBlockReceiptsByNumber),
    73  		newWorkLoadTest("History/getBlockTransactionCountByHash", s.testGetBlockTransactionCountByHash),
    74  		newWorkLoadTest("History/getBlockTransactionCountByNumber", s.testGetBlockTransactionCountByNumber),
    75  		newWorkLoadTest("History/getTransactionByBlockHashAndIndex", s.testGetTransactionByBlockHashAndIndex),
    76  		newWorkLoadTest("History/getTransactionByBlockNumberAndIndex", s.testGetTransactionByBlockNumberAndIndex),
    77  	}
    78  }
    79  
    80  func (s *historyTestSuite) testGetBlockByHash(t *utesting.T) {
    81  	ctx := context.Background()
    82  
    83  	for i, num := range s.tests.BlockNumbers {
    84  		bhash := s.tests.BlockHashes[i]
    85  		b, err := s.cfg.client.getBlockByHash(ctx, bhash, false)
    86  		if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory {
    87  			continue
    88  		} else if err != nil {
    89  			t.Errorf("block %d (hash %v): error %v", num, bhash, err)
    90  			continue
    91  		}
    92  		if b == nil {
    93  			t.Errorf("block %d (hash %v): not found", num, bhash)
    94  			continue
    95  		}
    96  		if b.Hash != bhash || uint64(b.Number) != num {
    97  			t.Errorf("block %d (hash %v): invalid number/hash", num, bhash)
    98  		}
    99  	}
   100  }
   101  
   102  func (s *historyTestSuite) testGetBlockByNumber(t *utesting.T) {
   103  	ctx := context.Background()
   104  
   105  	for i, num := range s.tests.BlockNumbers {
   106  		bhash := s.tests.BlockHashes[i]
   107  		b, err := s.cfg.client.getBlockByNumber(ctx, num, false)
   108  		if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory {
   109  			continue
   110  		} else if err != nil {
   111  			t.Errorf("block %d (hash %v): error %v", num, bhash, err)
   112  			continue
   113  		}
   114  		if b == nil {
   115  			t.Errorf("block %d (hash %v): not found", num, bhash)
   116  			continue
   117  		}
   118  		if b.Hash != bhash || uint64(b.Number) != num {
   119  			t.Errorf("block %d (hash %v): invalid number/hash", num, bhash)
   120  		}
   121  	}
   122  }
   123  
   124  func (s *historyTestSuite) testGetBlockTransactionCountByHash(t *utesting.T) {
   125  	ctx := context.Background()
   126  
   127  	for i, num := range s.tests.BlockNumbers {
   128  		bhash := s.tests.BlockHashes[i]
   129  		count, err := s.cfg.client.getBlockTransactionCountByHash(ctx, bhash)
   130  		if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory {
   131  			continue
   132  		} else if err != nil {
   133  			t.Errorf("block %d (hash %v): error %v", num, bhash, err)
   134  			continue
   135  		}
   136  		expectedCount := uint64(s.tests.TxCounts[i])
   137  		if count != expectedCount {
   138  			t.Errorf("block %d (hash %v): wrong txcount %d, want %d", count, expectedCount)
   139  		}
   140  	}
   141  }
   142  
   143  func (s *historyTestSuite) testGetBlockTransactionCountByNumber(t *utesting.T) {
   144  	ctx := context.Background()
   145  
   146  	for i, num := range s.tests.BlockNumbers {
   147  		bhash := s.tests.BlockHashes[i]
   148  		count, err := s.cfg.client.getBlockTransactionCountByNumber(ctx, num)
   149  		if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory {
   150  			continue
   151  		} else if err != nil {
   152  			t.Errorf("block %d (hash %v): error %v", num, bhash, err)
   153  			continue
   154  		}
   155  		expectedCount := uint64(s.tests.TxCounts[i])
   156  		if count != expectedCount {
   157  			t.Errorf("block %d (hash %v): wrong txcount %d, want %d", count, expectedCount)
   158  		}
   159  	}
   160  }
   161  
   162  func (s *historyTestSuite) testGetBlockReceiptsByHash(t *utesting.T) {
   163  	ctx := context.Background()
   164  
   165  	for i, num := range s.tests.BlockNumbers {
   166  		bhash := s.tests.BlockHashes[i]
   167  		receipts, err := s.cfg.client.getBlockReceipts(ctx, bhash)
   168  		if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory {
   169  			continue
   170  		} else if err != nil {
   171  			t.Errorf("block %d (hash %v): error %v", num, bhash, err)
   172  			continue
   173  		}
   174  		hash := calcReceiptsHash(receipts)
   175  		expectedHash := s.tests.ReceiptsHashes[i]
   176  		if hash != expectedHash {
   177  			t.Errorf("block %d (hash %v): wrong receipts hash %v, want %v", num, bhash, hash, expectedHash)
   178  		}
   179  	}
   180  }
   181  
   182  func (s *historyTestSuite) testGetBlockReceiptsByNumber(t *utesting.T) {
   183  	ctx := context.Background()
   184  
   185  	for i, num := range s.tests.BlockNumbers {
   186  		bhash := s.tests.BlockHashes[i]
   187  		receipts, err := s.cfg.client.getBlockReceipts(ctx, hexutil.Uint64(num))
   188  		if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory {
   189  			continue
   190  		} else if err != nil {
   191  			t.Errorf("block %d (hash %v): error %v", num, bhash, err)
   192  			continue
   193  		}
   194  		hash := calcReceiptsHash(receipts)
   195  		expectedHash := s.tests.ReceiptsHashes[i]
   196  		if hash != expectedHash {
   197  			t.Errorf("block %d (hash %v): wrong receipts hash %v, want %v", num, bhash, hash, expectedHash)
   198  		}
   199  	}
   200  }
   201  
   202  func (s *historyTestSuite) testGetTransactionByBlockHashAndIndex(t *utesting.T) {
   203  	ctx := context.Background()
   204  
   205  	for i, num := range s.tests.BlockNumbers {
   206  		bhash := s.tests.BlockHashes[i]
   207  		txIndex := s.tests.TxHashIndex[i]
   208  		expectedHash := s.tests.TxHashes[i]
   209  		if expectedHash == nil {
   210  			continue // no txs in block
   211  		}
   212  
   213  		tx, err := s.cfg.client.getTransactionByBlockHashAndIndex(ctx, bhash, uint64(txIndex))
   214  		if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory {
   215  			continue
   216  		} else if err != nil {
   217  			t.Errorf("block %d (hash %v): error %v", num, bhash, err)
   218  			continue
   219  		}
   220  		if tx == nil {
   221  			t.Errorf("block %d (hash %v): txIndex %d not found", num, bhash, txIndex)
   222  			continue
   223  		}
   224  		if tx.Hash != *expectedHash || uint64(tx.TransactionIndex) != uint64(txIndex) {
   225  			t.Errorf("block %d (hash %v): txIndex %d has wrong txHash/Index", num, bhash, txIndex)
   226  		}
   227  	}
   228  }
   229  
   230  func (s *historyTestSuite) testGetTransactionByBlockNumberAndIndex(t *utesting.T) {
   231  	ctx := context.Background()
   232  
   233  	for i, num := range s.tests.BlockNumbers {
   234  		bhash := s.tests.BlockHashes[i]
   235  		txIndex := s.tests.TxHashIndex[i]
   236  		expectedHash := s.tests.TxHashes[i]
   237  		if expectedHash == nil {
   238  			continue // no txs in block
   239  		}
   240  
   241  		tx, err := s.cfg.client.getTransactionByBlockNumberAndIndex(ctx, num, uint64(txIndex))
   242  		if err = validateHistoryPruneErr(err, num, s.cfg.historyPruneBlock); err == errPrunedHistory {
   243  			continue
   244  		} else if err != nil {
   245  			t.Errorf("block %d (hash %v): error %v", num, bhash, err)
   246  			continue
   247  		}
   248  		if tx == nil {
   249  			t.Errorf("block %d (hash %v): txIndex %d not found", num, bhash, txIndex)
   250  			continue
   251  		}
   252  		if tx.Hash != *expectedHash || uint64(tx.TransactionIndex) != uint64(txIndex) {
   253  			t.Errorf("block %d (hash %v): txIndex %d has wrong txHash/Index", num, bhash, txIndex)
   254  		}
   255  	}
   256  }