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