mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
cmd/devp2p: WIP nodeset filter
This commit is contained in:
parent
83e2b8547b
commit
bed03700ff
2 changed files with 146 additions and 0 deletions
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -55,6 +56,10 @@ func writeNodesJSON(file string, nodes nodeSet) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
}
|
}
|
||||||
|
if file == "-" {
|
||||||
|
os.Stdout.Write(nodesJSON)
|
||||||
|
return
|
||||||
|
}
|
||||||
if err := ioutil.WriteFile(file, nodesJSON, 0644); err != nil {
|
if err := ioutil.WriteFile(file, nodesJSON, 0644); err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,12 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core/forkid"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"gopkg.in/urfave/cli.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -28,6 +33,7 @@ var (
|
||||||
Usage: "Node set tools",
|
Usage: "Node set tools",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []cli.Command{
|
||||||
nodesetInfoCommand,
|
nodesetInfoCommand,
|
||||||
|
nodesetFilterCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
nodesetInfoCommand = cli.Command{
|
nodesetInfoCommand = cli.Command{
|
||||||
|
|
@ -36,6 +42,14 @@ var (
|
||||||
Action: nodesetInfo,
|
Action: nodesetInfo,
|
||||||
ArgsUsage: "<nodes.json>",
|
ArgsUsage: "<nodes.json>",
|
||||||
}
|
}
|
||||||
|
nodesetFilterCommand = cli.Command{
|
||||||
|
Name: "filter",
|
||||||
|
Usage: "Filters a node set",
|
||||||
|
Action: nodesetFilter,
|
||||||
|
ArgsUsage: "<nodes.json> filters..",
|
||||||
|
|
||||||
|
SkipFlagParsing: true,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func nodesetInfo(ctx *cli.Context) error {
|
func nodesetInfo(ctx *cli.Context) error {
|
||||||
|
|
@ -47,3 +61,130 @@ func nodesetInfo(ctx *cli.Context) error {
|
||||||
fmt.Printf("Set contains %d nodes.\n", len(ns))
|
fmt.Printf("Set contains %d nodes.\n", len(ns))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func nodesetFilter(ctx *cli.Context) error {
|
||||||
|
if ctx.NArg() < 1 {
|
||||||
|
return fmt.Errorf("need nodes file as argument")
|
||||||
|
}
|
||||||
|
ns := loadNodesJSON(ctx.Args().First())
|
||||||
|
filter, err := andFilter(ctx.Args().Tail())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make(nodeSet)
|
||||||
|
for id, n := range ns {
|
||||||
|
if filter(n) {
|
||||||
|
result[id] = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeNodesJSON("-", result)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type nodeFilter func(nodeJSON) bool
|
||||||
|
|
||||||
|
type nodeFilterC struct {
|
||||||
|
narg int
|
||||||
|
fn func([]string) (nodeFilter, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var filterFlags = map[string]nodeFilterC{
|
||||||
|
"-ip": {1, ipFilter},
|
||||||
|
"-min-age": {1, minAgeFilter},
|
||||||
|
"-eth-network": {1, ethFilter},
|
||||||
|
"-les-server": {0, lesFilter},
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFilters(args []string) ([]nodeFilter, error) {
|
||||||
|
var filters []nodeFilter
|
||||||
|
for len(args) > 0 {
|
||||||
|
fc, ok := filterFlags[args[0]]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid filter %q", args[0])
|
||||||
|
}
|
||||||
|
if len(args) < fc.narg {
|
||||||
|
return nil, fmt.Errorf("filter %q wants %d arguments, have %d", args[0], fc.narg, len(args))
|
||||||
|
}
|
||||||
|
filter, err := fc.fn(args[1:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s: %v", args[0], err)
|
||||||
|
}
|
||||||
|
filters = append(filters, filter)
|
||||||
|
args = args[fc.narg+1:]
|
||||||
|
}
|
||||||
|
return filters, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func andFilter(args []string) (nodeFilter, error) {
|
||||||
|
checks, err := parseFilters(args)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f := func(n nodeJSON) bool {
|
||||||
|
for _, filter := range checks {
|
||||||
|
if !filter(n) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ipFilter(args []string) (nodeFilter, error) {
|
||||||
|
_, cidr, err := net.ParseCIDR(args[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f := func(n nodeJSON) bool { return cidr.Contains(n.N.IP()) }
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func minAgeFilter(args []string) (nodeFilter, error) {
|
||||||
|
minage, err := time.ParseDuration(args[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f := func(n nodeJSON) bool {
|
||||||
|
age := n.LastSeen.Sub(n.FirstSeen)
|
||||||
|
return age >= minage
|
||||||
|
}
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ethFilter(args []string) (nodeFilter, error) {
|
||||||
|
// var config *params.ChainConfig
|
||||||
|
// switch args[0] {
|
||||||
|
// case "mainnet":
|
||||||
|
// config = params.MainnetChainConfig
|
||||||
|
// case "rinkeby":
|
||||||
|
// config = params.RinkebyChainConfig
|
||||||
|
// case "goerli":
|
||||||
|
// config = params.GoerliChainConfig
|
||||||
|
// default:
|
||||||
|
// return nil, fmt.Errorf("unknown network %q", args[0])
|
||||||
|
// }
|
||||||
|
|
||||||
|
forkFilter := forkid.NewFilter(nil)
|
||||||
|
f := func(n nodeJSON) bool {
|
||||||
|
var eth struct {
|
||||||
|
ForkID forkid.ID
|
||||||
|
_ []rlp.RawValue `rlp:"tail"`
|
||||||
|
}
|
||||||
|
if n.N.Load(enr.WithEntry("eth", ð)) != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return forkFilter(eth.ForkID) == nil
|
||||||
|
}
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func lesFilter(args []string) (nodeFilter, error) {
|
||||||
|
f := func(n nodeJSON) bool {
|
||||||
|
var les struct {
|
||||||
|
_ []rlp.RawValue `rlp:"tail"`
|
||||||
|
}
|
||||||
|
return n.N.Load(enr.WithEntry("les", &les)) == nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue