mirror of https://github.com/waku-org/nwaku.git
feat(wakunode): advertise custom multiaddresses (#1509)
* feat(wakunode2): ability to advertise custom multiaddresses * test(wakunode): test the feature * fix(wakunode): remove rln diff * revert(rln-relay): change that creeped into the diff * fix(wakunode): move extMultiaddrs closer to nat * fix(waku_node): idiomatic default arg * fix(config): shortened validation * fix(wakunode): discoverable via discv5 and dnsdisc
This commit is contained in:
parent
ea4703e9a2
commit
d09ec815ce
|
@ -10,6 +10,7 @@ import
|
|||
confutils/toml/std/net as confTomlNet,
|
||||
libp2p/crypto/crypto,
|
||||
libp2p/crypto/secp,
|
||||
libp2p/multiaddress,
|
||||
nimcrypto/utils
|
||||
import
|
||||
../../waku/common/confutils/envvar/defs as confEnvvarDefs,
|
||||
|
@ -75,6 +76,10 @@ type
|
|||
"Must be one of: any, none, upnp, pmp, extip:<IP>."
|
||||
defaultValue: "any" }: string
|
||||
|
||||
extMultiAddrs* {.
|
||||
desc: "External multiaddresses to advertise to the network. Argument may be repeated."
|
||||
name: "ext-multiaddr" }: seq[string]
|
||||
|
||||
maxConnections* {.
|
||||
desc: "Maximum allowed number of libp2p connections."
|
||||
defaultValue: 50
|
||||
|
@ -513,6 +518,12 @@ proc validateStoreMessageRetentionPolicy*(val: string): ConfResult[string] =
|
|||
else:
|
||||
err("invalid 'store message retention policy' option format: " & val)
|
||||
|
||||
proc validateExtMultiAddrs*(vals: seq[string]): ConfResult[seq[MultiAddress]] =
|
||||
var multiaddrs: seq[MultiAddress]
|
||||
for val in vals:
|
||||
let multiaddr = ? MultiAddress.init(val)
|
||||
multiaddrs.add(multiaddr)
|
||||
ok(multiaddrs)
|
||||
|
||||
## Load
|
||||
|
||||
|
|
|
@ -252,6 +252,14 @@ proc initNode(conf: WakuNodeConf,
|
|||
some(Port(uint16(conf.tcpPort) + conf.portsShift))
|
||||
else:
|
||||
extTcpPort
|
||||
extMultiAddrs = if (conf.extMultiAddrs.len > 0):
|
||||
let extMultiAddrsValidationRes = validateExtMultiAddrs(conf.extMultiAddrs)
|
||||
if extMultiAddrsValidationRes.isErr():
|
||||
return err("invalid external multiaddress: " & extMultiAddrsValidationRes.error)
|
||||
else:
|
||||
extMultiAddrsValidationRes.get()
|
||||
else:
|
||||
@[]
|
||||
|
||||
wakuFlags = initWakuFlags(conf.lightpush,
|
||||
conf.filter,
|
||||
|
@ -266,6 +274,7 @@ proc initNode(conf: WakuNodeConf,
|
|||
node = WakuNode.new(conf.nodekey,
|
||||
conf.listenAddress, Port(uint16(conf.tcpPort) + conf.portsShift),
|
||||
extIp, extPort,
|
||||
extMultiAddrs,
|
||||
pStorage,
|
||||
conf.maxConnections.int,
|
||||
Port(uint16(conf.websocketPort) + conf.portsShift),
|
||||
|
@ -279,8 +288,7 @@ proc initNode(conf: WakuNodeConf,
|
|||
dns4DomainName,
|
||||
discv5UdpPort,
|
||||
some(conf.agentString),
|
||||
some(conf.peerStoreCapacity),
|
||||
)
|
||||
some(conf.peerStoreCapacity))
|
||||
except:
|
||||
return err("failed to create waku node instance: " & getCurrentExceptionMsg())
|
||||
|
||||
|
|
|
@ -251,3 +251,36 @@ procSuite "WakuNode":
|
|||
node2Agent == expectedAgentString2
|
||||
|
||||
await allFutures(node1.stop(), node2.stop())
|
||||
|
||||
asyncTest "Custom multiaddresses are set and advertised correctly":
|
||||
let
|
||||
# custom multiaddress
|
||||
expectedMultiaddress1 = MultiAddress.init("/ip4/200.200.200.200/tcp/1234").get()
|
||||
|
||||
# Note: this could have been done with a single node, but it is useful to
|
||||
# have two nodes to check that the multiaddress is advertised correctly
|
||||
let
|
||||
# node with custom multiaddress
|
||||
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
||||
node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"), Port(61018),
|
||||
extMultiAddrs = @[expectedMultiaddress1])
|
||||
|
||||
# node with default multiaddress
|
||||
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
||||
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"), Port(61020))
|
||||
|
||||
await node1.start()
|
||||
await node1.mountRelay()
|
||||
|
||||
await node2.start()
|
||||
await node2.mountRelay()
|
||||
|
||||
await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()])
|
||||
await node2.connectToNodes(@[node1.switch.peerInfo.toRemotePeerInfo()])
|
||||
|
||||
let node1MultiAddrs = node2.switch.peerStore[AddressBook][node1.switch.peerInfo.toRemotePeerInfo().peerId]
|
||||
|
||||
check:
|
||||
node1MultiAddrs.contains(expectedMultiaddress1)
|
||||
|
||||
await allFutures(node1.stop(), node2.stop())
|
||||
|
|
|
@ -136,6 +136,7 @@ proc new*(T: type WakuNode,
|
|||
bindPort: Port,
|
||||
extIp = none(ValidIpAddress),
|
||||
extPort = none(Port),
|
||||
extMultiAddrs = newSeq[MultiAddress](),
|
||||
peerStorage: PeerStorage = nil,
|
||||
maxConnections = builders.MaxConnections,
|
||||
wsBindPort: Port = (Port)8000,
|
||||
|
@ -178,12 +179,17 @@ proc new*(T: type WakuNode,
|
|||
if (wsHostAddress.isSome()):
|
||||
wsExtAddress = some(ip4TcpEndPoint(extIp.get(), wsBindPort) & wsFlag(wssEnabled))
|
||||
|
||||
var announcedAddresses: seq[MultiAddress]
|
||||
var announcedAddresses = newSeq[MultiAddress]()
|
||||
|
||||
if hostExtAddress.isSome():
|
||||
announcedAddresses.add(hostExtAddress.get())
|
||||
else:
|
||||
announcedAddresses.add(hostAddress) # We always have at least a bind address for the host
|
||||
|
||||
# External multiaddrs that the operator may have configured
|
||||
if extMultiAddrs.len > 0:
|
||||
announcedAddresses.add(extMultiAddrs)
|
||||
|
||||
if wsExtAddress.isSome():
|
||||
announcedAddresses.add(wsExtAddress.get())
|
||||
elif wsHostAddress.isSome():
|
||||
|
@ -196,9 +202,12 @@ proc new*(T: type WakuNode,
|
|||
else: some(bindIp)
|
||||
enrTcpPort = if extPort.isSome(): extPort
|
||||
else: some(bindPort)
|
||||
enrMultiaddrs = if wsExtAddress.isSome(): @[wsExtAddress.get()] # Only add ws/wss to `multiaddrs` field
|
||||
elif wsHostAddress.isSome(): @[wsHostAddress.get()]
|
||||
else: @[]
|
||||
# enrMultiaddrs are just addresses which cannot be represented in ENR, as described in
|
||||
# https://rfc.vac.dev/spec/31/#many-connection-types
|
||||
enrMultiaddrs = announcedAddresses.filterIt(it.hasProtocol("dns4") or
|
||||
it.hasProtocol("dns6") or
|
||||
it.hasProtocol("ws") or
|
||||
it.hasProtocol("wss"))
|
||||
enr = initEnr(nodeKey,
|
||||
enrIp,
|
||||
enrTcpPort,
|
||||
|
@ -816,6 +825,7 @@ when defined(rln):
|
|||
return
|
||||
node.wakuRlnRelay = rlnRelayRes.get()
|
||||
|
||||
|
||||
## Waku peer-exchange
|
||||
|
||||
proc mountPeerExchange*(node: WakuNode) {.async, raises: [Defect, LPError].} =
|
||||
|
|
|
@ -13,6 +13,7 @@ import
|
|||
libp2p/crypto/[crypto, secp],
|
||||
libp2p/[errors,
|
||||
multiaddress,
|
||||
multicodec,
|
||||
peerid,
|
||||
peerinfo,
|
||||
routing_record]
|
||||
|
@ -169,3 +170,15 @@ proc toRemotePeerInfo*(peerInfo: PeerInfo): RemotePeerInfo =
|
|||
peerInfo.listenAddrs,
|
||||
none(enr.Record), # we could generate an ENR from PeerInfo
|
||||
peerInfo.protocols)
|
||||
|
||||
## Checks if a multiaddress contains a given protocol
|
||||
## Useful for filtering multiaddresses based on their protocols
|
||||
proc hasProtocol*(ma: MultiAddress, proto: string): bool =
|
||||
## Returns ``true`` if ``ma`` contains protocol ``proto``.
|
||||
let protos = ma.protocols()
|
||||
if protos.isErr():
|
||||
return false
|
||||
for p in protos.get():
|
||||
if p == MultiCodec.codec(proto):
|
||||
return true
|
||||
return false
|
||||
|
|
Loading…
Reference in New Issue