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 }