gitee.com/liu-zhao234568/cntest@v1.0.0/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 "gitee.com/liu-zhao234568/cntest/common" 27 "gitee.com/liu-zhao234568/cntest/crypto" 28 "gitee.com/liu-zhao234568/cntest/ethdb" 29 "gitee.com/liu-zhao234568/cntest/ethdb/memorydb" 30 ) 31 32 func TestIterator(t *testing.T) { 33 trie := newEmpty() 34 vals := []struct{ k, v string }{ 35 {"do", "verb"}, 36 {"ether", "wookiedoo"}, 37 {"horse", "stallion"}, 38 {"shaman", "horse"}, 39 {"doge", "coin"}, 40 {"dog", "puppy"}, 41 {"somethingveryoddindeedthis is", "myothernodedata"}, 42 } 43 all := make(map[string]string) 44 for _, val := range vals { 45 all[val.k] = val.v 46 trie.Update([]byte(val.k), []byte(val.v)) 47 } 48 trie.Commit(nil) 49 50 found := make(map[string]string) 51 it := NewIterator(trie.NodeIterator(nil)) 52 for it.Next() { 53 found[string(it.Key)] = string(it.Value) 54 } 55 56 for k, v := range all { 57 if found[k] != v { 58 t.Errorf("iterator value mismatch for %s: got %q want %q", k, found[k], v) 59 } 60 } 61 } 62 63 type kv struct { 64 k, v []byte 65 t bool 66 } 67 68 func TestIteratorLargeData(t *testing.T) { 69 trie := newEmpty() 70 vals := make(map[string]*kv) 71 72 for i := byte(0); i < 255; i++ { 73 value := &kv{common.LeftPadBytes([]byte{i}, 32), []byte{i}, false} 74 value2 := &kv{common.LeftPadBytes([]byte{10, i}, 32), []byte{i}, false} 75 trie.Update(value.k, value.v) 76 trie.Update(value2.k, value2.v) 77 vals[string(value.k)] = value 78 vals[string(value2.k)] = value2 79 } 80 81 it := NewIterator(trie.NodeIterator(nil)) 82 for it.Next() { 83 vals[string(it.Key)].t = true 84 } 85 86 var untouched []*kv 87 for _, value := range vals { 88 if !value.t { 89 untouched = append(untouched, value) 90 } 91 } 92 93 if len(untouched) > 0 { 94 t.Errorf("Missed %d nodes", len(untouched)) 95 for _, value := range untouched { 96 t.Error(value) 97 } 98 } 99 } 100 101 // Tests that the node iterator indeed walks over the entire database contents. 102 func TestNodeIteratorCoverage(t *testing.T) { 103 // Create some arbitrary test trie to iterate 104 db, trie, _ := makeTestTrie() 105 106 // Gather all the node hashes found by the iterator 107 hashes := make(map[common.Hash]struct{}) 108 for it := trie.NodeIterator(nil); it.Next(true); { 109 if it.Hash() != (common.Hash{}) { 110 hashes[it.Hash()] = struct{}{} 111 } 112 } 113 // Cross check the hashes and the database itself 114 for hash := range hashes { 115 if _, err := db.Node(hash); err != nil { 116 t.Errorf("failed to retrieve reported node %x: %v", hash, err) 117 } 118 } 119 for hash, obj := range db.dirties { 120 if obj != nil && hash != (common.Hash{}) { 121 if _, ok := hashes[hash]; !ok { 122 t.Errorf("state entry not reported %x", hash) 123 } 124 } 125 } 126 it := db.diskdb.NewIterator(nil, nil) 127 for it.Next() { 128 key := it.Key() 129 if _, ok := hashes[common.BytesToHash(key)]; !ok { 130 t.Errorf("state entry not reported %x", key) 131 } 132 } 133 it.Release() 134 } 135 136 type kvs struct{ k, v string } 137 138 var testdata1 = []kvs{ 139 {"barb", "ba"}, 140 {"bard", "bc"}, 141 {"bars", "bb"}, 142 {"bar", "b"}, 143 {"fab", "z"}, 144 {"food", "ab"}, 145 {"foos", "aa"}, 146 {"foo", "a"}, 147 } 148 149 var testdata2 = []kvs{ 150 {"aardvark", "c"}, 151 {"bar", "b"}, 152 {"barb", "bd"}, 153 {"bars", "be"}, 154 {"fab", "z"}, 155 {"foo", "a"}, 156 {"foos", "aa"}, 157 {"food", "ab"}, 158 {"jars", "d"}, 159 } 160 161 func TestIteratorSeek(t *testing.T) { 162 trie := newEmpty() 163 for _, val := range testdata1 { 164 trie.Update([]byte(val.k), []byte(val.v)) 165 } 166 167 // Seek to the middle. 168 it := NewIterator(trie.NodeIterator([]byte("fab"))) 169 if err := checkIteratorOrder(testdata1[4:], it); err != nil { 170 t.Fatal(err) 171 } 172 173 // Seek to a non-existent key. 174 it = NewIterator(trie.NodeIterator([]byte("barc"))) 175 if err := checkIteratorOrder(testdata1[1:], it); err != nil { 176 t.Fatal(err) 177 } 178 179 // Seek beyond the end. 180 it = NewIterator(trie.NodeIterator([]byte("z"))) 181 if err := checkIteratorOrder(nil, it); err != nil { 182 t.Fatal(err) 183 } 184 } 185 186 func checkIteratorOrder(want []kvs, it *Iterator) error { 187 for it.Next() { 188 if len(want) == 0 { 189 return fmt.Errorf("didn't expect any more values, got key %q", it.Key) 190 } 191 if !bytes.Equal(it.Key, []byte(want[0].k)) { 192 return fmt.Errorf("wrong key: got %q, want %q", it.Key, want[0].k) 193 } 194 want = want[1:] 195 } 196 if len(want) > 0 { 197 return fmt.Errorf("iterator ended early, want key %q", want[0]) 198 } 199 return nil 200 } 201 202 func TestDifferenceIterator(t *testing.T) { 203 triea := newEmpty() 204 for _, val := range testdata1 { 205 triea.Update([]byte(val.k), []byte(val.v)) 206 } 207 triea.Commit(nil) 208 209 trieb := newEmpty() 210 for _, val := range testdata2 { 211 trieb.Update([]byte(val.k), []byte(val.v)) 212 } 213 trieb.Commit(nil) 214 215 found := make(map[string]string) 216 di, _ := NewDifferenceIterator(triea.NodeIterator(nil), trieb.NodeIterator(nil)) 217 it := NewIterator(di) 218 for it.Next() { 219 found[string(it.Key)] = string(it.Value) 220 } 221 222 all := []struct{ k, v string }{ 223 {"aardvark", "c"}, 224 {"barb", "bd"}, 225 {"bars", "be"}, 226 {"jars", "d"}, 227 } 228 for _, item := range all { 229 if found[item.k] != item.v { 230 t.Errorf("iterator value mismatch for %s: got %v want %v", item.k, found[item.k], item.v) 231 } 232 } 233 if len(found) != len(all) { 234 t.Errorf("iterator count mismatch: got %d values, want %d", len(found), len(all)) 235 } 236 } 237 238 func TestUnionIterator(t *testing.T) { 239 triea := newEmpty() 240 for _, val := range testdata1 { 241 triea.Update([]byte(val.k), []byte(val.v)) 242 } 243 triea.Commit(nil) 244 245 trieb := newEmpty() 246 for _, val := range testdata2 { 247 trieb.Update([]byte(val.k), []byte(val.v)) 248 } 249 trieb.Commit(nil) 250 251 di, _ := NewUnionIterator([]NodeIterator{triea.NodeIterator(nil), trieb.NodeIterator(nil)}) 252 it := NewIterator(di) 253 254 all := []struct{ k, v string }{ 255 {"aardvark", "c"}, 256 {"barb", "ba"}, 257 {"barb", "bd"}, 258 {"bard", "bc"}, 259 {"bars", "bb"}, 260 {"bars", "be"}, 261 {"bar", "b"}, 262 {"fab", "z"}, 263 {"food", "ab"}, 264 {"foos", "aa"}, 265 {"foo", "a"}, 266 {"jars", "d"}, 267 } 268 269 for i, kv := range all { 270 if !it.Next() { 271 t.Errorf("Iterator ends prematurely at element %d", i) 272 } 273 if kv.k != string(it.Key) { 274 t.Errorf("iterator value mismatch for element %d: got key %s want %s", i, it.Key, kv.k) 275 } 276 if kv.v != string(it.Value) { 277 t.Errorf("iterator value mismatch for element %d: got value %s want %s", i, it.Value, kv.v) 278 } 279 } 280 if it.Next() { 281 t.Errorf("Iterator returned extra values.") 282 } 283 } 284 285 func TestIteratorNoDups(t *testing.T) { 286 var tr Trie 287 for _, val := range testdata1 { 288 tr.Update([]byte(val.k), []byte(val.v)) 289 } 290 checkIteratorNoDups(t, tr.NodeIterator(nil), nil) 291 } 292 293 // This test checks that nodeIterator.Next can be retried after inserting missing trie nodes. 294 func TestIteratorContinueAfterErrorDisk(t *testing.T) { testIteratorContinueAfterError(t, false) } 295 func TestIteratorContinueAfterErrorMemonly(t *testing.T) { testIteratorContinueAfterError(t, true) } 296 297 func testIteratorContinueAfterError(t *testing.T, memonly bool) { 298 diskdb := memorydb.New() 299 triedb := NewDatabase(diskdb) 300 301 tr, _ := New(common.Hash{}, triedb) 302 for _, val := range testdata1 { 303 tr.Update([]byte(val.k), []byte(val.v)) 304 } 305 tr.Commit(nil) 306 if !memonly { 307 triedb.Commit(tr.Hash(), true, nil) 308 } 309 wantNodeCount := checkIteratorNoDups(t, tr.NodeIterator(nil), nil) 310 311 var ( 312 diskKeys [][]byte 313 memKeys []common.Hash 314 ) 315 if memonly { 316 memKeys = triedb.Nodes() 317 } else { 318 it := diskdb.NewIterator(nil, nil) 319 for it.Next() { 320 diskKeys = append(diskKeys, it.Key()) 321 } 322 it.Release() 323 } 324 for i := 0; i < 20; i++ { 325 // Create trie that will load all nodes from DB. 326 tr, _ := New(tr.Hash(), triedb) 327 328 // Remove a random node from the database. It can't be the root node 329 // because that one is already loaded. 330 var ( 331 rkey common.Hash 332 rval []byte 333 robj *cachedNode 334 ) 335 for { 336 if memonly { 337 rkey = memKeys[rand.Intn(len(memKeys))] 338 } else { 339 copy(rkey[:], diskKeys[rand.Intn(len(diskKeys))]) 340 } 341 if rkey != tr.Hash() { 342 break 343 } 344 } 345 if memonly { 346 robj = triedb.dirties[rkey] 347 delete(triedb.dirties, rkey) 348 } else { 349 rval, _ = diskdb.Get(rkey[:]) 350 diskdb.Delete(rkey[:]) 351 } 352 // Iterate until the error is hit. 353 seen := make(map[string]bool) 354 it := tr.NodeIterator(nil) 355 checkIteratorNoDups(t, it, seen) 356 missing, ok := it.Error().(*MissingNodeError) 357 if !ok || missing.NodeHash != rkey { 358 t.Fatal("didn't hit missing node, got", it.Error()) 359 } 360 361 // Add the node back and continue iteration. 362 if memonly { 363 triedb.dirties[rkey] = robj 364 } else { 365 diskdb.Put(rkey[:], rval) 366 } 367 checkIteratorNoDups(t, it, seen) 368 if it.Error() != nil { 369 t.Fatal("unexpected error", it.Error()) 370 } 371 if len(seen) != wantNodeCount { 372 t.Fatal("wrong node iteration count, got", len(seen), "want", wantNodeCount) 373 } 374 } 375 } 376 377 // Similar to the test above, this one checks that failure to create nodeIterator at a 378 // certain key prefix behaves correctly when Next is called. The expectation is that Next 379 // should retry seeking before returning true for the first time. 380 func TestIteratorContinueAfterSeekErrorDisk(t *testing.T) { 381 testIteratorContinueAfterSeekError(t, false) 382 } 383 func TestIteratorContinueAfterSeekErrorMemonly(t *testing.T) { 384 testIteratorContinueAfterSeekError(t, true) 385 } 386 387 func testIteratorContinueAfterSeekError(t *testing.T, memonly bool) { 388 // Commit test trie to db, then remove the node containing "bars". 389 diskdb := memorydb.New() 390 triedb := NewDatabase(diskdb) 391 392 ctr, _ := New(common.Hash{}, triedb) 393 for _, val := range testdata1 { 394 ctr.Update([]byte(val.k), []byte(val.v)) 395 } 396 root, _ := ctr.Commit(nil) 397 if !memonly { 398 triedb.Commit(root, true, nil) 399 } 400 barNodeHash := common.HexToHash("05041990364eb72fcb1127652ce40d8bab765f2bfe53225b1170d276cc101c2e") 401 var ( 402 barNodeBlob []byte 403 barNodeObj *cachedNode 404 ) 405 if memonly { 406 barNodeObj = triedb.dirties[barNodeHash] 407 delete(triedb.dirties, barNodeHash) 408 } else { 409 barNodeBlob, _ = diskdb.Get(barNodeHash[:]) 410 diskdb.Delete(barNodeHash[:]) 411 } 412 // Create a new iterator that seeks to "bars". Seeking can't proceed because 413 // the node is missing. 414 tr, _ := New(root, triedb) 415 it := tr.NodeIterator([]byte("bars")) 416 missing, ok := it.Error().(*MissingNodeError) 417 if !ok { 418 t.Fatal("want MissingNodeError, got", it.Error()) 419 } else if missing.NodeHash != barNodeHash { 420 t.Fatal("wrong node missing") 421 } 422 // Reinsert the missing node. 423 if memonly { 424 triedb.dirties[barNodeHash] = barNodeObj 425 } else { 426 diskdb.Put(barNodeHash[:], barNodeBlob) 427 } 428 // Check that iteration produces the right set of values. 429 if err := checkIteratorOrder(testdata1[2:], NewIterator(it)); err != nil { 430 t.Fatal(err) 431 } 432 } 433 434 func checkIteratorNoDups(t *testing.T, it NodeIterator, seen map[string]bool) int { 435 if seen == nil { 436 seen = make(map[string]bool) 437 } 438 for it.Next(true) { 439 if seen[string(it.Path())] { 440 t.Fatalf("iterator visited node path %x twice", it.Path()) 441 } 442 seen[string(it.Path())] = true 443 } 444 return len(seen) 445 } 446 447 type loggingDb struct { 448 getCount uint64 449 backend ethdb.KeyValueStore 450 } 451 452 func (l *loggingDb) Has(key []byte) (bool, error) { 453 return l.backend.Has(key) 454 } 455 456 func (l *loggingDb) Get(key []byte) ([]byte, error) { 457 l.getCount++ 458 return l.backend.Get(key) 459 } 460 461 func (l *loggingDb) Put(key []byte, value []byte) error { 462 return l.backend.Put(key, value) 463 } 464 465 func (l *loggingDb) Delete(key []byte) error { 466 return l.backend.Delete(key) 467 } 468 469 func (l *loggingDb) NewBatch() ethdb.Batch { 470 return l.backend.NewBatch() 471 } 472 473 func (l *loggingDb) NewIterator(prefix []byte, start []byte) ethdb.Iterator { 474 fmt.Printf("NewIterator\n") 475 return l.backend.NewIterator(prefix, start) 476 } 477 func (l *loggingDb) Stat(property string) (string, error) { 478 return l.backend.Stat(property) 479 } 480 481 func (l *loggingDb) Compact(start []byte, limit []byte) error { 482 return l.backend.Compact(start, limit) 483 } 484 485 func (l *loggingDb) Close() error { 486 return l.backend.Close() 487 } 488 489 // makeLargeTestTrie create a sample test trie 490 func makeLargeTestTrie() (*Database, *SecureTrie, *loggingDb) { 491 // Create an empty trie 492 logDb := &loggingDb{0, memorydb.New()} 493 triedb := NewDatabase(logDb) 494 trie, _ := NewSecure(common.Hash{}, triedb) 495 496 // Fill it with some arbitrary data 497 for i := 0; i < 10000; i++ { 498 key := make([]byte, 32) 499 val := make([]byte, 32) 500 binary.BigEndian.PutUint64(key, uint64(i)) 501 binary.BigEndian.PutUint64(val, uint64(i)) 502 key = crypto.Keccak256(key) 503 val = crypto.Keccak256(val) 504 trie.Update(key, val) 505 } 506 trie.Commit(nil) 507 // Return the generated trie 508 return triedb, trie, logDb 509 } 510 511 // Tests that the node iterator indeed walks over the entire database contents. 512 func TestNodeIteratorLargeTrie(t *testing.T) { 513 // Create some arbitrary test trie to iterate 514 db, trie, logDb := makeLargeTestTrie() 515 db.Cap(0) // flush everything 516 // Do a seek operation 517 trie.NodeIterator(common.FromHex("0x77667766776677766778855885885885")) 518 // master: 24 get operations 519 // this pr: 5 get operations 520 if have, want := logDb.getCount, uint64(5); have != want { 521 t.Fatalf("Too many lookups during seek, have %d want %d", have, want) 522 } 523 }