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 }