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