mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 13:46:43 +00:00
add test case
Signed-off-by: jsvisa <delweng@gmail.com>
This commit is contained in:
parent
6831f8d4a3
commit
492ee0baba
1 changed files with 113 additions and 0 deletions
|
|
@ -754,3 +754,116 @@ func copyStorages(set map[common.Hash]map[common.Hash][]byte) map[common.Hash]ma
|
|||
}
|
||||
return copied
|
||||
}
|
||||
|
||||
// TestDatabaseRepair tests the fix for issue where state history index
|
||||
// metadata is not updated after state truncation during repairHistory.
|
||||
func TestDatabaseRepair(t *testing.T) {
|
||||
ancient := t.TempDir()
|
||||
diskdb, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{Ancient: ancient})
|
||||
defer diskdb.Close()
|
||||
|
||||
var (
|
||||
roots []common.Hash
|
||||
hs []*history
|
||||
config = &Config{EnableStateIndexing: true}
|
||||
)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
accounts := make(map[common.Address][]byte)
|
||||
storages := make(map[common.Address]map[common.Hash][]byte)
|
||||
|
||||
addr := testrand.Address()
|
||||
accounts[addr] = testrand.Bytes(32)
|
||||
storages[addr] = make(map[common.Hash][]byte)
|
||||
storages[addr][testrand.Hash()] = testrand.Bytes(32)
|
||||
|
||||
root := testrand.Hash()
|
||||
h := newHistory(root, common.Hash{}, uint64(i+1), accounts, storages, false)
|
||||
|
||||
hs = append(hs, h)
|
||||
roots = append(roots, root)
|
||||
}
|
||||
|
||||
db := New(diskdb, config, false)
|
||||
defer db.Close()
|
||||
|
||||
for i, h := range hs {
|
||||
accountData, storageData, accountIndex, storageIndex := h.encode()
|
||||
err := rawdb.WriteStateHistory(db.freezer, uint64(i+1), h.meta.encode(), accountIndex, storageIndex, accountData, storageData)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to write state history %d: %v", i+1, err)
|
||||
}
|
||||
rawdb.WriteStateID(diskdb, roots[i], uint64(i+1))
|
||||
}
|
||||
|
||||
// Create index metadata pointing to the last state (ID 5)
|
||||
storeIndexMetadata(diskdb, 5)
|
||||
|
||||
// Verify metadata exists and points to state ID 5
|
||||
meta := loadIndexMetadata(diskdb)
|
||||
if meta == nil {
|
||||
t.Fatal("Index metadata should exist")
|
||||
}
|
||||
if meta.Last != 5 {
|
||||
t.Fatalf("Expected metadata.Last = 5, got %d", meta.Last)
|
||||
}
|
||||
|
||||
// Close the current database to replace its tree
|
||||
db.Close()
|
||||
|
||||
// Create a new database with a mock tree that has state ID 3 as bottom
|
||||
// This simulates a scenario where the disk layer has state ID 3, but the
|
||||
// freezer has histories up to ID 5, and metadata points to ID 5
|
||||
db = &Database{
|
||||
readOnly: false,
|
||||
config: config,
|
||||
diskdb: diskdb,
|
||||
hasher: merkleNodeHasher,
|
||||
}
|
||||
|
||||
tree := &layerTree{
|
||||
base: newDiskLayer(roots[2], 3, db, nil, nil, nil, nil),
|
||||
layers: make(map[common.Hash]layer),
|
||||
}
|
||||
db.tree = tree
|
||||
|
||||
// repairHistory should truncate histories above state ID 3
|
||||
// and reset the index metadata from 5 to 3
|
||||
if err := db.repairHistory(); err != nil {
|
||||
t.Fatalf("repairHistory failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify that histories above state ID 3 have been truncated
|
||||
head, err := db.freezer.Ancients()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get freezer head: %v", err)
|
||||
}
|
||||
if head != 3 {
|
||||
t.Fatalf("Expected freezer head = 3, got %d", head)
|
||||
}
|
||||
|
||||
// Verify that the index metadata has been reset to 3
|
||||
meta = loadIndexMetadata(diskdb)
|
||||
if meta == nil {
|
||||
t.Fatal("Index metadata should still exist after repair")
|
||||
}
|
||||
if meta.Last != 3 {
|
||||
t.Fatalf("Expected metadata.Last = %d after repair, got %d", 3, meta.Last)
|
||||
}
|
||||
|
||||
// Verify that state ID mappings for truncated histories are removed
|
||||
for i := 4; i <= 5; i++ {
|
||||
if rawdb.ReadStateID(diskdb, roots[i-1]) != nil {
|
||||
t.Fatalf("State ID mapping for root %d should be removed", i)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that state ID mappings for remaining histories still exist
|
||||
for i := 1; i <= 3; i++ {
|
||||
if rawdb.ReadStateID(diskdb, roots[i-1]) == nil {
|
||||
t.Fatalf("State ID mapping for root %d should still exist", i)
|
||||
}
|
||||
}
|
||||
|
||||
t.Log("Successfully verified that index metadata is reset after state history truncation")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue