Skip to content

Commit

Permalink
cmd/geth, core/rawdb: add dbDeleteTrieState
Browse files Browse the repository at this point in the history
  • Loading branch information
weiihann authored and buddh0 committed Mar 20, 2024
1 parent 74d2054 commit 6978f00
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 0 deletions.
86 changes: 86 additions & 0 deletions cmd/geth/dbcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ Remove blockchain and state databases`,
dbCompactCmd,
dbGetCmd,
dbDeleteCmd,
dbDeleteTrieStateCmd,
dbInspectTrieCmd,
dbPutCmd,
dbGetSlotsCmd,
Expand Down Expand Up @@ -206,6 +207,15 @@ corruption if it is aborted during execution'!`,
Description: `This command deletes the specified database key from the database.
WARNING: This is a low-level operation which may cause database corruption!`,
}
dbDeleteTrieStateCmd = &cli.Command{
Action: dbDeleteTrieState,
Name: "delete-trie-state",
Usage: "Delete all trie state key-value pairs from the database and the ancient state. Does not support hash-based state scheme.",
Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag,
}, utils.NetworkFlags, utils.DatabaseFlags),
Description: `This command deletes all trie state key-value pairs from the database and the ancient state.`,
}
dbPutCmd = &cli.Command{
Action: dbPut,
Name: "put",
Expand Down Expand Up @@ -810,6 +820,82 @@ func dbDelete(ctx *cli.Context) error {
return nil
}

// dbDeleteTrieState deletes all trie state related key-value pairs from the database and the ancient state store.
func dbDeleteTrieState(ctx *cli.Context) error {
if ctx.NArg() > 0 {
return fmt.Errorf("no arguments required")
}

stack, config := makeConfigNode(ctx)
defer stack.Close()

db := utils.MakeChainDatabase(ctx, stack, false, false)
defer db.Close()

var (
err error
start = time.Now()
)

// If separate trie db exists, delete all files in the db folder
if db.StateStore() != nil {
statePath := filepath.Join(stack.ResolvePath("chaindata"), "state")
log.Info("Removing separate trie database", "path", statePath)
err = filepath.Walk(statePath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if path != statePath {
fileInfo, err := os.Lstat(path)
if err != nil {
return err
}
if !fileInfo.IsDir() {
os.Remove(path)
}
}
return nil
})
log.Info("Separate trie database deleted", "err", err, "elapsed", common.PrettyDuration(time.Since(start)))
return err
}

// Delete KV pairs from the database
err = rawdb.DeleteTrieState(db)
if err != nil {
return err
}

// Remove the full node ancient database
dbPath := config.Eth.DatabaseFreezer
switch {
case dbPath == "":
dbPath = filepath.Join(stack.ResolvePath("chaindata"), "ancient/state")
case !filepath.IsAbs(dbPath):
dbPath = config.Node.ResolvePath(dbPath)
}

if !common.FileExist(dbPath) {
return nil
}

log.Info("Removing ancient state database", "path", dbPath)
start = time.Now()
filepath.Walk(dbPath, func(path string, info os.FileInfo, err error) error {
if dbPath == path {
return nil
}
if !info.IsDir() {
os.Remove(path)
return nil
}
return filepath.SkipDir
})
log.Info("State database successfully deleted", "path", dbPath, "elapsed", common.PrettyDuration(time.Since(start)))

return nil
}

// dbPut overwrite a value in the database
func dbPut(ctx *cli.Context) error {
if ctx.NArg() != 2 {
Expand Down
56 changes: 56 additions & 0 deletions core/rawdb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,62 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
return nil
}

func DeleteTrieState(db ethdb.Database) error {
var (
it ethdb.Iterator
batch = db.NewBatch()
start = time.Now()
logged = time.Now()
count int64
key []byte
)

prefixKeys := map[string]func([]byte) bool{
string(trieNodeAccountPrefix): IsAccountTrieNode,
string(trieNodeStoragePrefix): IsStorageTrieNode,
string(stateIDPrefix): func(key []byte) bool { return len(key) == len(stateIDPrefix)+common.HashLength },
}

for prefix, isValid := range prefixKeys {
it = db.NewIterator([]byte(prefix), nil)

for it.Next() {
key = it.Key()
if !isValid(key) {
continue
}

batch.Delete(it.Key())
if batch.ValueSize() > ethdb.IdealBatchSize {
if err := batch.Write(); err != nil {
it.Release()
return err
}
batch.Reset()
}

count++
if time.Since(logged) > 8*time.Second {
log.Info("Deleting trie state", "count", count, "elapsed", common.PrettyDuration(time.Since(start)))
logged = time.Now()
}
}

it.Release()
}

if batch.ValueSize() > 0 {
if err := batch.Write(); err != nil {
return err
}
batch.Reset()
}

log.Info("Deleted trie state", "count", count, "elapsed", common.PrettyDuration(time.Since(start)))

return nil
}

// printChainMetadata prints out chain metadata to stderr.
func printChainMetadata(db ethdb.KeyValueStore) {
fmt.Fprintf(os.Stderr, "Chain metadata\n")
Expand Down

0 comments on commit 6978f00

Please sign in to comment.