|
17 | 17 | package snapshot |
18 | 18 |
|
19 | 19 | import ( |
| 20 | + "fmt" |
20 | 21 | "github.com/ethereum/go-ethereum/log" |
21 | 22 | "math/big" |
22 | 23 | "os" |
@@ -426,3 +427,64 @@ func TestGenerateCorruptStorageTrie(t *testing.T) { |
426 | 427 | snap.genAbort <- stop |
427 | 428 | <-stop |
428 | 429 | } |
| 430 | + |
| 431 | +func getStorageTrie(n int, triedb *trie.Database) *trie.SecureTrie { |
| 432 | + stTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
| 433 | + for i := 0; i < n; i++ { |
| 434 | + k := fmt.Sprintf("key-%d", i) |
| 435 | + v := fmt.Sprintf("val-%d", i) |
| 436 | + stTrie.Update([]byte(k), []byte(v)) |
| 437 | + } |
| 438 | + stTrie.Commit(nil) |
| 439 | + return stTrie |
| 440 | +} |
| 441 | + |
| 442 | +// Tests that snapshot generation when an extra account with storage exists in the snap state. |
| 443 | +func TestGenerateWithExtraAccounts(t *testing.T) { |
| 444 | + |
| 445 | + var ( |
| 446 | + diskdb = memorydb.New() |
| 447 | + triedb = trie.NewDatabase(diskdb) |
| 448 | + stTrie = getStorageTrie(5, triedb) |
| 449 | + ) |
| 450 | + accTrie, _ := trie.NewSecure(common.Hash{}, triedb) |
| 451 | + { // Account one in the trie |
| 452 | + acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} |
| 453 | + val, _ := rlp.EncodeToBytes(acc) |
| 454 | + accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e |
| 455 | + // Identical in the snap |
| 456 | + rawdb.WriteAccountSnapshot(diskdb, hashData([]byte("acc-1")), val) |
| 457 | + rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-1")), hashData([]byte("key-1")), []byte("val-1")) |
| 458 | + rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-1")), hashData([]byte("key-2")), []byte("val-2")) |
| 459 | + rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-1")), hashData([]byte("key-3")), []byte("val-3")) |
| 460 | + } |
| 461 | + { // Account two exists only in the snapshot |
| 462 | + acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} |
| 463 | + val, _ := rlp.EncodeToBytes(acc) |
| 464 | + rawdb.WriteAccountSnapshot(diskdb, hashData([]byte("acc-2")), val) |
| 465 | + rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1")), []byte("b-val-1")) |
| 466 | + rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-2")), []byte("b-val-2")) |
| 467 | + rawdb.WriteStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-3")), []byte("b-val-3")) |
| 468 | + } |
| 469 | + root, _ := accTrie.Commit(nil) |
| 470 | + t.Logf("root: %x", root) |
| 471 | + triedb.Commit(root, false, nil) |
| 472 | + |
| 473 | + snap := generateSnapshot(diskdb, triedb, 16, root) |
| 474 | + select { |
| 475 | + case <-snap.genPending: |
| 476 | + // Snapshot generation succeeded |
| 477 | + |
| 478 | + case <-time.After(250 * time.Millisecond): |
| 479 | + t.Errorf("Snapshot generation failed") |
| 480 | + } |
| 481 | + checkSnapRoot(t, snap, root) |
| 482 | + // Signal abortion to the generator and wait for it to tear down |
| 483 | + stop := make(chan *generatorStats) |
| 484 | + snap.genAbort <- stop |
| 485 | + <-stop |
| 486 | + // If we now inspect the snap db, there should exist no extraneous storage items |
| 487 | + if data := rawdb.ReadStorageSnapshot(diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { |
| 488 | + t.Fatalf("expected slot to be removed, got %v", string(data)) |
| 489 | + } |
| 490 | +} |
0 commit comments