Skip to content

Commit

Permalink
feat(node): added waku node builder type
Browse files Browse the repository at this point in the history
  • Loading branch information
Lorenzo Delgado authored Apr 5, 2023
1 parent e8448df commit e931fa5
Show file tree
Hide file tree
Showing 12 changed files with 234 additions and 40 deletions.
17 changes: 11 additions & 6 deletions apps/chat2/chat2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -390,12 +390,17 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
(extIp, extTcpPort, extUdpPort) = setupNat(conf.nat, clientId,
Port(uint16(conf.tcpPort) + conf.portsShift),
Port(uint16(conf.udpPort) + conf.portsShift))
node = WakuNode.new(nodekey, conf.listenAddress,
Port(uint16(conf.tcpPort) + conf.portsShift),
extIp, extTcpPort,
wsBindPort = Port(uint16(conf.websocketPort) + conf.portsShift),
wsEnabled = conf.websocketSupport,
wssEnabled = conf.websocketSecureSupport)

let node = block:
var builder = WakuNodeBuilder.init()
builder.withNodeKey(nodeKey)
builder.withNetworkConfigurationDetails(conf.listenAddress, Port(uint16(conf.tcpPort) + conf.portsShift),
extIp, extTcpPort,
wsBindPort = Port(uint16(conf.websocketPort) + conf.portsShift),
wsEnabled = conf.websocketSupport,
wssEnabled = conf.websocketSecureSupport).tryGet()
builder.build().tryGet()

await node.start()

