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 }