cmd/devp2p: add --extaddr flag (#26312)
The new flag allows configuring an explicit endpoint which is to be announced in the DHT. This feature was originally developed for the discv5 wormhole experiment (#25798), but it's useful in other contexts as well.
This commit is contained in:
parent
01953b3470
commit
b44abf56a9
@ -19,6 +19,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -50,34 +51,34 @@ var (
|
|||||||
Usage: "Sends ping to a node",
|
Usage: "Sends ping to a node",
|
||||||
Action: discv4Ping,
|
Action: discv4Ping,
|
||||||
ArgsUsage: "<node>",
|
ArgsUsage: "<node>",
|
||||||
Flags: v4NodeFlags,
|
Flags: discoveryNodeFlags,
|
||||||
}
|
}
|
||||||
discv4RequestRecordCommand = &cli.Command{
|
discv4RequestRecordCommand = &cli.Command{
|
||||||
Name: "requestenr",
|
Name: "requestenr",
|
||||||
Usage: "Requests a node record using EIP-868 enrRequest",
|
Usage: "Requests a node record using EIP-868 enrRequest",
|
||||||
Action: discv4RequestRecord,
|
Action: discv4RequestRecord,
|
||||||
ArgsUsage: "<node>",
|
ArgsUsage: "<node>",
|
||||||
Flags: v4NodeFlags,
|
Flags: discoveryNodeFlags,
|
||||||
}
|
}
|
||||||
discv4ResolveCommand = &cli.Command{
|
discv4ResolveCommand = &cli.Command{
|
||||||
Name: "resolve",
|
Name: "resolve",
|
||||||
Usage: "Finds a node in the DHT",
|
Usage: "Finds a node in the DHT",
|
||||||
Action: discv4Resolve,
|
Action: discv4Resolve,
|
||||||
ArgsUsage: "<node>",
|
ArgsUsage: "<node>",
|
||||||
Flags: v4NodeFlags,
|
Flags: discoveryNodeFlags,
|
||||||
}
|
}
|
||||||
discv4ResolveJSONCommand = &cli.Command{
|
discv4ResolveJSONCommand = &cli.Command{
|
||||||
Name: "resolve-json",
|
Name: "resolve-json",
|
||||||
Usage: "Re-resolves nodes in a nodes.json file",
|
Usage: "Re-resolves nodes in a nodes.json file",
|
||||||
Action: discv4ResolveJSON,
|
Action: discv4ResolveJSON,
|
||||||
Flags: v4NodeFlags,
|
Flags: discoveryNodeFlags,
|
||||||
ArgsUsage: "<nodes.json file>",
|
ArgsUsage: "<nodes.json file>",
|
||||||
}
|
}
|
||||||
discv4CrawlCommand = &cli.Command{
|
discv4CrawlCommand = &cli.Command{
|
||||||
Name: "crawl",
|
Name: "crawl",
|
||||||
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
||||||
Action: discv4Crawl,
|
Action: discv4Crawl,
|
||||||
Flags: flags.Merge(v4NodeFlags, []cli.Flag{crawlTimeoutFlag}),
|
Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{crawlTimeoutFlag}),
|
||||||
}
|
}
|
||||||
discv4TestCommand = &cli.Command{
|
discv4TestCommand = &cli.Command{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
@ -110,6 +111,10 @@ var (
|
|||||||
Name: "addr",
|
Name: "addr",
|
||||||
Usage: "Listening address",
|
Usage: "Listening address",
|
||||||
}
|
}
|
||||||
|
extAddrFlag = &cli.StringFlag{
|
||||||
|
Name: "extaddr",
|
||||||
|
Usage: "UDP endpoint announced in ENR. You can provide a bare IP address or IP:port as the value of this flag.",
|
||||||
|
}
|
||||||
crawlTimeoutFlag = &cli.DurationFlag{
|
crawlTimeoutFlag = &cli.DurationFlag{
|
||||||
Name: "timeout",
|
Name: "timeout",
|
||||||
Usage: "Time limit for the crawl.",
|
Usage: "Time limit for the crawl.",
|
||||||
@ -122,11 +127,12 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var v4NodeFlags = []cli.Flag{
|
var discoveryNodeFlags = []cli.Flag{
|
||||||
bootnodesFlag,
|
bootnodesFlag,
|
||||||
nodekeyFlag,
|
nodekeyFlag,
|
||||||
nodedbFlag,
|
nodedbFlag,
|
||||||
listenAddrFlag,
|
listenAddrFlag,
|
||||||
|
extAddrFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
func discv4Ping(ctx *cli.Context) error {
|
func discv4Ping(ctx *cli.Context) error {
|
||||||
@ -228,7 +234,7 @@ func discv4Test(ctx *cli.Context) error {
|
|||||||
// startV4 starts an ephemeral discovery V4 node.
|
// startV4 starts an ephemeral discovery V4 node.
|
||||||
func startV4(ctx *cli.Context) *discover.UDPv4 {
|
func startV4(ctx *cli.Context) *discover.UDPv4 {
|
||||||
ln, config := makeDiscoveryConfig(ctx)
|
ln, config := makeDiscoveryConfig(ctx)
|
||||||
socket := listen(ln, ctx.String(listenAddrFlag.Name))
|
socket := listen(ctx, ln)
|
||||||
disc, err := discover.ListenV4(socket, ln, config)
|
disc, err := discover.ListenV4(socket, ln, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
@ -266,7 +272,28 @@ func makeDiscoveryConfig(ctx *cli.Context) (*enode.LocalNode, discover.Config) {
|
|||||||
return ln, cfg
|
return ln, cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
func listen(ln *enode.LocalNode, addr string) *net.UDPConn {
|
func parseExtAddr(spec string) (ip net.IP, port int, ok bool) {
|
||||||
|
ip = net.ParseIP(spec)
|
||||||
|
if ip != nil {
|
||||||
|
return ip, 0, true
|
||||||
|
}
|
||||||
|
host, portstr, err := net.SplitHostPort(spec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, false
|
||||||
|
}
|
||||||
|
ip = net.ParseIP(host)
|
||||||
|
if ip == nil {
|
||||||
|
return nil, 0, false
|
||||||
|
}
|
||||||
|
port, err = strconv.Atoi(portstr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, false
|
||||||
|
}
|
||||||
|
return ip, port, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func listen(ctx *cli.Context, ln *enode.LocalNode) *net.UDPConn {
|
||||||
|
addr := ctx.String(listenAddrFlag.Name)
|
||||||
if addr == "" {
|
if addr == "" {
|
||||||
addr = "0.0.0.0:0"
|
addr = "0.0.0.0:0"
|
||||||
}
|
}
|
||||||
@ -274,6 +301,8 @@ func listen(ln *enode.LocalNode, addr string) *net.UDPConn {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configure UDP endpoint in ENR from listener address.
|
||||||
usocket := socket.(*net.UDPConn)
|
usocket := socket.(*net.UDPConn)
|
||||||
uaddr := socket.LocalAddr().(*net.UDPAddr)
|
uaddr := socket.LocalAddr().(*net.UDPAddr)
|
||||||
if uaddr.IP.IsUnspecified() {
|
if uaddr.IP.IsUnspecified() {
|
||||||
@ -282,6 +311,22 @@ func listen(ln *enode.LocalNode, addr string) *net.UDPConn {
|
|||||||
ln.SetFallbackIP(uaddr.IP)
|
ln.SetFallbackIP(uaddr.IP)
|
||||||
}
|
}
|
||||||
ln.SetFallbackUDP(uaddr.Port)
|
ln.SetFallbackUDP(uaddr.Port)
|
||||||
|
|
||||||
|
// If an ENR endpoint is set explicitly on the command-line, override
|
||||||
|
// the information from the listening address. Note this is careful not
|
||||||
|
// to set the UDP port if the external address doesn't have it.
|
||||||
|
extAddr := ctx.String(extAddrFlag.Name)
|
||||||
|
if extAddr != "" {
|
||||||
|
ip, port, ok := parseExtAddr(extAddr)
|
||||||
|
if !ok {
|
||||||
|
exit(fmt.Errorf("-%s: invalid external address %q", extAddrFlag.Name, extAddr))
|
||||||
|
}
|
||||||
|
ln.SetStaticIP(ip)
|
||||||
|
if port != 0 {
|
||||||
|
ln.SetFallbackUDP(port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return usocket
|
return usocket
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v5test"
|
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v5test"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
@ -42,18 +43,21 @@ var (
|
|||||||
Name: "ping",
|
Name: "ping",
|
||||||
Usage: "Sends ping to a node",
|
Usage: "Sends ping to a node",
|
||||||
Action: discv5Ping,
|
Action: discv5Ping,
|
||||||
|
Flags: discoveryNodeFlags,
|
||||||
}
|
}
|
||||||
discv5ResolveCommand = &cli.Command{
|
discv5ResolveCommand = &cli.Command{
|
||||||
Name: "resolve",
|
Name: "resolve",
|
||||||
Usage: "Finds a node in the DHT",
|
Usage: "Finds a node in the DHT",
|
||||||
Action: discv5Resolve,
|
Action: discv5Resolve,
|
||||||
Flags: []cli.Flag{bootnodesFlag},
|
Flags: discoveryNodeFlags,
|
||||||
}
|
}
|
||||||
discv5CrawlCommand = &cli.Command{
|
discv5CrawlCommand = &cli.Command{
|
||||||
Name: "crawl",
|
Name: "crawl",
|
||||||
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
||||||
Action: discv5Crawl,
|
Action: discv5Crawl,
|
||||||
Flags: []cli.Flag{bootnodesFlag, crawlTimeoutFlag},
|
Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{
|
||||||
|
crawlTimeoutFlag,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
discv5TestCommand = &cli.Command{
|
discv5TestCommand = &cli.Command{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
@ -70,12 +74,7 @@ var (
|
|||||||
Name: "listen",
|
Name: "listen",
|
||||||
Usage: "Runs a node",
|
Usage: "Runs a node",
|
||||||
Action: discv5Listen,
|
Action: discv5Listen,
|
||||||
Flags: []cli.Flag{
|
Flags: discoveryNodeFlags,
|
||||||
bootnodesFlag,
|
|
||||||
nodekeyFlag,
|
|
||||||
nodedbFlag,
|
|
||||||
listenAddrFlag,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -137,7 +136,7 @@ func discv5Listen(ctx *cli.Context) error {
|
|||||||
// startV5 starts an ephemeral discovery v5 node.
|
// startV5 starts an ephemeral discovery v5 node.
|
||||||
func startV5(ctx *cli.Context) *discover.UDPv5 {
|
func startV5(ctx *cli.Context) *discover.UDPv5 {
|
||||||
ln, config := makeDiscoveryConfig(ctx)
|
ln, config := makeDiscoveryConfig(ctx)
|
||||||
socket := listen(ln, ctx.String(listenAddrFlag.Name))
|
socket := listen(ctx, ln)
|
||||||
disc, err := discover.ListenV5(socket, ln, config)
|
disc, err := discover.ListenV5(socket, ln, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
|
Loading…
Reference in New Issue
Block a user