accessors_chain_test.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. // Copyright 2018 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser 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. // The go-ethereum library 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 Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package rawdb
  17. import (
  18. "bytes"
  19. "encoding/hex"
  20. "fmt"
  21. "github.com/ethereum/go-ethereum/common/math"
  22. "github.com/ethereum/go-ethereum/crypto"
  23. "github.com/ethereum/go-ethereum/params"
  24. "math/big"
  25. "testing"
  26. "github.com/ethereum/go-ethereum/common"
  27. "github.com/ethereum/go-ethereum/core/types"
  28. "github.com/ethereum/go-ethereum/rlp"
  29. "golang.org/x/crypto/sha3"
  30. )
  31. // Tests block header storage and retrieval operations.
  32. func TestHeaderStorage(t *testing.T) {
  33. db := NewMemoryDatabase()
  34. // Create a test header to move around the database and make sure it's really new
  35. header := &types.Header{Number: big.NewInt(42), Extra: []byte("test header")}
  36. if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry != nil {
  37. t.Fatalf("Non existent header returned: %v", entry)
  38. }
  39. // Write and verify the header in the database
  40. WriteHeader(db, header)
  41. if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry == nil {
  42. t.Fatalf("Stored header not found")
  43. } else if entry.Hash() != header.Hash() {
  44. t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, header)
  45. }
  46. if entry := ReadHeaderRLP(db, header.Hash(), header.Number.Uint64()); entry == nil {
  47. t.Fatalf("Stored header RLP not found")
  48. } else {
  49. hasher := sha3.NewLegacyKeccak256()
  50. hasher.Write(entry)
  51. if hash := common.BytesToHash(hasher.Sum(nil)); hash != header.Hash() {
  52. t.Fatalf("Retrieved RLP header mismatch: have %v, want %v", entry, header)
  53. }
  54. }
  55. // Delete the header and verify the execution
  56. DeleteHeader(db, header.Hash(), header.Number.Uint64())
  57. if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry != nil {
  58. t.Fatalf("Deleted header returned: %v", entry)
  59. }
  60. }
  61. // Tests block body storage and retrieval operations.
  62. func TestBodyStorage(t *testing.T) {
  63. db := NewMemoryDatabase()
  64. // Create a test body to move around the database and make sure it's really new
  65. body := &types.Body{Uncles: []*types.Header{{Extra: []byte("test header")}}}
  66. hasher := sha3.NewLegacyKeccak256()
  67. rlp.Encode(hasher, body)
  68. hash := common.BytesToHash(hasher.Sum(nil))
  69. if entry := ReadBody(db, hash, 0); entry != nil {
  70. t.Fatalf("Non existent body returned: %v", entry)
  71. }
  72. // Write and verify the body in the database
  73. WriteBody(db, hash, 0, body)
  74. if entry := ReadBody(db, hash, 0); entry == nil {
  75. t.Fatalf("Stored body not found")
  76. } else if types.DeriveSha(types.Transactions(entry.Transactions)) != types.DeriveSha(types.Transactions(body.Transactions)) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(body.Uncles) {
  77. t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, body)
  78. }
  79. if entry := ReadBodyRLP(db, hash, 0); entry == nil {
  80. t.Fatalf("Stored body RLP not found")
  81. } else {
  82. hasher := sha3.NewLegacyKeccak256()
  83. hasher.Write(entry)
  84. if calc := common.BytesToHash(hasher.Sum(nil)); calc != hash {
  85. t.Fatalf("Retrieved RLP body mismatch: have %v, want %v", entry, body)
  86. }
  87. }
  88. // Delete the body and verify the execution
  89. DeleteBody(db, hash, 0)
  90. if entry := ReadBody(db, hash, 0); entry != nil {
  91. t.Fatalf("Deleted body returned: %v", entry)
  92. }
  93. }
  94. // Tests block storage and retrieval operations.
  95. func TestBlockStorage(t *testing.T) {
  96. db := NewMemoryDatabase()
  97. // Create a test block to move around the database and make sure it's really new
  98. block := types.NewBlockWithHeader(&types.Header{
  99. Extra: []byte("test block"),
  100. UncleHash: types.EmptyUncleHash,
  101. TxHash: types.EmptyRootHash,
  102. ReceiptHash: types.EmptyRootHash,
  103. })
  104. if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
  105. t.Fatalf("Non existent block returned: %v", entry)
  106. }
  107. if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry != nil {
  108. t.Fatalf("Non existent header returned: %v", entry)
  109. }
  110. if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry != nil {
  111. t.Fatalf("Non existent body returned: %v", entry)
  112. }
  113. // Write and verify the block in the database
  114. WriteBlock(db, block)
  115. if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry == nil {
  116. t.Fatalf("Stored block not found")
  117. } else if entry.Hash() != block.Hash() {
  118. t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block)
  119. }
  120. if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry == nil {
  121. t.Fatalf("Stored header not found")
  122. } else if entry.Hash() != block.Header().Hash() {
  123. t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, block.Header())
  124. }
  125. if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry == nil {
  126. t.Fatalf("Stored body not found")
  127. } else if types.DeriveSha(types.Transactions(entry.Transactions)) != types.DeriveSha(block.Transactions()) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(block.Uncles()) {
  128. t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, block.Body())
  129. }
  130. // Delete the block and verify the execution
  131. DeleteBlock(db, block.Hash(), block.NumberU64())
  132. if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
  133. t.Fatalf("Deleted block returned: %v", entry)
  134. }
  135. if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry != nil {
  136. t.Fatalf("Deleted header returned: %v", entry)
  137. }
  138. if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry != nil {
  139. t.Fatalf("Deleted body returned: %v", entry)
  140. }
  141. }
  142. // Tests that partial block contents don't get reassembled into full blocks.
  143. func TestPartialBlockStorage(t *testing.T) {
  144. db := NewMemoryDatabase()
  145. block := types.NewBlockWithHeader(&types.Header{
  146. Extra: []byte("test block"),
  147. UncleHash: types.EmptyUncleHash,
  148. TxHash: types.EmptyRootHash,
  149. ReceiptHash: types.EmptyRootHash,
  150. })
  151. // Store a header and check that it's not recognized as a block
  152. WriteHeader(db, block.Header())
  153. if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
  154. t.Fatalf("Non existent block returned: %v", entry)
  155. }
  156. DeleteHeader(db, block.Hash(), block.NumberU64())
  157. // Store a body and check that it's not recognized as a block
  158. WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
  159. if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
  160. t.Fatalf("Non existent block returned: %v", entry)
  161. }
  162. DeleteBody(db, block.Hash(), block.NumberU64())
  163. // Store a header and a body separately and check reassembly
  164. WriteHeader(db, block.Header())
  165. WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
  166. if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry == nil {
  167. t.Fatalf("Stored block not found")
  168. } else if entry.Hash() != block.Hash() {
  169. t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block)
  170. }
  171. }
  172. // Tests block total difficulty storage and retrieval operations.
  173. func TestTdStorage(t *testing.T) {
  174. db := NewMemoryDatabase()
  175. // Create a test TD to move around the database and make sure it's really new
  176. hash, td := common.Hash{}, big.NewInt(314)
  177. if entry := ReadTd(db, hash, 0); entry != nil {
  178. t.Fatalf("Non existent TD returned: %v", entry)
  179. }
  180. // Write and verify the TD in the database
  181. WriteTd(db, hash, 0, td)
  182. if entry := ReadTd(db, hash, 0); entry == nil {
  183. t.Fatalf("Stored TD not found")
  184. } else if entry.Cmp(td) != 0 {
  185. t.Fatalf("Retrieved TD mismatch: have %v, want %v", entry, td)
  186. }
  187. // Delete the TD and verify the execution
  188. DeleteTd(db, hash, 0)
  189. if entry := ReadTd(db, hash, 0); entry != nil {
  190. t.Fatalf("Deleted TD returned: %v", entry)
  191. }
  192. }
  193. // Tests that canonical numbers can be mapped to hashes and retrieved.
  194. func TestCanonicalMappingStorage(t *testing.T) {
  195. db := NewMemoryDatabase()
  196. // Create a test canonical number and assinged hash to move around
  197. hash, number := common.Hash{0: 0xff}, uint64(314)
  198. if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) {
  199. t.Fatalf("Non existent canonical mapping returned: %v", entry)
  200. }
  201. // Write and verify the TD in the database
  202. WriteCanonicalHash(db, hash, number)
  203. if entry := ReadCanonicalHash(db, number); entry == (common.Hash{}) {
  204. t.Fatalf("Stored canonical mapping not found")
  205. } else if entry != hash {
  206. t.Fatalf("Retrieved canonical mapping mismatch: have %v, want %v", entry, hash)
  207. }
  208. // Delete the TD and verify the execution
  209. DeleteCanonicalHash(db, number)
  210. if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) {
  211. t.Fatalf("Deleted canonical mapping returned: %v", entry)
  212. }
  213. }
  214. // Tests that head headers and head blocks can be assigned, individually.
  215. func TestHeadStorage(t *testing.T) {
  216. db := NewMemoryDatabase()
  217. blockHead := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block header")})
  218. blockFull := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block full")})
  219. blockFast := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block fast")})
  220. // Check that no head entries are in a pristine database
  221. if entry := ReadHeadHeaderHash(db); entry != (common.Hash{}) {
  222. t.Fatalf("Non head header entry returned: %v", entry)
  223. }
  224. if entry := ReadHeadBlockHash(db); entry != (common.Hash{}) {
  225. t.Fatalf("Non head block entry returned: %v", entry)
  226. }
  227. if entry := ReadHeadFastBlockHash(db); entry != (common.Hash{}) {
  228. t.Fatalf("Non fast head block entry returned: %v", entry)
  229. }
  230. // Assign separate entries for the head header and block
  231. WriteHeadHeaderHash(db, blockHead.Hash())
  232. WriteHeadBlockHash(db, blockFull.Hash())
  233. WriteHeadFastBlockHash(db, blockFast.Hash())
  234. // Check that both heads are present, and different (i.e. two heads maintained)
  235. if entry := ReadHeadHeaderHash(db); entry != blockHead.Hash() {
  236. t.Fatalf("Head header hash mismatch: have %v, want %v", entry, blockHead.Hash())
  237. }
  238. if entry := ReadHeadBlockHash(db); entry != blockFull.Hash() {
  239. t.Fatalf("Head block hash mismatch: have %v, want %v", entry, blockFull.Hash())
  240. }
  241. if entry := ReadHeadFastBlockHash(db); entry != blockFast.Hash() {
  242. t.Fatalf("Fast head block hash mismatch: have %v, want %v", entry, blockFast.Hash())
  243. }
  244. }
  245. // Tests that receipts associated with a single block can be stored and retrieved.
  246. func TestBlockReceiptStorage(t *testing.T) {
  247. db := NewMemoryDatabase()
  248. tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil)
  249. tx2 := types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil)
  250. // Include block needed to read metadata.
  251. body := &types.Body{Transactions: types.Transactions{tx1, tx2}}
  252. receipt1 := &types.Receipt{
  253. Status: types.ReceiptStatusFailed,
  254. CumulativeGasUsed: 1,
  255. Logs: []*types.Log{
  256. {Address: common.BytesToAddress([]byte{0x11})},
  257. {Address: common.BytesToAddress([]byte{0x01, 0x11})},
  258. },
  259. TxHash: tx1.Hash(),
  260. ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
  261. GasUsed: 111111,
  262. }
  263. receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1})
  264. receipt2 := &types.Receipt{
  265. PostState: common.Hash{2}.Bytes(),
  266. CumulativeGasUsed: 2,
  267. Logs: []*types.Log{
  268. {Address: common.BytesToAddress([]byte{0x22})},
  269. {Address: common.BytesToAddress([]byte{0x02, 0x22})},
  270. },
  271. TxHash: tx2.Hash(),
  272. ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
  273. GasUsed: 222222,
  274. }
  275. receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2})
  276. receipts := []*types.Receipt{receipt1, receipt2}
  277. // Check that no receipt entries are in a pristine database
  278. hash := common.BytesToHash([]byte{0x03, 0x14})
  279. if rs := ReadReceipts(db, hash, 0); len(rs) != 0 {
  280. t.Fatalf("non existent receipts returned: %v", rs)
  281. }
  282. // Insert the body that corresponds to the receipts.
  283. WriteBody(db, hash, 0, body)
  284. // Insert the receipt slice into the database and check presence
  285. WriteReceipts(db, hash, 0, receipts)
  286. // Insert canonical hash that the chain configuration will be mapped to.
  287. WriteCanonicalHash(db, hash, 0)
  288. // Insert the chain configuration.
  289. WriteChainConfig(db, hash, params.MainnetChainConfig)
  290. if rs := ReadReceipts(db, hash, 0); len(rs) == 0 {
  291. t.Fatalf("no receipts returned")
  292. } else {
  293. if err := checkReceiptsRLP(rs, receipts); err != nil {
  294. t.Fatalf(err.Error())
  295. }
  296. }
  297. DeleteBody(db, hash, 0)
  298. // Check that receipts are no longer returned when metadata cannot be recomputed.
  299. if rs := ReadReceipts(db, hash, 0); rs != nil {
  300. t.Fatalf("receipts returned when body was deleted: %v", rs)
  301. }
  302. // Check that receipts without metadata can be returned when specifically
  303. rs := ReadRawReceipts(db, hash, 0)
  304. if err := checkReceiptsRLP(rs, receipts); err != nil {
  305. t.Fatalf(err.Error())
  306. }
  307. // Re-insert the body that corresponds to the receipts.
  308. WriteBody(db, hash, 0, body)
  309. // Delete the receipt slice and check purge
  310. DeleteReceipts(db, hash, 0)
  311. if rs := ReadReceipts(db, hash, 0); len(rs) != 0 {
  312. t.Fatalf("deleted receipts returned: %v", rs)
  313. }
  314. }
  315. func checkReceiptsRLP(have, want types.Receipts) error {
  316. if len(have) != len(want) {
  317. return fmt.Errorf("receipts sizes mismatch: have %d, want %d", len(have), len(want))
  318. }
  319. for i := 0; i < len(want); i++ {
  320. rlpHave, err := rlp.EncodeToBytes(have[i])
  321. if err != nil {
  322. return err
  323. }
  324. rlpWant, err := rlp.EncodeToBytes(want[i])
  325. if err != nil {
  326. return err
  327. }
  328. if !bytes.Equal(rlpHave, rlpWant) {
  329. return fmt.Errorf("receipt #%d: receipt mismatch: have %s, want %s", i, hex.EncodeToString(rlpHave), hex.EncodeToString(rlpWant))
  330. }
  331. }
  332. return nil
  333. }
  334. // Tests that receipts associated with a single block can be stored and retrieved.
  335. func TestSetReceiptsData(t *testing.T) {
  336. tx0 := types.NewContractCreation(1, big.NewInt(1), 1, big.NewInt(1), nil)
  337. tx1 := types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil)
  338. txs := types.Transactions{tx0, tx1}
  339. // Include block needed to read metadata.
  340. body := &types.Body{Transactions: txs}
  341. receipt1 := &types.Receipt{
  342. Status: types.ReceiptStatusFailed,
  343. CumulativeGasUsed: 1,
  344. Logs: []*types.Log{
  345. {Address: common.BytesToAddress([]byte{0x11})},
  346. {Address: common.BytesToAddress([]byte{0x01, 0x11})},
  347. },
  348. TxHash: tx0.Hash(),
  349. ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
  350. GasUsed: 1,
  351. }
  352. receipt2 := &types.Receipt{
  353. PostState: common.Hash{2}.Bytes(),
  354. CumulativeGasUsed: 3,
  355. Logs: []*types.Log{
  356. {Address: common.BytesToAddress([]byte{0x22})},
  357. {Address: common.BytesToAddress([]byte{0x02, 0x22})},
  358. },
  359. TxHash: tx1.Hash(),
  360. ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
  361. GasUsed: 2,
  362. }
  363. receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2})
  364. receipts := []*types.Receipt{receipt1, receipt2}
  365. blockNumber := big.NewInt(1)
  366. blockHash := common.BytesToHash([]byte{0x03, 0x14})
  367. clearComputedFieldsOnReceipts(t, receipts)
  368. if err := SetReceiptsData(params.MainnetChainConfig, blockHash, blockNumber, body, receipts); err != nil {
  369. t.Fatalf("SetReceiptsData(...) = %v, want <nil>", err)
  370. }
  371. signer := types.MakeSigner(params.MainnetChainConfig, blockNumber)
  372. logIndex := uint(0)
  373. for i := range receipts {
  374. if receipts[i].TxHash != txs[i].Hash() {
  375. t.Errorf("receipts[%d].TxHash = %s, want %s", i, receipts[i].TxHash.String(), txs[i].Hash().String())
  376. }
  377. if receipts[i].BlockHash != blockHash {
  378. t.Errorf("receipts[%d].BlockHash = %s, want %s", i, receipts[i].BlockHash.String(), blockHash.String())
  379. }
  380. if receipts[i].BlockNumber.Cmp(blockNumber) != 0 {
  381. t.Errorf("receipts[%c].BlockNumber = %s, want %s", i, receipts[i].BlockNumber.String(), blockNumber.String())
  382. }
  383. if receipts[i].TransactionIndex != uint(i) {
  384. t.Errorf("receipts[%d].TransactionIndex = %d, want %d", i, receipts[i].TransactionIndex, i)
  385. }
  386. if receipts[i].GasUsed != txs[i].Gas() {
  387. t.Errorf("receipts[%d].GasUsed = %d, want %d", i, receipts[i].GasUsed, txs[i].Gas())
  388. }
  389. if txs[i].To() != nil && receipts[i].ContractAddress != (common.Address{}) {
  390. t.Errorf("receipts[%d].ContractAddress = %s, want %s", i, receipts[i].ContractAddress, (common.Address{}).String())
  391. }
  392. from, _ := types.Sender(signer, txs[i])
  393. contractAddress := crypto.CreateAddress(from, txs[i].Nonce())
  394. if txs[i].To() == nil && receipts[i].ContractAddress != contractAddress {
  395. t.Errorf("receipts[%d].ContractAddress = %s, want %s", i, receipts[i].ContractAddress.String(), contractAddress.String())
  396. }
  397. for j := range receipts[i].Logs {
  398. if receipts[i].Logs[j].BlockNumber != blockNumber.Uint64() {
  399. t.Errorf("receipts[%d].Logs[%d].BlockNumber = %d, want %d", i, j, receipts[i].Logs[j].BlockNumber, blockNumber.Uint64())
  400. }
  401. if receipts[i].Logs[j].BlockHash != blockHash {
  402. t.Errorf("receipts[%d].Logs[%d].BlockHash = %s, want %s", i, j, receipts[i].Logs[j].BlockHash.String(), blockHash.String())
  403. }
  404. if receipts[i].Logs[j].TxHash != txs[i].Hash() {
  405. t.Errorf("receipts[%d].Logs[%d].TxHash = %s, want %s", i, j, receipts[i].Logs[j].TxHash.String(), txs[i].Hash().String())
  406. }
  407. if receipts[i].Logs[j].TxHash != txs[i].Hash() {
  408. t.Errorf("receipts[%d].Logs[%d].TxHash = %s, want %s", i, j, receipts[i].Logs[j].TxHash.String(), txs[i].Hash().String())
  409. }
  410. if receipts[i].Logs[j].TxIndex != uint(i) {
  411. t.Errorf("receipts[%d].Logs[%d].TransactionIndex = %d, want %d", i, j, receipts[i].Logs[j].TxIndex, i)
  412. }
  413. if receipts[i].Logs[j].Index != logIndex {
  414. t.Errorf("receipts[%d].Logs[%d].Index = %d, want %d", i, j, receipts[i].Logs[j].Index, logIndex)
  415. }
  416. logIndex++
  417. }
  418. }
  419. }
  420. func clearComputedFieldsOnReceipts(t *testing.T, receipts types.Receipts) {
  421. t.Helper()
  422. for _, receipt := range receipts {
  423. clearComputedFieldsOnReceipt(t, receipt)
  424. }
  425. }
  426. func clearComputedFieldsOnReceipt(t *testing.T, receipt *types.Receipt) {
  427. t.Helper()
  428. receipt.TxHash = common.Hash{}
  429. receipt.BlockHash = common.Hash{}
  430. receipt.BlockNumber = big.NewInt(math.MaxUint32)
  431. receipt.TransactionIndex = math.MaxUint32
  432. receipt.ContractAddress = common.Address{}
  433. receipt.GasUsed = 0
  434. clearComputedFieldsOnLogs(t, receipt.Logs)
  435. }
  436. func clearComputedFieldsOnLogs(t *testing.T, logs []*types.Log) {
  437. t.Helper()
  438. for _, log := range logs {
  439. clearComputedFieldsOnLog(t, log)
  440. }
  441. }
  442. func clearComputedFieldsOnLog(t *testing.T, log *types.Log) {
  443. t.Helper()
  444. log.BlockNumber = math.MaxUint32
  445. log.BlockHash = common.Hash{}
  446. log.TxHash = common.Hash{}
  447. log.TxIndex = math.MaxUint32
  448. log.Index = math.MaxUint32
  449. }