discv5cmd.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright 2019 The go-ethereum Authors
  2. // This file is part of go-ethereum.
  3. //
  4. // go-ethereum is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // go-ethereum is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
  16. package main
  17. import (
  18. "fmt"
  19. "os"
  20. "time"
  21. "github.com/ethereum/go-ethereum/cmd/devp2p/internal/v5test"
  22. "github.com/ethereum/go-ethereum/common"
  23. "github.com/ethereum/go-ethereum/internal/utesting"
  24. "github.com/ethereum/go-ethereum/log"
  25. "github.com/ethereum/go-ethereum/p2p/discover"
  26. "gopkg.in/urfave/cli.v1"
  27. )
  28. var (
  29. discv5Command = cli.Command{
  30. Name: "discv5",
  31. Usage: "Node Discovery v5 tools",
  32. Subcommands: []cli.Command{
  33. discv5PingCommand,
  34. discv5ResolveCommand,
  35. discv5CrawlCommand,
  36. discv5TestCommand,
  37. discv5ListenCommand,
  38. },
  39. }
  40. discv5PingCommand = cli.Command{
  41. Name: "ping",
  42. Usage: "Sends ping to a node",
  43. Action: discv5Ping,
  44. }
  45. discv5ResolveCommand = cli.Command{
  46. Name: "resolve",
  47. Usage: "Finds a node in the DHT",
  48. Action: discv5Resolve,
  49. Flags: []cli.Flag{bootnodesFlag},
  50. }
  51. discv5CrawlCommand = cli.Command{
  52. Name: "crawl",
  53. Usage: "Updates a nodes.json file with random nodes found in the DHT",
  54. Action: discv5Crawl,
  55. Flags: []cli.Flag{bootnodesFlag, crawlTimeoutFlag},
  56. }
  57. discv5TestCommand = cli.Command{
  58. Name: "test",
  59. Usage: "Runs protocol tests against a node",
  60. Action: discv5Test,
  61. Flags: []cli.Flag{testPatternFlag, testListen1Flag, testListen2Flag},
  62. }
  63. discv5ListenCommand = cli.Command{
  64. Name: "listen",
  65. Usage: "Runs a node",
  66. Action: discv5Listen,
  67. Flags: []cli.Flag{
  68. bootnodesFlag,
  69. nodekeyFlag,
  70. nodedbFlag,
  71. listenAddrFlag,
  72. },
  73. }
  74. )
  75. func discv5Ping(ctx *cli.Context) error {
  76. n := getNodeArg(ctx)
  77. disc := startV5(ctx)
  78. defer disc.Close()
  79. fmt.Println(disc.Ping(n))
  80. return nil
  81. }
  82. func discv5Resolve(ctx *cli.Context) error {
  83. n := getNodeArg(ctx)
  84. disc := startV5(ctx)
  85. defer disc.Close()
  86. fmt.Println(disc.Resolve(n))
  87. return nil
  88. }
  89. func discv5Crawl(ctx *cli.Context) error {
  90. if ctx.NArg() < 1 {
  91. return fmt.Errorf("need nodes file as argument")
  92. }
  93. nodesFile := ctx.Args().First()
  94. var inputSet nodeSet
  95. if common.FileExist(nodesFile) {
  96. inputSet = loadNodesJSON(nodesFile)
  97. }
  98. disc := startV5(ctx)
  99. defer disc.Close()
  100. c := newCrawler(inputSet, disc, disc.RandomNodes())
  101. c.revalidateInterval = 10 * time.Minute
  102. output := c.run(ctx.Duration(crawlTimeoutFlag.Name))
  103. writeNodesJSON(nodesFile, output)
  104. return nil
  105. }
  106. func discv5Test(ctx *cli.Context) error {
  107. // Disable logging unless explicitly enabled.
  108. if !ctx.GlobalIsSet("verbosity") && !ctx.GlobalIsSet("vmodule") {
  109. log.Root().SetHandler(log.DiscardHandler())
  110. }
  111. // Filter and run test cases.
  112. suite := &v5test.Suite{
  113. Dest: getNodeArg(ctx),
  114. Listen1: ctx.String(testListen1Flag.Name),
  115. Listen2: ctx.String(testListen2Flag.Name),
  116. }
  117. tests := suite.AllTests()
  118. if ctx.IsSet(testPatternFlag.Name) {
  119. tests = utesting.MatchTests(tests, ctx.String(testPatternFlag.Name))
  120. }
  121. results := utesting.RunTests(tests, os.Stdout)
  122. if fails := utesting.CountFailures(results); fails > 0 {
  123. return fmt.Errorf("%v/%v tests passed.", len(tests)-fails, len(tests))
  124. }
  125. fmt.Printf("%v/%v passed\n", len(tests), len(tests))
  126. return nil
  127. }
  128. func discv5Listen(ctx *cli.Context) error {
  129. disc := startV5(ctx)
  130. defer disc.Close()
  131. fmt.Println(disc.Self())
  132. select {}
  133. }
  134. // startV5 starts an ephemeral discovery v5 node.
  135. func startV5(ctx *cli.Context) *discover.UDPv5 {
  136. ln, config := makeDiscoveryConfig(ctx)
  137. socket := listen(ln, ctx.String(listenAddrFlag.Name))
  138. disc, err := discover.ListenV5(socket, ln, config)
  139. if err != nil {
  140. exit(err)
  141. }
  142. return disc
  143. }