From ef122ca5c68d20aba6febe75c2f94392dae107d5 Mon Sep 17 00:00:00 2001 From: sonhv0212 Date: Tue, 17 Dec 2024 17:56:06 +0700 Subject: [PATCH] cmd/db: Add inspect enode db --- cmd/ronin/dbcmd.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ p2p/enode/nodedb.go | 23 +++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/cmd/ronin/dbcmd.go b/cmd/ronin/dbcmd.go index 56fe03a3bd..02a9fb43d1 100644 --- a/cmd/ronin/dbcmd.go +++ b/cmd/ronin/dbcmd.go @@ -33,9 +33,13 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/console/prompt" + "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/p2p/enr" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" "github.com/urfave/cli/v2" ) @@ -243,8 +247,48 @@ WARNING: This is a low-level operation which may cause database corruption!`, }, Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.", } + inspectDHTCommand = &cli.Command{ + Action: inspectEnodeDB, + Name: "inspect-enode-db", + Usage: "Inspect nodes in enode db", + Flags: []cli.Flag{ + utils.DataDirFlag, + }, + Category: "DATABASE COMMANDS", + } ) +func inspectEnodeDB(ctx *cli.Context) error { + path := ctx.String(utils.DataDirFlag.Name) + db, err := enode.OpenDB(path) + if err != nil { + return err + } + + count := 0 + unknownNodes := []*enode.Node{} + db.IterateNodes(func(n *enode.Node) error { + count += 1 + var eth struct { + ForkID forkid.ID + Tail []rlp.RawValue `rlp:"tail"` + } + if n.Record().Load(enr.WithEntry("eth", ð)) == nil { + log.Info("Node", "ID", n.ID(), "IP", n.IP(), "UDP", n.UDP(), "TCP", n.TCP(), "eth", eth) + } else { + unknownNodes = append(unknownNodes, n) + } + return nil + }) + for _, n := range unknownNodes { + log.Info("Unkown node", "ID", n.ID(), "IP", n.IP(), "UDP", n.UDP(), "TCP", n.TCP()) + } + + log.Info("Total nodes", "count", count) + + return nil +} + func removeDB(ctx *cli.Context) error { stack, config := makeConfigNode(ctx) diff --git a/p2p/enode/nodedb.go b/p2p/enode/nodedb.go index d1712f7597..0be448776c 100644 --- a/p2p/enode/nodedb.go +++ b/p2p/enode/nodedb.go @@ -26,6 +26,7 @@ import ( "sync" "time" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb/errors" @@ -481,6 +482,28 @@ seek: return nodes } +// Testing purposes only. +func (db *DB) IterateNodes(f func(n *Node) error) { + it := db.lvl.NewIterator(util.BytesPrefix([]byte(dbNodePrefix)), nil) + defer it.Release() + + for it.Next() { + id, rest := splitNodeKey(it.Key()) + if string(rest) != dbDiscoverRoot { + continue + } + node := mustDecodeNode(id[:], it.Value()) + if node == nil { + return + } + + if err := f(node); err != nil { + log.Error("error during node iteration", "err", err) + return + } + } +} + // reads the next node record from the iterator, skipping over other // database entries. func nextNode(it iterator.Iterator) *Node {