Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions cmd/geth/dbcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package main
import (
"bytes"
"fmt"
"math"
"os"
"os/signal"
"path/filepath"
Expand Down Expand Up @@ -75,6 +76,7 @@ Remove blockchain and state databases`,
dbCompactCmd,
dbGetCmd,
dbDeleteCmd,
dbInspectTrieCmd,
dbPutCmd,
dbGetSlotsCmd,
dbDumpFreezerIndex,
Expand All @@ -93,6 +95,15 @@ Remove blockchain and state databases`,
Usage: "Inspect the storage size for each type of data in the database",
Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`,
}
dbInspectTrieCmd = &cli.Command{
Action: inspectTrie,
Name: "inspect-trie",
ArgsUsage: "<blocknum>",
Flags: slices.Concat([]cli.Flag{utils.ExcludeStorageFlag, utils.TopFlag}, utils.NetworkFlags, utils.DatabaseFlags),
Usage: "Print detailed trie information about the structure of account trie and storage tries.",
Description: `This commands iterates the entrie trie-backed state. If the 'blocknum' is not specified,
the latest block number will be used by default.`,
}
dbCheckStateContentCmd = &cli.Command{
Action: checkStateContent,
Name: "check-state-content",
Expand Down Expand Up @@ -386,6 +397,67 @@ func checkStateContent(ctx *cli.Context) error {
return nil
}

func inspectTrie(ctx *cli.Context) error {
if ctx.NArg() > 1 {
return fmt.Errorf("excessive number of arguments: %v", ctx.Command.ArgsUsage)
}
stack, _ := makeConfigNode(ctx)
db := utils.MakeChainDatabase(ctx, stack, false)
defer stack.Close()
defer db.Close()

var (
trieRoot common.Hash
hash common.Hash
number uint64
)
switch {
case ctx.NArg() == 0 || ctx.Args().Get(0) == "latest":
hash := rawdb.ReadHeadHeaderHash(db)
n, ok := rawdb.ReadHeaderNumber(db, hash)
if !ok {
return fmt.Errorf("could not load head block hash")
}
number = n
case ctx.Args().Get(0) == "snapshot":
trieRoot = rawdb.ReadSnapshotRoot(db)
number = math.MaxUint64
default:
var err error
number, err = strconv.ParseUint(ctx.Args().Get(0), 10, 64)
if err != nil {
return fmt.Errorf("failed to parse blocknum, Args[0]: %v, err: %v", ctx.Args().Get(0), err)
}
}

// Load head block number based on canonical hash, if applicable.
if number != math.MaxUint64 {
hash = rawdb.ReadCanonicalHash(db, number)
if hash == (common.Hash{}) {
return fmt.Errorf("canonical hash for block %d not found", number)
}
blockHeader := rawdb.ReadHeader(db, hash, number)
trieRoot = blockHeader.Root
}
if (trieRoot == common.Hash{}) {
log.Error("Empty root hash")
}

triedb := utils.MakeTrieDatabase(ctx, stack, db, false, true, false)
defer triedb.Close()

log.Info("Inspecting trie", "root", trieRoot, "block", number)
config := &trie.InspectConfig{
NoStorage: ctx.Bool(utils.ExcludeStorageFlag.Name),
TopN: ctx.Int(utils.TopFlag.Name),
}
err := trie.Inspect(triedb, trieRoot, config)
if err != nil {
return err
}
return nil
}

func showDBStats(db ethdb.KeyValueStater) {
stats, err := db.Stat()
if err != nil {
Expand Down
5 changes: 5 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ var (
Usage: "Max number of elements (0 = no limit)",
Value: 0,
}
TopFlag = &cli.IntFlag{
Name: "top",
Usage: "Print the top N results",
Value: 5,
}

SnapshotFlag = &cli.BoolFlag{
Name: "snapshot",
Expand Down
3 changes: 2 additions & 1 deletion core/rawdb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb/memorydb"
"github.com/ethereum/go-ethereum/internal/tablewriter"
"github.com/ethereum/go-ethereum/log"
"golang.org/x/sync/errgroup"
)
Expand Down Expand Up @@ -643,7 +644,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
total.Add(uint64(ancient.size()))
}

table := newTableWriter(os.Stdout)
table := tablewriter.NewWriter(os.Stdout)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the point of moving this to its own package, the tree writer is only used in trie, which is the one importing rawdb.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved it to it's own package because it isn't exported from rawdb. It felt wrong to expose it publicly in that package.

table.SetHeader([]string{"Database", "Category", "Size", "Items"})
table.SetFooter([]string{"", "Total", common.StorageSize(total.Load()).String(), fmt.Sprintf("%d", count.Load())})
table.AppendBulk(stats)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//go:build !tinygo
// +build !tinygo

package rawdb
package tablewriter

import (
"io"
Expand All @@ -28,6 +28,7 @@ import (
// Re-export the real tablewriter types and functions
type Table = tablewriter.Table

func newTableWriter(w io.Writer) *Table {
// Re-export NewWriter.
func NewWriter(w io.Writer) *Table {
return tablewriter.NewWriter(w)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
//go:build tinygo
// +build tinygo

package rawdb
package tablewriter

import (
"errors"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//go:build tinygo
// +build tinygo

package rawdb
package tablewriter

import (
"bytes"
Expand Down
Loading