github.com/calmw/ethereum@v0.1.1/trie/iterator_test.go (about)

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