github.com/jimmyx0x/go-ethereum@v1.10.28/core/rawdb/accessors_indexes_test.go (about) 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 17 package rawdb 18 19 import ( 20 "bytes" 21 "hash" 22 "math/big" 23 "testing" 24 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/core/types" 27 "github.com/ethereum/go-ethereum/ethdb" 28 "github.com/ethereum/go-ethereum/params" 29 "github.com/ethereum/go-ethereum/rlp" 30 "golang.org/x/crypto/sha3" 31 ) 32 33 // testHasher is the helper tool for transaction/receipt list hashing. 34 // The original hasher is trie, in order to get rid of import cycle, 35 // use the testing hasher instead. 36 type testHasher struct { 37 hasher hash.Hash 38 } 39 40 func newHasher() *testHasher { 41 return &testHasher{hasher: sha3.NewLegacyKeccak256()} 42 } 43 44 func (h *testHasher) Reset() { 45 h.hasher.Reset() 46 } 47 48 func (h *testHasher) Update(key, val []byte) { 49 h.hasher.Write(key) 50 h.hasher.Write(val) 51 } 52 53 func (h *testHasher) Hash() common.Hash { 54 return common.BytesToHash(h.hasher.Sum(nil)) 55 } 56 57 // Tests that positional lookup metadata can be stored and retrieved. 58 func TestLookupStorage(t *testing.T) { 59 tests := []struct { 60 name string 61 writeTxLookupEntriesByBlock func(ethdb.Writer, *types.Block) 62 }{ 63 { 64 "DatabaseV6", 65 func(db ethdb.Writer, block *types.Block) { 66 WriteTxLookupEntriesByBlock(db, block) 67 }, 68 }, 69 { 70 "DatabaseV4-V5", 71 func(db ethdb.Writer, block *types.Block) { 72 for _, tx := range block.Transactions() { 73 db.Put(txLookupKey(tx.Hash()), block.Hash().Bytes()) 74 } 75 }, 76 }, 77 { 78 "DatabaseV3", 79 func(db ethdb.Writer, block *types.Block) { 80 for index, tx := range block.Transactions() { 81 entry := LegacyTxLookupEntry{ 82 BlockHash: block.Hash(), 83 BlockIndex: block.NumberU64(), 84 Index: uint64(index), 85 } 86 data, _ := rlp.EncodeToBytes(entry) 87 db.Put(txLookupKey(tx.Hash()), data) 88 } 89 }, 90 }, 91 } 92 93 for _, tc := range tests { 94 t.Run(tc.name, func(t *testing.T) { 95 db := NewMemoryDatabase() 96 97 tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11}) 98 tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), 2222, big.NewInt(22222), []byte{0x22, 0x22, 0x22}) 99 tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33}) 100 txs := []*types.Transaction{tx1, tx2, tx3} 101 102 block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil, newHasher()) 103 104 // Check that no transactions entries are in a pristine database 105 for i, tx := range txs { 106 if txn, _, _, _ := ReadTransaction(db, tx.Hash()); txn != nil { 107 t.Fatalf("tx #%d [%x]: non existent transaction returned: %v", i, tx.Hash(), txn) 108 } 109 } 110 // Insert all the transactions into the database, and verify contents 111 WriteCanonicalHash(db, block.Hash(), block.NumberU64()) 112 WriteBlock(db, block) 113 tc.writeTxLookupEntriesByBlock(db, block) 114 115 for i, tx := range txs { 116 if txn, hash, number, index := ReadTransaction(db, tx.Hash()); txn == nil { 117 t.Fatalf("tx #%d [%x]: transaction not found", i, tx.Hash()) 118 } else { 119 if hash != block.Hash() || number != block.NumberU64() || index != uint64(i) { 120 t.Fatalf("tx #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v", i, tx.Hash(), hash, number, index, block.Hash(), block.NumberU64(), i) 121 } 122 if tx.Hash() != txn.Hash() { 123 t.Fatalf("tx #%d [%x]: transaction mismatch: have %v, want %v", i, tx.Hash(), txn, tx) 124 } 125 } 126 } 127 // Delete the transactions and check purge 128 for i, tx := range txs { 129 DeleteTxLookupEntry(db, tx.Hash()) 130 if txn, _, _, _ := ReadTransaction(db, tx.Hash()); txn != nil { 131 t.Fatalf("tx #%d [%x]: deleted transaction returned: %v", i, tx.Hash(), txn) 132 } 133 } 134 }) 135 } 136 } 137 138 func TestDeleteBloomBits(t *testing.T) { 139 // Prepare testing data 140 db := NewMemoryDatabase() 141 for i := uint(0); i < 2; i++ { 142 for s := uint64(0); s < 2; s++ { 143 WriteBloomBits(db, i, s, params.MainnetGenesisHash, []byte{0x01, 0x02}) 144 WriteBloomBits(db, i, s, params.RinkebyGenesisHash, []byte{0x01, 0x02}) 145 } 146 } 147 check := func(bit uint, section uint64, head common.Hash, exist bool) { 148 bits, _ := ReadBloomBits(db, bit, section, head) 149 if exist && !bytes.Equal(bits, []byte{0x01, 0x02}) { 150 t.Fatalf("Bloombits mismatch") 151 } 152 if !exist && len(bits) > 0 { 153 t.Fatalf("Bloombits should be removed") 154 } 155 } 156 // Check the existence of written data. 157 check(0, 0, params.MainnetGenesisHash, true) 158 check(0, 0, params.RinkebyGenesisHash, true) 159 160 // Check the existence of deleted data. 161 DeleteBloombits(db, 0, 0, 1) 162 check(0, 0, params.MainnetGenesisHash, false) 163 check(0, 0, params.RinkebyGenesisHash, false) 164 check(0, 1, params.MainnetGenesisHash, true) 165 check(0, 1, params.RinkebyGenesisHash, true) 166 167 // Check the existence of deleted data. 168 DeleteBloombits(db, 0, 0, 2) 169 check(0, 0, params.MainnetGenesisHash, false) 170 check(0, 0, params.RinkebyGenesisHash, false) 171 check(0, 1, params.MainnetGenesisHash, false) 172 check(0, 1, params.RinkebyGenesisHash, false) 173 174 // Bit1 shouldn't be affect. 175 check(1, 0, params.MainnetGenesisHash, true) 176 check(1, 0, params.RinkebyGenesisHash, true) 177 check(1, 1, params.MainnetGenesisHash, true) 178 check(1, 1, params.RinkebyGenesisHash, true) 179 }