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