github.com/MetalBlockchain/subnet-evm@v0.6.3/trie/iterator_test.go (about)

     1  // (c) 2020-2021, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2014 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package trie
    28  
    29  import (
    30  	"bytes"
    31  	"encoding/binary"
    32  	"fmt"
    33  	"math/rand"
    34  	"testing"
    35  
    36  	"github.com/MetalBlockchain/subnet-evm/core/rawdb"
    37  	"github.com/MetalBlockchain/subnet-evm/core/types"
    38  	"github.com/MetalBlockchain/subnet-evm/trie/trienode"
    39  	"github.com/ethereum/go-ethereum/common"
    40  	"github.com/ethereum/go-ethereum/crypto"
    41  	"github.com/ethereum/go-ethereum/ethdb"
    42  	"github.com/ethereum/go-ethereum/ethdb/memorydb"
    43  )
    44  
    45  func TestEmptyIterator(t *testing.T) {
    46  	trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase()))
    47  	iter := trie.MustNodeIterator(nil)
    48  
    49  	seen := make(map[string]struct{})
    50  	for iter.Next(true) {
    51  		seen[string(iter.Path())] = struct{}{}
    52  	}
    53  	if len(seen) != 0 {
    54  		t.Fatal("Unexpected trie node iterated")
    55  	}
    56  }
    57  
    58  func TestIterator(t *testing.T) {
    59  	db := NewDatabase(rawdb.NewMemoryDatabase())
    60  	trie := NewEmpty(db)
    61  	vals := []struct{ k, v string }{
    62  		{"do", "verb"},
    63  		{"ether", "wookiedoo"},
    64  		{"horse", "stallion"},
    65  		{"shaman", "horse"},
    66  		{"doge", "coin"},
    67  		{"dog", "puppy"},
    68  		{"somethingveryoddindeedthis is", "myothernodedata"},
    69  	}
    70  	all := make(map[string]string)
    71  	for _, val := range vals {
    72  		all[val.k] = val.v
    73  		trie.MustUpdate([]byte(val.k), []byte(val.v))
    74  	}
    75  	root, nodes, _ := trie.Commit(false)
    76  	db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
    77  
    78  	trie, _ = New(TrieID(root), db)
    79  	found := make(map[string]string)
    80  	it := NewIterator(trie.MustNodeIterator(nil))
    81  	for it.Next() {
    82  		found[string(it.Key)] = string(it.Value)
    83  	}
    84  
    85  	for k, v := range all {
    86  		if found[k] != v {
    87  			t.Errorf("iterator value mismatch for %s: got %q want %q", k, found[k], v)
    88  		}
    89  	}
    90  }
    91  
    92  type kv struct {
    93  	k, v []byte
    94  	t    bool
    95  }
    96  
    97  func (k *kv) cmp(other *kv) int {
    98  	return bytes.Compare(k.k, other.k)
    99  }
   100  
   101  func TestIteratorLargeData(t *testing.T) {
   102  	trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase()))
   103  	vals := make(map[string]*kv)
   104  
   105  	for i := byte(0); i < 255; i++ {
   106  		value := &kv{common.LeftPadBytes([]byte{i}, 32), []byte{i}, false}
   107  		value2 := &kv{common.LeftPadBytes([]byte{10, i}, 32), []byte{i}, false}
   108  		trie.MustUpdate(value.k, value.v)
   109  		trie.MustUpdate(value2.k, value2.v)
   110  		vals[string(value.k)] = value
   111  		vals[string(value2.k)] = value2
   112  	}
   113  
   114  	it := NewIterator(trie.MustNodeIterator(nil))
   115  	for it.Next() {
   116  		vals[string(it.Key)].t = true
   117  	}
   118  
   119  	var untouched []*kv
   120  	for _, value := range vals {
   121  		if !value.t {
   122  			untouched = append(untouched, value)
   123  		}
   124  	}
   125  
   126  	if len(untouched) > 0 {
   127  		t.Errorf("Missed %d nodes", len(untouched))
   128  		for _, value := range untouched {
   129  			t.Error(value)
   130  		}
   131  	}
   132  }
   133  
   134  type iterationElement struct {
   135  	hash common.Hash
   136  	path []byte
   137  	blob []byte
   138  }
   139  
   140  // Tests that the node iterator indeed walks over the entire database contents.
   141  func TestNodeIteratorCoverage(t *testing.T) {
   142  	testNodeIteratorCoverage(t, rawdb.HashScheme)
   143  	testNodeIteratorCoverage(t, rawdb.PathScheme)
   144  }
   145  
   146  func testNodeIteratorCoverage(t *testing.T, scheme string) {
   147  	// Create some arbitrary test trie to iterate
   148  	db, nodeDb, trie, _ := makeTestTrie(scheme)
   149  
   150  	// Gather all the node hashes found by the iterator
   151  	var elements = make(map[common.Hash]iterationElement)
   152  	for it := trie.MustNodeIterator(nil); it.Next(true); {
   153  		if it.Hash() != (common.Hash{}) {
   154  			elements[it.Hash()] = iterationElement{
   155  				hash: it.Hash(),
   156  				path: common.CopyBytes(it.Path()),
   157  				blob: common.CopyBytes(it.NodeBlob()),
   158  			}
   159  		}
   160  	}
   161  	// Cross check the hashes and the database itself
   162  	reader, err := nodeDb.Reader(trie.Hash())
   163  	if err != nil {
   164  		t.Fatalf("state is not available %x", trie.Hash())
   165  	}
   166  	for _, element := range elements {
   167  		if blob, err := reader.Node(common.Hash{}, element.path, element.hash); err != nil {
   168  			t.Errorf("failed to retrieve reported node %x: %v", element.hash, err)
   169  		} else if !bytes.Equal(blob, element.blob) {
   170  			t.Errorf("node blob is different, want %v got %v", element.blob, blob)
   171  		}
   172  	}
   173  	var (
   174  		count int
   175  		it    = db.NewIterator(nil, nil)
   176  	)
   177  	for it.Next() {
   178  		res, _, _ := isTrieNode(nodeDb.Scheme(), it.Key(), it.Value())
   179  		if !res {
   180  			continue
   181  		}
   182  		count += 1
   183  		if elem, ok := elements[crypto.Keccak256Hash(it.Value())]; !ok {
   184  			t.Error("state entry not reported")
   185  		} else if !bytes.Equal(it.Value(), elem.blob) {
   186  			t.Errorf("node blob is different, want %v got %v", elem.blob, it.Value())
   187  		}
   188  	}
   189  	it.Release()
   190  	if count != len(elements) {
   191  		t.Errorf("state entry is mismatched %d %d", count, len(elements))
   192  	}
   193  }
   194  
   195  type kvs struct{ k, v string }
   196  
   197  var testdata1 = []kvs{
   198  	{"barb", "ba"},
   199  	{"bard", "bc"},
   200  	{"bars", "bb"},
   201  	{"bar", "b"},
   202  	{"fab", "z"},
   203  	{"food", "ab"},
   204  	{"foos", "aa"},
   205  	{"foo", "a"},
   206  }
   207  
   208  var testdata2 = []kvs{
   209  	{"aardvark", "c"},
   210  	{"bar", "b"},
   211  	{"barb", "bd"},
   212  	{"bars", "be"},
   213  	{"fab", "z"},
   214  	{"foo", "a"},
   215  	{"foos", "aa"},
   216  	{"food", "ab"},
   217  	{"jars", "d"},
   218  }
   219  
   220  func TestIteratorSeek(t *testing.T) {
   221  	trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase()))
   222  	for _, val := range testdata1 {
   223  		trie.MustUpdate([]byte(val.k), []byte(val.v))
   224  	}
   225  
   226  	// Seek to the middle.
   227  	it := NewIterator(trie.MustNodeIterator([]byte("fab")))
   228  	if err := checkIteratorOrder(testdata1[4:], it); err != nil {
   229  		t.Fatal(err)
   230  	}
   231  
   232  	// Seek to a non-existent key.
   233  	it = NewIterator(trie.MustNodeIterator([]byte("barc")))
   234  	if err := checkIteratorOrder(testdata1[1:], it); err != nil {
   235  		t.Fatal(err)
   236  	}
   237  
   238  	// Seek beyond the end.
   239  	it = NewIterator(trie.MustNodeIterator([]byte("z")))
   240  	if err := checkIteratorOrder(nil, it); err != nil {
   241  		t.Fatal(err)
   242  	}
   243  }
   244  
   245  func checkIteratorOrder(want []kvs, it *Iterator) error {
   246  	for it.Next() {
   247  		if len(want) == 0 {
   248  			return fmt.Errorf("didn't expect any more values, got key %q", it.Key)
   249  		}
   250  		if !bytes.Equal(it.Key, []byte(want[0].k)) {
   251  			return fmt.Errorf("wrong key: got %q, want %q", it.Key, want[0].k)
   252  		}
   253  		want = want[1:]
   254  	}
   255  	if len(want) > 0 {
   256  		return fmt.Errorf("iterator ended early, want key %q", want[0])
   257  	}
   258  	return nil
   259  }
   260  
   261  func TestDifferenceIterator(t *testing.T) {
   262  	dba := NewDatabase(rawdb.NewMemoryDatabase())
   263  	triea := NewEmpty(dba)
   264  	for _, val := range testdata1 {
   265  		triea.MustUpdate([]byte(val.k), []byte(val.v))
   266  	}
   267  	rootA, nodesA, _ := triea.Commit(false)
   268  	dba.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil)
   269  	triea, _ = New(TrieID(rootA), dba)
   270  
   271  	dbb := NewDatabase(rawdb.NewMemoryDatabase())
   272  	trieb := NewEmpty(dbb)
   273  	for _, val := range testdata2 {
   274  		trieb.MustUpdate([]byte(val.k), []byte(val.v))
   275  	}
   276  	rootB, nodesB, _ := trieb.Commit(false)
   277  	dbb.Update(rootB, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesB), nil)
   278  	trieb, _ = New(TrieID(rootB), dbb)
   279  
   280  	found := make(map[string]string)
   281  	di, _ := NewDifferenceIterator(triea.MustNodeIterator(nil), trieb.MustNodeIterator(nil))
   282  	it := NewIterator(di)
   283  	for it.Next() {
   284  		found[string(it.Key)] = string(it.Value)
   285  	}
   286  
   287  	all := []struct{ k, v string }{
   288  		{"aardvark", "c"},
   289  		{"barb", "bd"},
   290  		{"bars", "be"},
   291  		{"jars", "d"},
   292  	}
   293  	for _, item := range all {
   294  		if found[item.k] != item.v {
   295  			t.Errorf("iterator value mismatch for %s: got %v want %v", item.k, found[item.k], item.v)
   296  		}
   297  	}
   298  	if len(found) != len(all) {
   299  		t.Errorf("iterator count mismatch: got %d values, want %d", len(found), len(all))
   300  	}
   301  }
   302  
   303  func TestUnionIterator(t *testing.T) {
   304  	dba := NewDatabase(rawdb.NewMemoryDatabase())
   305  	triea := NewEmpty(dba)
   306  	for _, val := range testdata1 {
   307  		triea.MustUpdate([]byte(val.k), []byte(val.v))
   308  	}
   309  	rootA, nodesA, _ := triea.Commit(false)
   310  	dba.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil)
   311  	triea, _ = New(TrieID(rootA), dba)
   312  
   313  	dbb := NewDatabase(rawdb.NewMemoryDatabase())
   314  	trieb := NewEmpty(dbb)
   315  	for _, val := range testdata2 {
   316  		trieb.MustUpdate([]byte(val.k), []byte(val.v))
   317  	}
   318  	rootB, nodesB, _ := trieb.Commit(false)
   319  	dbb.Update(rootB, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesB), nil)
   320  	trieb, _ = New(TrieID(rootB), dbb)
   321  
   322  	di, _ := NewUnionIterator([]NodeIterator{triea.MustNodeIterator(nil), trieb.MustNodeIterator(nil)})
   323  	it := NewIterator(di)
   324  
   325  	all := []struct{ k, v string }{
   326  		{"aardvark", "c"},
   327  		{"barb", "ba"},
   328  		{"barb", "bd"},
   329  		{"bard", "bc"},
   330  		{"bars", "bb"},
   331  		{"bars", "be"},
   332  		{"bar", "b"},
   333  		{"fab", "z"},
   334  		{"food", "ab"},
   335  		{"foos", "aa"},
   336  		{"foo", "a"},
   337  		{"jars", "d"},
   338  	}
   339  
   340  	for i, kv := range all {
   341  		if !it.Next() {
   342  			t.Errorf("Iterator ends prematurely at element %d", i)
   343  		}
   344  		if kv.k != string(it.Key) {
   345  			t.Errorf("iterator value mismatch for element %d: got key %s want %s", i, it.Key, kv.k)
   346  		}
   347  		if kv.v != string(it.Value) {
   348  			t.Errorf("iterator value mismatch for element %d: got value %s want %s", i, it.Value, kv.v)
   349  		}
   350  	}
   351  	if it.Next() {
   352  		t.Errorf("Iterator returned extra values.")
   353  	}
   354  }
   355  
   356  func TestIteratorNoDups(t *testing.T) {
   357  	tr := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase()))
   358  	for _, val := range testdata1 {
   359  		tr.MustUpdate([]byte(val.k), []byte(val.v))
   360  	}
   361  	checkIteratorNoDups(t, tr.MustNodeIterator(nil), nil)
   362  }
   363  
   364  // This test checks that nodeIterator.Next can be retried after inserting missing trie nodes.
   365  func TestIteratorContinueAfterError(t *testing.T) {
   366  	testIteratorContinueAfterError(t, false, rawdb.HashScheme)
   367  	testIteratorContinueAfterError(t, true, rawdb.HashScheme)
   368  	testIteratorContinueAfterError(t, false, rawdb.PathScheme)
   369  	testIteratorContinueAfterError(t, true, rawdb.PathScheme)
   370  }
   371  
   372  func testIteratorContinueAfterError(t *testing.T, memonly bool, scheme string) {
   373  	diskdb := rawdb.NewMemoryDatabase()
   374  	tdb := newTestDatabase(diskdb, scheme)
   375  
   376  	tr := NewEmpty(tdb)
   377  	for _, val := range testdata1 {
   378  		tr.MustUpdate([]byte(val.k), []byte(val.v))
   379  	}
   380  	root, nodes, _ := tr.Commit(false)
   381  	tdb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
   382  	if !memonly {
   383  		tdb.Commit(root, false)
   384  	}
   385  	tr, _ = New(TrieID(root), tdb)
   386  	wantNodeCount := checkIteratorNoDups(t, tr.MustNodeIterator(nil), nil)
   387  
   388  	var (
   389  		paths  [][]byte
   390  		hashes []common.Hash
   391  	)
   392  	if memonly {
   393  		for path, n := range nodes.Nodes {
   394  			paths = append(paths, []byte(path))
   395  			hashes = append(hashes, n.Hash)
   396  		}
   397  	} else {
   398  		it := diskdb.NewIterator(nil, nil)
   399  		for it.Next() {
   400  			ok, path, hash := isTrieNode(tdb.Scheme(), it.Key(), it.Value())
   401  			if !ok {
   402  				continue
   403  			}
   404  			paths = append(paths, path)
   405  			hashes = append(hashes, hash)
   406  		}
   407  		it.Release()
   408  	}
   409  	for i := 0; i < 20; i++ {
   410  		// Create trie that will load all nodes from DB.
   411  		tr, _ := New(TrieID(tr.Hash()), tdb)
   412  
   413  		// Remove a random node from the database. It can't be the root node
   414  		// because that one is already loaded.
   415  		var (
   416  			rval  []byte
   417  			rpath []byte
   418  			rhash common.Hash
   419  		)
   420  		for {
   421  			if memonly {
   422  				rpath = paths[rand.Intn(len(paths))]
   423  				n := nodes.Nodes[string(rpath)]
   424  				if n == nil {
   425  					continue
   426  				}
   427  				rhash = n.Hash
   428  			} else {
   429  				index := rand.Intn(len(paths))
   430  				rpath = paths[index]
   431  				rhash = hashes[index]
   432  			}
   433  			if rhash != tr.Hash() {
   434  				break
   435  			}
   436  		}
   437  		if memonly {
   438  			tr.reader.banned = map[string]struct{}{string(rpath): {}}
   439  		} else {
   440  			rval = rawdb.ReadTrieNode(diskdb, common.Hash{}, rpath, rhash, tdb.Scheme())
   441  			rawdb.DeleteTrieNode(diskdb, common.Hash{}, rpath, rhash, tdb.Scheme())
   442  		}
   443  		// Iterate until the error is hit.
   444  		seen := make(map[string]bool)
   445  		it := tr.MustNodeIterator(nil)
   446  		checkIteratorNoDups(t, it, seen)
   447  		missing, ok := it.Error().(*MissingNodeError)
   448  		if !ok || missing.NodeHash != rhash {
   449  			t.Fatal("didn't hit missing node, got", it.Error())
   450  		}
   451  
   452  		// Add the node back and continue iteration.
   453  		if memonly {
   454  			delete(tr.reader.banned, string(rpath))
   455  		} else {
   456  			rawdb.WriteTrieNode(diskdb, common.Hash{}, rpath, rhash, rval, tdb.Scheme())
   457  		}
   458  		checkIteratorNoDups(t, it, seen)
   459  		if it.Error() != nil {
   460  			t.Fatal("unexpected error", it.Error())
   461  		}
   462  		if len(seen) != wantNodeCount {
   463  			t.Fatal("wrong node iteration count, got", len(seen), "want", wantNodeCount)
   464  		}
   465  	}
   466  }
   467  
   468  // Similar to the test above, this one checks that failure to create nodeIterator at a
   469  // certain key prefix behaves correctly when Next is called. The expectation is that Next
   470  // should retry seeking before returning true for the first time.
   471  func TestIteratorContinueAfterSeekError(t *testing.T) {
   472  	testIteratorContinueAfterSeekError(t, false, rawdb.HashScheme)
   473  	testIteratorContinueAfterSeekError(t, true, rawdb.HashScheme)
   474  	testIteratorContinueAfterSeekError(t, false, rawdb.PathScheme)
   475  	testIteratorContinueAfterSeekError(t, true, rawdb.PathScheme)
   476  }
   477  
   478  func testIteratorContinueAfterSeekError(t *testing.T, memonly bool, scheme string) {
   479  	// Commit test trie to db, then remove the node containing "bars".
   480  	var (
   481  		barNodePath []byte
   482  		barNodeHash = common.HexToHash("05041990364eb72fcb1127652ce40d8bab765f2bfe53225b1170d276cc101c2e")
   483  	)
   484  	diskdb := rawdb.NewMemoryDatabase()
   485  	triedb := newTestDatabase(diskdb, scheme)
   486  	ctr := NewEmpty(triedb)
   487  	for _, val := range testdata1 {
   488  		ctr.MustUpdate([]byte(val.k), []byte(val.v))
   489  	}
   490  	root, nodes, _ := ctr.Commit(false)
   491  	for path, n := range nodes.Nodes {
   492  		if n.Hash == barNodeHash {
   493  			barNodePath = []byte(path)
   494  			break
   495  		}
   496  	}
   497  	triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
   498  	if !memonly {
   499  		triedb.Commit(root, false)
   500  	}
   501  	var (
   502  		barNodeBlob []byte
   503  	)
   504  	tr, _ := New(TrieID(root), triedb)
   505  	if memonly {
   506  		tr.reader.banned = map[string]struct{}{string(barNodePath): {}}
   507  	} else {
   508  		barNodeBlob = rawdb.ReadTrieNode(diskdb, common.Hash{}, barNodePath, barNodeHash, triedb.Scheme())
   509  		rawdb.DeleteTrieNode(diskdb, common.Hash{}, barNodePath, barNodeHash, triedb.Scheme())
   510  	}
   511  	// Create a new iterator that seeks to "bars". Seeking can't proceed because
   512  	// the node is missing.
   513  	it := tr.MustNodeIterator([]byte("bars"))
   514  	missing, ok := it.Error().(*MissingNodeError)
   515  	if !ok {
   516  		t.Fatal("want MissingNodeError, got", it.Error())
   517  	} else if missing.NodeHash != barNodeHash {
   518  		t.Fatal("wrong node missing")
   519  	}
   520  	// Reinsert the missing node.
   521  	if memonly {
   522  		delete(tr.reader.banned, string(barNodePath))
   523  	} else {
   524  		rawdb.WriteTrieNode(diskdb, common.Hash{}, barNodePath, barNodeHash, barNodeBlob, triedb.Scheme())
   525  	}
   526  	// Check that iteration produces the right set of values.
   527  	if err := checkIteratorOrder(testdata1[2:], NewIterator(it)); err != nil {
   528  		t.Fatal(err)
   529  	}
   530  }
   531  
   532  func checkIteratorNoDups(t *testing.T, it NodeIterator, seen map[string]bool) int {
   533  	if seen == nil {
   534  		seen = make(map[string]bool)
   535  	}
   536  	for it.Next(true) {
   537  		if seen[string(it.Path())] {
   538  			t.Fatalf("iterator visited node path %x twice", it.Path())
   539  		}
   540  		seen[string(it.Path())] = true
   541  	}
   542  	return len(seen)
   543  }
   544  
   545  func TestIteratorNodeBlob(t *testing.T) {
   546  	testIteratorNodeBlob(t, rawdb.HashScheme)
   547  	testIteratorNodeBlob(t, rawdb.PathScheme)
   548  }
   549  
   550  type loggingDb struct {
   551  	getCount uint64
   552  	backend  ethdb.KeyValueStore
   553  }
   554  
   555  func (l *loggingDb) Has(key []byte) (bool, error) {
   556  	return l.backend.Has(key)
   557  }
   558  
   559  func (l *loggingDb) Get(key []byte) ([]byte, error) {
   560  	l.getCount++
   561  	return l.backend.Get(key)
   562  }
   563  
   564  func (l *loggingDb) Put(key []byte, value []byte) error {
   565  	return l.backend.Put(key, value)
   566  }
   567  
   568  func (l *loggingDb) Delete(key []byte) error {
   569  	return l.backend.Delete(key)
   570  }
   571  
   572  func (l *loggingDb) NewBatch() ethdb.Batch {
   573  	return l.backend.NewBatch()
   574  }
   575  
   576  func (l *loggingDb) NewBatchWithSize(size int) ethdb.Batch {
   577  	return l.backend.NewBatchWithSize(size)
   578  }
   579  
   580  func (l *loggingDb) NewIterator(prefix []byte, start []byte) ethdb.Iterator {
   581  	return l.backend.NewIterator(prefix, start)
   582  }
   583  
   584  func (l *loggingDb) NewSnapshot() (ethdb.Snapshot, error) {
   585  	return l.backend.NewSnapshot()
   586  }
   587  
   588  func (l *loggingDb) Stat(property string) (string, error) {
   589  	return l.backend.Stat(property)
   590  }
   591  
   592  func (l *loggingDb) Compact(start []byte, limit []byte) error {
   593  	return l.backend.Compact(start, limit)
   594  }
   595  
   596  func (l *loggingDb) Close() error {
   597  	return l.backend.Close()
   598  }
   599  
   600  // makeLargeTestTrie create a sample test trie
   601  func makeLargeTestTrie() (*Database, *StateTrie, *loggingDb) {
   602  	// Create an empty trie
   603  	logDb := &loggingDb{0, memorydb.New()}
   604  	triedb := NewDatabase(rawdb.NewDatabase(logDb))
   605  	trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), triedb)
   606  
   607  	// Fill it with some arbitrary data
   608  	for i := 0; i < 10000; i++ {
   609  		key := make([]byte, 32)
   610  		val := make([]byte, 32)
   611  		binary.BigEndian.PutUint64(key, uint64(i))
   612  		binary.BigEndian.PutUint64(val, uint64(i))
   613  		key = crypto.Keccak256(key)
   614  		val = crypto.Keccak256(val)
   615  		trie.MustUpdate(key, val)
   616  	}
   617  	root, nodes, _ := trie.Commit(false)
   618  	triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
   619  	triedb.Commit(root, false)
   620  
   621  	// Return the generated trie
   622  	trie, _ = NewStateTrie(TrieID(root), triedb)
   623  	return triedb, trie, logDb
   624  }
   625  
   626  // Tests that the node iterator indeed walks over the entire database contents.
   627  func TestNodeIteratorLargeTrie(t *testing.T) {
   628  	// Create some arbitrary test trie to iterate
   629  	db, trie, logDb := makeLargeTestTrie()
   630  	db.Cap(0) // flush everything
   631  	// Do a seek operation
   632  	trie.NodeIterator(common.FromHex("0x77667766776677766778855885885885"))
   633  	// master: 24 get operations
   634  	// this pr: 6 get operations
   635  	if have, want := logDb.getCount, uint64(6); have != want {
   636  		t.Fatalf("Too many lookups during seek, have %d want %d", have, want)
   637  	}
   638  }
   639  
   640  func testIteratorNodeBlob(t *testing.T, scheme string) {
   641  	var (
   642  		db     = rawdb.NewMemoryDatabase()
   643  		triedb = newTestDatabase(db, scheme)
   644  		trie   = NewEmpty(triedb)
   645  	)
   646  	vals := []struct{ k, v string }{
   647  		{"do", "verb"},
   648  		{"ether", "wookiedoo"},
   649  		{"horse", "stallion"},
   650  		{"shaman", "horse"},
   651  		{"doge", "coin"},
   652  		{"dog", "puppy"},
   653  		{"somethingveryoddindeedthis is", "myothernodedata"},
   654  	}
   655  	all := make(map[string]string)
   656  	for _, val := range vals {
   657  		all[val.k] = val.v
   658  		trie.MustUpdate([]byte(val.k), []byte(val.v))
   659  	}
   660  	root, nodes, _ := trie.Commit(false)
   661  	triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
   662  	triedb.Commit(root, false)
   663  
   664  	var found = make(map[common.Hash][]byte)
   665  	trie, _ = New(TrieID(root), triedb)
   666  	it := trie.MustNodeIterator(nil)
   667  	for it.Next(true) {
   668  		if it.Hash() == (common.Hash{}) {
   669  			continue
   670  		}
   671  		found[it.Hash()] = it.NodeBlob()
   672  	}
   673  
   674  	dbIter := db.NewIterator(nil, nil)
   675  	defer dbIter.Release()
   676  
   677  	var count int
   678  	for dbIter.Next() {
   679  		ok, _, _ := isTrieNode(triedb.Scheme(), dbIter.Key(), dbIter.Value())
   680  		if !ok {
   681  			continue
   682  		}
   683  		got, present := found[crypto.Keccak256Hash(dbIter.Value())]
   684  		if !present {
   685  			t.Fatal("Miss trie node")
   686  		}
   687  		if !bytes.Equal(got, dbIter.Value()) {
   688  			t.Fatalf("Unexpected trie node want %v got %v", dbIter.Value(), got)
   689  		}
   690  		count += 1
   691  	}
   692  	if count != len(found) {
   693  		t.Fatal("Find extra trie node via iterator")
   694  	}
   695  }
   696  
   697  // isTrieNode is a helper function which reports if the provided
   698  // database entry belongs to a trie node or not. Note in tests
   699  // only single layer trie is used, namely storage trie is not
   700  // considered at all.
   701  func isTrieNode(scheme string, key, val []byte) (bool, []byte, common.Hash) {
   702  	var (
   703  		path []byte
   704  		hash common.Hash
   705  	)
   706  	if scheme == rawdb.HashScheme {
   707  		ok := rawdb.IsLegacyTrieNode(key, val)
   708  		if !ok {
   709  			return false, nil, common.Hash{}
   710  		}
   711  		hash = common.BytesToHash(key)
   712  	} else {
   713  		ok, remain := rawdb.IsAccountTrieNode(key)
   714  		if !ok {
   715  			return false, nil, common.Hash{}
   716  		}
   717  		path = common.CopyBytes(remain)
   718  		hash = crypto.Keccak256Hash(val)
   719  	}
   720  	return true, path, hash
   721  }