if conf.rlnRelayEthAccountPrivateKey == "" and conf.rlnRelayCredPath == "":
Expand Down
9 changes: 5 additions & 4 deletions apps/chat2bridge/chat2bridge.nim
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,11 @@ proc new*(T: type Chat2MatterBridge,
raise newException(ValueError, "Matterbridge client not reachable/healthy")

# Setup Waku v2 node
let
nodev2 = WakuNode.new(nodev2Key,
nodev2BindIp, nodev2BindPort,
nodev2ExtIp, nodev2ExtPort)
let nodev2 = block:
var builder = WakuNodeBuilder.init()
builder.withNodeKey(nodev2Key)
builder.withNetworkConfigurationDetails(nodev2BindIp, nodev2BindPort, nodev2ExtIp, nodev2ExtPort).tryGet()
builder.build().tryGet()

return Chat2MatterBridge(mbClient: mbClient,
nodev2: nodev2,
Expand Down
11 changes: 6 additions & 5 deletions apps/wakubridge/wakubridge.nim
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,12 @@ proc new*(T: type WakuBridge,
nodev1.configureWaku(wakuConfig)

# Setup Waku v2 node
let
nodev2 = WakuNode.new(nodev2Key,
nodev2BindIp, nodev2BindPort,
nodev2ExtIp, nodev2ExtPort,
nameResolver = nameResolver)
let nodev2 = block:
var builder = WakuNodeBuilder.init()
builder.withNodeKey(nodev2Key)
builder.withNetworkConfigurationDetails(nodev2BindIp, nodev2BindPort, nodev2ExtIp, nodev2ExtPort).tryGet()
builder.withSwitchConfiguration(nameResolver=nameResolver)
builder.build().tryGet()

return WakuBridge(nodev1: nodev1,
nodev2: nodev2,
Expand Down
33 changes: 18 additions & 15 deletions apps/wakunode2/wakunode2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -334,21 +334,24 @@ proc initNode(conf: WakuNodeConf,
))
except CatchableError:
return err("failed to create waku discv5 instance: " & getCurrentExceptionMsg())
try:
node = WakuNode.new(nodekey = nodekey,
netConfig = netConfig,
peerStorage = pStorage,
maxConnections = conf.maxConnections.int,
secureKey = conf.websocketSecureKeyPath,
secureCert = conf.websocketSecureCertPath,
nameResolver = dnsResolver,
sendSignedPeerRecord = conf.relayPeerExchange, # We send our own signed peer record when peer exchange enabled
wakuDiscv5 = wakuDiscv5,
agentString = some(conf.agentString),
peerStoreCapacity = conf.peerStoreCapacity,
rng = rng)
except CatchableError:
return err("failed to create waku node instance: " & getCurrentExceptionMsg())

# Build waku node instance
var builder = WakuNodeBuilder.init()
builder.withRng(rng)
builder.withNodeKey(nodekey)
builder.withNetworkConfiguration(netConfig)
builder.withPeerStorage(pStorage, capacity = conf.peerStoreCapacity)
builder.withSwitchConfiguration(
maxConnections = some(conf.maxConnections.int),
secureKey = some(conf.websocketSecureKeyPath),
secureCert = some(conf.websocketSecureCertPath),
nameResolver = dnsResolver,
sendSignedPeerRecord = conf.relayPeerExchange, # We send our own signed peer record when peer exchange enabled
agentString = some(conf.agentString)
)
builder.withWakuDiscv5(wakuDiscv5.get(nil))

node = ? builder.build().mapErr(proc (err: string): string = "failed to create waku node instance: " & err)

ok(node)

Expand Down
6 changes: 5 additions & 1 deletion examples/v2/publisher.nim
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,13 @@ proc setupAndPublish(rng: ref HmacDrbgContext) {.async.} =
let
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[]).get()
ip = ValidIpAddress.init("0.0.0.0")
node = WakuNode.new(nodeKey, ip, Port(wakuPort))
flags = CapabilitiesBitfield.init(lightpush = false, filter = false, store = false, relay = true)

var builder = WakuNodeBuilder.init()
builder.withNodeKey(nodeKey)
builder.withNetworkConfigurationDetails(ip, Port(wakuPort)).tryGet()
let node = builder.build().tryGet()

var bootstrapNodeEnr: enr.Record
discard bootstrapNodeEnr.fromURI(bootstrapNode)

Expand Down
6 changes: 5 additions & 1 deletion examples/v2/subscriber.nim
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,13 @@ proc setupAndSubscribe(rng: ref HmacDrbgContext) {.async.} =
let
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
ip = ValidIpAddress.init("0.0.0.0")
node = WakuNode.new(nodeKey, ip, Port(wakuPort))
flags = CapabilitiesBitfield.init(lightpush = false, filter = false, store = false, relay = true)

var builder = WakuNodeBuilder.init()
builder.withNodeKey(nodeKey)
builder.withNetworkConfigurationDetails(ip, Port(wakuPort)).tryGet()
let node = builder.build().tryGet()

var bootstrapNodeEnr: enr.Record
discard bootstrapNodeEnr.fromURI(bootstrapNode)

Expand Down
6 changes: 5 additions & 1 deletion tools/networkmonitor/networkmonitor.nim
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,11 @@ proc initAndStartNode(conf: NetworkMonitorConf): Result[WakuNode, string] =
let
bindIp = ValidIpAddress.init("0.0.0.0")
extIp = ValidIpAddress.init("127.0.0.1")
node = WakuNode.new(nodeKey, bindIp, nodeTcpPort)

var builder = WakuNodeBuilder.init()
builder.withNodeKey(nodeKey)
? builder.withNetworkConfigurationDetails(bindIp, nodeTcpPort)
let node = ? builder.build()

var discv5BootstrapEnrsRes = getBootstrapFromDiscDns(conf)
if not discv5BootstrapEnrsRes.isOk():
Expand Down
2 changes: 1 addition & 1 deletion tools/networkmonitor/networkmonitor_utils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ proc decodeBytes*(t: typedesc[NodeLocation], value: openArray[byte],
long: $jsonContent["lon"].getFloat(),
isp: jsonContent["isp"].getStr()
))
except CatchableError:
except Exception:
return err("failed to get the location: " & getCurrentExceptionMsg())

proc encodeString*(value: string): RestResult[string] =
Expand Down
13 changes: 8 additions & 5 deletions tools/wakucanary/wakucanary.nim
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,14 @@ proc main(rng: ref HmacDrbgContext): Future[int] {.async.} =
let
peer: RemotePeerInfo = parseRemotePeerInfo(conf.address)
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
node = WakuNode.new(
nodeKey,
ValidIpAddress.init("0.0.0.0"),
Port(conf.nodePort),
nameResolver = resolver)
bindIp = ValidIpAddress.init("0.0.0.0")
nodeTcpPort = Port(conf.nodePort)

var builder = WakuNodeBuilder.init()
builder.withNodeKey(nodeKey)
builder.withNetworkConfigurationDetails(bindIp, nodeTcpPort).tryGet()
builder.withSwitchConfiguration(nameResolver=resolver)
let node = builder.build().tryGet()

await node.start()

Expand Down
167 changes: 167 additions & 0 deletions waku/v2/node/builder.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
when (NimMajor, NimMinor) < (1, 4):
{.push raises: [Defect].}
else:
{.push raises: [].}

import
std/options,
stew/results,
stew/shims/net,
chronicles,
libp2p/crypto/crypto,
libp2p/builders,
libp2p/nameresolving/nameresolver
import
../protocol/waku_enr,
../protocol/waku_discv5,
./config,
./peer_manager,
./waku_node


type
WakuNodeBuilder* = object
# General
nodeRng: Option[ref crypto.HmacDrbgContext]
nodeKey: Option[crypto.PrivateKey]
netConfig: Option[NetConfig]

# Peer storage and peer manager
peerStorage: Option[PeerStorage]
peerStorageCapacity: Option[int]
peerManager: Option[PeerManager]

# Libp2p switch
switchMaxConnections: Option[int]
switchNameResolver: Option[NameResolver]
switchAgentString: Option[string]
switchSslSecureKey: Option[string]
switchSslSecureCert: Option[string]
switchSendSignedPeerRecord: Option[bool]

# Waku discv5
wakuDiscv5: Option[WakuDiscoveryV5]

WakuNodeBuilderResult* = Result[void, string]


## Init

proc init*(T: type WakuNodeBuilder): WakuNodeBuilder =
WakuNodeBuilder()


## General

proc withRng*(builder: var WakuNodeBuilder, rng: ref crypto.HmacDrbgContext) =
builder.nodeRng = some(rng)

proc withNodeKey*(builder: var WakuNodeBuilder, nodeKey: crypto.PrivateKey) =
builder.nodeKey = some(nodeKey)

proc withNetworkConfiguration*(builder: var WakuNodeBuilder, config: NetConfig) =
builder.netConfig = some(config)

proc withNetworkConfigurationDetails*(builder: var WakuNodeBuilder,
bindIp: ValidIpAddress,
bindPort: Port,
extIp = none(ValidIpAddress),
extPort = none(Port),
extMultiAddrs = newSeq[MultiAddress](),
wsBindPort: Port = Port(8000),
wsEnabled: bool = false,
wssEnabled: bool = false,
wakuFlags = none(CapabilitiesBitfield),
dns4DomainName = none(string),
discv5UdpPort = none(Port)): WakuNodeBuilderResult {.
deprecated: "use 'builder.withNetworkConfiguration()' instead".} =
let netConfig = ? NetConfig.init(
bindIp = bindIp,
bindPort = bindPort,
extIp = extIp,
extPort = extPort,
extMultiAddrs = extMultiAddrs,
wsBindPort = wsBindPort,
wsEnabled = wsEnabled,
wssEnabled = wssEnabled,
wakuFlags = wakuFlags,
dns4DomainName = dns4DomainName,
discv5UdpPort = discv5UdpPort,
)
builder.withNetworkConfiguration(netConfig)
ok()


## Peer storage and peer manager

proc withPeerStorage*(builder: var WakuNodeBuilder, peerStorage: PeerStorage, capacity = none(int)) =
if not peerStorage.isNil():
builder.peerStorage = some(peerStorage)

builder.peerStorageCapacity = capacity

proc withPeerManager*(builder: var WakuNodeBuilder, peerManager: PeerManager) =
builder.peerManager = some(peerManager)


## Waku switch

proc withSwitchConfiguration*(builder: var WakuNodeBuilder,
maxConnections = none(int),
nameResolver: NameResolver = nil,
sendSignedPeerRecord = false,
secureKey = none(string),
secureCert = none(string),
agentString = none(string)) =
builder.switchMaxConnections = maxConnections
builder.switchSendSignedPeerRecord = some(sendSignedPeerRecord)
builder.switchSslSecureKey = secureKey
builder.switchSslSecureCert = secureCert
builder.switchAgentString = agentString

if not nameResolver.isNil():
builder.switchNameResolver = some(nameResolver)


## Waku discv5

proc withWakuDiscv5*(builder: var WakuNodeBuilder, instance: WakuDiscoveryV5) =
if not instance.isNil():
builder.wakuDiscv5 = some(instance)


## Build

proc build*(builder: WakuNodeBuilder): Result[WakuNode, string] =
var rng: ref crypto.HmacDrbgContext
if builder.nodeRng.isNone():
rng = crypto.newRng()
else:
rng = builder.nodeRng.get()

if builder.nodeKey.isNone():
return err("node key is required")

if builder.netConfig.isNone():
return err("network configuration is required")

var node: WakuNode
try:
node = WakuNode.new(
rng = rng,
nodeKey = builder.nodeKey.get(),
netConfig = builder.netConfig.get(),
peerStorage = builder.peerStorage.get(nil),
peerStoreCapacity = builder.peerStorageCapacity,
maxConnections = builder.switchMaxConnections.get(builders.MaxConnections),
nameResolver = builder.switchNameResolver.get(nil),
agentString = builder.switchAgentString,
secureKey = builder.switchSslSecureKey.get(""),
secureCert = builder.switchSslSecureCert.get(""),
sendSignedPeerRecord = builder.switchSendSignedPeerRecord.get(false),
wakuDiscv5 = builder.wakuDiscv5,
)
except Exception:
return err("failed to build WakuNode instance: " & getCurrentExceptionMsg())

ok(node)
2 changes: 1 addition & 1 deletion waku/v2/utils/peers.nim
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ else:

# Collection of utilities related to Waku peers
import
std/[options, sequtils, strutils, times],
std/[options, sequtils, strutils],
chronos,
stew/results,
stew/shims/net,
Expand Down
2 changes: 2 additions & 0 deletions waku/v2/waku_node.nim
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import
./node/config,
./node/builder,
./node/waku_switch as switch,
./node/waku_node as node

export
config,
builder,
switch,
node

0 comments on commit e931fa5

Please sign in to comment.