github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/core/database_util_test.go (about)

     1  // Copyright 2015 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 core
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"math/big"
    25  	"os"
    26  	"strconv"
    27  	"testing"
    28  
    29  	"crypto/ecdsa"
    30  	"encoding/binary"
    31  	"github.com/ethereumproject/go-ethereum/common"
    32  	"github.com/ethereumproject/go-ethereum/core/types"
    33  	"github.com/ethereumproject/go-ethereum/core/vm"
    34  	"github.com/ethereumproject/go-ethereum/crypto"
    35  	"github.com/ethereumproject/go-ethereum/crypto/sha3"
    36  	"github.com/ethereumproject/go-ethereum/ethdb"
    37  	"github.com/ethereumproject/go-ethereum/rlp"
    38  	"strings"
    39  )
    40  
    41  type diffTest struct {
    42  	ParentTimestamp    uint64
    43  	ParentDifficulty   *big.Int
    44  	CurrentTimestamp   uint64
    45  	CurrentBlocknumber *big.Int
    46  	CurrentDifficulty  *big.Int
    47  }
    48  
    49  func (d *diffTest) UnmarshalJSON(b []byte) (err error) {
    50  	var ext struct {
    51  		ParentTimestamp    string
    52  		ParentDifficulty   string
    53  		CurrentTimestamp   string
    54  		CurrentBlocknumber string
    55  		CurrentDifficulty  string
    56  	}
    57  	if err := json.Unmarshal(b, &ext); err != nil {
    58  		return err
    59  	}
    60  
    61  	d.ParentTimestamp, err = strconv.ParseUint(ext.ParentTimestamp, 0, 64)
    62  	if err != nil {
    63  		return fmt.Errorf("malformed parent timestamp: %s", err)
    64  	}
    65  
    66  	d.ParentDifficulty = new(big.Int)
    67  	if _, ok := d.ParentDifficulty.SetString(ext.ParentDifficulty, 0); !ok {
    68  		return fmt.Errorf("malformed parent difficulty %q", ext.ParentDifficulty)
    69  	}
    70  
    71  	d.CurrentTimestamp, err = strconv.ParseUint(ext.CurrentTimestamp, 0, 64)
    72  	if err != nil {
    73  		return fmt.Errorf("malformed current timestamp: %s", err)
    74  	}
    75  
    76  	d.CurrentBlocknumber = new(big.Int)
    77  	if _, ok := d.CurrentBlocknumber.SetString(ext.CurrentBlocknumber, 0); !ok {
    78  		return fmt.Errorf("malformed current blocknumber %q", ext.CurrentBlocknumber)
    79  	}
    80  
    81  	d.CurrentDifficulty = new(big.Int)
    82  	if _, ok := d.CurrentDifficulty.SetString(ext.CurrentDifficulty, 0); !ok {
    83  		return fmt.Errorf("malformed current difficulty %q", ext.CurrentDifficulty)
    84  	}
    85  
    86  	return nil
    87  }
    88  
    89  func TestDifficultyFrontier(t *testing.T) {
    90  	file, err := os.Open("../tests/files/BasicTests/difficulty.json")
    91  	if err != nil {
    92  		t.Fatal(err)
    93  	}
    94  	defer file.Close()
    95  
    96  	tests := make(map[string]diffTest)
    97  	err = json.NewDecoder(file).Decode(&tests)
    98  	if err != nil {
    99  		t.Fatal(err)
   100  	}
   101  
   102  	for name, test := range tests {
   103  		number := new(big.Int).Sub(test.CurrentBlocknumber, big.NewInt(1))
   104  		diff := calcDifficultyFrontier(test.CurrentTimestamp, test.ParentTimestamp, number, test.ParentDifficulty)
   105  		if diff.Cmp(test.CurrentDifficulty) != 0 {
   106  			t.Error(name, "failed. Expected", test.CurrentDifficulty, "and calculated", diff)
   107  		}
   108  	}
   109  }
   110  
   111  // Tests block header storage and retrieval operations.
   112  func TestHeaderStorage(t *testing.T) {
   113  	db, _ := ethdb.NewMemDatabase()
   114  
   115  	// Create a test header to move around the database and make sure it's really new
   116  	header := &types.Header{Extra: []byte("test header")}
   117  	if entry := GetHeader(db, header.Hash()); entry != nil {
   118  		t.Fatalf("Non existent header returned: %v", entry)
   119  	}
   120  	// Write and verify the header in the database
   121  	if err := WriteHeader(db, header); err != nil {
   122  		t.Fatalf("Failed to write header into database: %v", err)
   123  	}
   124  	if entry := GetHeader(db, header.Hash()); entry == nil {
   125  		t.Fatalf("Stored header not found")
   126  	} else if entry.Hash() != header.Hash() {
   127  		t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, header)
   128  	}
   129  	if entry := GetHeaderRLP(db, header.Hash()); entry == nil {
   130  		t.Fatalf("Stored header RLP not found")
   131  	} else {
   132  		hasher := sha3.NewKeccak256()
   133  		hasher.Write(entry)
   134  
   135  		if hash := common.BytesToHash(hasher.Sum(nil)); hash != header.Hash() {
   136  			t.Fatalf("Retrieved RLP header mismatch: have %v, want %v", entry, header)
   137  		}
   138  	}
   139  	// Delete the header and verify the execution
   140  	DeleteHeader(db, header.Hash())
   141  	if entry := GetHeader(db, header.Hash()); entry != nil {
   142  		t.Fatalf("Deleted header returned: %v", entry)
   143  	}
   144  }
   145  
   146  // Tests block body storage and retrieval operations.
   147  func TestBodyStorage(t *testing.T) {
   148  	db, _ := ethdb.NewMemDatabase()
   149  
   150  	// Create a test body to move around the database and make sure it's really new
   151  	body := &types.Body{Uncles: []*types.Header{{Extra: []byte("test header")}}}
   152  
   153  	hasher := sha3.NewKeccak256()
   154  	rlp.Encode(hasher, body)
   155  	hash := common.BytesToHash(hasher.Sum(nil))
   156  
   157  	if entry := GetBody(db, hash); entry != nil {
   158  		t.Fatalf("Non existent body returned: %v", entry)
   159  	}
   160  	// Write and verify the body in the database
   161  	if err := WriteBody(db, hash, body); err != nil {
   162  		t.Fatalf("Failed to write body into database: %v", err)
   163  	}
   164  	if entry := GetBody(db, hash); entry == nil {
   165  		t.Fatalf("Stored body not found")
   166  	} else if types.DeriveSha(types.Transactions(entry.Transactions)) != types.DeriveSha(types.Transactions(body.Transactions)) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(body.Uncles) {
   167  		t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, body)
   168  	}
   169  	if entry := GetBodyRLP(db, hash); entry == nil {
   170  		t.Fatalf("Stored body RLP not found")
   171  	} else {
   172  		hasher := sha3.NewKeccak256()
   173  		hasher.Write(entry)
   174  
   175  		if calc := common.BytesToHash(hasher.Sum(nil)); calc != hash {
   176  			t.Fatalf("Retrieved RLP body mismatch: have %v, want %v", entry, body)
   177  		}
   178  	}
   179  	// Delete the body and verify the execution
   180  	DeleteBody(db, hash)
   181  	if entry := GetBody(db, hash); entry != nil {
   182  		t.Fatalf("Deleted body returned: %v", entry)
   183  	}
   184  }
   185  
   186  // Tests block storage and retrieval operations.
   187  func TestBlockStorage(t *testing.T) {
   188  	db, _ := ethdb.NewMemDatabase()
   189  
   190  	// Create a test block to move around the database and make sure it's really new
   191  	block := types.NewBlockWithHeader(&types.Header{
   192  		Extra:       []byte("test block"),
   193  		UncleHash:   types.EmptyUncleHash,
   194  		TxHash:      types.EmptyRootHash,
   195  		ReceiptHash: types.EmptyRootHash,
   196  	})
   197  	if entry := GetBlock(db, block.Hash()); entry != nil {
   198  		t.Fatalf("Non existent block returned: %v", entry)
   199  	}
   200  	if entry := GetHeader(db, block.Hash()); entry != nil {
   201  		t.Fatalf("Non existent header returned: %v", entry)
   202  	}
   203  	if entry := GetBody(db, block.Hash()); entry != nil {
   204  		t.Fatalf("Non existent body returned: %v", entry)
   205  	}
   206  	// Write and verify the block in the database
   207  	if err := WriteBlock(db, block); err != nil {
   208  		t.Fatalf("Failed to write block into database: %v", err)
   209  	}
   210  	if entry := GetBlock(db, block.Hash()); entry == nil {
   211  		t.Fatalf("Stored block not found")
   212  	} else if entry.Hash() != block.Hash() {
   213  		t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block)
   214  	}
   215  	if entry := GetHeader(db, block.Hash()); entry == nil {
   216  		t.Fatalf("Stored header not found")
   217  	} else if entry.Hash() != block.Header().Hash() {
   218  		t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, block.Header())
   219  	}
   220  	if entry := GetBody(db, block.Hash()); entry == nil {
   221  		t.Fatalf("Stored body not found")
   222  	} else if types.DeriveSha(types.Transactions(entry.Transactions)) != types.DeriveSha(block.Transactions()) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(block.Uncles()) {
   223  		t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, block.Body())
   224  	}
   225  	// Delete the block and verify the execution
   226  	DeleteBlock(db, block.Hash())
   227  	if entry := GetBlock(db, block.Hash()); entry != nil {
   228  		t.Fatalf("Deleted block returned: %v", entry)
   229  	}
   230  	if entry := GetHeader(db, block.Hash()); entry != nil {
   231  		t.Fatalf("Deleted header returned: %v", entry)
   232  	}
   233  	if entry := GetBody(db, block.Hash()); entry != nil {
   234  		t.Fatalf("Deleted body returned: %v", entry)
   235  	}
   236  }
   237  
   238  // Tests that partial block contents don't get reassembled into full blocks.
   239  func TestPartialBlockStorage(t *testing.T) {
   240  	db, _ := ethdb.NewMemDatabase()
   241  	block := types.NewBlockWithHeader(&types.Header{
   242  		Extra:       []byte("test block"),
   243  		UncleHash:   types.EmptyUncleHash,
   244  		TxHash:      types.EmptyRootHash,
   245  		ReceiptHash: types.EmptyRootHash,
   246  	})
   247  	// Store a header and check that it's not recognized as a block
   248  	if err := WriteHeader(db, block.Header()); err != nil {
   249  		t.Fatalf("Failed to write header into database: %v", err)
   250  	}
   251  	if entry := GetBlock(db, block.Hash()); entry != nil {
   252  		t.Fatalf("Non existent block returned: %v", entry)
   253  	}
   254  	DeleteHeader(db, block.Hash())
   255  
   256  	// Store a body and check that it's not recognized as a block
   257  	if err := WriteBody(db, block.Hash(), block.Body()); err != nil {
   258  		t.Fatalf("Failed to write body into database: %v", err)
   259  	}
   260  	if entry := GetBlock(db, block.Hash()); entry != nil {
   261  		t.Fatalf("Non existent block returned: %v", entry)
   262  	}
   263  	DeleteBody(db, block.Hash())
   264  
   265  	// Store a header and a body separately and check reassembly
   266  	if err := WriteHeader(db, block.Header()); err != nil {
   267  		t.Fatalf("Failed to write header into database: %v", err)
   268  	}
   269  	if err := WriteBody(db, block.Hash(), block.Body()); err != nil {
   270  		t.Fatalf("Failed to write body into database: %v", err)
   271  	}
   272  	if entry := GetBlock(db, block.Hash()); entry == nil {
   273  		t.Fatalf("Stored block not found")
   274  	} else if entry.Hash() != block.Hash() {
   275  		t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block)
   276  	}
   277  }
   278  
   279  // Tests block total difficulty storage and retrieval operations.
   280  func TestTdStorage(t *testing.T) {
   281  	db, _ := ethdb.NewMemDatabase()
   282  
   283  	// Create a test TD to move around the database and make sure it's really new
   284  	hash, td := common.Hash{}, big.NewInt(314)
   285  	if entry := GetTd(db, hash); entry != nil {
   286  		t.Fatalf("Non existent TD returned: %v", entry)
   287  	}
   288  	// Write and verify the TD in the database
   289  	if err := WriteTd(db, hash, td); err != nil {
   290  		t.Fatalf("Failed to write TD into database: %v", err)
   291  	}
   292  	if entry := GetTd(db, hash); entry == nil {
   293  		t.Fatalf("Stored TD not found")
   294  	} else if entry.Cmp(td) != 0 {
   295  		t.Fatalf("Retrieved TD mismatch: have %v, want %v", entry, td)
   296  	}
   297  	// Delete the TD and verify the execution
   298  	DeleteTd(db, hash)
   299  	if entry := GetTd(db, hash); entry != nil {
   300  		t.Fatalf("Deleted TD returned: %v", entry)
   301  	}
   302  }
   303  
   304  func TestAddrTxStorage(t *testing.T) {
   305  	dbFilepath, err := ioutil.TempDir("", "geth-db-util-test")
   306  	if err != nil {
   307  		t.Fatal(err)
   308  	}
   309  	defer os.RemoveAll(dbFilepath)
   310  	db, _ := ethdb.NewLDBDatabase(dbFilepath, 10, 100)
   311  
   312  	testKey := func(hex string) (*ecdsa.PrivateKey, common.Address) {
   313  		key := crypto.ToECDSA(common.Hex2Bytes(hex))
   314  		addr := crypto.PubkeyToAddress(key.PublicKey)
   315  		return key, addr
   316  	}
   317  
   318  	skey1, from1 := testKey("123915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8")
   319  	skey2, from2 := testKey("456915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8")
   320  
   321  	from2to := common.BytesToAddress([]byte{0x22})
   322  
   323  	// from1 -> 1
   324  	tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), big.NewInt(1111), big.NewInt(11111), []byte{0x11, 0x11, 0x11})
   325  
   326  	// from2 -> 2,3,txC
   327  	tx2 := types.NewTransaction(2, from2to, big.NewInt(222), big.NewInt(2222), big.NewInt(22222), []byte{0x22, 0x22, 0x22})
   328  	tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), big.NewInt(3333), big.NewInt(33333), []byte{0x33, 0x33, 0x33})
   329  	txC := types.NewTransaction(4, common.Address{}, big.NewInt(333), big.NewInt(3333), big.NewInt(33333), []byte{0x33, 0x33, 0x33})
   330  
   331  	txs := []*types.Transaction{tx1, tx2, tx3, txC}
   332  	txsSigned := []*types.Transaction{}
   333  
   334  	for _, x := range txs {
   335  		// Sign em so we get from
   336  		key := skey1
   337  		if x.Nonce() != 1 {
   338  			key = skey2
   339  		}
   340  		x.SetSigner(types.NewChainIdSigner(big.NewInt(1)))
   341  		xs, err := x.SignECDSA(key)
   342  		if err != nil {
   343  			t.Fatal(err)
   344  		}
   345  		txsSigned = append(txsSigned, xs)
   346  	}
   347  
   348  	block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txsSigned, nil, nil)
   349  
   350  	// Put in the transactions just for fun.
   351  	//
   352  	// Check that no transactions entries are in a pristine database
   353  	for i, tx := range txsSigned {
   354  		if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn != nil {
   355  			t.Fatalf("tx #%d [%x]: non existent transaction returned: %v", i, tx.Hash(), txn)
   356  		}
   357  	}
   358  	// Insert all the transactions into the database, and verify contents
   359  	if err := WriteTransactions(db, block); err != nil {
   360  		t.Fatalf("failed to write transactions: %v", err)
   361  	}
   362  	for i, tx := range txsSigned {
   363  		if txn, hash, number, index := GetTransaction(db, tx.Hash()); txn == nil {
   364  			t.Fatalf("tx #%d [%x]: transaction not found", i, tx.Hash())
   365  		} else {
   366  			if hash != block.Hash() || number != block.NumberU64() || index != uint64(i) {
   367  				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)
   368  			}
   369  			if tx.String() != txn.String() {
   370  				t.Fatalf("tx #%d [%x]: transaction mismatch: have %v, want %v", i, tx.Hash(), txn, tx)
   371  			}
   372  		}
   373  	}
   374  
   375  	// Write the atx indexes
   376  	if err := WriteBlockAddTxIndexes(db, block); err != nil {
   377  		t.Fatal(err)
   378  	}
   379  
   380  	prefix := ethdb.NewBytesPrefix(txAddressIndexPrefix)
   381  	it := db.NewIteratorRange(prefix)
   382  	count := 0
   383  	for it.Next() {
   384  		count++
   385  		//// Debugger -- it's kinda nice to see what the indexes look like
   386  		//ad, bn, tf, sc, txh := resolveAddrTxBytes(it.Key())
   387  		//addr, blockn, direc, ko, txhash := common.BytesToAddress(ad), binary.LittleEndian.Uint64(bn), string(tf), string(sc), common.BytesToHash(txh)
   388  		//t.Log(addr.Hex(), blockn, direc, ko, txhash.Hex())
   389  	}
   390  	it.Release()
   391  	if e := it.Error(); e != nil {
   392  		t.Fatal(e)
   393  	}
   394  	if count != 8 {
   395  		t.Errorf("want: %v, got: %v", 7, count)
   396  	}
   397  
   398  	out, _ := GetAddrTxs(db, from2, 0, 0, "", "", -1, -1, false)
   399  	if len(out) != 3 {
   400  		t.Errorf("want: %v, got: %v", 3, len(out))
   401  	}
   402  
   403  	// Test pagination and reverse
   404  	outReverse, _ := GetAddrTxs(db, from2, 0, 0, "", "", -1, -1, true)
   405  	if len(outReverse) != 3 {
   406  		t.Errorf("want: %v, got: %v", 3, len(outReverse))
   407  	}
   408  	// reverse
   409  	if out[0] != outReverse[2] || out[1] != outReverse[1] || out[2] != outReverse[0] {
   410  		t.Errorf("got: %v, want: %v", outReverse, out)
   411  	}
   412  	// pagination
   413  	outPag, _ := GetAddrTxs(db, from2, 0, 0, "", "", 1, -1, false)
   414  	if len(outPag) != 2 {
   415  		t.Errorf("got: %v, want: %v", len(outPag), 2)
   416  	}
   417  
   418  	out, _ = GetAddrTxs(db, from2, 0, 0, "", "c", -1, -1, false)
   419  	if len(out) != 1 {
   420  		t.Errorf("got: %v, want: %v", len(out), 1)
   421  	}
   422  	out, _ = GetAddrTxs(db, common.Address{}, 0, 0, "", "", -1, -1, false)
   423  	if len(out) != 1 {
   424  		t.Errorf("got: %v, want: %v", len(out), 1)
   425  	}
   426  
   427  	out, _ = GetAddrTxs(db, from1, 314, 314, "", "", -1, -1, false)
   428  	if len(out) != 1 {
   429  		t.Errorf("want: %v, got: %v", 1, len(out))
   430  	} else {
   431  		h := out[0]
   432  		if !strings.HasPrefix(h, "0x") {
   433  			t.Errorf("want: 0x-prefix, got: %v", h)
   434  		}
   435  		if !common.IsHex(h) {
   436  			t.Errorf("want: hex, got: %v", h)
   437  		}
   438  		txh := common.HexToHash(h)
   439  
   440  		if txh != txsSigned[0].Hash() {
   441  			t.Errorf("got: %x, want: %x", txh, txsSigned[0].Hash())
   442  		}
   443  
   444  		gx, _, _, _ := GetTransaction(db, txh)
   445  		if gx == nil {
   446  			t.Errorf("missing tx: %x", txh)
   447  		}
   448  	}
   449  
   450  	out, _ = GetAddrTxs(db, from2to, 314, 314, "to", "", -1, -1, false)
   451  	if len(out) != 1 {
   452  		t.Errorf("want: %v, got: %v", 1, len(out))
   453  	} else {
   454  		h := out[0]
   455  		if !strings.HasPrefix(h, "0x") {
   456  			t.Errorf("want: 0x-prefix, got: %v", h)
   457  		}
   458  		if !common.IsHex(h) {
   459  			t.Errorf("want: hex, got: %v", h)
   460  		}
   461  		txh := common.HexToHash(h)
   462  		if txh != txsSigned[1].Hash() {
   463  			t.Errorf("got: %x, want: %x", txh, txsSigned[0].Hash())
   464  		}
   465  		gx, _, _, _ := GetTransaction(db, txh)
   466  		if gx == nil {
   467  			t.Errorf("missing tx: %x", txh)
   468  		}
   469  		f, e := gx.From()
   470  		if e != nil {
   471  			t.Error(e)
   472  		}
   473  		if f != from2 {
   474  			t.Errorf("got: %v, want: %v", f, from2)
   475  		}
   476  	}
   477  	out, _ = GetAddrTxs(db, from2to, 314, 314, "from", "", -1, -1, false)
   478  	if len(out) != 0 {
   479  		t.Errorf("want: %v, got: %v", 0, len(out))
   480  	}
   481  }
   482  
   483  func TestFormatAndResolveAddrTxBytesKey(t *testing.T) {
   484  	testAddr := common.Address{}
   485  	testBN := uint64(42)
   486  	testTorf := "f"
   487  	testKindOf := "s"
   488  	testTxH := common.Hash{}
   489  
   490  	testBNBytes := make([]byte, 8)
   491  	binary.LittleEndian.PutUint64(testBNBytes, testBN)
   492  
   493  	key := formatAddrTxBytesIndex(testAddr.Bytes(), testBNBytes, []byte(testTorf), []byte(testKindOf), testTxH.Bytes())
   494  
   495  	// Test key/prefix iterator-ability.
   496  	itPrefix := formatAddrTxIterator(testAddr)
   497  	if !bytes.HasPrefix(key, itPrefix) {
   498  		t.Fatalf("key/prefix mismatch: prefix=%s key=%s", itPrefix, key)
   499  	}
   500  
   501  	// Reverse engineer key and ensure expected.
   502  	outAddr, outBNBytes, outTorf, outKindOf, outTxH := resolveAddrTxBytes(key)
   503  
   504  	if gotAddr := common.BytesToAddress(outAddr); gotAddr != testAddr {
   505  		t.Errorf("got: %v, want: %v", gotAddr.Hex(), testAddr.Hex())
   506  	}
   507  	if gotBN := binary.LittleEndian.Uint64(outBNBytes); gotBN != testBN {
   508  		t.Errorf("got: %v, want: %v", gotBN, testBN)
   509  	}
   510  	if gotTorf := string(outTorf); gotTorf != testTorf {
   511  		t.Errorf("got: %v, want: %v", gotTorf, testTorf)
   512  	}
   513  	if gotKindOf := string(outKindOf); gotKindOf != testKindOf {
   514  		t.Errorf("got: %v, want: %v", gotKindOf, testKindOf)
   515  	}
   516  	if gotTxH := common.BytesToHash(outTxH); gotTxH != testTxH {
   517  		t.Errorf("got: %v, want: %v", gotTxH, testTxH)
   518  	}
   519  
   520  	// Ensure proper key part sizing.
   521  	sizes := []struct {
   522  		b           []byte
   523  		expectedLen int
   524  	}{
   525  		{outAddr, common.AddressLength},
   526  		{outBNBytes, 8},
   527  		{outTorf, 1},
   528  		{outKindOf, 1},
   529  		{outTxH, common.HashLength},
   530  	}
   531  	for _, s := range sizes {
   532  		if l := len(s.b); l != s.expectedLen {
   533  			t.Errorf("want: %v, got: %v", s.expectedLen, l)
   534  		}
   535  	}
   536  }
   537  
   538  // Tests that canonical numbers can be mapped to hashes and retrieved.
   539  func TestCanonicalMappingStorage(t *testing.T) {
   540  	db, _ := ethdb.NewMemDatabase()
   541  
   542  	// Create a test canonical number and assinged hash to move around
   543  	hash, number := common.Hash{0: 0xff}, uint64(314)
   544  	if entry := GetCanonicalHash(db, number); entry != (common.Hash{}) {
   545  		t.Fatalf("Non existent canonical mapping returned: %v", entry)
   546  	}
   547  	// Write and verify the TD in the database
   548  	if err := WriteCanonicalHash(db, hash, number); err != nil {
   549  		t.Fatalf("Failed to write canonical mapping into database: %v", err)
   550  	}
   551  	if entry := GetCanonicalHash(db, number); entry == (common.Hash{}) {
   552  		t.Fatalf("Stored canonical mapping not found")
   553  	} else if entry != hash {
   554  		t.Fatalf("Retrieved canonical mapping mismatch: have %v, want %v", entry, hash)
   555  	}
   556  	// Delete the TD and verify the execution
   557  	DeleteCanonicalHash(db, number)
   558  	if entry := GetCanonicalHash(db, number); entry != (common.Hash{}) {
   559  		t.Fatalf("Deleted canonical mapping returned: %v", entry)
   560  	}
   561  }
   562  
   563  // Tests that head headers and head blocks can be assigned, individually.
   564  func TestHeadStorage(t *testing.T) {
   565  	db, _ := ethdb.NewMemDatabase()
   566  
   567  	blockHead := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block header")})
   568  	blockFull := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block full")})
   569  	blockFast := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block fast")})
   570  
   571  	// Check that no head entries are in a pristine database
   572  	if entry := GetHeadHeaderHash(db); entry != (common.Hash{}) {
   573  		t.Fatalf("Non head header entry returned: %v", entry)
   574  	}
   575  	if entry := GetHeadBlockHash(db); entry != (common.Hash{}) {
   576  		t.Fatalf("Non head block entry returned: %v", entry)
   577  	}
   578  	if entry := GetHeadFastBlockHash(db); entry != (common.Hash{}) {
   579  		t.Fatalf("Non fast head block entry returned: %v", entry)
   580  	}
   581  	// Assign separate entries for the head header and block
   582  	if err := WriteHeadHeaderHash(db, blockHead.Hash()); err != nil {
   583  		t.Fatalf("Failed to write head header hash: %v", err)
   584  	}
   585  	if err := WriteHeadBlockHash(db, blockFull.Hash()); err != nil {
   586  		t.Fatalf("Failed to write head block hash: %v", err)
   587  	}
   588  	if err := WriteHeadFastBlockHash(db, blockFast.Hash()); err != nil {
   589  		t.Fatalf("Failed to write fast head block hash: %v", err)
   590  	}
   591  	// Check that both heads are present, and different (i.e. two heads maintained)
   592  	if entry := GetHeadHeaderHash(db); entry != blockHead.Hash() {
   593  		t.Fatalf("Head header hash mismatch: have %v, want %v", entry, blockHead.Hash())
   594  	}
   595  	if entry := GetHeadBlockHash(db); entry != blockFull.Hash() {
   596  		t.Fatalf("Head block hash mismatch: have %v, want %v", entry, blockFull.Hash())
   597  	}
   598  	if entry := GetHeadFastBlockHash(db); entry != blockFast.Hash() {
   599  		t.Fatalf("Fast head block hash mismatch: have %v, want %v", entry, blockFast.Hash())
   600  	}
   601  }
   602  
   603  // Tests that transactions and associated metadata can be stored and retrieved.
   604  func TestTransactionStorage(t *testing.T) {
   605  	db, _ := ethdb.NewMemDatabase()
   606  
   607  	tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), big.NewInt(1111), big.NewInt(11111), []byte{0x11, 0x11, 0x11})
   608  	tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), big.NewInt(2222), big.NewInt(22222), []byte{0x22, 0x22, 0x22})
   609  	tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), big.NewInt(3333), big.NewInt(33333), []byte{0x33, 0x33, 0x33})
   610  	txs := []*types.Transaction{tx1, tx2, tx3}
   611  
   612  	block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil)
   613  
   614  	// Check that no transactions entries are in a pristine database
   615  	for i, tx := range txs {
   616  		if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn != nil {
   617  			t.Fatalf("tx #%d [%x]: non existent transaction returned: %v", i, tx.Hash(), txn)
   618  		}
   619  	}
   620  	// Insert all the transactions into the database, and verify contents
   621  	if err := WriteTransactions(db, block); err != nil {
   622  		t.Fatalf("failed to write transactions: %v", err)
   623  	}
   624  	for i, tx := range txs {
   625  		if txn, hash, number, index := GetTransaction(db, tx.Hash()); txn == nil {
   626  			t.Fatalf("tx #%d [%x]: transaction not found", i, tx.Hash())
   627  		} else {
   628  			if hash != block.Hash() || number != block.NumberU64() || index != uint64(i) {
   629  				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)
   630  			}
   631  			if tx.String() != txn.String() {
   632  				t.Fatalf("tx #%d [%x]: transaction mismatch: have %v, want %v", i, tx.Hash(), txn, tx)
   633  			}
   634  		}
   635  	}
   636  	// Delete the transactions and check purge
   637  	for i, tx := range txs {
   638  		DeleteTransaction(db, tx.Hash())
   639  		if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn != nil {
   640  			t.Fatalf("tx #%d [%x]: deleted transaction returned: %v", i, tx.Hash(), txn)
   641  		}
   642  	}
   643  }
   644  
   645  // Tests that receipts can be stored and retrieved.
   646  func TestReceiptStorage(t *testing.T) {
   647  	db, _ := ethdb.NewMemDatabase()
   648  
   649  	receipt1 := &types.Receipt{
   650  		PostState:         []byte{0x01},
   651  		CumulativeGasUsed: big.NewInt(1),
   652  		Logs: vm.Logs{
   653  			&vm.Log{Address: common.BytesToAddress([]byte{0x11})},
   654  			&vm.Log{Address: common.BytesToAddress([]byte{0x01, 0x11})},
   655  		},
   656  		TxHash:          common.BytesToHash([]byte{0x11, 0x11}),
   657  		ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
   658  		GasUsed:         big.NewInt(111111),
   659  	}
   660  	receipt2 := &types.Receipt{
   661  		PostState:         []byte{0x02},
   662  		CumulativeGasUsed: big.NewInt(2),
   663  		Logs: vm.Logs{
   664  			&vm.Log{Address: common.BytesToAddress([]byte{0x22})},
   665  			&vm.Log{Address: common.BytesToAddress([]byte{0x02, 0x22})},
   666  		},
   667  		TxHash:          common.BytesToHash([]byte{0x22, 0x22}),
   668  		ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
   669  		GasUsed:         big.NewInt(222222),
   670  	}
   671  	receipts := []*types.Receipt{receipt1, receipt2}
   672  
   673  	// Check that no receipt entries are in a pristine database
   674  	for i, receipt := range receipts {
   675  		if r := GetReceipt(db, receipt.TxHash); r != nil {
   676  			t.Fatalf("receipt #%d [%x]: non existent receipt returned: %v", i, receipt.TxHash, r)
   677  		}
   678  	}
   679  	// Insert all the receipts into the database, and verify contents
   680  	if err := WriteReceipts(db, receipts); err != nil {
   681  		t.Fatalf("failed to write receipts: %v", err)
   682  	}
   683  	for i, receipt := range receipts {
   684  		if r := GetReceipt(db, receipt.TxHash); r == nil {
   685  			t.Fatalf("receipt #%d [%x]: receipt not found", i, receipt.TxHash)
   686  		} else {
   687  			rlpHave, _ := rlp.EncodeToBytes(r)
   688  			rlpWant, _ := rlp.EncodeToBytes(receipt)
   689  
   690  			if bytes.Compare(rlpHave, rlpWant) != 0 {
   691  				t.Fatalf("receipt #%d [%x]: receipt mismatch: have %v, want %v", i, receipt.TxHash, r, receipt)
   692  			}
   693  		}
   694  	}
   695  	// Delete the receipts and check purge
   696  	for i, receipt := range receipts {
   697  		DeleteReceipt(db, receipt.TxHash)
   698  		if r := GetReceipt(db, receipt.TxHash); r != nil {
   699  			t.Fatalf("receipt #%d [%x]: deleted receipt returned: %v", i, receipt.TxHash, r)
   700  		}
   701  	}
   702  }
   703  
   704  // Tests that receipts associated with a single block can be stored and retrieved.
   705  func TestBlockReceiptStorage(t *testing.T) {
   706  	db, _ := ethdb.NewMemDatabase()
   707  
   708  	receipt1 := &types.Receipt{
   709  		PostState:         []byte{0x01},
   710  		CumulativeGasUsed: big.NewInt(1),
   711  		Logs: vm.Logs{
   712  			&vm.Log{Address: common.BytesToAddress([]byte{0x11})},
   713  			&vm.Log{Address: common.BytesToAddress([]byte{0x01, 0x11})},
   714  		},
   715  		TxHash:          common.BytesToHash([]byte{0x11, 0x11}),
   716  		ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
   717  		GasUsed:         big.NewInt(111111),
   718  	}
   719  	receipt2 := &types.Receipt{
   720  		PostState:         []byte{0x02},
   721  		CumulativeGasUsed: big.NewInt(2),
   722  		Logs: vm.Logs{
   723  			&vm.Log{Address: common.BytesToAddress([]byte{0x22})},
   724  			&vm.Log{Address: common.BytesToAddress([]byte{0x02, 0x22})},
   725  		},
   726  		TxHash:          common.BytesToHash([]byte{0x22, 0x22}),
   727  		ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
   728  		GasUsed:         big.NewInt(222222),
   729  	}
   730  	receipts := []*types.Receipt{receipt1, receipt2}
   731  
   732  	// Check that no receipt entries are in a pristine database
   733  	hash := common.BytesToHash([]byte{0x03, 0x14})
   734  	if rs := GetBlockReceipts(db, hash); len(rs) != 0 {
   735  		t.Fatalf("non existent receipts returned: %v", rs)
   736  	}
   737  	// Insert the receipt slice into the database and check presence
   738  	if err := WriteBlockReceipts(db, hash, receipts); err != nil {
   739  		t.Fatalf("failed to write block receipts: %v", err)
   740  	}
   741  	if rs := GetBlockReceipts(db, hash); len(rs) == 0 {
   742  		t.Fatalf("no receipts returned")
   743  	} else {
   744  		for i := 0; i < len(receipts); i++ {
   745  			rlpHave, _ := rlp.EncodeToBytes(rs[i])
   746  			rlpWant, _ := rlp.EncodeToBytes(receipts[i])
   747  
   748  			if bytes.Compare(rlpHave, rlpWant) != 0 {
   749  				t.Fatalf("receipt #%d: receipt mismatch: have %v, want %v", i, rs[i], receipts[i])
   750  			}
   751  		}
   752  	}
   753  	// Delete the receipt slice and check purge
   754  	DeleteBlockReceipts(db, hash)
   755  	if rs := GetBlockReceipts(db, hash); len(rs) != 0 {
   756  		t.Fatalf("deleted receipts returned: %v", rs)
   757  	}
   758  }
   759  
   760  func TestMipmapBloom(t *testing.T) {
   761  	db, _ := ethdb.NewMemDatabase()
   762  
   763  	receipt1 := new(types.Receipt)
   764  	receipt1.Logs = vm.Logs{
   765  		&vm.Log{Address: common.BytesToAddress([]byte("test"))},
   766  		&vm.Log{Address: common.BytesToAddress([]byte("address"))},
   767  	}
   768  	receipt2 := new(types.Receipt)
   769  	receipt2.Logs = vm.Logs{
   770  		&vm.Log{Address: common.BytesToAddress([]byte("test"))},
   771  		&vm.Log{Address: common.BytesToAddress([]byte("address1"))},
   772  	}
   773  
   774  	WriteMipmapBloom(db, 1, types.Receipts{receipt1})
   775  	WriteMipmapBloom(db, 2, types.Receipts{receipt2})
   776  
   777  	for _, level := range MIPMapLevels {
   778  		bloom := GetMipmapBloom(db, 2, level)
   779  		if !types.BloomLookup(bloom, []byte("address1")) {
   780  			t.Error("expected test to be included on level:", level)
   781  		}
   782  	}
   783  
   784  	// reset
   785  	db, _ = ethdb.NewMemDatabase()
   786  	receipt := new(types.Receipt)
   787  	receipt.Logs = vm.Logs{
   788  		&vm.Log{Address: common.BytesToAddress([]byte("test"))},
   789  	}
   790  	WriteMipmapBloom(db, 999, types.Receipts{receipt1})
   791  
   792  	receipt = new(types.Receipt)
   793  	receipt.Logs = vm.Logs{
   794  		&vm.Log{Address: common.BytesToAddress([]byte("test 1"))},
   795  	}
   796  	WriteMipmapBloom(db, 1000, types.Receipts{receipt})
   797  
   798  	bloom := GetMipmapBloom(db, 1000, 1000)
   799  	if types.BloomLookup(bloom, []byte("test")) {
   800  		t.Error("test should not have been included")
   801  	}
   802  }
   803  
   804  func TestMipmapChain(t *testing.T) {
   805  	dir, err := ioutil.TempDir("", "mipmap")
   806  	if err != nil {
   807  		t.Fatal(err)
   808  	}
   809  	defer os.RemoveAll(dir)
   810  
   811  	var (
   812  		db, _   = ethdb.NewLDBDatabase(dir, 0, 0)
   813  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   814  		addr    = crypto.PubkeyToAddress(key1.PublicKey)
   815  		addr2   = common.BytesToAddress([]byte("jeff"))
   816  
   817  		hash1 = common.BytesToHash([]byte("topic1"))
   818  	)
   819  	defer db.Close()
   820  
   821  	genesis := WriteGenesisBlockForTesting(db, GenesisAccount{addr, big.NewInt(1000000)})
   822  	chain, receipts := GenerateChain(testChainConfig(), genesis, db, 1010, func(i int, gen *BlockGen) {
   823  		var receipts types.Receipts
   824  		switch i {
   825  		case 1:
   826  			receipt := types.NewReceipt(nil, new(big.Int))
   827  			receipt.Logs = vm.Logs{
   828  				&vm.Log{
   829  					Address: addr,
   830  					Topics:  []common.Hash{hash1},
   831  				},
   832  			}
   833  			gen.AddUncheckedReceipt(receipt)
   834  			receipts = types.Receipts{receipt}
   835  		case 1000:
   836  			receipt := types.NewReceipt(nil, new(big.Int))
   837  			receipt.Logs = vm.Logs{&vm.Log{Address: addr2}}
   838  			gen.AddUncheckedReceipt(receipt)
   839  			receipts = types.Receipts{receipt}
   840  
   841  		}
   842  
   843  		// store the receipts
   844  		err := WriteReceipts(db, receipts)
   845  		if err != nil {
   846  			t.Fatal(err)
   847  		}
   848  		WriteMipmapBloom(db, uint64(i+1), receipts)
   849  	})
   850  	for i, block := range chain {
   851  		WriteBlock(db, block)
   852  		if err := WriteCanonicalHash(db, block.Hash(), block.NumberU64()); err != nil {
   853  			t.Fatalf("failed to insert block number: %v", err)
   854  		}
   855  		if err := WriteHeadBlockHash(db, block.Hash()); err != nil {
   856  			t.Fatalf("failed to insert block number: %v", err)
   857  		}
   858  		if err := WriteBlockReceipts(db, block.Hash(), receipts[i]); err != nil {
   859  			t.Fatal("error writing block receipts:", err)
   860  		}
   861  	}
   862  
   863  	bloom := GetMipmapBloom(db, 0, 1000)
   864  	if types.BloomLookup(bloom, addr2[:]) {
   865  		t.Error("address was included in bloom and should not have")
   866  	}
   867  }