cmd/geth: return storage slot count from traverseStorage

Have traverseStorage return the number of slots traversed and
accumulate it in traverseState and traverseRawState so progress logs
report the correct total slot count.
This commit is contained in:
Weixie Cui 2026-07-05 10:57:02 +08:00
parent e3b6d0c86f
commit bfbc2fcfae

View file

@ -516,11 +516,11 @@ func lookupAccount(accountHash common.Hash, tr *trie.Trie) (*types.StateAccount,
return &acc, nil return &acc, nil
} }
func traverseStorage(id *trie.ID, db *triedb.Database, report bool, detail bool) error { func traverseStorage(id *trie.ID, db *triedb.Database, report bool, detail bool) (int, error) {
tr, err := trie.NewStateTrie(id, db) tr, err := trie.NewStateTrie(id, db)
if err != nil { if err != nil {
log.Error("Failed to open storage trie", "account", id.Owner, "root", id.Root, "err", err) log.Error("Failed to open storage trie", "account", id.Owner, "root", id.Root, "err", err)
return err return 0, err
} }
var ( var (
slots int slots int
@ -531,7 +531,7 @@ func traverseStorage(id *trie.ID, db *triedb.Database, report bool, detail bool)
it, err := tr.NodeIterator(nil) it, err := tr.NodeIterator(nil)
if err != nil { if err != nil {
log.Error("Failed to open storage iterator", "account", id.Owner, "root", id.Root, "err", err) log.Error("Failed to open storage iterator", "account", id.Owner, "root", id.Root, "err", err)
return err return 0, err
} }
logger := log.Debug logger := log.Debug
if report { if report {
@ -550,14 +550,14 @@ func traverseStorage(id *trie.ID, db *triedb.Database, report bool, detail bool)
} }
if iter.Err != nil { if iter.Err != nil {
log.Error("Failed to traverse storage trie", "root", id.Root, "err", iter.Err) log.Error("Failed to traverse storage trie", "root", id.Root, "err", iter.Err)
return iter.Err return 0, iter.Err
} }
logger("Storage is complete", "account", id.Owner, "slots", slots, "elapsed", common.PrettyDuration(time.Since(start))) logger("Storage is complete", "account", id.Owner, "slots", slots, "elapsed", common.PrettyDuration(time.Since(start)))
} else { } else {
reader, err := db.NodeReader(id.StateRoot) reader, err := db.NodeReader(id.StateRoot)
if err != nil { if err != nil {
log.Error("Failed to open state reader", "err", err) log.Error("Failed to open state reader", "err", err)
return err return 0, err
} }
var ( var (
buffer = make([]byte, 32) buffer = make([]byte, 32)
@ -573,14 +573,14 @@ func traverseStorage(id *trie.ID, db *triedb.Database, report bool, detail bool)
blob, _ := reader.Node(id.Owner, it.Path(), node) blob, _ := reader.Node(id.Owner, it.Path(), node)
if len(blob) == 0 { if len(blob) == 0 {
log.Error("Missing trie node(storage)", "hash", node) log.Error("Missing trie node(storage)", "hash", node)
return errors.New("missing storage") return 0, errors.New("missing storage")
} }
hasher.Reset() hasher.Reset()
hasher.Write(blob) hasher.Write(blob)
hasher.Read(buffer) hasher.Read(buffer)
if !bytes.Equal(buffer, node.Bytes()) { if !bytes.Equal(buffer, node.Bytes()) {
log.Error("Invalid trie node(storage)", "hash", node.Hex(), "value", blob) log.Error("Invalid trie node(storage)", "hash", node.Hex(), "value", blob)
return errors.New("invalid storage node") return 0, errors.New("invalid storage node")
} }
} }
if it.Leaf() { if it.Leaf() {
@ -593,11 +593,11 @@ func traverseStorage(id *trie.ID, db *triedb.Database, report bool, detail bool)
} }
if err := it.Error(); err != nil { if err := it.Error(); err != nil {
log.Error("Failed to traverse storage trie", "root", id.Root, "err", err) log.Error("Failed to traverse storage trie", "root", id.Root, "err", err)
return err return 0, err
} }
logger("Storage is complete", "account", id.Owner, "nodes", nodes, "slots", slots, "elapsed", common.PrettyDuration(time.Since(start))) logger("Storage is complete", "account", id.Owner, "nodes", nodes, "slots", slots, "elapsed", common.PrettyDuration(time.Since(start)))
} }
return nil return slots, nil
} }
// traverseState is a helper function used for pruning verification. // traverseState is a helper function used for pruning verification.
@ -659,7 +659,8 @@ func traverseState(ctx *cli.Context) error {
log.Info("Account has no storage", "hash", accountHash) log.Info("Account has no storage", "hash", accountHash)
return nil return nil
} }
return traverseStorage(trie.StorageTrieID(root, accountHash, acc.Root), triedb, true, false) _, err = traverseStorage(trie.StorageTrieID(root, accountHash, acc.Root), triedb, true, false)
return err
} }
t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb) t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb)
if err != nil { if err != nil {
@ -687,10 +688,11 @@ func traverseState(ctx *cli.Context) error {
return err return err
} }
if acc.Root != types.EmptyRootHash { if acc.Root != types.EmptyRootHash {
err := traverseStorage(trie.StorageTrieID(root, common.BytesToHash(accIter.Key), acc.Root), triedb, false, false) nSlots, err := traverseStorage(trie.StorageTrieID(root, common.BytesToHash(accIter.Key), acc.Root), triedb, false, false)
if err != nil { if err != nil {
return err return err
} }
slots += nSlots
} }
if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) { if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) {
if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) { if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) {
@ -772,7 +774,8 @@ func traverseRawState(ctx *cli.Context) error {
log.Info("Account has no storage", "hash", accountHash) log.Info("Account has no storage", "hash", accountHash)
return nil return nil
} }
return traverseStorage(trie.StorageTrieID(root, accountHash, acc.Root), triedb, true, true) _, err = traverseStorage(trie.StorageTrieID(root, accountHash, acc.Root), triedb, true, true)
return err
} }
t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb) t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb)
if err != nil { if err != nil {
@ -829,10 +832,11 @@ func traverseRawState(ctx *cli.Context) error {
return errors.New("invalid account") return errors.New("invalid account")
} }
if acc.Root != types.EmptyRootHash { if acc.Root != types.EmptyRootHash {
err := traverseStorage(trie.StorageTrieID(root, common.BytesToHash(accIter.LeafKey()), acc.Root), triedb, false, true) nSlots, err := traverseStorage(trie.StorageTrieID(root, common.BytesToHash(accIter.LeafKey()), acc.Root), triedb, false, true)
if err != nil { if err != nil {
return err return err
} }
slots += nSlots
} }
if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) { if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) {
if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) { if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) {