feat: advertise custom multiaddresses

This replaces the flag `--advertise-address` with `--ext-multiaddr`
This commit is contained in:
Richard Ramos 2023-02-08 12:02:06 -04:00 committed by RichΛrd
parent 57d707ff50
commit eb9e727b1b
8 changed files with 59 additions and 98 deletions

View File

@ -147,11 +147,13 @@ var (
Destination: &options.NAT, // TODO: accept none,any,upnp,extaddr
EnvVars: []string{"WAKUNODE2_NAT"},
})
AdvertiseAddress = altsrc.NewStringFlag(&cli.StringFlag{
Name: "advertise-address",
Usage: "External address to advertise to other nodes (overrides --address and --ws-address flags)",
Destination: &options.AdvertiseAddress,
EnvVars: []string{"WAKUNODE2_ADVERTISE_ADDRESS"},
AdvertiseAddress = cliutils.NewGenericFlagMultiValue(&cli.GenericFlag{
Name: "ext-multiaddr",
Usage: "External address to advertise to other nodes. Ooverrides --address and --ws-address flags. Option may be repeated",
Value: &cliutils.MultiaddrSlice{
Values: &options.AdvertiseAddresses,
},
EnvVars: []string{"WAKUNODE2_EXT_MULTIADDR"},
})
ShowAddresses = altsrc.NewBoolFlag(&cli.BoolFlag{
Name: "show-addresses",

View File

@ -56,26 +56,6 @@ func failOnErr(err error, msg string) {
}
}
func freePort() (int, error) {
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
if err != nil {
return 0, err
}
l, err := net.ListenTCP("tcp", addr)
if err != nil {
return 0, err
}
port := l.Addr().(*net.TCPAddr).Port
err = l.Close()
if err != nil {
return 0, err
}
return port, nil
}
const dialTimeout = 7 * time.Second
// Execute starts a go-waku node with settings determined by the Options parameter
@ -127,21 +107,8 @@ func Execute(options Options) {
node.WithKeepAlive(options.KeepAlive),
}
if options.AdvertiseAddress != "" {
advertiseAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", options.AdvertiseAddress, options.Port))
failOnErr(err, "Invalid advertise address")
if advertiseAddr.Port == 0 {
for {
p, err := freePort()
if err == nil {
advertiseAddr.Port = p
break
}
}
}
nodeOpts = append(nodeOpts, node.WithAdvertiseAddress(advertiseAddr))
if len(options.AdvertiseAddresses) != 0 {
nodeOpts = append(nodeOpts, node.WithAdvertiseAddresses(options.AdvertiseAddresses...))
}
if options.Dns4DomainName != "" {
@ -149,7 +116,7 @@ func Execute(options Options) {
}
libp2pOpts := node.DefaultLibP2POptions
if options.AdvertiseAddress == "" {
if len(options.AdvertiseAddresses) == 0 {
libp2pOpts = append(libp2pOpts, libp2p.NATPortMap()) // Attempt to open ports using uPNP for NATed hosts.)
}

View File

@ -141,25 +141,25 @@ type PeerExchangeOptions struct {
// Options contains all the available features and settings that can be
// configured via flags when executing go-waku as a service.
type Options struct {
Port int
Address string
Dns4DomainName string
NodeKey *ecdsa.PrivateKey
KeyFile string
KeyPasswd string
GenerateKey bool
Overwrite bool
StaticNodes []multiaddr.Multiaddr
KeepAlive time.Duration
AdvertiseAddress string
ShowAddresses bool
LogLevel string
LogEncoding string
LogOutput string
NAT string
PersistPeers bool
UserAgent string
PProf bool
Port int
Address string
Dns4DomainName string
NodeKey *ecdsa.PrivateKey
KeyFile string
KeyPasswd string
GenerateKey bool
Overwrite bool
StaticNodes []multiaddr.Multiaddr
KeepAlive time.Duration
AdvertiseAddresses []multiaddr.Multiaddr
ShowAddresses bool
LogLevel string
LogEncoding string
LogOutput string
NAT string
PersistPeers bool
UserAgent string
PProf bool
PeerExchange PeerExchangeOptions
Websocket WSOptions

View File

@ -11,6 +11,7 @@ import (
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
"github.com/waku-org/go-discover/discover"
"github.com/waku-org/go-waku/logging"
"github.com/waku-org/go-waku/waku/v2/utils"
@ -22,7 +23,6 @@ import (
var ErrNoDiscV5Listener = errors.New("no discv5 listener")
type DiscoveryV5 struct {
sync.RWMutex
@ -46,7 +46,7 @@ type discV5Parameters struct {
autoUpdate bool
bootnodes []*enode.Node
udpPort uint
advertiseAddr *net.IP
advertiseAddr []multiaddr.Multiaddr
}
type DiscoveryV5Option func(*discV5Parameters)
@ -65,9 +65,9 @@ func WithBootnodes(bootnodes []*enode.Node) DiscoveryV5Option {
}
}
func WithAdvertiseAddr(addr net.IP) DiscoveryV5Option {
func WithAdvertiseAddr(addr []multiaddr.Multiaddr) DiscoveryV5Option {
return func(params *discV5Parameters) {
params.advertiseAddr = &addr
params.advertiseAddr = addr
}
}

View File

@ -53,7 +53,7 @@ func writeMultiaddressField(localnode *enode.LocalNode, addrAggr []ma.Multiaddr)
return nil
}
func (w *WakuNode) updateLocalNode(localnode *enode.LocalNode, multiaddrs []ma.Multiaddr, ipAddr *net.TCPAddr, udpPort uint, wakuFlags utils.WakuEnrBitfield, advertiseAddr *net.IP, shouldAutoUpdate bool, log *zap.Logger) error {
func (w *WakuNode) updateLocalNode(localnode *enode.LocalNode, multiaddrs []ma.Multiaddr, ipAddr *net.TCPAddr, udpPort uint, wakuFlags utils.WakuEnrBitfield, advertiseAddr []ma.Multiaddr, shouldAutoUpdate bool, log *zap.Logger) error {
localnode.SetFallbackUDP(int(udpPort))
localnode.Set(enr.WithEntry(utils.WakuENRField, wakuFlags))
localnode.SetFallbackIP(net.IP{127, 0, 0, 1})
@ -65,13 +65,22 @@ func (w *WakuNode) updateLocalNode(localnode *enode.LocalNode, multiaddrs []ma.M
if advertiseAddr != nil {
// An advertised address disables libp2p address updates
// and discv5 predictions
localnode.SetStaticIP(*advertiseAddr)
ipAddr, err := selectMostExternalAddress(advertiseAddr)
if err != nil {
return err
}
localnode.SetStaticIP(ipAddr.IP)
localnode.Set(enr.TCP(uint16(ipAddr.Port))) // TODO: ipv6?
return writeMultiaddresses(localnode, multiaddrs)
} else if !shouldAutoUpdate {
// We received a libp2p address update. Autoupdate is disabled
// Using a static ip will disable endpoint prediction.
localnode.SetStaticIP(ipAddr.IP)
localnode.Set(enr.TCP(uint16(ipAddr.Port))) // TODO: ipv6?
return writeMultiaddresses(localnode, multiaddrs)
} else {
// We received a libp2p address update, but we should still
// allow discv5 to update the enr record. We set the localnode
@ -94,8 +103,13 @@ func (w *WakuNode) updateLocalNode(localnode *enode.LocalNode, multiaddrs []ma.M
localnode.Delete(enr.IPv6{})
localnode.Delete(enr.TCP6(0))
}
return writeMultiaddresses(localnode, multiaddrs)
}
}
func writeMultiaddresses(localnode *enode.LocalNode, multiaddrs []ma.Multiaddr) error {
// Randomly shuffle multiaddresses
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(multiaddrs), func(i, j int) { multiaddrs[i], multiaddrs[j] = multiaddrs[j], multiaddrs[i] })
@ -203,7 +217,6 @@ func extractIPAddressForENR(addr ma.Multiaddr) (*net.TCPAddr, error) {
func selectMostExternalAddress(addresses []ma.Multiaddr) (*net.TCPAddr, error) {
var ipAddrs []*net.TCPAddr
for _, addr := range addresses {
ipAddr, err := extractIPAddressForENR(addr)
if err != nil {
@ -337,7 +350,7 @@ func (w *WakuNode) setupENR(ctx context.Context, addrs []ma.Multiaddr) error {
return err
}
err = w.updateLocalNode(w.localNode, multiaddresses, ipAddr, w.opts.udpPort, w.wakuFlag, w.opts.advertiseAddr, w.opts.discV5autoUpdate, w.log)
err = w.updateLocalNode(w.localNode, multiaddresses, ipAddr, w.opts.udpPort, w.wakuFlag, w.opts.advertiseAddrs, w.opts.discV5autoUpdate, w.log)
if err != nil {
w.log.Error("updating localnode ENR record", zap.Error(err))
return err

View File

@ -554,8 +554,8 @@ func (w *WakuNode) mountDiscV5() error {
discv5.WithAutoUpdate(w.opts.discV5autoUpdate),
}
if w.opts.advertiseAddr != nil {
discV5Options = append(discV5Options, discv5.WithAdvertiseAddr(*w.opts.advertiseAddr))
if w.opts.advertiseAddrs != nil {
discV5Options = append(discV5Options, discv5.WithAdvertiseAddr(w.opts.advertiseAddrs))
}
var err error

View File

@ -23,6 +23,7 @@ import (
quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
"github.com/multiformats/go-multiaddr"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"github.com/waku-org/go-waku/waku/v2/protocol/filter"
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
@ -42,7 +43,7 @@ const defaultMinRelayPeersToPublish = 0
type WakuNodeParameters struct {
hostAddr *net.TCPAddr
dns4Domain string
advertiseAddr *net.IP
advertiseAddrs []multiaddr.Multiaddr
multiAddr []multiaddr.Multiaddr
addressFactory basichost.AddrsFactory
privKey *ecdsa.PrivateKey
@ -199,32 +200,12 @@ func WithHostAddress(hostAddr *net.TCPAddr) WakuNodeOption {
}
}
// WithAdvertiseAddress is a WakuNodeOption that allows overriding the address used in the waku node with custom value
func WithAdvertiseAddress(address *net.TCPAddr) WakuNodeOption {
// WithAdvertiseAddresses is a WakuNodeOption that allows overriding the address used in the waku node with custom value
func WithAdvertiseAddresses(advertiseAddrs ...ma.Multiaddr) WakuNodeOption {
return func(params *WakuNodeParameters) error {
params.advertiseAddr = &address.IP
advertiseAddress, err := manet.FromNetAddr(address)
if err != nil {
return err
}
params.advertiseAddrs = advertiseAddrs
params.addressFactory = func([]multiaddr.Multiaddr) (addresses []multiaddr.Multiaddr) {
addresses = append(addresses, advertiseAddress)
if params.enableWSS {
wsMa, err := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/%s/tcp/%d/wss", address.IP, params.wssPort))
if err != nil {
panic(err)
}
addresses = append(addresses, wsMa)
} else if params.enableWS {
wsMa, err := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/%s/tcp/%d/ws", address.IP, params.wsPort))
if err != nil {
panic(err)
}
addresses = append(addresses, wsMa)
}
return addresses
return advertiseAddrs
}
return nil
}

View File

@ -27,15 +27,13 @@ func TestWakuOptions(t *testing.T) {
addr, err := multiaddr.NewMultiaddr("/ip4/0.0.0.0/tcp/4000/ws")
require.NoError(t, err)
advertiseAddr, _ := net.ResolveTCPAddr("tcp", "0.0.0.0:0")
storeFactory := func(w *WakuNode) store.Store {
return store.NewWakuStore(w.host, w.swap, w.opts.messageProvider, w.timesource, w.log)
}
options := []WakuNodeOption{
WithHostAddress(hostAddr),
WithAdvertiseAddress(advertiseAddr),
WithAdvertiseAddresses(addr),
WithMultiaddress([]multiaddr.Multiaddr{addr}),
WithPrivateKey(prvKey),
WithLibP2POptions(),