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