Skip to content

Commit 6ed387b

Browse files
fynnssMariusVanDerWijden
authored andcommitted
cmd/dbcmd: add inspect trie tool (#2082)
1 parent 429e821 commit 6ed387b

File tree

3 files changed

+410
-0
lines changed

3 files changed

+410
-0
lines changed

cmd/geth/dbcmd.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package main
1919
import (
2020
"bytes"
2121
"fmt"
22+
"math"
2223
"os"
2324
"os/signal"
2425
"path/filepath"
@@ -40,6 +41,7 @@ import (
4041
"github.com/ethereum/go-ethereum/log"
4142
"github.com/ethereum/go-ethereum/rlp"
4243
"github.com/ethereum/go-ethereum/trie"
44+
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
4345
"github.com/ethereum/go-ethereum/triedb"
4446
"github.com/olekukonko/tablewriter"
4547
"github.com/urfave/cli/v2"
@@ -75,6 +77,7 @@ Remove blockchain and state databases`,
7577
dbCompactCmd,
7678
dbGetCmd,
7779
dbDeleteCmd,
80+
dbInspectTrieCmd,
7881
dbPutCmd,
7982
dbGetSlotsCmd,
8083
dbDumpFreezerIndex,
@@ -93,6 +96,17 @@ Remove blockchain and state databases`,
9396
Usage: "Inspect the storage size for each type of data in the database",
9497
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.`,
9598
}
99+
dbInspectTrieCmd = &cli.Command{
100+
Action: inspectTrie,
101+
Name: "inspect-trie",
102+
ArgsUsage: "<blocknum> <jobnum>",
103+
Flags: []cli.Flag{
104+
utils.DataDirFlag,
105+
utils.SyncModeFlag,
106+
},
107+
Usage: "Inspect the MPT tree of the account and contract.",
108+
Description: `This commands iterates the entrie WorldState.`,
109+
}
96110
dbCheckStateContentCmd = &cli.Command{
97111
Action: checkStateContent,
98112
Name: "check-state-content",
@@ -301,6 +315,92 @@ func confirmAndRemoveDB(paths []string, kind string, ctx *cli.Context, removeFla
301315
}
302316
}
303317

318+
func inspectTrie(ctx *cli.Context) error {
319+
if ctx.NArg() < 1 {
320+
return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage)
321+
}
322+
323+
if ctx.NArg() > 3 {
324+
return fmt.Errorf("Max 3 arguments: %v", ctx.Command.ArgsUsage)
325+
}
326+
327+
var (
328+
blockNumber uint64
329+
trieRootHash common.Hash
330+
jobnum uint64
331+
)
332+
333+
stack, _ := makeConfigNode(ctx)
334+
defer stack.Close()
335+
336+
db := utils.MakeChainDatabase(ctx, stack, false)
337+
defer db.Close()
338+
339+
var headerBlockHash common.Hash
340+
if ctx.NArg() >= 1 {
341+
if ctx.Args().Get(0) == "latest" {
342+
headerHash := rawdb.ReadHeadHeaderHash(db)
343+
blockNumber = *(rawdb.ReadHeaderNumber(db, headerHash))
344+
} else if ctx.Args().Get(0) == "snapshot" {
345+
trieRootHash = rawdb.ReadSnapshotRoot(db)
346+
blockNumber = math.MaxUint64
347+
} else {
348+
var err error
349+
blockNumber, err = strconv.ParseUint(ctx.Args().Get(0), 10, 64)
350+
if err != nil {
351+
return fmt.Errorf("failed to Parse blocknum, Args[0]: %v, err: %v", ctx.Args().Get(0), err)
352+
}
353+
}
354+
355+
if ctx.NArg() == 1 {
356+
jobnum = 1000
357+
} else {
358+
var err error
359+
jobnum, err = strconv.ParseUint(ctx.Args().Get(1), 10, 64)
360+
if err != nil {
361+
return fmt.Errorf("failed to Parse jobnum, Args[1]: %v, err: %v", ctx.Args().Get(1), err)
362+
}
363+
}
364+
365+
if blockNumber != math.MaxUint64 {
366+
headerBlockHash = rawdb.ReadCanonicalHash(db, blockNumber)
367+
if headerBlockHash == (common.Hash{}) {
368+
return fmt.Errorf("ReadHeadBlockHash empry hash")
369+
}
370+
blockHeader := rawdb.ReadHeader(db, headerBlockHash, blockNumber)
371+
trieRootHash = blockHeader.Root
372+
}
373+
if (trieRootHash == common.Hash{}) {
374+
log.Error("Empty root hash")
375+
}
376+
fmt.Printf("ReadBlockHeader, root: %v, blocknum: %v\n", trieRootHash, blockNumber)
377+
378+
dbScheme := rawdb.ReadStateScheme(db)
379+
var config *trie.Config
380+
if dbScheme == rawdb.PathScheme {
381+
config = &trie.Config{
382+
PathDB: pathdb.ReadOnly,
383+
}
384+
} else if dbScheme == rawdb.HashScheme {
385+
config = trie.HashDefaults
386+
}
387+
388+
triedb := trie.NewDatabase(db, config)
389+
theTrie, err := trie.New(trie.TrieID(trieRootHash), triedb)
390+
if err != nil {
391+
fmt.Printf("fail to new trie tree, err: %v, rootHash: %v\n", err, trieRootHash.String())
392+
return err
393+
}
394+
theInspect, err := trie.NewInspector(theTrie, triedb, trieRootHash, blockNumber, jobnum)
395+
if err != nil {
396+
return err
397+
}
398+
theInspect.Run()
399+
theInspect.DisplayResult()
400+
}
401+
return nil
402+
}
403+
304404
func inspect(ctx *cli.Context) error {
305405
var (
306406
prefix []byte

0 commit comments

Comments
 (0)