github.com/klaytn/klaytn@v1.12.1/snapshot/iterator_test.go (about) 1 // Modifications Copyright 2021 The klaytn Authors 2 // Copyright 2019 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from core/state/snapshot/iterator_test.go (2021/10/21). 19 // Modified and improved for the klaytn development. 20 21 package snapshot 22 23 import ( 24 "bytes" 25 "encoding/binary" 26 "fmt" 27 "math/rand" 28 "testing" 29 30 "github.com/VictoriaMetrics/fastcache" 31 "github.com/klaytn/klaytn/common" 32 "github.com/klaytn/klaytn/storage/database" 33 ) 34 35 // TestAccountIteratorBasics tests some simple single-layer(diff and disk) iteration 36 func TestAccountIteratorBasics(t *testing.T) { 37 var ( 38 destructs = make(map[common.Hash]struct{}) 39 accounts = make(map[common.Hash][]byte) 40 storage = make(map[common.Hash]map[common.Hash][]byte) 41 ) 42 // Fill up a parent 43 for i := 0; i < 100; i++ { 44 h := randomHash() 45 data := randomAccount() 46 47 accounts[h] = data 48 if rand.Intn(4) == 0 { 49 destructs[h] = struct{}{} 50 } 51 if rand.Intn(2) == 0 { 52 accStorage := make(map[common.Hash][]byte) 53 value := make([]byte, 32) 54 rand.Read(value) 55 accStorage[randomHash()] = value 56 storage[h] = accStorage 57 } 58 } 59 // Add some (identical) layers on top 60 diffLayer := newDiffLayer(emptyLayer(), common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage)) 61 it := diffLayer.AccountIterator(common.Hash{}) 62 verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator 63 64 diskLayer := diffToDisk(diffLayer) 65 it = diskLayer.AccountIterator(common.Hash{}) 66 verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator 67 } 68 69 // TestStorageIteratorBasics tests some simple single-layer(diff and disk) iteration for storage 70 func TestStorageIteratorBasics(t *testing.T) { 71 var ( 72 nilStorage = make(map[common.Hash]int) 73 accounts = make(map[common.Hash][]byte) 74 storage = make(map[common.Hash]map[common.Hash][]byte) 75 ) 76 // Fill some random data 77 for i := 0; i < 10; i++ { 78 h := randomHash() 79 accounts[h] = randomAccount() 80 81 accStorage := make(map[common.Hash][]byte) 82 value := make([]byte, 32) 83 84 var nilstorage int 85 for i := 0; i < 100; i++ { 86 rand.Read(value) 87 if rand.Intn(2) == 0 { 88 accStorage[randomHash()] = common.CopyBytes(value) 89 } else { 90 accStorage[randomHash()] = nil // delete slot 91 nilstorage += 1 92 } 93 } 94 storage[h] = accStorage 95 nilStorage[h] = nilstorage 96 } 97 // Add some (identical) layers on top 98 diffLayer := newDiffLayer(emptyLayer(), common.Hash{}, nil, copyAccounts(accounts), copyStorage(storage)) 99 for account := range accounts { 100 it, _ := diffLayer.StorageIterator(account, common.Hash{}) 101 verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator 102 } 103 104 diskLayer := diffToDisk(diffLayer) 105 for account := range accounts { 106 it, _ := diskLayer.StorageIterator(account, common.Hash{}) 107 verifyIterator(t, 100-nilStorage[account], it, verifyNothing) // Nil is allowed for single layer iterator 108 } 109 } 110 111 type testIterator struct { 112 values []byte 113 } 114 115 func newTestIterator(values ...byte) *testIterator { 116 return &testIterator{values} 117 } 118 119 func (ti *testIterator) Seek(common.Hash) { 120 panic("implement me") 121 } 122 123 func (ti *testIterator) Next() bool { 124 ti.values = ti.values[1:] 125 return len(ti.values) > 0 126 } 127 128 func (ti *testIterator) Error() error { 129 return nil 130 } 131 132 func (ti *testIterator) Hash() common.Hash { 133 return common.BytesToHash([]byte{ti.values[0]}) 134 } 135 136 func (ti *testIterator) Account() []byte { 137 return nil 138 } 139 140 func (ti *testIterator) Slot() []byte { 141 return nil 142 } 143 144 func (ti *testIterator) Release() {} 145 146 func TestFastIteratorBasics(t *testing.T) { 147 type testCase struct { 148 lists [][]byte 149 expKeys []byte 150 } 151 for i, tc := range []testCase{ 152 { 153 lists: [][]byte{ 154 {0, 1, 8}, 155 {1, 2, 8}, 156 {2, 9}, 157 {4}, 158 {7, 14, 15}, 159 {9, 13, 15, 16}, 160 }, 161 expKeys: []byte{0, 1, 2, 4, 7, 8, 9, 13, 14, 15, 16}, 162 }, 163 { 164 lists: [][]byte{ 165 {0, 8}, 166 {1, 2, 8}, 167 {7, 14, 15}, 168 {8, 9}, 169 {9, 10}, 170 {10, 13, 15, 16}, 171 }, 172 expKeys: []byte{0, 1, 2, 7, 8, 9, 10, 13, 14, 15, 16}, 173 }, 174 } { 175 var iterators []*weightedIterator 176 for i, data := range tc.lists { 177 it := newTestIterator(data...) 178 iterators = append(iterators, &weightedIterator{it, i}) 179 } 180 fi := &fastIterator{ 181 iterators: iterators, 182 initiated: false, 183 } 184 count := 0 185 for fi.Next() { 186 if got, exp := fi.Hash()[31], tc.expKeys[count]; exp != got { 187 t.Errorf("tc %d, [%d]: got %d exp %d", i, count, got, exp) 188 } 189 count++ 190 } 191 } 192 } 193 194 type verifyContent int 195 196 const ( 197 verifyNothing verifyContent = iota 198 verifyAccount 199 verifyStorage 200 ) 201 202 func verifyIterator(t *testing.T, expCount int, it Iterator, verify verifyContent) { 203 t.Helper() 204 205 var ( 206 count = 0 207 last = common.Hash{} 208 ) 209 for it.Next() { 210 hash := it.Hash() 211 if bytes.Compare(last[:], hash[:]) >= 0 { 212 t.Errorf("wrong order: %x >= %x", last, hash) 213 } 214 count++ 215 if verify == verifyAccount && len(it.(AccountIterator).Account()) == 0 { 216 t.Errorf("iterator returned nil-value for hash %x", hash) 217 } else if verify == verifyStorage && len(it.(StorageIterator).Slot()) == 0 { 218 t.Errorf("iterator returned nil-value for hash %x", hash) 219 } 220 last = hash 221 } 222 if count != expCount { 223 t.Errorf("iterator count mismatch: have %d, want %d", count, expCount) 224 } 225 if err := it.Error(); err != nil { 226 t.Errorf("iterator failed: %v", err) 227 } 228 } 229 230 // TestAccountIteratorTraversal tests some simple multi-layer iteration. 231 func TestAccountIteratorTraversal(t *testing.T) { 232 // Create an empty base layer and a snapshot tree out of it 233 base := &diskLayer{ 234 diskdb: database.NewMemoryDBManager(), 235 root: common.HexToHash("0x01"), 236 cache: fastcache.New(1024 * 500), 237 } 238 snaps := &Tree{ 239 layers: map[common.Hash]snapshot{ 240 base.root: base, 241 }, 242 } 243 // Stack three diff layers on top with various overlaps 244 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, 245 randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil) 246 247 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, 248 randomAccountSet("0xbb", "0xdd", "0xf0"), nil) 249 250 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, 251 randomAccountSet("0xcc", "0xf0", "0xff"), nil) 252 253 // Verify the single and multi-layer iterators 254 head := snaps.Snapshot(common.HexToHash("0x04")) 255 256 verifyIterator(t, 3, head.(snapshot).AccountIterator(common.Hash{}), verifyNothing) 257 verifyIterator(t, 7, head.(*diffLayer).newBinaryAccountIterator(), verifyAccount) 258 259 it, _ := snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) 260 verifyIterator(t, 7, it, verifyAccount) 261 it.Release() 262 263 // Test after persist some bottom-most layers into the disk, 264 // the functionalities still work. 265 limit := aggregatorMemoryLimit 266 defer func() { 267 aggregatorMemoryLimit = limit 268 }() 269 aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk 270 snaps.Cap(common.HexToHash("0x04"), 2) 271 verifyIterator(t, 7, head.(*diffLayer).newBinaryAccountIterator(), verifyAccount) 272 273 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) 274 verifyIterator(t, 7, it, verifyAccount) 275 it.Release() 276 } 277 278 func TestStorageIteratorTraversal(t *testing.T) { 279 // Create an empty base layer and a snapshot tree out of it 280 base := &diskLayer{ 281 diskdb: database.NewMemoryDBManager(), 282 root: common.HexToHash("0x01"), 283 cache: fastcache.New(1024 * 500), 284 } 285 snaps := &Tree{ 286 layers: map[common.Hash]snapshot{ 287 base.root: base, 288 }, 289 } 290 // Stack three diff layers on top with various overlaps 291 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, 292 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x02", "0x03"}}, nil)) 293 294 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, 295 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x04", "0x05", "0x06"}}, nil)) 296 297 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, 298 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x02", "0x03"}}, nil)) 299 300 // Verify the single and multi-layer iterators 301 head := snaps.Snapshot(common.HexToHash("0x04")) 302 303 diffIter, _ := head.(snapshot).StorageIterator(common.HexToHash("0xaa"), common.Hash{}) 304 verifyIterator(t, 3, diffIter, verifyNothing) 305 verifyIterator(t, 6, head.(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa")), verifyStorage) 306 307 it, _ := snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.Hash{}) 308 verifyIterator(t, 6, it, verifyStorage) 309 it.Release() 310 311 // Test after persist some bottom-most layers into the disk, 312 // the functionalities still work. 313 limit := aggregatorMemoryLimit 314 defer func() { 315 aggregatorMemoryLimit = limit 316 }() 317 aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk 318 snaps.Cap(common.HexToHash("0x04"), 2) 319 verifyIterator(t, 6, head.(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa")), verifyStorage) 320 321 it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.Hash{}) 322 verifyIterator(t, 6, it, verifyStorage) 323 it.Release() 324 } 325 326 // TestAccountIteratorTraversalValues tests some multi-layer iteration, where we 327 // also expect the correct values to show up. 328 func TestAccountIteratorTraversalValues(t *testing.T) { 329 // Create an empty base layer and a snapshot tree out of it 330 base := &diskLayer{ 331 diskdb: database.NewMemoryDBManager(), 332 root: common.HexToHash("0x01"), 333 cache: fastcache.New(1024 * 500), 334 } 335 snaps := &Tree{ 336 layers: map[common.Hash]snapshot{ 337 base.root: base, 338 }, 339 } 340 // Create a batch of account sets to seed subsequent layers with 341 var ( 342 a = make(map[common.Hash][]byte) 343 b = make(map[common.Hash][]byte) 344 c = make(map[common.Hash][]byte) 345 d = make(map[common.Hash][]byte) 346 e = make(map[common.Hash][]byte) 347 f = make(map[common.Hash][]byte) 348 g = make(map[common.Hash][]byte) 349 h = make(map[common.Hash][]byte) 350 ) 351 for i := byte(2); i < 0xff; i++ { 352 a[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 0, i)) 353 if i > 20 && i%2 == 0 { 354 b[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 1, i)) 355 } 356 if i%4 == 0 { 357 c[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 2, i)) 358 } 359 if i%7 == 0 { 360 d[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 3, i)) 361 } 362 if i%8 == 0 { 363 e[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 4, i)) 364 } 365 if i > 50 || i < 85 { 366 f[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 5, i)) 367 } 368 if i%64 == 0 { 369 g[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 6, i)) 370 } 371 if i%128 == 0 { 372 h[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 7, i)) 373 } 374 } 375 // Assemble a stack of snapshots from the account layers 376 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, a, nil) 377 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, b, nil) 378 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, c, nil) 379 snaps.Update(common.HexToHash("0x05"), common.HexToHash("0x04"), nil, d, nil) 380 snaps.Update(common.HexToHash("0x06"), common.HexToHash("0x05"), nil, e, nil) 381 snaps.Update(common.HexToHash("0x07"), common.HexToHash("0x06"), nil, f, nil) 382 snaps.Update(common.HexToHash("0x08"), common.HexToHash("0x07"), nil, g, nil) 383 snaps.Update(common.HexToHash("0x09"), common.HexToHash("0x08"), nil, h, nil) 384 385 it, _ := snaps.AccountIterator(common.HexToHash("0x09"), common.Hash{}) 386 head := snaps.Snapshot(common.HexToHash("0x09")) 387 for it.Next() { 388 hash := it.Hash() 389 want, err := head.AccountRLP(hash) 390 if err != nil { 391 t.Fatalf("failed to retrieve expected account: %v", err) 392 } 393 if have := it.Account(); !bytes.Equal(want, have) { 394 t.Fatalf("hash %x: account mismatch: have %x, want %x", hash, have, want) 395 } 396 } 397 it.Release() 398 399 // Test after persist some bottom-most layers into the disk, 400 // the functionalities still work. 401 limit := aggregatorMemoryLimit 402 defer func() { 403 aggregatorMemoryLimit = limit 404 }() 405 aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk 406 snaps.Cap(common.HexToHash("0x09"), 2) 407 408 it, _ = snaps.AccountIterator(common.HexToHash("0x09"), common.Hash{}) 409 for it.Next() { 410 hash := it.Hash() 411 want, err := head.AccountRLP(hash) 412 if err != nil { 413 t.Fatalf("failed to retrieve expected account: %v", err) 414 } 415 if have := it.Account(); !bytes.Equal(want, have) { 416 t.Fatalf("hash %x: account mismatch: have %x, want %x", hash, have, want) 417 } 418 } 419 it.Release() 420 } 421 422 func TestStorageIteratorTraversalValues(t *testing.T) { 423 // Create an empty base layer and a snapshot tree out of it 424 base := &diskLayer{ 425 diskdb: database.NewMemoryDBManager(), 426 root: common.HexToHash("0x01"), 427 cache: fastcache.New(1024 * 500), 428 } 429 snaps := &Tree{ 430 layers: map[common.Hash]snapshot{ 431 base.root: base, 432 }, 433 } 434 wrapStorage := func(storage map[common.Hash][]byte) map[common.Hash]map[common.Hash][]byte { 435 return map[common.Hash]map[common.Hash][]byte{ 436 common.HexToHash("0xaa"): storage, 437 } 438 } 439 // Create a batch of storage sets to seed subsequent layers with 440 var ( 441 a = make(map[common.Hash][]byte) 442 b = make(map[common.Hash][]byte) 443 c = make(map[common.Hash][]byte) 444 d = make(map[common.Hash][]byte) 445 e = make(map[common.Hash][]byte) 446 f = make(map[common.Hash][]byte) 447 g = make(map[common.Hash][]byte) 448 h = make(map[common.Hash][]byte) 449 ) 450 for i := byte(2); i < 0xff; i++ { 451 a[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 0, i)) 452 if i > 20 && i%2 == 0 { 453 b[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 1, i)) 454 } 455 if i%4 == 0 { 456 c[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 2, i)) 457 } 458 if i%7 == 0 { 459 d[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 3, i)) 460 } 461 if i%8 == 0 { 462 e[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 4, i)) 463 } 464 if i > 50 || i < 85 { 465 f[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 5, i)) 466 } 467 if i%64 == 0 { 468 g[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 6, i)) 469 } 470 if i%128 == 0 { 471 h[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 7, i)) 472 } 473 } 474 // Assemble a stack of snapshots from the account layers 475 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, randomAccountSet("0xaa"), wrapStorage(a)) 476 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, randomAccountSet("0xaa"), wrapStorage(b)) 477 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, randomAccountSet("0xaa"), wrapStorage(c)) 478 snaps.Update(common.HexToHash("0x05"), common.HexToHash("0x04"), nil, randomAccountSet("0xaa"), wrapStorage(d)) 479 snaps.Update(common.HexToHash("0x06"), common.HexToHash("0x05"), nil, randomAccountSet("0xaa"), wrapStorage(e)) 480 snaps.Update(common.HexToHash("0x07"), common.HexToHash("0x06"), nil, randomAccountSet("0xaa"), wrapStorage(e)) 481 snaps.Update(common.HexToHash("0x08"), common.HexToHash("0x07"), nil, randomAccountSet("0xaa"), wrapStorage(g)) 482 snaps.Update(common.HexToHash("0x09"), common.HexToHash("0x08"), nil, randomAccountSet("0xaa"), wrapStorage(h)) 483 484 it, _ := snaps.StorageIterator(common.HexToHash("0x09"), common.HexToHash("0xaa"), common.Hash{}) 485 head := snaps.Snapshot(common.HexToHash("0x09")) 486 for it.Next() { 487 hash := it.Hash() 488 want, err := head.Storage(common.HexToHash("0xaa"), hash) 489 if err != nil { 490 t.Fatalf("failed to retrieve expected storage slot: %v", err) 491 } 492 if have := it.Slot(); !bytes.Equal(want, have) { 493 t.Fatalf("hash %x: slot mismatch: have %x, want %x", hash, have, want) 494 } 495 } 496 it.Release() 497 498 // Test after persist some bottom-most layers into the disk, 499 // the functionalities still work. 500 limit := aggregatorMemoryLimit 501 defer func() { 502 aggregatorMemoryLimit = limit 503 }() 504 aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk 505 snaps.Cap(common.HexToHash("0x09"), 2) 506 507 it, _ = snaps.StorageIterator(common.HexToHash("0x09"), common.HexToHash("0xaa"), common.Hash{}) 508 for it.Next() { 509 hash := it.Hash() 510 want, err := head.Storage(common.HexToHash("0xaa"), hash) 511 if err != nil { 512 t.Fatalf("failed to retrieve expected slot: %v", err) 513 } 514 if have := it.Slot(); !bytes.Equal(want, have) { 515 t.Fatalf("hash %x: slot mismatch: have %x, want %x", hash, have, want) 516 } 517 } 518 it.Release() 519 } 520 521 // This testcase is notorious, all layers contain the exact same 200 accounts. 522 func TestAccountIteratorLargeTraversal(t *testing.T) { 523 // Create a custom account factory to recreate the same addresses 524 makeAccounts := func(num int) map[common.Hash][]byte { 525 accounts := make(map[common.Hash][]byte) 526 for i := 0; i < num; i++ { 527 h := common.Hash{} 528 binary.BigEndian.PutUint64(h[:], uint64(i+1)) 529 accounts[h] = randomAccount() 530 } 531 return accounts 532 } 533 // Build up a large stack of snapshots 534 base := &diskLayer{ 535 diskdb: database.NewMemoryDBManager(), 536 root: common.HexToHash("0x01"), 537 cache: fastcache.New(1024 * 500), 538 } 539 snaps := &Tree{ 540 layers: map[common.Hash]snapshot{ 541 base.root: base, 542 }, 543 } 544 for i := 1; i < 128; i++ { 545 snaps.Update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(200), nil) 546 } 547 // Iterate the entire stack and ensure everything is hit only once 548 head := snaps.Snapshot(common.HexToHash("0x80")) 549 verifyIterator(t, 200, head.(snapshot).AccountIterator(common.Hash{}), verifyNothing) 550 verifyIterator(t, 200, head.(*diffLayer).newBinaryAccountIterator(), verifyAccount) 551 552 it, _ := snaps.AccountIterator(common.HexToHash("0x80"), common.Hash{}) 553 verifyIterator(t, 200, it, verifyAccount) 554 it.Release() 555 556 // Test after persist some bottom-most layers into the disk, 557 // the functionalities still work. 558 limit := aggregatorMemoryLimit 559 defer func() { 560 aggregatorMemoryLimit = limit 561 }() 562 aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk 563 snaps.Cap(common.HexToHash("0x80"), 2) 564 565 verifyIterator(t, 200, head.(*diffLayer).newBinaryAccountIterator(), verifyAccount) 566 567 it, _ = snaps.AccountIterator(common.HexToHash("0x80"), common.Hash{}) 568 verifyIterator(t, 200, it, verifyAccount) 569 it.Release() 570 } 571 572 // TestAccountIteratorFlattening tests what happens when we 573 // - have a live iterator on child C (parent C1 -> C2 .. CN) 574 // - flattens C2 all the way into CN 575 // - continues iterating 576 func TestAccountIteratorFlattening(t *testing.T) { 577 // Create an empty base layer and a snapshot tree out of it 578 base := &diskLayer{ 579 diskdb: database.NewMemoryDBManager(), 580 root: common.HexToHash("0x01"), 581 cache: fastcache.New(1024 * 500), 582 } 583 snaps := &Tree{ 584 layers: map[common.Hash]snapshot{ 585 base.root: base, 586 }, 587 } 588 // Create a stack of diffs on top 589 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, 590 randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil) 591 592 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, 593 randomAccountSet("0xbb", "0xdd", "0xf0"), nil) 594 595 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, 596 randomAccountSet("0xcc", "0xf0", "0xff"), nil) 597 598 // Create an iterator and flatten the data from underneath it 599 it, _ := snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) 600 defer it.Release() 601 602 if err := snaps.Cap(common.HexToHash("0x04"), 1); err != nil { 603 t.Fatalf("failed to flatten snapshot stack: %v", err) 604 } 605 // verifyIterator(t, 7, it) 606 } 607 608 func TestAccountIteratorSeek(t *testing.T) { 609 // Create a snapshot stack with some initial data 610 base := &diskLayer{ 611 diskdb: database.NewMemoryDBManager(), 612 root: common.HexToHash("0x01"), 613 cache: fastcache.New(1024 * 500), 614 } 615 snaps := &Tree{ 616 layers: map[common.Hash]snapshot{ 617 base.root: base, 618 }, 619 } 620 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, 621 randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil) 622 623 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, 624 randomAccountSet("0xbb", "0xdd", "0xf0"), nil) 625 626 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, 627 randomAccountSet("0xcc", "0xf0", "0xff"), nil) 628 629 // Account set is now 630 // 02: aa, ee, f0, ff 631 // 03: aa, bb, dd, ee, f0 (, f0), ff 632 // 04: aa, bb, cc, dd, ee, f0 (, f0), ff (, ff) 633 // Construct various iterators and ensure their traversal is correct 634 it, _ := snaps.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xdd")) 635 defer it.Release() 636 verifyIterator(t, 3, it, verifyAccount) // expected: ee, f0, ff 637 638 it, _ = snaps.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xaa")) 639 defer it.Release() 640 verifyIterator(t, 4, it, verifyAccount) // expected: aa, ee, f0, ff 641 642 it, _ = snaps.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xff")) 643 defer it.Release() 644 verifyIterator(t, 1, it, verifyAccount) // expected: ff 645 646 it, _ = snaps.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xff1")) 647 defer it.Release() 648 verifyIterator(t, 0, it, verifyAccount) // expected: nothing 649 650 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xbb")) 651 defer it.Release() 652 verifyIterator(t, 6, it, verifyAccount) // expected: bb, cc, dd, ee, f0, ff 653 654 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xef")) 655 defer it.Release() 656 verifyIterator(t, 2, it, verifyAccount) // expected: f0, ff 657 658 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xf0")) 659 defer it.Release() 660 verifyIterator(t, 2, it, verifyAccount) // expected: f0, ff 661 662 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xff")) 663 defer it.Release() 664 verifyIterator(t, 1, it, verifyAccount) // expected: ff 665 666 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xff1")) 667 defer it.Release() 668 verifyIterator(t, 0, it, verifyAccount) // expected: nothing 669 } 670 671 func TestStorageIteratorSeek(t *testing.T) { 672 // Create a snapshot stack with some initial data 673 base := &diskLayer{ 674 diskdb: database.NewMemoryDBManager(), 675 root: common.HexToHash("0x01"), 676 cache: fastcache.New(1024 * 500), 677 } 678 snaps := &Tree{ 679 layers: map[common.Hash]snapshot{ 680 base.root: base, 681 }, 682 } 683 // Stack three diff layers on top with various overlaps 684 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, 685 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x03", "0x05"}}, nil)) 686 687 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, 688 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x02", "0x05", "0x06"}}, nil)) 689 690 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, 691 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x05", "0x08"}}, nil)) 692 693 // Account set is now 694 // 02: 01, 03, 05 695 // 03: 01, 02, 03, 05 (, 05), 06 696 // 04: 01(, 01), 02, 03, 05(, 05, 05), 06, 08 697 // Construct various iterators and ensure their traversal is correct 698 it, _ := snaps.StorageIterator(common.HexToHash("0x02"), common.HexToHash("0xaa"), common.HexToHash("0x01")) 699 defer it.Release() 700 verifyIterator(t, 3, it, verifyStorage) // expected: 01, 03, 05 701 702 it, _ = snaps.StorageIterator(common.HexToHash("0x02"), common.HexToHash("0xaa"), common.HexToHash("0x02")) 703 defer it.Release() 704 verifyIterator(t, 2, it, verifyStorage) // expected: 03, 05 705 706 it, _ = snaps.StorageIterator(common.HexToHash("0x02"), common.HexToHash("0xaa"), common.HexToHash("0x5")) 707 defer it.Release() 708 verifyIterator(t, 1, it, verifyStorage) // expected: 05 709 710 it, _ = snaps.StorageIterator(common.HexToHash("0x02"), common.HexToHash("0xaa"), common.HexToHash("0x6")) 711 defer it.Release() 712 verifyIterator(t, 0, it, verifyStorage) // expected: nothing 713 714 it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.HexToHash("0x01")) 715 defer it.Release() 716 verifyIterator(t, 6, it, verifyStorage) // expected: 01, 02, 03, 05, 06, 08 717 718 it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.HexToHash("0x05")) 719 defer it.Release() 720 verifyIterator(t, 3, it, verifyStorage) // expected: 05, 06, 08 721 722 it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.HexToHash("0x08")) 723 defer it.Release() 724 verifyIterator(t, 1, it, verifyStorage) // expected: 08 725 726 it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.HexToHash("0x09")) 727 defer it.Release() 728 verifyIterator(t, 0, it, verifyStorage) // expected: nothing 729 } 730 731 // TestAccountIteratorDeletions tests that the iterator behaves correct when there are 732 // deleted accounts (where the Account() value is nil). The iterator 733 // should not output any accounts or nil-values for those cases. 734 func TestAccountIteratorDeletions(t *testing.T) { 735 // Create an empty base layer and a snapshot tree out of it 736 base := &diskLayer{ 737 diskdb: database.NewMemoryDBManager(), 738 root: common.HexToHash("0x01"), 739 cache: fastcache.New(1024 * 500), 740 } 741 snaps := &Tree{ 742 layers: map[common.Hash]snapshot{ 743 base.root: base, 744 }, 745 } 746 // Stack three diff layers on top with various overlaps 747 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), 748 nil, randomAccountSet("0x11", "0x22", "0x33"), nil) 749 750 deleted := common.HexToHash("0x22") 751 destructed := map[common.Hash]struct{}{ 752 deleted: {}, 753 } 754 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), 755 destructed, randomAccountSet("0x11", "0x33"), nil) 756 757 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), 758 nil, randomAccountSet("0x33", "0x44", "0x55"), nil) 759 760 // The output should be 11,33,44,55 761 it, _ := snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) 762 // Do a quick check 763 verifyIterator(t, 4, it, verifyAccount) 764 it.Release() 765 766 // And a more detailed verification that we indeed do not see '0x22' 767 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) 768 defer it.Release() 769 for it.Next() { 770 hash := it.Hash() 771 if it.Account() == nil { 772 t.Errorf("iterator returned nil-value for hash %x", hash) 773 } 774 if hash == deleted { 775 t.Errorf("expected deleted elem %x to not be returned by iterator", deleted) 776 } 777 } 778 } 779 780 func TestStorageIteratorDeletions(t *testing.T) { 781 // Create an empty base layer and a snapshot tree out of it 782 base := &diskLayer{ 783 diskdb: database.NewMemoryDBManager(), 784 root: common.HexToHash("0x01"), 785 cache: fastcache.New(1024 * 500), 786 } 787 snaps := &Tree{ 788 layers: map[common.Hash]snapshot{ 789 base.root: base, 790 }, 791 } 792 // Stack three diff layers on top with various overlaps 793 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, 794 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x03", "0x05"}}, nil)) 795 796 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, 797 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x02", "0x04", "0x06"}}, [][]string{{"0x01", "0x03"}})) 798 799 // The output should be 02,04,05,06 800 it, _ := snaps.StorageIterator(common.HexToHash("0x03"), common.HexToHash("0xaa"), common.Hash{}) 801 verifyIterator(t, 4, it, verifyStorage) 802 it.Release() 803 804 // The output should be 04,05,06 805 it, _ = snaps.StorageIterator(common.HexToHash("0x03"), common.HexToHash("0xaa"), common.HexToHash("0x03")) 806 verifyIterator(t, 3, it, verifyStorage) 807 it.Release() 808 809 // Destruct the whole storage 810 destructed := map[common.Hash]struct{}{ 811 common.HexToHash("0xaa"): {}, 812 } 813 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), destructed, nil, nil) 814 815 it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.Hash{}) 816 verifyIterator(t, 0, it, verifyStorage) 817 it.Release() 818 819 // Re-insert the slots of the same account 820 snaps.Update(common.HexToHash("0x05"), common.HexToHash("0x04"), nil, 821 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x07", "0x08", "0x09"}}, nil)) 822 823 // The output should be 07,08,09 824 it, _ = snaps.StorageIterator(common.HexToHash("0x05"), common.HexToHash("0xaa"), common.Hash{}) 825 verifyIterator(t, 3, it, verifyStorage) 826 it.Release() 827 828 // Destruct the whole storage but re-create the account in the same layer 829 snaps.Update(common.HexToHash("0x06"), common.HexToHash("0x05"), destructed, randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x11", "0x12"}}, nil)) 830 it, _ = snaps.StorageIterator(common.HexToHash("0x06"), common.HexToHash("0xaa"), common.Hash{}) 831 verifyIterator(t, 2, it, verifyStorage) // The output should be 11,12 832 it.Release() 833 834 verifyIterator(t, 2, snaps.Snapshot(common.HexToHash("0x06")).(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa")), verifyStorage) 835 } 836 837 // BenchmarkAccountIteratorTraversal is a bit a bit notorious -- all layers contain the 838 // exact same 200 accounts. That means that we need to process 2000 items, but 839 // only spit out 200 values eventually. 840 // 841 // The value-fetching benchmark is easy on the binary iterator, since it never has to reach 842 // down at any depth for retrieving the values -- all are on the toppmost layer 843 // 844 // BenchmarkAccountIteratorTraversal/binary_iterator_keys-6 2239 483674 ns/op 845 // BenchmarkAccountIteratorTraversal/binary_iterator_values-6 2403 501810 ns/op 846 // BenchmarkAccountIteratorTraversal/fast_iterator_keys-6 1923 677966 ns/op 847 // BenchmarkAccountIteratorTraversal/fast_iterator_values-6 1741 649967 ns/op 848 func BenchmarkAccountIteratorTraversal(b *testing.B) { 849 // Create a custom account factory to recreate the same addresses 850 makeAccounts := func(num int) map[common.Hash][]byte { 851 accounts := make(map[common.Hash][]byte) 852 for i := 0; i < num; i++ { 853 h := common.Hash{} 854 binary.BigEndian.PutUint64(h[:], uint64(i+1)) 855 accounts[h] = randomAccount() 856 } 857 return accounts 858 } 859 // Build up a large stack of snapshots 860 base := &diskLayer{ 861 diskdb: database.NewMemoryDBManager(), 862 root: common.HexToHash("0x01"), 863 cache: fastcache.New(1024 * 500), 864 } 865 snaps := &Tree{ 866 layers: map[common.Hash]snapshot{ 867 base.root: base, 868 }, 869 } 870 for i := 1; i <= 100; i++ { 871 snaps.Update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(200), nil) 872 } 873 // We call this once before the benchmark, so the creation of 874 // sorted accountlists are not included in the results. 875 head := snaps.Snapshot(common.HexToHash("0x65")) 876 head.(*diffLayer).newBinaryAccountIterator() 877 878 b.Run("binary iterator keys", func(b *testing.B) { 879 for i := 0; i < b.N; i++ { 880 got := 0 881 it := head.(*diffLayer).newBinaryAccountIterator() 882 for it.Next() { 883 got++ 884 } 885 if exp := 200; got != exp { 886 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 887 } 888 } 889 }) 890 b.Run("binary iterator values", func(b *testing.B) { 891 for i := 0; i < b.N; i++ { 892 got := 0 893 it := head.(*diffLayer).newBinaryAccountIterator() 894 for it.Next() { 895 got++ 896 head.(*diffLayer).accountRLP(it.Hash(), 0) 897 } 898 if exp := 200; got != exp { 899 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 900 } 901 } 902 }) 903 b.Run("fast iterator keys", func(b *testing.B) { 904 for i := 0; i < b.N; i++ { 905 it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) 906 defer it.Release() 907 908 got := 0 909 for it.Next() { 910 got++ 911 } 912 if exp := 200; got != exp { 913 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 914 } 915 } 916 }) 917 b.Run("fast iterator values", func(b *testing.B) { 918 for i := 0; i < b.N; i++ { 919 it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) 920 defer it.Release() 921 922 got := 0 923 for it.Next() { 924 got++ 925 it.Account() 926 } 927 if exp := 200; got != exp { 928 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 929 } 930 } 931 }) 932 } 933 934 // BenchmarkAccountIteratorLargeBaselayer is a pretty realistic benchmark, where 935 // the baselayer is a lot larger than the upper layer. 936 // 937 // This is heavy on the binary iterator, which in most cases will have to 938 // call recursively 100 times for the majority of the values 939 // 940 // BenchmarkAccountIteratorLargeBaselayer/binary_iterator_(keys)-6 514 1971999 ns/op 941 // BenchmarkAccountIteratorLargeBaselayer/binary_iterator_(values)-6 61 18997492 ns/op 942 // BenchmarkAccountIteratorLargeBaselayer/fast_iterator_(keys)-6 10000 114385 ns/op 943 // BenchmarkAccountIteratorLargeBaselayer/fast_iterator_(values)-6 4047 296823 ns/op 944 func BenchmarkAccountIteratorLargeBaselayer(b *testing.B) { 945 // Create a custom account factory to recreate the same addresses 946 makeAccounts := func(num int) map[common.Hash][]byte { 947 accounts := make(map[common.Hash][]byte) 948 for i := 0; i < num; i++ { 949 h := common.Hash{} 950 binary.BigEndian.PutUint64(h[:], uint64(i+1)) 951 accounts[h] = randomAccount() 952 } 953 return accounts 954 } 955 // Build up a large stack of snapshots 956 base := &diskLayer{ 957 diskdb: database.NewMemoryDBManager(), 958 root: common.HexToHash("0x01"), 959 cache: fastcache.New(1024 * 500), 960 } 961 snaps := &Tree{ 962 layers: map[common.Hash]snapshot{ 963 base.root: base, 964 }, 965 } 966 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, makeAccounts(2000), nil) 967 for i := 2; i <= 100; i++ { 968 snaps.Update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(20), nil) 969 } 970 // We call this once before the benchmark, so the creation of 971 // sorted accountlists are not included in the results. 972 head := snaps.Snapshot(common.HexToHash("0x65")) 973 head.(*diffLayer).newBinaryAccountIterator() 974 975 b.Run("binary iterator (keys)", func(b *testing.B) { 976 for i := 0; i < b.N; i++ { 977 got := 0 978 it := head.(*diffLayer).newBinaryAccountIterator() 979 for it.Next() { 980 got++ 981 } 982 if exp := 2000; got != exp { 983 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 984 } 985 } 986 }) 987 b.Run("binary iterator (values)", func(b *testing.B) { 988 for i := 0; i < b.N; i++ { 989 got := 0 990 it := head.(*diffLayer).newBinaryAccountIterator() 991 for it.Next() { 992 got++ 993 v := it.Hash() 994 head.(*diffLayer).accountRLP(v, 0) 995 } 996 if exp := 2000; got != exp { 997 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 998 } 999 } 1000 }) 1001 b.Run("fast iterator (keys)", func(b *testing.B) { 1002 for i := 0; i < b.N; i++ { 1003 it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) 1004 defer it.Release() 1005 1006 got := 0 1007 for it.Next() { 1008 got++ 1009 } 1010 if exp := 2000; got != exp { 1011 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 1012 } 1013 } 1014 }) 1015 b.Run("fast iterator (values)", func(b *testing.B) { 1016 for i := 0; i < b.N; i++ { 1017 it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) 1018 defer it.Release() 1019 1020 got := 0 1021 for it.Next() { 1022 it.Account() 1023 got++ 1024 } 1025 if exp := 2000; got != exp { 1026 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 1027 } 1028 } 1029 }) 1030 } 1031 1032 /* 1033 func BenchmarkBinaryAccountIteration(b *testing.B) { 1034 benchmarkAccountIteration(b, func(snap snapshot) AccountIterator { 1035 return snap.(*diffLayer).newBinaryAccountIterator() 1036 }) 1037 } 1038 1039 func BenchmarkFastAccountIteration(b *testing.B) { 1040 benchmarkAccountIteration(b, newFastAccountIterator) 1041 } 1042 1043 func benchmarkAccountIteration(b *testing.B, iterator func(snap snapshot) AccountIterator) { 1044 // Create a diff stack and randomize the accounts across them 1045 layers := make([]map[common.Hash][]byte, 128) 1046 for i := 0; i < len(layers); i++ { 1047 layers[i] = make(map[common.Hash][]byte) 1048 } 1049 for i := 0; i < b.N; i++ { 1050 depth := rand.Intn(len(layers)) 1051 layers[depth][randomHash()] = randomAccount() 1052 } 1053 stack := snapshot(emptyLayer()) 1054 for _, layer := range layers { 1055 stack = stack.Update(common.Hash{}, layer, nil, nil) 1056 } 1057 // Reset the timers and report all the stats 1058 it := iterator(stack) 1059 1060 b.ResetTimer() 1061 b.ReportAllocs() 1062 1063 for it.Next() { 1064 } 1065 } 1066 */