From 59ac3c9fd30eb4134da60d0549cfd84b27a3a3f7 Mon Sep 17 00:00:00 2001
From: Martin Holst Swende <martin@swende.se>
Date: Tue, 30 Mar 2021 13:57:21 +0200
Subject: [PATCH] cmd/geth: add db dumptrie command (#22563)

Adds the command "geth db dumptrie <root> <seek> <max>", to better help investigate the trie data
---
 cmd/geth/dbcmd.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go
index 078cad53b..db1fb0b80 100644
--- a/cmd/geth/dbcmd.go
+++ b/cmd/geth/dbcmd.go
@@ -20,6 +20,7 @@ import (
 	"fmt"
 	"os"
 	"path/filepath"
+	"strconv"
 	"time"
 
 	"github.com/ethereum/go-ethereum/cmd/utils"
@@ -29,6 +30,7 @@ import (
 	"github.com/ethereum/go-ethereum/core/rawdb"
 	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/log"
+	"github.com/ethereum/go-ethereum/trie"
 	"gopkg.in/urfave/cli.v1"
 )
 
@@ -57,6 +59,7 @@ Remove blockchain and state databases`,
 			dbGetCmd,
 			dbDeleteCmd,
 			dbPutCmd,
+			dbGetSlotsCmd,
 		},
 	}
 	dbInspectCmd = cli.Command{
@@ -158,6 +161,22 @@ WARNING: This is a low-level operation which may cause database corruption!`,
 		Description: `This command sets a given database key to the given value. 
 WARNING: This is a low-level operation which may cause database corruption!`,
 	}
+	dbGetSlotsCmd = cli.Command{
+		Action:    utils.MigrateFlags(dbDumpTrie),
+		Name:      "dumptrie",
+		Usage:     "Show the storage key/values of a given storage trie",
+		ArgsUsage: "<hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>",
+		Flags: []cli.Flag{
+			utils.DataDirFlag,
+			utils.SyncModeFlag,
+			utils.MainnetFlag,
+			utils.RopstenFlag,
+			utils.RinkebyFlag,
+			utils.GoerliFlag,
+			utils.YoloV3Flag,
+		},
+		Description: "This command looks up the specified database key from the database.",
+	}
 )
 
 func removeDB(ctx *cli.Context) error {
@@ -380,3 +399,53 @@ func dbPut(ctx *cli.Context) error {
 	}
 	return db.Put(key, value)
 }
+
+// dbDumpTrie shows the key-value slots of a given storage trie
+func dbDumpTrie(ctx *cli.Context) error {
+	if ctx.NArg() < 1 {
+		return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage)
+	}
+	stack, _ := makeConfigNode(ctx)
+	defer stack.Close()
+
+	db := utils.MakeChainDatabase(ctx, stack, true)
+	defer db.Close()
+	var (
+		root  []byte
+		start []byte
+		max   = int64(-1)
+		err   error
+	)
+	if root, err = hexutil.Decode(ctx.Args().Get(0)); err != nil {
+		log.Info("Could not decode the root", "error", err)
+		return err
+	}
+	stRoot := common.BytesToHash(root)
+	if ctx.NArg() >= 2 {
+		if start, err = hexutil.Decode(ctx.Args().Get(1)); err != nil {
+			log.Info("Could not decode the seek position", "error", err)
+			return err
+		}
+	}
+	if ctx.NArg() >= 3 {
+		if max, err = strconv.ParseInt(ctx.Args().Get(2), 10, 64); err != nil {
+			log.Info("Could not decode the max count", "error", err)
+			return err
+		}
+	}
+	theTrie, err := trie.New(stRoot, trie.NewDatabase(db))
+	if err != nil {
+		return err
+	}
+	var count int64
+	it := trie.NewIterator(theTrie.NodeIterator(start))
+	for it.Next() {
+		if max > 0 && count == max {
+			fmt.Printf("Exiting after %d values\n", count)
+			break
+		}
+		fmt.Printf("  %d. key %#x: %#x\n", count, it.Key, it.Value)
+		count++
+	}
+	return it.Err
+}
-- 
GitLab