Skip to content

Commit

Permalink
cli: add command for traversing MPT for the current state
Browse files Browse the repository at this point in the history
Traverse MPT for the current state and dump key/value pairs into file.

Close #3519

Signed-off-by: Ekaterina Pavlova <[email protected]>
  • Loading branch information
AliceInHunterland committed Jul 24, 2024
1 parent 2c12563 commit 043e9f0
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 0 deletions.
95 changes: 95 additions & 0 deletions cli/server/mptdump.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package server

import (
"encoding/hex"
"encoding/json"
"fmt"
"os"

"github.com/nspcc-dev/neo-go/cli/options"
"github.com/nspcc-dev/neo-go/pkg/core/mpt"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/urfave/cli/v2"
"go.uber.org/zap"
)

// KVPair represents a key-value pair.
type KVPair struct {
Key string `json:"key"`
Value string `json:"value"`
}

// TraverseMPT collects key-value pairs from the TrieStore and returns them.
func TraverseMPT(store *mpt.TrieStore) ([]KVPair, error) {
var kvPairs []KVPair
prefix := []byte{byte(storage.STStorage)}
rng := storage.SeekRange{Prefix: prefix}

store.Seek(rng, func(k, v []byte) bool {
kvPairs = append(kvPairs, KVPair{
Key: hex.EncodeToString(k),
Value: hex.EncodeToString(v),
})
return true
})

return kvPairs, nil
}

// DumpKVPairsToFile dumps the collected key-value pairs into a file.
func DumpKVPairsToFile(kvPairs []KVPair, filename string) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()

encoder := json.NewEncoder(file)
encoder.SetIndent("", " ")
err = encoder.Encode(kvPairs)
if err != nil {
return err
}

return nil
}

// traverseMPT handles the CLI command to traverse the MPT and dump key-value pairs.
func traverseMPT(ctx *cli.Context) error {
logger := zap.NewExample()
cfg, err := options.GetConfigFromContext(ctx)
if err != nil {
return cli.Exit(err, 1)
}

chain, store, err := initBlockChain(cfg, logger)
if err != nil {
return cli.Exit(err, 1)
}
defer store.Close()
defer chain.Close()

stateModule := chain.GetStateModule()
stateRoot := stateModule.CurrentLocalStateRoot()
stateRootHash := stateRoot

trieStore := mpt.NewTrieStore(stateRootHash, mpt.ModeLatest, store)

kvPairs, err := TraverseMPT(trieStore)
if err != nil {
return cli.Exit(err, 1)
}

outputFile := ctx.String("out")
if outputFile == "" {
outputFile = "kv_pairs.json"
}

err = DumpKVPairsToFile(kvPairs, outputFile)
if err != nil {
return cli.Exit(err, 1)
}

fmt.Println("MPT key-value pairs successfully dumped to", outputFile)
return nil
}
13 changes: 13 additions & 0 deletions cli/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,19 @@ func NewCommands() []*cli.Command {
Action: resetDB,
Flags: cfgHeightFlags,
},
{
Name: "traverse",
Usage: "Traverse the MPT and dump key-value pairs to a file",
UsageText: "neo-go db traverse [--out file] [--config-path path] [-p/-m/-t] [--config-file file]",
Action: traverseMPT,
Flags: append(cfgFlags,
&cli.StringFlag{
Name: "out",
Aliases: []string{"o"},
Usage: "Output file (default: kv_pairs.json)",
},
),
},
},
},
}
Expand Down

0 comments on commit 043e9f0

Please sign in to comment.