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